refactor: replace all old router to new router

This commit is contained in:
moonrailgun 2024-04-02 01:12:44 +08:00
parent fa7534a8e0
commit 3bb2cc8715
21 changed files with 298 additions and 105 deletions

View File

@ -1,8 +1,8 @@
import dayjs from 'dayjs';
import { useUserStore } from '../../store/user';
import { useEvent } from '../../hooks/useEvent';
import { useNavigate } from 'react-router';
import { clearJWT } from '../auth';
import { useNavigate } from '@tanstack/react-router';
/**
* Mock
@ -18,7 +18,10 @@ export function useLogout() {
const logout = useEvent(() => {
useUserStore.setState({ info: null });
clearJWT();
navigate('/login');
navigate({
to: '/login',
replace: true,
});
});
return logout;

View File

@ -6,6 +6,7 @@ import { useNavigate, useRouterState } from '@tanstack/react-router';
import { LuSearch } from 'react-icons/lu';
import { Input } from './ui/input';
import { useFuseSearch } from '@/hooks/useFuseSearch';
import { Empty } from 'antd';
export interface CommonListItem {
id: string;
@ -65,6 +66,8 @@ export const CommonList: React.FC<CommonListProps> = React.memo((props) => {
<ScrollArea className="flex-1">
<div className="flex flex-col gap-2 p-4">
{finalList.length === 0 && <Empty />}
{finalList.map((item) => {
const isSelected = item.href === location.pathname;

View File

@ -5,16 +5,15 @@ import { Loading } from '../../Loading';
import { NotFoundTip } from '../../NotFoundTip';
import { WebsiteOverview } from '../../website/WebsiteOverview';
import { Button } from 'antd';
import { useNavigate } from 'react-router';
import { ArrowRightOutlined } from '@ant-design/icons';
import { useTranslation } from '@i18next-toolkit/react';
import { Link } from '@tanstack/react-router';
export const WebsiteOverviewItem: React.FC<{
websiteId: string;
}> = React.memo((props) => {
const { t } = useTranslation();
const workspaceId = useCurrentWorkspaceId();
const navigate = useNavigate();
const { data: websiteInfo, isLoading } = trpc.website.info.useQuery({
workspaceId,
@ -34,15 +33,11 @@ export const WebsiteOverviewItem: React.FC<{
website={websiteInfo}
actions={
<>
<Button
type="primary"
size="large"
onClick={() => {
navigate(`/website/${websiteInfo.id}`);
}}
>
{t('View Details')} <ArrowRightOutlined />
</Button>
<Link to="/website/$websiteId" params={{ websiteId: websiteInfo.id }}>
<Button type="primary" size="large">
{t('View Details')} <ArrowRightOutlined />
</Button>
</Link>
</>
}
/>

View File

@ -14,7 +14,6 @@ import { MonitorInfo as MonitorInfoType } from '../../../types';
import { MonitorHealthBar } from './MonitorHealthBar';
import { last } from 'lodash-es';
import { ColorTag } from '../ColorTag';
import { useNavigate } from 'react-router';
import { MonitorEventList } from './MonitorEventList';
import { useEvent } from '../../hooks/useEvent';
import { MonitorDataMetrics } from './MonitorDataMetrics';
@ -22,6 +21,7 @@ import { MonitorDataChart } from './MonitorDataChart';
import { DeleteOutlined, MoreOutlined } from '@ant-design/icons';
import { MonitorBadgeView } from './MonitorBadgeView';
import { useTranslation } from '@i18next-toolkit/react';
import { useNavigate } from '@tanstack/react-router';
interface MonitorInfoProps {
monitorId: string;
@ -109,7 +109,8 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
});
await trpcUtils.monitor.all.refetch();
navigate('/monitor', {
navigate({
to: '/monitor',
replace: true,
});
},
@ -198,7 +199,12 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
<Button
type="primary"
onClick={() => {
navigate(`/monitor/${monitorInfo.id}/edit`);
navigate({
to: '/monitor/$monitorId/edit',
params: {
monitorId: monitorInfo.id,
},
});
}}
>
{t('Edit')}

View File

@ -8,25 +8,26 @@ import {
} from './EditForm';
import clsx from 'clsx';
import { useRequest } from '../../../hooks/useRequest';
import { useNavigate } from 'react-router';
import { ColorSchemeSwitcher } from '../../ColorSchemeSwitcher';
import { StatusPageServices } from './Services';
import { useTranslation } from '@i18next-toolkit/react';
import { Link, useNavigate } from '@tanstack/react-router';
interface MonitorStatusPageProps {
slug: string;
showBackBtn?: boolean;
}
export const MonitorStatusPage: React.FC<MonitorStatusPageProps> = React.memo(
(props) => {
const { t } = useTranslation();
const { slug } = props;
const { slug, showBackBtn = true } = props;
const { data: info } = trpc.monitor.getPageInfo.useQuery({
slug,
});
const editPageMutation = trpc.monitor.editPage.useMutation();
const trpcUtils = trpc.useContext();
const trpcUtils = trpc.useUtils();
const navigate = useNavigate();
const allowEdit = useAllowEdit(info?.workspaceId);
@ -58,7 +59,13 @@ export const MonitorStatusPage: React.FC<MonitorStatusPageProps> = React.memo(
if (info.slug !== newPageInfo.slug) {
// if slug is changed, should to navigate to new url
navigate(`/status/${newPageInfo.slug}`);
navigate({
to: '/status/$slug',
params: {
slug: newPageInfo.slug,
},
replace: true,
});
}
}
);
@ -94,9 +101,11 @@ export const MonitorStatusPage: React.FC<MonitorStatusPageProps> = React.memo(
{t('Edit')}
</Button>
<Button type="default" onClick={() => navigate(`/`)}>
{t('Back to Admin')}
</Button>
{showBackBtn && (
<Link to="/">
<Button type="default">{t('Back to Admin')}</Button>
</Link>
)}
</div>
)}

View File

@ -3,9 +3,9 @@ import React from 'react';
import { trpc } from '../../api/trpc';
import { useCurrentWorkspaceId } from '../../store/user';
import { ColorTag } from '../ColorTag';
import { useNavigate } from 'react-router';
import { PlusOutlined } from '@ant-design/icons';
import { useTranslation } from '@i18next-toolkit/react';
import { useNavigate } from '@tanstack/react-router';
interface NotificationPickerProps extends SelectProps<string> {}
export const NotificationPicker: React.FC<NotificationPickerProps> = React.memo(
@ -26,7 +26,11 @@ export const NotificationPicker: React.FC<NotificationPickerProps> = React.memo(
<div className="mb-1">{t('Not found any notification')}</div>
<Button
icon={<PlusOutlined />}
onClick={() => navigate('/settings/notifications')}
onClick={() =>
navigate({
to: '/settings/notifications',
})
}
>
{t('Create Now')}
</Button>

View File

@ -26,11 +26,10 @@ import {
PlusOutlined,
DeleteOutlined,
} from '@ant-design/icons';
import { useNavigate } from 'react-router';
import { PageHeader } from '../PageHeader';
import { useEvent } from '../../hooks/useEvent';
import { TelemetryCounter } from './TelemetryCounter';
import { LuDelete, LuTrash } from 'react-icons/lu';
import { useNavigate } from '@tanstack/react-router';
type TelemetryInfo = AppRouterOutput['telemetry']['all'][number];
@ -276,7 +275,12 @@ const TelemetryListTable: React.FC<{
<Button
icon={<BarChartOutlined />}
onClick={() => {
navigate(`/telemetry/${record.id}`);
navigate({
to: '/telemetry/$telemetryId',
params: {
telemetryId: record.id,
},
});
}}
>
{t('View')}

View File

@ -1,6 +1,5 @@
import { Button, Form, Input, message, Popconfirm, Tabs } from 'antd';
import React from 'react';
import { useNavigate, useParams } from 'react-router';
import { deleteWorkspaceWebsite } from '../../api/model/website';
import { useRequest } from '../../hooks/useRequest';
import { useCurrentWorkspaceId } from '../../store/user';
@ -18,6 +17,7 @@ import { useQueryClient } from '@tanstack/react-query';
import { useEvent } from '../../hooks/useEvent';
import { hostnameValidator } from '../../utils/validator';
import { useTranslation } from '@i18next-toolkit/react';
import { useNavigate } from '@tanstack/react-router';
export const WebsiteConfig: React.FC<{ websiteId: string }> = React.memo(
(props) => {
@ -57,7 +57,9 @@ export const WebsiteConfig: React.FC<{ websiteId: string }> = React.memo(
message.success(t('Delete Success'));
navigate('/settings/websites');
navigate({
to: '/website',
});
});
if (!workspaceId) {

View File

@ -10,12 +10,12 @@ import { formatNumber, formatShortTime } from '../../utils/common';
import { WebsiteOnlineCount } from './WebsiteOnlineCount';
import { useGlobalRangeDate } from '../../hooks/useGlobalRangeDate';
import { MonitorHealthBar } from '../monitor/MonitorHealthBar';
import { useNavigate } from 'react-router';
import { AppRouterOutput, trpc } from '../../api/trpc';
import { getUserTimezone } from '../../api/model/user';
import { useGlobalStateStore } from '../../store/global';
import { useTranslation } from '@i18next-toolkit/react';
import { TimeEventChart } from '../TimeEventChart';
import { Link } from '@tanstack/react-router';
export const WebsiteOverview: React.FC<{
website: WebsiteInfo;
@ -25,7 +25,6 @@ export const WebsiteOverview: React.FC<{
const { t } = useTranslation();
const { website, showDateFilter = false, actions } = props;
const { startDate, endDate, unit, refresh } = useGlobalRangeDate();
const navigate = useNavigate();
const showPreviousPeriod = useGlobalStateStore(
(state) => state.showPreviousPeriod
);
@ -91,15 +90,16 @@ export const WebsiteOverview: React.FC<{
</span>
{website.monitorId && (
<div
<Link
className="cursor-pointer"
onClick={() => navigate(`/monitor/${website.monitorId}`)}
to="/monitor/$monitorId"
params={{ monitorId: website.monitorId }}
>
<MonitorHealthBar
workspaceId={website.workspaceId}
monitorId={website.monitorId}
/>
</div>
</Link>
)}
<div className="ml-4 text-base font-normal">

View File

@ -20,7 +20,7 @@ import { WorkspaceSwitcher } from '@/components/WorkspaceSwitcher';
import { UserConfig } from './Layout/UserConfig';
import { Outlet } from '@tanstack/react-router';
import { trpc } from '@/api/trpc';
import { useCurrentWorkspaceId } from '@/store/user';
import { useCurrentWorkspaceId, useUserStore } from '@/store/user';
const defaultLayout: [number, number, number] = [265, 440, 655];
@ -38,10 +38,15 @@ export const LayoutV2: React.FC<LayoutProps> = React.memo((props) => {
defaultValue: false,
}
);
const workspaceId = useCurrentWorkspaceId();
const { data: serviceCount } = trpc.workspace.getServiceCount.useQuery({
workspaceId,
});
const workspaceId = useUserStore((state) => state.info?.currentWorkspace?.id);
const { data: serviceCount } = trpc.workspace.getServiceCount.useQuery(
{
workspaceId: workspaceId!,
},
{
enabled: !!workspaceId,
}
);
return (
<TooltipProvider delayDuration={0}>

View File

@ -25,6 +25,7 @@ import { Route as WebsiteOverviewImport } from './routes/website/overview'
import { Route as WebsiteAddImport } from './routes/website/add'
import { Route as TelemetryAddImport } from './routes/telemetry/add'
import { Route as TelemetryTelemetryIdImport } from './routes/telemetry/$telemetryId'
import { Route as StatusSlugImport } from './routes/status/$slug'
import { Route as SettingsUsageImport } from './routes/settings/usage'
import { Route as SettingsProfileImport } from './routes/settings/profile'
import { Route as SettingsNotificationsImport } from './routes/settings/notifications'
@ -32,9 +33,10 @@ import { Route as SettingsAuditLogImport } from './routes/settings/auditLog'
import { Route as PageAddImport } from './routes/page/add'
import { Route as PageSlugImport } from './routes/page/$slug'
import { Route as MonitorAddImport } from './routes/monitor/add'
import { Route as MonitorMonitorIdImport } from './routes/monitor/$monitorId'
import { Route as WebsiteWebsiteIdIndexImport } from './routes/website/$websiteId/index'
import { Route as MonitorMonitorIdIndexImport } from './routes/monitor/$monitorId/index'
import { Route as WebsiteWebsiteIdConfigImport } from './routes/website/$websiteId/config'
import { Route as MonitorMonitorIdEditImport } from './routes/monitor/$monitorId/edit'
// Create/Update Routes
@ -108,6 +110,11 @@ const TelemetryTelemetryIdRoute = TelemetryTelemetryIdImport.update({
getParentRoute: () => TelemetryRoute,
} as any)
const StatusSlugRoute = StatusSlugImport.update({
path: '/status/$slug',
getParentRoute: () => rootRoute,
} as any)
const SettingsUsageRoute = SettingsUsageImport.update({
path: '/usage',
getParentRoute: () => SettingsRoute,
@ -143,21 +150,26 @@ const MonitorAddRoute = MonitorAddImport.update({
getParentRoute: () => MonitorRoute,
} as any)
const MonitorMonitorIdRoute = MonitorMonitorIdImport.update({
path: '/$monitorId',
getParentRoute: () => MonitorRoute,
} as any)
const WebsiteWebsiteIdIndexRoute = WebsiteWebsiteIdIndexImport.update({
path: '/$websiteId/',
getParentRoute: () => WebsiteRoute,
} as any)
const MonitorMonitorIdIndexRoute = MonitorMonitorIdIndexImport.update({
path: '/$monitorId/',
getParentRoute: () => MonitorRoute,
} as any)
const WebsiteWebsiteIdConfigRoute = WebsiteWebsiteIdConfigImport.update({
path: '/$websiteId/config',
getParentRoute: () => WebsiteRoute,
} as any)
const MonitorMonitorIdEditRoute = MonitorMonitorIdEditImport.update({
path: '/$monitorId/edit',
getParentRoute: () => MonitorRoute,
} as any)
// Populate the FileRoutesByPath interface
declare module '@tanstack/react-router' {
@ -202,10 +214,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof WebsiteImport
parentRoute: typeof rootRoute
}
'/monitor/$monitorId': {
preLoaderRoute: typeof MonitorMonitorIdImport
parentRoute: typeof MonitorImport
}
'/monitor/add': {
preLoaderRoute: typeof MonitorAddImport
parentRoute: typeof MonitorImport
@ -234,6 +242,10 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof SettingsUsageImport
parentRoute: typeof SettingsImport
}
'/status/$slug': {
preLoaderRoute: typeof StatusSlugImport
parentRoute: typeof rootRoute
}
'/telemetry/$telemetryId': {
preLoaderRoute: typeof TelemetryTelemetryIdImport
parentRoute: typeof TelemetryImport
@ -250,10 +262,18 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof WebsiteOverviewImport
parentRoute: typeof WebsiteImport
}
'/monitor/$monitorId/edit': {
preLoaderRoute: typeof MonitorMonitorIdEditImport
parentRoute: typeof MonitorImport
}
'/website/$websiteId/config': {
preLoaderRoute: typeof WebsiteWebsiteIdConfigImport
parentRoute: typeof WebsiteImport
}
'/monitor/$monitorId/': {
preLoaderRoute: typeof MonitorMonitorIdIndexImport
parentRoute: typeof MonitorImport
}
'/website/$websiteId/': {
preLoaderRoute: typeof WebsiteWebsiteIdIndexImport
parentRoute: typeof WebsiteImport
@ -267,7 +287,11 @@ export const routeTree = rootRoute.addChildren([
IndexRoute,
DashboardRoute,
LoginRoute,
MonitorRoute.addChildren([MonitorMonitorIdRoute, MonitorAddRoute]),
MonitorRoute.addChildren([
MonitorAddRoute,
MonitorMonitorIdEditRoute,
MonitorMonitorIdIndexRoute,
]),
PageRoute.addChildren([PageSlugRoute, PageAddRoute]),
RegisterRoute,
ServerRoute,
@ -284,6 +308,7 @@ export const routeTree = rootRoute.addChildren([
WebsiteWebsiteIdConfigRoute,
WebsiteWebsiteIdIndexRoute,
]),
StatusSlugRoute,
])
/* prettier-ignore-end */

