diff --git a/plane-src/apps/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx b/plane-src/apps/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx index a4fe414..bd9b3e7 100644 --- a/plane-src/apps/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx +++ b/plane-src/apps/web/app/(all)/[workspaceSlug]/(projects)/layout.tsx @@ -13,7 +13,7 @@ function WorkspaceLayout() { return ( <> -
+
diff --git a/plane-src/apps/web/app/(all)/[workspaceSlug]/(projects)/top-toolbar/expanded-layout.tsx b/plane-src/apps/web/app/(all)/[workspaceSlug]/(projects)/top-toolbar/expanded-layout.tsx index a28fa28..5df1e25 100644 --- a/plane-src/apps/web/app/(all)/[workspaceSlug]/(projects)/top-toolbar/expanded-layout.tsx +++ b/plane-src/apps/web/app/(all)/[workspaceSlug]/(projects)/top-toolbar/expanded-layout.tsx @@ -8,9 +8,11 @@ import { useTranslation } from "@plane/i18n"; import { Shapes } from "lucide-react"; +import { useEffect, useState } from "react"; import { cn } from "@plane/utils"; // components import { TopNavPowerK } from "@/components/navigation"; +import { buildNodeDCBrandConfigUrl, buildNodeDCLauncherUrl } from "@/helpers/nodedc-auth"; import { UserMenuRoot } from "@/components/workspace/sidebar/user-menu-root"; import { WorkspaceMenuRoot } from "@/components/workspace/sidebar/workspace-menu-root"; import { useHome } from "@/hooks/store/use-home"; @@ -30,17 +32,35 @@ export const ExpandedProjectShellToolbarLayout = ({ }: TProjectShellToolbarLayoutProps) => { const { t } = useTranslation(); const { toggleWidgetSettings } = useHome(); + const [logoLinkUrl, setLogoLinkUrl] = useState(buildNodeDCLauncherUrl); + + useEffect(() => { + let isMounted = true; + + fetch(buildNodeDCBrandConfigUrl(), { cache: "no-store" }) + .then((response) => (response.ok ? response.json() : null)) + .then((payload: { logoLinkUrl?: string } | null) => { + if (isMounted && payload?.logoLinkUrl) { + setLogoLinkUrl(payload.logoLinkUrl); + } + }) + .catch((error: unknown) => { + console.warn(error instanceof Error ? error.message : "Не удалось загрузить brand config NODE.DC"); + }); + + return () => { + isMounted = false; + }; + }, []); return ( -
+
- NODE DC + + NODE DC +
diff --git a/plane-src/apps/web/helpers/nodedc-auth.ts b/plane-src/apps/web/helpers/nodedc-auth.ts index 2943b42..c80165b 100644 --- a/plane-src/apps/web/helpers/nodedc-auth.ts +++ b/plane-src/apps/web/helpers/nodedc-auth.ts @@ -33,6 +33,10 @@ export function buildNodeDCLauncherUrl(): string { return process.env.VITE_NODEDC_LAUNCHER_URL || "http://launcher.local.nodedc/"; } +export function buildNodeDCBrandConfigUrl(): string { + return new URL("/api/public/brand", buildNodeDCLauncherUrl()).toString(); +} + export function getCurrentRelativePath(): string { if (typeof window === "undefined") { return "/"; diff --git a/plane-src/apps/web/styles/globals.css b/plane-src/apps/web/styles/globals.css index 776d6e7..e9e0854 100644 --- a/plane-src/apps/web/styles/globals.css +++ b/plane-src/apps/web/styles/globals.css @@ -57,6 +57,17 @@ --nodedc-list-properties-panel-width: 64rem; --nodedc-list-quick-actions-width: 3.15rem; --nodedc-quick-add-reserve: 2.5rem; + --nodedc-shell-padding-x: 1.25rem; + --nodedc-shell-padding-top: 1rem; + --nodedc-shell-padding-bottom: 0.75rem; + --nodedc-shell-frame-gutter-x: 18px; + --nodedc-shell-height: 4.25rem; + --nodedc-shell-row-height: 3rem; + --nodedc-shell-logo-width: 7.25rem; + --nodedc-shell-logo-height: 1.79rem; + --nodedc-shell-pill-height: 3.45rem; + --nodedc-shell-pill-padding: 0.32rem; + --nodedc-shell-control-height: 2.78rem; --brand-default: rgb(var(--nodedc-accent-rgb)); --brand-300: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 65%, white); --brand-700: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 75%, black); @@ -1201,21 +1212,35 @@ .nodedc-expanded-toolbar { display: flex; - min-height: 4.25rem; + min-height: var(--nodedc-shell-height); width: 100%; flex-direction: column; gap: 0; } + .nodedc-project-shell-frame::before { + content: ""; + position: absolute; + inset: 0; + z-index: 90; + pointer-events: none; + border: 1px solid var(--border-color-subtle); + border-radius: inherit; + } + .nodedc-expanded-toolbar-shell { position: relative; z-index: 80; + width: min(100%, calc(100vw - var(--nodedc-shell-frame-gutter-x))); + margin-inline: auto; + flex-shrink: 0; + padding: var(--nodedc-shell-padding-top) var(--nodedc-shell-padding-x) var(--nodedc-shell-padding-bottom); } .nodedc-expanded-toolbar-top { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); - min-height: 3rem; + min-height: var(--nodedc-shell-row-height); width: 100%; align-items: center; gap: 1rem; @@ -1234,6 +1259,16 @@ justify-content: flex-start; } + .nodedc-expanded-brand-link { + display: inline-flex; + width: var(--nodedc-shell-logo-width); + height: var(--nodedc-shell-logo-height); + flex: 0 0 auto; + align-items: center; + justify-content: flex-start; + line-height: 0; + } + .nodedc-expanded-toolbar-center { justify-content: center; } @@ -1244,25 +1279,25 @@ .nodedc-expanded-brand-logo { display: block; - width: 7.25rem; - height: auto; - max-height: 2.2rem; + width: 100%; + height: 100%; + max-height: none; object-fit: contain; } .nodedc-expanded-user-group { display: inline-flex; - height: 3.45rem; - min-height: 3.45rem; + height: var(--nodedc-shell-pill-height); + min-height: var(--nodedc-shell-pill-height); align-items: center; gap: 0.22rem; border-radius: 999px; background: rgba(64, 64, 64, 0.48); - padding: 0.32rem; + padding: var(--nodedc-shell-pill-padding); } .nodedc-expanded-user-group .nodedc-expanded-nav-button { - min-height: 2.78rem; + min-height: var(--nodedc-shell-control-height); padding-inline: 1.2rem; } @@ -1272,13 +1307,13 @@ .nodedc-expanded-nav-group { display: inline-flex; - min-height: 3.45rem; + min-height: var(--nodedc-shell-pill-height); align-items: center; gap: 0.18rem; border: 0 !important; border-radius: 999px; background: rgba(64, 64, 64, 0.48); - padding: 0.32rem; + padding: var(--nodedc-shell-pill-padding); box-shadow: none !important; } @@ -1326,7 +1361,7 @@ align-items: center; justify-content: center; gap: 0; - min-height: 2.78rem; + min-height: var(--nodedc-shell-control-height); border: 0 !important; outline: none !important; box-shadow: none !important; @@ -1688,8 +1723,8 @@ } .nodedc-expanded-notification-button { - height: 2.78rem; - width: 2.78rem; + height: var(--nodedc-shell-control-height); + width: var(--nodedc-shell-control-height); background: transparent !important; color: rgba(255, 255, 255, 0.68) !important; }