feat: add global config to control register feature and inject website id

This commit is contained in:
moonrailgun 2023-10-21 00:18:30 +08:00
parent 461d819246
commit a7f9870e64
8 changed files with 108 additions and 13 deletions

View File

@ -1 +1,8 @@
# postgresql url
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
# Whether allow register user
ALLOW_REGISTER=
# For analyze tianji self
WEBSITE_ID=

View File

@ -13,9 +13,14 @@ import React from 'react';
import { trpc, trpcClient } from './api/trpc'; import { trpc, trpcClient } from './api/trpc';
import { MonitorPage } from './pages/Monitor'; import { MonitorPage } from './pages/Monitor';
import { WebsitePage } from './pages/Website'; import { WebsitePage } from './pages/Website';
import { useGlobalConfig } from './hooks/useConfig';
import { useInjectWebsiteScript } from './hooks/useInjectWebsiteScript';
export const AppRoutes: React.FC = React.memo(() => { export const AppRoutes: React.FC = React.memo(() => {
const { info } = useUserStore(); const { info } = useUserStore();
const { allowRegister } = useGlobalConfig();
useInjectWebsiteScript();
return ( return (
<Routes> <Routes>
@ -30,7 +35,7 @@ export const AppRoutes: React.FC = React.memo(() => {
) : ( ) : (
<Route> <Route>
<Route path="/login" element={<Login />} /> <Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} /> {allowRegister && <Route path="/register" element={<Register />} />}
</Route> </Route>
)} )}

View File

@ -0,0 +1,19 @@
import { AppRouterOutput, trpc } from '../api/trpc';
const defaultGlobalConfig: AppRouterOutput['global']['config'] = {
allowRegister: false,
};
/**
* Fetch settings from server
*/
export function useGlobalConfig(): AppRouterOutput['global']['config'] {
const { data = defaultGlobalConfig } = trpc.global.config.useQuery(
undefined,
{
staleTime: 1000 * 60 * 60 * 1, // 1 hour
}
);
return data;
}

View File

@ -0,0 +1,27 @@
import { DependencyList, useLayoutEffect, useRef } from 'react';
import { useEvent } from './useEvent';
/**
* Call once on data ready(validator return true)
*/
export function useDataReady(
validator: () => boolean,
cb: () => void,
deps?: DependencyList
) {
const isReadyRef = useRef(false);
const _validator = useEvent(validator);
const _callback = useEvent(cb);
useLayoutEffect(() => {
if (isReadyRef.current) {
return;
}
if (_validator() === true) {
_callback();
isReadyRef.current = true;
}
}, deps);
}

View File

@ -0,0 +1,16 @@
import { useGlobalConfig } from './useConfig';
import { useDataReady } from './useDataReady';
export function useInjectWebsiteScript() {
const { websiteId } = useGlobalConfig();
useDataReady(
() => typeof websiteId === 'string' && websiteId.length > 0,
() => {
const el = document.createElement('script');
el.src = location.origin + '/tracker.js';
el.setAttribute('data-website-id', String(websiteId));
document.head.append(el);
}
);
}

View File

@ -5,6 +5,7 @@ import { useRequest } from '../hooks/useRequest';
import { trpc } from '../api/trpc'; import { trpc } from '../api/trpc';
import { setJWT } from '../api/auth'; import { setJWT } from '../api/auth';
import { setUserInfo } from '../store/user'; import { setUserInfo } from '../store/user';
import { useGlobalConfig } from '../hooks/useConfig';
export const Login: React.FC = React.memo(() => { export const Login: React.FC = React.memo(() => {
const navigate = useNavigate(); const navigate = useNavigate();
@ -20,6 +21,7 @@ export const Login: React.FC = React.memo(() => {
setUserInfo(res.info); setUserInfo(res.info);
navigate('/dashboard'); navigate('/dashboard');
}); });
const { allowRegister } = useGlobalConfig();
return ( return (
<div className="w-full h-full flex justify-center items-center"> <div className="w-full h-full flex justify-center items-center">
@ -51,18 +53,21 @@ export const Login: React.FC = React.memo(() => {
Login Login
</Button> </Button>
</Form.Item> </Form.Item>
<Form.Item>
<Button {allowRegister && (
size="large" <Form.Item>
htmlType="button" <Button
block={true} size="large"
onClick={() => { htmlType="button"
navigate('/register'); block={true}
}} onClick={() => {
> navigate('/register');
Register }}
</Button> >
</Form.Item> Register
</Button>
</Form.Item>
)}
</Form> </Form>
</div> </div>
</div> </div>

View File

@ -0,0 +1,14 @@
import { publicProcedure, router } from '../trpc';
export const globalRouter = router({
config: publicProcedure.query(async ({ input }) => {
return {
allowRegister: checkEnvTrusty(process.env.ALLOW_REGISTER),
websiteId: process.env.WEBSITE_ID,
};
}),
});
function checkEnvTrusty(env: string | undefined): boolean {
return env === '1' || env === 'true';
}

View File

@ -4,8 +4,10 @@ import { websiteRouter } from './website';
import { monitorRouter } from './monitor'; import { monitorRouter } from './monitor';
import { userRouter } from './user'; import { userRouter } from './user';
import { workspaceRouter } from './workspace'; import { workspaceRouter } from './workspace';
import { globalRouter } from './global';
export const appRouter = router({ export const appRouter = router({
global: globalRouter,
user: userRouter, user: userRouter,
workspace: workspaceRouter, workspace: workspaceRouter,
website: websiteRouter, website: websiteRouter,