View File

@ -1,5 +1,6 @@
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
import { Suspense } from 'react';
interface RouterContext {
// The ReturnType of your useAuth hook or the value of your AuthContext
@ -9,10 +10,11 @@ interface RouterContext {
export const Route = createRootRouteWithContext<RouterContext>()({
component: () => {
return (
<>
// https://github.com/TanStack/router/issues/857
<Suspense fallback={null}>
<Outlet />
<TanStackRouterDevtools position="bottom-right" />
</>
</Suspense>
);
},
});

View File

@ -1,8 +1,4 @@
import {
createFileRoute,
getRouteApi,
useNavigate,
} from '@tanstack/react-router';
import { createFileRoute, redirect, useNavigate } from '@tanstack/react-router';
import { useRequest } from '@/hooks/useRequest';
import { setJWT } from '@/api/auth';
import { useGlobalConfig } from '@/hooks/useConfig';
@ -17,16 +13,21 @@ export const Route = createFileRoute('/login')({
// redirect: z.string().catch('/'),
redirect: z.string().optional(),
}),
beforeLoad: ({ context }) => {
if (context.userInfo) {
redirect({
to: '/website',
});
}
},
component: LoginComponent,
});
const routeApi = getRouteApi('/login');
function LoginComponent() {
const navigate = useNavigate();
const { t } = useTranslation();
const loginMutation = trpc.user.login.useMutation();
const search = routeApi.useSearch();
const search = Route.useSearch();
const [{ loading }, handleLogin] = useRequest(async (values: any) => {
const res = await loginMutation.mutateAsync({
@ -37,16 +38,17 @@ function LoginComponent() {
setJWT(res.token);
setUserInfo(res.info);
navigate({
to: search.redirect ?? '/dashboard',
to: search.redirect ?? '/',
replace: true,
});
});
const { allowRegister } = useGlobalConfig();
return (
<div className="w-full h-full flex justify-center items-center dark:bg-gray-900">
<div className="flex h-full w-full items-center justify-center dark:bg-gray-900">
<div className="w-80 -translate-y-1/4">
<div className="text-center">
<img className="w-24 h-24" src="/icon.svg" />
<img className="m-auto h-24 w-24" src="/icon.svg" />
</div>
<Typography.Title className="text-center" level={2}>
Tianji

View File

@ -0,0 +1,79 @@
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { t, useTranslation } from '@i18next-toolkit/react';
import { Button } from '@/components/ui/button';
import { useEvent } from '@/hooks/useEvent';
import { useCurrentWorkspaceId } from '@/store/user';
import { trpc } from '@/api/trpc';
import { Card, CardContent, CardFooter } from '@/components/ui/card';
import { CommonWrapper } from '@/components/CommonWrapper';
import {
MonitorInfoEditor,
MonitorInfoEditorValues,
} from '@/components/monitor/MonitorInfoEditor';
import { routeAuthBeforeLoad } from '@/utils/route';
import { useMonitorUpsert } from '@/api/model/monitor';
import { Loading } from '@/components/Loading';
import { ErrorTip } from '@/components/ErrorTip';
import { CommonHeader } from '@/components/CommonHeader';
export const Route = createFileRoute('/monitor/$monitorId/edit')({
beforeLoad: routeAuthBeforeLoad,
component: PageComponent,
});
function PageComponent() {
const { t } = useTranslation();
const { monitorId } = Route.useParams<{ monitorId: string }>();
const workspaceId = useCurrentWorkspaceId();
const navigate = useNavigate();
const mutation = useMonitorUpsert();
const { data: monitor, isLoading } = trpc.monitor.get.useQuery({
monitorId,
workspaceId,
});
const handleSubmit = useEvent(async (values: MonitorInfoEditorValues) => {
const res = await mutation.mutateAsync({
...values,
workspaceId,
});
navigate({
to: '/monitor/$monitorId',
params: {
monitorId: res.id,
},
replace: true,
});
});
if (isLoading) {
return <Loading />;
}
if (!monitor) {
return <ErrorTip />;
}
return (
<CommonWrapper
header={<CommonHeader title={monitor.name} desc={t('Edit')} />}
>
<div className="p-4">
<Card>
<CardContent className="pt-4">
<MonitorInfoEditor
initialValues={
{
...monitor,
notificationIds: monitor.notifications.map((n) => n.id),
} as MonitorInfoEditorValues
}
onSave={handleSubmit}
/>
</CardContent>
</Card>
</div>
</CommonWrapper>
);
}

View File

@ -10,7 +10,7 @@ import { useCurrentWorkspaceId } from '@/store/user';
import { routeAuthBeforeLoad } from '@/utils/route';
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/monitor/$monitorId')({
export const Route = createFileRoute('/monitor/$monitorId/')({
beforeLoad: routeAuthBeforeLoad,
component: MonitorDetailComponent,
});

View File

@ -12,6 +12,7 @@ import {
} from '@/components/monitor/MonitorInfoEditor';
import { routeAuthBeforeLoad } from '@/utils/route';
import { useMonitorUpsert } from '@/api/model/monitor';
import { CommonHeader } from '@/components/CommonHeader';
export const Route = createFileRoute('/monitor/add')({
beforeLoad: routeAuthBeforeLoad,
@ -23,7 +24,6 @@ function MonitorAddComponent() {
const workspaceId = useCurrentWorkspaceId();
const navigate = useNavigate();
const mutation = useMonitorUpsert();
const utils = trpc.useUtils();
const handleSubmit = useEvent(async (values: MonitorInfoEditorValues) => {
const res = await mutation.mutateAsync({
@ -31,8 +31,6 @@ function MonitorAddComponent() {
workspaceId,
});
utils.monitor.all.refetch();
navigate({
to: '/monitor/$monitorId',
params: {
@ -42,9 +40,7 @@ function MonitorAddComponent() {
});
return (
<CommonWrapper
header={<h1 className="text-xl font-bold">{t('Add Monitor')}</h1>}
>
<CommonWrapper header={<CommonHeader title={t('Add Monitor')} />}>
<div className="p-4">
<Card>
<CardContent className="pt-4">

View File

@ -5,17 +5,21 @@ import { ErrorTip } from '@/components/ErrorTip';
import { Loading } from '@/components/Loading';
import { NotFoundTip } from '@/components/NotFoundTip';
import { MonitorStatusPage } from '@/components/monitor/StatusPage';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Button } from '@/components/ui/button';
import { routeAuthBeforeLoad } from '@/utils/route';
import { createFileRoute } from '@tanstack/react-router';
import { useTranslation } from '@i18next-toolkit/react';
import { Link, createFileRoute, useNavigate } from '@tanstack/react-router';
import { LuEye } from 'react-icons/lu';
export const Route = createFileRoute('/page/$slug')({
beforeLoad: routeAuthBeforeLoad,
component: PageDetailComponent,
component: PageComponent,
});
function PageDetailComponent() {
function PageComponent() {
const { slug } = Route.useParams<{ slug: string }>();
const { t } = useTranslation();
const navigate = useNavigate();
const { data: pageInfo, isLoading } = trpc.monitor.getPageInfo.useQuery({
slug,
});
@ -33,10 +37,21 @@ function PageDetailComponent() {
}
return (
<CommonWrapper header={<CommonHeader title={pageInfo.title} />}>
{/* <ScrollArea className="h-full overflow-hidden"> */}
<MonitorStatusPage slug={slug} />
{/* </ScrollArea> */}
<CommonWrapper
header={
<CommonHeader
title={pageInfo.title}
actions={
<Link to="/status/$slug" params={{ slug }} target="_blank">
<Button variant="outline" Icon={LuEye}>
{t('Preview')}
</Button>
</Link>
}
/>
}
>
<MonitorStatusPage slug={slug} showBackBtn={false} />
</CommonWrapper>
);
}

View File

@ -1,11 +1,10 @@
import { Button, Form, Input, Typography } from 'antd';
import { useNavigate } from 'react-router';
import { useRequest } from '../hooks/useRequest';
import { trpc } from '../api/trpc';
import { setJWT } from '../api/auth';
import { setUserInfo } from '../store/user';
import { useTranslation } from '@i18next-toolkit/react';
import { createFileRoute } from '@tanstack/react-router';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
export const Route = createFileRoute('/register')({
component: RegisterComponent,
@ -25,14 +24,17 @@ function RegisterComponent() {
setJWT(res.token);
setUserInfo(res.info);
navigate('/dashboard');
navigate({
to: '/',
replace: true,
});
});
return (
<div className="flex h-full w-full items-center justify-center">
<div className="flex h-full w-full items-center justify-center dark:bg-gray-900">
<div className="w-80 -translate-y-1/4">
<div className="text-center">
<img className="h-24 w-24" src="/icon.svg" />
<img className="m-auto h-24 w-24 " src="/icon.svg" />
</div>
<Typography.Title className="text-center" level={2}>
{t('Register Account')}

View File

@ -3,12 +3,14 @@ import { createFileRoute } from '@tanstack/react-router';
import { useTranslation } from '@i18next-toolkit/react';
import { CommonWrapper } from '@/components/CommonWrapper';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Button, Card, Form, Input, Modal, Typography } from 'antd';
import { Card, Form, Input, Modal, Popconfirm, Typography } from 'antd';
import { useLogout } from '@/api/model/user';
import { trpc, defaultSuccessHandler, defaultErrorHandler } from '@/api/trpc';
import { useUserStore } from '@/store/user';
import { useState } from 'react';
import { CommonHeader } from '@/components/CommonHeader';
import { Separator } from '@/components/ui/separator';
import { Button } from '@/components/ui/button';
export const Route = createFileRoute('/settings/profile')({
beforeLoad: routeAuthBeforeLoad,
@ -45,13 +47,22 @@ function PageComponent() {
</Form.Item>
<Form.Item label={t('Password')}>
<Button
danger={true}
variant="destructive"
onClick={() => setOpenChangePassword(true)}
>
{t('Change Password')}
</Button>
</Form.Item>
</Form>
<Separator className="mb-4" />
<Popconfirm
title={t('Confirm to logout')}
onConfirm={() => logout()}
>
<Button variant="destructive">{t('Logout')}</Button>
</Popconfirm>
</Card>
<Modal

View File

@ -0,0 +1,33 @@
import { trpc } from '@/api/trpc';
import { ErrorTip } from '@/components/ErrorTip';
import { Loading } from '@/components/Loading';
import { NotFoundTip } from '@/components/NotFoundTip';
import { MonitorStatusPage } from '@/components/monitor/StatusPage';
import { Button } from '@/components/ui/button';
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/status/$slug')({
component: PageComponent,
});
function PageComponent() {
const { slug } = Route.useParams<{ slug: string }>();
const { data: pageInfo, isLoading } = trpc.monitor.getPageInfo.useQuery({
slug,
});
if (!slug) {
return <ErrorTip />;
}
if (isLoading) {
return <Loading />;
}
if (!pageInfo) {
return <NotFoundTip />;
}
return <MonitorStatusPage slug={slug} />;
}

View File

@ -1,29 +1,13 @@
import { routeAuthBeforeLoad } from '@/utils/route';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { Link, createFileRoute, useNavigate } from '@tanstack/react-router';
import { useTranslation } from '@i18next-toolkit/react';
import { Button } from '@/components/ui/button';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { useEvent } from '@/hooks/useEvent';
import { Input } from '@/components/ui/input';
import { useCurrentWorkspaceId } from '@/store/user';
import { trpc } from '@/api/trpc';
import { hostnameRegex } from '@tianji/shared';
import { Card, CardContent, CardFooter } from '@/components/ui/card';
import { CommonWrapper } from '@/components/CommonWrapper';
import { WebsiteOverview } from '@/components/website/WebsiteOverview';
import { Empty } from 'antd';
import { LuPlus } from 'react-icons/lu';
import { LuArrowRight, LuPlus } from 'react-icons/lu';
import { ScrollArea } from '@/components/ui/scroll-area';
export const Route = createFileRoute('/website/overview')({
@ -46,6 +30,7 @@ function WebsiteOverviewComponent() {
<ScrollArea className="h-full overflow-hidden p-4">
{websites.length === 0 && isLoading === false && (
<Empty
className="pt-8"
description={
<div className="py-2">
<div className="mb-1">
@ -68,7 +53,19 @@ function WebsiteOverviewComponent() {
<div className="space-y-10 p-4">
{websites.map((website) => (
<WebsiteOverview website={website} />
<WebsiteOverview
website={website}
actions={
<Link
to="/website/$websiteId"
params={{ websiteId: website.id }}
>
<Button size="lg">
{t('View Details')} <LuArrowRight className="ml-2" />
</Button>
</Link>
}
/>
))}
</div>
</ScrollArea>