@burdenoff/microfe-bigconsole 2026.1004.7 → 2026.1004.8

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.
Files changed (35) hide show
  1. package/dist/bigconsole/BigConsoleRoutes.d.ts.map +1 -1
  2. package/dist/bigconsole/BigConsoleRoutes.js +35 -31
  3. package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
  4. package/dist/bigconsole/components/datasink/AlertExecutionHistory.d.ts +11 -0
  5. package/dist/bigconsole/components/datasink/AlertExecutionHistory.d.ts.map +1 -0
  6. package/dist/bigconsole/components/datasink/AlertExecutionHistory.js +248 -0
  7. package/dist/bigconsole/components/datasink/AlertExecutionHistory.js.map +1 -0
  8. package/dist/bigconsole/components/datasink/AlertRuleEditor.d.ts +23 -0
  9. package/dist/bigconsole/components/datasink/AlertRuleEditor.d.ts.map +1 -0
  10. package/dist/bigconsole/components/datasink/AlertRuleEditor.js +357 -0
  11. package/dist/bigconsole/components/datasink/AlertRuleEditor.js.map +1 -0
  12. package/dist/bigconsole/hooks/useDataSinkAlerts.d.ts +146 -0
  13. package/dist/bigconsole/hooks/useDataSinkAlerts.d.ts.map +1 -0
  14. package/dist/bigconsole/hooks/useDataSinkAlerts.js +221 -0
  15. package/dist/bigconsole/hooks/useDataSinkAlerts.js.map +1 -0
  16. package/dist/bigconsole/pages/DataSinkAlertsPage.d.ts +2 -0
  17. package/dist/bigconsole/pages/DataSinkAlertsPage.d.ts.map +1 -0
  18. package/dist/bigconsole/pages/DataSinkAlertsPage.js +422 -0
  19. package/dist/bigconsole/pages/DataSinkAlertsPage.js.map +1 -0
  20. package/dist/bigconsole/pages/DataSinkViewPage.d.ts.map +1 -1
  21. package/dist/bigconsole/pages/DataSinkViewPage.js +235 -229
  22. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  23. package/dist/bigconsole/utils/alertRules.d.ts +40 -0
  24. package/dist/bigconsole/utils/alertRules.d.ts.map +1 -0
  25. package/dist/bigconsole/utils/alertRules.js +83 -0
  26. package/dist/bigconsole/utils/alertRules.js.map +1 -0
  27. package/dist/generated/wspace-operations.d.ts +376 -0
  28. package/dist/generated/wspace-operations.d.ts.map +1 -1
  29. package/dist/generated/wspace-operations.js +321 -200
  30. package/dist/generated/wspace-operations.js.map +1 -1
  31. package/dist/generated/wspace-types.d.ts +122 -0
  32. package/dist/generated/wspace-types.d.ts.map +1 -1
  33. package/dist/generated/wspace-types.js +7 -1
  34. package/dist/generated/wspace-types.js.map +1 -1
  35. package/package.json +1 -1
@@ -0,0 +1,221 @@
1
+ import { BigConsoleDataSinkAlertChannelsDocument as e, BigConsoleDataSinkAlertExecutionsDocument as t, BigConsoleDataSinkAlertsDocument as n, BigConsoleDeleteDataSinkAlertDocument as r, BigConsolePreviewDataSinkAlertDocument as i, BigConsoleUpsertDataSinkAlertDocument as a } from "../../generated/wspace-operations.js";
2
+ import { useBigConsole as o } from "../context/BigConsoleContext.js";
3
+ import "../context/index.js";
4
+ import { useCallback as s, useEffect as c, useLayoutEffect as l, useRef as u, useState as d } from "react";
5
+ import { useApolloClient as f } from "@apollo/client/react";
6
+ //#region src/bigconsole/hooks/useDataSinkAlerts.ts
7
+ var p = {
8
+ owner: "",
9
+ sink: null,
10
+ channels: [],
11
+ loading: !1,
12
+ error: null,
13
+ channelError: null
14
+ }, m = (e) => e instanceof Error ? e.message : "The alert operation failed. Please try again.";
15
+ function h(h, g) {
16
+ let _ = f(), { currentUser: v, workspaceId: y } = o(), b = `${v?.id ?? ""}|${y ?? ""}|${h}`, x = u(null);
17
+ l(() => (x.current = g ? b : null, () => {
18
+ x.current = null;
19
+ }), [b, g]);
20
+ let [S, C] = d(p), [w, T] = d(!1), E = s(() => ({
21
+ requiredWorkspaceAuth: !0,
22
+ requiredWorkspaceId: y,
23
+ queryDeduplication: !1
24
+ }), [y]), D = s(() => g && !!y && !!v?.id && x.current === b, [
25
+ g,
26
+ y,
27
+ v?.id,
28
+ b
29
+ ]), O = s((e) => {
30
+ if (!D()) return null;
31
+ if (!e || e.id !== h || e.workspaceId !== y) throw Error("Data sink not found in this workspace.");
32
+ return C((t) => ({
33
+ ...t.owner === b ? t : p,
34
+ owner: b,
35
+ sink: t.owner === b && t.sink && t.sink.version > e.version ? t.sink : e,
36
+ loading: !1,
37
+ error: null
38
+ })), e;
39
+ }, [
40
+ D,
41
+ h,
42
+ y,
43
+ b
44
+ ]), k = s(async () => {
45
+ if (D()) {
46
+ T(!0), C((e) => ({
47
+ ...e.owner === b ? e : p,
48
+ owner: b,
49
+ loading: !e.sink,
50
+ error: null
51
+ }));
52
+ try {
53
+ return O((await _.query({
54
+ query: n,
55
+ variables: { dataSinkId: h },
56
+ fetchPolicy: "no-cache",
57
+ errorPolicy: "none",
58
+ context: E()
59
+ })).data?.getDataSink);
60
+ } catch (e) {
61
+ D() && C((t) => ({
62
+ ...t,
63
+ owner: b,
64
+ loading: !1,
65
+ error: m(e)
66
+ }));
67
+ } finally {
68
+ D() && T(!1);
69
+ }
70
+ }
71
+ }, [
72
+ _,
73
+ h,
74
+ b,
75
+ D,
76
+ O,
77
+ E
78
+ ]), A = s(async () => {
79
+ if (D()) try {
80
+ let t = await _.query({
81
+ query: e,
82
+ variables: { dataSinkId: h },
83
+ fetchPolicy: "no-cache",
84
+ errorPolicy: "none",
85
+ context: E()
86
+ });
87
+ if (!t.data) throw Error("Delivery channels did not load.");
88
+ let n = t.data.dataSinkAlertChannels;
89
+ D() && C((e) => ({
90
+ ...e.owner === b ? e : p,
91
+ owner: b,
92
+ channels: n,
93
+ channelError: null
94
+ }));
95
+ } catch (e) {
96
+ D() && C((t) => ({
97
+ ...t,
98
+ owner: b,
99
+ channels: [],
100
+ channelError: m(e)
101
+ }));
102
+ }
103
+ }, [
104
+ _,
105
+ h,
106
+ b,
107
+ D,
108
+ E
109
+ ]);
110
+ c(() => {
111
+ Promise.resolve().then(() => {
112
+ D() && (k(), A());
113
+ });
114
+ let e = window.setInterval(() => {
115
+ document.visibilityState === "visible" && k();
116
+ }, 1e4);
117
+ return () => window.clearInterval(e);
118
+ }, [
119
+ D,
120
+ k,
121
+ A
122
+ ]);
123
+ let j = s(async (e, t) => {
124
+ if (!D()) throw Error("Workspace context changed. Reopen the alert.");
125
+ return O((await _.mutate({
126
+ mutation: a,
127
+ variables: {
128
+ dataSinkId: h,
129
+ alert: e,
130
+ expectedVersion: t
131
+ },
132
+ errorPolicy: "none",
133
+ context: E()
134
+ })).data?.upsertDataSinkAlert);
135
+ }, [
136
+ _,
137
+ h,
138
+ D,
139
+ O,
140
+ E
141
+ ]), M = s(async (e, t) => {
142
+ if (!D()) throw Error("Workspace context changed. Reopen the alert.");
143
+ return O((await _.mutate({
144
+ mutation: r,
145
+ variables: {
146
+ dataSinkId: h,
147
+ alertId: e,
148
+ expectedVersion: t
149
+ },
150
+ errorPolicy: "none",
151
+ context: E()
152
+ })).data?.deleteDataSinkAlert);
153
+ }, [
154
+ _,
155
+ h,
156
+ D,
157
+ O,
158
+ E
159
+ ]), N = s(async (e, t) => {
160
+ if (!D()) throw Error("Workspace context changed. Reopen the alert.");
161
+ let n = await _.query({
162
+ query: i,
163
+ variables: {
164
+ dataSinkId: h,
165
+ condition: e,
166
+ conditionType: t
167
+ },
168
+ fetchPolicy: "no-cache",
169
+ errorPolicy: "none",
170
+ context: E()
171
+ });
172
+ if (!D()) return null;
173
+ if (!n.data) throw Error("Condition preview returned no result.");
174
+ return n.data.previewDataSinkAlert;
175
+ }, [
176
+ _,
177
+ h,
178
+ D,
179
+ E
180
+ ]), P = s(async (e, n) => {
181
+ if (!D()) return null;
182
+ let r = await _.query({
183
+ query: t,
184
+ variables: {
185
+ dataSinkId: h,
186
+ alertId: e,
187
+ after: n,
188
+ first: 21
189
+ },
190
+ fetchPolicy: "no-cache",
191
+ errorPolicy: "none",
192
+ context: E()
193
+ });
194
+ if (!D()) return null;
195
+ if (!r.data) throw Error("Execution history returned no result.");
196
+ return r.data.dataSinkAlertExecutions.filter((e) => e.dataSinkId === h);
197
+ }, [
198
+ _,
199
+ h,
200
+ D,
201
+ E
202
+ ]);
203
+ return {
204
+ ...S.owner === b ? S : {
205
+ ...p,
206
+ loading: g
207
+ },
208
+ owner: b,
209
+ refreshing: w,
210
+ reload: k,
211
+ reloadChannels: A,
212
+ save: j,
213
+ remove: M,
214
+ preview: N,
215
+ history: P
216
+ };
217
+ }
218
+ //#endregion
219
+ export { m as alertErrorMessage, h as useDataSinkAlerts };
220
+
221
+ //# sourceMappingURL=useDataSinkAlerts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDataSinkAlerts.js","names":[],"sources":["../../../src/bigconsole/hooks/useDataSinkAlerts.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport { useBigConsole } from '../context';\nimport {\n BigConsoleDataSinkAlertsDocument,\n BigConsoleDataSinkAlertChannelsDocument,\n BigConsoleDataSinkAlertExecutionsDocument,\n BigConsolePreviewDataSinkAlertDocument,\n BigConsoleUpsertDataSinkAlertDocument,\n BigConsoleDeleteDataSinkAlertDocument,\n type BigConsoleDataSinkAlertsQuery,\n type BigConsoleDataSinkAlertChannelsQuery,\n type BigConsoleDataSinkAlertExecutionsQuery,\n type BigConsolePreviewDataSinkAlertQuery,\n type BigConsoleUpsertDataSinkAlertMutation,\n type BigConsoleDeleteDataSinkAlertMutation,\n} from '../../generated/wspace-operations';\nimport type { DataSinkAlertInput, DataSinkAlertConditionType } from '../../generated/wspace-types';\n\nexport type AlertSink = NonNullable<BigConsoleDataSinkAlertsQuery['getDataSink']>;\nexport type AlertRule = NonNullable<AlertSink['alerts']>[number];\nexport type AlertChannel = BigConsoleDataSinkAlertChannelsQuery['dataSinkAlertChannels'][number];\nexport type AlertExecution = BigConsoleDataSinkAlertExecutionsQuery['dataSinkAlertExecutions'][number];\nexport type AlertPreview = BigConsolePreviewDataSinkAlertQuery['previewDataSinkAlert'];\n\ninterface AlertState {\n owner: string;\n sink: AlertSink | null;\n channels: AlertChannel[];\n loading: boolean;\n error: string | null;\n channelError: string | null;\n}\nconst EMPTY: AlertState = { owner: '', sink: null, channels: [], loading: false, error: null, channelError: null };\nexport const alertErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : 'The alert operation failed. Please try again.';\n\n/** Every read and write uses the selected workspace; late requests cannot populate a new owner. */\nexport function useDataSinkAlerts(dataSinkId: string, enabled: boolean) {\n const client = useApolloClient();\n const { currentUser, workspaceId } = useBigConsole();\n const owner = `${currentUser?.id ?? ''}|${workspaceId ?? ''}|${dataSinkId}`;\n const activeOwner = useRef<string | null>(null);\n useLayoutEffect(() => {\n activeOwner.current = enabled ? owner : null;\n return () => {\n activeOwner.current = null;\n };\n }, [owner, enabled]);\n const [state, setState] = useState<AlertState>(EMPTY);\n const [refreshing, setRefreshing] = useState(false);\n const context = useCallback(\n () => ({ requiredWorkspaceAuth: true, requiredWorkspaceId: workspaceId, queryDeduplication: false }),\n [workspaceId]\n );\n const ownsRequest = useCallback(\n () => enabled && !!workspaceId && !!currentUser?.id && activeOwner.current === owner,\n [enabled, workspaceId, currentUser?.id, owner]\n );\n const acceptSink = useCallback(\n (sink: AlertSink | null | undefined) => {\n if (!ownsRequest()) return null;\n if (!sink || sink.id !== dataSinkId || sink.workspaceId !== workspaceId)\n throw new Error('Data sink not found in this workspace.');\n setState((previous) => ({\n ...(previous.owner === owner ? previous : EMPTY),\n owner,\n sink: previous.owner === owner && previous.sink && previous.sink.version > sink.version ? previous.sink : sink,\n loading: false,\n error: null,\n }));\n return sink;\n },\n [ownsRequest, dataSinkId, workspaceId, owner]\n );\n const reload = useCallback(async () => {\n if (!ownsRequest()) return;\n setRefreshing(true);\n setState((previous) => ({\n ...(previous.owner === owner ? previous : EMPTY),\n owner,\n loading: !previous.sink,\n error: null,\n }));\n try {\n const result = await client.query<BigConsoleDataSinkAlertsQuery>({\n query: BigConsoleDataSinkAlertsDocument,\n variables: { dataSinkId },\n fetchPolicy: 'no-cache',\n errorPolicy: 'none',\n context: context(),\n });\n return acceptSink(result.data?.getDataSink);\n } catch (error) {\n if (ownsRequest())\n setState((previous) => ({ ...previous, owner, loading: false, error: alertErrorMessage(error) }));\n } finally {\n if (ownsRequest()) setRefreshing(false);\n }\n }, [client, dataSinkId, owner, ownsRequest, acceptSink, context]);\n const reloadChannels = useCallback(async () => {\n if (!ownsRequest()) return;\n try {\n const result = await client.query<BigConsoleDataSinkAlertChannelsQuery>({\n query: BigConsoleDataSinkAlertChannelsDocument,\n variables: { dataSinkId },\n fetchPolicy: 'no-cache',\n errorPolicy: 'none',\n context: context(),\n });\n if (!result.data) throw new Error('Delivery channels did not load.');\n const channels = result.data.dataSinkAlertChannels;\n if (ownsRequest())\n setState((previous) => ({\n ...(previous.owner === owner ? previous : EMPTY),\n owner,\n channels,\n channelError: null,\n }));\n } catch (error) {\n if (ownsRequest())\n setState((previous) => ({ ...previous, owner, channels: [], channelError: alertErrorMessage(error) }));\n }\n }, [client, dataSinkId, owner, ownsRequest, context]);\n useEffect(() => {\n void Promise.resolve().then(() => {\n if (ownsRequest()) {\n void reload();\n void reloadChannels();\n }\n });\n const timer = window.setInterval(() => {\n if (document.visibilityState === 'visible') void reload();\n }, 10000);\n return () => window.clearInterval(timer);\n }, [ownsRequest, reload, reloadChannels]);\n const save = useCallback(\n async (alert: DataSinkAlertInput, expectedVersion: number) => {\n if (!ownsRequest()) throw new Error('Workspace context changed. Reopen the alert.');\n const result = await client.mutate<BigConsoleUpsertDataSinkAlertMutation>({\n mutation: BigConsoleUpsertDataSinkAlertDocument,\n variables: { dataSinkId, alert, expectedVersion },\n errorPolicy: 'none',\n context: context(),\n });\n return acceptSink(result.data?.upsertDataSinkAlert);\n },\n [client, dataSinkId, ownsRequest, acceptSink, context]\n );\n const remove = useCallback(\n async (alertId: string, expectedVersion: number) => {\n if (!ownsRequest()) throw new Error('Workspace context changed. Reopen the alert.');\n const result = await client.mutate<BigConsoleDeleteDataSinkAlertMutation>({\n mutation: BigConsoleDeleteDataSinkAlertDocument,\n variables: { dataSinkId, alertId, expectedVersion },\n errorPolicy: 'none',\n context: context(),\n });\n return acceptSink(result.data?.deleteDataSinkAlert);\n },\n [client, dataSinkId, ownsRequest, acceptSink, context]\n );\n const preview = useCallback(\n async (condition: string, conditionType: DataSinkAlertConditionType) => {\n if (!ownsRequest()) throw new Error('Workspace context changed. Reopen the alert.');\n const result = await client.query<BigConsolePreviewDataSinkAlertQuery>({\n query: BigConsolePreviewDataSinkAlertDocument,\n variables: { dataSinkId, condition, conditionType },\n fetchPolicy: 'no-cache',\n errorPolicy: 'none',\n context: context(),\n });\n if (!ownsRequest()) return null;\n if (!result.data) throw new Error('Condition preview returned no result.');\n return result.data.previewDataSinkAlert;\n },\n [client, dataSinkId, ownsRequest, context]\n );\n const history = useCallback(\n async (alertId?: string, after?: string) => {\n if (!ownsRequest()) return null;\n const result = await client.query<BigConsoleDataSinkAlertExecutionsQuery>({\n query: BigConsoleDataSinkAlertExecutionsDocument,\n variables: { dataSinkId, alertId, after, first: 21 },\n fetchPolicy: 'no-cache',\n errorPolicy: 'none',\n context: context(),\n });\n if (!ownsRequest()) return null;\n if (!result.data) throw new Error('Execution history returned no result.');\n return result.data.dataSinkAlertExecutions.filter((row) => row.dataSinkId === dataSinkId);\n },\n [client, dataSinkId, ownsRequest, context]\n );\n return {\n ...(state.owner === owner ? state : { ...EMPTY, loading: enabled }),\n owner,\n refreshing,\n reload,\n reloadChannels,\n save,\n remove,\n preview,\n history,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export default function DataSinkAlertsPage(): import("react").JSX.Element;
2
+ //# sourceMappingURL=DataSinkAlertsPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataSinkAlertsPage.d.ts","sourceRoot":"","sources":["../../../src/bigconsole/pages/DataSinkAlertsPage.tsx"],"names":[],"mappings":"AAmCA,MAAM,CAAC,OAAO,UAAU,kBAAkB,gCASzC"}
@@ -0,0 +1,422 @@
1
+ import { useAppNavigate as e } from "../contexts/NavigationContext.js";
2
+ import "../contexts/index.js";
3
+ import { useBigConsole as t } from "../context/BigConsoleContext.js";
4
+ import "../context/index.js";
5
+ import { SECTION_FOCUS_RING as n } from "../components/common/sectionStyles.js";
6
+ import { Section as r } from "../components/common/Section.js";
7
+ import "../components/common/index.js";
8
+ import { BIGCONSOLE_PERMISSIONS as i } from "../../constants/permissions.js";
9
+ import { nativeConfirm as ee } from "../../utils/nativeBridge.js";
10
+ import { AlertRuleEditor as te } from "../components/datasink/AlertRuleEditor.js";
11
+ import { alertErrorMessage as a, useDataSinkAlerts as ne } from "../hooks/useDataSinkAlerts.js";
12
+ import { AlertExecutionHistory as re } from "../components/datasink/AlertExecutionHistory.js";
13
+ import { ALERT_VALIDATION_MESSAGES as o, alertDraft as s, alertDraftInput as c, validateAlertDraft as l } from "../utils/alertRules.js";
14
+ import { useEffect as u, useRef as d, useState as f } from "react";
15
+ import { useParams as p } from "react-router";
16
+ import { AccessDenied as ie } from "@burdenoff/fe-libs/shared/components";
17
+ import { usePermissions as ae } from "@burdenoff/fe-libs/shared/providers/shell";
18
+ import { ArrowLeft as oe, Bell as se, Loader2 as ce, Plus as le, RefreshCw as ue, Trash2 as m } from "lucide-react";
19
+ import { Button as h, Switch as de } from "@burdenoff/fe-libs/ui";
20
+ import { Fragment as fe, jsx as g, jsxs as _ } from "react/jsx-runtime";
21
+ import { useI18n as pe } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
22
+ //#region src/bigconsole/pages/DataSinkAlertsPage.tsx
23
+ function v() {
24
+ let { dataSinkId: e = "" } = p(), { currentUser: n, workspaceId: r } = t();
25
+ return /* @__PURE__ */ g(y, { dataSinkId: e }, `${n?.id ?? ""}|${r ?? ""}|${e}`);
26
+ }
27
+ function y({ dataSinkId: p }) {
28
+ let { t: v } = pe(), y = e(), { currentUser: b, workspaceId: x } = t(), { hasPermission: S, isLoading: C } = ae(), w = S(i.DATASINK_READ), T = !C && S(i.DATASINK_UPDATE), E = ne(p, !C && w && !!x && !!b?.id), D = E.sink, O = D?.alerts ?? [], [k, me] = f(""), [A, j] = f(null), [M, N] = f(!1), P = d(!1), F = d(null), [I, L] = f(null), [R, z] = f(null), [B, V] = f(!1), [he, H] = f(null), [U, W] = f(null), [ge, G] = f(0), K = d(0), q = d(0), J = A?.selection;
29
+ u(() => {
30
+ J !== void 0 && document.getElementById("alert-name")?.focus();
31
+ }, [J]);
32
+ let _e = !!A && JSON.stringify(A.draft) !== A.original, Y = async (e) => await ee({
33
+ title: v("bigconsole.alerts.confirm.title", "Confirm alert change"),
34
+ message: e,
35
+ okButtonTitle: v("bigconsole.alerts.confirm.continue", "Continue"),
36
+ cancelButtonTitle: v("bigconsole.alerts.rule.cancel", "Cancel")
37
+ }) ?? window.confirm(e), X = () => !_e || Y(v("bigconsole.alerts.confirm.discard", "Discard your unsaved rule changes?")), Z = async (e) => {
38
+ if (M || !D || !await X()) return;
39
+ document.activeElement instanceof HTMLElement && (F.current = document.activeElement);
40
+ let t = s(e);
41
+ j({
42
+ draft: t,
43
+ original: JSON.stringify(t),
44
+ version: D.version,
45
+ selection: ++q.current
46
+ }), K.current++, W(null), H(null), V(!1), L(null), z(null);
47
+ }, ve = async () => {
48
+ M || !await X() || (j(null), W(null), H(null), K.current++, V(!1), L(null), F.current?.isConnected && F.current.focus());
49
+ }, Q = async () => {
50
+ if (!A || !D || !T || P.current) return;
51
+ let e = l(A.draft, E.channels);
52
+ if (e) {
53
+ L(v(`bigconsole.alerts.validation.${e}`, o[e]));
54
+ return;
55
+ }
56
+ P.current = !0, N(!0), L(null), z(null);
57
+ let t = new Set(O.map((e) => e.id));
58
+ try {
59
+ let e = await E.save(c(A.draft), A.version);
60
+ if (!e) return;
61
+ let n = e.alerts?.find((e) => A.draft.id ? e.id === A.draft.id : !t.has(e.id));
62
+ if (n) {
63
+ let t = s(n);
64
+ j({
65
+ draft: t,
66
+ original: JSON.stringify(t),
67
+ version: e.version,
68
+ selection: A.selection
69
+ });
70
+ } else j(null);
71
+ z(v("bigconsole.alerts.feedback.saved", "Alert rule saved.")), G((e) => e + 1);
72
+ } catch (e) {
73
+ L(a(e));
74
+ } finally {
75
+ P.current = !1, N(!1);
76
+ }
77
+ }, ye = async (e) => {
78
+ if (!D || !T || P.current) return;
79
+ let t = {
80
+ ...s(e),
81
+ enabled: !e.enabled
82
+ }, n = l(t, E.channels);
83
+ if (n) {
84
+ L(v(`bigconsole.alerts.validation.${n}`, o[n]));
85
+ return;
86
+ }
87
+ P.current = !0, N(!0), L(null), z(null);
88
+ try {
89
+ await E.save(c(t), D.version) && (z(t.enabled ? v("bigconsole.alerts.feedback.enabled", "Alert rule enabled.") : v("bigconsole.alerts.feedback.disabled", "Alert rule disabled.")), G((e) => e + 1));
90
+ } catch (e) {
91
+ L(a(e));
92
+ } finally {
93
+ P.current = !1, N(!1);
94
+ }
95
+ }, be = async (e) => {
96
+ if (!(!D || !T || P.current) && !(!await Y(`${v("bigconsole.alerts.confirm.delete", "Delete alert rule")} “${e.name}”?`) || P.current)) {
97
+ P.current = !0, N(!0), L(null), z(null);
98
+ try {
99
+ await E.remove(e.id, D.version) && (A?.draft.id === e.id && j(null), z(v("bigconsole.alerts.feedback.deleted", "Alert rule deleted.")), G((e) => e + 1));
100
+ } catch (e) {
101
+ L(a(e));
102
+ } finally {
103
+ P.current = !1, N(!1);
104
+ }
105
+ }
106
+ }, xe = async () => {
107
+ if (!A || B || M) return;
108
+ let e = ++K.current, { condition: t, conditionType: n } = A.draft;
109
+ V(!0), H(null), W(null);
110
+ try {
111
+ let r = await E.preview(t, n);
112
+ r && K.current === e && W({
113
+ condition: t,
114
+ conditionType: n,
115
+ result: r
116
+ });
117
+ } catch (t) {
118
+ K.current === e && H(a(t));
119
+ } finally {
120
+ K.current === e && V(!1);
121
+ }
122
+ }, Se = async () => {
123
+ if (!A?.draft.id || M || !await X()) return;
124
+ let e = await E.reload(), t = e?.alerts?.find((e) => e.id === A.draft.id);
125
+ if (!e) return;
126
+ if (!t) {
127
+ j(null), z(v("bigconsole.alerts.feedback.removedElsewhere", "This rule no longer exists."));
128
+ return;
129
+ }
130
+ let n = s(t);
131
+ j({
132
+ draft: n,
133
+ original: JSON.stringify(n),
134
+ version: e.version,
135
+ selection: ++q.current
136
+ }), L(null), W(null);
137
+ };
138
+ if (C || E.loading) return /* @__PURE__ */ _("div", {
139
+ role: "status",
140
+ className: "flex min-h-60 items-center justify-center p-card-padding",
141
+ children: [/* @__PURE__ */ g(ce, { className: "mr-2 h-5 w-5 animate-spin text-text-secondary" }), v("bigconsole.alerts.loading", "Loading alerts…")]
142
+ });
143
+ if (!w) return /* @__PURE__ */ g(ie, {
144
+ title: v("bigconsole.alerts.denied", "Access denied"),
145
+ description: v("bigconsole.alerts.deniedDescription", "You do not have permission to read this data sink.")
146
+ });
147
+ if (!x || !b?.id) return /* @__PURE__ */ g("p", {
148
+ className: "p-card-padding text-text-secondary",
149
+ children: v("bigconsole.alerts.selectWorkspace", "Select a workspace to view its alerts.")
150
+ });
151
+ if (!D) return /* @__PURE__ */ g("div", {
152
+ className: "p-card-padding",
153
+ children: /* @__PURE__ */ g(r, {
154
+ title: v("bigconsole.alerts.unavailable", "Alerts could not be loaded"),
155
+ headingLevel: 2,
156
+ tone: "danger",
157
+ description: E.error ?? v("bigconsole.alerts.notFound", "Data sink not found."),
158
+ actions: /* @__PURE__ */ g(h, {
159
+ onClick: () => void E.reload(),
160
+ variant: "secondary",
161
+ children: v("bigconsole.alerts.retry", "Retry")
162
+ })
163
+ })
164
+ });
165
+ let $ = O.filter((e) => `${e.name} ${e.condition}`.toLowerCase().includes(k.trim().toLowerCase()));
166
+ return /* @__PURE__ */ _("div", {
167
+ className: "min-w-0 p-card-padding",
168
+ children: [
169
+ /* @__PURE__ */ _("header", {
170
+ className: "mb-section-gap flex flex-col gap-form-gap sm:flex-row sm:items-start sm:justify-between",
171
+ children: [/* @__PURE__ */ _("div", {
172
+ className: "min-w-0",
173
+ children: [
174
+ /* @__PURE__ */ _(h, {
175
+ variant: "ghost",
176
+ size: "sm",
177
+ onClick: () => y(`/datasinks/${p}`),
178
+ className: "mb-3",
179
+ children: [/* @__PURE__ */ g(oe, { className: "mr-2 h-4 w-4" }), v("bigconsole.alerts.back", "Back to data sink")]
180
+ }),
181
+ /* @__PURE__ */ _("h1", {
182
+ className: "break-words text-2xl font-bold text-text-primary",
183
+ children: [
184
+ v("bigconsole.alerts.title", "Alerts"),
185
+ " · ",
186
+ D.name || D.key
187
+ ]
188
+ }),
189
+ /* @__PURE__ */ g("p", {
190
+ className: "mt-2 text-sm text-text-secondary",
191
+ children: v("bigconsole.alerts.purpose", "Create and manage alert rules for this data sink.")
192
+ })
193
+ ]
194
+ }), /* @__PURE__ */ _(h, {
195
+ variant: "secondary",
196
+ size: "sm",
197
+ onClick: () => {
198
+ E.reload(), E.reloadChannels(), G((e) => e + 1);
199
+ },
200
+ disabled: E.refreshing || M,
201
+ children: [/* @__PURE__ */ g(ue, { className: `mr-2 h-4 w-4 ${E.refreshing ? "animate-spin" : ""}` }), v("bigconsole.alerts.refresh", "Refresh alerts")]
202
+ })]
203
+ }),
204
+ R && /* @__PURE__ */ g("p", {
205
+ role: "status",
206
+ className: "mb-4 rounded-control bg-[var(--color-status-success-bgSubtle)] p-3 text-sm text-status-success-text",
207
+ children: R
208
+ }),
209
+ I && !A && /* @__PURE__ */ g("p", {
210
+ role: "alert",
211
+ className: "mb-4 break-words text-sm text-status-error-text",
212
+ children: I
213
+ }),
214
+ E.error && /* @__PURE__ */ g("p", {
215
+ role: "alert",
216
+ className: "mb-4 break-words text-sm text-status-error-text",
217
+ children: E.error
218
+ }),
219
+ /* @__PURE__ */ _("div", {
220
+ className: "grid min-w-0 items-start gap-section-gap xl:grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)]",
221
+ children: [/* @__PURE__ */ _("div", {
222
+ className: "min-w-0 space-y-section-gap",
223
+ children: [/* @__PURE__ */ _(r, {
224
+ title: v("bigconsole.alerts.list.title", "Alert rules"),
225
+ headingLevel: 2,
226
+ icon: /* @__PURE__ */ g(se, { className: "h-4 w-4" }),
227
+ actions: /* @__PURE__ */ _(h, {
228
+ size: "sm",
229
+ onClick: () => void Z(),
230
+ disabled: !T || M,
231
+ children: [/* @__PURE__ */ g(le, { className: "mr-2 h-4 w-4" }), v("bigconsole.alerts.list.new", "New alert rule")]
232
+ }),
233
+ children: [
234
+ /* @__PURE__ */ g("label", {
235
+ htmlFor: "alert-search",
236
+ className: "sr-only",
237
+ children: v("bigconsole.alerts.list.search", "Search alerts")
238
+ }),
239
+ /* @__PURE__ */ g("input", {
240
+ id: "alert-search",
241
+ type: "search",
242
+ value: k,
243
+ onChange: (e) => me(e.target.value),
244
+ placeholder: v("bigconsole.alerts.list.searchPlaceholder", "Search alerts…"),
245
+ className: `mb-4 w-full min-w-0 rounded-control border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary ${n}`
246
+ }),
247
+ /* @__PURE__ */ g("div", {
248
+ className: "max-w-full overflow-x-auto",
249
+ children: /* @__PURE__ */ _("table", {
250
+ className: "w-full text-sm",
251
+ children: [
252
+ /* @__PURE__ */ g("caption", {
253
+ className: "sr-only",
254
+ children: v("bigconsole.alerts.list.caption", "Rules for this data sink")
255
+ }),
256
+ /* @__PURE__ */ g("thead", { children: /* @__PURE__ */ _("tr", {
257
+ className: "border-b border-border-subtle text-left text-xs text-text-secondary",
258
+ children: [
259
+ /* @__PURE__ */ g("th", {
260
+ scope: "col",
261
+ className: "pb-3 pr-2",
262
+ children: v("bigconsole.alerts.rule.name", "Name")
263
+ }),
264
+ /* @__PURE__ */ g("th", {
265
+ scope: "col",
266
+ className: "hidden pb-3 pr-2 sm:table-cell",
267
+ children: v("bigconsole.alerts.rule.severity", "Severity")
268
+ }),
269
+ /* @__PURE__ */ g("th", {
270
+ scope: "col",
271
+ className: "hidden pb-3 pr-2 lg:table-cell",
272
+ children: v("bigconsole.alerts.rule.destinations", "Delivery destinations")
273
+ }),
274
+ /* @__PURE__ */ g("th", {
275
+ scope: "col",
276
+ className: "hidden pb-3 pr-2 md:table-cell",
277
+ children: v("bigconsole.alerts.rule.throttle", "Throttle")
278
+ }),
279
+ /* @__PURE__ */ g("th", {
280
+ scope: "col",
281
+ className: "pb-3 pr-2",
282
+ children: v("bigconsole.alerts.list.enabled", "Enabled")
283
+ }),
284
+ /* @__PURE__ */ g("th", {
285
+ scope: "col",
286
+ className: "pb-3",
287
+ children: /* @__PURE__ */ g("span", {
288
+ className: "sr-only",
289
+ children: v("bigconsole.alerts.list.actions", "Actions")
290
+ })
291
+ })
292
+ ]
293
+ }) }),
294
+ /* @__PURE__ */ g("tbody", { children: $.map((e) => /* @__PURE__ */ _("tr", {
295
+ className: "border-b border-border-subtle last:border-0",
296
+ children: [
297
+ /* @__PURE__ */ _("th", {
298
+ scope: "row",
299
+ className: "max-w-64 py-4 pr-2 text-left font-normal",
300
+ children: [
301
+ /* @__PURE__ */ g("button", {
302
+ type: "button",
303
+ onClick: () => void Z(e),
304
+ disabled: M,
305
+ className: `break-words text-left font-medium text-text-primary underline-offset-4 hover:underline ${n}`,
306
+ children: e.name
307
+ }),
308
+ /* @__PURE__ */ g("p", {
309
+ className: "mt-1 text-xs text-text-secondary sm:hidden",
310
+ children: v(`bigconsole.alerts.severity.${e.severity}`, e.severity.toUpperCase())
311
+ }),
312
+ /* @__PURE__ */ g("p", {
313
+ className: "mt-1 text-xs text-text-muted md:hidden",
314
+ children: e.throttle?.enabled ? `${e.throttle.maxAlertsPerWindow} / ${e.throttle.windowMinutes} min` : v("bigconsole.alerts.list.noThrottle", "No throttle")
315
+ })
316
+ ]
317
+ }),
318
+ /* @__PURE__ */ g("td", {
319
+ className: "hidden py-4 pr-2 sm:table-cell",
320
+ children: /* @__PURE__ */ g("span", {
321
+ className: "rounded-pill border border-border-subtle bg-bg-sunken px-2 py-1 text-xs text-text-primary",
322
+ children: v(`bigconsole.alerts.severity.${e.severity}`, e.severity.toUpperCase())
323
+ })
324
+ }),
325
+ /* @__PURE__ */ g("td", {
326
+ className: "hidden py-4 pr-2 text-xs text-text-secondary lg:table-cell",
327
+ children: e.deliveries.length ? [...new Set(e.deliveries.map((e) => e.channel))].join(", ") : v("bigconsole.alerts.list.unconfigured", "Not configured")
328
+ }),
329
+ /* @__PURE__ */ g("td", {
330
+ className: "hidden py-4 pr-2 text-xs text-text-secondary md:table-cell",
331
+ children: e.throttle?.enabled ? `${e.throttle.maxAlertsPerWindow} / ${e.throttle.windowMinutes} min` : v("bigconsole.alerts.list.noThrottle", "No throttle")
332
+ }),
333
+ /* @__PURE__ */ g("td", {
334
+ className: "py-4 pr-2",
335
+ children: /* @__PURE__ */ g(de, {
336
+ checked: e.enabled,
337
+ onCheckedChange: () => void ye(e),
338
+ disabled: !T || M,
339
+ "aria-label": `${v("bigconsole.alerts.list.enabled", "Enabled")} · ${e.name}`
340
+ })
341
+ }),
342
+ /* @__PURE__ */ g("td", {
343
+ className: "py-4",
344
+ children: /* @__PURE__ */ g(h, {
345
+ type: "button",
346
+ variant: "ghost",
347
+ size: "sm",
348
+ onClick: () => void be(e),
349
+ disabled: !T || M,
350
+ "aria-label": `${v("bigconsole.alerts.confirm.delete", "Delete alert rule")} · ${e.name}`,
351
+ children: /* @__PURE__ */ g(m, { className: "h-4 w-4" })
352
+ })
353
+ })
354
+ ]
355
+ }, e.id)) })
356
+ ]
357
+ })
358
+ }),
359
+ !$.length && /* @__PURE__ */ g("p", {
360
+ className: "py-4 text-sm text-text-secondary",
361
+ children: O.length ? v("bigconsole.alerts.list.noMatches", "No alerts match your search.") : v("bigconsole.alerts.list.empty", "No alert rules yet. Create a disabled rule and preview its condition before enabling it.")
362
+ }),
363
+ /* @__PURE__ */ _("p", {
364
+ className: "mt-3 text-xs text-text-muted",
365
+ children: [
366
+ $.length,
367
+ " ",
368
+ v("bigconsole.alerts.list.count", "rules shown")
369
+ ]
370
+ })
371
+ ]
372
+ }), /* @__PURE__ */ g(re, {
373
+ owner: E.owner,
374
+ rules: O,
375
+ load: E.history,
376
+ refreshVersion: ge
377
+ })]
378
+ }), /* @__PURE__ */ g("div", {
379
+ className: "min-w-0",
380
+ children: A ? /* @__PURE__ */ _(fe, { children: [/* @__PURE__ */ g(te, {
381
+ draft: A.draft,
382
+ channels: E.channels,
383
+ channelError: E.channelError,
384
+ canUpdate: T,
385
+ pending: M,
386
+ previewing: B,
387
+ preview: U?.result ?? null,
388
+ previewError: he,
389
+ previewStale: !!U && (U.condition !== A.draft.condition || U.conditionType !== A.draft.conditionType || D.version > U.result.version),
390
+ error: I,
391
+ onChange: (e) => {
392
+ (e.condition !== A.draft.condition || e.conditionType !== A.draft.conditionType) && (K.current++, H(null), V(!1)), j({
393
+ ...A,
394
+ draft: e
395
+ });
396
+ },
397
+ onSave: () => void Q(),
398
+ onCancel: () => void ve(),
399
+ onPreview: () => void xe(),
400
+ onReloadChannels: () => void E.reloadChannels()
401
+ }), A.draft.id && /* @__PURE__ */ g(h, {
402
+ type: "button",
403
+ variant: "ghost",
404
+ size: "sm",
405
+ onClick: () => void Se(),
406
+ disabled: M || E.refreshing,
407
+ className: "mt-3",
408
+ children: v("bigconsole.alerts.rule.reloadSaved", "Reload saved rule")
409
+ })] }) : /* @__PURE__ */ g(r, {
410
+ title: v("bigconsole.alerts.rule.title", "Alert rule"),
411
+ headingLevel: 2,
412
+ description: v("bigconsole.alerts.rule.select", "Select a rule to inspect it, or create a new alert rule.")
413
+ })
414
+ })]
415
+ })
416
+ ]
417
+ });
418
+ }
419
+ //#endregion
420
+ export { v as default };
421
+
422
+ //# sourceMappingURL=DataSinkAlertsPage.js.map