feat: add monitor badge #6
This commit is contained in:
parent
19e7ed516b
commit
3e9760d895
@ -42,6 +42,7 @@
|
||||
"colord": "^2.9.3",
|
||||
"compose-middleware": "^5.0.1",
|
||||
"compression": "^1.7.4",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"cors": "^2.8.5",
|
||||
"croner": "^7.0.1",
|
||||
"dayjs": "^1.11.9",
|
||||
|
@ -61,6 +61,9 @@ dependencies:
|
||||
compression:
|
||||
specifier: ^1.7.4
|
||||
version: 1.7.4
|
||||
copy-to-clipboard:
|
||||
specifier: ^3.3.3
|
||||
version: 3.3.3
|
||||
cors:
|
||||
specifier: ^2.8.5
|
||||
version: 2.8.5
|
||||
|
101
src/client/components/monitor/MonitorBadgeView.tsx
Normal file
101
src/client/components/monitor/MonitorBadgeView.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
import { Checkbox, Divider, Input, message } from 'antd';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useEvent } from '../../hooks/useEvent';
|
||||
import copy from 'copy-to-clipboard';
|
||||
|
||||
export const MonitorBadgeView: React.FC<{
|
||||
workspaceId: string;
|
||||
monitorId: string;
|
||||
}> = React.memo((props) => {
|
||||
const { workspaceId, monitorId } = props;
|
||||
|
||||
const [showDetail, setShowDetail] = useState(false);
|
||||
|
||||
const url = useMemo(() => {
|
||||
let url = `${window.location.origin}/monitor/${workspaceId}/${monitorId}/badge.svg`;
|
||||
|
||||
if (showDetail) {
|
||||
url += `?showDetail=true`;
|
||||
}
|
||||
|
||||
return url;
|
||||
}, [showDetail]);
|
||||
|
||||
const handleCopy = useEvent((text: string) => {
|
||||
copy(text);
|
||||
message.success('Copy success!');
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<img src={url} />
|
||||
</div>
|
||||
<p>This will show your recent result of your monitor</p>
|
||||
<div>
|
||||
<Checkbox
|
||||
checked={showDetail}
|
||||
onChange={(e) => setShowDetail(e.target.checked)}
|
||||
>
|
||||
Show Detail Number
|
||||
</Checkbox>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
<p>Share with...</p>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Input
|
||||
addonBefore="HTML Embed"
|
||||
value={`<img src="${url}" />`}
|
||||
addonAfter={
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
onClick={() => handleCopy(`<img src="${url}" />`)}
|
||||
>
|
||||
Copy
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
<Input
|
||||
addonBefore="Markdown"
|
||||
value={`![](${url})`}
|
||||
addonAfter={
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
onClick={() => handleCopy(`![](${url})`)}
|
||||
>
|
||||
Copy
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
<Input
|
||||
addonBefore="BBCode"
|
||||
value={`[img]${url}[/img]`}
|
||||
addonAfter={
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
onClick={() => handleCopy(`[img]${url}[/img]`)}
|
||||
>
|
||||
Copy
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
<Input
|
||||
addonBefore="url"
|
||||
value={url}
|
||||
addonAfter={
|
||||
<div className="cursor-pointer" onClick={() => handleCopy(url)}>
|
||||
Copy
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
MonitorBadgeView.displayName = 'MonitorBadgeView';
|
@ -19,7 +19,8 @@ import { MonitorEventList } from './MonitorEventList';
|
||||
import { useEvent } from '../../hooks/useEvent';
|
||||
import { MonitorDataMetrics } from './MonitorDataMetrics';
|
||||
import { MonitorDataChart } from './MonitorDataChart';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import { DeleteOutlined, MoreOutlined } from '@ant-design/icons';
|
||||
import { MonitorBadgeView } from './MonitorBadgeView';
|
||||
|
||||
interface MonitorInfoProps {
|
||||
monitorId: string;
|
||||
@ -29,6 +30,7 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
|
||||
const { monitorId } = props;
|
||||
const [currectResponse, setCurrentResponse] = useState(0);
|
||||
const navigate = useNavigate();
|
||||
const [showBadge, setShowBadge] = useState(false);
|
||||
|
||||
const {
|
||||
data: monitorInfo,
|
||||
@ -209,6 +211,35 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
|
||||
>
|
||||
<Button danger={true}>Delete</Button>
|
||||
</Popconfirm>
|
||||
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
placement="bottomRight"
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: 'badge',
|
||||
label: 'Show Badge',
|
||||
onClick: () => setShowBadge(true),
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
<Button icon={<MoreOutlined />} />
|
||||
</Dropdown>
|
||||
|
||||
<Modal
|
||||
open={showBadge}
|
||||
onCancel={() => setShowBadge(false)}
|
||||
onOk={() => setShowBadge(false)}
|
||||
destroyOnClose={true}
|
||||
centered={true}
|
||||
>
|
||||
<MonitorBadgeView
|
||||
workspaceId={workspaceId}
|
||||
monitorId={monitorId}
|
||||
/>
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
|
@ -25,6 +25,7 @@ import cors from 'cors';
|
||||
import { serverStatusRouter } from './router/serverStatus';
|
||||
import { initCronjob } from './cronjob';
|
||||
import { logger } from './utils/logger';
|
||||
import { monitorRouter } from './router/monitor';
|
||||
|
||||
const port = settings.port;
|
||||
|
||||
@ -57,6 +58,7 @@ app.use(
|
||||
|
||||
app.use('/api/website', websiteRouter);
|
||||
app.use('/api/workspace', workspaceRouter);
|
||||
app.use('/monitor', monitorRouter);
|
||||
app.use('/telemetry', telemetryRouter);
|
||||
app.use('/serverStatus', serverStatusRouter);
|
||||
|
||||
|
39
src/server/router/monitor.ts
Normal file
39
src/server/router/monitor.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { Router } from 'express';
|
||||
import { param, validate, query } from '../middleware/validate';
|
||||
import { numify } from '../utils/common';
|
||||
import { makeBadge } from 'badge-maker';
|
||||
import { getMonitorPublicInfos, getMonitorRecentData } from '../model/monitor';
|
||||
import { checkEnvTrusty } from '../utils/env';
|
||||
|
||||
export const monitorRouter = Router();
|
||||
|
||||
monitorRouter.get(
|
||||
'/:workspaceId/:monitorId/badge.svg',
|
||||
validate(
|
||||
param('workspaceId').isString(),
|
||||
param('monitorId').isString(),
|
||||
query('showDetail').optional().isString()
|
||||
),
|
||||
async (req, res) => {
|
||||
const { workspaceId, monitorId } = req.params;
|
||||
const showDetail = checkEnvTrusty(String(req.query.showDetail));
|
||||
|
||||
const [info] = await getMonitorPublicInfos([monitorId]);
|
||||
const [{ value }] = await getMonitorRecentData(workspaceId, monitorId, 1);
|
||||
|
||||
const svg =
|
||||
value >= 0
|
||||
? makeBadge({
|
||||
label: info.name,
|
||||
message: showDetail ? numify(value) : 'Health',
|
||||
color: 'green',
|
||||
})
|
||||
: makeBadge({
|
||||
label: info.name,
|
||||
message: 'Error',
|
||||
color: 'red',
|
||||
});
|
||||
|
||||
res.header('Content-Type', 'image/svg+xml').send(svg);
|
||||
}
|
||||
);
|
Loading…
Reference in New Issue
Block a user