From d71fbe6c758c004d931e8057228a7da1d3f57dd3 Mon Sep 17 00:00:00 2001 From: Vadym Samoilenko Date: Wed, 1 Apr 2026 12:43:03 +0100 Subject: [PATCH] Fix: prepend basePath to all client-side API calls + add server config API path fixes: - _app.jsx: SWR middleware prefixes all useSWR keys with NEXT_PUBLIC_BASE_PATH - index.jsx: update fallback keys, raw fetch() calls, and Script src - _document.jsx: update custom.css link hrefs - revalidate.jsx, search.jsx, api-helpers.js: update raw fetch/proxy calls Initial dashboard config (force-added, config/ is gitignored by default): - settings.yaml: dark slate theme, English, two-row layout - services.yaml: all 5 server apps with Docker container health links - widgets.yaml: CPU/RAM/disk resources widget + datetime - docker.yaml: local Docker socket for auto-discovery Co-Authored-By: Claude Sonnet 4.6 --- config/docker.yaml | 3 ++ config/services.yaml | 44 ++++++++++++++++++++++++ config/settings.yaml | 14 ++++++++ config/widgets.yaml | 14 ++++++++ src/components/toggles/revalidate.jsx | 2 +- src/components/widgets/search/search.jsx | 2 +- src/pages/_app.jsx | 7 ++++ src/pages/_document.jsx | 4 +-- src/pages/index.jsx | 21 +++++------ src/utils/proxy/api-helpers.js | 2 +- 10 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 config/docker.yaml create mode 100644 config/services.yaml create mode 100644 config/settings.yaml create mode 100644 config/widgets.yaml diff --git a/config/docker.yaml b/config/docker.yaml new file mode 100644 index 00000000..0245011d --- /dev/null +++ b/config/docker.yaml @@ -0,0 +1,3 @@ +--- +local: + socket: /var/run/docker.sock diff --git a/config/services.yaml b/config/services.yaml new file mode 100644 index 00000000..f4ae9ad1 --- /dev/null +++ b/config/services.yaml @@ -0,0 +1,44 @@ +--- +- AI Tools: + - DeckForge: + icon: mdi-presentation + href: https://optical-dev.oliver.solutions/ppt-tool + description: AI presentation generator + container: ppt-tool-web-1 + server: local + + - GMAL Scope Builder: + icon: mdi-briefcase-outline + href: https://optical-dev.oliver.solutions/gsb + description: AI ratecard & team scoping + container: gmal-scope-builder-backend-1 + server: local + + - Semblance: + icon: mdi-account-group-outline + href: https://optical-dev.oliver.solutions/semblance + description: Synthetic personas & focus groups + container: semblance-backend-1 + server: local + + - CC Dashboard: + icon: mdi-view-dashboard-outline + href: https://optical-dev.oliver.solutions/cc-dashboard + description: API key & project management + container: cc-dashboard-app-1 + server: local + + - OliVAS: + icon: mdi-robot-outline + href: https://optical-dev.oliver.solutions + description: OliVAS backend API + container: olivas-backend-1 + server: local + +- Infrastructure: + - Homepage: + icon: mdi-home-outline + href: https://optical-dev.oliver.solutions/homepage + description: This dashboard + container: homepage-app-1 + server: local diff --git a/config/settings.yaml b/config/settings.yaml new file mode 100644 index 00000000..e2791cc4 --- /dev/null +++ b/config/settings.yaml @@ -0,0 +1,14 @@ +--- +title: Optical Dev +description: optical-dev.oliver.solutions internal dashboard +language: en +theme: dark +color: slate +headerStyle: clean +layout: + Infrastructure: + style: row + columns: 4 + AI Tools: + style: row + columns: 4 diff --git a/config/widgets.yaml b/config/widgets.yaml new file mode 100644 index 00000000..8aa127a8 --- /dev/null +++ b/config/widgets.yaml @@ -0,0 +1,14 @@ +--- +- resources: + cpu: true + memory: true + disk: / + label: optical-dev server + expanded: true + +- datetime: + text_size: xl + format: + timeStyle: short + dateStyle: short + hourCycle: h23 diff --git a/src/components/toggles/revalidate.jsx b/src/components/toggles/revalidate.jsx index 14fe8b37..f57470c3 100644 --- a/src/components/toggles/revalidate.jsx +++ b/src/components/toggles/revalidate.jsx @@ -2,7 +2,7 @@ import { MdRefresh } from "react-icons/md"; export default function Revalidate() { const revalidate = () => { - fetch("/api/revalidate").then((res) => { + fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/revalidate`).then((res) => { if (res.ok) { window.location.reload(); } diff --git a/src/components/widgets/search/search.jsx b/src/components/widgets/search/search.jsx index b2204e35..9530b4c0 100644 --- a/src/components/widgets/search/search.jsx +++ b/src/components/widgets/search/search.jsx @@ -106,7 +106,7 @@ export default function Search({ options }) { query.trim().length > 0 && query.trim() !== searchSuggestions[0] ) { - fetch(`/api/search/searchSuggestion?query=${encodeURIComponent(query)}&providerName=${selectedProvider.name}`, { + fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/search/searchSuggestion?query=${encodeURIComponent(query)}&providerName=${selectedProvider.name}`, { signal: abortController.signal, }) .then(async (searchSuggestionResult) => { diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index 8e88f6b2..f5a0da7b 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -67,11 +67,18 @@ const tailwindSafelist = [ "2xl:h-0 2xl:h-1 2xl:h-2 2xl:h-3 2xl:h-4 2xl:h-5 2xl:h-6 2xl:h-7 2xl:h-8 2xl:h-9 2xl:h-10 2xl:h-11 2xl:h-12 2xl:h-13 2xl:h-14 2xl:h-15 2xl:h-16 2xl:h-17 2xl:h-18 2xl:h-19 2xl:h-20 2xl:h-21 2xl:h-22 2xl:h-23 2xl:h-24 2xl:h-25 2xl:h-26 2xl:h-27 2xl:h-28 2xl:h-29 2xl:h-30 2xl:h-31 2xl:h-32 2xl:h-33 2xl:h-34 2xl:h-35 2xl:h-36 2xl:h-37 2xl:h-38 2xl:h-39 2xl:h-40 2xl:h-41 2xl:h-42 2xl:h-43 2xl:h-44 2xl:h-45 2xl:h-46 2xl:h-47 2xl:h-48 2xl:h-49 2xl:h-50 2xl:h-51 2xl:h-52 2xl:h-53 2xl:h-54 2xl:h-55 2xl:h-56 2xl:h-57 2xl:h-58 2xl:h-59 2xl:h-60 2xl:h-61 2xl:h-62 2xl:h-63 2xl:h-64 2xl:h-65 2xl:h-66 2xl:h-67 2xl:h-68 2xl:h-69 2xl:h-70 2xl:h-71 2xl:h-72 2xl:h-73 2xl:h-74 2xl:h-75 2xl:h-76 2xl:h-77 2xl:h-78 2xl:h-79 2xl:h-80 2xl:h-81 2xl:h-82 2xl:h-83 2xl:h-84 2xl:h-85 2xl:h-86 2xl:h-87 2xl:h-88 2xl:h-89 2xl:h-90 2xl:h-91 2xl:h-92 2xl:h-93 2xl:h-94 2xl:h-95 2xl:h-96", ]; +const basePathMiddleware = (useSWRNext) => (key, fetcher, config) => { + const bp = process.env.NEXT_PUBLIC_BASE_PATH ?? ""; + const adjustedKey = bp && typeof key === "string" ? `${bp}${key}` : key; + return useSWRNext(adjustedKey, fetcher, config); +}; + function MyApp({ Component, pageProps }) { return ( fetch(resource, init).then((res) => res.json()), + use: [basePathMiddleware], }} > diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx index ece38aec..bb53fe2e 100644 --- a/src/pages/_document.jsx +++ b/src/pages/_document.jsx @@ -6,8 +6,8 @@ export default function Document() { - - {/* eslint-disable-line @next/next/no-css-tags */} + + {/* eslint-disable-line @next/next/no-css-tags */}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx index c243c3ff..e77481db 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -63,14 +63,15 @@ export async function getStaticProps() { const widgets = await widgetsResponse(); const language = normalizeLanguage(settings.language); + const bp = process.env.NEXT_PUBLIC_BASE_PATH ?? ""; return { props: { initialSettings: settings, fallback: { - "/api/services": services, - "/api/bookmarks": bookmarks, - "/api/widgets": widgets, - "/api/hash": false, + [`${bp}/api/services`]: services, + [`${bp}/api/bookmarks`]: bookmarks, + [`${bp}/api/widgets`]: widgets, + [`${bp}/api/hash`]: false, }, ...(await serverSideTranslations(language)), }, @@ -83,10 +84,10 @@ export async function getStaticProps() { props: { initialSettings: {}, fallback: { - "/api/services": [], - "/api/bookmarks": [], - "/api/widgets": [], - "/api/hash": false, + [`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/services`]: [], + [`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/bookmarks`]: [], + [`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/widgets`]: [], + [`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/hash`]: false, }, ...(await serverSideTranslations("en")), }, @@ -120,7 +121,7 @@ function Index({ initialSettings, fallback }) { setStale(true); localStorage.setItem("hash", hashData.hash); - fetch("/api/revalidate").then((res) => { + fetch(`${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/api/revalidate`).then((res) => { if (res.ok) { window.location.reload(); } @@ -434,7 +435,7 @@ function Home({ initialSettings }) { -