UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: канонизация breadcrumb и CTA на экране страниц

This commit is contained in:
DCCONSTRUCTIONS 2026-04-22 19:44:27 +03:00
parent 312fc1eca4
commit 55549219ff
5 changed files with 22 additions and 28 deletions

View File

@ -7,12 +7,11 @@
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
// plane imports // plane imports
import { EProjectFeatureKey } from "@plane/constants";
import { PageIcon } from "@plane/propel/icons"; import { PageIcon } from "@plane/propel/icons";
import type { ICustomSearchSelectOption } from "@plane/types"; import type { ICustomSearchSelectOption } from "@plane/types";
import { Breadcrumbs, Header, BreadcrumbNavigationSearchDropdown } from "@plane/ui"; import { Breadcrumbs, Header, BreadcrumbNavigationSearchDropdown } from "@plane/ui";
import { getPageName } from "@plane/utils"; import { getPageName } from "@plane/utils";
// components
import { BreadcrumbLink } from "@/components/common/breadcrumb-link";
import { PageAccessIcon } from "@/components/common/page-access-icon"; import { PageAccessIcon } from "@/components/common/page-access-icon";
import { SwitcherIcon, SwitcherLabel } from "@/components/common/switcher-label"; import { SwitcherIcon, SwitcherLabel } from "@/components/common/switcher-label";
import { PageHeaderActions } from "@/components/pages/header/actions"; import { PageHeaderActions } from "@/components/pages/header/actions";
@ -22,6 +21,7 @@ import { useProject } from "@/hooks/store/use-project";
import { useAppRouter } from "@/hooks/use-app-router"; import { useAppRouter } from "@/hooks/use-app-router";
// plane web imports // plane web imports
import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/common"; import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/common";
import { ProjectFeatureBreadcrumb } from "@/plane-web/components/breadcrumbs/project-feature";
import { PageDetailsHeaderExtraActions } from "@/plane-web/components/pages"; import { PageDetailsHeaderExtraActions } from "@/plane-web/components/pages";
import { EPageStoreType, usePage, usePageStore } from "@/plane-web/hooks/store"; import { EPageStoreType, usePage, usePageStore } from "@/plane-web/hooks/store";
@ -70,14 +70,10 @@ export const PageDetailsHeader = observer(function PageDetailsHeader() {
<div> <div>
<Breadcrumbs isLoading={loader === "init-loader"}> <Breadcrumbs isLoading={loader === "init-loader"}>
<CommonProjectBreadcrumbs workspaceSlug={workspaceSlug?.toString()} projectId={projectId?.toString()} /> <CommonProjectBreadcrumbs workspaceSlug={workspaceSlug?.toString()} projectId={projectId?.toString()} />
<Breadcrumbs.Item <ProjectFeatureBreadcrumb
component={ workspaceSlug={workspaceSlug?.toString()}
<BreadcrumbLink projectId={projectId?.toString()}
label="Pages" featureKey={EProjectFeatureKey.PAGES}
href={`/${workspaceSlug}/projects/${projectId}/pages/`}
icon={<PageIcon className="h-4 w-4 text-tertiary" />}
/>
}
/> />
<Breadcrumbs.Item <Breadcrumbs.Item

View File

@ -8,25 +8,26 @@ import { useState } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useParams, useRouter, useSearchParams } from "next/navigation"; import { useParams, useRouter, useSearchParams } from "next/navigation";
// constants // constants
import { EPageAccess } from "@plane/constants"; import { EPageAccess, EProjectFeatureKey } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// plane types // plane types
import { Button } from "@plane/propel/button";
import { PageIcon } from "@plane/propel/icons";
import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { TPage } from "@plane/types"; import type { TPage } from "@plane/types";
// plane ui // plane ui
import { Breadcrumbs, Header } from "@plane/ui"; import { Breadcrumbs, Header } from "@plane/ui";
// helpers // components
import { BreadcrumbLink } from "@/components/common/breadcrumb-link"; import { AppHeaderPrimaryActionButton } from "@/components/core/app-header/primary-action-button";
// hooks // hooks
import { useProject } from "@/hooks/store/use-project"; import { useProject } from "@/hooks/store/use-project";
// plane web imports // plane web imports
import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/common"; import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/common";
import { ProjectFeatureBreadcrumb } from "@/plane-web/components/breadcrumbs/project-feature";
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store"; import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
export const PagesListHeader = observer(function PagesListHeader() { export const PagesListHeader = observer(function PagesListHeader() {
// states // states
const [isCreatingPage, setIsCreatingPage] = useState(false); const [isCreatingPage, setIsCreatingPage] = useState(false);
const { t } = useTranslation();
// router // router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = useParams(); const { workspaceSlug, projectId } = useParams();
@ -63,24 +64,19 @@ export const PagesListHeader = observer(function PagesListHeader() {
<Header.LeftItem> <Header.LeftItem>
<Breadcrumbs isLoading={loader === "init-loader"}> <Breadcrumbs isLoading={loader === "init-loader"}>
<CommonProjectBreadcrumbs workspaceSlug={workspaceSlug?.toString()} projectId={projectId?.toString()} /> <CommonProjectBreadcrumbs workspaceSlug={workspaceSlug?.toString()} projectId={projectId?.toString()} />
<Breadcrumbs.Item <ProjectFeatureBreadcrumb
component={ workspaceSlug={workspaceSlug?.toString()}
<BreadcrumbLink projectId={projectId?.toString()}
label="Pages" featureKey={EProjectFeatureKey.PAGES}
href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/pages/`}
icon={<PageIcon className="h-4 w-4 text-tertiary" />}
isLast
/>
}
isLast isLast
/> />
</Breadcrumbs> </Breadcrumbs>
</Header.LeftItem> </Header.LeftItem>
{canCurrentUserCreatePage && ( {canCurrentUserCreatePage && (
<Header.RightItem> <Header.RightItem>
<Button variant="primary" size="lg" onClick={handleCreatePage} loading={isCreatingPage}> <AppHeaderPrimaryActionButton onClick={handleCreatePage} loading={isCreatingPage}>
{isCreatingPage ? "Adding" : "Add page"} {isCreatingPage ? t("creating") : t("app_header.add_page")}
</Button> </AppHeaderPrimaryActionButton>
</Header.RightItem> </Header.RightItem>
)} )}
</Header> </Header>

View File

@ -49,7 +49,7 @@ function ProjectPagesPage({ params }: Route.ComponentProps) {
const { allowPermissions } = useUserPermissions(); const { allowPermissions } = useUserPermissions();
// derived values // derived values
const project = getProjectById(projectId); const project = getProjectById(projectId);
const pageTitle = project?.name ? `${project?.name} - Pages` : undefined; const pageTitle = project?.name ? `${project?.name} - ${t("sidebar.pages")}` : undefined;
const canPerformEmptyStateActions = allowPermissions([EUserProjectRoles.ADMIN], EUserPermissionsLevel.PROJECT); const canPerformEmptyStateActions = allowPermissions([EUserProjectRoles.ADMIN], EUserPermissionsLevel.PROJECT);
const resolvedPath = resolvedTheme === "light" ? lightPagesAsset : darkPagesAsset; const resolvedPath = resolvedTheme === "light" ? lightPagesAsset : darkPagesAsset;
const pageType = getPageType(type); const pageType = getPageType(type);

View File

@ -511,6 +511,7 @@ export default {
add_work_item: "Add work item", add_work_item: "Add work item",
app_header: { app_header: {
add_task: "Add task", add_task: "Add task",
add_page: "Add page",
}, },
advanced_description_placeholder: "Press '/' for commands", advanced_description_placeholder: "Press '/' for commands",
create_work_item: "Create work item", create_work_item: "Create work item",

View File

@ -667,6 +667,7 @@ export default {
add_work_item: "Добавить рабочий элемент", add_work_item: "Добавить рабочий элемент",
app_header: { app_header: {
add_task: "Добавить задачу", add_task: "Добавить задачу",
add_page: "Добавить страницу",
}, },
advanced_description_placeholder: "Нажмите '/' для команд", advanced_description_placeholder: "Нажмите '/' для команд",
create_work_item: "Создать рабочий элемент", create_work_item: "Создать рабочий элемент",