mirror of
https://github.com/hexastack/hexabot
synced 2025-01-22 10:35:37 +00:00
fix: load config on runtime
This commit is contained in:
parent
d2555d9f94
commit
aa05fe1704
@ -16,6 +16,11 @@ services:
|
||||
- ../api/migrations:/app/migrations
|
||||
#- ../api/node_modules:/app/node_modules
|
||||
command: ["npm", "run", "start:debug"]
|
||||
|
||||
hexabot-frontend:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: ./frontend/Dockerfile
|
||||
|
||||
mongo-express:
|
||||
container_name: mongoUi
|
||||
|
@ -30,7 +30,6 @@ services:
|
||||
condition: service_healthy
|
||||
database-init:
|
||||
condition: service_completed_successfully
|
||||
|
||||
healthcheck:
|
||||
test: "wget --spider http://localhost:3000"
|
||||
interval: 10s
|
||||
@ -40,12 +39,7 @@ services:
|
||||
|
||||
hexabot-frontend:
|
||||
container_name: frontend
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: ./frontend/Dockerfile
|
||||
args:
|
||||
- NEXT_PUBLIC_API_ORIGIN=${NEXT_PUBLIC_API_ORIGIN}
|
||||
- NEXT_PUBLIC_SSO_ENABLED=${NEXT_PUBLIC_SSO_ENABLED}
|
||||
image: hexabot-ui:latest
|
||||
env_file: .env
|
||||
ports:
|
||||
- ${APP_FRONTEND_PORT}:8080
|
||||
|
@ -21,14 +21,6 @@ RUN \
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
ARG NEXT_PUBLIC_API_ORIGIN
|
||||
ENV NEXT_PUBLIC_API_ORIGIN=${NEXT_PUBLIC_API_ORIGIN}
|
||||
ARG NEXT_PUBLIC_SSO_ENABLED
|
||||
ENV NEXT_PUBLIC_SSO_ENABLED=${NEXT_PUBLIC_SSO_ENABLED}
|
||||
|
||||
ENV REACT_APP_WIDGET_API_URL=${NEXT_PUBLIC_API_ORIGIN}
|
||||
ENV REACT_APP_WIDGET_CHANNEL=test
|
||||
ENV REACT_APP_WIDGET_TOKEN=test
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@ -57,10 +49,6 @@ ENV NODE_ENV production
|
||||
# Uncomment the following line in case you want to disable telemetry during runtime.
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
# Set the environment variable API_ORIGIN
|
||||
ENV NEXT_PUBLIC_API_ORIGIN ${NEXT_PUBLIC_API_ORIGIN:-"http://localhost:3000"}
|
||||
ENV NEXT_PUBLIC_SSO_ENABLED ${NEXT_PUBLIC_SSO_ENABLED:-"false"}
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
|
@ -4,6 +4,14 @@ import withTM from "next-transpile-modules";
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_ORIGIN || "http://localhost:4000/";
|
||||
const url = new URL(apiUrl);
|
||||
const nextConfig = withTM(["hexabot-widget"])({
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/config",
|
||||
destination: "/api/config",
|
||||
},
|
||||
];
|
||||
},
|
||||
webpack(config, _options) {
|
||||
return config;
|
||||
},
|
||||
|
50
frontend/src/hooks/useConfig.tsx
Normal file
50
frontend/src/hooks/useConfig.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import { createContext, useContext, useEffect, useState } from "react";
|
||||
|
||||
const ConfigContext = createContext(null);
|
||||
|
||||
export interface IConfig {
|
||||
NEXT_PUBLIC_API_ORIGIN: string;
|
||||
NEXT_PUBLIC_SSO_ENABLED: boolean;
|
||||
REACT_APP_WIDGET_API_URL: string;
|
||||
REACT_APP_WIDGET_CHANNEL: string;
|
||||
REACT_APP_WIDGET_TOKEN: string;
|
||||
}
|
||||
|
||||
export const ConfigProvider = ({ children }) => {
|
||||
const [config, setConfig] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchConfig = async () => {
|
||||
try {
|
||||
const res = await fetch("/config");
|
||||
const data = await res.json();
|
||||
|
||||
setConfig(data);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Failed to fetch configuration:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchConfig();
|
||||
}, []);
|
||||
|
||||
if (!config) {
|
||||
// You can return a loader here if you want
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useConfig = () => {
|
||||
const context = useContext(ConfigContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useConfig must be used within a ConfigProvider");
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
@ -20,6 +20,7 @@ import { ReactQueryDevtools } from "react-query/devtools";
|
||||
import { SnackbarCloseButton } from "@/app-components/displays/Toast/CloseButton";
|
||||
import { ApiClientProvider } from "@/hooks/useApiClient";
|
||||
import { AuthProvider } from "@/hooks/useAuth";
|
||||
import { ConfigProvider } from "@/hooks/useConfig";
|
||||
import { PermissionProvider } from "@/hooks/useHasPermission";
|
||||
import { SettingsProvider } from "@/hooks/useSetting";
|
||||
import { ToastProvider } from "@/hooks/useToast";
|
||||
@ -69,33 +70,35 @@ const App = ({ Component, pageProps }: TAppPropsWithLayout) => {
|
||||
/>
|
||||
</Head>
|
||||
<main className={roboto.className}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<ToastProvider
|
||||
maxSnack={3}
|
||||
anchorOrigin={{ vertical: "top", horizontal: "center" }}
|
||||
action={(snackbarKey) => (
|
||||
<SnackbarCloseButton snackbarKey={snackbarKey} />
|
||||
)}
|
||||
>
|
||||
<StyledEngineProvider injectFirst>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<CssBaseline />
|
||||
<ApiClientProvider>
|
||||
<AuthProvider>
|
||||
<PermissionProvider>
|
||||
<SettingsProvider>
|
||||
<SocketProvider>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</SocketProvider>
|
||||
</SettingsProvider>
|
||||
</PermissionProvider>
|
||||
</AuthProvider>
|
||||
</ApiClientProvider>
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
</QueryClientProvider>
|
||||
</StyledEngineProvider>
|
||||
</ToastProvider>
|
||||
</ThemeProvider>
|
||||
<ConfigProvider>
|
||||
<ThemeProvider theme={theme}>
|
||||
<ToastProvider
|
||||
maxSnack={3}
|
||||
anchorOrigin={{ vertical: "top", horizontal: "center" }}
|
||||
action={(snackbarKey) => (
|
||||
<SnackbarCloseButton snackbarKey={snackbarKey} />
|
||||
)}
|
||||
>
|
||||
<StyledEngineProvider injectFirst>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<CssBaseline />
|
||||
<ApiClientProvider>
|
||||
<AuthProvider>
|
||||
<PermissionProvider>
|
||||
<SettingsProvider>
|
||||
<SocketProvider>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</SocketProvider>
|
||||
</SettingsProvider>
|
||||
</PermissionProvider>
|
||||
</AuthProvider>
|
||||
</ApiClientProvider>
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
</QueryClientProvider>
|
||||
</StyledEngineProvider>
|
||||
</ToastProvider>
|
||||
</ThemeProvider>
|
||||
</ConfigProvider>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
|
16
frontend/src/pages/api/config.ts
Normal file
16
frontend/src/pages/api/config.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
type ResponseData = {
|
||||
apiUrl: string;
|
||||
ssoEnabled: boolean;
|
||||
};
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<ResponseData>,
|
||||
) {
|
||||
res.status(200).json({
|
||||
apiUrl: process.env.NEXT_PUBLIC_API_ORIGIN || "http://localhost:3000",
|
||||
ssoEnabled: process.env.NEXT_PUBLIC_SSO_ENABLED === "true" || false,
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user