From 86dee6457631d32953dd306573e3c8a38149601e Mon Sep 17 00:00:00 2001 From: Xiao Yijun Date: Wed, 24 May 2023 08:31:26 +0800 Subject: [PATCH] feat(console): display webhook execution stats (#3883) --- .../pages/WebhookDetails/index.module.scss | 16 +++++++--- .../src/pages/WebhookDetails/index.tsx | 32 ++++++++++++++++--- .../console/src/pages/WebhookDetails/types.ts | 4 +-- .../Webhooks/components/SuccessRate/index.tsx | 24 ++++++++++++++ .../src/pages/Webhooks/index.module.scss | 8 +++++ packages/console/src/pages/Webhooks/index.tsx | 27 ++++++++++++---- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- .../admin-console/webhook-details.ts | 2 +- 21 files changed, 109 insertions(+), 32 deletions(-) create mode 100644 packages/console/src/pages/Webhooks/components/SuccessRate/index.tsx diff --git a/packages/console/src/pages/WebhookDetails/index.module.scss b/packages/console/src/pages/WebhookDetails/index.module.scss index 4631b8be3..429f1ad80 100644 --- a/packages/console/src/pages/WebhookDetails/index.module.scss +++ b/packages/console/src/pages/WebhookDetails/index.module.scss @@ -26,10 +26,6 @@ > div { display: flex; align-items: center; - - > *:not(:last-child) { - margin-right: _.unit(2); - } } .title { @@ -40,11 +36,23 @@ .text { font: var(--font-label-2); color: var(--color-text-secondary); + margin-right: _.unit(2); } .verticalBar { @include _.vertical-bar; height: 12px; + margin: 0 _.unit(2); + } + + .state { + display: flex; + align-items: center; + font: var(--font-body-2); + + .successRate { + margin-right: _.unit(1); + } } } } diff --git a/packages/console/src/pages/WebhookDetails/index.tsx b/packages/console/src/pages/WebhookDetails/index.tsx index 5cbe64a7b..b88179785 100644 --- a/packages/console/src/pages/WebhookDetails/index.tsx +++ b/packages/console/src/pages/WebhookDetails/index.tsx @@ -1,5 +1,5 @@ import { withAppInsights } from '@logto/app-insights/react'; -import { type Hook } from '@logto/schemas'; +import { type HookResponse, type Hook } from '@logto/schemas'; import classNames from 'classnames'; import { useEffect, useState } from 'react'; import { toast } from 'react-hot-toast'; @@ -26,6 +26,9 @@ import Tag from '@/components/Tag'; import { WebhookDetailsTabs } from '@/consts'; import useApi, { type RequestError } from '@/hooks/use-api'; import useTheme from '@/hooks/use-theme'; +import { buildUrl } from '@/utils/url'; + +import SuccessRate from '../Webhooks/components/SuccessRate'; import * as styles from './index.module.scss'; import { type WebhookDetailsOutletContext } from './types'; @@ -36,7 +39,9 @@ function WebhookDetails() { const isPageHasTable = pathname.endsWith(WebhookDetailsTabs.RecentRequests); const navigate = useNavigate(); const { id } = useParams(); - const { data, error, mutate } = useSWR(id && `api/hooks/${id}`); + const { data, error, mutate } = useSWR( + id && buildUrl(`api/hooks/${id}`, { includeExecutionStats: String(true) }) + ); const isLoading = !data && !error; const api = useApi(); @@ -52,7 +57,7 @@ function WebhookDetails() { useEffect(() => { setIsDeleteFormOpen(false); setIsDisableFormOpen(false); - }, [pathname]); + }, [data?.enabled, pathname]); const onDelete = async () => { if (!data || isDeleting) { @@ -109,7 +114,19 @@ function WebhookDetails() {
{data.name}
{isEnabled ? ( -
Success Rate (WIP)
+
+ + +
+ +
) : ( @@ -191,7 +208,12 @@ function WebhookDetails() { hook: data, isDeleting, onHookUpdated: (hook) => { - void mutate(hook); + if (hook) { + const { executionStats } = data; + void mutate({ ...hook, executionStats }); + return; + } + void mutate(); }, } satisfies WebhookDetailsOutletContext } diff --git a/packages/console/src/pages/WebhookDetails/types.ts b/packages/console/src/pages/WebhookDetails/types.ts index 01c5156b8..df8d3152a 100644 --- a/packages/console/src/pages/WebhookDetails/types.ts +++ b/packages/console/src/pages/WebhookDetails/types.ts @@ -1,9 +1,9 @@ -import { type Hook } from '@logto/schemas'; +import { type HookResponse, type Hook } from '@logto/schemas'; import { type BasicWebhookFormType } from '../Webhooks/types'; export type WebhookDetailsOutletContext = { - hook: Hook; + hook: HookResponse; isDeleting: boolean; onHookUpdated: (hook?: Hook) => void; }; diff --git a/packages/console/src/pages/Webhooks/components/SuccessRate/index.tsx b/packages/console/src/pages/Webhooks/components/SuccessRate/index.tsx new file mode 100644 index 000000000..a21710b61 --- /dev/null +++ b/packages/console/src/pages/Webhooks/components/SuccessRate/index.tsx @@ -0,0 +1,24 @@ +import Tag from '@/components/Tag'; + +type Props = { + successCount: number; + totalCount: number; + className?: string; +}; + +function SuccessRate({ successCount, totalCount, className }: Props) { + if (totalCount === 0) { + return
-
; + } + + const percent = (successCount / totalCount) * 100; + const statusStyle = percent < 90 ? 'error' : percent < 99 ? 'alert' : 'success'; + + return ( + + {percent.toFixed(2)}% + + ); +} + +export default SuccessRate; diff --git a/packages/console/src/pages/Webhooks/index.module.scss b/packages/console/src/pages/Webhooks/index.module.scss index 1e038bbbe..65da58292 100644 --- a/packages/console/src/pages/Webhooks/index.module.scss +++ b/packages/console/src/pages/Webhooks/index.module.scss @@ -1,5 +1,13 @@ +@use '@/scss/underscore' as _; + .icon { width: 40px; height: 40px; flex-shrink: 0; } + +.requests { + font: var(--font-body-2); + text-align: right; + margin-right: _.unit(4); +} diff --git a/packages/console/src/pages/Webhooks/index.tsx b/packages/console/src/pages/Webhooks/index.tsx index 536a0347d..fe70f6300 100644 --- a/packages/console/src/pages/Webhooks/index.tsx +++ b/packages/console/src/pages/Webhooks/index.tsx @@ -1,5 +1,5 @@ import { withAppInsights } from '@logto/app-insights/react'; -import { type HookEvent, type Hook, Theme } from '@logto/schemas'; +import { type HookEvent, type Hook, Theme, type HookResponse } from '@logto/schemas'; import { conditional } from '@silverhand/essentials'; import { toast } from 'react-hot-toast'; import { useTranslation } from 'react-i18next'; @@ -16,11 +16,14 @@ import DynamicT from '@/components/DynamicT'; import ItemPreview from '@/components/ItemPreview'; import ListPage from '@/components/ListPage'; import TablePlaceholder from '@/components/Table/TablePlaceholder'; +import Tag from '@/components/Tag'; import { hookEventLabel } from '@/consts/webhooks'; import { type RequestError } from '@/hooks/use-api'; import useTheme from '@/hooks/use-theme'; +import { buildUrl } from '@/utils/url'; import CreateFormModal from './components/CreateFormModal'; +import SuccessRate from './components/SuccessRate'; import * as styles from './index.module.scss'; const webhooksPathname = '/webhooks'; @@ -32,7 +35,9 @@ function Webhooks() { const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const { pathname } = useLocation(); const isCreateNew = pathname === createWebhookPathname; - const { data, error, mutate } = useSWR('api/hooks'); + const { data, error, mutate } = useSWR( + buildUrl('api/hooks', { includeExecutionStats: String(true) }) + ); const isLoading = !data && !error; const navigate = useNavigate(); const theme = useTheme(); @@ -87,16 +92,26 @@ function Webhooks() { title: , dataIndex: 'successRate', colSpan: 3, - render: () => { - return
WIP
; + render: ({ enabled, executionStats: { successCount, requestCount } }) => { + return enabled ? ( + + ) : ( + + + + ); }, }, { title: , dataIndex: 'Requests', colSpan: 2, - render: () => { - return
WIP
; + render: ({ enabled, executionStats: { requestCount } }) => { + return ( +
+ {enabled ? requestCount.toLocaleString() : '-'} +
+ ); }, }, ], diff --git a/packages/phrases/src/locales/de/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/de/translation/admin-console/webhook-details.ts index f309cfdfd..f08015ac1 100644 --- a/packages/phrases/src/locales/de/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/de/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Webhook-Details', back_to_webhooks: 'Zurück zu Webhooks', not_in_use: 'Nicht in Nutzung', - success_rate: '{{value, number}} Erfolgsrate', + success_rate: 'Erfolgsrate', requests: '{{value, number}} Requests in 24 Stunden', disable_webhook: 'Webhook deaktivieren', disable_reminder: diff --git a/packages/phrases/src/locales/en/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/en/translation/admin-console/webhook-details.ts index 02c1aec5f..64ea9ee4a 100644 --- a/packages/phrases/src/locales/en/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/en/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Webhook details', back_to_webhooks: 'Back to Webhooks', not_in_use: 'Not in use', - success_rate: '{{value, number}} success rate', + success_rate: 'success rate', requests: '{{value, number}} requests in 24h', disable_webhook: 'Disable webhook', disable_reminder: diff --git a/packages/phrases/src/locales/es/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/es/translation/admin-console/webhook-details.ts index d571a45d4..d131a937d 100644 --- a/packages/phrases/src/locales/es/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/es/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Detalles de Webhook', back_to_webhooks: 'Volver a Webhooks', not_in_use: 'No se está usando', - success_rate: 'Tasa de éxito: {{value, number}}', + success_rate: 'Tasa de éxito', requests: 'Solicitudes en 24h: {{value, number}}', disable_webhook: 'Desactivar webhook', disable_reminder: diff --git a/packages/phrases/src/locales/fr/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/fr/translation/admin-console/webhook-details.ts index 791d66d40..322cbc862 100644 --- a/packages/phrases/src/locales/fr/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/fr/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Détails du webhook', back_to_webhooks: 'Retour aux webhooks', not_in_use: "Pas en cours d'utilisation", - success_rate: 'Taux de réussite de {{value, number}}', + success_rate: 'Taux de réussite', requests: '{{value, number}} requêtes en 24h', disable_webhook: 'Désactiver le webhook', disable_reminder: diff --git a/packages/phrases/src/locales/it/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/it/translation/admin-console/webhook-details.ts index ff87a2617..d63bc5744 100644 --- a/packages/phrases/src/locales/it/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/it/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Dettagli webhook', back_to_webhooks: 'Torna ai Webhook', not_in_use: 'Non in uso', - success_rate: 'Tasso di successo {{value,number}}', + success_rate: 'Tasso di successo', requests: '{{value, number}} richieste in 24h', disable_webhook: 'Disabilita webhook', disable_reminder: diff --git a/packages/phrases/src/locales/ja/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/ja/translation/admin-console/webhook-details.ts index 3afbd4752..a0f93ab43 100644 --- a/packages/phrases/src/locales/ja/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/ja/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Webhookの詳細', back_to_webhooks: 'Webhooksに戻る', not_in_use: '使用されていない', - success_rate: '{{value, number}}成功率', + success_rate: '成功率', requests: '24時間に{{value, number}}件のリクエスト', disable_webhook: 'Webhookを無効にする', disable_reminder: diff --git a/packages/phrases/src/locales/ko/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/ko/translation/admin-console/webhook-details.ts index 45015f3c5..07aed23fa 100644 --- a/packages/phrases/src/locales/ko/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/ko/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Webhook 담당자', back_to_webhooks: 'Webhooks로 돌아가기', not_in_use: '사용 중이 아님', - success_rate: '{{value, number}} 성공율', + success_rate: '성공율', requests: '24시간 동안 {{value, number}}개의 요청', disable_webhook: 'Webhook 비활성화', disable_reminder: diff --git a/packages/phrases/src/locales/pl-pl/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/pl-pl/translation/admin-console/webhook-details.ts index dec7e1f40..26c738cc5 100644 --- a/packages/phrases/src/locales/pl-pl/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/pl-pl/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Szczegóły webhooka', back_to_webhooks: 'Wróć do Webhooks', not_in_use: 'Nieaktywne', - success_rate: 'Stosunek sukcesów: {{value, number}}', + success_rate: 'Stosunek sukcesów', requests: '{{value, number}} żądań w ciągu 24h', disable_webhook: 'Wyłącz webhook', disable_reminder: diff --git a/packages/phrases/src/locales/pt-br/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/pt-br/translation/admin-console/webhook-details.ts index e1f7fffc3..35d25852f 100644 --- a/packages/phrases/src/locales/pt-br/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/pt-br/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Detalhes do webhook', back_to_webhooks: 'Voltar para Webhooks', not_in_use: 'Não em uso', - success_rate: 'Taxa de sucesso de {{value, number}}', + success_rate: 'Taxa de sucesso', requests: '{{value, number}} requisições em 24h', disable_webhook: 'Desativar webhook', disable_reminder: diff --git a/packages/phrases/src/locales/pt-pt/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/pt-pt/translation/admin-console/webhook-details.ts index 22ba00d4f..5ceb6d08b 100644 --- a/packages/phrases/src/locales/pt-pt/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/pt-pt/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Detalhes do webhook', back_to_webhooks: 'Voltar para Webhooks', not_in_use: 'Não está em uso', - success_rate: 'Taxa de sucesso de {{value, number}}', + success_rate: 'Taxa de sucesso', requests: '{{value, number}} solicitações em 24h', disable_webhook: 'Desativar o webhook', disable_reminder: diff --git a/packages/phrases/src/locales/ru/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/ru/translation/admin-console/webhook-details.ts index 71b48af58..142a5dc83 100644 --- a/packages/phrases/src/locales/ru/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/ru/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Данные вебхука', back_to_webhooks: 'Вернуться к вебхукам', not_in_use: 'Не используется', - success_rate: 'Коэффициент успешности {{value, number}}', + success_rate: 'Коэффициент успешности', requests: '{{value, number}} запросов за 24 часа', disable_webhook: 'Отключить вебхук', disable_reminder: diff --git a/packages/phrases/src/locales/tr-tr/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/tr-tr/translation/admin-console/webhook-details.ts index b820f3409..a8086a586 100644 --- a/packages/phrases/src/locales/tr-tr/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/tr-tr/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Webhook ayrıntıları', back_to_webhooks: 'Webhooklara geri dön', not_in_use: 'Kullanılmıyor', - success_rate: '{{value, number}} başarı oranı', + success_rate: 'başarı oranı', requests: '24 saatte {{value, number}} istek', disable_webhook: 'Webhooku devre dışı bırak', disable_reminder: diff --git a/packages/phrases/src/locales/zh-cn/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/zh-cn/translation/admin-console/webhook-details.ts index 245e52e19..ec1d4713a 100644 --- a/packages/phrases/src/locales/zh-cn/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/zh-cn/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Webhook 详情', back_to_webhooks: '返回 Webhooks', not_in_use: '未使用', - success_rate: '{{value, number}} 成功率', + success_rate: '成功率', requests: '24 小时内请求次数:{{value, number}}', disable_webhook: '禁用 Webhook', disable_reminder: '是否确定重新激活此 Webhook?重新激活后将不会向端点 URL 发送 HTTP 请求。', diff --git a/packages/phrases/src/locales/zh-hk/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/zh-hk/translation/admin-console/webhook-details.ts index db69c8ca7..14cff4833 100644 --- a/packages/phrases/src/locales/zh-hk/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/zh-hk/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Webhook 詳細資料', back_to_webhooks: '返回 Webhooks', not_in_use: '未啟用', - success_rate: '{{value, number}} 成功率', + success_rate: '成功率', requests: '24 小時內收到 {{value, number}} 個請求', disable_webhook: '停用 webhook', disable_reminder: '確定要重新啟用此 webhook?重新啟用後,不會對端點 URL 發送 HTTP 請求。', diff --git a/packages/phrases/src/locales/zh-tw/translation/admin-console/webhook-details.ts b/packages/phrases/src/locales/zh-tw/translation/admin-console/webhook-details.ts index 30442ac25..2a03cb65d 100644 --- a/packages/phrases/src/locales/zh-tw/translation/admin-console/webhook-details.ts +++ b/packages/phrases/src/locales/zh-tw/translation/admin-console/webhook-details.ts @@ -2,7 +2,7 @@ const webhook_details = { page_title: 'Webhook 詳情', back_to_webhooks: '返回 Webhooks', not_in_use: '未使用', - success_rate: '{{value, number}} 成功率', + success_rate: '成功率', requests: '24 小時內 {{value, number}} 個請求', disable_webhook: '停用 Webhook', disable_reminder: '確定要重新啟用此 Webhook 嗎?繼續操作後,將不會向端點 URL 發送 HTTP 請求。',