Skip to content

Commit 7279552

Browse files
committed
4565: Reverted how config is loaded in client and admin
1 parent 6907751 commit 7279552

26 files changed

+453
-233
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
let configData = null;
2+
let activePromise = null;
3+
4+
const AdminConfigLoader = {
5+
async loadConfig() {
6+
if (activePromise) {
7+
return activePromise;
8+
}
9+
10+
activePromise = new Promise((resolve) => {
11+
if (configData !== null) {
12+
resolve(configData);
13+
} else {
14+
fetch("/config/admin")
15+
.then((response) => response.json())
16+
.then((data) => {
17+
configData = data;
18+
resolve(configData);
19+
})
20+
.catch(() => {
21+
if (configData !== null) {
22+
resolve(configData);
23+
} else {
24+
// eslint-disable-next-line no-console
25+
console.error(
26+
"Could not load config. Will use default config."
27+
);
28+
29+
// Default config.
30+
resolve({
31+
rejseplanenApiKey: null,
32+
touchButtonRegions: false,
33+
showScreenStatus: false,
34+
enhancedPreview: false,
35+
loginMethods: [
36+
{
37+
type: "username-password",
38+
enabled: true,
39+
provider: "username-password",
40+
label: null,
41+
icon: null,
42+
},
43+
],
44+
});
45+
}
46+
})
47+
.finally(() => {
48+
activePromise = null;
49+
});
50+
}
51+
});
52+
53+
return activePromise;
54+
},
55+
};
56+
57+
Object.freeze(AdminConfigLoader);
58+
59+
export default AdminConfigLoader;

assets/admin/app.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import UsersList from "./components/users/users-list";
3939
import ActivationCodeList from "./components/activation-code/activation-code-list";
4040
import ActivationCodeCreate from "./components/activation-code/activation-code-create";
4141
import ActivationCodeActivate from "./components/activation-code/activation-code-activate";
42-
import ConfigLoader from "../shared/config-loader.js";
42+
import AdminConfigLoader from "./admin-config-loader.js";
4343
import "react-toastify/dist/ReactToastify.css";
4444
import "./app.scss";
4545
import FeedSourcesList from "./components/feed-sources/feed-sources-list";
@@ -90,7 +90,9 @@ function App() {
9090
};
9191

9292
useEffect(() => {
93-
setConfig(ConfigLoader.getConfig());
93+
AdminConfigLoader.loadConfig().then((loadedConfig) => {
94+
setConfig(loadedConfig);
95+
})
9496
}, []);
9597

9698
const handleReauthenticate = () => {

assets/admin/components/screen/screen-list.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
displayError,
1919
} from "../util/list/toast-component/display-toast";
2020
import "./screen-list.scss";
21-
import ConfigLoader from "../../../shared/config-loader.js";
21+
import AdminConfigLoader from "../../admin-config-loader.js";
2222

