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"
# 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 { MonitorPage } from './pages/Monitor';
import { WebsitePage } from './pages/Website';
import { useGlobalConfig } from './hooks/useConfig';
import { useInjectWebsiteScript } from './hooks/useInjectWebsiteScript';
export const AppRoutes: React.FC = React.memo(() => {
const { info } = useUserStore();
const { allowRegister } = useGlobalConfig();
useInjectWebsiteScript();
return (
<Routes>
@ -30,7 +35,7 @@ export const AppRoutes: React.FC = React.memo(() => {
) : (
<Route>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
{allowRegister && <Route path="/register" element={<Register />} />}
</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 { setJWT } from '../api/auth';
import { setUserInfo } from '../store/user';
import { useGlobalConfig } from '../hooks/useConfig';
export const Login: React.FC = React.memo(() => {
const navigate = useNavigate();
@ -20,6 +21,7 @@ export const Login: React.FC = React.memo(() => {
setUserInfo(res.info);
navigate('/dashboard');
});
const { allowRegister } = useGlobalConfig();
return (
<div className="w-full h-full flex justify-center items-center">
@ -51,6 +53,8 @@ export const Login: React.FC = React.memo(() => {
Login
</Button>
</Form.Item>
{allowRegister && (
<Form.Item>
<Button
size="large"
@ -63,6 +67,7 @@ export const Login: React.FC = React.memo(() => {
Register
</Button>
</Form.Item>
)}
</Form>
</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 { userRouter } from './user';
import { workspaceRouter } from './workspace';
import { globalRouter } from './global';
export const appRouter = router({
global: globalRouter,
user: userRouter,
workspace: workspaceRouter,
website: websiteRouter,