@webx-ui/module-notifications 0.2.1 → 0.3.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.
@@ -0,0 +1,1414 @@
1
+ import { defineComponent as L, useModel as q, computed as h, openBlock as p, createElementBlock as w, createVNode as g, unref as s, createBlock as k, withCtx as m, createTextVNode as y, toDisplayString as v, createCommentVNode as W, mergeModels as K, provide as xe, inject as $e, ref as j, onMounted as ne, isRef as Te, Fragment as z, renderList as M, createElementVNode as I, watch as Ce, onBeforeUnmount as Se, normalizeStyle as Ae, defineAsyncComponent as pe } from "vue";
2
+ import { useRouter as je } from "vue-router";
3
+ import { WxLink as We, useModal as Ne, WxDialog as Ve, WxSkeleton as Oe, WxAlert as D, WxEmpty as ze, WxCheckbox as Fe, WxText as N, WxBadge as ae, WxSpace as le, WxButton as V, createModal as Ee, WxInput as Z, WxAction as fe, WxIcon as H, toast as J, WxSelect as Me, useLocales as me, mustacheCompletions as Le, mustacheProblems as Pe, WxCodeEditor as Re, WxTooltip as Ue, confirm as Be, localizedValue as ie, WxCard as Ie } from "@webx-ui/core";
4
+ import { useAdmin as G, useTranslate as P, WxRelationsField as De, useErrorText as He } from "@webx-ui/module-admin";
5
+ import qe from "mustache";
6
+ const Ke = {
7
+ module: {
8
+ title: "Notifications",
9
+ channel: "Channel",
10
+ statuses: {
11
+ queued: "Queued",
12
+ sent: "Sent",
13
+ failed: "Failed",
14
+ skipped: "Skipped"
15
+ },
16
+ reasons: {
17
+ channel_deleted: "The channel is deleted",
18
+ channel_disabled: "The channel is switched off",
19
+ wrong_event: "The channel is for another event",
20
+ provider_missing: "The provider is not installed",
21
+ no_recipients: "The channel has no recipients",
22
+ no_address: "The event brought no address",
23
+ admin_deleted: "The administrator is deleted",
24
+ admin_inactive: "The administrator is switched off"
25
+ }
26
+ },
27
+ screen: {
28
+ "any-event": "Any event"
29
+ },
30
+ panel: {
31
+ channels: "Channels",
32
+ log: "Log",
33
+ bin: "Bin",
34
+ new: "New channel",
35
+ untitled: "Untitled channel",
36
+ "new-title": "New channel",
37
+ "new-help": "The kind is chosen once. An event is optional: with one, the editor knows its variables and only that event offers the channel.",
38
+ "new-provider": "Kind",
39
+ "new-event": "For the event",
40
+ "new-create": "Continue",
41
+ "any-event": "Any event",
42
+ "event-undeclared": "Event not declared",
43
+ "event-undeclared-text": "No installed module declares “:event” any more. The channel works as one for any event.",
44
+ "provider-undeclared": "Provider not installed",
45
+ "provider-undeclared-text": "The provider “:provider” is not installed on the site: the channel sends nothing.",
46
+ unreadable: "The channel's secrets cannot be read: the application key has changed. Enter them again.",
47
+ recipients: "Recipients: :count",
48
+ "never-sent": "Nothing sent yet",
49
+ off: "Off",
50
+ enable: "Enabled",
51
+ enabled: "Switched on.",
52
+ disabled: "Switched off.",
53
+ edit: "Edit",
54
+ copy: "Make a copy",
55
+ copied: "A copy is made, switched off: “:name”.",
56
+ "copied-from": "The secrets were copied from channel #:id. Replace them if this channel needs another bot or server.",
57
+ delete: "Delete",
58
+ "delete-title": "Delete “:title”?",
59
+ "delete-text": "The channel goes to the bin and sends nothing. The modules that chose it keep it, and it comes back to them when it is restored.",
60
+ deleted: "The channel is in the bin.",
61
+ restore: "Restore",
62
+ restored: "The channel is back.",
63
+ purge: "Delete for good",
64
+ "purge-title": "Delete “:title” for good?",
65
+ "purge-text": "The channel disappears from every module that chose it. Its lines in the log stay, without a link to it.",
66
+ purged: "The channel is deleted for good.",
67
+ cancel: "Cancel",
68
+ save: "Save",
69
+ saved: "Saved.",
70
+ "saved-warning": "Saved, but look: :warning",
71
+ "save-failed": "Not saved: look at the fields marked in red.",
72
+ "leave-title": "Leave without saving?",
73
+ "leave-text": "The changes to this channel will be lost.",
74
+ leave: "Leave",
75
+ "empty-channels-text": "A channel is where notifications go and how they read: a Telegram bot and its chats, or e-mail and its addresses.",
76
+ "empty-bin": "The bin is empty",
77
+ environment: "The site runs as “:environment”: notifications are sent all the same. Switch channels off on a copy of the site.",
78
+ "mode-after-response": "The site has no queue worker: notifications are sent right after the page answers, without retries in the background.",
79
+ "secret-set": "Set. Type a new one to replace it.",
80
+ forget: "Forget :field",
81
+ forgotten: ":field will be forgotten on save.",
82
+ check: "Check the connection",
83
+ "check-ok": "Connection works.",
84
+ test: "Send a test",
85
+ "test-title": "Send a test",
86
+ "test-help": "Sent now, past the queue, with the example values of the event — even through a channel that is switched off. What the form has is used, saved or not.",
87
+ "test-to": "To",
88
+ "test-everybody": "Everybody on the list",
89
+ "test-send": "Send",
90
+ "test-sent": "Sent to :recipient.",
91
+ "test-failed": "Not sent to :recipient: :error",
92
+ "test-none": "The channel has no recipients to send a test to.",
93
+ preview: "Preview",
94
+ "preview-help": "The message as it goes out, on the example values of the event.",
95
+ "preview-no-event": "For any event: the variables are empty here.",
96
+ "preview-subject": "Subject",
97
+ "preview-empty": "The message is empty.",
98
+ "preview-truncated": "Longer than :limit characters: Telegram gets it as plain text, cut to fit.",
99
+ "preview-unknown": "Empty in this message: :names.",
100
+ "preview-refused": "The template cannot be drawn:",
101
+ variables: "Variables",
102
+ "variables-help": "A click puts it where the cursor is; type {{ to see them in the editor.",
103
+ "variables-none": "A channel for any event knows no variables. Choose an event to get its list, or type the names it gives.",
104
+ "default-insert": "Insert the default template",
105
+ "default-title": "Replace the message with the default template?",
106
+ "default-text": "The subject and the template in every language become the ones the event suggests. What is written now is lost once you save.",
107
+ "default-replace": "Replace",
108
+ "default-inserted": "The event's default template is in the message. Save to keep it.",
109
+ "variable-list": "list of :fields",
110
+ "problem-unclosed": "The section {{#:name}} is not closed: end it with {{/:name}}.",
111
+ "problem-stray": "{{/:name}} closes a section that was never opened.",
112
+ "problem-unknown": "Not a variable of this event: :names.",
113
+ "problem-refused": ":tag is not available in a message template.",
114
+ "problem-broken": "A tag is not closed: end it with }}.",
115
+ "hint-variable": "variable",
116
+ "hint-list": "list",
117
+ "hint-field": "field of :list",
118
+ "hint-section": "shown when :name has a value",
119
+ "hint-inverted": "shown when :name is empty",
120
+ "hint-close": "closes :name",
121
+ "hint-comment": "a comment, never printed",
122
+ "hint-example": "Example: :example",
123
+ "add-chat": "Add a chat",
124
+ "chat-id": "Chat id",
125
+ "chat-label": "Label",
126
+ "find-chats": "Find chats",
127
+ "find-title": "Chats the bot has seen",
128
+ "find-help": "Write to the bot, or add it to a group and write there, then search again.",
129
+ "find-add": "Add the chosen",
130
+ "find-token": "Type the bot token first.",
131
+ "find-added": "Chats added: :count.",
132
+ "chat-private": "Private",
133
+ "chat-group": "Group",
134
+ "chat-supergroup": "Supergroup",
135
+ "chat-channel": "Channel",
136
+ addressee: "From the event: :label",
137
+ "add-admin": "Add an administrator",
138
+ "add-email": "Add an address",
139
+ "admin-unknown": "Administrator #:id",
140
+ remove: "Remove",
141
+ "no-recipients": "No recipients yet.",
142
+ "column-when": "When",
143
+ "column-channel": "Channel",
144
+ "column-recipient": "Recipient",
145
+ "column-status": "Status",
146
+ "column-attempts": "Attempts",
147
+ "all-statuses": "Any status",
148
+ "all-channels": "Any channel",
149
+ "with-tests": "Tests too",
150
+ "test-mark": "Test",
151
+ "cut-mark": "Cut",
152
+ "log-empty": "Nothing sent yet.",
153
+ retry: "Send again",
154
+ retried: "Queued again.",
155
+ "open-subject": "Open",
156
+ "unknown-variables": "Empty variables: :names",
157
+ "channel-gone": "deleted",
158
+ filters: "Filters",
159
+ "pick-channels": "Choose channels",
160
+ "set-up-channels": "Set up channels"
161
+ },
162
+ errors: {
163
+ "template-unclosed": "The section {{#:section}} is not closed: end it with {{/:section}}.",
164
+ "template-unexpected": "{{/:section}} closes a section that was never opened.",
165
+ "template-tag": "The tag {{:tag is not closed: end it with }}.",
166
+ "template-name": "{{:name}} is not a variable name: lowercase letters, digits and _, one dot at most.",
167
+ "template-partial": "Partials ({{>name}}) are not available in a message template.",
168
+ "template-delimiters": "Changing the delimiters ({{=<% %>=}}) is not available in a message template.",
169
+ "template-pragma": "Pragmas and blocks ({{%…}}, {{$…}}) are not available in a message template."
170
+ }
171
+ }, oe = /* @__PURE__ */ new WeakSet();
172
+ function R() {
173
+ try {
174
+ const { i18n: t } = G();
175
+ oe.has(t) || (t.defaults("webx-notifications", Ke), oe.add(t));
176
+ } catch {
177
+ }
178
+ }
179
+ const Ge = { class: "wx-notification-channels" }, Qe = /* @__PURE__ */ L({
180
+ name: "WxNotificationChannelsField",
181
+ __name: "ChannelsField",
182
+ props: /* @__PURE__ */ K({
183
+ event: {},
184
+ disabled: { type: Boolean, default: !1 },
185
+ base: { default: "/notifications" },
186
+ addText: { default: void 0 },
187
+ emptyText: { default: void 0 }
188
+ }, {
189
+ modelValue: { default: () => [] },
190
+ modelModifiers: {}
191
+ }),
192
+ emits: ["update:modelValue"],
193
+ setup(t) {
194
+ const e = t, a = q(t, "modelValue");
195
+ R();
196
+ const l = G(), n = P("webx-notifications"), i = h(() => `notify-${e.event.replace(/[._]/g, "-")}`), o = h(() => l.can("notifications.manage")), d = je(), _ = h(() => `${l.basePath}${e.base}`.replace(/\/{2,}/g, "/"));
197
+ function x(b) {
198
+ b.metaKey || b.ctrlKey || b.shiftKey || b.button !== 0 || (b.preventDefault(), d.push(e.base));
199
+ }
200
+ return (b, $) => (p(), w("div", Ge, [
201
+ g(s(De), {
202
+ modelValue: a.value,
203
+ "onUpdate:modelValue": $[0] || ($[0] = (C) => a.value = C),
204
+ target: i.value,
205
+ sortable: !1,
206
+ disabled: e.disabled,
207
+ "add-text": e.addText ?? s(n)("panel.pick-channels"),
208
+ "empty-text": e.emptyText
209
+ }, null, 8, ["modelValue", "target", "disabled", "add-text", "empty-text"]),
210
+ o.value ? (p(), k(s(We), {
211
+ key: 0,
212
+ href: _.value,
213
+ size: "sm",
214
+ onClick: x
215
+ }, {
216
+ default: m(() => [
217
+ y(v(s(n)("panel.set-up-channels")), 1)
218
+ ]),
219
+ _: 1
220
+ }, 8, ["href"])) : W("", !0)
221
+ ]));
222
+ }
223
+ }), U = (t, e) => {
224
+ const a = t.__vccOpts || t;
225
+ for (const [l, n] of e)
226
+ a[l] = n;
227
+ return a;
228
+ }, Xe = /* @__PURE__ */ U(Qe, [["__scopeId", "data-v-e0a57880"]]);
229
+ function he() {
230
+ const t = j(null), e = /* @__PURE__ */ new Map();
231
+ return {
232
+ focused: t,
233
+ inserters: e,
234
+ insert: (a) => (e.get(t.value ?? "") ?? e.get("template"))?.(a)
235
+ };
236
+ }
237
+ const ve = /* @__PURE__ */ Symbol("wx-notifications-channel");
238
+ function Qt(t, e, a) {
239
+ const l = {
240
+ meta: t,
241
+ values: e,
242
+ id: a,
243
+ provider: h(
244
+ () => t.value?.providers.find((n) => n.key === e.value.provider) ?? null
245
+ ),
246
+ event: h(() => t.value?.events.find((n) => n.key === e.value.event) ?? null),
247
+ ...he()
248
+ };
249
+ return xe(ve, l), l;
250
+ }
251
+ function Q() {
252
+ return $e(ve, null) ?? {
253
+ meta: j(null),
254
+ values: j({}),
255
+ id: j(null),
256
+ provider: h(() => null),
257
+ event: h(() => null),
258
+ ...he()
259
+ };
260
+ }
261
+ const Ze = "notifications";
262
+ function Je(t) {
263
+ const e = new URLSearchParams();
264
+ for (const [l, n] of Object.entries(t))
265
+ n == null || n === "" || e.set(l, typeof n == "boolean" ? n ? "1" : "0" : String(n));
266
+ const a = e.toString();
267
+ return a === "" ? "" : `?${a}`;
268
+ }
269
+ function be(t) {
270
+ const e = `${t.apiPath}/${Ze}`, a = (n) => n.data, l = (n) => n === null ? e : `${e}/channels/${n}`;
271
+ return {
272
+ meta: () => t.http.get(`${e}/meta`).then(a),
273
+ channels: (n = {}) => {
274
+ const i = new URLSearchParams();
275
+ n.trashed && i.set("trashed", "1"), n.event && i.set("event", n.event);
276
+ const o = i.toString();
277
+ return t.http.get(`${e}/channels${o === "" ? "" : `?${o}`}`);
278
+ },
279
+ get: (n) => t.http.get(`${e}/channels/${n}`).then(a),
280
+ create: (n) => t.http.post(`${e}/channels`, { values: n }).then(a),
281
+ save: (n, i) => t.http.put(`${e}/channels/${n}`, { values: i }).then(a),
282
+ remove: (n) => t.http.delete(`${e}/channels/${n}`).then(() => {
283
+ }),
284
+ restore: (n) => t.http.post(`${e}/channels/${n}/restore`, {}).then(a),
285
+ purge: (n) => t.http.delete(`${e}/channels/${n}/purge`).then(() => {
286
+ }),
287
+ copy: (n, i) => t.http.post(`${e}/channels/${n}/copy`, i ? { name: i } : {}).then(a),
288
+ test: (n, i, o) => t.http.post(`${l(n)}/test`, {
289
+ values: i,
290
+ ...o ? { recipient: o } : {}
291
+ }).then((d) => d.data.results),
292
+ preview: (n, i, o) => t.http.post(`${l(n)}/preview`, { values: i, locale: o }).then(a),
293
+ check: (n, i) => t.http.post(`${e}/check`, { values: i, ...n ? { channel: n } : {} }).then(a),
294
+ findRecipients: ({ provider: n, channel: i, token: o }) => t.http.post(
295
+ `${e}/find-recipients`,
296
+ { provider: n, ...i ? { channel: i } : {}, ...o ? { token: o } : {} }
297
+ ).then(a),
298
+ administrators: () => t.http.get(`${e}/administrators`).then(a),
299
+ deliveries: (n = {}) => t.http.get(`${e}/deliveries${Je(n)}`),
300
+ retry: (n) => t.http.post(`${e}/deliveries/${n}/retry`, {}).then(a)
301
+ };
302
+ }
303
+ const Ye = {
304
+ key: 3,
305
+ class: "wx-notifications-found"
306
+ }, et = { class: "wx-notifications-found__text" }, tt = /* @__PURE__ */ L({
307
+ name: "WxNotificationsFindChats",
308
+ __name: "FindChatsDialog",
309
+ props: {
310
+ channel: { default: null },
311
+ token: { default: "" },
312
+ chosen: { default: () => [] }
313
+ },
314
+ setup(t) {
315
+ const e = t, { open: a, resolve: l, dismiss: n } = Ne(), i = be(G());
316
+ R();
317
+ const o = P("webx-notifications"), d = He(), _ = j([]), x = j(null), b = j(null), $ = j(!0), C = j(/* @__PURE__ */ new Set());
318
+ async function S() {
319
+ $.value = !0, b.value = null;
320
+ try {
321
+ const r = await i.findRecipients({
322
+ provider: "telegram",
323
+ channel: e.channel,
324
+ token: e.token.trim() === "" ? void 0 : e.token.trim()
325
+ });
326
+ _.value = r.recipients, x.value = r.hint;
327
+ } catch (r) {
328
+ b.value = d(r);
329
+ } finally {
330
+ $.value = !1;
331
+ }
332
+ }
333
+ ne(() => {
334
+ S();
335
+ });
336
+ const O = h(() => _.value.filter((r) => !e.chosen.includes(r.id)));
337
+ function T(r, c) {
338
+ const u = new Set(C.value);
339
+ c ? u.add(r) : u.delete(r), C.value = u;
340
+ }
341
+ function f() {
342
+ l(O.value.filter((r) => C.value.has(r.id)));
343
+ }
344
+ return (r, c) => (p(), k(s(Ve), {
345
+ open: s(a),
346
+ "onUpdate:open": c[1] || (c[1] = (u) => Te(a) ? a.value = u : null),
347
+ title: s(o)("panel.find-title"),
348
+ width: 480
349
+ }, {
350
+ footer: m(() => [
351
+ g(s(le), { size: "sm" }, {
352
+ default: m(() => [
353
+ g(s(V), {
354
+ variant: "outline",
355
+ disabled: $.value,
356
+ onClick: S
357
+ }, {
358
+ default: m(() => [
359
+ y(v(s(o)("panel.find-chats")), 1)
360
+ ]),
361
+ _: 1
362
+ }, 8, ["disabled"]),
363
+ g(s(V), {
364
+ variant: "outline",
365
+ onClick: c[0] || (c[0] = (u) => s(n)())
366
+ }, {
367
+ default: m(() => [
368
+ y(v(s(o)("panel.cancel")), 1)
369
+ ]),
370
+ _: 1
371
+ }),
372
+ g(s(V), {
373
+ type: "primary",
374
+ disabled: C.value.size === 0,
375
+ onClick: f
376
+ }, {
377
+ default: m(() => [
378
+ y(v(s(o)("panel.find-add")), 1)
379
+ ]),
380
+ _: 1
381
+ }, 8, ["disabled"])
382
+ ]),
383
+ _: 1
384
+ })
385
+ ]),
386
+ default: m(() => [
387
+ $.value ? (p(), k(s(Oe), {
388
+ key: 0,
389
+ rows: 3
390
+ })) : b.value ? (p(), k(s(D), {
391
+ key: 1,
392
+ type: "danger",
393
+ variant: "soft",
394
+ description: b.value
395
+ }, null, 8, ["description"])) : _.value.length === 0 ? (p(), k(s(ze), {
396
+ key: 2,
397
+ title: s(o)("panel.find-title"),
398
+ description: x.value ?? s(o)("panel.find-help")
399
+ }, null, 8, ["title", "description"])) : (p(), w("ul", Ye, [
400
+ (p(!0), w(z, null, M(_.value, (u) => (p(), w("li", {
401
+ key: u.id,
402
+ class: "wx-notifications-found__row"
403
+ }, [
404
+ g(s(Fe), {
405
+ "model-value": e.chosen.includes(u.id) || C.value.has(u.id),
406
+ disabled: e.chosen.includes(u.id),
407
+ "onUpdate:modelValue": (A) => T(u.id, A)
408
+ }, {
409
+ default: m(() => [
410
+ I("span", et, [
411
+ g(s(N), { truncate: "" }, {
412
+ default: m(() => [
413
+ y(v(u.title), 1)
414
+ ]),
415
+ _: 2
416
+ }, 1024),
417
+ g(s(N), {
418
+ size: "sm",
419
+ tone: "muted",
420
+ mono: "",
421
+ truncate: ""
422
+ }, {
423
+ default: m(() => [
424
+ y(v([u.id, u.username].filter(Boolean).join(" · ")), 1)
425
+ ]),
426
+ _: 2
427
+ }, 1024)
428
+ ])
429
+ ]),
430
+ _: 2
431
+ }, 1032, ["model-value", "disabled", "onUpdate:modelValue"]),
432
+ g(s(ae), null, {
433
+ default: m(() => [
434
+ y(v(s(o)(`panel.chat-${u.type}`)), 1)
435
+ ]),
436
+ _: 2
437
+ }, 1024)
438
+ ]))), 128))
439
+ ]))
440
+ ]),
441
+ _: 1
442
+ }, 8, ["open", "title"]));
443
+ }
444
+ }), nt = /* @__PURE__ */ U(tt, [["__scopeId", "data-v-71616d40"]]);
445
+ function at(t) {
446
+ return (t?.variables ?? []).map((e) => ({
447
+ name: e.name,
448
+ label: e.label,
449
+ example: e.example,
450
+ fields: e.fields.length > 0 ? e.fields : void 0
451
+ }));
452
+ }
453
+ function lt(t, e = "value") {
454
+ const a = t.name.endsWith(".*") ? `${t.name.slice(0, -2)}.name` : t.name;
455
+ if ((t.fields?.length ?? 0) > 0) {
456
+ const l = (t.fields ?? []).map((n) => `{{${n.name}}}`).join(" ");
457
+ return `{{#${a}}}
458
+ ${l}
459
+ {{/${a}}}`;
460
+ }
461
+ return e === "has" ? `{{#${a}}}{{${a}}}{{/${a}}}` : e === "empty" ? `{{^${a}}}{{/${a}}}` : `{{${a}}}`;
462
+ }
463
+ function ge(t, e) {
464
+ return (t?.variables ?? []).filter((a) => a.address === e);
465
+ }
466
+ const st = { class: "wx-notifications-recipients" }, it = /* @__PURE__ */ L({
467
+ name: "WxNotificationsChatsField",
468
+ __name: "ChatsField",
469
+ props: /* @__PURE__ */ K({
470
+ disabled: { type: Boolean, default: !1 }
471
+ }, {
472
+ modelValue: { default: () => [] },
473
+ modelModifiers: {}
474
+ }),
475
+ emits: ["update:modelValue"],
476
+ setup(t) {
477
+ const e = t, a = q(t, "modelValue");
478
+ R();
479
+ const l = P("webx-notifications"), n = Q(), i = Ee(nt), o = h(() => Array.isArray(a.value) ? a.value : []), d = h(() => ge(n.event.value, "telegram")), _ = h(
480
+ () => d.value.filter((f) => !o.value.some((r) => r.variable === f.name))
481
+ );
482
+ function x(f) {
483
+ return d.value.find((r) => r.name === f)?.label ?? `{{${f}}}`;
484
+ }
485
+ function b(f, r) {
486
+ a.value = o.value.map((c, u) => u === f ? { ...c, ...r } : c);
487
+ }
488
+ function $(f) {
489
+ a.value = [...o.value, f];
490
+ }
491
+ function C(f) {
492
+ a.value = o.value.filter((r, c) => c !== f);
493
+ }
494
+ const S = h(() => {
495
+ const f = n.values.value.token;
496
+ return typeof f == "string" ? f : "";
497
+ }), O = h(
498
+ () => S.value.trim() !== "" || n.id.value !== null && n.values.value.provider === "telegram"
499
+ );
500
+ async function T() {
501
+ if (!O.value) {
502
+ J.warning(l("panel.find-token"));
503
+ return;
504
+ }
505
+ const f = await i({
506
+ channel: n.id.value,
507
+ token: S.value,
508
+ chosen: o.value.map((r) => r.chat_id ?? "").filter(Boolean)
509
+ });
510
+ !f || f.length === 0 || (a.value = [...o.value, ...f.map((r) => ({ chat_id: r.id, label: r.title }))], J.success(l("panel.find-added", { count: String(f.length) })));
511
+ }
512
+ return (f, r) => (p(), w("div", st, [
513
+ o.value.length === 0 ? (p(), k(s(N), {
514
+ key: 0,
515
+ size: "sm",
516
+ tone: "placeholder"
517
+ }, {
518
+ default: m(() => [
519
+ y(v(s(l)("panel.no-recipients")), 1)
520
+ ]),
521
+ _: 1
522
+ })) : W("", !0),
523
+ (p(!0), w(z, null, M(o.value, (c, u) => (p(), w("div", {
524
+ key: u,
525
+ class: "wx-notifications-recipients__row"
526
+ }, [
527
+ c.variable ? (p(), k(s(ae), {
528
+ key: 0,
529
+ type: "primary",
530
+ class: "wx-notifications-recipients__addressee"
531
+ }, {
532
+ default: m(() => [
533
+ y(v(s(l)("panel.addressee", { label: x(c.variable) })), 1)
534
+ ]),
535
+ _: 2
536
+ }, 1024)) : (p(), w(z, { key: 1 }, [
537
+ g(s(Z), {
538
+ class: "wx-notifications-recipients__id",
539
+ "model-value": c.chat_id ?? "",
540
+ placeholder: s(l)("panel.chat-id"),
541
+ "aria-label": s(l)("panel.chat-id"),
542
+ disabled: e.disabled,
543
+ inputmode: "text",
544
+ "onUpdate:modelValue": (A) => b(u, { chat_id: String(A ?? "") })
545
+ }, null, 8, ["model-value", "placeholder", "aria-label", "disabled", "onUpdate:modelValue"]),
546
+ g(s(Z), {
547
+ class: "wx-notifications-recipients__label",
548
+ "model-value": c.label ?? "",
549
+ placeholder: s(l)("panel.chat-label"),
550
+ "aria-label": s(l)("panel.chat-label"),
551
+ disabled: e.disabled,
552
+ "onUpdate:modelValue": (A) => b(u, { label: String(A ?? "") })
553
+ }, null, 8, ["model-value", "placeholder", "aria-label", "disabled", "onUpdate:modelValue"])
554
+ ], 64)),
555
+ e.disabled ? W("", !0) : (p(), k(s(fe), {
556
+ key: 2,
557
+ icon: "trash",
558
+ tone: "danger",
559
+ title: s(l)("panel.remove"),
560
+ onClick: (A) => C(u)
561
+ }, null, 8, ["title", "onClick"]))
562
+ ]))), 128)),
563
+ e.disabled ? W("", !0) : (p(), k(s(le), {
564
+ key: 1,
565
+ size: "sm",
566
+ wrap: ""
567
+ }, {
568
+ default: m(() => [
569
+ g(s(V), {
570
+ variant: "outline",
571
+ size: "sm",
572
+ onClick: r[0] || (r[0] = (c) => $({ chat_id: "", label: "" }))
573
+ }, {
574
+ icon: m(() => [
575
+ g(s(H), { name: "plus" })
576
+ ]),
577
+ default: m(() => [
578
+ y(" " + v(s(l)("panel.add-chat")), 1)
579
+ ]),
580
+ _: 1
581
+ }),
582
+ g(s(V), {
583
+ variant: "outline",
584
+ size: "sm",
585
+ onClick: T
586
+ }, {
587
+ icon: m(() => [
588
+ g(s(H), { name: "search" })
589
+ ]),
590
+ default: m(() => [
591
+ y(" " + v(s(l)("panel.find-chats")), 1)
592
+ ]),
593
+ _: 1
594
+ }),
595
+ (p(!0), w(z, null, M(_.value, (c) => (p(), k(s(V), {
596
+ key: c.name,
597
+ variant: "outline",
598
+ size: "sm",
599
+ onClick: (u) => $({ variable: c.name })
600
+ }, {
601
+ default: m(() => [
602
+ y(v(s(l)("panel.addressee", { label: c.label })), 1)
603
+ ]),
604
+ _: 2
605
+ }, 1032, ["onClick"]))), 128))
606
+ ]),
607
+ _: 1
608
+ }))
609
+ ]));
610
+ }
611
+ }), ot = /* @__PURE__ */ U(it, [["__scopeId", "data-v-00cd60ee"]]), rt = { class: "wx-notifications-recipients" }, ct = /* @__PURE__ */ L({
612
+ name: "WxNotificationsEmailsField",
613
+ __name: "EmailsField",
614
+ props: /* @__PURE__ */ K({
615
+ disabled: { type: Boolean, default: !1 }
616
+ }, {
617
+ modelValue: { default: () => [] },
618
+ modelModifiers: {}
619
+ }),
620
+ emits: ["update:modelValue"],
621
+ setup(t) {
622
+ const e = t, a = q(t, "modelValue");
623
+ R();
624
+ const l = P("webx-notifications"), n = Q(), i = G(), o = j([]);
625
+ ne(async () => {
626
+ try {
627
+ o.value = await be(i).administrators();
628
+ } catch {
629
+ }
630
+ });
631
+ const d = h(() => Array.isArray(a.value) ? a.value : []), _ = h(
632
+ () => o.value.map((f) => ({ value: f.id, label: `${f.name} · ${f.email}` }))
633
+ ), x = h(() => ge(n.event.value, "email")), b = h(
634
+ () => x.value.filter((f) => !d.value.some((r) => r.variable === f.name))
635
+ );
636
+ function $(f) {
637
+ return x.value.find((r) => r.name === f)?.label ?? `{{${f}}}`;
638
+ }
639
+ function C(f, r) {
640
+ a.value = d.value.map((c, u) => u === f ? r : c);
641
+ }
642
+ function S(f) {
643
+ a.value = [...d.value, f];
644
+ }
645
+ function O(f) {
646
+ a.value = d.value.filter((r, c) => c !== f);
647
+ }
648
+ function T(f) {
649
+ return _.value.some((r) => r.value === f) ? _.value : [..._.value, { value: f, label: l("panel.admin-unknown", { id: String(f) }) }];
650
+ }
651
+ return (f, r) => (p(), w("div", rt, [
652
+ d.value.length === 0 ? (p(), k(s(N), {
653
+ key: 0,
654
+ size: "sm",
655
+ tone: "placeholder"
656
+ }, {
657
+ default: m(() => [
658
+ y(v(s(l)("panel.no-recipients")), 1)
659
+ ]),
660
+ _: 1
661
+ })) : W("", !0),
662
+ (p(!0), w(z, null, M(d.value, (c, u) => (p(), w("div", {
663
+ key: u,
664
+ class: "wx-notifications-recipients__row"
665
+ }, [
666
+ c.variable ? (p(), k(s(ae), {
667
+ key: 0,
668
+ type: "primary",
669
+ class: "wx-notifications-recipients__wide"
670
+ }, {
671
+ default: m(() => [
672
+ y(v(s(l)("panel.addressee", { label: $(c.variable) })), 1)
673
+ ]),
674
+ _: 2
675
+ }, 1024)) : c.admin_id !== void 0 ? (p(), k(s(Me), {
676
+ key: 1,
677
+ class: "wx-notifications-recipients__wide",
678
+ "model-value": c.admin_id,
679
+ options: T(c.admin_id),
680
+ disabled: e.disabled,
681
+ "onUpdate:modelValue": (A) => C(u, { admin_id: Number(A) })
682
+ }, null, 8, ["model-value", "options", "disabled", "onUpdate:modelValue"])) : (p(), k(s(Z), {
683
+ key: 2,
684
+ class: "wx-notifications-recipients__wide",
685
+ type: "email",
686
+ "model-value": c.email ?? "",
687
+ placeholder: "manager@site.test",
688
+ disabled: e.disabled,
689
+ "onUpdate:modelValue": (A) => C(u, { email: String(A ?? "") })
690
+ }, null, 8, ["model-value", "disabled", "onUpdate:modelValue"])),
691
+ e.disabled ? W("", !0) : (p(), k(s(fe), {
692
+ key: 3,
693
+ icon: "trash",
694
+ tone: "danger",
695
+ title: s(l)("panel.remove"),
696
+ onClick: (A) => O(u)
697
+ }, null, 8, ["title", "onClick"]))
698
+ ]))), 128)),
699
+ e.disabled ? W("", !0) : (p(), k(s(le), {
700
+ key: 1,
701
+ size: "sm",
702
+ wrap: ""
703
+ }, {
704
+ default: m(() => [
705
+ g(s(V), {
706
+ variant: "outline",
707
+ size: "sm",
708
+ disabled: _.value.length === 0,
709
+ onClick: r[0] || (r[0] = (c) => S({ admin_id: Number(_.value[0]?.value) }))
710
+ }, {
711
+ icon: m(() => [
712
+ g(s(H), { name: "user" })
713
+ ]),
714
+ default: m(() => [
715
+ y(" " + v(s(l)("panel.add-admin")), 1)
716
+ ]),
717
+ _: 1
718
+ }, 8, ["disabled"]),
719
+ g(s(V), {
720
+ variant: "outline",
721
+ size: "sm",
722
+ onClick: r[1] || (r[1] = (c) => S({ email: "" }))
723
+ }, {
724
+ icon: m(() => [
725
+ g(s(H), { name: "mail" })
726
+ ]),
727
+ default: m(() => [
728
+ y(" " + v(s(l)("panel.add-email")), 1)
729
+ ]),
730
+ _: 1
731
+ }),
732
+ (p(!0), w(z, null, M(b.value, (c) => (p(), k(s(V), {
733
+ key: c.name,
734
+ variant: "outline",
735
+ size: "sm",
736
+ onClick: (u) => S({ variable: c.name })
737
+ }, {
738
+ default: m(() => [
739
+ y(v(s(l)("panel.addressee", { label: c.label })), 1)
740
+ ]),
741
+ _: 2
742
+ }, 1032, ["onClick"]))), 128))
743
+ ]),
744
+ _: 1
745
+ }))
746
+ ]));
747
+ }
748
+ }), dt = /* @__PURE__ */ U(ct, [["__scopeId", "data-v-ae639366"]]);
749
+ function we(t, e) {
750
+ return !t || !e ? null : t.sample[e] ?? t.sample["*"] ?? null;
751
+ }
752
+ function B(t) {
753
+ return t == null ? !0 : typeof t == "string" ? t.trim() === "" : typeof t == "object" ? Object.values(t).every((e) => B(e)) : !1;
754
+ }
755
+ function ye(t, e, a) {
756
+ return {
757
+ ...t,
758
+ template: { ...e.template },
759
+ ...a && e.subject !== null ? { subject: { ...e.subject } } : {}
760
+ };
761
+ }
762
+ function Xt(t, e, a) {
763
+ Ce(
764
+ () => t.values.value.event,
765
+ (l, n) => {
766
+ if (e.value || l === n) return;
767
+ const i = we(t.event.value, t.provider.value?.key), o = t.provider.value?.subject ?? !1, d = t.values.value;
768
+ i === null || !B(d.template) || o && !B(d.subject) || (t.values.value = ye(d, i, o), a());
769
+ },
770
+ { flush: "sync" }
771
+ );
772
+ }
773
+ class E extends Error {
774
+ constructor(e, a = {}) {
775
+ super(e), this.key = e, this.replace = a, this.name = "TemplateRefusal";
776
+ }
777
+ key;
778
+ replace;
779
+ }
780
+ const ut = /^[a-z0-9_]+(\.[a-z0-9_]+)?$/;
781
+ function _e(t) {
782
+ return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
783
+ }
784
+ function re(t) {
785
+ return t.replace(/[\r\n]+/g, " ");
786
+ }
787
+ function pt(t, e = "") {
788
+ return se(t, e) ? ft : t === "telegram" ? _e : (a) => a;
789
+ }
790
+ function se(t, e) {
791
+ return t === "email" && /^\s*<[a-zA-Z]/.test(e);
792
+ }
793
+ function ft(t) {
794
+ return _e(t).replace(/\r\n|\r|\n/g, "<br>");
795
+ }
796
+ function X(t) {
797
+ const e = document.createElement("textarea");
798
+ return e.innerHTML = t, e.value;
799
+ }
800
+ const mt = "p|h[1-6]|table|ul|ol|blockquote|pre", ht = "tr|div";
801
+ function vt(t) {
802
+ let e = t.replace(/[ \t\r\n\f]+/g, " ");
803
+ return e = e.replace(
804
+ /<a\b[^>]*?\bhref\s*=\s*"([^"]*)"[^>]*>([\s\S]*?)<\/a\s*>/gi,
805
+ (l, n, i) => {
806
+ const o = X(n), d = X(i.replace(/<[^>]*>/g, "")).trim();
807
+ return d === "" || d === o ? o : /^(https?:|mailto:)/i.test(o) ? `${i} (${n})` : i;
808
+ }
809
+ ), e = e.replace(/<br\s*\/?>/gi, `
810
+ `), e = e.replace(/<\/t[dh]\s*>\s*(?=<t[dh][\s>])/gi, ": "), e = e.replace(/<li\b[^>]*>/gi, `
811
+ - `), e = e.replace(new RegExp(`<hr\\b[^>]*>|</?(?:${mt})\\b[^>]*>`, "gi"), `
812
+
813
+ `), e = e.replace(new RegExp(`<div\\b[^>]*>|</(?:${ht})\\s*>`, "gi"), `
814
+ `), e = X(e.replace(/<[^>]*>/g, "")), e.split(`
815
+ `).map((l) => l.replace(/ {2,}/g, " ").trim()).join(`
816
+ `).replace(/\n{3,}/g, `
817
+
818
+ `).trim();
819
+ }
820
+ function bt(t) {
821
+ try {
822
+ return qe.parse(t, ["{{", "}}"]);
823
+ } catch (e) {
824
+ const a = e instanceof Error ? e.message : String(e), l = /section "([^"]*)"/.exec(a)?.[1] ?? "";
825
+ if (a.startsWith("Unopened section"))
826
+ throw new E("template-unexpected", { section: l });
827
+ if (a.startsWith("Unclosed section"))
828
+ throw new E("template-unclosed", { section: l });
829
+ const n = Number(/at (\d+)/.exec(a)?.[1] ?? t.lastIndexOf("{{")), i = t.slice(n).replace(/^\{\{\{?[#^/!&>=]?/, "").trim();
830
+ throw new E("template-tag", { tag: i });
831
+ }
832
+ }
833
+ function ke(t) {
834
+ for (const e of t) {
835
+ const [a, l] = e;
836
+ if (a === ">") throw new E("template-partial");
837
+ if (a === "=") throw new E("template-delimiters");
838
+ if (a === "text" || a === "!") continue;
839
+ const n = l.trim();
840
+ if (n.startsWith("<")) throw new E("template-partial");
841
+ if (n.startsWith("%") || n.startsWith("$")) throw new E("template-pragma");
842
+ if (!ut.test(n)) throw new E("template-name", { name: n });
843
+ e[4] && ke(e[4]);
844
+ }
845
+ }
846
+ function gt(t) {
847
+ const e = {};
848
+ for (const [a, l] of Object.entries(t)) {
849
+ if (!a.includes(".")) {
850
+ e[a] = l;
851
+ continue;
852
+ }
853
+ const [n, ...i] = a.split("."), o = n, d = e[o];
854
+ (d === void 0 || F(d)) && (e[o] = { ...F(d) ? d : {}, [i.join(".")]: l });
855
+ }
856
+ return e;
857
+ }
858
+ function F(t) {
859
+ return typeof t == "object" && t !== null && !Array.isArray(t);
860
+ }
861
+ function ce(t) {
862
+ return t == null || t === !1 || t === "" || t === "0" || t === 0 ? !0 : Array.isArray(t) ? t.length === 0 : F(t) ? Object.keys(t).length === 0 : !1;
863
+ }
864
+ function wt(t, e) {
865
+ const [a, ...l] = e.split(".");
866
+ let n;
867
+ for (let i = t.length - 1; i >= 0; i--) {
868
+ const o = t[i];
869
+ if (F(o) && Object.prototype.hasOwnProperty.call(o, a)) {
870
+ n = o[a];
871
+ break;
872
+ }
873
+ }
874
+ for (const i of l) {
875
+ if (n === "" || n === void 0) return n;
876
+ n = F(n) && Object.prototype.hasOwnProperty.call(n, i) ? n[i] : "";
877
+ }
878
+ return n;
879
+ }
880
+ function yt(t) {
881
+ return typeof t == "string" ? t : typeof t == "number" ? String(t) : t === !0 ? "1" : "";
882
+ }
883
+ function Y(t, e, a) {
884
+ let l = "";
885
+ for (const n of t) {
886
+ const [i, o] = n;
887
+ if (i === "text") {
888
+ l += o;
889
+ continue;
890
+ }
891
+ if (i === "!") continue;
892
+ const d = wt(e, o.trim());
893
+ if (i === "name" || i === "&") {
894
+ l += F(d) || Array.isArray(d) ? "" : a(yt(d));
895
+ continue;
896
+ }
897
+ const _ = n[4] ?? [];
898
+ if (i === "#" && !ce(d))
899
+ for (const x of Array.isArray(d) ? d : [d])
900
+ l += Y(_, [...e, x], a);
901
+ i === "^" && ce(d) && (l += Y(_, e, a));
902
+ }
903
+ return l;
904
+ }
905
+ function ee(t, e = [], a = []) {
906
+ for (const l of t) {
907
+ const [n, i] = l;
908
+ if (n === "text" || n === "!") continue;
909
+ const o = i.trim();
910
+ a.push({ name: o, sections: e }), n === "#" && ee(l[4] ?? [], [...e, o], a), n === "^" && ee(l[4] ?? [], e, a);
911
+ }
912
+ return a;
913
+ }
914
+ function de(t, e) {
915
+ const [a, ...l] = e.split(".");
916
+ for (const n of [...t].reverse()) {
917
+ if (!F(n) || !Object.prototype.hasOwnProperty.call(n, a)) continue;
918
+ let i = n[a];
919
+ for (const o of l) {
920
+ if (!F(i) || !Object.prototype.hasOwnProperty.call(i, o)) return null;
921
+ i = i[o];
922
+ }
923
+ return i ?? null;
924
+ }
925
+ return null;
926
+ }
927
+ function _t(t, e, a) {
928
+ const l = [t];
929
+ for (const n of a) {
930
+ const i = de(l, n);
931
+ Array.isArray(i) ? l.push(Object.assign({}, ...i.filter(F))) : F(i) && l.push(i);
932
+ }
933
+ return de(l, e) !== null;
934
+ }
935
+ function kt(t, e, a) {
936
+ for (const l of [...a].reverse()) {
937
+ const n = t.variables.find((i) => i.name === l);
938
+ if (n && n.fields.length > 0 && n.fields.some((i) => i.name === e))
939
+ return !0;
940
+ }
941
+ return t.variables.some(
942
+ (l) => l.name === e || l.name.endsWith(".*") && e.startsWith(l.name.slice(0, -1))
943
+ );
944
+ }
945
+ function ue(t, e, a, l) {
946
+ const n = bt(t);
947
+ ke(n);
948
+ const i = gt(e), o = /* @__PURE__ */ new Set();
949
+ for (const d of ee(n))
950
+ !_t(i, d.name, d.sections) && !l?.(d.name, d.sections) && o.add(d.name);
951
+ return { text: Y(n, [i], a), unknown: [...o] };
952
+ }
953
+ function xt(t) {
954
+ const e = {};
955
+ for (const a of t?.variables ?? [])
956
+ a.name.endsWith(".*") || (e[a.name] = a.example);
957
+ return e;
958
+ }
959
+ function $t(t) {
960
+ return new DOMParser().parseFromString(`<body>${t}</body>`, "text/html").body.textContent ?? "";
961
+ }
962
+ function Tt(t) {
963
+ const e = se(t.provider, t.template), a = pt(t.provider, t.template), l = t.event ?? null, n = l === null ? void 0 : (b, $) => kt(l, b, $), i = ue(t.template, t.values, a, n);
964
+ let o = null, d = i.unknown;
965
+ if (t.hasSubject) {
966
+ const b = ue(t.subject ?? "", t.values, re, n);
967
+ o = re(b.text).trim(), d = [.../* @__PURE__ */ new Set([...d, ...b.unknown])];
968
+ }
969
+ const _ = e ? vt(i.text) : t.provider === "telegram" ? $t(i.text) : i.text, x = t.limit ?? null;
970
+ if (x !== null && [..._].length > x) {
971
+ const b = `${[..._].slice(0, x - 1).join("")}…`;
972
+ return { subject: o, body: a(b), plain: b, truncated: !0, unknown: d, html: e };
973
+ }
974
+ return { subject: o, body: i.text, plain: _, truncated: !1, unknown: d, html: e };
975
+ }
976
+ const Ct = { class: "wx-notifications-template" }, St = {
977
+ key: 0,
978
+ class: "wx-notifications-template__variables"
979
+ }, At = { class: "wx-notifications-template__chips" }, jt = { class: "wx-notifications-template__name" }, Wt = {
980
+ key: 2,
981
+ class: "wx-notifications-template__default"
982
+ }, Nt = /* @__PURE__ */ L({
983
+ name: "WxNotificationsTemplateField",
984
+ __name: "TemplateField",
985
+ props: /* @__PURE__ */ K({
986
+ localized: { type: Boolean, default: !1 },
987
+ disabled: { type: Boolean, default: void 0 },
988
+ minHeight: { default: "200px" },
989
+ singleLine: { type: Boolean, default: !1 },
990
+ part: { default: "template" },
991
+ chips: { type: Boolean, default: !0 }
992
+ }, {
993
+ modelValue: { default: "" },
994
+ modelModifiers: {}
995
+ }),
996
+ emits: ["update:modelValue"],
997
+ setup(t) {
998
+ const e = t, a = q(t, "modelValue");
999
+ R();
1000
+ const l = P("webx-notifications"), n = Q(), i = me(), o = j(null), d = h(() => at(n.event.value)), _ = h(
1001
+ () => Le(d.value, {
1002
+ variable: l("panel.hint-variable"),
1003
+ list: l("panel.hint-list"),
1004
+ field: l("panel.hint-field"),
1005
+ section: l("panel.hint-section"),
1006
+ inverted: l("panel.hint-inverted"),
1007
+ close: l("panel.hint-close"),
1008
+ comment: l("panel.hint-comment"),
1009
+ example: l("panel.hint-example")
1010
+ })
1011
+ ), x = h(() => {
1012
+ const r = a.value;
1013
+ if (r == null) return "";
1014
+ if (typeof r == "string") return r;
1015
+ const c = i.active.value || i.list.value[0]?.code || "";
1016
+ return r[c] ?? "";
1017
+ }), b = h(() => {
1018
+ if (e.singleLine) return "mustache";
1019
+ const r = n.provider.value?.key ?? "";
1020
+ return r === "telegram" || se(r, x.value) ? "mustache-html" : "mustache";
1021
+ }), $ = h(
1022
+ () => Pe(x.value, n.event.value === null ? void 0 : d.value)
1023
+ ), C = h(() => {
1024
+ const r = $.value;
1025
+ return [
1026
+ ...r.unclosed.map((c) => l("panel.problem-unclosed", { name: c })),
1027
+ ...r.stray.map((c) => l("panel.problem-stray", { name: c })),
1028
+ ...r.refused.map((c) => l("panel.problem-refused", { tag: c })),
1029
+ ...r.broken ? [l("panel.problem-broken")] : [],
1030
+ ...r.unknown.length > 0 ? [
1031
+ l("panel.problem-unknown", {
1032
+ names: r.unknown.map((c) => `{{${c}}}`).join(", ")
1033
+ })
1034
+ ] : []
1035
+ ];
1036
+ });
1037
+ function S(r) {
1038
+ if ((r.fields?.length ?? 0) > 0)
1039
+ return l("panel.variable-list", {
1040
+ fields: (r.fields ?? []).map((u) => u.name).join(", ")
1041
+ });
1042
+ const c = r.example;
1043
+ return typeof c == "string" || typeof c == "number" ? String(c) : "";
1044
+ }
1045
+ function O(r) {
1046
+ const c = o.value?.view;
1047
+ if (!c) return;
1048
+ const u = c.state.selection.main;
1049
+ c.dispatch({
1050
+ changes: { from: u.from, to: u.to, insert: r },
1051
+ selection: { anchor: u.from + r.length },
1052
+ scrollIntoView: !0
1053
+ }), c.focus();
1054
+ }
1055
+ ne(() => n.inserters.set(e.part, O)), Se(() => {
1056
+ n.inserters.get(e.part) === O && n.inserters.delete(e.part);
1057
+ });
1058
+ const T = h(() => we(n.event.value, n.provider.value?.key));
1059
+ async function f() {
1060
+ const r = T.value;
1061
+ if (r === null) return;
1062
+ const c = n.values.value, u = n.provider.value?.subject ?? !1;
1063
+ (!B(c.template) || u && !B(c.subject)) && !await Be({
1064
+ title: l("panel.default-title"),
1065
+ message: l("panel.default-text"),
1066
+ confirmText: l("panel.default-replace"),
1067
+ cancelText: l("panel.cancel")
1068
+ }) || (n.values.value = ye(n.values.value, r, u), J.info(l("panel.default-inserted")));
1069
+ }
1070
+ return (r, c) => (p(), w("div", Ct, [
1071
+ g(s(Re), {
1072
+ ref_key: "editor",
1073
+ ref: o,
1074
+ modelValue: a.value,
1075
+ "onUpdate:modelValue": c[0] || (c[0] = (u) => a.value = u),
1076
+ language: b.value,
1077
+ completions: _.value,
1078
+ localized: e.localized,
1079
+ disabled: e.disabled,
1080
+ "line-numbers": !1,
1081
+ "line-wrapping": !e.singleLine,
1082
+ "single-line": e.singleLine,
1083
+ "min-height": e.singleLine ? void 0 : e.minHeight,
1084
+ onFocus: c[1] || (c[1] = (u) => s(n).focused.value = e.part)
1085
+ }, null, 8, ["modelValue", "language", "completions", "localized", "disabled", "line-wrapping", "single-line", "min-height"]),
1086
+ (p(!0), w(z, null, M(C.value, (u) => (p(), k(s(D), {
1087
+ key: u,
1088
+ type: "warning",
1089
+ variant: "soft",
1090
+ description: u
1091
+ }, null, 8, ["description"]))), 128)),
1092
+ e.chips ? (p(), w("div", St, [
1093
+ g(s(N), {
1094
+ size: "sm",
1095
+ weight: "medium"
1096
+ }, {
1097
+ default: m(() => [
1098
+ y(v(s(l)("panel.variables")), 1)
1099
+ ]),
1100
+ _: 1
1101
+ }),
1102
+ d.value.length === 0 ? (p(), k(s(N), {
1103
+ key: 0,
1104
+ size: "sm",
1105
+ tone: "muted"
1106
+ }, {
1107
+ default: m(() => [
1108
+ y(v(s(l)("panel.variables-none")), 1)
1109
+ ]),
1110
+ _: 1
1111
+ })) : (p(), w(z, { key: 1 }, [
1112
+ g(s(N), {
1113
+ size: "sm",
1114
+ tone: "muted"
1115
+ }, {
1116
+ default: m(() => [
1117
+ y(v(s(l)("panel.variables-help")), 1)
1118
+ ]),
1119
+ _: 1
1120
+ }),
1121
+ I("div", At, [
1122
+ (p(!0), w(z, null, M(d.value, (u) => (p(), k(s(Ue), {
1123
+ key: u.name,
1124
+ content: [u.label, S(u)].filter(Boolean).join(" — ")
1125
+ }, {
1126
+ default: m(() => [
1127
+ g(s(V), {
1128
+ size: "sm",
1129
+ variant: "outline",
1130
+ class: "wx-notifications-template__chip",
1131
+ disabled: e.disabled,
1132
+ onClick: (A) => s(n).insert(s(lt)(u))
1133
+ }, {
1134
+ default: m(() => [
1135
+ I("span", jt, v((u.fields?.length ?? 0) > 0 ? `#${u.name}` : u.name), 1)
1136
+ ]),
1137
+ _: 2
1138
+ }, 1032, ["disabled", "onClick"])
1139
+ ]),
1140
+ _: 2
1141
+ }, 1032, ["content"]))), 128))
1142
+ ])
1143
+ ], 64)),
1144
+ T.value ? (p(), w("div", Wt, [
1145
+ g(s(V), {
1146
+ size: "sm",
1147
+ variant: "text",
1148
+ icon: "file-text",
1149
+ disabled: e.disabled,
1150
+ onClick: f
1151
+ }, {
1152
+ default: m(() => [
1153
+ y(v(s(l)("panel.default-insert")), 1)
1154
+ ]),
1155
+ _: 1
1156
+ }, 8, ["disabled"])
1157
+ ])) : W("", !0)
1158
+ ])) : W("", !0)
1159
+ ]));
1160
+ }
1161
+ }), Vt = /* @__PURE__ */ U(Nt, [["__scopeId", "data-v-d491fffa"]]);
1162
+ function Zt(t = {}) {
1163
+ const e = t.path ?? "/notifications";
1164
+ return {
1165
+ id: "notifications",
1166
+ path: e,
1167
+ routes: [
1168
+ {
1169
+ path: e,
1170
+ name: "webx.notifications",
1171
+ component: () => import("./NotificationsPage-CtP9bFgU.js"),
1172
+ props: { base: e }
1173
+ },
1174
+ {
1175
+ path: `${e}/channels/new`,
1176
+ name: "webx.notifications.new",
1177
+ component: () => import("./ChannelPage-DB6cyt1W.js"),
1178
+ props: { base: e }
1179
+ },
1180
+ {
1181
+ path: `${e}/channels/:id(\\d+)`,
1182
+ name: "webx.notifications.channel",
1183
+ component: () => import("./ChannelPage-DB6cyt1W.js"),
1184
+ props: { base: e }
1185
+ }
1186
+ ],
1187
+ types: {
1188
+ "wx-notifications-template": { component: Vt, kind: "field", wide: !0 },
1189
+ "wx-notifications-chats": { component: ot, kind: "field" },
1190
+ "wx-notifications-emails": { component: dt, kind: "field" },
1191
+ "wx-notifications-channels": {
1192
+ component: Xe,
1193
+ kind: "field",
1194
+ bind: (a) => ({ event: a.props?.event, base: e })
1195
+ }
1196
+ }
1197
+ };
1198
+ }
1199
+ const Ot = /* @__PURE__ */ new Set([
1200
+ "b",
1201
+ "strong",
1202
+ "i",
1203
+ "em",
1204
+ "u",
1205
+ "ins",
1206
+ "s",
1207
+ "strike",
1208
+ "del",
1209
+ "a",
1210
+ "code",
1211
+ "pre",
1212
+ "blockquote",
1213
+ "tg-spoiler",
1214
+ "span"
1215
+ ]);
1216
+ function te(t, e, a) {
1217
+ for (const l of Array.from(t.childNodes)) {
1218
+ if (l.nodeType === Node.TEXT_NODE) {
1219
+ e.appendChild(a.createTextNode(l.textContent ?? ""));
1220
+ continue;
1221
+ }
1222
+ if (!(l instanceof Element)) continue;
1223
+ const n = l.tagName.toLowerCase();
1224
+ if (!Ot.has(n) || n === "span" && !l.classList.contains("tg-spoiler")) {
1225
+ te(l, e, a);
1226
+ continue;
1227
+ }
1228
+ const i = a.createElement(n === "tg-spoiler" ? "span" : n);
1229
+ if ((n === "tg-spoiler" || n === "span") && (i.className = "tg-spoiler"), n === "a") {
1230
+ const o = l.getAttribute("href") ?? "";
1231
+ /^(https?:|tg:)/i.test(o) && (i.setAttribute("href", o), i.setAttribute("target", "_blank"), i.setAttribute("rel", "noopener noreferrer"));
1232
+ }
1233
+ te(l, i, a), e.appendChild(i);
1234
+ }
1235
+ }
1236
+ function zt(t) {
1237
+ const e = new DOMParser().parseFromString(`<body>${t}</body>`, "text/html"), a = document.implementation.createHTMLDocument(""), l = a.createElement("div");
1238
+ return te(e.body, l, a), l.innerHTML;
1239
+ }
1240
+ const Ft = {
1241
+ key: 0,
1242
+ class: "wx-notifications-preview__chat"
1243
+ }, Et = ["innerHTML"], Mt = {
1244
+ key: 1,
1245
+ class: "wx-notifications-preview__bubble"
1246
+ }, Lt = {
1247
+ key: 1,
1248
+ class: "wx-notifications-preview__letter"
1249
+ }, Pt = { class: "wx-notifications-preview__subject" }, Rt = ["title", "srcdoc"], Ut = {
1250
+ key: 1,
1251
+ class: "wx-notifications-preview__body"
1252
+ }, Bt = /* @__PURE__ */ L({
1253
+ name: "WxNotificationsPreview",
1254
+ __name: "MessagePreview",
1255
+ setup(t) {
1256
+ R();
1257
+ const e = P("webx-notifications"), a = Q(), l = me(), n = h(() => l.active.value || l.list.value[0]?.code || ""), i = h(() => {
1258
+ const T = a.provider.value;
1259
+ if (T === null) return null;
1260
+ const f = a.values.value;
1261
+ try {
1262
+ return {
1263
+ message: Tt({
1264
+ provider: T.key,
1265
+ template: ie(f.template, n.value),
1266
+ subject: ie(f.subject, n.value),
1267
+ hasSubject: T.subject,
1268
+ limit: T.limit,
1269
+ values: xt(a.event.value),
1270
+ event: a.event.value
1271
+ })
1272
+ };
1273
+ } catch (r) {
1274
+ if (r instanceof E)
1275
+ return { refusal: e(`errors.${r.key}`, r.replace) };
1276
+ throw r;
1277
+ }
1278
+ }), o = h(
1279
+ () => i.value !== null && "message" in i.value ? i.value.message : null
1280
+ ), d = h(
1281
+ () => i.value !== null && "refusal" in i.value ? i.value.refusal : null
1282
+ ), _ = h(
1283
+ () => e("panel.preview-unknown", {
1284
+ names: (o.value?.unknown ?? []).map((T) => "{{" + T + "}}").join(", ")
1285
+ })
1286
+ ), x = h(() => a.provider.value?.key === "telegram"), b = h(
1287
+ () => o.value?.html ? `<!doctype html><html><head><meta charset="utf-8"><style>body{margin:0;padding:16px;background:#fff;color:#111827;font:14px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;}</style></head><body>` + o.value.body + "</body></html>" : ""
1288
+ ), $ = j(null), C = j(240);
1289
+ function S() {
1290
+ const T = $.value?.contentDocument?.body;
1291
+ T && (C.value = Math.max(80, Math.ceil(T.scrollHeight)));
1292
+ }
1293
+ const O = h(
1294
+ () => o.value === null || o.value.truncated ? "" : zt(o.value.body)
1295
+ );
1296
+ return (T, f) => (p(), k(s(Ie), {
1297
+ title: s(e)("panel.preview"),
1298
+ class: "wx-notifications-preview"
1299
+ }, {
1300
+ default: m(() => [
1301
+ g(s(N), {
1302
+ size: "sm",
1303
+ tone: "muted"
1304
+ }, {
1305
+ default: m(() => [
1306
+ y(v(s(a).event.value ? s(e)("panel.preview-help") : s(e)("panel.preview-no-event")), 1)
1307
+ ]),
1308
+ _: 1
1309
+ }),
1310
+ d.value ? (p(), k(s(D), {
1311
+ key: 0,
1312
+ type: "danger",
1313
+ variant: "soft",
1314
+ title: s(e)("panel.preview-refused"),
1315
+ description: d.value
1316
+ }, null, 8, ["title", "description"])) : o.value ? (p(), w(z, { key: 1 }, [
1317
+ x.value ? (p(), w("div", Ft, [
1318
+ o.value.truncated ? (p(), w("div", Mt, v(o.value.plain), 1)) : (p(), w("div", {
1319
+ key: 0,
1320
+ class: "wx-notifications-preview__bubble",
1321
+ innerHTML: O.value
1322
+ }, null, 8, Et))
1323
+ ])) : (p(), w("div", Lt, [
1324
+ I("div", Pt, [
1325
+ g(s(N), {
1326
+ size: "sm",
1327
+ tone: "muted"
1328
+ }, {
1329
+ default: m(() => [
1330
+ y(v(s(e)("panel.preview-subject")), 1)
1331
+ ]),
1332
+ _: 1
1333
+ }),
1334
+ g(s(N), { weight: "medium" }, {
1335
+ default: m(() => [
1336
+ y(v(o.value.subject || "—"), 1)
1337
+ ]),
1338
+ _: 1
1339
+ })
1340
+ ]),
1341
+ o.value.html ? (p(), w("iframe", {
1342
+ key: 0,
1343
+ ref_key: "frame",
1344
+ ref: $,
1345
+ class: "wx-notifications-preview__frame",
1346
+ sandbox: "allow-same-origin",
1347
+ title: s(e)("panel.preview"),
1348
+ srcdoc: b.value,
1349
+ style: Ae({ height: `${C.value}px` }),
1350
+ onLoad: S
1351
+ }, null, 44, Rt)) : (p(), w("div", Ut, v(o.value.body), 1))
1352
+ ])),
1353
+ o.value.plain.trim() === "" ? (p(), k(s(N), {
1354
+ key: 2,
1355
+ size: "sm",
1356
+ tone: "muted"
1357
+ }, {
1358
+ default: m(() => [
1359
+ y(v(s(e)("panel.preview-empty")), 1)
1360
+ ]),
1361
+ _: 1
1362
+ })) : W("", !0),
1363
+ o.value.truncated ? (p(), k(s(D), {
1364
+ key: 3,
1365
+ type: "warning",
1366
+ variant: "soft",
1367
+ description: s(e)("panel.preview-truncated", { limit: String(s(a).provider.value?.limit ?? "") })
1368
+ }, null, 8, ["description"])) : W("", !0),
1369
+ o.value.unknown.length > 0 && s(a).event.value ? (p(), k(s(N), {
1370
+ key: 4,
1371
+ size: "sm",
1372
+ tone: "muted"
1373
+ }, {
1374
+ default: m(() => [
1375
+ y(v(_.value), 1)
1376
+ ]),
1377
+ _: 1
1378
+ })) : W("", !0)
1379
+ ], 64)) : W("", !0)
1380
+ ]),
1381
+ _: 1
1382
+ }, 8, ["title"]));
1383
+ }
1384
+ }), Jt = /* @__PURE__ */ U(Bt, [["__scopeId", "data-v-2e2a2dc3"]]), Yt = pe(() => import("./NotificationsPage-CtP9bFgU.js")), en = pe(() => import("./ChannelPage-DB6cyt1W.js"));
1385
+ export {
1386
+ Xe as C,
1387
+ dt as E,
1388
+ Jt as M,
1389
+ Ze as N,
1390
+ E as T,
1391
+ en as W,
1392
+ U as _,
1393
+ ot as a,
1394
+ Yt as b,
1395
+ be as c,
1396
+ Vt as d,
1397
+ ge as e,
1398
+ Xt as f,
1399
+ pt as g,
1400
+ _e as h,
1401
+ xt as i,
1402
+ Ke as j,
1403
+ ue as k,
1404
+ lt as l,
1405
+ Q as m,
1406
+ Zt as n,
1407
+ Qt as p,
1408
+ Tt as r,
1409
+ we as s,
1410
+ zt as t,
1411
+ R as u,
1412
+ at as v
1413
+ };
1414
+ //# sourceMappingURL=index-Bki9dkMd.js.map