refactor: replace all old router to new router
This commit is contained in:
parent
fa7534a8e0
commit
3bb2cc8715
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
@ -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')}
|
||||
|
@ -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>
|
||||
)}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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')}
|
||||
|
@ -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) {
|
||||
|
@ -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">
|
||||
|
@ -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}>
|
||||
|
@ -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 */
|
||||
|
@ -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>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -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
|
||||
|
79
src/client/routes/monitor/$monitorId/edit.tsx
Normal file
79
src/client/routes/monitor/$monitorId/edit.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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,
|
||||
});
|
@ -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">
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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')}
|
||||
|
@ -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
|
||||
|
33
src/client/routes/status/$slug.tsx
Normal file
33
src/client/routes/status/$slug.tsx
Normal 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} />;
|
||||
}
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user