2323
/**
2424
* The screen list component.
@@ -68,8 +68,9 @@ function ScreenList() {
6868
});
6969

7070
useEffect(() => {
71-
const config = ConfigLoader.getConfig();
72-
setShowScreenStatus(config.showScreenStatus);
71+
AdminConfigLoader.loadConfig().then((loadedConfig) => {
72+
setShowScreenStatus(loadedConfig.showScreenStatus);
73+
});
7374
}, []);
7475

7576
useEffect(() => {

assets/admin/components/screen/screen-status.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import idFromUrl from "../util/helpers/id-from-url";
1818
import { api } from "../../redux/api/api.generated.ts";
1919
import { displayError } from "../util/list/toast-component/display-toast";
2020
import FormInput from "../util/forms/form-input";
21-
import ConfigLoader from "../../../shared/config-loader.js";
21+
import AdminConfigLoader from "../../admin-config-loader.js";
2222

2323
/**
2424
* Displays screen status.
@@ -102,8 +102,9 @@ function ScreenStatus({ screen, handleInput = () => {}, mode = "default" }) {
102102
}, [status]);
103103

104104
useEffect(() => {
105-
const config = ConfigLoader.getConfig();
106-
setShowScreenStatus(config.showScreenStatus);
105+
AdminConfigLoader.loadConfig().then((loadedConfig) => {
106+
setShowScreenStatus(loadedConfig.showScreenStatus);
107+
});
107108
}, []);
108109

109110
if (mode === "minimal") {

assets/admin/components/user/login.jsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {MultiSelect} from "react-multi-select-component";
99
import UserContext from "../../context/user-context";
1010
import FormInput from "../util/forms/form-input";
1111
import {api} from "../../redux/api/api.generated.ts";
12-
import ConfigLoader from "../../../shared/config-loader.js";
12+
import AdminConfigLoader from "../../admin-config-loader.js";
1313
import {displayError} from "../util/list/toast-component/display-toast";
1414
import localStorageKeys from "../util/local-storage-keys";
1515
import LoginSidebar from "../navigation/login-sidebar/login-sidebar";
@@ -193,7 +193,6 @@ function Login() {
193193
};
194194

195195
useEffect(() => {
196-
const config = ConfigLoader.getConfig();
197196
const loginMethodDefaults = [
198197
{
199198
type: "oidc",
@@ -217,9 +216,11 @@ function Login() {
217216
},
218217
];
219218

220-
setLoginMethods(
221-
config.loginMethods ?? loginMethodDefaults
222-
);
219+
AdminConfigLoader.loadConfig().then((loadedConfig) => {
220+
setLoginMethods(
221+
loadedConfig.loginMethods ?? loginMethodDefaults
222+
);
223+
});
223224
}, []);
224225

225226
useEffect(() => {

assets/client/app.jsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
22
import PropTypes from "prop-types";
33
import Screen from "./components/screen.jsx";
44
import ContentService from "./service/content-service";
5-
import ConfigLoader from "../shared/config-loader";
5+
import ClientConfigLoader from "./client-config-loader.js";
66
import logger from "./logger/logger";
77
import "./app.scss";
88
import fallback from "./assets/fallback.png";
@@ -97,12 +97,12 @@ function App({ preview, previewId }) {
9797
clearTimeout(checkLoginTimeoutRef.current);
9898
}
9999

100-
const config = ConfigLoader.getConfig();
101-
102-
checkLoginTimeoutRef.current = setTimeout(
103-
checkLogin,
104-
config.loginCheckTimeout ?? defaults.loginCheckTimeoutDefault
105-
);
100+
ClientConfigLoader.loadConfig().then((config) => {
101+
checkLoginTimeoutRef.current = setTimeout(
102+
checkLogin,
103+
config.loginCheckTimeout ?? defaults.loginCheckTimeoutDefault
104+
);
105+
});
106106
};
107107
/* eslint-enable no-use-before-define */
108108

