feat: add clear offlline node button
This commit is contained in:
parent
c41994879a
commit
b6846b0419
@ -1,11 +1,13 @@
|
|||||||
import React, { useEffect, useMemo, useReducer, useRef, useState } from 'react';
|
import React, { useMemo, useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
|
Divider,
|
||||||
Empty,
|
Empty,
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
Modal,
|
Modal,
|
||||||
|
Popconfirm,
|
||||||
Steps,
|
Steps,
|
||||||
Switch,
|
Switch,
|
||||||
Table,
|
Table,
|
||||||
@ -28,15 +30,31 @@ import { Loading } from '../components/Loading';
|
|||||||
import { without } from 'lodash-es';
|
import { without } from 'lodash-es';
|
||||||
import { useIntervalUpdate } from '../hooks/useIntervalUpdate';
|
import { useIntervalUpdate } from '../hooks/useIntervalUpdate';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import { isServerOnline } from '../../shared';
|
||||||
|
import { defaultErrorHandler, trpc } from '../api/trpc';
|
||||||
|
import { useEvent } from '../hooks/useEvent';
|
||||||
|
import { useRequest } from '../hooks/useRequest';
|
||||||
|
|
||||||
export const Servers: React.FC = React.memo(() => {
|
export const Servers: React.FC = React.memo(() => {
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [hideOfflineServer, setHideOfflineServer] = useState(false);
|
const [hideOfflineServer, setHideOfflineServer] = useState(false);
|
||||||
|
const workspaceId = useCurrentWorkspaceId();
|
||||||
|
|
||||||
const handleOk = () => {
|
const handleOk = () => {
|
||||||
setIsModalOpen(false);
|
setIsModalOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const clearOfflineNodeMutation =
|
||||||
|
trpc.serverStatus.clearOfflineServerStatus.useMutation({
|
||||||
|
onError: defaultErrorHandler,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [{ loading }, handleClearOfflineNode] = useRequest(async (e) => {
|
||||||
|
await clearOfflineNodeMutation.mutateAsync({
|
||||||
|
workspaceId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="h-24 flex items-center">
|
<div className="h-24 flex items-center">
|
||||||
@ -50,6 +68,21 @@ export const Servers: React.FC = React.memo(() => {
|
|||||||
Hide Offline
|
Hide Offline
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Popconfirm
|
||||||
|
title="Clear Offline Node"
|
||||||
|
description="Are you sure to clear all offline node?"
|
||||||
|
disabled={loading}
|
||||||
|
onConfirm={handleClearOfflineNode}
|
||||||
|
>
|
||||||
|
<Button size="large" loading={loading}>
|
||||||
|
Clear Offline
|
||||||
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider type="vertical" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
@ -151,10 +184,10 @@ export const ServerList: React.FC<{
|
|||||||
dataIndex: 'hostname',
|
dataIndex: 'hostname',
|
||||||
title: 'Host Name',
|
title: 'Host Name',
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
dataIndex: ['payload', 'system'],
|
// dataIndex: ['payload', 'system'],
|
||||||
title: 'System',
|
// title: 'System',
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
dataIndex: ['payload', 'uptime'],
|
dataIndex: ['payload', 'uptime'],
|
||||||
title: 'Uptime',
|
title: 'Uptime',
|
||||||
@ -351,7 +384,3 @@ export const AddServerStep: React.FC = React.memo(() => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
AddServerStep.displayName = 'AddServerStep';
|
AddServerStep.displayName = 'AddServerStep';
|
||||||
|
|
||||||
function isServerOnline(info: ServerStatusInfo): boolean {
|
|
||||||
return new Date(info.updatedAt).valueOf() + info.timeout * 1000 > Date.now();
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
import dayjs from 'dayjs';
|
||||||
import { ServerStatusInfo } from '../../types';
|
import { ServerStatusInfo } from '../../types';
|
||||||
import { createSubscribeInitializer, subscribeEventBus } from '../ws/shared';
|
import { createSubscribeInitializer, subscribeEventBus } from '../ws/shared';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { isServerOnline } from '../../shared';
|
||||||
|
|
||||||
const serverMap: Record<
|
const serverMap: Record<
|
||||||
string, // workspaceId
|
string, // workspaceId
|
||||||
@ -47,3 +50,28 @@ export function recordServerStatus(info: ServerStatusInfo) {
|
|||||||
serverMap[workspaceId]
|
serverMap[workspaceId]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clearOfflineServerStatus(workspaceId: string) {
|
||||||
|
if (!serverMap[workspaceId]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const offlineNode: string[] = [];
|
||||||
|
Object.entries(serverMap[workspaceId]).forEach(([key, info]) => {
|
||||||
|
if (!isServerOnline(info)) {
|
||||||
|
offlineNode.push(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const node of offlineNode) {
|
||||||
|
delete serverMap[workspaceId][node];
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeEventBus.emit(
|
||||||
|
'onServerStatusUpdate',
|
||||||
|
workspaceId,
|
||||||
|
serverMap[workspaceId]
|
||||||
|
);
|
||||||
|
|
||||||
|
return serverMap[workspaceId];
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { monitorRouter } from './monitor';
|
|||||||
import { userRouter } from './user';
|
import { userRouter } from './user';
|
||||||
import { workspaceRouter } from './workspace';
|
import { workspaceRouter } from './workspace';
|
||||||
import { globalRouter } from './global';
|
import { globalRouter } from './global';
|
||||||
|
import { serverStatusRouter } from './serverStatus';
|
||||||
|
|
||||||
export const appRouter = router({
|
export const appRouter = router({
|
||||||
global: globalRouter,
|
global: globalRouter,
|
||||||
@ -13,6 +14,7 @@ export const appRouter = router({
|
|||||||
website: websiteRouter,
|
website: websiteRouter,
|
||||||
notification: notificationRouter,
|
notification: notificationRouter,
|
||||||
monitor: monitorRouter,
|
monitor: monitorRouter,
|
||||||
|
serverStatus: serverStatusRouter,
|
||||||
});
|
});
|
||||||
|
|
||||||
export type AppRouter = typeof appRouter;
|
export type AppRouter = typeof appRouter;
|
||||||
|
12
src/server/trpc/routers/serverStatus.ts
Normal file
12
src/server/trpc/routers/serverStatus.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { router, workspaceOwnerProcedure } from '../trpc';
|
||||||
|
import { clearOfflineServerStatus } from '../../model/serverStatus';
|
||||||
|
|
||||||
|
export const serverStatusRouter = router({
|
||||||
|
clearOfflineServerStatus: workspaceOwnerProcedure.mutation(
|
||||||
|
async ({ input }) => {
|
||||||
|
const workspaceId = input.workspaceId;
|
||||||
|
|
||||||
|
return clearOfflineServerStatus(workspaceId);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
});
|
@ -1 +1,2 @@
|
|||||||
export * from './date';
|
export * from './date';
|
||||||
|
export * from './server';
|
||||||
|
5
src/shared/server.ts
Normal file
5
src/shared/server.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { ServerStatusInfo } from '../types';
|
||||||
|
|
||||||
|
export function isServerOnline(info: ServerStatusInfo): boolean {
|
||||||
|
return new Date(info.updatedAt).valueOf() + info.timeout * 1000 > Date.now();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user