Skip to content

Commit 8c89da1

Browse files
committed
configuration for frontend python server
1 parent b0bcf48 commit 8c89da1

File tree

4 files changed

+142
-46
lines changed

4 files changed

+142
-46
lines changed

src/frontend_react/src/api/apiClient.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import { headerBuilder } from '../auth';
2-
3-
// Get base API URL
4-
const api = process.env.REACT_APP_API_BASE_URL || 'http://127.0.0.1:8000/api';
1+
import { headerBuilder, getApiUrl } from './config';
52

63
// Helper function to build URL with query parameters
74
const buildUrl = (url: string, params?: Record<string, any>): string => {
@@ -46,7 +43,9 @@ const fetchWithAuth = async (url: string, method: string = "GET", body: BodyInit
4643
};
4744

4845
try {
49-
const response = await fetch(`${api}${url}`, options);
46+
const apiUrl = getApiUrl();
47+
48+
const response = await fetch(`${apiUrl}${url}`, options);
5049
console.log('response', response);
5150

5251
if (!response.ok) {
@@ -75,7 +74,8 @@ const fetchWithoutAuth = async (url: string, method: string = "POST", body: Body
7574
};
7675

7776
try {
78-
const response = await fetch(`${api}${url}`, options);
77+
const apiUrl = getApiUrl();
78+
const response = await fetch(`${apiUrl}${url}`, options);
7979

8080
if (!response.ok) {
8181
const errorText = await response.text();
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// src/config.js
2+
3+
declare global {
4+
interface Window {
5+
appConfig?: Record<string, any>;
6+
activeUserId?: string;
7+
}
8+
}
9+
10+
export let API_URL: string | null = null;
11+
export let USER_ID: string | null = null;
12+
13+
export let config = {
14+
API_URL: "http://localhost:8000/api",
15+
ENABLE_AUTH: false,
16+
};
17+
18+
export function setApiUrl(url: string | null) {
19+
console.log('setApiUrl called with:', url);
20+
if (url) {
21+
API_URL = url.includes('/api') ? url : `${url}/api`;
22+
}
23+
}
24+
25+
export function setEnvData(configData: Record<string, any>) {
26+
if (configData) {
27+
config.API_URL = configData.API_URL || "";
28+
config.ENABLE_AUTH = configData.ENABLE_AUTH || false;
29+
}
30+
}
31+
32+
export function getConfigData() {
33+
if (!config.API_URL || !config.ENABLE_AUTH) {
34+
// Check if window.appConfig exists
35+
if (window.appConfig) {
36+
setEnvData(window.appConfig);
37+
}
38+
}
39+
40+
return { ...config };
41+
}
42+
43+
export function getApiUrl() {
44+
console.log('getApiUrl called');
45+
if (!API_URL) {
46+
// Check if window.appConfig exists
47+
if (window.appConfig && window.appConfig.API_URL) {
48+
setApiUrl(window.appConfig.API_URL);
49+
}
50+
}
51+
52+
if (!API_URL) {
53+
console.info('API URL not yet configured');
54+
return null;
55+
}
56+
57+
return API_URL;
58+
}
59+
60+
export function getUserId(): string {
61+
USER_ID = window.activeUserId ?? null;
62+
const userId = USER_ID ?? "00000000-0000-0000-0000-000000000000";
63+
return userId;
64+
}
65+
66+
/**
67+
* Build headers with authentication information
68+
* @param headers Optional additional headers to merge
69+
* @returns Combined headers object with authentication
70+
*/
71+
export function headerBuilder(headers?: Record<string, string>): Record<string, string> {
72+
let userId = getUserId();
73+
let defaultHeaders = {
74+
"x-ms-client-principal-id": String(userId) || "", // Custom header
75+
};
76+
return {
77+
...defaultHeaders,
78+
...(headers ? headers : {})
79+
};
80+
}
81+
export const toBoolean = (value: any): boolean => {
82+
if (typeof value !== 'string') {
83+
return false;
84+
}
85+
return value.trim().toLowerCase() === 'true';
86+
};
87+
export default {
88+
setApiUrl,
89+
getApiUrl,
90+
toBoolean,
91+
getUserId,
92+
getConfigData,
93+
setEnvData,
94+
config,
95+
USER_ID,
96+
API_URL
97+
};
Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +0,0 @@
1-
2-
declare global {
3-
interface Window {
4-
activeUserId?: string;
5-
}
6-
}
7-
8-
let USER_ID: string | undefined;
9-
10-
/**
11-
* Get the current user ID from the window.activeUserId or return a default UUID
12-
* @returns The user ID string
13-
*/
14-
export function getUserId(): string {
15-
USER_ID = window.activeUserId;
16-
const userId = USER_ID ?? "00000000-0000-0000-0000-000000000000";
17-
return userId;
18-
}
19-
20-
/**
21-
* Build headers with authentication information
22-
* @param headers Optional additional headers to merge
23-
* @returns Combined headers object with authentication
24-
*/
25-
export function headerBuilder(headers?: Record<string, string>): Record<string, string> {
26-
let userId = getUserId();
27-
let defaultHeaders = {
28-
"x-ms-client-principal-id": String(userId) || "", // Custom header
29-
};
30-
return {
31-
...defaultHeaders,
32-
...(headers ? headers : {})
33-
};
34-
}

src/frontend_react/src/index.tsx

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,49 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { StrictMode, useEffect, useState } from 'react';
22
import ReactDOM from 'react-dom/client';
33
import './index.css';
44
import App from './App';
55
import reportWebVitals from './reportWebVitals';
66
import { FluentProvider, teamsLightTheme, teamsDarkTheme } from "@fluentui/react-components";
7-
7+
import { setEnvData, setApiUrl, config as defaultConfig, toBoolean } from './api/config';
88
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
99

1010
const AppWrapper = () => {
1111
// State to store the current theme
12+
const [isConfigLoaded, setIsConfigLoaded] = useState(false);
1213
const [isDarkMode, setIsDarkMode] = useState(
1314
window.matchMedia("(prefers-color-scheme: dark)").matches
1415
);
16+
type ConfigType = typeof defaultConfig;
17+
console.log("defaultConfig", defaultConfig);
18+
const [config, setConfig] = useState<ConfigType>(defaultConfig);
19+
useEffect(() => {
20+
const initConfig = async () => {
21+
window.appConfig = config;
22+
setEnvData(config);
23+
setApiUrl(config.API_URL);
24+
25+
try {
26+
const response = await fetch('/config');
27+
let config = defaultConfig;
28+
if (response.ok) {
29+
config = await response.json();
30+
config.ENABLE_AUTH = toBoolean(config.ENABLE_AUTH);
31+
}
32+
33+
window.appConfig = config;
34+
setEnvData(config);
35+
setApiUrl(config.API_URL);
36+
setConfig(config);
1537

38+
} catch (error) {
39+
console.info("Error fetching config:", error);
40+
} finally {
41+
setIsConfigLoaded(true);
42+
}
43+
};
44+
45+
initConfig(); // Call the async function inside useEffect
46+
}, []);
1647
// Effect to listen for changes in the user's preferred color scheme
1748
useEffect(() => {
1849
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
@@ -28,11 +59,13 @@ const AppWrapper = () => {
2859
mediaQuery.addEventListener("change", handleThemeChange);
2960
return () => mediaQuery.removeEventListener("change", handleThemeChange);
3061
}, []);
31-
62+
if (!isConfigLoaded) return <div>Loading...</div>;
3263
return (
33-
<FluentProvider theme={isDarkMode ? teamsDarkTheme : teamsLightTheme} style={{ height: "100vh" }}>
34-
<App />
35-
</FluentProvider>
64+
<StrictMode>
65+
<FluentProvider theme={isDarkMode ? teamsDarkTheme : teamsLightTheme} style={{ height: "100vh" }}>
66+
<App />
67+
</FluentProvider>
68+
</StrictMode>
3669
);
3770
};
3871
root.render(<AppWrapper />);

0 commit comments

Comments
 (0)