@@ -220,8 +220,9 @@ function App({ preview, previewId }) {
220220

221221
tokenService.checkToken();
222222

223-
const config = ConfigLoader.getConfig();
224-
setDebug(config.debug ?? false);
223+
ClientConfigLoader.loadConfig().then((config) => {
224+
setDebug(config.debug ?? false);
225+
});
225226

226227
releaseService.checkForNewRelease().finally(() => {
227228
releaseService.setPreviousBootInUrl();
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Only fetch new config if more than 15 minutes have passed.
2+
import appStorage from './util/app-storage';
3+
4+
const configFetchIntervalDefault = 15 * 60 * 1000;
5+
6+
// Defaults.
7+
let configData = null;
8+
9+
// Last time the config was fetched.
10+
let latestFetchTimestamp = 0;
11+
12+
let activePromise = null;
13+
14+
const ClientConfigLoader = {
15+
async loadConfig() {
16+
if (activePromise) {
17+
return activePromise;
18+
}
19+
20+
activePromise = new Promise((resolve) => {
21+
const nowTimestamp = new Date().getTime();
22+
23+
if (
24+
latestFetchTimestamp +
25+
(configData?.configFetchInterval ?? configFetchIntervalDefault) >=
26+
nowTimestamp
27+
) {
28+
resolve(configData);
29+
} else {
30+
fetch(`/config/client`)
31+
.then((response) => response.json())
32+
.then((data) => {
33+
latestFetchTimestamp = nowTimestamp;
34+
configData = data;
35+
36+
// Make api endpoint available through localstorage.
37+
appStorage.setApiUrl(configData.apiEndpoint);
38+
39+
resolve(configData);
40+
})
41+
.catch(() => {
42+
if (configData !== null) {
43+
resolve(configData);
44+
} else {
45+
// eslint-disable-next-line no-console
46+
console.error(
47+
'Could not load config. Will use default config.'
48+
);
49+
50+
// Default config.
51+
resolve({
52+
apiEndpoint: '/api',
53+
dataStrategy: {
54+
type: 'pull',
55+
config: {
56+
interval: 30000,
57+
},
58+
},
59+
loginCheckTimeout: 20000,
60+
configFetchInterval: 900000,
61+
refreshTokenTimeout: 15000,
62+
releaseTimestampIntervalTimeout: 600000,
63+
colorScheme: {
64+
type: 'library',
65+
lat: 56.0,
66+
lng: 10.0,
67+
},
68+
schedulingInterval: 60000,
69+
debug: false,
70+
});
71+
}
72+
})
73+
.finally(() => {
74+
activePromise = null;
75+
});
76+
}
77+
});
78+
79+
return activePromise;
80+
},
81+
};
82+
83+
Object.freeze(ClientConfigLoader);
84+
85+
export default ClientConfigLoader;

assets/client/components/screen.jsx

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Region from "./region.jsx";
66
import "./screen.scss";
77
import logger from "../logger/logger";
88
import TouchRegion from "./touch-region.jsx";
9-
import ConfigLoader from "../../shared/config-loader";
9+
import ClientConfigLoader from "../client-config-loader.js";
1010

1111
/**
1212
* Screen component.
@@ -32,41 +32,41 @@ function Screen({ screen }) {
3232
};
3333

3434
const refreshColorScheme = () => {
35-
const config = ConfigLoader.getConfig();
36-
3735
logger.info("Refreshing color scheme.");
3836

39-
const now = new Date();
40-
let colorScheme = "";
37+
ClientConfigLoader.loadConfig().then((config) => {
38+
const now = new Date();
39+
let colorScheme;
4140

42-
if (config.colorScheme?.type === "library") {
43-
// Default to somewhere in Denmark.
44-
const times = SunCalc.getTimes(
45-
now,
46-
config.colorScheme?.lat ?? 56.0,
47-
config.colorScheme?.lng ?? 10.0
48-
);
41+
if (config.colorScheme?.type === "library") {
42+
// Default to somewhere in Denmark.
43+
const times = SunCalc.getTimes(
44+
now,
45+
config.colorScheme?.lat ?? 56.0,
46+
config.colorScheme?.lng ?? 10.0
47+
);
4948

50-
if (now > times.sunrise && now < times.sunset) {
51-
logger.info("Light color scheme activated.");
52-
colorScheme = "color-scheme-light";
49+
if (now > times.sunrise && now < times.sunset) {
50+
logger.info("Light color scheme activated.");
51+
colorScheme = "color-scheme-light";
52+
} else {
53+
logger.info("Dark color scheme activated.");
54+
colorScheme = "color-scheme-dark";
55+
}
5356
} else {
54-
logger.info("Dark color scheme activated.");
55-
colorScheme = "color-scheme-dark";
57+
// Browser based.
58+
colorScheme = window?.matchMedia("(prefers-color-scheme: dark)").matches
59+
? "color-scheme-dark"
60+
: "color-scheme-light";
5661
}
57-
} else {
58-
// Browser based.
59-
colorScheme = window?.matchMedia("(prefers-color-scheme: dark)").matches
60-
? "color-scheme-dark"
61-
: "color-scheme-light";
62-
}
6362

64-
// Set class name on html root.
65-
document.documentElement.classList.remove(
66-
"color-scheme-light",
67-
"color-scheme-dark"
68-
);
69-
document.documentElement.classList.add(colorScheme);
63+
// Set class name on html root.
64+
document.documentElement.classList.remove(
65+
"color-scheme-light",
66+
"color-scheme-dark"
67+
);
68+
document.documentElement.classList.add(colorScheme);
69+
});
7070
};
7171

7272
useEffect(() => {

assets/client/service/content-service.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import logger from "../logger/logger";
99
import DataSync from "../data-sync/data-sync";
1010
import ScheduleService from "./schedule-service";
11-
import ConfigLoader from "../../shared/config-loader";
11+
import ClientConfigLoader from "../client-config-loader.js";
1212

1313
/**
1414
* ContentService.
@@ -48,18 +48,19 @@ class ContentService {
4848
startSyncing(screenPath) {
4949
logger.info("Starting data synchronization");
5050

51-
const config = ConfigLoader.getConfig();
52-
const dataStrategyConfig = {
53-
interval: config.pullStrategyInterval,
54-
endpoint: "",
55-
};
51+
ClientConfigLoader.loadConfig().then((config) => {
52+
const dataStrategyConfig = {
53+
interval: config.pullStrategyInterval,
54+
endpoint: "",
55+
};
5656

57-
if (screenPath) {
58-
dataStrategyConfig.entryPoint = screenPath;
59-
}
57+
if (screenPath) {
58+
dataStrategyConfig.entryPoint = screenPath;
59+
}
6060

61-
this.dataSync = new DataSync(dataStrategyConfig);
62-
this.dataSync.start();
61+
this.dataSync = new DataSync(dataStrategyConfig);
62+
this.dataSync.start();
63+
});
6364
}
6465

6566
/**

0 commit comments

Comments
 (0)