UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: унификация верхней шапки NodeDC
This commit is contained in:
parent
4400b7f438
commit
a111574039
|
|
@ -13,7 +13,7 @@ function WorkspaceLayout() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ProjectsAppPowerKProvider />
|
<ProjectsAppPowerKProvider />
|
||||||
<div className="relative flex h-full w-full flex-col overflow-hidden rounded-lg border border-subtle">
|
<div className="nodedc-project-shell-frame relative flex h-full w-full flex-col overflow-hidden rounded-lg">
|
||||||
<div id="full-screen-portal" className="absolute inset-0 w-full" />
|
<div id="full-screen-portal" className="absolute inset-0 w-full" />
|
||||||
<div className="relative flex size-full overflow-hidden">
|
<div className="relative flex size-full overflow-hidden">
|
||||||
<main className="relative flex h-full w-full min-w-0 flex-col overflow-hidden bg-surface-1">
|
<main className="relative flex h-full w-full min-w-0 flex-col overflow-hidden bg-surface-1">
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@
|
||||||
|
|
||||||
import { useTranslation } from "@plane/i18n";
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { Shapes } from "lucide-react";
|
import { Shapes } from "lucide-react";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { cn } from "@plane/utils";
|
import { cn } from "@plane/utils";
|
||||||
// components
|
// components
|
||||||
import { TopNavPowerK } from "@/components/navigation";
|
import { TopNavPowerK } from "@/components/navigation";
|
||||||
|
import { buildNodeDCBrandConfigUrl, buildNodeDCLauncherUrl } from "@/helpers/nodedc-auth";
|
||||||
import { UserMenuRoot } from "@/components/workspace/sidebar/user-menu-root";
|
import { UserMenuRoot } from "@/components/workspace/sidebar/user-menu-root";
|
||||||
import { WorkspaceMenuRoot } from "@/components/workspace/sidebar/workspace-menu-root";
|
import { WorkspaceMenuRoot } from "@/components/workspace/sidebar/workspace-menu-root";
|
||||||
import { useHome } from "@/hooks/store/use-home";
|
import { useHome } from "@/hooks/store/use-home";
|
||||||
|
|
@ -30,17 +32,35 @@ export const ExpandedProjectShellToolbarLayout = ({
|
||||||
}: TProjectShellToolbarLayoutProps) => {
|
}: TProjectShellToolbarLayoutProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { toggleWidgetSettings } = useHome();
|
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 (
|
return (
|
||||||
<div
|
<div className={cn("nodedc-expanded-toolbar-shell", { "nodedc-home-top-toolbar": isWorkspaceHome })}>
|
||||||
className={cn("nodedc-expanded-toolbar-shell w-full flex-shrink-0 px-5 pt-4 pb-3", {
|
|
||||||
"nodedc-home-top-toolbar": isWorkspaceHome,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<div className="nodedc-expanded-toolbar">
|
<div className="nodedc-expanded-toolbar">
|
||||||
<div className="nodedc-expanded-toolbar-top">
|
<div className="nodedc-expanded-toolbar-top">
|
||||||
<div className="nodedc-expanded-toolbar-left">
|
<div className="nodedc-expanded-toolbar-left">
|
||||||
<img src="/nodedc-logo.svg" alt="NODE DC" className="nodedc-expanded-brand-logo" />
|
<a href={logoLinkUrl} className="nodedc-expanded-brand-link" aria-label="NODE.DC">
|
||||||
|
<img src="/nodedc-logo.svg" alt="NODE DC" className="nodedc-expanded-brand-logo" />
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="nodedc-expanded-toolbar-center">
|
<div className="nodedc-expanded-toolbar-center">
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ export function buildNodeDCLauncherUrl(): string {
|
||||||
return process.env.VITE_NODEDC_LAUNCHER_URL || "http://launcher.local.nodedc/";
|
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 {
|
export function getCurrentRelativePath(): string {
|
||||||
if (typeof window === "undefined") {
|
if (typeof window === "undefined") {
|
||||||
return "/";
|
return "/";
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,17 @@
|
||||||
--nodedc-list-properties-panel-width: 64rem;
|
--nodedc-list-properties-panel-width: 64rem;
|
||||||
--nodedc-list-quick-actions-width: 3.15rem;
|
--nodedc-list-quick-actions-width: 3.15rem;
|
||||||
--nodedc-quick-add-reserve: 2.5rem;
|
--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-default: rgb(var(--nodedc-accent-rgb));
|
||||||
--brand-300: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 65%, white);
|
--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);
|
--brand-700: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 75%, black);
|
||||||
|
|
@ -1201,21 +1212,35 @@
|
||||||
|
|
||||||
.nodedc-expanded-toolbar {
|
.nodedc-expanded-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 4.25rem;
|
min-height: var(--nodedc-shell-height);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0;
|
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 {
|
.nodedc-expanded-toolbar-shell {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 80;
|
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 {
|
.nodedc-expanded-toolbar-top {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
||||||
min-height: 3rem;
|
min-height: var(--nodedc-shell-row-height);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
@ -1234,6 +1259,16 @@
|
||||||
justify-content: flex-start;
|
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 {
|
.nodedc-expanded-toolbar-center {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
@ -1244,25 +1279,25 @@
|
||||||
|
|
||||||
.nodedc-expanded-brand-logo {
|
.nodedc-expanded-brand-logo {
|
||||||
display: block;
|
display: block;
|
||||||
width: 7.25rem;
|
width: 100%;
|
||||||
height: auto;
|
height: 100%;
|
||||||
max-height: 2.2rem;
|
max-height: none;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodedc-expanded-user-group {
|
.nodedc-expanded-user-group {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
height: 3.45rem;
|
height: var(--nodedc-shell-pill-height);
|
||||||
min-height: 3.45rem;
|
min-height: var(--nodedc-shell-pill-height);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.22rem;
|
gap: 0.22rem;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(64, 64, 64, 0.48);
|
background: rgba(64, 64, 64, 0.48);
|
||||||
padding: 0.32rem;
|
padding: var(--nodedc-shell-pill-padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodedc-expanded-user-group .nodedc-expanded-nav-button {
|
.nodedc-expanded-user-group .nodedc-expanded-nav-button {
|
||||||
min-height: 2.78rem;
|
min-height: var(--nodedc-shell-control-height);
|
||||||
padding-inline: 1.2rem;
|
padding-inline: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1272,13 +1307,13 @@
|
||||||
|
|
||||||
.nodedc-expanded-nav-group {
|
.nodedc-expanded-nav-group {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
min-height: 3.45rem;
|
min-height: var(--nodedc-shell-pill-height);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.18rem;
|
gap: 0.18rem;
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(64, 64, 64, 0.48);
|
background: rgba(64, 64, 64, 0.48);
|
||||||
padding: 0.32rem;
|
padding: var(--nodedc-shell-pill-padding);
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1326,7 +1361,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
min-height: 2.78rem;
|
min-height: var(--nodedc-shell-control-height);
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
|
|
@ -1688,8 +1723,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodedc-expanded-notification-button {
|
.nodedc-expanded-notification-button {
|
||||||
height: 2.78rem;
|
height: var(--nodedc-shell-control-height);
|
||||||
width: 2.78rem;
|
width: var(--nodedc-shell-control-height);
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
color: rgba(255, 255, 255, 0.68) !important;
|
color: rgba(255, 255, 255, 0.68) !important;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue