@agent-native/core 0.91.2 → 0.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +17 -0
- package/corpus/core/docs/content/faq.mdx +17 -0
- package/corpus/core/docs/content/notifications.mdx +12 -6
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +140 -46
- package/corpus/core/src/agent/tool-search.ts +71 -4
- package/corpus/core/src/cli/index.ts +20 -0
- package/corpus/core/src/cli/upgrade.ts +798 -0
- package/corpus/core/src/client/AssistantChat.tsx +1 -1
- package/corpus/core/src/client/HighlightedCodeBlock.tsx +20 -3
- package/corpus/core/src/client/agent-chat-adapter.ts +31 -6
- package/corpus/core/src/client/chat/message-components.tsx +85 -8
- package/corpus/core/src/client/chat/tool-call-display.tsx +355 -144
- package/corpus/core/src/client/code-agent-chat-adapter.ts +2 -9
- package/corpus/core/src/client/session-replay.ts +3 -97
- package/corpus/core/src/client/settings/SettingsPanel.tsx +533 -389
- package/corpus/core/src/client/settings/SettingsSection.tsx +154 -17
- package/corpus/core/src/client/sse-event-processor.ts +29 -2
- package/corpus/core/src/extensions/actions.ts +113 -5
- package/corpus/core/src/notifications/channels.ts +88 -25
- package/corpus/core/src/notifications/registry.ts +17 -3
- package/corpus/core/src/notifications/types.ts +4 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +7 -3
- package/corpus/core/src/server/request-context.ts +7 -0
- package/corpus/core/src/styles/agent-conversation.css +1 -1
- package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/core/src/templates/default/AGENTS.md +10 -3
- package/corpus/core/src/templates/default/package.json +2 -1
- package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/core/src/templates/headless/AGENTS.md +9 -3
- package/corpus/core/src/templates/headless/package.json +1 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/core/src/templates/workspace-root/AGENTS.md +10 -4
- package/corpus/core/src/templates/workspace-root/package.json +1 -0
- package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +5 -6
- package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/analytics/AGENTS.md +7 -5
- package/corpus/templates/analytics/actions/save-monitor.ts +14 -0
- package/corpus/templates/analytics/app/components/dashboard/DataTable.tsx +41 -6
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +122 -11
- package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +8 -2
- package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +151 -32
- package/corpus/templates/analytics/app/pages/monitoring/uptime/i18n.ts +17 -2
- package/corpus/templates/analytics/app/pages/monitoring/uptime/types.ts +4 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +54 -190
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-tables-keep-their-size-while-loading.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-monitoring-uptime-and-errors-tabs-now-clearly-show-which-view-is-active.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-uses-stock-rrweb-sizing-again-so-recorded.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-sidebar-dashboard-menus-now-open-above-the-dashboard-canvas.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-uptime-alerting-clarifies-in-app-inbox-vs-email-and-lets-you-paste-slack-or-webhook-urls-per-monitor.md +6 -0
- package/corpus/templates/analytics/docs/uptime-monitoring.md +13 -11
- package/corpus/templates/analytics/server/db/schema-monitoring.ts +4 -0
- package/corpus/templates/analytics/server/lib/uptime-monitors.ts +60 -12
- package/corpus/templates/analytics/server/plugins/db.ts +10 -0
- package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/clips/changelog/2026-07-08-desktop-meeting-notes-stay-active-from-tray-and-shortcut-controls.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-desktop-meeting-popovers-can-start-notes-and-join-the-meetin.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-notes-keep-their-recording-state-when-the-desktop.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-reminder-dropdowns-now-expand-fully-instead-of-being.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +123 -3
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +15 -1
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +23 -0
- package/corpus/templates/clips/desktop/src/styles.css +23 -1
- package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +1 -3
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +40 -6
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -2
- package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +3 -5
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +23 -19
- package/corpus/templates/clips/desktop/src-tauri/src/shortcuts.rs +3 -3
- package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +0 -1
- package/corpus/templates/clips/desktop/src-tauri/src/state.rs +5 -0
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +18 -6
- package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/content/actions/_batch-utils.ts +8 -0
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +7 -5
- package/corpus/templates/content/actions/_database-source-utils.ts +776 -319
- package/corpus/templates/content/actions/_database-utils.ts +6 -1
- package/corpus/templates/content/actions/_property-utils.ts +168 -0
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +19 -12
- package/corpus/templates/content/actions/bind-content-database-source-field.ts +19 -12
- package/corpus/templates/content/actions/delete-document.ts +9 -13
- package/corpus/templates/content/actions/refresh-content-database-source.ts +5 -5
- package/corpus/templates/content/app/components/editor/body-hydration.ts +35 -11
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +47 -5
- package/corpus/templates/content/app/hooks/use-documents.ts +8 -2
- package/corpus/templates/content/changelog/2026-07-08-builder-source-sync-now-completes-reliably-on-hosted-databases.md +6 -0
- package/corpus/templates/content/changelog/2026-07-08-fixed-builder-database-sync-so-large-sources-continue-past-t.md +6 -0
- package/corpus/templates/content/server/plugins/db.ts +19 -0
- package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/videos/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/voice/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/dist/agent/production-agent.d.ts +5 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +112 -42
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/tool-search.d.ts +2 -0
- package/dist/agent/tool-search.d.ts.map +1 -1
- package/dist/agent/tool-search.js +60 -4
- package/dist/agent/tool-search.js.map +1 -1
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/upgrade.d.ts +100 -0
- package/dist/cli/upgrade.d.ts.map +1 -0
- package/dist/cli/upgrade.js +678 -0
- package/dist/cli/upgrade.js.map +1 -0
- package/dist/client/AssistantChat.js +1 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/HighlightedCodeBlock.d.ts +2 -0
- package/dist/client/HighlightedCodeBlock.d.ts.map +1 -1
- package/dist/client/HighlightedCodeBlock.js +10 -1
- package/dist/client/HighlightedCodeBlock.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +32 -4
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +61 -8
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +12 -0
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +136 -42
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/code-agent-chat-adapter.js +2 -9
- package/dist/client/code-agent-chat-adapter.js.map +1 -1
- package/dist/client/session-replay.d.ts +0 -8
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +3 -80
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +52 -19
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsSection.d.ts +19 -4
- package/dist/client/settings/SettingsSection.d.ts.map +1 -1
- package/dist/client/settings/SettingsSection.js +33 -4
- package/dist/client/settings/SettingsSection.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +9 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +20 -2
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +85 -5
- package/dist/extensions/actions.js.map +1 -1
- package/dist/notifications/channels.d.ts +8 -3
- package/dist/notifications/channels.d.ts.map +1 -1
- package/dist/notifications/channels.js +61 -22
- package/dist/notifications/channels.js.map +1 -1
- package/dist/notifications/registry.d.ts.map +1 -1
- package/dist/notifications/registry.js +14 -3
- package/dist/notifications/registry.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/notifications/types.d.ts +4 -1
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/notifications/types.js.map +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-chat-plugin.d.ts +5 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +2 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/styles/agent-conversation.css +1 -1
- package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/dist/templates/default/AGENTS.md +10 -3
- package/dist/templates/default/package.json +2 -1
- package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/dist/templates/headless/AGENTS.md +9 -3
- package/dist/templates/headless/package.json +1 -0
- package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/dist/templates/workspace-root/AGENTS.md +10 -4
- package/dist/templates/workspace-root/package.json +1 -0
- package/docs/content/faq.mdx +17 -0
- package/docs/content/notifications.mdx +12 -6
- package/package.json +2 -2
- package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/src/templates/default/AGENTS.md +10 -3
- package/src/templates/default/package.json +2 -1
- package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/src/templates/headless/AGENTS.md +9 -3
- package/src/templates/headless/package.json +1 -0
- package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/src/templates/workspace-root/AGENTS.md +10 -4
- package/src/templates/workspace-root/package.json +1 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-clamps-ultra-wide-viewports-while-keeping-the.md +0 -6
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upgrade-agent-native
|
|
3
|
+
description: >-
|
|
4
|
+
Bring an older Agent Native app or workspace current. Use when updating
|
|
5
|
+
@agent-native/core, fixing a broken upgrade, or when tempted to patch or
|
|
6
|
+
override core/dispatch packages to make an old branch run.
|
|
7
|
+
scope: dev
|
|
8
|
+
metadata:
|
|
9
|
+
internal: true
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Upgrade Agent Native
|
|
13
|
+
|
|
14
|
+
## Rule
|
|
15
|
+
|
|
16
|
+
When an older Agent Native app/branch needs to run on current packages, use
|
|
17
|
+
`agent-native upgrade`. Never "fix" upgrade breakage with
|
|
18
|
+
`pnpm.overrides`, `patchedDependencies`, `resolutions`, local patches, or
|
|
19
|
+
edits under `node_modules/@agent-native/*` — especially not against
|
|
20
|
+
`@agent-native/core` or `@agent-native/dispatch`.
|
|
21
|
+
|
|
22
|
+
## Why
|
|
23
|
+
|
|
24
|
+
Agents often respond to a failed core bump by inventing framework patches and
|
|
25
|
+
dispatch behavior overrides. That hides the real app-level break, drifts from
|
|
26
|
+
upstream, and makes the next upgrade worse. The supported path is bump →
|
|
27
|
+
install → refresh scaffold skills → verify, then fix **app** code only.
|
|
28
|
+
|
|
29
|
+
## How
|
|
30
|
+
|
|
31
|
+
1. **Doctor first (optional but recommended)**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx @agent-native/core@latest upgrade check
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This reports framework overrides/patches and pending `@agent-native/*`
|
|
38
|
+
bumps. If overrides/patches are present, remove them before continuing.
|
|
39
|
+
|
|
40
|
+
2. **Run the upgrade**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx @agent-native/core@latest upgrade
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or from an already-installed CLI: `pnpm exec agent-native upgrade` /
|
|
47
|
+
`agent-native upgrade`.
|
|
48
|
+
|
|
49
|
+
What it does:
|
|
50
|
+
|
|
51
|
+
- Blocks (unless `--force`) when `@agent-native/*` overrides/patches exist
|
|
52
|
+
- Rewrites non-local `@agent-native/*` dependency pins to `latest`
|
|
53
|
+
- Runs the package manager install
|
|
54
|
+
- Runs `skills update scaffold --project`
|
|
55
|
+
- Runs `typecheck` when the project has that script
|
|
56
|
+
|
|
57
|
+
3. **If upgrade or typecheck fails**
|
|
58
|
+
|
|
59
|
+
- Read the concrete error
|
|
60
|
+
- Fix **app** source, actions, config, or env — not framework packages
|
|
61
|
+
- Re-run `agent-native upgrade` or `pnpm typecheck`
|
|
62
|
+
- Stop and ask the user if you cannot fix the app-level error
|
|
63
|
+
|
|
64
|
+
4. **Dry-run / partial runs**
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
agent-native upgrade --dry-run
|
|
68
|
+
agent-native upgrade --skip-verify
|
|
69
|
+
agent-native upgrade --skip-install # package.json bumps only
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Don't
|
|
73
|
+
|
|
74
|
+
- Don't add `pnpm.overrides`, `overrides`, `resolutions`, or
|
|
75
|
+
`patchedDependencies` for any `@agent-native/*` package
|
|
76
|
+
- Don't edit `node_modules/@agent-native/core` or
|
|
77
|
+
`node_modules/@agent-native/dispatch`
|
|
78
|
+
- Don't invent local "dispatch behavior" shims to paper over version skew
|
|
79
|
+
- Don't keep iterating with more framework patches after a failed install
|
|
80
|
+
- Don't skip `skills update scaffold --project` after a core bump (the
|
|
81
|
+
upgrade command does this for you)
|
|
82
|
+
|
|
83
|
+
## Related Skills
|
|
84
|
+
|
|
85
|
+
- **self-modifying-code** — Tier 4: framework packages are off limits
|
|
86
|
+
- **agent-native-docs** — version-matched docs after the bump
|
|
87
|
+
- **portability** — keep app code provider-agnostic across upgrades
|
|
@@ -140,11 +140,13 @@ details live in `.agents/skills/`.
|
|
|
140
140
|
`thresholdMode: "distinct_count"` counts unique values from `distinctBy`.
|
|
141
141
|
Alert notifications use the shared notification channel registry, so
|
|
142
142
|
`channels` can include `inbox`, `email`, `slack`, `webhook`, or any custom
|
|
143
|
-
registered channel.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
`
|
|
147
|
-
|
|
143
|
+
registered channel. Slack/webhook prefer delivery-only
|
|
144
|
+
`metadata.delivery.slackWebhookUrl` / `metadata.delivery.webhookUrl` (uptime
|
|
145
|
+
monitors store these on the monitor row), then fall back to
|
|
146
|
+
`NOTIFICATIONS_SLACK_WEBHOOK_URL` / `NOTIFICATIONS_WEBHOOK_URL`. Configure
|
|
147
|
+
optional `NOTIFICATIONS_SLACK_WEBHOOK_AUTH`; configure email with existing
|
|
148
|
+
`RESEND_API_KEY` or `SENDGRID_API_KEY` plus `EMAIL_FROM`, and pass per-rule
|
|
149
|
+
`emailRecipients` or the fallback `NOTIFICATIONS_EMAIL_RECIPIENTS`.
|
|
148
150
|
Netlify builds emit an alert cron trigger plus background worker from
|
|
149
151
|
`scripts/emit-netlify-dashboard-report-cron.ts` every five minutes; long-lived
|
|
150
152
|
runtimes use the in-process scheduler unless `ANALYTICS_ALERT_JOBS=0` is set.
|
|
@@ -123,6 +123,20 @@ export default defineAction({
|
|
|
123
123
|
.array(z.string().email())
|
|
124
124
|
.optional()
|
|
125
125
|
.describe("Email recipients used by the email channel."),
|
|
126
|
+
slackWebhookUrl: z
|
|
127
|
+
.string()
|
|
128
|
+
.nullable()
|
|
129
|
+
.optional()
|
|
130
|
+
.describe(
|
|
131
|
+
"Optional Slack incoming webhook URL for this monitor. Overrides NOTIFICATIONS_SLACK_WEBHOOK_URL when set.",
|
|
132
|
+
),
|
|
133
|
+
webhookUrl: z
|
|
134
|
+
.string()
|
|
135
|
+
.nullable()
|
|
136
|
+
.optional()
|
|
137
|
+
.describe(
|
|
138
|
+
"Optional generic webhook URL for this monitor. Overrides NOTIFICATIONS_WEBHOOK_URL when set.",
|
|
139
|
+
),
|
|
126
140
|
cooldownMinutes: z
|
|
127
141
|
.number()
|
|
128
142
|
.int()
|
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
import { cn } from "@/lib/utils";
|
|
28
28
|
|
|
29
29
|
const PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
|
|
30
|
+
const TABLE_MIN_HEIGHT_CLASS = "min-h-[386px]";
|
|
31
|
+
const TABLE_SKELETON_ROWS = 10;
|
|
30
32
|
|
|
31
33
|
interface DataTableProps {
|
|
32
34
|
title?: string;
|
|
@@ -109,11 +111,7 @@ export function DataTable({
|
|
|
109
111
|
const content = (
|
|
110
112
|
<>
|
|
111
113
|
{isLoading ? (
|
|
112
|
-
<
|
|
113
|
-
{Array.from({ length: 5 }).map((_, i) => (
|
|
114
|
-
<Skeleton key={i} className="h-8 w-full" />
|
|
115
|
-
))}
|
|
116
|
-
</div>
|
|
114
|
+
<DataTableLoadingSkeleton />
|
|
117
115
|
) : error ? (
|
|
118
116
|
<p className="text-sm text-red-400 py-4">{error}</p>
|
|
119
117
|
) : data.length === 0 ? (
|
|
@@ -121,7 +119,7 @@ export function DataTable({
|
|
|
121
119
|
{t("common.noData")}
|
|
122
120
|
</p>
|
|
123
121
|
) : (
|
|
124
|
-
<div className=
|
|
122
|
+
<div className={`overflow-x-auto ${TABLE_MIN_HEIGHT_CLASS}`}>
|
|
125
123
|
<Table>
|
|
126
124
|
<TableHeader>
|
|
127
125
|
<TableRow>
|
|
@@ -227,3 +225,40 @@ export function DataTable({
|
|
|
227
225
|
</Card>
|
|
228
226
|
);
|
|
229
227
|
}
|
|
228
|
+
|
|
229
|
+
function DataTableLoadingSkeleton() {
|
|
230
|
+
const columnWidths = ["w-24", "w-32", "w-20", "w-28"];
|
|
231
|
+
|
|
232
|
+
return (
|
|
233
|
+
<div className={`space-y-1 ${TABLE_MIN_HEIGHT_CLASS}`}>
|
|
234
|
+
<div className="overflow-x-auto">
|
|
235
|
+
<div className="min-w-[480px]">
|
|
236
|
+
<div className="grid h-8 grid-cols-4 items-center border-b border-border px-2">
|
|
237
|
+
{columnWidths.map((width, index) => (
|
|
238
|
+
<Skeleton key={index} className={`h-3 ${width}`} />
|
|
239
|
+
))}
|
|
240
|
+
</div>
|
|
241
|
+
{Array.from({ length: TABLE_SKELETON_ROWS }).map((_, row) => (
|
|
242
|
+
<div
|
|
243
|
+
key={row}
|
|
244
|
+
className="grid h-8 grid-cols-4 items-center border-b border-border/50 px-2"
|
|
245
|
+
>
|
|
246
|
+
{columnWidths.map((width, col) => (
|
|
247
|
+
<Skeleton
|
|
248
|
+
key={col}
|
|
249
|
+
className={`h-3 ${
|
|
250
|
+
col === 0 ? "w-36" : col === 2 ? "ml-auto w-16" : width
|
|
251
|
+
}`}
|
|
252
|
+
/>
|
|
253
|
+
))}
|
|
254
|
+
</div>
|
|
255
|
+
))}
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
<div className="flex h-8 items-center justify-between border-t border-border px-2 text-xs">
|
|
259
|
+
<Skeleton className="h-3 w-28" />
|
|
260
|
+
<Skeleton className="h-3 w-24" />
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
);
|
|
264
|
+
}
|
|
@@ -113,6 +113,8 @@ const CHART_LEGEND_PROPS = {
|
|
|
113
113
|
const PARTIAL_DAY_TIME_ZONE = "America/Los_Angeles";
|
|
114
114
|
const PARTIAL_DAY_DASH = "3 5";
|
|
115
115
|
const PARTIAL_DAY_KEY_PREFIX = "__sql_chart_partial_day";
|
|
116
|
+
const TABLE_PANEL_MIN_HEIGHT_CLASS = "min-h-[386px]";
|
|
117
|
+
const TABLE_PANEL_SKELETON_ROWS = 10;
|
|
116
118
|
|
|
117
119
|
function formatYValue(
|
|
118
120
|
value: number,
|
|
@@ -488,7 +490,7 @@ function SeriesLegend({
|
|
|
488
490
|
if (!shouldShowLegend(panel, keys.length)) return null;
|
|
489
491
|
|
|
490
492
|
return (
|
|
491
|
-
<div className="mt-2 max-h-16 overflow-y-auto overflow-x-hidden pr-1 text-[11px] leading-4 text-muted-foreground">
|
|
493
|
+
<div className="mt-2 min-h-16 max-h-16 overflow-y-auto overflow-x-hidden pr-1 text-[11px] leading-4 text-muted-foreground">
|
|
492
494
|
<div className="flex flex-wrap gap-x-3 gap-y-1">
|
|
493
495
|
{keys.map((key, i) => {
|
|
494
496
|
const hidden = hiddenKeys?.has(key) ?? false;
|
|
@@ -586,6 +588,113 @@ function ChartFrame({
|
|
|
586
588
|
);
|
|
587
589
|
}
|
|
588
590
|
|
|
591
|
+
function isTableLikeChartType(type: ChartType): boolean {
|
|
592
|
+
return type === "table" || type === "heatmap";
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function chartTypeReservesLegend(panel: SqlPanel): boolean {
|
|
596
|
+
if (panel.config?.legend === false) return false;
|
|
597
|
+
const chartUsesFrame =
|
|
598
|
+
panel.chartType === "line" ||
|
|
599
|
+
panel.chartType === "area" ||
|
|
600
|
+
panel.chartType === "bar" ||
|
|
601
|
+
panel.chartType === "pie";
|
|
602
|
+
if (!chartUsesFrame) return false;
|
|
603
|
+
return (
|
|
604
|
+
panel.chartType === "line" ||
|
|
605
|
+
panel.chartType === "area" ||
|
|
606
|
+
panel.chartType === "bar" ||
|
|
607
|
+
usesPrometheusPresentation(panel)
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function TableLoadingSkeleton() {
|
|
612
|
+
const columnWidths = ["w-24", "w-32", "w-20", "w-28"];
|
|
613
|
+
|
|
614
|
+
return (
|
|
615
|
+
<div
|
|
616
|
+
data-dashboard-report-loading="true"
|
|
617
|
+
className={`w-full flex-1 space-y-1 ${TABLE_PANEL_MIN_HEIGHT_CLASS}`}
|
|
618
|
+
>
|
|
619
|
+
<div className="relative overflow-x-auto">
|
|
620
|
+
<div className="min-w-[480px]">
|
|
621
|
+
<div className="grid h-8 grid-cols-4 items-center border-b border-border px-2">
|
|
622
|
+
{columnWidths.map((width, index) => (
|
|
623
|
+
<Skeleton key={index} className={`h-3 ${width}`} />
|
|
624
|
+
))}
|
|
625
|
+
</div>
|
|
626
|
+
{Array.from({ length: TABLE_PANEL_SKELETON_ROWS }).map((_, row) => (
|
|
627
|
+
<div
|
|
628
|
+
key={row}
|
|
629
|
+
className="grid h-8 grid-cols-4 items-center border-b border-border/50 px-2"
|
|
630
|
+
>
|
|
631
|
+
{columnWidths.map((width, col) => (
|
|
632
|
+
<Skeleton
|
|
633
|
+
key={col}
|
|
634
|
+
className={`h-3 ${
|
|
635
|
+
col === 0 ? "w-36" : col === 2 ? "ml-auto w-16" : width
|
|
636
|
+
}`}
|
|
637
|
+
/>
|
|
638
|
+
))}
|
|
639
|
+
</div>
|
|
640
|
+
))}
|
|
641
|
+
</div>
|
|
642
|
+
</div>
|
|
643
|
+
<div className="flex h-8 items-center justify-between border-t border-border px-1 text-xs">
|
|
644
|
+
<Skeleton className="h-3 w-28" />
|
|
645
|
+
<Skeleton className="h-3 w-24" />
|
|
646
|
+
</div>
|
|
647
|
+
</div>
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function SqlChartLoadingSkeleton({ panel }: { panel: SqlPanel }) {
|
|
652
|
+
const fill = useContext(ChartFillHeightContext);
|
|
653
|
+
|
|
654
|
+
if (panel.chartType === "metric") {
|
|
655
|
+
return (
|
|
656
|
+
<Skeleton
|
|
657
|
+
data-dashboard-report-loading="true"
|
|
658
|
+
className="w-full flex-1 min-h-12"
|
|
659
|
+
/>
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if (isTableLikeChartType(panel.chartType)) {
|
|
664
|
+
return <TableLoadingSkeleton />;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const reserveLegend = chartTypeReservesLegend(panel);
|
|
668
|
+
|
|
669
|
+
if (!reserveLegend) {
|
|
670
|
+
return (
|
|
671
|
+
<Skeleton
|
|
672
|
+
data-dashboard-report-loading="true"
|
|
673
|
+
className={`w-full flex-1 ${fill ? "h-full min-h-[250px]" : "min-h-[250px]"}`}
|
|
674
|
+
/>
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return (
|
|
679
|
+
<div
|
|
680
|
+
data-dashboard-report-loading="true"
|
|
681
|
+
className={`flex w-full flex-1 flex-col overflow-hidden ${fill ? "h-full" : ""}`}
|
|
682
|
+
>
|
|
683
|
+
<Skeleton
|
|
684
|
+
className={`w-full ${fill ? "h-full min-h-[250px] flex-1" : "h-[250px]"}`}
|
|
685
|
+
/>
|
|
686
|
+
<div className="mt-2 grid min-h-16 grid-cols-2 gap-x-3 gap-y-1 overflow-hidden pr-1 sm:grid-cols-3">
|
|
687
|
+
{Array.from({ length: 6 }).map((_, index) => (
|
|
688
|
+
<div key={index} className="flex items-center gap-1.5">
|
|
689
|
+
<Skeleton className="h-2.5 w-3 shrink-0 rounded-sm" />
|
|
690
|
+
<Skeleton className="h-3 w-20 min-w-0" />
|
|
691
|
+
</div>
|
|
692
|
+
))}
|
|
693
|
+
</div>
|
|
694
|
+
</div>
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
|
|
589
698
|
function ChartTooltip({
|
|
590
699
|
active,
|
|
591
700
|
payload,
|
|
@@ -962,16 +1071,16 @@ export function SqlChart({
|
|
|
962
1071
|
const yFormatter = panel.config?.yFormatter;
|
|
963
1072
|
|
|
964
1073
|
const isMetric = panel.chartType === "metric";
|
|
965
|
-
const
|
|
1074
|
+
const isTableLike = isTableLikeChartType(panel.chartType);
|
|
1075
|
+
const placeholderMinH = isMetric
|
|
1076
|
+
? "min-h-12"
|
|
1077
|
+
: isTableLike
|
|
1078
|
+
? TABLE_PANEL_MIN_HEIGHT_CLASS
|
|
1079
|
+
: "min-h-[250px]";
|
|
966
1080
|
const placeholderPadY = isMetric ? "py-2" : "py-8";
|
|
967
1081
|
|
|
968
1082
|
if (!loadData || isLoading) {
|
|
969
|
-
return
|
|
970
|
-
<Skeleton
|
|
971
|
-
data-dashboard-report-loading="true"
|
|
972
|
-
className={`w-full flex-1 ${placeholderMinH}`}
|
|
973
|
-
/>
|
|
974
|
-
);
|
|
1083
|
+
return <SqlChartLoadingSkeleton panel={panel} />;
|
|
975
1084
|
}
|
|
976
1085
|
|
|
977
1086
|
if (error) {
|
|
@@ -1366,7 +1475,7 @@ function TableRenderer({
|
|
|
1366
1475
|
}, [handleExportCsv, onExportCsvChange]);
|
|
1367
1476
|
|
|
1368
1477
|
return (
|
|
1369
|
-
<div className=
|
|
1478
|
+
<div className={`space-y-1 ${TABLE_PANEL_MIN_HEIGHT_CLASS}`}>
|
|
1370
1479
|
<div className="relative overflow-x-auto">
|
|
1371
1480
|
<table className="w-full text-sm">
|
|
1372
1481
|
<thead>
|
|
@@ -1989,7 +2098,9 @@ function HeatmapRenderer({
|
|
|
1989
2098
|
|
|
1990
2099
|
if (rows.length === 0 || !valueKey) {
|
|
1991
2100
|
return (
|
|
1992
|
-
<div
|
|
2101
|
+
<div
|
|
2102
|
+
className={`flex items-center justify-center py-8 ${TABLE_PANEL_MIN_HEIGHT_CLASS}`}
|
|
2103
|
+
>
|
|
1993
2104
|
<p className="text-sm text-muted-foreground text-center">
|
|
1994
2105
|
{t("common.noData")}
|
|
1995
2106
|
</p>
|
|
@@ -2010,7 +2121,7 @@ function HeatmapRenderer({
|
|
|
2010
2121
|
};
|
|
2011
2122
|
|
|
2012
2123
|
return (
|
|
2013
|
-
<div className=
|
|
2124
|
+
<div className={`${TABLE_PANEL_MIN_HEIGHT_CLASS} overflow-x-auto`}>
|
|
2014
2125
|
<table className="w-full border-collapse text-sm">
|
|
2015
2126
|
<thead>
|
|
2016
2127
|
<tr className="border-b border-border">
|
|
@@ -69,11 +69,17 @@ export default function MonitoringPage() {
|
|
|
69
69
|
{inSubView ? null : (
|
|
70
70
|
<div className="flex items-center justify-between gap-2">
|
|
71
71
|
<TabsList>
|
|
72
|
-
<TabsTrigger
|
|
72
|
+
<TabsTrigger
|
|
73
|
+
value="uptime"
|
|
74
|
+
className="gap-2 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-sm"
|
|
75
|
+
>
|
|
73
76
|
<IconHeartbeat className="h-4 w-4" />
|
|
74
77
|
{t("navigation.monitoringUptime")}
|
|
75
78
|
</TabsTrigger>
|
|
76
|
-
<TabsTrigger
|
|
79
|
+
<TabsTrigger
|
|
80
|
+
value="errors"
|
|
81
|
+
className="gap-2 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-sm"
|
|
82
|
+
>
|
|
77
83
|
<IconAlertTriangle className="h-4 w-4" />
|
|
78
84
|
{t("navigation.monitoringErrors")}
|
|
79
85
|
</TabsTrigger>
|
|
@@ -101,6 +101,8 @@ interface MonitorFormValues {
|
|
|
101
101
|
severity: MonitorSeverity;
|
|
102
102
|
channels: Record<(typeof KNOWN_CHANNELS)[number], boolean>;
|
|
103
103
|
emailRecipients: string;
|
|
104
|
+
slackWebhookUrl: string;
|
|
105
|
+
webhookUrl: string;
|
|
104
106
|
cooldownMinutes: number;
|
|
105
107
|
enabled: boolean;
|
|
106
108
|
}
|
|
@@ -160,6 +162,8 @@ function defaultValues(monitor: MonitorSummary | null): MonitorFormValues {
|
|
|
160
162
|
webhook: channelSet.has("webhook"),
|
|
161
163
|
},
|
|
162
164
|
emailRecipients: (monitor?.emailRecipients ?? []).join(", "),
|
|
165
|
+
slackWebhookUrl: monitor?.slackWebhookUrl ?? "",
|
|
166
|
+
webhookUrl: monitor?.webhookUrl ?? "",
|
|
163
167
|
cooldownMinutes: monitor?.cooldownMinutes ?? 15,
|
|
164
168
|
enabled: monitor?.enabled ?? true,
|
|
165
169
|
};
|
|
@@ -206,6 +210,8 @@ function initialSections(monitor: MonitorSummary | null): SectionState {
|
|
|
206
210
|
alerting:
|
|
207
211
|
!isDefaultChannels ||
|
|
208
212
|
monitor.emailRecipients.length > 0 ||
|
|
213
|
+
Boolean(monitor.slackWebhookUrl) ||
|
|
214
|
+
Boolean(monitor.webhookUrl) ||
|
|
209
215
|
monitor.severity !== "critical",
|
|
210
216
|
advanced:
|
|
211
217
|
monitor.method !== "GET" ||
|
|
@@ -362,6 +368,30 @@ export function MonitorFormPage({
|
|
|
362
368
|
setError("channels", { message: t.channelRequired });
|
|
363
369
|
return;
|
|
364
370
|
}
|
|
371
|
+
if (
|
|
372
|
+
formValues.channels.email &&
|
|
373
|
+
!splitList(formValues.emailRecipients).length
|
|
374
|
+
) {
|
|
375
|
+
setSections((prev) => ({ ...prev, alerting: true }));
|
|
376
|
+
setError("emailRecipients", { message: t.emailRecipientsRequired });
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
if (formValues.channels.slack) {
|
|
380
|
+
const slackUrl = formValues.slackWebhookUrl.trim();
|
|
381
|
+
if (slackUrl && !isHttpUrl(slackUrl)) {
|
|
382
|
+
setSections((prev) => ({ ...prev, alerting: true }));
|
|
383
|
+
setError("slackWebhookUrl", { message: t.slackWebhookUrlInvalid });
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (formValues.channels.webhook) {
|
|
388
|
+
const hookUrl = formValues.webhookUrl.trim();
|
|
389
|
+
if (hookUrl && !isHttpUrl(hookUrl)) {
|
|
390
|
+
setSections((prev) => ({ ...prev, alerting: true }));
|
|
391
|
+
setError("webhookUrl", { message: t.webhookUrlInvalid });
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
365
395
|
|
|
366
396
|
const assertions = formValues.assertions
|
|
367
397
|
.map((assertion) => {
|
|
@@ -399,7 +429,15 @@ export function MonitorFormPage({
|
|
|
399
429
|
followRedirects: formValues.followRedirects,
|
|
400
430
|
severity: formValues.severity,
|
|
401
431
|
channels,
|
|
402
|
-
emailRecipients:
|
|
432
|
+
emailRecipients: formValues.channels.email
|
|
433
|
+
? splitList(formValues.emailRecipients)
|
|
434
|
+
: [],
|
|
435
|
+
slackWebhookUrl: formValues.channels.slack
|
|
436
|
+
? formValues.slackWebhookUrl.trim()
|
|
437
|
+
: null,
|
|
438
|
+
webhookUrl: formValues.channels.webhook
|
|
439
|
+
? formValues.webhookUrl.trim()
|
|
440
|
+
: null,
|
|
403
441
|
cooldownMinutes: formValues.cooldownMinutes,
|
|
404
442
|
enabled: formValues.enabled,
|
|
405
443
|
};
|
|
@@ -736,8 +774,8 @@ export function MonitorFormPage({
|
|
|
736
774
|
setSections((prev) => ({ ...prev, alerting: open }))
|
|
737
775
|
}
|
|
738
776
|
>
|
|
739
|
-
<div className="
|
|
740
|
-
<div className="space-y-1.5">
|
|
777
|
+
<div className="space-y-4">
|
|
778
|
+
<div className="space-y-1.5 sm:max-w-xs">
|
|
741
779
|
<Label htmlFor="monitor-severity">{t.fieldSeverity}</Label>
|
|
742
780
|
<Controller
|
|
743
781
|
control={control}
|
|
@@ -765,43 +803,108 @@ export function MonitorFormPage({
|
|
|
765
803
|
/>
|
|
766
804
|
</div>
|
|
767
805
|
|
|
768
|
-
<div className="space-y-
|
|
806
|
+
<div className="space-y-2">
|
|
769
807
|
<Label>{t.fieldChannels}</Label>
|
|
770
808
|
<Controller
|
|
771
809
|
control={control}
|
|
772
810
|
name="channels"
|
|
773
811
|
render={({ field }) => (
|
|
774
|
-
<div className="
|
|
775
|
-
{KNOWN_CHANNELS.map((channel) =>
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
812
|
+
<div className="space-y-2">
|
|
813
|
+
{KNOWN_CHANNELS.map((channel) => {
|
|
814
|
+
const checked = field.value[channel];
|
|
815
|
+
return (
|
|
816
|
+
<div
|
|
817
|
+
key={channel}
|
|
818
|
+
className="rounded-md border border-border/60"
|
|
819
|
+
>
|
|
820
|
+
<label className="flex cursor-pointer items-start gap-2.5 px-3 py-2.5">
|
|
821
|
+
<Checkbox
|
|
822
|
+
className="mt-0.5"
|
|
823
|
+
checked={checked}
|
|
824
|
+
onCheckedChange={(next) =>
|
|
825
|
+
field.onChange({
|
|
826
|
+
...field.value,
|
|
827
|
+
[channel]: next === true,
|
|
828
|
+
})
|
|
829
|
+
}
|
|
830
|
+
/>
|
|
831
|
+
<span className="min-w-0">
|
|
832
|
+
<span className="block text-sm">
|
|
833
|
+
{channelLabel(channel, t)}
|
|
834
|
+
</span>
|
|
835
|
+
<span className="block text-xs text-muted-foreground">
|
|
836
|
+
{channelHint(channel, t)}
|
|
837
|
+
</span>
|
|
838
|
+
</span>
|
|
839
|
+
</label>
|
|
840
|
+
{channel === "email" && checked ? (
|
|
841
|
+
<div className="space-y-1.5 border-t border-border/60 px-3 py-2.5">
|
|
842
|
+
<Label htmlFor="monitor-emails">
|
|
843
|
+
{t.fieldEmailRecipients}
|
|
844
|
+
</Label>
|
|
845
|
+
<Textarea
|
|
846
|
+
id="monitor-emails"
|
|
847
|
+
className="min-h-[64px]"
|
|
848
|
+
placeholder={t.fieldEmailRecipientsPlaceholder}
|
|
849
|
+
{...register("emailRecipients")}
|
|
850
|
+
/>
|
|
851
|
+
{errors.emailRecipients ? (
|
|
852
|
+
<p className="text-xs text-destructive">
|
|
853
|
+
{errors.emailRecipients.message}
|
|
854
|
+
</p>
|
|
855
|
+
) : null}
|
|
856
|
+
</div>
|
|
857
|
+
) : null}
|
|
858
|
+
{channel === "slack" && checked ? (
|
|
859
|
+
<div className="space-y-1.5 border-t border-border/60 px-3 py-2.5">
|
|
860
|
+
<Label htmlFor="monitor-slack-url">
|
|
861
|
+
{t.fieldSlackWebhookUrl}
|
|
862
|
+
</Label>
|
|
863
|
+
<Input
|
|
864
|
+
id="monitor-slack-url"
|
|
865
|
+
type="url"
|
|
866
|
+
placeholder={t.fieldSlackWebhookUrlPlaceholder}
|
|
867
|
+
{...register("slackWebhookUrl")}
|
|
868
|
+
/>
|
|
869
|
+
{errors.slackWebhookUrl ? (
|
|
870
|
+
<p className="text-xs text-destructive">
|
|
871
|
+
{errors.slackWebhookUrl.message}
|
|
872
|
+
</p>
|
|
873
|
+
) : (
|
|
874
|
+
<p className="text-xs text-muted-foreground">
|
|
875
|
+
{t.fieldSlackWebhookUrlHint}
|
|
876
|
+
</p>
|
|
877
|
+
)}
|
|
878
|
+
</div>
|
|
879
|
+
) : null}
|
|
880
|
+
{channel === "webhook" && checked ? (
|
|
881
|
+
<div className="space-y-1.5 border-t border-border/60 px-3 py-2.5">
|
|
882
|
+
<Label htmlFor="monitor-webhook-url">
|
|
883
|
+
{t.fieldWebhookUrl}
|
|
884
|
+
</Label>
|
|
885
|
+
<Input
|
|
886
|
+
id="monitor-webhook-url"
|
|
887
|
+
type="url"
|
|
888
|
+
placeholder={t.fieldWebhookUrlPlaceholder}
|
|
889
|
+
{...register("webhookUrl")}
|
|
890
|
+
/>
|
|
891
|
+
{errors.webhookUrl ? (
|
|
892
|
+
<p className="text-xs text-destructive">
|
|
893
|
+
{errors.webhookUrl.message}
|
|
894
|
+
</p>
|
|
895
|
+
) : (
|
|
896
|
+
<p className="text-xs text-muted-foreground">
|
|
897
|
+
{t.fieldWebhookUrlHint}
|
|
898
|
+
</p>
|
|
899
|
+
)}
|
|
900
|
+
</div>
|
|
901
|
+
) : null}
|
|
902
|
+
</div>
|
|
903
|
+
);
|
|
904
|
+
})}
|
|
792
905
|
</div>
|
|
793
906
|
)}
|
|
794
907
|
/>
|
|
795
|
-
</div>
|
|
796
|
-
|
|
797
|
-
<div className="space-y-1.5 sm:col-span-2">
|
|
798
|
-
<Label htmlFor="monitor-emails">{t.fieldEmailRecipients}</Label>
|
|
799
|
-
<Textarea
|
|
800
|
-
id="monitor-emails"
|
|
801
|
-
className="min-h-[64px]"
|
|
802
|
-
placeholder={t.fieldEmailRecipientsPlaceholder}
|
|
803
|
-
{...register("emailRecipients")}
|
|
804
|
-
/>
|
|
805
908
|
{errors.channels ? (
|
|
806
909
|
<p className="text-xs text-destructive">
|
|
807
910
|
{errors.channels.message}
|
|
@@ -1024,3 +1127,19 @@ function channelLabel(
|
|
|
1024
1127
|
return t.channelWebhook;
|
|
1025
1128
|
}
|
|
1026
1129
|
}
|
|
1130
|
+
|
|
1131
|
+
function channelHint(
|
|
1132
|
+
channel: (typeof KNOWN_CHANNELS)[number],
|
|
1133
|
+
t: ReturnType<typeof useUptimeT>,
|
|
1134
|
+
): string {
|
|
1135
|
+
switch (channel) {
|
|
1136
|
+
case "inbox":
|
|
1137
|
+
return t.channelInboxHint;
|
|
1138
|
+
case "email":
|
|
1139
|
+
return t.channelEmailHint;
|
|
1140
|
+
case "slack":
|
|
1141
|
+
return t.channelSlackHint;
|
|
1142
|
+
case "webhook":
|
|
1143
|
+
return t.channelWebhookHint;
|
|
1144
|
+
}
|
|
1145
|
+
}
|