ARCH - TASKER DEPLOY: закрепление live baseline и env-driven сборки
This commit is contained in:
@@ -53,6 +53,9 @@ ENV VITE_WEB_BASE_URL=$VITE_WEB_BASE_URL
|
||||
ARG VITE_WEB_BASE_PATH=""
|
||||
ENV VITE_WEB_BASE_PATH=$VITE_WEB_BASE_PATH
|
||||
|
||||
ARG VITE_NODEDC_LAUNCHER_URL=""
|
||||
ENV VITE_NODEDC_LAUNCHER_URL=$VITE_NODEDC_LAUNCHER_URL
|
||||
|
||||
ARG VITE_WEBSITE_URL="https://plane.so"
|
||||
ENV VITE_WEBSITE_URL=$VITE_WEBSITE_URL
|
||||
ARG VITE_SUPPORT_EMAIL="support@plane.so"
|
||||
@@ -67,8 +70,8 @@ COPY --from=builder /app/out/full/ .
|
||||
COPY turbo.json turbo.json
|
||||
|
||||
# Fetch dependencies to cache store, then install offline with dev deps
|
||||
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm fetch --store-dir=/pnpm/store
|
||||
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store CI=true pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store --prod=false
|
||||
RUN pnpm fetch --store-dir=/pnpm/store
|
||||
RUN CI=true pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store --prod=false
|
||||
|
||||
# Build only the admin package
|
||||
RUN pnpm turbo run build --filter=admin
|
||||
@@ -79,7 +82,6 @@ FROM nginx:1.29-alpine AS production
|
||||
|
||||
COPY apps/admin/nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
COPY --from=installer /app/apps/admin/build/client /usr/share/nginx/html/nodedcsudo
|
||||
RUN chmod -R a+rX /usr/share/nginx/html
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import Link from "next/link";
|
||||
import { useNodeDCBrandLinkUrl } from "@/hooks/use-nodedc-brand-link-url";
|
||||
|
||||
export function AuthHeader() {
|
||||
const logoLinkUrl = useNodeDCBrandLinkUrl();
|
||||
|
||||
return (
|
||||
<div className="sticky top-0 flex w-full flex-shrink-0 items-center justify-between gap-6">
|
||||
<Link href="/">
|
||||
<a href={logoLinkUrl}>
|
||||
<span className="tracking-normal text-16 font-semibold text-primary">NODE.DC</span>
|
||||
</Link>
|
||||
</a>
|
||||
<span className="rounded-full bg-white/6 px-3 py-1 text-11 font-medium text-secondary">
|
||||
Глобальное администрирование
|
||||
</span>
|
||||
|
||||
@@ -21,6 +21,7 @@ import { cn, getFileURL } from "@plane/utils";
|
||||
import NodeDcLogo from "@/app/assets/logos/nodedc-logo.svg?url";
|
||||
// hooks
|
||||
import { useUser } from "@/hooks/store";
|
||||
import { useNodeDCBrandLinkUrl } from "@/hooks/use-nodedc-brand-link-url";
|
||||
// local imports
|
||||
|
||||
const authService = new AuthService();
|
||||
@@ -42,6 +43,7 @@ export const AdminHeader = observer(function AdminHeader() {
|
||||
const { currentUser, signOut } = useUser();
|
||||
const { resolvedTheme, setTheme } = useNextTheme();
|
||||
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
||||
const logoLinkUrl = useNodeDCBrandLinkUrl();
|
||||
|
||||
const isFeatureRoute = FEATURE_NAVIGATION.some((item) => pathName?.startsWith(item.href));
|
||||
const adminName = currentUser?.display_name || currentUser?.email || "Глобальный админ";
|
||||
@@ -60,7 +62,7 @@ export const AdminHeader = observer(function AdminHeader() {
|
||||
return (
|
||||
<header className="nodedc-admin-header relative z-30 flex w-full flex-shrink-0 flex-col gap-4">
|
||||
<div className="nodedc-admin-header-top grid w-full items-center gap-4">
|
||||
<a href="/" className="nodedc-admin-logo-link inline-flex w-fit items-center" aria-label="NODE.DC">
|
||||
<a href={logoLinkUrl} className="nodedc-admin-logo-link inline-flex w-fit items-center" aria-label="NODE.DC">
|
||||
<img src={NodeDcLogo} alt="NODE.DC" className="nodedc-admin-logo" />
|
||||
</a>
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
export function buildNodeDCLauncherUrl(): string {
|
||||
const configuredUrl = process.env.VITE_NODEDC_LAUNCHER_URL;
|
||||
|
||||
if (configuredUrl) {
|
||||
return configuredUrl;
|
||||
}
|
||||
|
||||
if (typeof window === "undefined") {
|
||||
return "http://launcher.local.nodedc/";
|
||||
}
|
||||
|
||||
const hostname = window.location.hostname.toLowerCase();
|
||||
|
||||
if (hostname.endsWith(".nodedc.ru")) {
|
||||
return "https://hub.nodedc.ru/";
|
||||
}
|
||||
|
||||
if (hostname.endsWith(".nas.nodedc")) {
|
||||
const port = window.location.port ? `:${window.location.port}` : "";
|
||||
return `${window.location.protocol}//launcher.nas.nodedc${port}/`;
|
||||
}
|
||||
|
||||
return "http://launcher.local.nodedc/";
|
||||
}
|
||||
|
||||
export function buildNodeDCBrandConfigUrl(): string {
|
||||
return new URL("/api/public/brand", buildNodeDCLauncherUrl()).toString();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { buildNodeDCBrandConfigUrl, buildNodeDCLauncherUrl } from "@/helpers/nodedc-brand";
|
||||
|
||||
type TNodeDCBrandPayload = {
|
||||
logoLinkUrl?: string | null;
|
||||
};
|
||||
|
||||
export function useNodeDCBrandLinkUrl() {
|
||||
const [logoLinkUrl, setLogoLinkUrl] = useState(buildNodeDCLauncherUrl);
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
|
||||
fetch(buildNodeDCBrandConfigUrl(), { cache: "no-store" })
|
||||
.then((response) => (response.ok ? response.json() : null))
|
||||
.then((payload: TNodeDCBrandPayload | null) => {
|
||||
const configuredUrl = typeof payload?.logoLinkUrl === "string" ? payload.logoLinkUrl.trim() : "";
|
||||
if (isMounted && configuredUrl) setLogoLinkUrl(configuredUrl);
|
||||
return undefined;
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
console.warn(error instanceof Error ? error.message : "Не удалось загрузить brand config NODE.DC");
|
||||
});
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return logoLinkUrl;
|
||||
}
|
||||
Reference in New Issue
Block a user