@webx-ui/module-notifications 0.0.0-stage → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 webx-ui
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,42 @@
1
- # Temporary Holding Version
1
+ # @webx-ui/module-notifications
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The front end of the Notifications section of the [WebX UI](https://github.com/webx-ui/webx-ui)
4
+ admin panel: channels to Telegram and e-mail, their Mustache templates in every language of the
5
+ site, a live preview, tests, and the log of every delivery.
6
+
7
+ The other half is the Composer package `webx-ui/module-notifications`, which owns the channels, the
8
+ providers, the queue, the API and the agent tools. A section appears in the panel when both halves
9
+ are installed.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install @webx-ui/module-notifications
15
+ ```
16
+
17
+ ```ts
18
+ import { createAdmin } from '@webx-ui/module-admin'
19
+ import { notifications } from '@webx-ui/module-notifications'
20
+ import '@webx-ui/module-notifications/style.css'
21
+
22
+ createAdmin({
23
+ basePath: '/cms',
24
+ modules: [notifications()],
25
+ }).mount()
26
+ ```
27
+
28
+ `php artisan webx:module:add notifications` installs both halves and writes this into the panel's
29
+ entry. `notifications({ path: '/alerts' })` puts the section somewhere else inside the panel.
30
+
31
+ ## What is in it
32
+
33
+ - The section: channels with their switch, copy and bin; the delivery log with filters and
34
+ «Send again».
35
+ - A channel's page: the described screen `notifications.channel` with the provider's settings, the
36
+ template in `WxCodeEditor` with Mustache highlighted and suggested after `{{`, and the preview
37
+ beside it — rendered by `renderMessage()`, held to the server's render by shared test cases.
38
+ - Node types for screens: `wx-notifications-template`, `wx-notifications-chats`,
39
+ `wx-notifications-emails`, and `wx-notifications-channels` — the picker a module chooses its
40
+ channels for an event with, also exported as `WxNotificationChannelsField`.
41
+
42
+ The guide: https://webx-ui.github.io/webx-ui/guide/notifications
@@ -0,0 +1,427 @@
1
+ import { defineComponent as le, ref as v, computed as p, openBlock as o, createBlock as f, unref as a, isRef as Se, withCtx as m, createVNode as g, createTextVNode as V, toDisplayString as B, createCommentVNode as _, createElementBlock as j, Fragment as L, renderList as ie, onMounted as We, onBeforeUnmount as $e, createSlots as Ne, createElementVNode as Ce } from "vue";
2
+ import { useRoute as Te, useRouter as Ve, onBeforeRouteLeave as Be } from "vue-router";
3
+ import { useModal as Ae, WxDialog as Me, WxText as te, WxFormItem as je, WxSelect as De, WxAlert as W, WxSpace as Le, WxButton as P, useLocales as qe, createModal as Ee, confirm as ne, WxSkeleton as Oe, WxBadge as Pe, WxActionBar as Ke, toast as y } from "@webx-ui/core";
4
+ import { useAdmin as re, useTranslate as se, useErrorText as oe, provideHistorySubject as Re, useBodyKeys as Ue, WxScreenHead as ze, WxScreen as Je, WxSaveState as Fe } from "@webx-ui/module-admin";
5
+ import { c as ue, u as ce, p as He, M as Ie, _ as Ge } from "./index-DIeEPPSh.js";
6
+ const Qe = /* @__PURE__ */ le({
7
+ name: "WxNotificationsTestDialog",
8
+ __name: "TestDialog",
9
+ props: {
10
+ channel: { default: null },
11
+ values: {},
12
+ recipients: { default: () => [] }
13
+ },
14
+ setup(q) {
15
+ const w = q, { open: C, dismiss: h } = Ae(), k = ue(re());
16
+ ce();
17
+ const d = se("webx-notifications"), E = oe(), t = v(""), x = v(!1), r = v(null), S = v(null), l = p(() => [
18
+ { value: "", label: d("panel.test-everybody") },
19
+ ...w.recipients
20
+ ]);
21
+ async function i() {
22
+ x.value = !0, S.value = null;
23
+ try {
24
+ r.value = await k.test(w.channel, w.values, t.value === "" ? null : t.value);
25
+ } catch (u) {
26
+ const c = u.body;
27
+ S.value = c?.errors ? Object.values(c.errors).flat().join(" ") : E(u);
28
+ } finally {
29
+ x.value = !1;
30
+ }
31
+ }
32
+ function N(u) {
33
+ const c = u.label ? `${u.label} (${u.recipient})` : u.recipient;
34
+ return u.status === "sent" ? d("panel.test-sent", { recipient: c }) : d("panel.test-failed", {
35
+ recipient: c,
36
+ error: u.error ?? (u.reason ? d(`module.reasons.${u.reason}`) : u.status)
37
+ });
38
+ }
39
+ return (u, c) => (o(), f(a(Me), {
40
+ open: a(C),
41
+ "onUpdate:open": c[2] || (c[2] = (b) => Se(C) ? C.value = b : null),
42
+ title: a(d)("panel.test-title"),
43
+ width: 480
44
+ }, {
45
+ footer: m(() => [
46
+ g(a(Le), { size: "sm" }, {
47
+ default: m(() => [
48
+ g(a(P), {
49
+ variant: "outline",
50
+ onClick: c[1] || (c[1] = (b) => a(h)())
51
+ }, {
52
+ default: m(() => [
53
+ V(B(a(d)("panel.cancel")), 1)
54
+ ]),
55
+ _: 1
56
+ }),
57
+ g(a(P), {
58
+ type: "primary",
59
+ loading: x.value,
60
+ onClick: i
61
+ }, {
62
+ default: m(() => [
63
+ V(B(a(d)("panel.test-send")), 1)
64
+ ]),
65
+ _: 1
66
+ }, 8, ["loading"])
67
+ ]),
68
+ _: 1
69
+ })
70
+ ]),
71
+ default: m(() => [
72
+ g(a(te), {
73
+ size: "sm",
74
+ tone: "muted"
75
+ }, {
76
+ default: m(() => [
77
+ V(B(a(d)("panel.test-help")), 1)
78
+ ]),
79
+ _: 1
80
+ }),
81
+ g(a(je), {
82
+ label: a(d)("panel.test-to")
83
+ }, {
84
+ default: m(() => [
85
+ g(a(De), {
86
+ modelValue: t.value,
87
+ "onUpdate:modelValue": c[0] || (c[0] = (b) => t.value = b),
88
+ options: l.value,
89
+ disabled: x.value
90
+ }, null, 8, ["modelValue", "options", "disabled"])
91
+ ]),
92
+ _: 1
93
+ }, 8, ["label"]),
94
+ S.value ? (o(), f(a(W), {
95
+ key: 0,
96
+ type: "danger",
97
+ variant: "soft",
98
+ description: S.value
99
+ }, null, 8, ["description"])) : _("", !0),
100
+ r.value ? (o(), j(L, { key: 1 }, [
101
+ r.value.length === 0 ? (o(), f(a(te), {
102
+ key: 0,
103
+ size: "sm",
104
+ tone: "muted"
105
+ }, {
106
+ default: m(() => [
107
+ V(B(a(d)("panel.test-none")), 1)
108
+ ]),
109
+ _: 1
110
+ })) : _("", !0),
111
+ (o(!0), j(L, null, ie(r.value, (b, $) => (o(), f(a(W), {
112
+ key: $,
113
+ type: b.status === "sent" ? "success" : "danger",
114
+ variant: "soft",
115
+ description: N(b)
116
+ }, null, 8, ["type", "description"]))), 128))
117
+ ], 64)) : _("", !0)
118
+ ]),
119
+ _: 1
120
+ }, 8, ["open", "title"]));
121
+ }
122
+ }), Xe = { class: "wx-notifications-channel__body" }, Ye = /* @__PURE__ */ le({
123
+ __name: "ChannelPage",
124
+ props: {
125
+ base: { default: "/notifications" }
126
+ },
127
+ setup(q) {
128
+ const w = q, C = re(), h = ue(C), k = Te(), d = Ve(), E = qe();
129
+ ce();
130
+ const t = se("webx-notifications"), x = oe(), r = v(
131
+ typeof k.params.id == "string" && k.params.id !== "" ? Number(k.params.id) : null
132
+ ), S = v(null), l = v(null), i = v({}), N = v(""), u = v([]), c = v({}), b = v(!0), $ = v(!1), O = v(!1), K = He(S, i, r);
133
+ Re({ id: p(() => l.value?.id ?? null) });
134
+ const T = p(() => C.can("notifications.manage")), R = p(() => JSON.stringify(i.value)), A = p(() => N.value !== "" && R.value !== N.value), de = p(() => $.value ? "saving" : A.value || r.value === null ? "unsaved" : "saved"), U = p(() => {
135
+ const e = typeof i.value.name == "string" ? i.value.name.trim() : "";
136
+ return e !== "" ? e : r.value === null ? t("panel.new") : t("panel.untitled");
137
+ }), z = p(
138
+ () => Array.isArray(i.value.forget) ? i.value.forget : []
139
+ ), J = p(
140
+ () => (K.provider.value?.fields ?? []).filter((e) => e.secret).map((e) => ({
141
+ field: e,
142
+ set: l.value?.credentials_set[e.name] === !0 && !z.value.includes(e.name)
143
+ }))
144
+ ), ve = p(() => [
145
+ { op: "set", target: "provider", props: { disabled: !0 } },
146
+ ...J.value.filter((e) => e.set).map((e) => ({
147
+ op: "set",
148
+ target: e.field.name,
149
+ help: t("panel.secret-set"),
150
+ props: { placeholder: "••••••••" }
151
+ }))
152
+ ]);
153
+ function F(e) {
154
+ l.value = e.channel, i.value = e.values, N.value = JSON.stringify(e.values), u.value = e.warnings;
155
+ }
156
+ function pe(e) {
157
+ const n = typeof k.query.provider == "string" ? k.query.provider : "email", s = typeof k.query.event == "string" && k.query.event !== "" ? k.query.event : null, D = e.events.find((M) => M.key === s), Z = D?.sample[n] ?? D?.sample["*"], ee = E.list.value[0]?.code ?? "en", ae = {};
158
+ for (const M of e.providers.find((xe) => xe.key === n)?.fields ?? [])
159
+ ae[M.name] = M.secret ? "" : M.default ?? "";
160
+ return {
161
+ name: "",
162
+ provider: n,
163
+ event: s,
164
+ enabled: !1,
165
+ recipients: [],
166
+ ...ae,
167
+ template: { [ee]: Z?.template ?? "" },
168
+ subject: { [ee]: Z?.subject ?? "" }
169
+ };
170
+ }
171
+ const H = v([]);
172
+ async function fe() {
173
+ b.value = !0;
174
+ try {
175
+ const [e, n] = await Promise.all([
176
+ h.meta(),
177
+ r.value === null ? Promise.resolve(null) : h.get(r.value)
178
+ ]);
179
+ if (S.value = e, n === null) {
180
+ const s = pe(e);
181
+ i.value = s, N.value = JSON.stringify(s);
182
+ } else
183
+ F(n);
184
+ } catch (e) {
185
+ y.danger(x(e)), d.push(w.base);
186
+ } finally {
187
+ b.value = !1;
188
+ }
189
+ i.value.provider === "email" && T.value && h.administrators().then((e) => H.value = e).catch(() => {
190
+ });
191
+ }
192
+ function I(e) {
193
+ const n = e.body;
194
+ n?.errors ? (c.value = n.errors, y.danger(t("panel.save-failed"))) : y.danger(x(e));
195
+ }
196
+ async function G() {
197
+ if (!($.value || !T.value)) {
198
+ $.value = !0, c.value = {};
199
+ try {
200
+ const e = r.value === null, n = e ? await h.create(i.value) : await h.save(r.value, i.value);
201
+ F(n), n.warnings.length > 0 ? y.warning(t("panel.saved-warning", { warning: n.warnings.join(" ") })) : y.success(t("panel.saved")), e && (r.value = n.channel.id, d.replace(`${w.base}/channels/${n.channel.id}`));
202
+ } catch (e) {
203
+ I(e);
204
+ } finally {
205
+ $.value = !1;
206
+ }
207
+ }
208
+ }
209
+ async function me() {
210
+ O.value = !0;
211
+ try {
212
+ const e = await h.check(r.value, i.value);
213
+ e.ok ? y.success(e.message || t("panel.check-ok")) : y.warning(e.message);
214
+ } catch (e) {
215
+ I(e);
216
+ } finally {
217
+ O.value = !1;
218
+ }
219
+ }
220
+ const ye = Ee(Qe), ge = p(() => (Array.isArray(i.value.recipients) ? i.value.recipients : []).flatMap((n) => {
221
+ if (n.chat_id)
222
+ return [
223
+ { value: n.chat_id, label: n.label ? `${n.label} · ${n.chat_id}` : n.chat_id }
224
+ ];
225
+ if (n.email) return [{ value: n.email, label: n.email }];
226
+ const s = H.value.find((D) => D.id === n.admin_id);
227
+ return s ? [{ value: s.email, label: `${s.name} · ${s.email}` }] : [];
228
+ }));
229
+ async function be() {
230
+ await ye({ channel: r.value, values: i.value, recipients: ge.value });
231
+ }
232
+ async function he() {
233
+ if (r.value !== null)
234
+ try {
235
+ const e = await h.copy(r.value);
236
+ y.success(t("panel.copied", { name: e.channel.name })), d.push(`${w.base}/channels/${e.channel.id}`);
237
+ } catch (e) {
238
+ y.danger(x(e));
239
+ }
240
+ }
241
+ async function ke() {
242
+ const e = l.value;
243
+ if (!(!e || !await ne({
244
+ title: t("panel.delete-title", { title: U.value }),
245
+ message: t("panel.delete-text"),
246
+ confirmText: t("panel.delete"),
247
+ cancelText: t("panel.cancel"),
248
+ tone: "danger"
249
+ })))
250
+ try {
251
+ await h.remove(e.id), y.success(t("panel.deleted")), N.value = R.value, d.push(w.base);
252
+ } catch (s) {
253
+ y.danger(x(s));
254
+ }
255
+ }
256
+ function _e(e, n) {
257
+ i.value = { ...i.value, forget: [...z.value, e], [e]: "" }, y.info(t("panel.forgotten", { field: n }));
258
+ }
259
+ function Q(e) {
260
+ A.value && e.preventDefault();
261
+ }
262
+ function X(e) {
263
+ (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "s" && (e.preventDefault(), (A.value || r.value === null) && G());
264
+ }
265
+ Ue(X), We(() => {
266
+ fe(), window.addEventListener("beforeunload", Q);
267
+ }), $e(() => {
268
+ window.removeEventListener("beforeunload", Q);
269
+ }), Be(async () => !A.value || !T.value ? !0 : await ne({
270
+ title: t("panel.leave-title"),
271
+ message: t("panel.leave-text"),
272
+ confirmText: t("panel.leave"),
273
+ cancelText: t("panel.cancel"),
274
+ tone: "danger"
275
+ }));
276
+ const we = p(() => {
277
+ if (!T.value) return [];
278
+ const e = [
279
+ {
280
+ key: "check",
281
+ label: t("panel.check"),
282
+ icon: "check-circle",
283
+ loading: O.value,
284
+ run: () => {
285
+ me();
286
+ }
287
+ },
288
+ { key: "test", label: t("panel.test"), icon: "send", run: () => {
289
+ be();
290
+ } }
291
+ ];
292
+ l.value !== null && e.push({
293
+ key: "copy",
294
+ label: t("panel.copy"),
295
+ icon: "copy",
296
+ menu: !0,
297
+ run: () => {
298
+ he();
299
+ }
300
+ });
301
+ for (const n of J.value.filter((s) => s.set))
302
+ e.push({
303
+ key: `forget-${n.field.name}`,
304
+ label: t("panel.forget", { field: n.field.label }),
305
+ icon: "unlock",
306
+ menu: !0,
307
+ run: () => _e(n.field.name, n.field.label)
308
+ });
309
+ return l.value !== null && e.push({
310
+ key: "delete",
311
+ label: t("panel.delete"),
312
+ icon: "trash",
313
+ danger: !0,
314
+ run: () => {
315
+ ke();
316
+ }
317
+ }), e;
318
+ }), Y = p(() => S.value?.environment ?? "production");
319
+ return (e, n) => (o(), j("div", {
320
+ class: "wx-notifications-channel",
321
+ onKeydown: X
322
+ }, [
323
+ b.value ? (o(), f(a(Oe), {
324
+ key: 0,
325
+ class: "wx-notifications-channel__ghost",
326
+ title: "",
327
+ rows: 8
328
+ })) : (o(), j(L, { key: 1 }, [
329
+ g(a(ze), {
330
+ back: w.base,
331
+ "back-label": a(t)("panel.channels"),
332
+ title: U.value,
333
+ subtitle: l.value?.provider_label ?? a(K).provider.value?.label,
334
+ actions: we.value
335
+ }, Ne({ _: 2 }, [
336
+ l.value && !l.value.enabled ? {
337
+ name: "title-after",
338
+ fn: m(() => [
339
+ g(a(Pe), { dot: "" }, {
340
+ default: m(() => [
341
+ V(B(a(t)("panel.off")), 1)
342
+ ]),
343
+ _: 1
344
+ })
345
+ ]),
346
+ key: "0"
347
+ } : void 0
348
+ ]), 1032, ["back", "back-label", "title", "subtitle", "actions"]),
349
+ Y.value !== "production" ? (o(), f(a(W), {
350
+ key: 0,
351
+ type: "info",
352
+ variant: "soft",
353
+ description: a(t)("panel.environment", { environment: Y.value })
354
+ }, null, 8, ["description"])) : _("", !0),
355
+ S.value?.mode === "after_response" ? (o(), f(a(W), {
356
+ key: 1,
357
+ type: "warning",
358
+ variant: "soft",
359
+ description: a(t)("panel.mode-after-response")
360
+ }, null, 8, ["description"])) : _("", !0),
361
+ l.value && !l.value.provider_declared ? (o(), f(a(W), {
362
+ key: 2,
363
+ type: "danger",
364
+ title: a(t)("panel.provider-undeclared"),
365
+ description: a(t)("panel.provider-undeclared-text", { provider: l.value.provider })
366
+ }, null, 8, ["title", "description"])) : _("", !0),
367
+ l.value && !l.value.event_declared ? (o(), f(a(W), {
368
+ key: 3,
369
+ type: "warning",
370
+ title: a(t)("panel.event-undeclared"),
371
+ description: a(t)("panel.event-undeclared-text", { event: l.value.event ?? "" })
372
+ }, null, 8, ["title", "description"])) : _("", !0),
373
+ l.value && !l.value.credentials_readable ? (o(), f(a(W), {
374
+ key: 4,
375
+ type: "danger",
376
+ description: a(t)("panel.unreadable")
377
+ }, null, 8, ["description"])) : _("", !0),
378
+ l.value?.copied_from ? (o(), f(a(W), {
379
+ key: 5,
380
+ type: "info",
381
+ variant: "soft",
382
+ description: a(t)("panel.copied-from", { id: String(l.value.copied_from) })
383
+ }, null, 8, ["description"])) : _("", !0),
384
+ (o(!0), j(L, null, ie(u.value, (s) => (o(), f(a(W), {
385
+ key: s,
386
+ type: "warning",
387
+ description: s
388
+ }, null, 8, ["description"]))), 128)),
389
+ Ce("div", Xe, [
390
+ g(a(Je), {
391
+ modelValue: i.value,
392
+ "onUpdate:modelValue": n[0] || (n[0] = (s) => i.value = s),
393
+ class: "wx-notifications-channel__form",
394
+ name: "notifications.channel",
395
+ errors: c.value,
396
+ patch: ve.value,
397
+ disabled: !T.value || $.value
398
+ }, null, 8, ["modelValue", "errors", "patch", "disabled"]),
399
+ g(Ie, { class: "wx-notifications-channel__preview" })
400
+ ]),
401
+ T.value ? (o(), f(a(Ke), { key: 6 }, {
402
+ state: m(() => [
403
+ g(a(Fe), { state: de.value }, null, 8, ["state"])
404
+ ]),
405
+ default: m(() => [
406
+ g(a(P), {
407
+ type: "primary",
408
+ loading: $.value,
409
+ disabled: !A.value && r.value !== null,
410
+ onClick: G
411
+ }, {
412
+ default: m(() => [
413
+ V(B(a(t)("panel.save")), 1)
414
+ ]),
415
+ _: 1
416
+ }, 8, ["loading", "disabled"])
417
+ ]),
418
+ _: 1
419
+ })) : _("", !0)
420
+ ], 64))
421
+ ], 32));
422
+ }
423
+ }), la = /* @__PURE__ */ Ge(Ye, [["__scopeId", "data-v-b5c7b69a"]]);
424
+ export {
425
+ la as default
426
+ };
427
+ //# sourceMappingURL=ChannelPage-C47YoMPO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChannelPage-C47YoMPO.js","sources":["../src/TestDialog.vue","../src/ChannelPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n useModal,\n WxAlert,\n WxButton,\n WxDialog,\n WxFormItem,\n WxSelect,\n WxSpace,\n WxText,\n} from '@webx-ui/core'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport { createNotificationsApi } from './api'\nimport { useNotificationsMessages } from './i18n'\nimport type { TestResult } from './types'\n\n/**\n * \"Send a test\" (§8.5): now, past the queue, with the event's example values, to everybody on the\n * list or to one of them — through the form's values, saved or not, and through a channel that\n * is switched off, which is what a test is for. What happened to each recipient stays in the\n * dialog: a test that failed is read, not dismissed with a toast.\n */\ndefineOptions({ name: 'WxNotificationsTestDialog' })\n\nconst props = withDefaults(\n defineProps<{\n channel?: number | null\n values: ScreenModel\n /** The fixed recipients, as the server knows them by: a chat id, an address. */\n recipients?: { value: string; label: string }[]\n }>(),\n { channel: null, recipients: () => [] },\n)\n\nconst { open, dismiss } = useModal<void>()\n\nconst api = createNotificationsApi(useAdmin())\nuseNotificationsMessages()\n\nconst t = useTranslate('webx-notifications')\nconst message = useErrorText()\n\nconst to = ref('')\nconst sending = ref(false)\nconst results = ref<TestResult[] | null>(null)\nconst failure = ref<string | null>(null)\n\nconst options = computed(() => [\n { value: '', label: t('panel.test-everybody') },\n ...props.recipients,\n])\n\nasync function send(): Promise<void> {\n sending.value = true\n failure.value = null\n\n try {\n results.value = await api.test(props.channel, props.values, to.value === '' ? null : to.value)\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n\n failure.value = body?.errors ? Object.values(body.errors).flat().join(' ') : message(error)\n } finally {\n sending.value = false\n }\n}\n\nfunction lineOf(result: TestResult): string {\n const recipient = result.label ? `${result.label} (${result.recipient})` : result.recipient\n\n if (result.status === 'sent') return t('panel.test-sent', { recipient })\n\n return t('panel.test-failed', {\n recipient,\n error: result.error ?? (result.reason ? t(`module.reasons.${result.reason}`) : result.status),\n })\n}\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('panel.test-title')\" :width=\"480\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.test-help') }}</wx-text>\n\n <wx-form-item :label=\"t('panel.test-to')\">\n <wx-select v-model=\"to\" :options=\"options\" :disabled=\"sending\" />\n </wx-form-item>\n\n <wx-alert v-if=\"failure\" type=\"danger\" variant=\"soft\" :description=\"failure\" />\n\n <template v-if=\"results\">\n <wx-text v-if=\"results.length === 0\" size=\"sm\" tone=\"muted\">{{\n t('panel.test-none')\n }}</wx-text>\n <wx-alert\n v-for=\"(result, index) in results\"\n :key=\"index\"\n :type=\"result.status === 'sent' ? 'success' : 'danger'\"\n variant=\"soft\"\n :description=\"lineOf(result)\"\n />\n </template>\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('panel.cancel') }}</wx-button>\n <wx-button type=\"primary\" :loading=\"sending\" @click=\"send\">\n {{ t('panel.test-send') }}\n </wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport { onBeforeRouteLeave, useRoute, useRouter } from 'vue-router'\nimport {\n confirm,\n createModal,\n toast,\n useLocales,\n WxActionBar,\n WxAlert,\n WxBadge,\n WxButton,\n WxSkeleton,\n} from '@webx-ui/core'\nimport {\n provideHistorySubject,\n useAdmin,\n useBodyKeys,\n useErrorText,\n useTranslate,\n WxSaveState,\n WxScreen,\n WxScreenHead,\n type ScreenAction,\n} from '@webx-ui/module-admin'\nimport type { Patch, ScreenModel } from '@webx-ui/schema'\nimport { createNotificationsApi } from './api'\nimport { provideChannel } from './context'\nimport { useNotificationsMessages } from './i18n'\nimport MessagePreview from './MessagePreview.vue'\nimport TestDialog from './TestDialog.vue'\nimport type {\n Administrator,\n ChannelDetail,\n ChannelRow,\n ChatRecipient,\n EmailRecipient,\n NotificationsMeta,\n} from './types'\n\n/**\n * One channel (§10.3): the described screen `notifications.channel` — the common part and the\n * provider's settings the server lays over it — with the live preview beside it on a wide pane and\n * under it on a narrow one, and one explicit save.\n *\n * A secret is never in the form: the server answers which are set, and the field says so with\n * `••••••••` until a new one is typed. \"Forget\" is in the head's menu, one per secret that is set,\n * and takes effect on the save, like every other change here.\n *\n * The form's values are what \"Check\", \"Send a test\" and the preview run on — saved or not: a\n * channel is tried before it is kept, and a test of a switched-off channel is the point of one.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/notifications' })\n\nconst admin = useAdmin()\nconst api = createNotificationsApi(admin)\nconst route = useRoute()\nconst router = useRouter()\nconst locales = useLocales()\nuseNotificationsMessages()\n\nconst t = useTranslate('webx-notifications')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst id = ref<number | null>(\n typeof route.params.id === 'string' && route.params.id !== '' ? Number(route.params.id) : null,\n)\n\nconst meta = ref<NotificationsMeta | null>(null)\nconst channel = ref<ChannelRow | null>(null)\nconst values = ref<ScreenModel>({})\nconst snapshot = ref('')\nconst warnings = ref<string[]>([])\nconst errors = ref<Record<string, string[]>>({})\nconst loading = ref(true)\nconst saving = ref(false)\nconst checking = ref(false)\n\nconst context = provideChannel(meta, values, id)\n\nprovideHistorySubject({ id: computed(() => channel.value?.id ?? null) })\n\nconst canManage = computed(() => admin.can('notifications.manage'))\n\nconst current = computed(() => JSON.stringify(values.value))\nconst dirty = computed(() => snapshot.value !== '' && current.value !== snapshot.value)\n\nconst state = computed<'saving' | 'unsaved' | 'saved'>(() => {\n if (saving.value) return 'saving'\n\n return dirty.value || id.value === null ? 'unsaved' : 'saved'\n})\n\nconst title = computed(() => {\n const written = typeof values.value.name === 'string' ? values.value.name.trim() : ''\n\n if (written !== '') return written\n\n return id.value === null ? t('panel.new') : t('panel.untitled')\n})\n\nconst forgetting = computed<string[]>(() =>\n Array.isArray(values.value.forget) ? (values.value.forget as string[]) : [],\n)\n\n/** The provider's secret settings, and whether each is set on the saved channel. */\nconst secrets = computed(() =>\n (context.provider.value?.fields ?? [])\n .filter((field) => field.secret)\n .map((field) => ({\n field,\n set:\n channel.value?.credentials_set[field.name] === true &&\n !forgetting.value.includes(field.name),\n })),\n)\n\n/*\n * What only this page knows about the tree: the kind of channel is chosen once, and a secret that\n * is set says so instead of showing an empty field that reads as \"not set\".\n */\nconst patch = computed<Patch>(() => [\n { op: 'set', target: 'provider', props: { disabled: true } },\n ...secrets.value\n .filter((one) => one.set)\n .map((one): Patch[number] => ({\n op: 'set',\n target: one.field.name,\n help: t('panel.secret-set'),\n props: { placeholder: '••••••••' },\n })),\n])\n\nfunction take(detail: ChannelDetail): void {\n channel.value = detail.channel\n values.value = detail.values\n snapshot.value = JSON.stringify(detail.values)\n warnings.value = detail.warnings\n}\n\n/** What the server would answer for a channel with nothing in it yet, and the event's sample. */\nfunction blank(found: NotificationsMeta): ScreenModel {\n const provider = typeof route.query.provider === 'string' ? route.query.provider : 'email'\n const event =\n typeof route.query.event === 'string' && route.query.event !== '' ? route.query.event : null\n const definition = found.events.find((one) => one.key === event)\n const sample = definition?.sample[provider] ?? definition?.sample['*']\n const locale = locales.list.value[0]?.code ?? 'en'\n const settings: ScreenModel = {}\n\n for (const field of found.providers.find((one) => one.key === provider)?.fields ?? []) {\n settings[field.name] = field.secret ? '' : (field.default ?? '')\n }\n\n return {\n name: '',\n provider,\n event,\n enabled: false,\n recipients: [],\n ...settings,\n template: { [locale]: sample?.template ?? '' },\n subject: { [locale]: sample?.subject ?? '' },\n }\n}\n\nconst administrators = ref<Administrator[]>([])\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n const [found, detail] = await Promise.all([\n api.meta(),\n id.value === null ? Promise.resolve(null) : api.get(id.value),\n ])\n\n meta.value = found\n\n if (detail === null) {\n const made = blank(found)\n\n values.value = made\n snapshot.value = JSON.stringify(made)\n } else {\n take(detail)\n }\n } catch (error) {\n toast.danger(message(error))\n void router.push(props.base)\n } finally {\n loading.value = false\n }\n\n if (values.value.provider === 'email' && canManage.value) {\n api\n .administrators()\n .then((found) => (administrators.value = found))\n .catch(() => undefined)\n }\n}\n\nfunction refusal(error: unknown): void {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n toast.danger(t('panel.save-failed'))\n } else {\n toast.danger(message(error))\n }\n}\n\nasync function save(): Promise<void> {\n if (saving.value || !canManage.value) return\n\n saving.value = true\n errors.value = {}\n\n try {\n const made = id.value === null\n const detail = made\n ? await api.create(values.value)\n : await api.save(id.value as number, values.value)\n\n take(detail)\n\n if (detail.warnings.length > 0) {\n toast.warning(t('panel.saved-warning', { warning: detail.warnings.join(' ') }))\n } else {\n toast.success(t('panel.saved'))\n }\n\n if (made) {\n id.value = detail.channel.id\n // Nothing left to protect: the record exists, and its address is the one to keep.\n void router.replace(`${props.base}/channels/${detail.channel.id}`)\n }\n } catch (error) {\n refusal(error)\n } finally {\n saving.value = false\n }\n}\n\nasync function check(): Promise<void> {\n checking.value = true\n\n try {\n const answer = await api.check(id.value, values.value)\n\n if (answer.ok) toast.success(answer.message || t('panel.check-ok'))\n else toast.warning(answer.message)\n } catch (error) {\n refusal(error)\n } finally {\n checking.value = false\n }\n}\n\nconst tester = createModal<\n void,\n { channel?: number | null; values: ScreenModel; recipients?: { value: string; label: string }[] }\n>(TestDialog)\n\n/** The fixed recipients as the server knows them by: a chat id, an address. */\nconst fixed = computed(() => {\n const list = Array.isArray(values.value.recipients) ? values.value.recipients : []\n\n return (list as (ChatRecipient & EmailRecipient)[]).flatMap((one) => {\n if (one.chat_id)\n return [\n { value: one.chat_id, label: one.label ? `${one.label} · ${one.chat_id}` : one.chat_id },\n ]\n if (one.email) return [{ value: one.email, label: one.email }]\n\n const found = administrators.value.find((person) => person.id === one.admin_id)\n\n return found ? [{ value: found.email, label: `${found.name} · ${found.email}` }] : []\n })\n})\n\nasync function test(): Promise<void> {\n await tester({ channel: id.value, values: values.value, recipients: fixed.value })\n}\n\nasync function copy(): Promise<void> {\n if (id.value === null) return\n\n try {\n const detail = await api.copy(id.value)\n\n toast.success(t('panel.copied', { name: detail.channel.name }))\n void router.push(`${props.base}/channels/${detail.channel.id}`)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nasync function remove(): Promise<void> {\n const row = channel.value\n\n if (!row) return\n\n const agreed = await confirm({\n title: t('panel.delete-title', { title: title.value }),\n message: t('panel.delete-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.remove(row.id)\n toast.success(t('panel.deleted'))\n snapshot.value = current.value\n void router.push(props.base)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nfunction forget(name: string, label: string): void {\n values.value = { ...values.value, forget: [...forgetting.value, name], [name]: '' }\n toast.info(t('panel.forgotten', { field: label }))\n}\n\n/* The browser's own guard: it cannot wait for a request, so all it can do is ask. */\nfunction leaveGuard(event: BeforeUnloadEvent): void {\n if (dirty.value) event.preventDefault()\n}\n\n/* Ctrl+S saves, as it does everywhere else that has a save button. */\nfunction onKeydown(event: KeyboardEvent): void {\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {\n event.preventDefault()\n if (dirty.value || id.value === null) void save()\n }\n}\n\nuseBodyKeys(onKeydown)\n\nonMounted(() => {\n void load()\n window.addEventListener('beforeunload', leaveGuard)\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('beforeunload', leaveGuard)\n})\n\nonBeforeRouteLeave(async () => {\n if (!dirty.value || !canManage.value) return true\n\n return await confirm({\n title: t('panel.leave-title'),\n message: t('panel.leave-text'),\n confirmText: t('panel.leave'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n})\n\nconst actions = computed<ScreenAction[]>(() => {\n if (!canManage.value) return []\n\n const list: ScreenAction[] = [\n {\n key: 'check',\n label: t('panel.check'),\n icon: 'check-circle',\n loading: checking.value,\n run: () => void check(),\n },\n { key: 'test', label: t('panel.test'), icon: 'send', run: () => void test() },\n ]\n\n if (channel.value !== null) {\n list.push({\n key: 'copy',\n label: t('panel.copy'),\n icon: 'copy',\n menu: true,\n run: () => void copy(),\n })\n }\n\n for (const one of secrets.value.filter((secret) => secret.set)) {\n list.push({\n key: `forget-${one.field.name}`,\n label: t('panel.forget', { field: one.field.label }),\n icon: 'unlock',\n menu: true,\n run: () => forget(one.field.name, one.field.label),\n })\n }\n\n if (channel.value !== null) {\n list.push({\n key: 'delete',\n label: t('panel.delete'),\n icon: 'trash',\n danger: true,\n run: () => void remove(),\n })\n }\n\n return list\n})\n\nconst environment = computed(() => meta.value?.environment ?? 'production')\n</script>\n\n<template>\n <div class=\"wx-notifications-channel\" @keydown=\"onKeydown\">\n <wx-skeleton v-if=\"loading\" class=\"wx-notifications-channel__ghost\" title :rows=\"8\" />\n\n <template v-else>\n <wx-screen-head\n :back=\"props.base\"\n :back-label=\"t('panel.channels')\"\n :title=\"title\"\n :subtitle=\"channel?.provider_label ?? context.provider.value?.label\"\n :actions=\"actions\"\n >\n <template v-if=\"channel && !channel.enabled\" #title-after>\n <wx-badge dot>{{ t('panel.off') }}</wx-badge>\n </template>\n </wx-screen-head>\n\n <wx-alert\n v-if=\"environment !== 'production'\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('panel.environment', { environment })\"\n />\n <wx-alert\n v-if=\"meta?.mode === 'after_response'\"\n type=\"warning\"\n variant=\"soft\"\n :description=\"t('panel.mode-after-response')\"\n />\n <wx-alert\n v-if=\"channel && !channel.provider_declared\"\n type=\"danger\"\n :title=\"t('panel.provider-undeclared')\"\n :description=\"t('panel.provider-undeclared-text', { provider: channel.provider })\"\n />\n <wx-alert\n v-if=\"channel && !channel.event_declared\"\n type=\"warning\"\n :title=\"t('panel.event-undeclared')\"\n :description=\"t('panel.event-undeclared-text', { event: channel.event ?? '' })\"\n />\n <wx-alert\n v-if=\"channel && !channel.credentials_readable\"\n type=\"danger\"\n :description=\"t('panel.unreadable')\"\n />\n <wx-alert\n v-if=\"channel?.copied_from\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('panel.copied-from', { id: String(channel.copied_from) })\"\n />\n <wx-alert v-for=\"warning in warnings\" :key=\"warning\" type=\"warning\" :description=\"warning\" />\n\n <div class=\"wx-notifications-channel__body\">\n <wx-screen\n v-model=\"values\"\n class=\"wx-notifications-channel__form\"\n name=\"notifications.channel\"\n :errors=\"errors\"\n :patch=\"patch\"\n :disabled=\"!canManage || saving\"\n />\n\n <message-preview class=\"wx-notifications-channel__preview\" />\n </div>\n\n <wx-action-bar v-if=\"canManage\">\n <template #state>\n <wx-save-state :state=\"state\" />\n </template>\n\n <wx-button type=\"primary\" :loading=\"saving\" :disabled=\"!dirty && id !== null\" @click=\"save\">\n {{ t('panel.save') }}\n </wx-button>\n </wx-action-bar>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-notifications-channel {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n container-type: inline-size;\n}\n\n.wx-notifications-channel__ghost {\n max-width: 480px;\n}\n\n.wx-notifications-channel__body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n}\n\n.wx-notifications-channel__form,\n.wx-notifications-channel__preview {\n min-width: 0;\n}\n\n/*\n * Beside the form once the pane has room for both, and staying in view while the template is\n * scrolled to: the preview is read while typing, not after.\n */\n@container (min-width: 1040px) {\n .wx-notifications-channel__body {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(320px, 400px);\n align-items: start;\n }\n\n .wx-notifications-channel__preview {\n position: sticky;\n top: var(--wx-space-16);\n }\n}\n</style>\n"],"names":["props","__props","open","dismiss","useModal","api","createNotificationsApi","useAdmin","useNotificationsMessages","t","useTranslate","message","useErrorText","to","ref","sending","results","failure","options","computed","send","error","body","lineOf","result","recipient","_createBlock","_unref","WxDialog","$event","_createVNode","WxSpace","WxButton","WxText","WxFormItem","WxSelect","WxAlert","_createElementBlock","_Fragment","_openBlock","_renderList","index","admin","route","useRoute","router","useRouter","locales","useLocales","id","meta","channel","values","snapshot","warnings","errors","loading","saving","checking","context","provideChannel","provideHistorySubject","canManage","current","dirty","state","title","written","forgetting","secrets","field","patch","one","take","detail","blank","found","provider","event","definition","sample","locale","settings","administrators","load","made","toast","refusal","save","check","answer","tester","createModal","TestDialog","fixed","person","test","copy","remove","row","confirm","forget","name","label","leaveGuard","onKeydown","useBodyKeys","onMounted","onBeforeUnmount","onBeforeRouteLeave","actions","list","secret","environment","WxSkeleton","WxScreenHead","WxBadge","warning","_createElementVNode","_hoisted_1","WxScreen","MessagePreview","WxActionBar","WxSaveState"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * One channel (§10.3): the described screen `notifications.channel` — the common part and the
3
+ * provider's settings the server lays over it — with the live preview beside it on a wide pane and
4
+ * under it on a narrow one, and one explicit save.
5
+ *
6
+ * A secret is never in the form: the server answers which are set, and the field says so with
7
+ * `••••••••` until a new one is typed. "Forget" is in the head's menu, one per secret that is set,
8
+ * and takes effect on the save, like every other change here.
9
+ *
10
+ * The form's values are what "Check", "Send a test" and the preview run on — saved or not: a
11
+ * channel is tried before it is kept, and a test of a switched-off channel is the point of one.
12
+ */
13
+ type __VLS_Props = {
14
+ base?: string;
15
+ };
16
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
17
+ base: string;
18
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
19
+ export default _default;
@@ -0,0 +1,23 @@
1
+ type __VLS_Props = {
2
+ /** The event the channels are for: `inbox.submission`. */
3
+ event: string;
4
+ disabled?: boolean;
5
+ /** Where the section is in the panel, for the link to it. */
6
+ base?: string;
7
+ addText?: string;
8
+ emptyText?: string;
9
+ };
10
+ type __VLS_PublicProps = {
11
+ modelValue?: number[] | null;
12
+ } & __VLS_Props;
13
+ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
14
+ "update:modelValue": (value: number[] | null) => any;
15
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
16
+ "onUpdate:modelValue"?: ((value: number[] | null) => any) | undefined;
17
+ }>, {
18
+ disabled: boolean;
19
+ base: string;
20
+ addText: string;
21
+ emptyText: string;
22
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
23
+ export default _default;
@@ -0,0 +1,15 @@
1
+ import { ChatRecipient } from './types';
2
+ type __VLS_Props = {
3
+ disabled?: boolean;
4
+ };
5
+ type __VLS_PublicProps = {
6
+ modelValue?: ChatRecipient[] | null;
7
+ } & __VLS_Props;
8
+ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
9
+ "update:modelValue": (value: ChatRecipient[] | null) => any;
10
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: ChatRecipient[] | null) => any) | undefined;
12
+ }>, {
13
+ disabled: boolean;
14
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
15
+ export default _default;
@@ -0,0 +1,15 @@
1
+ import { EmailRecipient } from './types';
2
+ type __VLS_Props = {
3
+ disabled?: boolean;
4
+ };
5
+ type __VLS_PublicProps = {
6
+ modelValue?: EmailRecipient[] | null;
7
+ } & __VLS_Props;
8
+ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
9
+ "update:modelValue": (value: EmailRecipient[] | null) => any;
10
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
11
+ "onUpdate:modelValue"?: ((value: EmailRecipient[] | null) => any) | undefined;
12
+ }>, {
13
+ disabled: boolean;
14
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
15
+ export default _default;