From 50e491af06e1451233c4ac9733a32ba9901127cf Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 1 Aug 2022 23:04:47 -0700 Subject: [PATCH] Added endpoint for fetching server-side variables. --- components/common/UpdateNotice.js | 11 ++++++++--- components/layout/Footer.js | 6 +++--- components/layout/Header.js | 6 +++--- hooks/useApi.js | 10 +++++----- hooks/useConfig.js | 24 ++++++++++++++++++++++++ pages/_app.js | 1 - pages/api/config.js | 14 ++++++++++++++ store/app.js | 5 +++++ 8 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 hooks/useConfig.js create mode 100644 pages/api/config.js diff --git a/components/common/UpdateNotice.js b/components/common/UpdateNotice.js index a5036808..bc27215e 100644 --- a/components/common/UpdateNotice.js +++ b/components/common/UpdateNotice.js @@ -6,10 +6,15 @@ import { setItem } from 'lib/web'; import { REPO_URL, VERSION_CHECK } from 'lib/constants'; import Button from './Button'; import styles from './UpdateNotice.module.css'; +import useUser from 'hooks/useUser'; +import useConfig from 'hooks/useConfig'; export default function UpdateNotice() { + const { user } = useUser(); + const { updatesDisabled } = useConfig(); const { latest, checked, hasUpdate, releaseUrl } = useStore(); const [dismissed, setDismissed] = useState(false); + const allowCheck = user?.is_admin && !updatesDisabled; const updateCheck = useCallback(() => { setItem(VERSION_CHECK, { version: latest, time: Date.now() }); @@ -27,12 +32,12 @@ export default function UpdateNotice() { } useEffect(() => { - if (!checked) { + if (!checked && allowCheck) { checkVersion(); } - }, []); + }, [checked]); - if (!hasUpdate || dismissed) { + if (!hasUpdate || dismissed || !allowCheck) { return null; } diff --git a/components/layout/Footer.js b/components/layout/Footer.js index ff7db96c..e7d0b14f 100644 --- a/components/layout/Footer.js +++ b/components/layout/Footer.js @@ -5,9 +5,11 @@ import Link from 'components/common/Link'; import styles from './Footer.module.css'; import useStore from 'store/version'; import { HOMEPAGE_URL, REPO_URL } from 'lib/constants'; +import useConfig from 'hooks/useConfig'; export default function Footer() { const { current } = useStore(); + const { telemetryDisabled } = useConfig(); return ( ); } diff --git a/components/layout/Header.js b/components/layout/Header.js index 5f5a85bc..0d36429d 100644 --- a/components/layout/Header.js +++ b/components/layout/Header.js @@ -8,10 +8,10 @@ import ThemeButton from 'components/settings/ThemeButton'; import HamburgerButton from 'components/common/HamburgerButton'; import UpdateNotice from 'components/common/UpdateNotice'; import UserButton from 'components/settings/UserButton'; -import Logo from 'assets/logo.svg'; -import styles from './Header.module.css'; import useUser from 'hooks/useUser'; import { HOMEPAGE_URL } from 'lib/constants'; +import Logo from 'assets/logo.svg'; +import styles from './Header.module.css'; export default function Header() { const { user } = useUser(); @@ -19,7 +19,7 @@ export default function Header() { return ( <> - {user?.is_admin && !process.env.updatesDisabled && } +
} size="large" className={styles.logo} /> diff --git a/hooks/useApi.js b/hooks/useApi.js index b2e74998..63e88a46 100644 --- a/hooks/useApi.js +++ b/hooks/useApi.js @@ -6,7 +6,7 @@ import useStore from 'store/app'; const selector = state => state.shareToken; -function parseHeaders(headers = {}, { authToken, shareToken }) { +function parseHeaders(headers, { authToken, shareToken }) { if (authToken) { headers.authorization = `Bearer ${authToken}`; } @@ -25,7 +25,7 @@ export default function useApi() { return { get: useCallback( - async (url, params, headers) => { + async (url, params = {}, headers = {}) => { return get( `${basePath}/api${url}`, params, @@ -36,7 +36,7 @@ export default function useApi() { ), post: useCallback( - async (url, params, headers) => { + async (url, params = {}, headers = {}) => { return post( `${basePath}/api${url}`, params, @@ -47,7 +47,7 @@ export default function useApi() { ), put: useCallback( - async (url, params, headers) => { + async (url, params = {}, headers = {}) => { return put( `${basePath}/api${url}`, params, @@ -58,7 +58,7 @@ export default function useApi() { ), del: useCallback( - async (url, params, headers) => { + async (url, params = {}, headers = {}) => { return del( `${basePath}/api${url}`, params, diff --git a/hooks/useConfig.js b/hooks/useConfig.js new file mode 100644 index 00000000..8adedcaf --- /dev/null +++ b/hooks/useConfig.js @@ -0,0 +1,24 @@ +import { useEffect } from 'react'; +import useStore, { setConfig } from 'store/app'; +import useApi from 'hooks/useApi'; + +let fetched = false; + +export default function useConfig() { + const { config } = useStore(); + const { get } = useApi(); + + async function loadConfig() { + const { data } = await get('/config'); + setConfig(data); + } + + useEffect(() => { + if (!config && !fetched) { + fetched = true; + loadConfig(); + } + }, []); + + return config || {}; +} diff --git a/pages/_app.js b/pages/_app.js index 5c83c264..b8653113 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -1,4 +1,3 @@ -import React from 'react'; import Head from 'next/head'; import { useRouter } from 'next/router'; import { IntlProvider } from 'react-intl'; diff --git a/pages/api/config.js b/pages/api/config.js new file mode 100644 index 00000000..a72eb0ba --- /dev/null +++ b/pages/api/config.js @@ -0,0 +1,14 @@ +import { ok, methodNotAllowed } from 'lib/response'; + +export default async (req, res) => { + if (req.method === 'GET') { + return ok(res, { + basePath: process.env.BASE_PATH || '', + trackerScriptName: process.env.TRACKER_SCRIPT_NAME, + updatesDisabled: !!process.env.DISABLE_UPDATES, + telemetryDisabled: !!process.env.DISABLE_TELEMETRY, + }); + } + + return methodNotAllowed(res); +}; diff --git a/store/app.js b/store/app.js index 65295fd0..ff4a91a4 100644 --- a/store/app.js +++ b/store/app.js @@ -20,6 +20,7 @@ const initialState = { dashboard: getItem(DASHBOARD_CONFIG) || defaultDashboardConfig, shareToken: null, user: null, + config: null, }; const store = create(() => ({ ...initialState })); @@ -45,4 +46,8 @@ export function setDashboard(dashboard) { setItem(DASHBOARD_CONFIG, dashboard); } +export function setConfig(config) { + store.setState({ config }); +} + export default store;