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 dayjs from 'dayjs';
|
||||||
import { useUserStore } from '../../store/user';
|
import { useUserStore } from '../../store/user';
|
||||||
import { useEvent } from '../../hooks/useEvent';
|
import { useEvent } from '../../hooks/useEvent';
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { clearJWT } from '../auth';
|
import { clearJWT } from '../auth';
|
||||||
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock
|
* Mock
|
||||||
@ -18,7 +18,10 @@ export function useLogout() {
|
|||||||
const logout = useEvent(() => {
|
const logout = useEvent(() => {
|
||||||
useUserStore.setState({ info: null });
|
useUserStore.setState({ info: null });
|
||||||
clearJWT();
|
clearJWT();
|
||||||
navigate('/login');
|
navigate({
|
||||||
|
to: '/login',
|
||||||
|
replace: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return logout;
|
return logout;
|
||||||
|
@ -6,6 +6,7 @@ import { useNavigate, useRouterState } from '@tanstack/react-router';
|
|||||||
import { LuSearch } from 'react-icons/lu';
|
import { LuSearch } from 'react-icons/lu';
|
||||||
import { Input } from './ui/input';
|
import { Input } from './ui/input';
|
||||||
import { useFuseSearch } from '@/hooks/useFuseSearch';
|
import { useFuseSearch } from '@/hooks/useFuseSearch';
|
||||||
|
import { Empty } from 'antd';
|
||||||
|
|
||||||
export interface CommonListItem {
|
export interface CommonListItem {
|
||||||
id: string;
|
id: string;
|
||||||
@ -65,6 +66,8 @@ export const CommonList: React.FC<CommonListProps> = React.memo((props) => {
|
|||||||
|
|
||||||
<ScrollArea className="flex-1">
|
<ScrollArea className="flex-1">
|
||||||
<div className="flex flex-col gap-2 p-4">
|
<div className="flex flex-col gap-2 p-4">
|
||||||
|
{finalList.length === 0 && <Empty />}
|
||||||
|
|
||||||
{finalList.map((item) => {
|
{finalList.map((item) => {
|
||||||
const isSelected = item.href === location.pathname;
|
const isSelected = item.href === location.pathname;
|
||||||
|
|
||||||
|
@ -5,16 +5,15 @@ import { Loading } from '../../Loading';
|
|||||||
import { NotFoundTip } from '../../NotFoundTip';
|
import { NotFoundTip } from '../../NotFoundTip';
|
||||||
import { WebsiteOverview } from '../../website/WebsiteOverview';
|
import { WebsiteOverview } from '../../website/WebsiteOverview';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { ArrowRightOutlined } from '@ant-design/icons';
|
import { ArrowRightOutlined } from '@ant-design/icons';
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
|
import { Link } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const WebsiteOverviewItem: React.FC<{
|
export const WebsiteOverviewItem: React.FC<{
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
}> = React.memo((props) => {
|
}> = React.memo((props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const workspaceId = useCurrentWorkspaceId();
|
const workspaceId = useCurrentWorkspaceId();
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const { data: websiteInfo, isLoading } = trpc.website.info.useQuery({
|
const { data: websiteInfo, isLoading } = trpc.website.info.useQuery({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -34,15 +33,11 @@ export const WebsiteOverviewItem: React.FC<{
|
|||||||
website={websiteInfo}
|
website={websiteInfo}
|
||||||
actions={
|
actions={
|
||||||
<>
|
<>
|
||||||
<Button
|
<Link to="/website/$websiteId" params={{ websiteId: websiteInfo.id }}>
|
||||||
type="primary"
|
<Button type="primary" size="large">
|
||||||
size="large"
|
{t('View Details')} <ArrowRightOutlined />
|
||||||
onClick={() => {
|
</Button>
|
||||||
navigate(`/website/${websiteInfo.id}`);
|
</Link>
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('View Details')} <ArrowRightOutlined />
|
|
||||||
</Button>
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -14,7 +14,6 @@ import { MonitorInfo as MonitorInfoType } from '../../../types';
|
|||||||
import { MonitorHealthBar } from './MonitorHealthBar';
|
import { MonitorHealthBar } from './MonitorHealthBar';
|
||||||
import { last } from 'lodash-es';
|
import { last } from 'lodash-es';
|
||||||
import { ColorTag } from '../ColorTag';
|
import { ColorTag } from '../ColorTag';
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { MonitorEventList } from './MonitorEventList';
|
import { MonitorEventList } from './MonitorEventList';
|
||||||
import { useEvent } from '../../hooks/useEvent';
|
import { useEvent } from '../../hooks/useEvent';
|
||||||
import { MonitorDataMetrics } from './MonitorDataMetrics';
|
import { MonitorDataMetrics } from './MonitorDataMetrics';
|
||||||
@ -22,6 +21,7 @@ import { MonitorDataChart } from './MonitorDataChart';
|
|||||||
import { DeleteOutlined, MoreOutlined } from '@ant-design/icons';
|
import { DeleteOutlined, MoreOutlined } from '@ant-design/icons';
|
||||||
import { MonitorBadgeView } from './MonitorBadgeView';
|
import { MonitorBadgeView } from './MonitorBadgeView';
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
|
|
||||||
interface MonitorInfoProps {
|
interface MonitorInfoProps {
|
||||||
monitorId: string;
|
monitorId: string;
|
||||||
@ -109,7 +109,8 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
|
|||||||
});
|
});
|
||||||
await trpcUtils.monitor.all.refetch();
|
await trpcUtils.monitor.all.refetch();
|
||||||
|
|
||||||
navigate('/monitor', {
|
navigate({
|
||||||
|
to: '/monitor',
|
||||||
replace: true,
|
replace: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -198,7 +199,12 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
|
|||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(`/monitor/${monitorInfo.id}/edit`);
|
navigate({
|
||||||
|
to: '/monitor/$monitorId/edit',
|
||||||
|
params: {
|
||||||
|
monitorId: monitorInfo.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('Edit')}
|
{t('Edit')}
|
||||||
|
@ -8,25 +8,26 @@ import {
|
|||||||
} from './EditForm';
|
} from './EditForm';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useRequest } from '../../../hooks/useRequest';
|
import { useRequest } from '../../../hooks/useRequest';
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { ColorSchemeSwitcher } from '../../ColorSchemeSwitcher';
|
import { ColorSchemeSwitcher } from '../../ColorSchemeSwitcher';
|
||||||
import { StatusPageServices } from './Services';
|
import { StatusPageServices } from './Services';
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
|
import { Link, useNavigate } from '@tanstack/react-router';
|
||||||
|
|
||||||
interface MonitorStatusPageProps {
|
interface MonitorStatusPageProps {
|
||||||
slug: string;
|
slug: string;
|
||||||
|
showBackBtn?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MonitorStatusPage: React.FC<MonitorStatusPageProps> = React.memo(
|
export const MonitorStatusPage: React.FC<MonitorStatusPageProps> = React.memo(
|
||||||
(props) => {
|
(props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { slug } = props;
|
const { slug, showBackBtn = true } = props;
|
||||||
|
|
||||||
const { data: info } = trpc.monitor.getPageInfo.useQuery({
|
const { data: info } = trpc.monitor.getPageInfo.useQuery({
|
||||||
slug,
|
slug,
|
||||||
});
|
});
|
||||||
const editPageMutation = trpc.monitor.editPage.useMutation();
|
const editPageMutation = trpc.monitor.editPage.useMutation();
|
||||||
const trpcUtils = trpc.useContext();
|
const trpcUtils = trpc.useUtils();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const allowEdit = useAllowEdit(info?.workspaceId);
|
const allowEdit = useAllowEdit(info?.workspaceId);
|
||||||
@ -58,7 +59,13 @@ export const MonitorStatusPage: React.FC<MonitorStatusPageProps> = React.memo(
|
|||||||
|
|
||||||
if (info.slug !== newPageInfo.slug) {
|
if (info.slug !== newPageInfo.slug) {
|
||||||
// if slug is changed, should to navigate to new url
|
// 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')}
|
{t('Edit')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button type="default" onClick={() => navigate(`/`)}>
|
{showBackBtn && (
|
||||||
{t('Back to Admin')}
|
<Link to="/">
|
||||||
</Button>
|
<Button type="default">{t('Back to Admin')}</Button>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@ import React from 'react';
|
|||||||
import { trpc } from '../../api/trpc';
|
import { trpc } from '../../api/trpc';
|
||||||
import { useCurrentWorkspaceId } from '../../store/user';
|
import { useCurrentWorkspaceId } from '../../store/user';
|
||||||
import { ColorTag } from '../ColorTag';
|
import { ColorTag } from '../ColorTag';
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { PlusOutlined } from '@ant-design/icons';
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
|
|
||||||
interface NotificationPickerProps extends SelectProps<string> {}
|
interface NotificationPickerProps extends SelectProps<string> {}
|
||||||
export const NotificationPicker: React.FC<NotificationPickerProps> = React.memo(
|
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>
|
<div className="mb-1">{t('Not found any notification')}</div>
|
||||||
<Button
|
<Button
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
onClick={() => navigate('/settings/notifications')}
|
onClick={() =>
|
||||||
|
navigate({
|
||||||
|
to: '/settings/notifications',
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{t('Create Now')}
|
{t('Create Now')}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -26,11 +26,10 @@ import {
|
|||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { PageHeader } from '../PageHeader';
|
import { PageHeader } from '../PageHeader';
|
||||||
import { useEvent } from '../../hooks/useEvent';
|
import { useEvent } from '../../hooks/useEvent';
|
||||||
import { TelemetryCounter } from './TelemetryCounter';
|
import { TelemetryCounter } from './TelemetryCounter';
|
||||||
import { LuDelete, LuTrash } from 'react-icons/lu';
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
|
|
||||||
type TelemetryInfo = AppRouterOutput['telemetry']['all'][number];
|
type TelemetryInfo = AppRouterOutput['telemetry']['all'][number];
|
||||||
|
|
||||||
@ -276,7 +275,12 @@ const TelemetryListTable: React.FC<{
|
|||||||
<Button
|
<Button
|
||||||
icon={<BarChartOutlined />}
|
icon={<BarChartOutlined />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(`/telemetry/${record.id}`);
|
navigate({
|
||||||
|
to: '/telemetry/$telemetryId',
|
||||||
|
params: {
|
||||||
|
telemetryId: record.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('View')}
|
{t('View')}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Button, Form, Input, message, Popconfirm, Tabs } from 'antd';
|
import { Button, Form, Input, message, Popconfirm, Tabs } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useNavigate, useParams } from 'react-router';
|
|
||||||
import { deleteWorkspaceWebsite } from '../../api/model/website';
|
import { deleteWorkspaceWebsite } from '../../api/model/website';
|
||||||
import { useRequest } from '../../hooks/useRequest';
|
import { useRequest } from '../../hooks/useRequest';
|
||||||
import { useCurrentWorkspaceId } from '../../store/user';
|
import { useCurrentWorkspaceId } from '../../store/user';
|
||||||
@ -18,6 +17,7 @@ import { useQueryClient } from '@tanstack/react-query';
|
|||||||
import { useEvent } from '../../hooks/useEvent';
|
import { useEvent } from '../../hooks/useEvent';
|
||||||
import { hostnameValidator } from '../../utils/validator';
|
import { hostnameValidator } from '../../utils/validator';
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const WebsiteConfig: React.FC<{ websiteId: string }> = React.memo(
|
export const WebsiteConfig: React.FC<{ websiteId: string }> = React.memo(
|
||||||
(props) => {
|
(props) => {
|
||||||
@ -57,7 +57,9 @@ export const WebsiteConfig: React.FC<{ websiteId: string }> = React.memo(
|
|||||||
|
|
||||||
message.success(t('Delete Success'));
|
message.success(t('Delete Success'));
|
||||||
|
|
||||||
navigate('/settings/websites');
|
navigate({
|
||||||
|
to: '/website',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!workspaceId) {
|
if (!workspaceId) {
|
||||||
|
@ -10,12 +10,12 @@ import { formatNumber, formatShortTime } from '../../utils/common';
|
|||||||
import { WebsiteOnlineCount } from './WebsiteOnlineCount';
|
import { WebsiteOnlineCount } from './WebsiteOnlineCount';
|
||||||
import { useGlobalRangeDate } from '../../hooks/useGlobalRangeDate';
|
import { useGlobalRangeDate } from '../../hooks/useGlobalRangeDate';
|
||||||
import { MonitorHealthBar } from '../monitor/MonitorHealthBar';
|
import { MonitorHealthBar } from '../monitor/MonitorHealthBar';
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { AppRouterOutput, trpc } from '../../api/trpc';
|
import { AppRouterOutput, trpc } from '../../api/trpc';
|
||||||
import { getUserTimezone } from '../../api/model/user';
|
import { getUserTimezone } from '../../api/model/user';
|
||||||
import { useGlobalStateStore } from '../../store/global';
|
import { useGlobalStateStore } from '../../store/global';
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
import { TimeEventChart } from '../TimeEventChart';
|
import { TimeEventChart } from '../TimeEventChart';
|
||||||
|
import { Link } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const WebsiteOverview: React.FC<{
|
export const WebsiteOverview: React.FC<{
|
||||||
website: WebsiteInfo;
|
website: WebsiteInfo;
|
||||||
@ -25,7 +25,6 @@ export const WebsiteOverview: React.FC<{
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { website, showDateFilter = false, actions } = props;
|
const { website, showDateFilter = false, actions } = props;
|
||||||
const { startDate, endDate, unit, refresh } = useGlobalRangeDate();
|
const { startDate, endDate, unit, refresh } = useGlobalRangeDate();
|
||||||
const navigate = useNavigate();
|
|
||||||
const showPreviousPeriod = useGlobalStateStore(
|
const showPreviousPeriod = useGlobalStateStore(
|
||||||
(state) => state.showPreviousPeriod
|
(state) => state.showPreviousPeriod
|
||||||
);
|
);
|
||||||
@ -91,15 +90,16 @@ export const WebsiteOverview: React.FC<{
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
{website.monitorId && (
|
{website.monitorId && (
|
||||||
<div
|
<Link
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
onClick={() => navigate(`/monitor/${website.monitorId}`)}
|
to="/monitor/$monitorId"
|
||||||
|
params={{ monitorId: website.monitorId }}
|
||||||
>
|
>
|
||||||
<MonitorHealthBar
|
<MonitorHealthBar
|
||||||
workspaceId={website.workspaceId}
|
workspaceId={website.workspaceId}
|
||||||
monitorId={website.monitorId}
|
monitorId={website.monitorId}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="ml-4 text-base font-normal">
|
<div className="ml-4 text-base font-normal">
|
||||||
|
@ -20,7 +20,7 @@ import { WorkspaceSwitcher } from '@/components/WorkspaceSwitcher';
|
|||||||
import { UserConfig } from './Layout/UserConfig';
|
import { UserConfig } from './Layout/UserConfig';
|
||||||
import { Outlet } from '@tanstack/react-router';
|
import { Outlet } from '@tanstack/react-router';
|
||||||
import { trpc } from '@/api/trpc';
|
import { trpc } from '@/api/trpc';
|
||||||
import { useCurrentWorkspaceId } from '@/store/user';
|
import { useCurrentWorkspaceId, useUserStore } from '@/store/user';
|
||||||
|
|
||||||
const defaultLayout: [number, number, number] = [265, 440, 655];
|
const defaultLayout: [number, number, number] = [265, 440, 655];
|
||||||
|
|
||||||
@ -38,10 +38,15 @@ export const LayoutV2: React.FC<LayoutProps> = React.memo((props) => {
|
|||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const workspaceId = useCurrentWorkspaceId();
|
const workspaceId = useUserStore((state) => state.info?.currentWorkspace?.id);
|
||||||
const { data: serviceCount } = trpc.workspace.getServiceCount.useQuery({
|
const { data: serviceCount } = trpc.workspace.getServiceCount.useQuery(
|
||||||
workspaceId,
|
{
|
||||||
});
|
workspaceId: workspaceId!,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: !!workspaceId,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipProvider delayDuration={0}>
|
<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 WebsiteAddImport } from './routes/website/add'
|
||||||
import { Route as TelemetryAddImport } from './routes/telemetry/add'
|
import { Route as TelemetryAddImport } from './routes/telemetry/add'
|
||||||
import { Route as TelemetryTelemetryIdImport } from './routes/telemetry/$telemetryId'
|
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 SettingsUsageImport } from './routes/settings/usage'
|
||||||
import { Route as SettingsProfileImport } from './routes/settings/profile'
|
import { Route as SettingsProfileImport } from './routes/settings/profile'
|
||||||
import { Route as SettingsNotificationsImport } from './routes/settings/notifications'
|
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 PageAddImport } from './routes/page/add'
|
||||||
import { Route as PageSlugImport } from './routes/page/$slug'
|
import { Route as PageSlugImport } from './routes/page/$slug'
|
||||||
import { Route as MonitorAddImport } from './routes/monitor/add'
|
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 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 WebsiteWebsiteIdConfigImport } from './routes/website/$websiteId/config'
|
||||||
|
import { Route as MonitorMonitorIdEditImport } from './routes/monitor/$monitorId/edit'
|
||||||
|
|
||||||
// Create/Update Routes
|
// Create/Update Routes
|
||||||
|
|
||||||
@ -108,6 +110,11 @@ const TelemetryTelemetryIdRoute = TelemetryTelemetryIdImport.update({
|
|||||||
getParentRoute: () => TelemetryRoute,
|
getParentRoute: () => TelemetryRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const StatusSlugRoute = StatusSlugImport.update({
|
||||||
|
path: '/status/$slug',
|
||||||
|
getParentRoute: () => rootRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const SettingsUsageRoute = SettingsUsageImport.update({
|
const SettingsUsageRoute = SettingsUsageImport.update({
|
||||||
path: '/usage',
|
path: '/usage',
|
||||||
getParentRoute: () => SettingsRoute,
|
getParentRoute: () => SettingsRoute,
|
||||||
@ -143,21 +150,26 @@ const MonitorAddRoute = MonitorAddImport.update({
|
|||||||
getParentRoute: () => MonitorRoute,
|
getParentRoute: () => MonitorRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
const MonitorMonitorIdRoute = MonitorMonitorIdImport.update({
|
|
||||||
path: '/$monitorId',
|
|
||||||
getParentRoute: () => MonitorRoute,
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
const WebsiteWebsiteIdIndexRoute = WebsiteWebsiteIdIndexImport.update({
|
const WebsiteWebsiteIdIndexRoute = WebsiteWebsiteIdIndexImport.update({
|
||||||
path: '/$websiteId/',
|
path: '/$websiteId/',
|
||||||
getParentRoute: () => WebsiteRoute,
|
getParentRoute: () => WebsiteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const MonitorMonitorIdIndexRoute = MonitorMonitorIdIndexImport.update({
|
||||||
|
path: '/$monitorId/',
|
||||||
|
getParentRoute: () => MonitorRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const WebsiteWebsiteIdConfigRoute = WebsiteWebsiteIdConfigImport.update({
|
const WebsiteWebsiteIdConfigRoute = WebsiteWebsiteIdConfigImport.update({
|
||||||
path: '/$websiteId/config',
|
path: '/$websiteId/config',
|
||||||
getParentRoute: () => WebsiteRoute,
|
getParentRoute: () => WebsiteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const MonitorMonitorIdEditRoute = MonitorMonitorIdEditImport.update({
|
||||||
|
path: '/$monitorId/edit',
|
||||||
|
getParentRoute: () => MonitorRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
// Populate the FileRoutesByPath interface
|
// Populate the FileRoutesByPath interface
|
||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
@ -202,10 +214,6 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof WebsiteImport
|
preLoaderRoute: typeof WebsiteImport
|
||||||
parentRoute: typeof rootRoute
|
parentRoute: typeof rootRoute
|
||||||
}
|
}
|
||||||
'/monitor/$monitorId': {
|
|
||||||
preLoaderRoute: typeof MonitorMonitorIdImport
|
|
||||||
parentRoute: typeof MonitorImport
|
|
||||||
}
|
|
||||||
'/monitor/add': {
|
'/monitor/add': {
|
||||||
preLoaderRoute: typeof MonitorAddImport
|
preLoaderRoute: typeof MonitorAddImport
|
||||||
parentRoute: typeof MonitorImport
|
parentRoute: typeof MonitorImport
|
||||||
@ -234,6 +242,10 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof SettingsUsageImport
|
preLoaderRoute: typeof SettingsUsageImport
|
||||||
parentRoute: typeof SettingsImport
|
parentRoute: typeof SettingsImport
|
||||||
}
|
}
|
||||||
|
'/status/$slug': {
|
||||||
|
preLoaderRoute: typeof StatusSlugImport
|
||||||
|
parentRoute: typeof rootRoute
|
||||||
|
}
|
||||||
'/telemetry/$telemetryId': {
|
'/telemetry/$telemetryId': {
|
||||||
preLoaderRoute: typeof TelemetryTelemetryIdImport
|
preLoaderRoute: typeof TelemetryTelemetryIdImport
|
||||||
parentRoute: typeof TelemetryImport
|
parentRoute: typeof TelemetryImport
|
||||||
@ -250,10 +262,18 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof WebsiteOverviewImport
|
preLoaderRoute: typeof WebsiteOverviewImport
|
||||||
parentRoute: typeof WebsiteImport
|
parentRoute: typeof WebsiteImport
|
||||||
}
|
}
|
||||||
|
'/monitor/$monitorId/edit': {
|
||||||
|
preLoaderRoute: typeof MonitorMonitorIdEditImport
|
||||||
|
parentRoute: typeof MonitorImport
|
||||||
|
}
|
||||||
'/website/$websiteId/config': {
|
'/website/$websiteId/config': {
|
||||||
preLoaderRoute: typeof WebsiteWebsiteIdConfigImport
|
preLoaderRoute: typeof WebsiteWebsiteIdConfigImport
|
||||||
parentRoute: typeof WebsiteImport
|
parentRoute: typeof WebsiteImport
|
||||||
}
|
}
|
||||||
|
'/monitor/$monitorId/': {
|
||||||
|
preLoaderRoute: typeof MonitorMonitorIdIndexImport
|
||||||
|
parentRoute: typeof MonitorImport
|
||||||
|
}
|
||||||
'/website/$websiteId/': {
|
'/website/$websiteId/': {
|
||||||
preLoaderRoute: typeof WebsiteWebsiteIdIndexImport
|
preLoaderRoute: typeof WebsiteWebsiteIdIndexImport
|
||||||
parentRoute: typeof WebsiteImport
|
parentRoute: typeof WebsiteImport
|
||||||
@ -267,7 +287,11 @@ export const routeTree = rootRoute.addChildren([
|
|||||||
IndexRoute,
|
IndexRoute,
|
||||||
DashboardRoute,
|
DashboardRoute,
|
||||||
LoginRoute,
|
LoginRoute,
|
||||||
MonitorRoute.addChildren([MonitorMonitorIdRoute, MonitorAddRoute]),
|
MonitorRoute.addChildren([
|
||||||
|
MonitorAddRoute,
|
||||||
|
MonitorMonitorIdEditRoute,
|
||||||
|
MonitorMonitorIdIndexRoute,
|
||||||
|
]),
|
||||||
PageRoute.addChildren([PageSlugRoute, PageAddRoute]),
|
PageRoute.addChildren([PageSlugRoute, PageAddRoute]),
|
||||||
RegisterRoute,
|
RegisterRoute,
|
||||||
ServerRoute,
|
ServerRoute,
|
||||||
@ -284,6 +308,7 @@ export const routeTree = rootRoute.addChildren([
|
|||||||
WebsiteWebsiteIdConfigRoute,
|
WebsiteWebsiteIdConfigRoute,
|
||||||
WebsiteWebsiteIdIndexRoute,
|
WebsiteWebsiteIdIndexRoute,
|
||||||
]),
|
]),
|
||||||
|
StatusSlugRoute,
|
||||||
])
|
])
|
||||||
|
|
||||||
/* prettier-ignore-end */
|
/* prettier-ignore-end */
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router';
|
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router';
|
||||||
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
|
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
|
||||||
|
import { Suspense } from 'react';
|
||||||
|
|
||||||
interface RouterContext {
|
interface RouterContext {
|
||||||
// The ReturnType of your useAuth hook or the value of your AuthContext
|
// The ReturnType of your useAuth hook or the value of your AuthContext
|
||||||
@ -9,10 +10,11 @@ interface RouterContext {
|
|||||||
export const Route = createRootRouteWithContext<RouterContext>()({
|
export const Route = createRootRouteWithContext<RouterContext>()({
|
||||||
component: () => {
|
component: () => {
|
||||||
return (
|
return (
|
||||||
<>
|
// https://github.com/TanStack/router/issues/857
|
||||||
|
<Suspense fallback={null}>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
<TanStackRouterDevtools position="bottom-right" />
|
<TanStackRouterDevtools position="bottom-right" />
|
||||||
</>
|
</Suspense>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
import {
|
import { createFileRoute, redirect, useNavigate } from '@tanstack/react-router';
|
||||||
createFileRoute,
|
|
||||||
getRouteApi,
|
|
||||||
useNavigate,
|
|
||||||
} from '@tanstack/react-router';
|
|
||||||
import { useRequest } from '@/hooks/useRequest';
|
import { useRequest } from '@/hooks/useRequest';
|
||||||
import { setJWT } from '@/api/auth';
|
import { setJWT } from '@/api/auth';
|
||||||
import { useGlobalConfig } from '@/hooks/useConfig';
|
import { useGlobalConfig } from '@/hooks/useConfig';
|
||||||
@ -17,16 +13,21 @@ export const Route = createFileRoute('/login')({
|
|||||||
// redirect: z.string().catch('/'),
|
// redirect: z.string().catch('/'),
|
||||||
redirect: z.string().optional(),
|
redirect: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
|
beforeLoad: ({ context }) => {
|
||||||
|
if (context.userInfo) {
|
||||||
|
redirect({
|
||||||
|
to: '/website',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
component: LoginComponent,
|
component: LoginComponent,
|
||||||
});
|
});
|
||||||
|
|
||||||
const routeApi = getRouteApi('/login');
|
|
||||||
|
|
||||||
function LoginComponent() {
|
function LoginComponent() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const loginMutation = trpc.user.login.useMutation();
|
const loginMutation = trpc.user.login.useMutation();
|
||||||
const search = routeApi.useSearch();
|
const search = Route.useSearch();
|
||||||
|
|
||||||
const [{ loading }, handleLogin] = useRequest(async (values: any) => {
|
const [{ loading }, handleLogin] = useRequest(async (values: any) => {
|
||||||
const res = await loginMutation.mutateAsync({
|
const res = await loginMutation.mutateAsync({
|
||||||
@ -37,16 +38,17 @@ function LoginComponent() {
|
|||||||
setJWT(res.token);
|
setJWT(res.token);
|
||||||
setUserInfo(res.info);
|
setUserInfo(res.info);
|
||||||
navigate({
|
navigate({
|
||||||
to: search.redirect ?? '/dashboard',
|
to: search.redirect ?? '/',
|
||||||
|
replace: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const { allowRegister } = useGlobalConfig();
|
const { allowRegister } = useGlobalConfig();
|
||||||
|
|
||||||
return (
|
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="w-80 -translate-y-1/4">
|
||||||
<div className="text-center">
|
<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>
|
</div>
|
||||||
<Typography.Title className="text-center" level={2}>
|
<Typography.Title className="text-center" level={2}>
|
||||||
Tianji
|
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 { routeAuthBeforeLoad } from '@/utils/route';
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/monitor/$monitorId')({
|
export const Route = createFileRoute('/monitor/$monitorId/')({
|
||||||
beforeLoad: routeAuthBeforeLoad,
|
beforeLoad: routeAuthBeforeLoad,
|
||||||
component: MonitorDetailComponent,
|
component: MonitorDetailComponent,
|
||||||
});
|
});
|
@ -12,6 +12,7 @@ import {
|
|||||||
} from '@/components/monitor/MonitorInfoEditor';
|
} from '@/components/monitor/MonitorInfoEditor';
|
||||||
import { routeAuthBeforeLoad } from '@/utils/route';
|
import { routeAuthBeforeLoad } from '@/utils/route';
|
||||||
import { useMonitorUpsert } from '@/api/model/monitor';
|
import { useMonitorUpsert } from '@/api/model/monitor';
|
||||||
|
import { CommonHeader } from '@/components/CommonHeader';
|
||||||
|
|
||||||
export const Route = createFileRoute('/monitor/add')({
|
export const Route = createFileRoute('/monitor/add')({
|
||||||
beforeLoad: routeAuthBeforeLoad,
|
beforeLoad: routeAuthBeforeLoad,
|
||||||
@ -23,7 +24,6 @@ function MonitorAddComponent() {
|
|||||||
const workspaceId = useCurrentWorkspaceId();
|
const workspaceId = useCurrentWorkspaceId();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const mutation = useMonitorUpsert();
|
const mutation = useMonitorUpsert();
|
||||||
const utils = trpc.useUtils();
|
|
||||||
|
|
||||||
const handleSubmit = useEvent(async (values: MonitorInfoEditorValues) => {
|
const handleSubmit = useEvent(async (values: MonitorInfoEditorValues) => {
|
||||||
const res = await mutation.mutateAsync({
|
const res = await mutation.mutateAsync({
|
||||||
@ -31,8 +31,6 @@ function MonitorAddComponent() {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
utils.monitor.all.refetch();
|
|
||||||
|
|
||||||
navigate({
|
navigate({
|
||||||
to: '/monitor/$monitorId',
|
to: '/monitor/$monitorId',
|
||||||
params: {
|
params: {
|
||||||
@ -42,9 +40,7 @@ function MonitorAddComponent() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommonWrapper
|
<CommonWrapper header={<CommonHeader title={t('Add Monitor')} />}>
|
||||||
header={<h1 className="text-xl font-bold">{t('Add Monitor')}</h1>}
|
|
||||||
>
|
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<Card>
|
<Card>
|
||||||
<CardContent className="pt-4">
|
<CardContent className="pt-4">
|
||||||
|
@ -5,17 +5,21 @@ import { ErrorTip } from '@/components/ErrorTip';
|
|||||||
import { Loading } from '@/components/Loading';
|
import { Loading } from '@/components/Loading';
|
||||||
import { NotFoundTip } from '@/components/NotFoundTip';
|
import { NotFoundTip } from '@/components/NotFoundTip';
|
||||||
import { MonitorStatusPage } from '@/components/monitor/StatusPage';
|
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 { 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')({
|
export const Route = createFileRoute('/page/$slug')({
|
||||||
beforeLoad: routeAuthBeforeLoad,
|
beforeLoad: routeAuthBeforeLoad,
|
||||||
component: PageDetailComponent,
|
component: PageComponent,
|
||||||
});
|
});
|
||||||
|
|
||||||
function PageDetailComponent() {
|
function PageComponent() {
|
||||||
const { slug } = Route.useParams<{ slug: string }>();
|
const { slug } = Route.useParams<{ slug: string }>();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const navigate = useNavigate();
|
||||||
const { data: pageInfo, isLoading } = trpc.monitor.getPageInfo.useQuery({
|
const { data: pageInfo, isLoading } = trpc.monitor.getPageInfo.useQuery({
|
||||||
slug,
|
slug,
|
||||||
});
|
});
|
||||||
@ -33,10 +37,21 @@ function PageDetailComponent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommonWrapper header={<CommonHeader title={pageInfo.title} />}>
|
<CommonWrapper
|
||||||
{/* <ScrollArea className="h-full overflow-hidden"> */}
|
header={
|
||||||
<MonitorStatusPage slug={slug} />
|
<CommonHeader
|
||||||
{/* </ScrollArea> */}
|
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>
|
</CommonWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { Button, Form, Input, Typography } from 'antd';
|
import { Button, Form, Input, Typography } from 'antd';
|
||||||
import { useNavigate } from 'react-router';
|
|
||||||
import { useRequest } from '../hooks/useRequest';
|
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 { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
||||||
|
|
||||||
export const Route = createFileRoute('/register')({
|
export const Route = createFileRoute('/register')({
|
||||||
component: RegisterComponent,
|
component: RegisterComponent,
|
||||||
@ -25,14 +24,17 @@ function RegisterComponent() {
|
|||||||
setJWT(res.token);
|
setJWT(res.token);
|
||||||
setUserInfo(res.info);
|
setUserInfo(res.info);
|
||||||
|
|
||||||
navigate('/dashboard');
|
navigate({
|
||||||
|
to: '/',
|
||||||
|
replace: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
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="w-80 -translate-y-1/4">
|
||||||
<div className="text-center">
|
<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>
|
</div>
|
||||||
<Typography.Title className="text-center" level={2}>
|
<Typography.Title className="text-center" level={2}>
|
||||||
{t('Register Account')}
|
{t('Register Account')}
|
||||||
|
@ -3,12 +3,14 @@ import { createFileRoute } from '@tanstack/react-router';
|
|||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
import { CommonWrapper } from '@/components/CommonWrapper';
|
import { CommonWrapper } from '@/components/CommonWrapper';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
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 { useLogout } from '@/api/model/user';
|
||||||
import { trpc, defaultSuccessHandler, defaultErrorHandler } from '@/api/trpc';
|
import { trpc, defaultSuccessHandler, defaultErrorHandler } from '@/api/trpc';
|
||||||
import { useUserStore } from '@/store/user';
|
import { useUserStore } from '@/store/user';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { CommonHeader } from '@/components/CommonHeader';
|
import { CommonHeader } from '@/components/CommonHeader';
|
||||||
|
import { Separator } from '@/components/ui/separator';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
export const Route = createFileRoute('/settings/profile')({
|
export const Route = createFileRoute('/settings/profile')({
|
||||||
beforeLoad: routeAuthBeforeLoad,
|
beforeLoad: routeAuthBeforeLoad,
|
||||||
@ -45,13 +47,22 @@ function PageComponent() {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t('Password')}>
|
<Form.Item label={t('Password')}>
|
||||||
<Button
|
<Button
|
||||||
danger={true}
|
variant="destructive"
|
||||||
onClick={() => setOpenChangePassword(true)}
|
onClick={() => setOpenChangePassword(true)}
|
||||||
>
|
>
|
||||||
{t('Change Password')}
|
{t('Change Password')}
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
|
<Separator className="mb-4" />
|
||||||
|
|
||||||
|
<Popconfirm
|
||||||
|
title={t('Confirm to logout')}
|
||||||
|
onConfirm={() => logout()}
|
||||||
|
>
|
||||||
|
<Button variant="destructive">{t('Logout')}</Button>
|
||||||
|
</Popconfirm>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Modal
|
<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 { routeAuthBeforeLoad } from '@/utils/route';
|
||||||
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
import { Link, createFileRoute, useNavigate } from '@tanstack/react-router';
|
||||||
import { z } from 'zod';
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
|
||||||
import { useForm } from 'react-hook-form';
|
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
import { Button } from '@/components/ui/button';
|
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 { useCurrentWorkspaceId } from '@/store/user';
|
||||||
import { trpc } from '@/api/trpc';
|
import { trpc } from '@/api/trpc';
|
||||||
import { hostnameRegex } from '@tianji/shared';
|
|
||||||
import { Card, CardContent, CardFooter } from '@/components/ui/card';
|
|
||||||
import { CommonWrapper } from '@/components/CommonWrapper';
|
import { CommonWrapper } from '@/components/CommonWrapper';
|
||||||
import { WebsiteOverview } from '@/components/website/WebsiteOverview';
|
import { WebsiteOverview } from '@/components/website/WebsiteOverview';
|
||||||
import { Empty } from 'antd';
|
import { Empty } from 'antd';
|
||||||
import { LuPlus } from 'react-icons/lu';
|
import { LuArrowRight, LuPlus } from 'react-icons/lu';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
|
|
||||||
export const Route = createFileRoute('/website/overview')({
|
export const Route = createFileRoute('/website/overview')({
|
||||||
@ -46,6 +30,7 @@ function WebsiteOverviewComponent() {
|
|||||||
<ScrollArea className="h-full overflow-hidden p-4">
|
<ScrollArea className="h-full overflow-hidden p-4">
|
||||||
{websites.length === 0 && isLoading === false && (
|
{websites.length === 0 && isLoading === false && (
|
||||||
<Empty
|
<Empty
|
||||||
|
className="pt-8"
|
||||||
description={
|
description={
|
||||||
<div className="py-2">
|
<div className="py-2">
|
||||||
<div className="mb-1">
|
<div className="mb-1">
|
||||||
@ -68,7 +53,19 @@ function WebsiteOverviewComponent() {
|
|||||||
|
|
||||||
<div className="space-y-10 p-4">
|
<div className="space-y-10 p-4">
|
||||||
{websites.map((website) => (
|
{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>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
Loading…
Reference in New Issue
Block a user