@webx-ui/module-auth 0.12.0 → 0.13.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,2865 @@
1
+ import { inject as ge, defineComponent as X, computed as P, ref as A, useTemplateRef as ne, onBeforeUnmount as Je, resolveComponent as H, openBlock as c, createBlock as h, withCtx as a, createVNode as l, withModifiers as We, createCommentVNode as B, createElementVNode as N, createTextVNode as p, toDisplayString as m, watch as de, unref as e, isRef as we, normalizeClass as Fe, createElementBlock as K, resolveDynamicComponent as Pe, createSlots as Oe, Fragment as ie, renderList as _e, onMounted as Qe, h as Be, defineAsyncComponent as Xe } from "vue";
2
+ import { useTranslate as J, HttpError as Ze, useAdmin as te, useI18n as Re, useErrorText as ce, rowMenuWidth as ea, WxDate as Z, WxRowMenu as Ve, WxFilterChips as Ee, WxListScreen as aa, useTheme as ta } from "@webx-ui/module-admin";
3
+ import { useRouter as la, useRoute as sa } from "vue-router";
4
+ import { useModal as fe, WxDialog as ye, WxFormItem as I, WxInput as ee, WxSelect as ae, WxSpace as le, WxCheckbox as Ae, WxText as E, WxButton as j, toast as G, useElementWidth as he, WxTable as be, WxEntityCard as ke, WxBadge as M, WxAvatar as na, WxIcon as ue, confirm as xe, WxAlert as oa, WxRadioGroup as ia, createModal as pe, WxThemeSwitch as ra } from "@webx-ui/core";
5
+ const De = /* @__PURE__ */ Symbol("webx-auth");
6
+ function Ce() {
7
+ const s = ge(De, null);
8
+ if (s === null)
9
+ throw new Error("useAuth() was called outside a panel that installed the auth plugin.");
10
+ return s;
11
+ }
12
+ function ua(s) {
13
+ const r = `${s.apiPath}/auth`;
14
+ return {
15
+ async me() {
16
+ try {
17
+ return (await s.http.get(`${r}/me`)).data;
18
+ } catch (o) {
19
+ if (ca(o))
20
+ return null;
21
+ throw o;
22
+ }
23
+ },
24
+ async login(o) {
25
+ const i = await s.http.post(`${r}/login`, {
26
+ email: o.email,
27
+ password: o.password,
28
+ remember: o.remember ?? !1
29
+ });
30
+ return s.setUser(i.data), await s.reload(), i.data;
31
+ },
32
+ async setLocale(o) {
33
+ const i = await s.http.put(`${r}/locale`, { locale: o });
34
+ s.setUser(i.data), await s.setLocale(o);
35
+ },
36
+ async setTheme(o) {
37
+ const i = await s.http.put(`${r}/theme`, {
38
+ theme: o === "system" ? null : o
39
+ });
40
+ s.setUser(i.data);
41
+ },
42
+ async setSiteBar(o) {
43
+ const i = await s.http.put(`${r}/site-bar`, { enabled: o });
44
+ s.setUser(i.data);
45
+ },
46
+ async updateProfile(o) {
47
+ const i = await s.http.put(
48
+ `${r}/me`,
49
+ o
50
+ );
51
+ return s.setUser(i.data), i.data;
52
+ },
53
+ async logout() {
54
+ try {
55
+ await s.http.post(`${r}/logout`);
56
+ } finally {
57
+ s.setUser(null), s.state.status = "unauthenticated", s.state.manifest = null;
58
+ }
59
+ }
60
+ };
61
+ }
62
+ const Ie = /* @__PURE__ */ Symbol("webx-auth-avatar"), Ne = /* @__PURE__ */ Symbol("webx-auth-avatar-field");
63
+ function da(s, r, o = null, i = null) {
64
+ s.provide(De, r), s.provide(Ie, o), s.provide(Ne, i);
65
+ }
66
+ function ca(s) {
67
+ return typeof s == "object" && s !== null && "status" in s && s.status === 401;
68
+ }
69
+ const ma = ["title", "aria-label", "aria-pressed"], va = /* @__PURE__ */ X({
70
+ __name: "LoginCard",
71
+ props: {
72
+ emailLabel: { default: void 0 },
73
+ passwordLabel: { default: void 0 },
74
+ rememberLabel: { default: void 0 },
75
+ submitLabel: { default: void 0 },
76
+ capsLockWarning: { default: void 0 },
77
+ throttleMessage: { default: void 0 },
78
+ revealLabel: { default: void 0 },
79
+ hideLabel: { default: void 0 },
80
+ remember: { type: Boolean, default: !0 },
81
+ autofocus: { type: Boolean, default: !0 }
82
+ },
83
+ emits: ["success"],
84
+ setup(s, { expose: r, emit: o }) {
85
+ const i = s, v = o, k = Ce(), z = J("webx-auth"), n = P(() => ({
86
+ email: i.emailLabel ?? z("card.email"),
87
+ password: i.passwordLabel ?? z("card.password"),
88
+ remember: i.rememberLabel ?? z("card.remember"),
89
+ submit: i.submitLabel ?? z("card.submit"),
90
+ capsLock: i.capsLockWarning ?? z("card.caps-lock"),
91
+ reveal: i.revealLabel ?? z("card.reveal"),
92
+ hide: i.hideLabel ?? z("card.hide")
93
+ })), y = A(""), O = A(""), u = A(!1), w = A(!1), V = A(!1), f = A(!1), S = A(""), $ = A({}), x = A(0), T = ne("emailField");
94
+ let g = null;
95
+ Je(F);
96
+ const D = P(() => x.value > 0), t = P(
97
+ () => i.throttleMessage === void 0 ? z("card.throttled", { seconds: x.value }) : i.throttleMessage.replace(":seconds", String(x.value))
98
+ );
99
+ async function b() {
100
+ if (!(w.value || D.value)) {
101
+ w.value = !0, S.value = "", $.value = {};
102
+ try {
103
+ await k.login({
104
+ email: y.value,
105
+ password: O.value,
106
+ remember: u.value
107
+ }), O.value = "", v("success");
108
+ } catch (d) {
109
+ U(d);
110
+ } finally {
111
+ w.value = !1;
112
+ }
113
+ }
114
+ }
115
+ function U(d) {
116
+ if (!(d instanceof Ze)) {
117
+ S.value = d instanceof Error ? d.message : String(d);
118
+ return;
119
+ }
120
+ if (d.isValidation) {
121
+ $.value = d.errors;
122
+ return;
123
+ }
124
+ if (d.isThrottled) {
125
+ Y(d.retryAfter ?? 60);
126
+ return;
127
+ }
128
+ S.value = d.message;
129
+ }
130
+ function Y(d) {
131
+ F(), x.value = d, g = setInterval(() => {
132
+ x.value -= 1, x.value <= 0 && F();
133
+ }, 1e3);
134
+ }
135
+ function F() {
136
+ g !== null && (clearInterval(g), g = null), x.value = 0;
137
+ }
138
+ function C(d) {
139
+ f.value = d.getModifierState("CapsLock");
140
+ }
141
+ return r({ focus: () => T.value?.focus() }), (d, W) => {
142
+ const _ = H("wx-alert"), Q = H("wx-icon"), ve = H("wx-input"), R = H("wx-form-item"), q = H("wx-checkbox"), L = H("wx-button"), oe = H("wx-form"), Ye = H("wx-card");
143
+ return c(), h(Ye, {
144
+ class: "wx-login",
145
+ padding: 24
146
+ }, {
147
+ default: a(() => [
148
+ l(oe, {
149
+ errors: $.value,
150
+ disabled: w.value,
151
+ gap: "md",
152
+ onSubmit: We(b, ["prevent"])
153
+ }, {
154
+ default: a(() => [
155
+ S.value !== "" ? (c(), h(_, {
156
+ key: 0,
157
+ type: "danger",
158
+ variant: "soft",
159
+ live: "",
160
+ description: S.value,
161
+ class: "wx-login__message"
162
+ }, null, 8, ["description"])) : D.value ? (c(), h(_, {
163
+ key: 1,
164
+ type: "warning",
165
+ variant: "soft",
166
+ live: "",
167
+ description: t.value,
168
+ class: "wx-login__message"
169
+ }, null, 8, ["description"])) : B("", !0),
170
+ l(R, { name: "email" }, {
171
+ default: a(() => [
172
+ l(ve, {
173
+ ref_key: "emailField",
174
+ ref: T,
175
+ modelValue: y.value,
176
+ "onUpdate:modelValue": W[0] || (W[0] = (re) => y.value = re),
177
+ type: "email",
178
+ placeholder: n.value.email,
179
+ "aria-label": n.value.email,
180
+ autocomplete: "username",
181
+ autofocus: s.autofocus,
182
+ inputmode: "email",
183
+ size: "lg"
184
+ }, {
185
+ prefix: a(() => [
186
+ l(Q, { name: "mail" })
187
+ ]),
188
+ _: 1
189
+ }, 8, ["modelValue", "placeholder", "aria-label", "autofocus"])
190
+ ]),
191
+ _: 1
192
+ }),
193
+ l(R, {
194
+ name: "password",
195
+ help: f.value ? n.value.capsLock : void 0
196
+ }, {
197
+ default: a(() => [
198
+ l(ve, {
199
+ modelValue: O.value,
200
+ "onUpdate:modelValue": W[2] || (W[2] = (re) => O.value = re),
201
+ type: V.value ? "text" : "password",
202
+ placeholder: n.value.password,
203
+ "aria-label": n.value.password,
204
+ autocomplete: "current-password",
205
+ size: "lg",
206
+ onKeydown: C,
207
+ onKeyup: C
208
+ }, {
209
+ prefix: a(() => [
210
+ l(Q, { name: "lock" })
211
+ ]),
212
+ suffix: a(() => [
213
+ N("button", {
214
+ type: "button",
215
+ class: "wx-login__reveal",
216
+ title: V.value ? n.value.hide : n.value.reveal,
217
+ "aria-label": V.value ? n.value.hide : n.value.reveal,
218
+ "aria-pressed": V.value,
219
+ tabindex: "-1",
220
+ onClick: W[1] || (W[1] = (re) => V.value = !V.value)
221
+ }, [
222
+ l(Q, {
223
+ name: V.value ? "eye-off" : "eye"
224
+ }, null, 8, ["name"])
225
+ ], 8, ma)
226
+ ]),
227
+ _: 1
228
+ }, 8, ["modelValue", "type", "placeholder", "aria-label"])
229
+ ]),
230
+ _: 1
231
+ }, 8, ["help"]),
232
+ s.remember ? (c(), h(q, {
233
+ key: 2,
234
+ modelValue: u.value,
235
+ "onUpdate:modelValue": W[3] || (W[3] = (re) => u.value = re),
236
+ label: n.value.remember,
237
+ class: "wx-login__remember"
238
+ }, null, 8, ["modelValue", "label"])) : B("", !0),
239
+ l(L, {
240
+ type: "primary",
241
+ "native-type": "submit",
242
+ size: "lg",
243
+ block: "",
244
+ loading: w.value,
245
+ disabled: D.value
246
+ }, {
247
+ default: a(() => [
248
+ p(m(n.value.submit), 1)
249
+ ]),
250
+ _: 1
251
+ }, 8, ["loading", "disabled"])
252
+ ]),
253
+ _: 1
254
+ }, 8, ["errors", "disabled"])
255
+ ]),
256
+ _: 1
257
+ });
258
+ };
259
+ }
260
+ }), $e = (s, r) => {
261
+ const o = s.__vccOpts || s;
262
+ for (const [i, v] of r)
263
+ o[i] = v;
264
+ return o;
265
+ }, pa = /* @__PURE__ */ $e(va, [["__scopeId", "data-v-3c206e31"]]);
266
+ function Me(s) {
267
+ return s.types["wx-media"]?.component ?? null;
268
+ }
269
+ function qe(s) {
270
+ const r = s.assetUrls;
271
+ return r ? async (o) => (await r([o]))[o] ?? null : null;
272
+ }
273
+ const Ke = {
274
+ card: {
275
+ email: "Email",
276
+ password: "Password",
277
+ remember: "Stay signed in",
278
+ submit: "Sign in",
279
+ "caps-lock": "Caps Lock is on.",
280
+ reveal: "Show the password",
281
+ hide: "Hide the password",
282
+ throttled: "Too many attempts. Try again in :seconds s.",
283
+ failed: "Those details do not match an account."
284
+ },
285
+ admins: {
286
+ title: "Administrators",
287
+ "filter-role": "Role",
288
+ "filter-state": "State",
289
+ search: "Search administrators",
290
+ new: "New administrator",
291
+ edit: "Edit administrator",
292
+ // The same two, short enough for a button on a phone and for a dialog's heading.
293
+ "new-short": "Add",
294
+ "edit-short": "Edit",
295
+ name: "Name",
296
+ email: "Email",
297
+ password: "Password",
298
+ "password-hint": "At least 12 characters",
299
+ "password-keep": "Leave blank to keep the current one",
300
+ avatar: "Photo",
301
+ roles: "Roles",
302
+ "no-roles": "No roles",
303
+ active: "Active",
304
+ super: "Super administrator",
305
+ "super-hint": "Answers yes to everything, whatever the roles say",
306
+ locale: "Panel language",
307
+ "locale-auto": "Follow the browser",
308
+ "last-login": "Last signed in",
309
+ save: "Save",
310
+ cancel: "Cancel",
311
+ delete: "Delete",
312
+ "delete-title": "Delete :name?",
313
+ "delete-text": "They lose access at once. What they have written stays.",
314
+ "all-roles": "All roles",
315
+ "any-state": "Active and not",
316
+ "only-active": "Active only",
317
+ "only-inactive": "Switched off only",
318
+ empty: "Nobody matches that",
319
+ "select-one": "Choose an administrator",
320
+ "select-many": "Choose administrators",
321
+ chosen: "Chosen: :count",
322
+ created: "Administrator created",
323
+ updated: "Administrator saved",
324
+ deleted: "Administrator deleted"
325
+ },
326
+ // The trail of what agents did through the panel: the view next to the administrators.
327
+ calls: {
328
+ title: "Agent calls",
329
+ when: "When",
330
+ who: "Who",
331
+ client: "Client",
332
+ tool: "Tool",
333
+ outcome: "Outcome",
334
+ took: "Took",
335
+ ms: ":count ms",
336
+ answered: "Answered",
337
+ refused: "Refused",
338
+ "dry-run": "Dry run",
339
+ local: "Local server",
340
+ deleted: "Administrator #:id",
341
+ "filter-user": "Administrator",
342
+ "filter-tool": "Tool",
343
+ "filter-outcome": "Outcome",
344
+ everybody: "Everybody",
345
+ "all-tools": "All tools",
346
+ "any-outcome": "Any outcome",
347
+ "only-answered": "Answered only",
348
+ "only-refused": "Refused only",
349
+ "only-dry": "Dry runs only",
350
+ arguments: "Arguments",
351
+ "no-arguments": "Called with no arguments",
352
+ request: "The agent's request",
353
+ "request-hint": "What the agent passed to the tool. The answer is not kept.",
354
+ error: "Refused with",
355
+ empty: "No calls match"
356
+ },
357
+ // The connections tab and the page that tells somebody how to make one.
358
+ connections: {
359
+ title: "Connections",
360
+ client: "Client",
361
+ allowed: "What is allowed",
362
+ connected: "Connected",
363
+ "last-used": "Last used",
364
+ who: "Administrator",
365
+ full: "Everything :name can do",
366
+ "full-you": "Everything you can do",
367
+ "read-only": "Reading only",
368
+ "returns-to": "Answers go to :host",
369
+ disconnect: "Disconnect",
370
+ disconnected: "Disconnected",
371
+ "never-used": "Never",
372
+ empty: "No agents are connected",
373
+ "empty-all": "Nobody has connected an agent",
374
+ "confirm-title": "Disconnect :client?",
375
+ "confirm-text": "It loses access at once, including the month of refreshing it was given. Connecting it again takes three clicks.",
376
+ confirm: "Disconnect",
377
+ cancel: "Cancel",
378
+ done: ":client is disconnected",
379
+ deleted: "Administrator #:id"
380
+ },
381
+ // Keys for programs, issued and revoked under Administrators → Keys.
382
+ keys: {
383
+ title: "Keys",
384
+ issue: "Issue a key",
385
+ "issue-short": "Issue",
386
+ lead: "A key lets a program — a queue watcher, a nightly import — work in this panel without a browser. It acts as the administrator you choose and can never do more than they may. A key is a program, not a person: what a module keeps for a person, such as a stage checked by hand, it cannot do.",
387
+ name: "Name",
388
+ "name-hint": 'What the program is, so that the list says it: "queue watcher", "nightly import".',
389
+ who: "Acts as",
390
+ "who-hint": "Everything the key changes is done in this administrator's name, within their permissions.",
391
+ allowed: "What is allowed",
392
+ everything: "Everything the administrator may do",
393
+ chosen: "Only the scopes chosen below",
394
+ scopes: "Scopes",
395
+ "scopes-hint": "A module installed later is out of reach until a new key names it.",
396
+ "scopes-required": "Choose at least one scope.",
397
+ lifetime: "Lives for",
398
+ "lifetime-hint": "A key cannot be extended: issue a new one before this one runs out, then revoke the old one.",
399
+ "days-30": "30 days",
400
+ "days-90": "90 days",
401
+ "days-365": "1 year",
402
+ "days-1095": "3 years",
403
+ "days-3650": "10 years",
404
+ "issued-title": "Copy the key now",
405
+ "issued-text": "This is the only time the key is shown. Nobody can see it again — not here, not on the server. If it is lost, revoke it and issue a new one.",
406
+ secret: "Key",
407
+ copy: "Copy",
408
+ copied: "Copied",
409
+ "copy-failed": "Could not reach the clipboard. Select the key and copy it by hand.",
410
+ address: "Server address",
411
+ "header-hint": "The program sends the key in a header: Authorization: Bearer <key>.",
412
+ done: "Done",
413
+ cancel: "Cancel",
414
+ expires: "Expires",
415
+ until: "until",
416
+ "last-used": "Last used",
417
+ "never-used": "Never",
418
+ "issued-by": "Issued by :name",
419
+ "issued-console": "Issued in a terminal",
420
+ full: "Everything :name can do",
421
+ deleted: "Administrator #:id",
422
+ revoke: "Revoke",
423
+ revoked: "Revoked",
424
+ expired: "Expired",
425
+ "confirm-title": "Revoke :name?",
426
+ "confirm-text": "The program using it is refused from its next call. A revoked key cannot be switched back on.",
427
+ confirm: "Revoke",
428
+ "revoked-done": ":name is revoked",
429
+ empty: "No keys have been issued"
430
+ },
431
+ connect: {
432
+ lead: "An AI agent — Claude, ChatGPT, Cursor — can work in this panel as you. Give it the address below; it will ask you to sign in and then ask what it may do.",
433
+ title: "Connect an agent",
434
+ address: "The address of this panel for agents",
435
+ copy: "Copy the address",
436
+ copied: "Copied",
437
+ "copy-failed": "Could not reach the clipboard. Select the address and copy it by hand.",
438
+ "copy-line": "Copy",
439
+ how: "How to add it",
440
+ "claude-title": "Claude",
441
+ "claude-1": "Open Settings and go to Connectors.",
442
+ "claude-2": 'Press "Add custom connector".',
443
+ "claude-3": "Paste the address and press Add.",
444
+ "chatgpt-title": "ChatGPT",
445
+ "chatgpt-1": "Open Settings and go to Connectors.",
446
+ "chatgpt-2": 'Press "Add" and choose a custom MCP server.',
447
+ "chatgpt-3": "Paste the address, leave the authentication as OAuth, and confirm.",
448
+ "claude-code-title": "Claude Code",
449
+ "claude-code-hint": "One line in a terminal, from any project:",
450
+ "codex-title": "Codex",
451
+ "codex-hint": "These lines in ~/.codex/config.toml:",
452
+ "one-click": "One click",
453
+ "one-click-hint": "These two take the whole thing from a link: the editor opens, asks once, and the server is there.",
454
+ "install-in": "Add to :client",
455
+ "cursor-title": "Cursor",
456
+ "vscode-title": "VS Code",
457
+ next: "What happens next",
458
+ "next-1": "The client opens this site in a browser and asks you to sign in to the panel, with your usual password. It never sees the password.",
459
+ "next-2": 'The panel shows who is asking and where the answer goes. There is a "read only" switch on that screen, and turning it on is the safe way to begin.',
460
+ "next-3": "From then on the agent acts as you: it can do what you can do and nothing more, and every call it makes is written down.",
461
+ mine: "Your connections",
462
+ rules: "Rules for agents",
463
+ "rules-hint": "Every connected agent reads these before it writes anything a visitor will see."
464
+ },
465
+ errors: {
466
+ unauthenticated: "Unauthenticated.",
467
+ inactive: "This account is no longer active.",
468
+ forbidden: "This account may not do that.",
469
+ "not-yourself": "You cannot do that to your own account.",
470
+ "last-super": "There has to be one super administrator left."
471
+ },
472
+ // Somebody editing themselves, which is a shorter list than an administrator editing them.
473
+ profile: {
474
+ title: "Your profile",
475
+ menu: "Edit your profile",
476
+ name: "Name",
477
+ avatar: "Photo",
478
+ password: "New password",
479
+ "password-hint": "At least 12 characters. Leave blank to keep the current one.",
480
+ "current-password": "Current password",
481
+ "current-password-hint": "Asked for before the password is changed.",
482
+ "wrong-password": "That is not the current password.",
483
+ saved: "Your profile is saved.",
484
+ save: "Save",
485
+ cancel: "Cancel"
486
+ },
487
+ menu: {
488
+ "sign-out": "Sign out",
489
+ language: "Interface language",
490
+ "site-bar": "Panel on the site"
491
+ }
492
+ };
493
+ function me(s) {
494
+ const r = `${s.apiPath}/auth`, o = (i) => i.data;
495
+ return {
496
+ list: (i = {}) => s.http.get(`${r}/admins`, {
497
+ query: {
498
+ q: i.q || void 0,
499
+ role: i.role ?? void 0,
500
+ active: i.active ?? void 0,
501
+ sort: i.sort,
502
+ page: i.page,
503
+ per_page: i.per_page
504
+ }
505
+ }).then((v) => ({ ...v.meta, data: v.data })),
506
+ get: (i) => s.http.get(`${r}/admins/${i}`).then(o),
507
+ create: (i) => s.http.post(`${r}/admins`, i).then(o),
508
+ update: (i, v) => s.http.patch(`${r}/admins/${i}`, v).then(o),
509
+ remove: (i) => s.http.delete(`${r}/admins/${i}`),
510
+ roles: () => s.http.get(`${r}/roles`).then(o),
511
+ calls: (i = {}) => s.http.get(`${r}/mcp-calls`, {
512
+ query: {
513
+ user: i.user ?? void 0,
514
+ tool: i.tool ?? void 0,
515
+ outcome: i.outcome ?? void 0,
516
+ page: i.page,
517
+ per_page: i.per_page
518
+ }
519
+ }).then((v) => ({ ...v.meta, data: v.data, filters: v.filters }))
520
+ };
521
+ }
522
+ const ze = /* @__PURE__ */ new WeakSet();
523
+ function se() {
524
+ try {
525
+ const { i18n: s } = te();
526
+ ze.has(s) || (s.defaults("webx-auth", Ke), ze.add(s));
527
+ } catch {
528
+ }
529
+ }
530
+ const fa = { class: "wx-admin-form" }, ya = {
531
+ key: 0,
532
+ class: "wx-admin-form__aside"
533
+ }, ha = { class: "wx-admin-form__fields" }, ba = /* @__PURE__ */ X({
534
+ __name: "AdminDialog",
535
+ props: {
536
+ admin: { default: null },
537
+ avatarField: { default: void 0 }
538
+ },
539
+ setup(s) {
540
+ const r = s, { resolve: o, dismiss: i, open: v } = fe(), k = te(), z = me(k), n = Re();
541
+ se();
542
+ const y = J("webx-auth"), O = ce(), u = A([]), w = A(!1), V = A({}), f = A({
543
+ name: "",
544
+ email: "",
545
+ password: "",
546
+ avatar: null,
547
+ is_active: !0,
548
+ is_super: !1,
549
+ locale: null,
550
+ roles: []
551
+ }), S = P({
552
+ get: () => f.value.avatar ? { path: f.value.avatar } : null,
553
+ set: (t) => {
554
+ f.value.avatar = t?.path ?? null;
555
+ }
556
+ }), $ = P(() => r.admin !== null), x = P(() => u.value.map((t) => ({ value: t.id, label: t.name }))), T = P(() => [
557
+ { value: "auto", label: y("admins.locale-auto") },
558
+ ...n.state.panelLocales.map((t) => ({ value: t.code, label: t.nativeName }))
559
+ ]);
560
+ z.roles().then((t) => u.value = t), de(
561
+ () => r.admin,
562
+ (t) => {
563
+ f.value = {
564
+ name: t?.name ?? "",
565
+ email: t?.email ?? "",
566
+ password: "",
567
+ avatar: t?.avatar ?? null,
568
+ is_active: t?.is_active ?? !0,
569
+ is_super: t?.is_super ?? !1,
570
+ locale: t?.locale ?? "auto",
571
+ roles: t?.roles.map((b) => b.id) ?? []
572
+ }, V.value = {};
573
+ },
574
+ { immediate: !0 }
575
+ );
576
+ function g(t) {
577
+ return V.value[t]?.[0];
578
+ }
579
+ async function D() {
580
+ w.value = !0, V.value = {};
581
+ const t = {
582
+ name: f.value.name,
583
+ email: f.value.email,
584
+ avatar: f.value.avatar,
585
+ is_active: f.value.is_active,
586
+ is_super: f.value.is_super,
587
+ locale: f.value.locale === "auto" ? null : f.value.locale,
588
+ roles: f.value.roles ?? []
589
+ };
590
+ f.value.password && (t.password = f.value.password);
591
+ try {
592
+ const b = r.admin ? await z.update(r.admin.id, t) : await z.create(t);
593
+ G.success(y($.value ? "admins.updated" : "admins.created")), o(b);
594
+ } catch (b) {
595
+ const U = b.body;
596
+ U?.errors ? V.value = U.errors : G.danger(O(b));
597
+ } finally {
598
+ w.value = !1;
599
+ }
600
+ }
601
+ return (t, b) => (c(), h(e(ye), {
602
+ open: e(v),
603
+ "onUpdate:open": b[9] || (b[9] = (U) => we(v) ? v.value = U : null),
604
+ title: $.value ? e(y)("admins.edit-short") : e(y)("admins.new-short"),
605
+ width: 720
606
+ }, {
607
+ footer: a(() => [
608
+ l(e(le), { size: "sm" }, {
609
+ default: a(() => [
610
+ l(e(j), {
611
+ variant: "outline",
612
+ onClick: b[8] || (b[8] = (U) => e(i)())
613
+ }, {
614
+ default: a(() => [
615
+ p(m(e(y)("admins.cancel")), 1)
616
+ ]),
617
+ _: 1
618
+ }),
619
+ l(e(j), {
620
+ type: "primary",
621
+ loading: w.value,
622
+ onClick: D
623
+ }, {
624
+ default: a(() => [
625
+ p(m(e(y)("admins.save")), 1)
626
+ ]),
627
+ _: 1
628
+ }, 8, ["loading"])
629
+ ]),
630
+ _: 1
631
+ })
632
+ ]),
633
+ default: a(() => [
634
+ N("div", fa, [
635
+ N("div", {
636
+ class: Fe(["wx-admin-form__grid", { "has-aside": s.avatarField }])
637
+ }, [
638
+ s.avatarField ? (c(), K("div", ya, [
639
+ (c(), h(Pe(s.avatarField), {
640
+ modelValue: S.value,
641
+ "onUpdate:modelValue": b[0] || (b[0] = (U) => S.value = U),
642
+ label: e(y)("admins.avatar"),
643
+ aspect: "1/1",
644
+ captions: !1
645
+ }, null, 8, ["modelValue", "label"]))
646
+ ])) : B("", !0),
647
+ N("div", ha, [
648
+ l(e(I), {
649
+ label: e(y)("admins.name"),
650
+ error: g("name")
651
+ }, {
652
+ default: a(() => [
653
+ l(e(ee), {
654
+ modelValue: f.value.name,
655
+ "onUpdate:modelValue": b[1] || (b[1] = (U) => f.value.name = U),
656
+ name: "name"
657
+ }, null, 8, ["modelValue"])
658
+ ]),
659
+ _: 1
660
+ }, 8, ["label", "error"]),
661
+ l(e(I), {
662
+ label: e(y)("admins.email"),
663
+ error: g("email")
664
+ }, {
665
+ default: a(() => [
666
+ l(e(ee), {
667
+ modelValue: f.value.email,
668
+ "onUpdate:modelValue": b[2] || (b[2] = (U) => f.value.email = U),
669
+ type: "email",
670
+ name: "email",
671
+ autocomplete: "off"
672
+ }, null, 8, ["modelValue"])
673
+ ]),
674
+ _: 1
675
+ }, 8, ["label", "error"]),
676
+ l(e(I), {
677
+ label: e(y)("admins.password"),
678
+ error: g("password"),
679
+ help: $.value ? e(y)("admins.password-keep") : e(y)("admins.password-hint")
680
+ }, {
681
+ default: a(() => [
682
+ l(e(ee), {
683
+ modelValue: f.value.password,
684
+ "onUpdate:modelValue": b[3] || (b[3] = (U) => f.value.password = U),
685
+ type: "password",
686
+ name: "password",
687
+ autocomplete: "new-password"
688
+ }, null, 8, ["modelValue"])
689
+ ]),
690
+ _: 1
691
+ }, 8, ["label", "error", "help"]),
692
+ l(e(I), {
693
+ label: e(y)("admins.roles"),
694
+ error: g("roles")
695
+ }, {
696
+ default: a(() => [
697
+ l(e(ae), {
698
+ modelValue: f.value.roles,
699
+ "onUpdate:modelValue": b[4] || (b[4] = (U) => f.value.roles = U),
700
+ options: x.value,
701
+ multiple: ""
702
+ }, null, 8, ["modelValue", "options"])
703
+ ]),
704
+ _: 1
705
+ }, 8, ["label", "error"]),
706
+ l(e(I), {
707
+ label: e(y)("admins.locale")
708
+ }, {
709
+ default: a(() => [
710
+ l(e(ae), {
711
+ modelValue: f.value.locale,
712
+ "onUpdate:modelValue": b[5] || (b[5] = (U) => f.value.locale = U),
713
+ options: T.value
714
+ }, null, 8, ["modelValue", "options"])
715
+ ]),
716
+ _: 1
717
+ }, 8, ["label"]),
718
+ l(e(le), { size: "md" }, {
719
+ default: a(() => [
720
+ l(e(Ae), {
721
+ modelValue: f.value.is_active,
722
+ "onUpdate:modelValue": b[6] || (b[6] = (U) => f.value.is_active = U),
723
+ label: e(y)("admins.active")
724
+ }, null, 8, ["modelValue", "label"]),
725
+ l(e(Ae), {
726
+ modelValue: f.value.is_super,
727
+ "onUpdate:modelValue": b[7] || (b[7] = (U) => f.value.is_super = U),
728
+ label: e(y)("admins.super")
729
+ }, null, 8, ["modelValue", "label"])
730
+ ]),
731
+ _: 1
732
+ }),
733
+ l(e(E), {
734
+ size: "sm",
735
+ tone: "muted"
736
+ }, {
737
+ default: a(() => [
738
+ p(m(e(y)("admins.super-hint")), 1)
739
+ ]),
740
+ _: 1
741
+ })
742
+ ])
743
+ ], 2)
744
+ ])
745
+ ]),
746
+ _: 1
747
+ }, 8, ["open", "title"]));
748
+ }
749
+ }), Se = 480, je = /* @__PURE__ */ X({
750
+ __name: "AdminList",
751
+ props: {
752
+ picking: { type: Boolean, default: !1 },
753
+ multiple: { type: Boolean, default: !1 },
754
+ removable: { type: Boolean, default: !1 },
755
+ filters: { type: Boolean, default: !1 },
756
+ resolveAvatar: { type: Function, default: void 0 }
757
+ },
758
+ emits: ["open", "chosen", "selection", "remove"],
759
+ setup(s, { expose: r, emit: o }) {
760
+ const i = s, v = o, k = te(), z = me(k);
761
+ se();
762
+ const n = ne("root"), y = he(n), O = P(() => y.value > 0 && y.value < Se), u = J("webx-auth"), w = J("webx-admin"), V = A(null), f = A([]), S = A(!1), $ = A("all"), x = A("any"), T = A([]), g = A({});
763
+ let D = { page: 1, perPage: 20, sort: null, search: "" };
764
+ const t = P(() => [
765
+ { value: "all", label: u("admins.all-roles") },
766
+ ...f.value.map((R) => ({ value: R.slug, label: R.name }))
767
+ ]), b = P(() => [
768
+ { value: "any", label: u("admins.any-state") },
769
+ { value: "yes", label: u("admins.only-active") },
770
+ { value: "no", label: u("admins.only-inactive") }
771
+ ]), U = P(() => {
772
+ const R = [], q = f.value.find((L) => L.slug === $.value);
773
+ return q && R.push({
774
+ key: "role",
775
+ label: `${u("admins.filter-role")}: ${q.name}`,
776
+ clear: () => $.value = "all"
777
+ }), x.value !== "any" && R.push({
778
+ key: "state",
779
+ label: `${u("admins.filter-state")}: ${x.value === "yes" ? u("admins.only-active") : u("admins.only-inactive")}`,
780
+ clear: () => x.value = "any"
781
+ }), R;
782
+ });
783
+ function Y() {
784
+ $.value = "all", x.value = "any";
785
+ }
786
+ const F = P(() => O.value ? [{ key: "card", label: "" }] : [
787
+ { key: "name", label: u("admins.name"), sortable: !0 },
788
+ { key: "email", label: u("admins.email"), sortable: !0, hideBelow: 560 },
789
+ { key: "roles", label: u("admins.roles"), hideBelow: 760 },
790
+ { key: "is_active", label: u("admins.active"), align: "center", hideBelow: 660 },
791
+ {
792
+ key: "last_login_at",
793
+ label: u("admins.last-login"),
794
+ sortable: !0,
795
+ hideBelow: 900,
796
+ // The first thing to go when a row becomes a card: it is a date somebody scans down a
797
+ // column, and a card has no column to scan.
798
+ hideOnCards: !0
799
+ },
800
+ {
801
+ key: "actions",
802
+ label: "",
803
+ width: ea,
804
+ align: "right",
805
+ hidden: !i.removable,
806
+ // A card puts them along its top instead, through the `card-actions` slot.
807
+ hideOnCards: !0
808
+ }
809
+ ]);
810
+ z.roles().then((R) => f.value = R), de([$, x], () => C(D));
811
+ async function C(R) {
812
+ D = R, S.value = !0;
813
+ try {
814
+ V.value = await z.list({
815
+ q: R.search,
816
+ role: $.value === "all" ? null : $.value,
817
+ active: x.value === "any" ? null : x.value,
818
+ sort: R.sort ? `${R.sort.order === "desc" ? "-" : ""}${R.sort.key}` : "name",
819
+ page: R.page,
820
+ per_page: R.perPage
821
+ }), d();
822
+ } finally {
823
+ S.value = !1;
824
+ }
825
+ }
826
+ async function d() {
827
+ const R = i.resolveAvatar;
828
+ if (R)
829
+ for (const q of V.value?.data ?? []) {
830
+ if (!q.avatar || g.value[q.avatar]) continue;
831
+ const L = await R(q.avatar);
832
+ L && (g.value = { ...g.value, [q.avatar]: L });
833
+ }
834
+ }
835
+ function W(R) {
836
+ return [
837
+ {
838
+ key: "delete",
839
+ icon: "trash",
840
+ label: u("admins.delete"),
841
+ danger: !0,
842
+ run: () => v("remove", R)
843
+ }
844
+ ];
845
+ }
846
+ function _(R) {
847
+ if (i.picking) {
848
+ v("chosen", [R]);
849
+ return;
850
+ }
851
+ v("open", R);
852
+ }
853
+ const Q = P(() => !(i.picking && i.multiple));
854
+ function ve(R, q) {
855
+ T.value = q, v("selection", q);
856
+ }
857
+ return r({ reload: () => C(D), chosen: () => T.value }), (R, q) => (c(), K("div", {
858
+ ref_key: "root",
859
+ ref: n,
860
+ class: "wx-admin-list"
861
+ }, [
862
+ l(e(be), {
863
+ data: V.value,
864
+ columns: F.value,
865
+ "row-key": "id",
866
+ searchable: "",
867
+ clickable: Q.value,
868
+ hover: Q.value,
869
+ flush: "",
870
+ loading: S.value,
871
+ "search-placeholder": e(u)("admins.search"),
872
+ "empty-text": e(u)("admins.empty"),
873
+ selectable: s.picking && s.multiple,
874
+ "select-row-label": e(w)("filters.select-row"),
875
+ "select-all-label": e(w)("filters.select-all"),
876
+ "cards-below": Se,
877
+ "filters-count": U.value.length,
878
+ "filters-label": e(w)("filters.title"),
879
+ onRowClick: _,
880
+ onStateChange: C,
881
+ onSelectionChange: ve
882
+ }, Oe({
883
+ "cell-name": a(({ row: L }) => [
884
+ l(e(le), {
885
+ size: "sm",
886
+ align: "center"
887
+ }, {
888
+ default: a(() => [
889
+ l(e(na), {
890
+ name: L.name,
891
+ src: L.avatar ? g.value[L.avatar] : void 0,
892
+ size: "sm"
893
+ }, null, 8, ["name", "src"]),
894
+ N("span", null, m(L.name), 1),
895
+ L.is_super ? (c(), h(e(M), {
896
+ key: 0,
897
+ type: "warning"
898
+ }, {
899
+ default: a(() => [
900
+ p(m(e(u)("admins.super")), 1)
901
+ ]),
902
+ _: 1
903
+ })) : B("", !0)
904
+ ]),
905
+ _: 2
906
+ }, 1024)
907
+ ]),
908
+ "cell-roles": a(({ row: L }) => [
909
+ L.roles.length > 0 ? (c(), h(e(le), {
910
+ key: 0,
911
+ size: "xs",
912
+ wrap: ""
913
+ }, {
914
+ default: a(() => [
915
+ (c(!0), K(ie, null, _e(L.roles, (oe) => (c(), h(e(M), {
916
+ key: oe.id
917
+ }, {
918
+ default: a(() => [
919
+ p(m(oe.name), 1)
920
+ ]),
921
+ _: 2
922
+ }, 1024))), 128))
923
+ ]),
924
+ _: 2
925
+ }, 1024)) : (c(), h(e(E), {
926
+ key: 1,
927
+ size: "sm",
928
+ tone: "muted"
929
+ }, {
930
+ default: a(() => [
931
+ p(m(e(u)("admins.no-roles")), 1)
932
+ ]),
933
+ _: 1
934
+ }))
935
+ ]),
936
+ "cell-is_active": a(({ row: L }) => [
937
+ l(e(M), {
938
+ type: L.is_active ? "success" : "default",
939
+ dot: ""
940
+ }, {
941
+ default: a(() => [
942
+ p(m(L.is_active ? e(u)("admins.active") : e(u)("admins.only-inactive")), 1)
943
+ ]),
944
+ _: 2
945
+ }, 1032, ["type"])
946
+ ]),
947
+ "card-actions": a(({ row: L }) => [
948
+ s.removable ? (c(), h(e(Ve), {
949
+ key: 0,
950
+ actions: W(L),
951
+ label: L.name
952
+ }, null, 8, ["actions", "label"])) : B("", !0)
953
+ ]),
954
+ "cell-actions": a(({ row: L }) => [
955
+ l(e(Ve), {
956
+ actions: W(L),
957
+ label: L.name
958
+ }, null, 8, ["actions", "label"])
959
+ ]),
960
+ "cell-last_login_at": a(({ row: L }) => [
961
+ l(e(Z), {
962
+ value: L.last_login_at,
963
+ tone: L.last_login_at ? "default" : "muted",
964
+ compact: ""
965
+ }, null, 8, ["value", "tone"])
966
+ ]),
967
+ "cell-card": a(({ row: L }) => [
968
+ l(e(ke), {
969
+ variant: "plain",
970
+ shape: "circle",
971
+ title: L.name,
972
+ image: L.avatar ? g.value[L.avatar] : void 0,
973
+ subtitle: L.email
974
+ }, {
975
+ meta: a(() => [
976
+ L.is_super ? (c(), h(e(M), {
977
+ key: 0,
978
+ type: "warning",
979
+ size: "sm"
980
+ }, {
981
+ default: a(() => [
982
+ p(m(e(u)("admins.super")), 1)
983
+ ]),
984
+ _: 1
985
+ })) : B("", !0),
986
+ (c(!0), K(ie, null, _e(L.roles, (oe) => (c(), h(e(M), {
987
+ key: oe.id,
988
+ size: "sm"
989
+ }, {
990
+ default: a(() => [
991
+ p(m(oe.name), 1)
992
+ ]),
993
+ _: 2
994
+ }, 1024))), 128)),
995
+ l(e(M), {
996
+ type: L.is_active ? "success" : "default",
997
+ dot: "",
998
+ size: "sm"
999
+ }, {
1000
+ default: a(() => [
1001
+ p(m(L.is_active ? e(u)("admins.active") : e(u)("admins.only-inactive")), 1)
1002
+ ]),
1003
+ _: 2
1004
+ }, 1032, ["type"])
1005
+ ]),
1006
+ _: 2
1007
+ }, 1032, ["title", "image", "subtitle"])
1008
+ ]),
1009
+ _: 2
1010
+ }, [
1011
+ s.filters ? {
1012
+ name: "filters",
1013
+ fn: a(() => [
1014
+ l(e(I), {
1015
+ label: e(u)("admins.filter-role")
1016
+ }, {
1017
+ default: a(() => [
1018
+ l(e(ae), {
1019
+ modelValue: $.value,
1020
+ "onUpdate:modelValue": q[0] || (q[0] = (L) => $.value = L),
1021
+ options: t.value,
1022
+ size: "sm"
1023
+ }, null, 8, ["modelValue", "options"])
1024
+ ]),
1025
+ _: 1
1026
+ }, 8, ["label"]),
1027
+ l(e(I), {
1028
+ label: e(u)("admins.filter-state")
1029
+ }, {
1030
+ default: a(() => [
1031
+ l(e(ae), {
1032
+ modelValue: x.value,
1033
+ "onUpdate:modelValue": q[1] || (q[1] = (L) => x.value = L),
1034
+ options: b.value,
1035
+ size: "sm"
1036
+ }, null, 8, ["modelValue", "options"])
1037
+ ]),
1038
+ _: 1
1039
+ }, 8, ["label"]),
1040
+ U.value.length > 0 ? (c(), h(e(j), {
1041
+ key: 0,
1042
+ variant: "text",
1043
+ size: "sm",
1044
+ block: "",
1045
+ onClick: Y
1046
+ }, {
1047
+ icon: a(() => [
1048
+ l(e(ue), { name: "close" })
1049
+ ]),
1050
+ default: a(() => [
1051
+ p(" " + m(e(w)("filters.reset")), 1)
1052
+ ]),
1053
+ _: 1
1054
+ })) : B("", !0)
1055
+ ]),
1056
+ key: "0"
1057
+ } : void 0,
1058
+ s.filters ? {
1059
+ name: "applied",
1060
+ fn: a(() => [
1061
+ l(e(Ee), { filters: U.value }, null, 8, ["filters"])
1062
+ ]),
1063
+ key: "1"
1064
+ } : void 0
1065
+ ]), 1032, ["data", "columns", "clickable", "hover", "loading", "search-placeholder", "empty-text", "selectable", "select-row-label", "select-all-label", "filters-count", "filters-label"])
1066
+ ], 512));
1067
+ }
1068
+ }), ka = { class: "wx-call-list__details" }, ga = { class: "wx-call-list__label" }, _a = {
1069
+ key: 1,
1070
+ class: "wx-call-list__arguments"
1071
+ }, wa = {
1072
+ class: "wx-call-list__glyph",
1073
+ "aria-hidden": "true"
1074
+ }, xa = {
1075
+ key: 2,
1076
+ class: "wx-call-list__arguments"
1077
+ }, Le = 480, Ca = /* @__PURE__ */ X({
1078
+ __name: "CallList",
1079
+ setup(s, { expose: r }) {
1080
+ const o = te(), i = me(o);
1081
+ se();
1082
+ const v = ne("root"), k = he(v), z = P(() => k.value > 0 && k.value < Le), n = J("webx-auth"), y = J("webx-admin"), O = A(null), u = A({ users: [], tools: [] }), w = A(!1), V = A("all"), f = A("all"), S = A("any");
1083
+ let $ = { page: 1, perPage: 30, sort: null, search: "" };
1084
+ function x(d) {
1085
+ return d === null ? n("calls.local") : d.name ?? n("calls.deleted", { id: d.id });
1086
+ }
1087
+ const T = P(() => [
1088
+ { value: "all", label: n("calls.everybody") },
1089
+ ...u.value.users.map((d) => ({
1090
+ value: d.id === null ? "none" : String(d.id),
1091
+ label: x(d.id === null ? null : { id: d.id, name: d.name })
1092
+ }))
1093
+ ]), g = P(() => [
1094
+ { value: "all", label: n("calls.all-tools") },
1095
+ ...u.value.tools.map((d) => ({ value: d, label: d }))
1096
+ ]), D = P(() => [
1097
+ { value: "any", label: n("calls.any-outcome") },
1098
+ { value: "ok", label: n("calls.only-answered") },
1099
+ { value: "failed", label: n("calls.only-refused") },
1100
+ { value: "dry", label: n("calls.only-dry") }
1101
+ ]), t = P(() => {
1102
+ const d = [], W = T.value.find((Q) => Q.value === V.value);
1103
+ V.value !== "all" && W && d.push({
1104
+ key: "user",
1105
+ label: `${n("calls.filter-user")}: ${W.label}`,
1106
+ clear: () => V.value = "all"
1107
+ }), f.value !== "all" && d.push({
1108
+ key: "tool",
1109
+ label: `${n("calls.filter-tool")}: ${f.value}`,
1110
+ clear: () => f.value = "all"
1111
+ });
1112
+ const _ = D.value.find((Q) => Q.value === S.value);
1113
+ return S.value !== "any" && _ && d.push({
1114
+ key: "outcome",
1115
+ label: `${n("calls.filter-outcome")}: ${_.label}`,
1116
+ clear: () => S.value = "any"
1117
+ }), d;
1118
+ });
1119
+ function b() {
1120
+ V.value = "all", f.value = "all", S.value = "any";
1121
+ }
1122
+ const U = P(() => z.value ? [{ key: "card", label: "" }] : [
1123
+ { key: "at", label: n("calls.when") },
1124
+ { key: "user", label: n("calls.who"), hideBelow: 640 },
1125
+ { key: "tool", label: n("calls.tool") },
1126
+ { key: "outcome", label: n("calls.outcome") },
1127
+ { key: "duration_ms", label: n("calls.took"), align: "right", hideBelow: 820 },
1128
+ { key: "client", label: n("calls.client"), hideBelow: 960 }
1129
+ ]);
1130
+ de([V, f, S], () => Y({ ...$, page: 1 }));
1131
+ async function Y(d) {
1132
+ $ = d, w.value = !0;
1133
+ try {
1134
+ O.value = await i.calls({
1135
+ user: V.value === "all" ? null : V.value,
1136
+ tool: f.value === "all" ? null : f.value,
1137
+ outcome: S.value === "any" ? null : S.value,
1138
+ page: d.page,
1139
+ per_page: d.perPage
1140
+ }), u.value = O.value.filters;
1141
+ } finally {
1142
+ w.value = !1;
1143
+ }
1144
+ }
1145
+ function F(d) {
1146
+ return d.ok ? d.dry_run ? { type: "info", label: n("calls.dry-run") } : { type: "success", label: n("calls.answered") } : { type: "danger", label: n("calls.refused") };
1147
+ }
1148
+ function C(d) {
1149
+ return d.arguments !== null || d.error !== null;
1150
+ }
1151
+ return r({ reload: () => Y($) }), (d, W) => (c(), K("div", {
1152
+ ref_key: "root",
1153
+ ref: v,
1154
+ class: "wx-call-list"
1155
+ }, [
1156
+ l(e(be), {
1157
+ data: O.value,
1158
+ columns: U.value,
1159
+ "row-key": "id",
1160
+ flush: "",
1161
+ loading: w.value,
1162
+ clickable: !1,
1163
+ expandable: !z.value,
1164
+ "expandable-if": C,
1165
+ "empty-text": e(n)("calls.empty"),
1166
+ "cards-below": Le,
1167
+ "filters-count": t.value.length,
1168
+ "filters-label": e(y)("filters.title"),
1169
+ onStateChange: Y
1170
+ }, {
1171
+ filters: a(() => [
1172
+ l(e(I), {
1173
+ label: e(n)("calls.filter-user")
1174
+ }, {
1175
+ default: a(() => [
1176
+ l(e(ae), {
1177
+ modelValue: V.value,
1178
+ "onUpdate:modelValue": W[0] || (W[0] = (_) => V.value = _),
1179
+ options: T.value,
1180
+ size: "sm"
1181
+ }, null, 8, ["modelValue", "options"])
1182
+ ]),
1183
+ _: 1
1184
+ }, 8, ["label"]),
1185
+ l(e(I), {
1186
+ label: e(n)("calls.filter-tool")
1187
+ }, {
1188
+ default: a(() => [
1189
+ l(e(ae), {
1190
+ modelValue: f.value,
1191
+ "onUpdate:modelValue": W[1] || (W[1] = (_) => f.value = _),
1192
+ options: g.value,
1193
+ size: "sm"
1194
+ }, null, 8, ["modelValue", "options"])
1195
+ ]),
1196
+ _: 1
1197
+ }, 8, ["label"]),
1198
+ l(e(I), {
1199
+ label: e(n)("calls.filter-outcome")
1200
+ }, {
1201
+ default: a(() => [
1202
+ l(e(ae), {
1203
+ modelValue: S.value,
1204
+ "onUpdate:modelValue": W[2] || (W[2] = (_) => S.value = _),
1205
+ options: D.value,
1206
+ size: "sm"
1207
+ }, null, 8, ["modelValue", "options"])
1208
+ ]),
1209
+ _: 1
1210
+ }, 8, ["label"]),
1211
+ t.value.length > 0 ? (c(), h(e(j), {
1212
+ key: 0,
1213
+ variant: "text",
1214
+ size: "sm",
1215
+ block: "",
1216
+ onClick: b
1217
+ }, {
1218
+ icon: a(() => [
1219
+ l(e(ue), { name: "close" })
1220
+ ]),
1221
+ default: a(() => [
1222
+ p(" " + m(e(y)("filters.reset")), 1)
1223
+ ]),
1224
+ _: 1
1225
+ })) : B("", !0)
1226
+ ]),
1227
+ applied: a(() => [
1228
+ l(e(Ee), { filters: t.value }, null, 8, ["filters"])
1229
+ ]),
1230
+ "cell-at": a(({ row: _ }) => [
1231
+ l(e(Z), {
1232
+ value: _.at,
1233
+ tone: "default",
1234
+ compact: ""
1235
+ }, null, 8, ["value"])
1236
+ ]),
1237
+ "cell-user": a(({ row: _ }) => [
1238
+ l(e(E), {
1239
+ tone: _.user === null || _.user.name === null ? "muted" : "default"
1240
+ }, {
1241
+ default: a(() => [
1242
+ p(m(x(_.user)), 1)
1243
+ ]),
1244
+ _: 2
1245
+ }, 1032, ["tone"])
1246
+ ]),
1247
+ "cell-tool": a(({ row: _ }) => [
1248
+ l(e(E), {
1249
+ mono: "",
1250
+ size: "sm"
1251
+ }, {
1252
+ default: a(() => [
1253
+ p(m(_.tool), 1)
1254
+ ]),
1255
+ _: 2
1256
+ }, 1024)
1257
+ ]),
1258
+ "cell-outcome": a(({ row: _ }) => [
1259
+ l(e(M), {
1260
+ type: F(_).type,
1261
+ dot: ""
1262
+ }, {
1263
+ default: a(() => [
1264
+ p(m(F(_).label), 1)
1265
+ ]),
1266
+ _: 2
1267
+ }, 1032, ["type"])
1268
+ ]),
1269
+ "cell-duration_ms": a(({ row: _ }) => [
1270
+ l(e(E), {
1271
+ size: "sm",
1272
+ tone: "muted"
1273
+ }, {
1274
+ default: a(() => [
1275
+ p(m(e(n)("calls.ms", { count: _.duration_ms })), 1)
1276
+ ]),
1277
+ _: 2
1278
+ }, 1024)
1279
+ ]),
1280
+ "cell-client": a(({ row: _ }) => [
1281
+ _.client ? (c(), h(e(E), {
1282
+ key: 0,
1283
+ size: "sm"
1284
+ }, {
1285
+ default: a(() => [
1286
+ p(m(_.client), 1)
1287
+ ]),
1288
+ _: 2
1289
+ }, 1024)) : (c(), h(e(E), {
1290
+ key: 1,
1291
+ size: "sm",
1292
+ tone: "muted"
1293
+ }, {
1294
+ default: a(() => [...W[3] || (W[3] = [
1295
+ p("—", -1)
1296
+ ])]),
1297
+ _: 1
1298
+ }))
1299
+ ]),
1300
+ expanded: a(({ row: _ }) => [
1301
+ N("div", ka, [
1302
+ _.error ? (c(), h(e(E), {
1303
+ key: 0,
1304
+ tone: "danger",
1305
+ size: "sm",
1306
+ class: "wx-call-list__error"
1307
+ }, {
1308
+ default: a(() => [
1309
+ N("strong", null, m(e(n)("calls.error")) + ":", 1),
1310
+ p(" " + m(_.error), 1)
1311
+ ]),
1312
+ _: 2
1313
+ }, 1024)) : B("", !0),
1314
+ N("div", ga, [
1315
+ l(e(E), {
1316
+ size: "sm",
1317
+ weight: "semibold"
1318
+ }, {
1319
+ default: a(() => [
1320
+ p(m(e(n)("calls.request")), 1)
1321
+ ]),
1322
+ _: 1
1323
+ }),
1324
+ l(e(E), {
1325
+ size: "xs",
1326
+ tone: "muted"
1327
+ }, {
1328
+ default: a(() => [
1329
+ p(m(e(n)("calls.request-hint")), 1)
1330
+ ]),
1331
+ _: 1
1332
+ })
1333
+ ]),
1334
+ _.arguments ? (c(), K("pre", _a, m(_.arguments), 1)) : (c(), h(e(E), {
1335
+ key: 2,
1336
+ size: "sm",
1337
+ tone: "muted"
1338
+ }, {
1339
+ default: a(() => [
1340
+ p(m(e(n)("calls.no-arguments")), 1)
1341
+ ]),
1342
+ _: 1
1343
+ }))
1344
+ ])
1345
+ ]),
1346
+ "cell-card": a(({ row: _ }) => [
1347
+ l(e(ke), {
1348
+ variant: "plain",
1349
+ title: _.tool,
1350
+ subtitle: x(_.user)
1351
+ }, {
1352
+ media: a(() => [
1353
+ N("span", wa, [
1354
+ l(e(ue), { name: "sliders" })
1355
+ ])
1356
+ ]),
1357
+ meta: a(() => [
1358
+ l(e(M), {
1359
+ type: F(_).type,
1360
+ dot: "",
1361
+ size: "sm"
1362
+ }, {
1363
+ default: a(() => [
1364
+ p(m(F(_).label), 1)
1365
+ ]),
1366
+ _: 2
1367
+ }, 1032, ["type"]),
1368
+ l(e(Z), {
1369
+ value: _.at,
1370
+ compact: ""
1371
+ }, null, 8, ["value"]),
1372
+ _.client ? (c(), h(e(E), {
1373
+ key: 0,
1374
+ size: "xs",
1375
+ tone: "muted"
1376
+ }, {
1377
+ default: a(() => [
1378
+ p(m(_.client), 1)
1379
+ ]),
1380
+ _: 2
1381
+ }, 1024)) : B("", !0)
1382
+ ]),
1383
+ default: a(() => [
1384
+ C(_) ? (c(), h(e(le), {
1385
+ key: 0,
1386
+ direction: "vertical",
1387
+ size: "xs",
1388
+ class: "wx-call-list__card-details"
1389
+ }, {
1390
+ default: a(() => [
1391
+ _.error ? (c(), h(e(E), {
1392
+ key: 0,
1393
+ tone: "danger",
1394
+ size: "sm"
1395
+ }, {
1396
+ default: a(() => [
1397
+ p(m(_.error), 1)
1398
+ ]),
1399
+ _: 2
1400
+ }, 1024)) : B("", !0),
1401
+ _.arguments ? (c(), h(e(E), {
1402
+ key: 1,
1403
+ size: "xs",
1404
+ tone: "muted"
1405
+ }, {
1406
+ default: a(() => [
1407
+ p(m(e(n)("calls.request")), 1)
1408
+ ]),
1409
+ _: 1
1410
+ })) : B("", !0),
1411
+ _.arguments ? (c(), K("pre", xa, m(_.arguments), 1)) : B("", !0)
1412
+ ]),
1413
+ _: 2
1414
+ }, 1024)) : B("", !0)
1415
+ ]),
1416
+ _: 2
1417
+ }, 1032, ["title", "subtitle"])
1418
+ ]),
1419
+ _: 1
1420
+ }, 8, ["data", "columns", "loading", "expandable", "empty-text", "filters-count", "filters-label"])
1421
+ ], 512));
1422
+ }
1423
+ });
1424
+ function $a(s) {
1425
+ const r = `${s.apiPath}/auth/connections`;
1426
+ return {
1427
+ list: (o = "mine") => s.http.get(r, { query: { all: o === "all" ? 1 : void 0 } }).then((i) => ({
1428
+ data: i.data,
1429
+ scope: i.meta.scope,
1430
+ canSeeEverybody: i.meta.can_see_everybody
1431
+ })),
1432
+ disconnect: (o) => s.http.delete(`${r}/${o}`).then((i) => i.data)
1433
+ };
1434
+ }
1435
+ const Va = {
1436
+ class: "wx-connection-list__glyph",
1437
+ "aria-hidden": "true"
1438
+ }, Ue = 560, Aa = /* @__PURE__ */ X({
1439
+ __name: "ConnectionList",
1440
+ props: {
1441
+ scope: { default: "mine" }
1442
+ },
1443
+ setup(s, { expose: r }) {
1444
+ const o = s, i = te(), v = $a(i);
1445
+ se();
1446
+ const k = J("webx-auth"), z = ce(), n = ne("root"), y = he(n), O = P(() => y.value > 0 && y.value < Ue), u = A([]), w = A(!1), V = A(null), f = P(() => O.value ? [{ key: "card", label: "" }] : [
1447
+ { key: "client", label: k("connections.client"), minWidth: 210 },
1448
+ ...o.scope === "all" ? [{ key: "user", label: k("connections.who"), minWidth: 140 }] : [],
1449
+ { key: "read_only", label: k("connections.allowed"), minWidth: 160 },
1450
+ { key: "connected_at", label: k("connections.connected"), hideBelow: 860 },
1451
+ { key: "last_used_at", label: k("connections.last-used"), minWidth: 130 },
1452
+ { key: "end", label: "", align: "right", width: 140 }
1453
+ ]);
1454
+ function S(g) {
1455
+ return g.user.name ?? k("calls.deleted", { id: g.user.id });
1456
+ }
1457
+ function $(g) {
1458
+ if (g.read_only) return k("connections.read-only");
1459
+ if (o.scope !== "all") return k("connections.full-you");
1460
+ const D = g.user.name?.split(" ")[0];
1461
+ return k("connections.full", { name: D || S(g) });
1462
+ }
1463
+ async function x() {
1464
+ w.value = !0;
1465
+ try {
1466
+ u.value = (await v.list(o.scope)).data;
1467
+ } catch (g) {
1468
+ G.danger(z(g));
1469
+ } finally {
1470
+ w.value = !1;
1471
+ }
1472
+ }
1473
+ async function T(g) {
1474
+ if (await xe({
1475
+ title: k("connections.confirm-title", { client: g.client }),
1476
+ message: k("connections.confirm-text"),
1477
+ confirmText: k("connections.confirm"),
1478
+ cancelText: k("connections.cancel"),
1479
+ tone: "danger"
1480
+ })) {
1481
+ V.value = g.id;
1482
+ try {
1483
+ const t = await v.disconnect(g.id);
1484
+ u.value = u.value.map((b) => b.id === t.id ? t : b), G.success(k("connections.done", { client: g.client }));
1485
+ } catch (t) {
1486
+ G.danger(z(t));
1487
+ } finally {
1488
+ V.value = null;
1489
+ }
1490
+ }
1491
+ }
1492
+ return de(() => o.scope, x, { immediate: !0 }), r({ reload: x }), (g, D) => (c(), K("div", {
1493
+ ref_key: "root",
1494
+ ref: n,
1495
+ class: "wx-connection-list"
1496
+ }, [
1497
+ l(e(be), {
1498
+ data: u.value,
1499
+ columns: f.value,
1500
+ "row-key": "id",
1501
+ flush: "",
1502
+ loading: w.value,
1503
+ clickable: !1,
1504
+ "empty-text": s.scope === "all" ? e(k)("connections.empty-all") : e(k)("connections.empty"),
1505
+ "cards-below": Ue,
1506
+ "row-class": (t) => t.revoked_at ? "is-ended" : ""
1507
+ }, {
1508
+ "cell-client": a(({ row: t }) => [
1509
+ l(e(le), {
1510
+ direction: "vertical",
1511
+ size: "none"
1512
+ }, {
1513
+ default: a(() => [
1514
+ l(e(E), {
1515
+ tone: t.revoked_at ? "muted" : "default",
1516
+ weight: "medium"
1517
+ }, {
1518
+ default: a(() => [
1519
+ p(m(t.client), 1)
1520
+ ]),
1521
+ _: 2
1522
+ }, 1032, ["tone"]),
1523
+ l(e(E), {
1524
+ size: "xs",
1525
+ tone: "muted"
1526
+ }, {
1527
+ default: a(() => [
1528
+ p(m(e(k)("connections.returns-to", { host: t.host })), 1)
1529
+ ]),
1530
+ _: 2
1531
+ }, 1024)
1532
+ ]),
1533
+ _: 2
1534
+ }, 1024)
1535
+ ]),
1536
+ "cell-user": a(({ row: t }) => [
1537
+ l(e(E), {
1538
+ tone: t.user.name === null ? "muted" : "default"
1539
+ }, {
1540
+ default: a(() => [
1541
+ p(m(S(t)), 1)
1542
+ ]),
1543
+ _: 2
1544
+ }, 1032, ["tone"])
1545
+ ]),
1546
+ "cell-read_only": a(({ row: t }) => [
1547
+ t.revoked_at ? (c(), h(e(M), {
1548
+ key: 0,
1549
+ type: "default",
1550
+ dot: ""
1551
+ }, {
1552
+ default: a(() => [
1553
+ p(m(e(k)("connections.disconnected")), 1)
1554
+ ]),
1555
+ _: 1
1556
+ })) : (c(), h(e(M), {
1557
+ key: 1,
1558
+ type: t.read_only ? "info" : "success",
1559
+ dot: ""
1560
+ }, {
1561
+ default: a(() => [
1562
+ p(m($(t)), 1)
1563
+ ]),
1564
+ _: 2
1565
+ }, 1032, ["type"]))
1566
+ ]),
1567
+ "cell-connected_at": a(({ row: t }) => [
1568
+ l(e(Z), {
1569
+ value: t.connected_at,
1570
+ tone: "muted",
1571
+ compact: ""
1572
+ }, null, 8, ["value"])
1573
+ ]),
1574
+ "cell-last_used_at": a(({ row: t }) => [
1575
+ t.last_used_at ? (c(), h(e(Z), {
1576
+ key: 0,
1577
+ value: t.last_used_at,
1578
+ tone: "default",
1579
+ compact: ""
1580
+ }, null, 8, ["value"])) : (c(), h(e(E), {
1581
+ key: 1,
1582
+ size: "sm",
1583
+ tone: "muted"
1584
+ }, {
1585
+ default: a(() => [
1586
+ p(m(e(k)("connections.never-used")), 1)
1587
+ ]),
1588
+ _: 1
1589
+ }))
1590
+ ]),
1591
+ "cell-end": a(({ row: t }) => [
1592
+ t.revoked_at ? B("", !0) : (c(), h(e(j), {
1593
+ key: 0,
1594
+ type: "danger",
1595
+ variant: "text",
1596
+ size: "sm",
1597
+ loading: V.value === t.id,
1598
+ onClick: (b) => T(t)
1599
+ }, {
1600
+ default: a(() => [
1601
+ p(m(e(k)("connections.disconnect")), 1)
1602
+ ]),
1603
+ _: 1
1604
+ }, 8, ["loading", "onClick"]))
1605
+ ]),
1606
+ "cell-card": a(({ row: t }) => [
1607
+ l(e(ke), {
1608
+ variant: "plain",
1609
+ title: t.client,
1610
+ subtitle: e(k)("connections.returns-to", { host: t.host })
1611
+ }, {
1612
+ media: a(() => [
1613
+ N("span", Va, [
1614
+ l(e(ue), { name: "link" })
1615
+ ])
1616
+ ]),
1617
+ meta: a(() => [
1618
+ t.revoked_at ? (c(), h(e(M), {
1619
+ key: 0,
1620
+ type: "default",
1621
+ dot: "",
1622
+ size: "sm"
1623
+ }, {
1624
+ default: a(() => [
1625
+ p(m(e(k)("connections.disconnected")), 1)
1626
+ ]),
1627
+ _: 1
1628
+ })) : (c(), h(e(M), {
1629
+ key: 1,
1630
+ type: t.read_only ? "info" : "success",
1631
+ dot: "",
1632
+ size: "sm"
1633
+ }, {
1634
+ default: a(() => [
1635
+ p(m($(t)), 1)
1636
+ ]),
1637
+ _: 2
1638
+ }, 1032, ["type"])),
1639
+ s.scope === "all" ? (c(), h(e(E), {
1640
+ key: 2,
1641
+ size: "xs",
1642
+ tone: "muted"
1643
+ }, {
1644
+ default: a(() => [
1645
+ p(m(S(t)), 1)
1646
+ ]),
1647
+ _: 2
1648
+ }, 1024)) : B("", !0),
1649
+ t.last_used_at ? (c(), h(e(Z), {
1650
+ key: 3,
1651
+ value: t.last_used_at,
1652
+ compact: ""
1653
+ }, null, 8, ["value"])) : (c(), h(e(E), {
1654
+ key: 4,
1655
+ size: "xs",
1656
+ tone: "muted"
1657
+ }, {
1658
+ default: a(() => [
1659
+ p(m(e(k)("connections.never-used")), 1)
1660
+ ]),
1661
+ _: 1
1662
+ }))
1663
+ ]),
1664
+ actions: a(() => [
1665
+ t.revoked_at ? B("", !0) : (c(), h(e(j), {
1666
+ key: 0,
1667
+ type: "danger",
1668
+ variant: "text",
1669
+ size: "sm",
1670
+ loading: V.value === t.id,
1671
+ onClick: (b) => T(t)
1672
+ }, {
1673
+ default: a(() => [
1674
+ p(m(e(k)("connections.disconnect")), 1)
1675
+ ]),
1676
+ _: 1
1677
+ }, 8, ["loading", "onClick"]))
1678
+ ]),
1679
+ _: 2
1680
+ }, 1032, ["title", "subtitle"])
1681
+ ]),
1682
+ _: 1
1683
+ }, 8, ["data", "columns", "loading", "empty-text", "row-class"])
1684
+ ], 512));
1685
+ }
1686
+ });
1687
+ async function za(s) {
1688
+ try {
1689
+ if (navigator.clipboard?.writeText)
1690
+ return await navigator.clipboard.writeText(s), !0;
1691
+ } catch {
1692
+ }
1693
+ return Sa(s);
1694
+ }
1695
+ function Sa(s) {
1696
+ const r = document.createElement("textarea");
1697
+ r.value = s, r.setAttribute("readonly", ""), r.style.position = "fixed", r.style.opacity = "0", document.body.append(r), r.select();
1698
+ try {
1699
+ return document.execCommand("copy");
1700
+ } catch {
1701
+ return !1;
1702
+ } finally {
1703
+ r.remove();
1704
+ }
1705
+ }
1706
+ function Ge(s) {
1707
+ const r = `${s.apiPath}/auth/keys`;
1708
+ return {
1709
+ list: () => s.http.get(r).then((o) => ({
1710
+ data: o.data,
1711
+ scopes: o.meta.scopes,
1712
+ maxDays: o.meta.max_days
1713
+ })),
1714
+ issue: (o) => s.http.post(r, o).then((i) => ({ key: i.data, token: i.token })),
1715
+ revoke: (o) => s.http.delete(`${r}/${o}`).then((i) => i.data)
1716
+ };
1717
+ }
1718
+ const La = {
1719
+ key: 0,
1720
+ class: "wx-key-dialog"
1721
+ }, Ua = { class: "wx-key-dialog__secret" }, Ta = {
1722
+ key: 1,
1723
+ class: "wx-key-dialog"
1724
+ }, Wa = /* @__PURE__ */ X({
1725
+ __name: "KeyDialog",
1726
+ setup(s) {
1727
+ const { open: r, resolve: o, dismiss: i } = fe(), v = te(), k = Ge(v), z = me(v);
1728
+ se();
1729
+ const n = J("webx-auth"), y = ce(), O = [30, 90, 365, 1095, 3650], u = A({
1730
+ name: "",
1731
+ admin: null,
1732
+ access: "everything",
1733
+ scopes: [],
1734
+ days: 365
1735
+ }), w = A([]), V = A([]), f = A(!1), S = A({}), $ = A(null), x = A(!1), T = P(
1736
+ () => w.value.filter((C) => C !== "mcp:use").map((C) => ({ value: C, label: C }))
1737
+ ), g = P(() => [
1738
+ { value: "everything", label: n("keys.everything") },
1739
+ { value: "chosen", label: n("keys.chosen") }
1740
+ ]), D = P(
1741
+ () => O.map((C) => ({ value: C, label: n(`keys.days-${C}`) }))
1742
+ ), t = P(() => {
1743
+ const C = v.state.manifest?.modules.find((d) => d.id === "connect")?.meta;
1744
+ return typeof C?.url == "string" ? C.url : "";
1745
+ });
1746
+ k.list().then(
1747
+ (C) => w.value = C.scopes,
1748
+ (C) => G.danger(y(C))
1749
+ ), z.list({ active: "yes", per_page: 100, sort: "name" }).then(
1750
+ (C) => V.value = C.data.map((d) => ({
1751
+ value: d.id,
1752
+ label: `${d.name} · ${d.email}`
1753
+ })),
1754
+ (C) => G.danger(y(C))
1755
+ );
1756
+ function b(C) {
1757
+ return S.value[C]?.[0] ?? S.value[`${C}.0`]?.[0];
1758
+ }
1759
+ async function U() {
1760
+ if (S.value = {}, u.value.access === "chosen" && u.value.scopes.length === 0) {
1761
+ S.value = { scopes: [n("keys.scopes-required")] };
1762
+ return;
1763
+ }
1764
+ f.value = !0;
1765
+ try {
1766
+ $.value = await k.issue({
1767
+ name: u.value.name,
1768
+ admin: u.value.admin ?? 0,
1769
+ scopes: u.value.access === "chosen" ? u.value.scopes : [],
1770
+ days: u.value.days
1771
+ });
1772
+ } catch (C) {
1773
+ const d = C.body;
1774
+ d?.errors ? S.value = d.errors : G.danger(y(C));
1775
+ } finally {
1776
+ f.value = !1;
1777
+ }
1778
+ }
1779
+ async function Y() {
1780
+ $.value !== null && (await za($.value.token) ? x.value = !0 : G.danger(n("keys.copy-failed")));
1781
+ }
1782
+ function F() {
1783
+ $.value ? o($.value.key) : i();
1784
+ }
1785
+ return (C, d) => (c(), h(e(ye), {
1786
+ open: e(r),
1787
+ title: $.value ? e(n)("keys.issued-title") : e(n)("keys.issue"),
1788
+ width: 640,
1789
+ "onUpdate:open": d[5] || (d[5] = (W) => W ? void 0 : F())
1790
+ }, {
1791
+ footer: a(() => [
1792
+ l(e(le), { size: "sm" }, {
1793
+ default: a(() => [
1794
+ $.value ? (c(), h(e(j), {
1795
+ key: 0,
1796
+ type: "primary",
1797
+ onClick: F
1798
+ }, {
1799
+ default: a(() => [
1800
+ p(m(e(n)("keys.done")), 1)
1801
+ ]),
1802
+ _: 1
1803
+ })) : (c(), K(ie, { key: 1 }, [
1804
+ l(e(j), {
1805
+ variant: "outline",
1806
+ onClick: F
1807
+ }, {
1808
+ default: a(() => [
1809
+ p(m(e(n)("keys.cancel")), 1)
1810
+ ]),
1811
+ _: 1
1812
+ }),
1813
+ l(e(j), {
1814
+ type: "primary",
1815
+ loading: f.value,
1816
+ onClick: U
1817
+ }, {
1818
+ default: a(() => [
1819
+ p(m(e(n)("keys.issue-short")), 1)
1820
+ ]),
1821
+ _: 1
1822
+ }, 8, ["loading"])
1823
+ ], 64))
1824
+ ]),
1825
+ _: 1
1826
+ })
1827
+ ]),
1828
+ default: a(() => [
1829
+ $.value ? (c(), K("div", La, [
1830
+ l(e(oa), {
1831
+ type: "warning",
1832
+ closable: !1
1833
+ }, {
1834
+ default: a(() => [
1835
+ p(m(e(n)("keys.issued-text")), 1)
1836
+ ]),
1837
+ _: 1
1838
+ }),
1839
+ l(e(I), {
1840
+ label: e(n)("keys.secret")
1841
+ }, {
1842
+ default: a(() => [
1843
+ N("div", Ua, [
1844
+ l(e(ee), {
1845
+ "model-value": $.value.token,
1846
+ readonly: "",
1847
+ name: "token"
1848
+ }, null, 8, ["model-value"]),
1849
+ l(e(j), {
1850
+ type: "primary",
1851
+ onClick: Y
1852
+ }, {
1853
+ icon: a(() => [
1854
+ l(e(ue), {
1855
+ name: x.value ? "check" : "copy"
1856
+ }, null, 8, ["name"])
1857
+ ]),
1858
+ default: a(() => [
1859
+ p(" " + m(x.value ? e(n)("keys.copied") : e(n)("keys.copy")), 1)
1860
+ ]),
1861
+ _: 1
1862
+ })
1863
+ ])
1864
+ ]),
1865
+ _: 1
1866
+ }, 8, ["label"]),
1867
+ t.value ? (c(), h(e(I), {
1868
+ key: 0,
1869
+ label: e(n)("keys.address")
1870
+ }, {
1871
+ default: a(() => [
1872
+ l(e(ee), {
1873
+ "model-value": t.value,
1874
+ readonly: "",
1875
+ name: "address"
1876
+ }, null, 8, ["model-value"])
1877
+ ]),
1878
+ _: 1
1879
+ }, 8, ["label"])) : B("", !0),
1880
+ l(e(E), {
1881
+ size: "sm",
1882
+ tone: "muted"
1883
+ }, {
1884
+ default: a(() => [
1885
+ p(m(e(n)("keys.header-hint")), 1)
1886
+ ]),
1887
+ _: 1
1888
+ })
1889
+ ])) : (c(), K("div", Ta, [
1890
+ l(e(E), {
1891
+ size: "sm",
1892
+ tone: "muted"
1893
+ }, {
1894
+ default: a(() => [
1895
+ p(m(e(n)("keys.lead")), 1)
1896
+ ]),
1897
+ _: 1
1898
+ }),
1899
+ l(e(I), {
1900
+ label: e(n)("keys.name"),
1901
+ error: b("name"),
1902
+ help: e(n)("keys.name-hint")
1903
+ }, {
1904
+ default: a(() => [
1905
+ l(e(ee), {
1906
+ modelValue: u.value.name,
1907
+ "onUpdate:modelValue": d[0] || (d[0] = (W) => u.value.name = W),
1908
+ name: "name",
1909
+ autocomplete: "off"
1910
+ }, null, 8, ["modelValue"])
1911
+ ]),
1912
+ _: 1
1913
+ }, 8, ["label", "error", "help"]),
1914
+ l(e(I), {
1915
+ label: e(n)("keys.who"),
1916
+ error: b("admin"),
1917
+ help: e(n)("keys.who-hint")
1918
+ }, {
1919
+ default: a(() => [
1920
+ l(e(ae), {
1921
+ modelValue: u.value.admin,
1922
+ "onUpdate:modelValue": d[1] || (d[1] = (W) => u.value.admin = W),
1923
+ options: V.value,
1924
+ filterable: "",
1925
+ name: "admin"
1926
+ }, null, 8, ["modelValue", "options"])
1927
+ ]),
1928
+ _: 1
1929
+ }, 8, ["label", "error", "help"]),
1930
+ l(e(I), {
1931
+ label: e(n)("keys.allowed")
1932
+ }, {
1933
+ default: a(() => [
1934
+ l(e(ia), {
1935
+ modelValue: u.value.access,
1936
+ "onUpdate:modelValue": d[2] || (d[2] = (W) => u.value.access = W),
1937
+ options: g.value,
1938
+ name: "access"
1939
+ }, null, 8, ["modelValue", "options"])
1940
+ ]),
1941
+ _: 1
1942
+ }, 8, ["label"]),
1943
+ u.value.access === "chosen" ? (c(), h(e(I), {
1944
+ key: 0,
1945
+ label: e(n)("keys.scopes"),
1946
+ error: b("scopes"),
1947
+ help: e(n)("keys.scopes-hint")
1948
+ }, {
1949
+ default: a(() => [
1950
+ l(e(ae), {
1951
+ modelValue: u.value.scopes,
1952
+ "onUpdate:modelValue": d[3] || (d[3] = (W) => u.value.scopes = W),
1953
+ options: T.value,
1954
+ multiple: "",
1955
+ filterable: "",
1956
+ name: "scopes"
1957
+ }, null, 8, ["modelValue", "options"])
1958
+ ]),
1959
+ _: 1
1960
+ }, 8, ["label", "error", "help"])) : B("", !0),
1961
+ l(e(I), {
1962
+ label: e(n)("keys.lifetime"),
1963
+ error: b("days"),
1964
+ help: e(n)("keys.lifetime-hint")
1965
+ }, {
1966
+ default: a(() => [
1967
+ l(e(ae), {
1968
+ modelValue: u.value.days,
1969
+ "onUpdate:modelValue": d[4] || (d[4] = (W) => u.value.days = W),
1970
+ options: D.value,
1971
+ name: "days"
1972
+ }, null, 8, ["modelValue", "options"])
1973
+ ]),
1974
+ _: 1
1975
+ }, 8, ["label", "error", "help"])
1976
+ ]))
1977
+ ]),
1978
+ _: 1
1979
+ }, 8, ["open", "title"]));
1980
+ }
1981
+ }), Fa = {
1982
+ class: "wx-key-list__glyph",
1983
+ "aria-hidden": "true"
1984
+ }, Te = 560, Pa = /* @__PURE__ */ X({
1985
+ __name: "KeyList",
1986
+ setup(s, { expose: r }) {
1987
+ const o = te(), i = Ge(o);
1988
+ se();
1989
+ const v = J("webx-auth"), k = ce(), z = ne("root"), n = he(z), y = P(() => n.value > 0 && n.value < Te), O = A([]), u = A(!1), w = A(null), V = P(() => y.value ? [{ key: "card", label: "" }] : [
1990
+ { key: "name", label: v("keys.name"), minWidth: 200 },
1991
+ { key: "user", label: v("keys.who"), minWidth: 140 },
1992
+ { key: "scopes", label: v("keys.allowed"), minWidth: 180 },
1993
+ { key: "expires_at", label: v("keys.expires"), minWidth: 120 },
1994
+ { key: "last_used_at", label: v("keys.last-used"), minWidth: 120, hideBelow: 860 },
1995
+ { key: "end", label: "", align: "right", width: 120 }
1996
+ ]);
1997
+ function f(g) {
1998
+ return g.user.name ?? v("keys.deleted", { id: g.user.id });
1999
+ }
2000
+ function S(g) {
2001
+ return g.created_by?.name ? v("keys.issued-by", { name: g.created_by.name }) : v("keys.issued-console");
2002
+ }
2003
+ function $(g) {
2004
+ return g.everything ? v("keys.full", { name: g.user.name?.split(" ")[0] || f(g) }) : g.scopes.join(", ");
2005
+ }
2006
+ async function x() {
2007
+ u.value = !0;
2008
+ try {
2009
+ O.value = (await i.list()).data;
2010
+ } catch (g) {
2011
+ G.danger(k(g));
2012
+ } finally {
2013
+ u.value = !1;
2014
+ }
2015
+ }
2016
+ async function T(g) {
2017
+ if (await xe({
2018
+ title: v("keys.confirm-title", { name: g.name }),
2019
+ message: v("keys.confirm-text"),
2020
+ confirmText: v("keys.confirm"),
2021
+ cancelText: v("keys.cancel"),
2022
+ tone: "danger"
2023
+ })) {
2024
+ w.value = g.id;
2025
+ try {
2026
+ const t = await i.revoke(g.id);
2027
+ O.value = O.value.map((b) => b.id === t.id ? t : b), G.success(v("keys.revoked-done", { name: g.name }));
2028
+ } catch (t) {
2029
+ G.danger(k(t));
2030
+ } finally {
2031
+ w.value = null;
2032
+ }
2033
+ }
2034
+ }
2035
+ return Qe(x), r({ reload: x }), (g, D) => (c(), K("div", {
2036
+ ref_key: "root",
2037
+ ref: z,
2038
+ class: "wx-key-list"
2039
+ }, [
2040
+ l(e(be), {
2041
+ data: O.value,
2042
+ columns: V.value,
2043
+ "row-key": "id",
2044
+ flush: "",
2045
+ loading: u.value,
2046
+ clickable: !1,
2047
+ "empty-text": e(v)("keys.empty"),
2048
+ "cards-below": Te,
2049
+ "row-class": (t) => t.state === "live" ? "" : "is-ended"
2050
+ }, {
2051
+ "cell-name": a(({ row: t }) => [
2052
+ l(e(le), {
2053
+ direction: "vertical",
2054
+ size: "none"
2055
+ }, {
2056
+ default: a(() => [
2057
+ l(e(E), {
2058
+ tone: t.state === "live" ? "default" : "muted",
2059
+ weight: "medium"
2060
+ }, {
2061
+ default: a(() => [
2062
+ p(m(t.name), 1)
2063
+ ]),
2064
+ _: 2
2065
+ }, 1032, ["tone"]),
2066
+ l(e(E), {
2067
+ size: "xs",
2068
+ tone: "muted"
2069
+ }, {
2070
+ default: a(() => [
2071
+ p(m(S(t)) + " · ", 1),
2072
+ l(e(Z), {
2073
+ value: t.created_at,
2074
+ tone: "muted",
2075
+ compact: ""
2076
+ }, null, 8, ["value"])
2077
+ ]),
2078
+ _: 2
2079
+ }, 1024)
2080
+ ]),
2081
+ _: 2
2082
+ }, 1024)
2083
+ ]),
2084
+ "cell-user": a(({ row: t }) => [
2085
+ l(e(E), {
2086
+ tone: t.user.name === null ? "muted" : "default"
2087
+ }, {
2088
+ default: a(() => [
2089
+ p(m(f(t)), 1)
2090
+ ]),
2091
+ _: 2
2092
+ }, 1032, ["tone"])
2093
+ ]),
2094
+ "cell-scopes": a(({ row: t }) => [
2095
+ t.state === "revoked" ? (c(), h(e(M), {
2096
+ key: 0,
2097
+ type: "default",
2098
+ dot: ""
2099
+ }, {
2100
+ default: a(() => [
2101
+ p(m(e(v)("keys.revoked")), 1)
2102
+ ]),
2103
+ _: 1
2104
+ })) : t.state === "expired" ? (c(), h(e(M), {
2105
+ key: 1,
2106
+ type: "default",
2107
+ dot: ""
2108
+ }, {
2109
+ default: a(() => [
2110
+ p(m(e(v)("keys.expired")), 1)
2111
+ ]),
2112
+ _: 1
2113
+ })) : (c(), h(e(M), {
2114
+ key: 2,
2115
+ type: t.everything ? "success" : "info",
2116
+ dot: ""
2117
+ }, {
2118
+ default: a(() => [
2119
+ p(m($(t)), 1)
2120
+ ]),
2121
+ _: 2
2122
+ }, 1032, ["type"]))
2123
+ ]),
2124
+ "cell-expires_at": a(({ row: t }) => [
2125
+ t.expires_at ? (c(), h(e(Z), {
2126
+ key: 0,
2127
+ value: t.expires_at,
2128
+ compact: ""
2129
+ }, null, 8, ["value"])) : B("", !0)
2130
+ ]),
2131
+ "cell-last_used_at": a(({ row: t }) => [
2132
+ t.last_used_at ? (c(), h(e(Z), {
2133
+ key: 0,
2134
+ value: t.last_used_at,
2135
+ compact: ""
2136
+ }, null, 8, ["value"])) : (c(), h(e(E), {
2137
+ key: 1,
2138
+ size: "sm",
2139
+ tone: "muted"
2140
+ }, {
2141
+ default: a(() => [
2142
+ p(m(e(v)("keys.never-used")), 1)
2143
+ ]),
2144
+ _: 1
2145
+ }))
2146
+ ]),
2147
+ "cell-end": a(({ row: t }) => [
2148
+ t.state === "live" ? (c(), h(e(j), {
2149
+ key: 0,
2150
+ type: "danger",
2151
+ variant: "text",
2152
+ size: "sm",
2153
+ loading: w.value === t.id,
2154
+ onClick: (b) => T(t)
2155
+ }, {
2156
+ default: a(() => [
2157
+ p(m(e(v)("keys.revoke")), 1)
2158
+ ]),
2159
+ _: 1
2160
+ }, 8, ["loading", "onClick"])) : B("", !0)
2161
+ ]),
2162
+ "cell-card": a(({ row: t }) => [
2163
+ l(e(ke), {
2164
+ variant: "plain",
2165
+ title: t.name,
2166
+ subtitle: f(t)
2167
+ }, {
2168
+ media: a(() => [
2169
+ N("span", Fa, [
2170
+ l(e(ue), { name: "lock" })
2171
+ ])
2172
+ ]),
2173
+ meta: a(() => [
2174
+ t.state === "revoked" ? (c(), h(e(M), {
2175
+ key: 0,
2176
+ type: "default",
2177
+ dot: "",
2178
+ size: "sm"
2179
+ }, {
2180
+ default: a(() => [
2181
+ p(m(e(v)("keys.revoked")), 1)
2182
+ ]),
2183
+ _: 1
2184
+ })) : t.state === "expired" ? (c(), h(e(M), {
2185
+ key: 1,
2186
+ type: "default",
2187
+ dot: "",
2188
+ size: "sm"
2189
+ }, {
2190
+ default: a(() => [
2191
+ p(m(e(v)("keys.expired")), 1)
2192
+ ]),
2193
+ _: 1
2194
+ })) : (c(), h(e(M), {
2195
+ key: 2,
2196
+ type: t.everything ? "success" : "info",
2197
+ dot: "",
2198
+ size: "sm"
2199
+ }, {
2200
+ default: a(() => [
2201
+ p(m($(t)), 1)
2202
+ ]),
2203
+ _: 2
2204
+ }, 1032, ["type"])),
2205
+ t.expires_at ? (c(), h(e(E), {
2206
+ key: 3,
2207
+ size: "xs",
2208
+ tone: "muted"
2209
+ }, {
2210
+ default: a(() => [
2211
+ p(m(e(v)("keys.until")) + " ", 1),
2212
+ l(e(Z), {
2213
+ value: t.expires_at,
2214
+ compact: ""
2215
+ }, null, 8, ["value"])
2216
+ ]),
2217
+ _: 2
2218
+ }, 1024)) : B("", !0)
2219
+ ]),
2220
+ actions: a(() => [
2221
+ t.state === "live" ? (c(), h(e(j), {
2222
+ key: 0,
2223
+ type: "danger",
2224
+ variant: "text",
2225
+ size: "sm",
2226
+ loading: w.value === t.id,
2227
+ onClick: (b) => T(t)
2228
+ }, {
2229
+ default: a(() => [
2230
+ p(m(e(v)("keys.revoke")), 1)
2231
+ ]),
2232
+ _: 1
2233
+ }, 8, ["loading", "onClick"])) : B("", !0)
2234
+ ]),
2235
+ _: 2
2236
+ }, 1032, ["title", "subtitle"])
2237
+ ]),
2238
+ _: 1
2239
+ }, 8, ["data", "columns", "loading", "empty-text", "row-class"])
2240
+ ], 512));
2241
+ }
2242
+ }), Oa = /* @__PURE__ */ X({
2243
+ __name: "AdminsPage",
2244
+ props: {
2245
+ base: { default: "/admins" },
2246
+ current: { default: "admins" },
2247
+ avatarField: { default: void 0 },
2248
+ resolveAvatar: { type: Function, default: void 0 }
2249
+ },
2250
+ setup(s) {
2251
+ const r = s, o = te(), i = me(o), v = r.avatarField ?? Me(o) ?? void 0, k = r.resolveAvatar ?? qe(o) ?? void 0, z = la(), n = sa();
2252
+ se();
2253
+ const y = J("webx-auth"), O = ce(), u = ne("list"), w = ne("keys"), V = A(null), f = pe(ba), S = pe(Wa), $ = o.can("admins.manage"), x = o.can("admins.audit"), T = P(
2254
+ () => o.state.manifest?.modules.find((F) => F.id === "admins")?.title ?? y("admins.title")
2255
+ ), g = P(() => {
2256
+ const F = [{ value: "admins", label: T.value }];
2257
+ return x && F.push({ value: "calls", label: y("calls.title") }), $ && F.push({ value: "connections", label: y("connections.title") }), $ && F.push({ value: "keys", label: y("keys.title") }), F.length > 1 ? F : void 0;
2258
+ }), D = P({
2259
+ get: () => r.current,
2260
+ set: (F) => {
2261
+ const C = F === "admins" ? r.base : `${r.base}/${String(F)}`;
2262
+ C !== n.path && z.push(C);
2263
+ }
2264
+ }), t = P(() => $ ? r.current === "admins" ? [
2265
+ {
2266
+ key: "new",
2267
+ label: y("admins.new-short"),
2268
+ icon: "plus",
2269
+ primary: !0,
2270
+ run: () => {
2271
+ U(null);
2272
+ }
2273
+ }
2274
+ ] : r.current === "keys" ? [
2275
+ {
2276
+ key: "issue",
2277
+ label: y("keys.issue-short"),
2278
+ icon: "plus",
2279
+ primary: !0,
2280
+ run: () => {
2281
+ b();
2282
+ }
2283
+ }
2284
+ ] : [] : []);
2285
+ async function b() {
2286
+ await S() && w.value?.reload();
2287
+ }
2288
+ async function U(F) {
2289
+ V.value = F, await f({ admin: F, avatarField: v }) && u.value?.reload();
2290
+ }
2291
+ async function Y(F) {
2292
+ if (await xe({
2293
+ title: y("admins.delete-title", { name: F.name }),
2294
+ message: y("admins.delete-text"),
2295
+ confirmText: y("admins.delete"),
2296
+ cancelText: y("admins.cancel"),
2297
+ tone: "danger"
2298
+ }))
2299
+ try {
2300
+ await i.remove(F.id), G.success(y("admins.deleted")), u.value?.reload();
2301
+ } catch (d) {
2302
+ G.danger(O(d));
2303
+ }
2304
+ }
2305
+ return (F, C) => (c(), h(e(aa), {
2306
+ view: D.value,
2307
+ "onUpdate:view": C[0] || (C[0] = (d) => D.value = d),
2308
+ title: T.value,
2309
+ views: g.value,
2310
+ actions: t.value
2311
+ }, {
2312
+ default: a(() => [
2313
+ s.current === "calls" ? (c(), h(Ca, { key: 0 })) : s.current === "connections" ? (c(), h(Aa, {
2314
+ key: 1,
2315
+ scope: "all"
2316
+ })) : s.current === "keys" ? (c(), h(Pa, {
2317
+ key: 2,
2318
+ ref: "keys"
2319
+ }, null, 512)) : (c(), h(je, {
2320
+ key: 3,
2321
+ ref_key: "list",
2322
+ ref: u,
2323
+ removable: e($),
2324
+ "resolve-avatar": e(k),
2325
+ onOpen: U,
2326
+ onRemove: Y
2327
+ }, null, 8, ["removable", "resolve-avatar"]))
2328
+ ]),
2329
+ _: 1
2330
+ }, 8, ["view", "title", "views", "actions"]));
2331
+ }
2332
+ });
2333
+ function et(s = {}) {
2334
+ const r = s.path ?? "/admins", o = (i) => ({
2335
+ render: () => Be(Oa, {
2336
+ base: r,
2337
+ current: i,
2338
+ avatarField: s.avatarField,
2339
+ resolveAvatar: s.resolveAvatar
2340
+ })
2341
+ });
2342
+ return {
2343
+ id: "admins",
2344
+ path: r,
2345
+ routes: [
2346
+ { path: r, name: "webx.admins", component: o("admins") },
2347
+ // What their agents did, which agents they let in, and their keys: more views of the same
2348
+ // section, each with an address of its own so that its filters survive a trip to the
2349
+ // people and back.
2350
+ { path: `${r}/calls`, name: "webx.admins.calls", component: o("calls") },
2351
+ {
2352
+ path: `${r}/connections`,
2353
+ name: "webx.admins.connections",
2354
+ component: o("connections")
2355
+ },
2356
+ // Keys for programs: a connection without a browser, issued by somebody who manages
2357
+ // the people it acts as.
2358
+ { path: `${r}/keys`, name: "webx.admins.keys", component: o("keys") }
2359
+ ]
2360
+ };
2361
+ }
2362
+ function at(s = {}) {
2363
+ const r = s.path ?? "/connect";
2364
+ return {
2365
+ id: "connect",
2366
+ path: r,
2367
+ routes: [{ path: r, name: "webx.connect", component: () => import("./ConnectPage-CGGeG8--.js") }]
2368
+ };
2369
+ }
2370
+ const Ba = /* @__PURE__ */ X({
2371
+ __name: "AdminPicker",
2372
+ props: {
2373
+ multiple: { type: Boolean, default: !1 },
2374
+ title: { default: void 0 },
2375
+ resolveAvatar: { type: Function, default: void 0 }
2376
+ },
2377
+ setup(s) {
2378
+ const r = s, { open: o, resolve: i, dismiss: v } = fe();
2379
+ se();
2380
+ const k = J("webx-auth"), z = ne("list"), n = A(0);
2381
+ function y(u) {
2382
+ i(u);
2383
+ }
2384
+ function O(u) {
2385
+ n.value = u.length;
2386
+ }
2387
+ return (u, w) => (c(), h(e(ye), {
2388
+ open: e(o),
2389
+ "onUpdate:open": w[2] || (w[2] = (V) => we(o) ? o.value = V : null),
2390
+ title: s.title ?? e(k)(s.multiple ? "admins.select-many" : "admins.select-one"),
2391
+ width: 880
2392
+ }, Oe({
2393
+ default: a(() => [
2394
+ l(je, {
2395
+ ref_key: "list",
2396
+ ref: z,
2397
+ picking: "",
2398
+ multiple: s.multiple,
2399
+ "resolve-avatar": r.resolveAvatar,
2400
+ onChosen: y,
2401
+ onSelection: O
2402
+ }, null, 8, ["multiple", "resolve-avatar"])
2403
+ ]),
2404
+ _: 2
2405
+ }, [
2406
+ s.multiple ? {
2407
+ name: "footer",
2408
+ fn: a(() => [
2409
+ l(e(le), {
2410
+ size: "sm",
2411
+ align: "center"
2412
+ }, {
2413
+ default: a(() => [
2414
+ l(e(E), {
2415
+ size: "sm",
2416
+ tone: "muted"
2417
+ }, {
2418
+ default: a(() => [
2419
+ p(m(e(k)("admins.chosen", { count: n.value })), 1)
2420
+ ]),
2421
+ _: 1
2422
+ }),
2423
+ l(e(j), {
2424
+ variant: "outline",
2425
+ onClick: w[0] || (w[0] = (V) => e(v)())
2426
+ }, {
2427
+ default: a(() => [
2428
+ p(m(e(k)("admins.cancel")), 1)
2429
+ ]),
2430
+ _: 1
2431
+ }),
2432
+ l(e(j), {
2433
+ type: "primary",
2434
+ disabled: n.value === 0,
2435
+ onClick: w[1] || (w[1] = (V) => e(i)(z.value?.chosen() ?? []))
2436
+ }, {
2437
+ default: a(() => [
2438
+ p(m(e(k)("admins.save")), 1)
2439
+ ]),
2440
+ _: 1
2441
+ }, 8, ["disabled"])
2442
+ ]),
2443
+ _: 1
2444
+ })
2445
+ ]),
2446
+ key: "0"
2447
+ } : void 0
2448
+ ]), 1032, ["open", "title"]));
2449
+ }
2450
+ }), He = pe(Ba);
2451
+ async function tt(s = {}) {
2452
+ return (await He({ ...s, multiple: !1 }))?.[0];
2453
+ }
2454
+ function lt(s = {}) {
2455
+ return He({ ...s, multiple: !0 });
2456
+ }
2457
+ const Ra = { class: "wx-profile-host" }, Ea = { class: "wx-profile" }, Da = {
2458
+ key: 0,
2459
+ class: "wx-profile__aside"
2460
+ }, Ia = { class: "wx-profile__fields" }, Na = /* @__PURE__ */ X({
2461
+ __name: "ProfileDialog",
2462
+ props: {
2463
+ avatarField: { default: void 0 }
2464
+ },
2465
+ setup(s) {
2466
+ const r = s, { resolve: o, dismiss: i, open: v } = fe(), k = te(), z = Ce();
2467
+ se();
2468
+ const n = J("webx-auth"), y = ce(), O = A(!1), u = A({}), w = A({
2469
+ name: k.state.user?.name ?? "",
2470
+ avatar: k.state.user?.avatar ?? null,
2471
+ password: "",
2472
+ current_password: ""
2473
+ }), V = A(w.value.avatar ? { path: w.value.avatar } : null);
2474
+ function f($) {
2475
+ return u.value[$]?.[0];
2476
+ }
2477
+ async function S() {
2478
+ O.value = !0, u.value = {};
2479
+ try {
2480
+ await z.updateProfile({
2481
+ name: w.value.name,
2482
+ avatar: V.value?.path ?? null,
2483
+ // Blank is left out entirely rather than sent as an empty string: the server reads a
2484
+ // filled password as "change it", and an empty one would be a change to nothing.
2485
+ ...w.value.password ? { password: w.value.password, current_password: w.value.current_password } : {}
2486
+ }), G.success(n("profile.saved")), o(!0);
2487
+ } catch ($) {
2488
+ const x = $.body;
2489
+ x?.errors ? u.value = x.errors : G.danger(y($));
2490
+ } finally {
2491
+ O.value = !1;
2492
+ }
2493
+ }
2494
+ return ($, x) => (c(), h(e(ye), {
2495
+ open: e(v),
2496
+ "onUpdate:open": x[5] || (x[5] = (T) => we(v) ? v.value = T : null),
2497
+ title: e(n)("profile.title"),
2498
+ width: 560
2499
+ }, {
2500
+ footer: a(() => [
2501
+ l(e(j), {
2502
+ onClick: x[4] || (x[4] = (T) => e(i)())
2503
+ }, {
2504
+ default: a(() => [
2505
+ p(m(e(n)("profile.cancel")), 1)
2506
+ ]),
2507
+ _: 1
2508
+ }),
2509
+ l(e(j), {
2510
+ type: "primary",
2511
+ loading: O.value,
2512
+ onClick: S
2513
+ }, {
2514
+ default: a(() => [
2515
+ p(m(e(n)("profile.save")), 1)
2516
+ ]),
2517
+ _: 1
2518
+ }, 8, ["loading"])
2519
+ ]),
2520
+ default: a(() => [
2521
+ N("div", Ra, [
2522
+ N("div", Ea, [
2523
+ r.avatarField ? (c(), K("div", Da, [
2524
+ (c(), h(Pe(r.avatarField), {
2525
+ modelValue: V.value,
2526
+ "onUpdate:modelValue": x[0] || (x[0] = (T) => V.value = T),
2527
+ label: e(n)("profile.avatar"),
2528
+ aspect: "1/1",
2529
+ captions: !1
2530
+ }, null, 8, ["modelValue", "label"]))
2531
+ ])) : B("", !0),
2532
+ N("div", Ia, [
2533
+ l(e(I), {
2534
+ label: e(n)("profile.name"),
2535
+ error: f("name")
2536
+ }, {
2537
+ default: a(() => [
2538
+ l(e(ee), {
2539
+ modelValue: w.value.name,
2540
+ "onUpdate:modelValue": x[1] || (x[1] = (T) => w.value.name = T),
2541
+ name: "name"
2542
+ }, null, 8, ["modelValue"])
2543
+ ]),
2544
+ _: 1
2545
+ }, 8, ["label", "error"]),
2546
+ l(e(I), {
2547
+ label: e(n)("admins.email")
2548
+ }, {
2549
+ default: a(() => [
2550
+ l(e(ee), {
2551
+ "model-value": e(k).state.user?.email ?? "",
2552
+ readonly: ""
2553
+ }, null, 8, ["model-value"])
2554
+ ]),
2555
+ _: 1
2556
+ }, 8, ["label"]),
2557
+ l(e(I), {
2558
+ label: e(n)("profile.password"),
2559
+ help: e(n)("profile.password-hint"),
2560
+ error: f("password")
2561
+ }, {
2562
+ default: a(() => [
2563
+ l(e(ee), {
2564
+ modelValue: w.value.password,
2565
+ "onUpdate:modelValue": x[2] || (x[2] = (T) => w.value.password = T),
2566
+ type: "password",
2567
+ autocomplete: "new-password"
2568
+ }, null, 8, ["modelValue"])
2569
+ ]),
2570
+ _: 1
2571
+ }, 8, ["label", "help", "error"]),
2572
+ w.value.password ? (c(), h(e(I), {
2573
+ key: 0,
2574
+ label: e(n)("profile.current-password"),
2575
+ help: e(n)("profile.current-password-hint"),
2576
+ error: f("current_password")
2577
+ }, {
2578
+ default: a(() => [
2579
+ l(e(ee), {
2580
+ modelValue: w.value.current_password,
2581
+ "onUpdate:modelValue": x[3] || (x[3] = (T) => w.value.current_password = T),
2582
+ type: "password",
2583
+ autocomplete: "current-password"
2584
+ }, null, 8, ["modelValue"])
2585
+ ]),
2586
+ _: 1
2587
+ }, 8, ["label", "help", "error"])) : B("", !0)
2588
+ ])
2589
+ ])
2590
+ ])
2591
+ ]),
2592
+ _: 1
2593
+ }, 8, ["open", "title"]));
2594
+ }
2595
+ }), Ma = /* @__PURE__ */ $e(Na, [["__scopeId", "data-v-9583a67a"]]), qa = ["title"], Ka = { class: "wx-user-menu__who" }, ja = { class: "wx-user-menu__name" }, Ga = { class: "wx-user-menu__email" }, Ha = /* @__PURE__ */ X({
2596
+ __name: "UserMenu",
2597
+ props: {
2598
+ signOutLabel: { default: void 0 },
2599
+ resolveAvatar: { type: Function, default: void 0 },
2600
+ avatarField: { default: void 0 },
2601
+ expanded: { type: Boolean, default: !1 }
2602
+ },
2603
+ setup(s) {
2604
+ const r = s, o = te(), i = Ce(), v = Re(), k = ta(), z = J("webx-auth"), n = v.scope("webx-admin"), y = P(() => o.state.user), O = o.siteUrl, u = P(
2605
+ () => v.state.panelLocales.length > 1 ? v.state.panelLocales : []
2606
+ ), w = ge(Ie, null), V = ge(Ne, null), f = A(void 0);
2607
+ de(
2608
+ () => typeof y.value?.avatar == "string" ? y.value.avatar : null,
2609
+ async (t) => {
2610
+ const b = r.resolveAvatar ?? w;
2611
+ if (t === null || t === "" || b === null) {
2612
+ f.value = void 0;
2613
+ return;
2614
+ }
2615
+ const U = await b(t);
2616
+ y.value?.avatar === t && (f.value = U ?? void 0);
2617
+ },
2618
+ { immediate: !0 }
2619
+ );
2620
+ const S = pe(Ma);
2621
+ function $() {
2622
+ setTimeout(
2623
+ () => {
2624
+ S({ avatarField: r.avatarField ?? V ?? void 0 });
2625
+ },
2626
+ 0
2627
+ );
2628
+ }
2629
+ const x = P({
2630
+ get: () => k.state.preference,
2631
+ set: (t) => {
2632
+ k.set(t), i.setTheme(t);
2633
+ }
2634
+ }), T = P(
2635
+ () => typeof y.value?.siteBar == "boolean" ? y.value.siteBar : null
2636
+ );
2637
+ function g() {
2638
+ T.value !== null && i.setSiteBar(!T.value);
2639
+ }
2640
+ async function D(t) {
2641
+ t !== v.state.locale && await i.setLocale(t);
2642
+ }
2643
+ return (t, b) => {
2644
+ const U = H("wx-avatar"), Y = H("wx-icon"), F = H("wx-text"), C = H("wx-dropdown-item"), d = H("wx-divider"), W = H("wx-dropdown");
2645
+ return y.value !== null ? (c(), h(W, { key: 0 }, {
2646
+ trigger: a(() => [
2647
+ N("button", {
2648
+ type: "button",
2649
+ class: Fe(["wx-user-menu__trigger", { "wx-user-menu__trigger--named": s.expanded }]),
2650
+ title: y.value.name
2651
+ }, [
2652
+ l(U, {
2653
+ name: y.value.name,
2654
+ src: f.value,
2655
+ size: "lg"
2656
+ }, null, 8, ["name", "src"]),
2657
+ s.expanded ? (c(), K(ie, { key: 0 }, [
2658
+ N("span", Ka, [
2659
+ N("span", ja, m(y.value.name), 1),
2660
+ N("span", Ga, m(y.value.email), 1)
2661
+ ]),
2662
+ l(Y, {
2663
+ name: "chevron-up",
2664
+ size: "sm",
2665
+ class: "wx-user-menu__chevron"
2666
+ })
2667
+ ], 64)) : B("", !0)
2668
+ ], 10, qa)
2669
+ ]),
2670
+ default: a(() => [
2671
+ l(C, { disabled: "" }, {
2672
+ default: a(() => [
2673
+ l(F, { size: "sm" }, {
2674
+ default: a(() => [
2675
+ p(m(y.value.email), 1)
2676
+ ]),
2677
+ _: 1
2678
+ })
2679
+ ]),
2680
+ _: 1
2681
+ }),
2682
+ l(d, { spacing: "sm" }),
2683
+ l(C, {
2684
+ icon: "user",
2685
+ onClick: $
2686
+ }, {
2687
+ default: a(() => [
2688
+ p(m(e(z)("profile.menu")), 1)
2689
+ ]),
2690
+ _: 1
2691
+ }),
2692
+ e(O) ? (c(), h(C, {
2693
+ key: 0,
2694
+ icon: "external-link",
2695
+ href: e(O),
2696
+ target: "_blank",
2697
+ rel: "noopener"
2698
+ }, {
2699
+ default: a(() => [
2700
+ p(m(e(n)("nav.open-site")), 1)
2701
+ ]),
2702
+ _: 1
2703
+ }, 8, ["href"])) : B("", !0),
2704
+ l(d, { spacing: "sm" }),
2705
+ l(C, { disabled: "" }, {
2706
+ default: a(() => [
2707
+ l(F, {
2708
+ size: "sm",
2709
+ tone: "muted"
2710
+ }, {
2711
+ default: a(() => [
2712
+ p(m(e(n)("theme.label")), 1)
2713
+ ]),
2714
+ _: 1
2715
+ })
2716
+ ]),
2717
+ _: 1
2718
+ }),
2719
+ N("div", {
2720
+ class: "wx-user-menu__theme",
2721
+ onClick: b[1] || (b[1] = We(() => {
2722
+ }, ["stop"]))
2723
+ }, [
2724
+ l(e(ra), {
2725
+ modelValue: x.value,
2726
+ "onUpdate:modelValue": b[0] || (b[0] = (_) => x.value = _),
2727
+ size: "sm",
2728
+ block: "",
2729
+ "aria-label": e(n)("theme.label"),
2730
+ "light-label": e(n)("theme.light"),
2731
+ "dark-label": e(n)("theme.dark"),
2732
+ "system-label": e(n)("theme.system")
2733
+ }, null, 8, ["modelValue", "aria-label", "light-label", "dark-label", "system-label"])
2734
+ ]),
2735
+ T.value !== null ? (c(), K(ie, { key: 1 }, [
2736
+ l(d, { spacing: "sm" }),
2737
+ l(C, {
2738
+ icon: T.value ? "check" : void 0,
2739
+ onClick: g
2740
+ }, {
2741
+ default: a(() => [
2742
+ p(m(e(z)("menu.site-bar")), 1)
2743
+ ]),
2744
+ _: 1
2745
+ }, 8, ["icon"])
2746
+ ], 64)) : B("", !0),
2747
+ u.value.length > 0 ? (c(), K(ie, { key: 2 }, [
2748
+ l(d, { spacing: "sm" }),
2749
+ l(C, { disabled: "" }, {
2750
+ default: a(() => [
2751
+ l(F, {
2752
+ size: "sm",
2753
+ tone: "muted"
2754
+ }, {
2755
+ default: a(() => [
2756
+ p(m(e(z)("menu.language")), 1)
2757
+ ]),
2758
+ _: 1
2759
+ })
2760
+ ]),
2761
+ _: 1
2762
+ }),
2763
+ (c(!0), K(ie, null, _e(u.value, (_) => (c(), h(C, {
2764
+ key: _.code,
2765
+ icon: _.code === e(v).state.locale ? "check" : void 0,
2766
+ onClick: (Q) => D(_.code)
2767
+ }, {
2768
+ default: a(() => [
2769
+ p(m(_.nativeName), 1)
2770
+ ]),
2771
+ _: 2
2772
+ }, 1032, ["icon", "onClick"]))), 128)),
2773
+ l(d, { spacing: "sm" })
2774
+ ], 64)) : B("", !0),
2775
+ l(C, {
2776
+ icon: "logout",
2777
+ onClick: b[2] || (b[2] = (_) => e(i).logout())
2778
+ }, {
2779
+ default: a(() => [
2780
+ p(m(s.signOutLabel ?? e(z)("menu.sign-out")), 1)
2781
+ ]),
2782
+ _: 1
2783
+ })
2784
+ ]),
2785
+ _: 1
2786
+ })) : B("", !0);
2787
+ };
2788
+ }
2789
+ }), st = /* @__PURE__ */ $e(Ha, [["__scopeId", "data-v-31b12be6"]]);
2790
+ function nt(s = {}) {
2791
+ const r = s.path ?? "/login";
2792
+ return {
2793
+ install(o) {
2794
+ const i = ua(o.context);
2795
+ o.i18n.defaults("webx-auth", Ke), da(
2796
+ o.app,
2797
+ i,
2798
+ s.resolveAvatar ?? qe(o.context),
2799
+ s.avatarField ?? Me(o.context)
2800
+ ), o.context.useSessionLoader(() => i.me()), o.router.addRoute({
2801
+ path: r,
2802
+ name: "webx.login",
2803
+ meta: { public: !0 },
2804
+ component: { render: () => Be(pa, { ...s.card }) }
2805
+ }), o.router.beforeEach((v) => v.meta.public === !0 || o.context.state.status !== "unauthenticated" ? !0 : { path: r, query: v.fullPath === "/" ? {} : { next: v.fullPath } }), de(
2806
+ () => o.context.state.status,
2807
+ (v) => {
2808
+ const k = o.router.currentRoute.value;
2809
+ if (v === "unauthenticated" && k.path !== r) {
2810
+ o.router.replace({ path: r, query: { next: k.fullPath } });
2811
+ return;
2812
+ }
2813
+ if (v === "ready" && k.path === r) {
2814
+ const z = k.query.next;
2815
+ if (typeof z == "string" && Ya(z)) {
2816
+ location.assign(z);
2817
+ return;
2818
+ }
2819
+ o.router.replace(typeof z == "string" ? z : "/");
2820
+ }
2821
+ }
2822
+ );
2823
+ }
2824
+ };
2825
+ }
2826
+ function Ya(s) {
2827
+ if (!/^https?:\/\//i.test(s))
2828
+ return !1;
2829
+ try {
2830
+ return new URL(s).origin === location.origin;
2831
+ } catch {
2832
+ return !1;
2833
+ }
2834
+ }
2835
+ const ot = Xe(() => import("./ConnectPage-CGGeG8--.js"));
2836
+ export {
2837
+ pa as L,
2838
+ Ma as P,
2839
+ st as U,
2840
+ ot as W,
2841
+ $e as _,
2842
+ Aa as a,
2843
+ je as b,
2844
+ za as c,
2845
+ Oa as d,
2846
+ Ca as e,
2847
+ Pa as f,
2848
+ et as g,
2849
+ nt as h,
2850
+ De as i,
2851
+ Ke as j,
2852
+ Ne as k,
2853
+ Ie as l,
2854
+ at as m,
2855
+ me as n,
2856
+ ua as o,
2857
+ $a as p,
2858
+ Ge as q,
2859
+ da as r,
2860
+ tt as s,
2861
+ lt as t,
2862
+ se as u,
2863
+ Ce as v
2864
+ };
2865
+ //# sourceMappingURL=index-BUVSIwLQ.js.map