@webx-ui/module-audit 0.4.7 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AuditHostsPage-YFRORYHZ.js +343 -0
- package/dist/AuditHostsPage-YFRORYHZ.js.map +1 -0
- package/dist/AuditIssuesPage-BjTPgAnD.js +693 -0
- package/dist/AuditIssuesPage-BjTPgAnD.js.map +1 -0
- package/dist/AuditLayout.vue_vue_type_script_setup_true_lang-C8H5jlTe.js +66 -0
- package/dist/AuditLayout.vue_vue_type_script_setup_true_lang-C8H5jlTe.js.map +1 -0
- package/dist/AuditOverviewPage-gVpdBOAY.js +432 -0
- package/dist/AuditOverviewPage-gVpdBOAY.js.map +1 -0
- package/dist/AuditPagesPage-DNgZo-K-.js +355 -0
- package/dist/AuditPagesPage-DNgZo-K-.js.map +1 -0
- package/dist/AuditRunsPage-BbWsuATw.js +375 -0
- package/dist/AuditRunsPage-BbWsuATw.js.map +1 -0
- package/dist/AuditSettingsPage-HwfdLU_s.js +88 -0
- package/dist/AuditSettingsPage-HwfdLU_s.js.map +1 -0
- package/dist/index-BFYHJYU_.js +1880 -0
- package/dist/index-BFYHJYU_.js.map +1 -0
- package/dist/index.d.ts +30 -6
- package/dist/index.js +17 -4126
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import { defineComponent as L, ref as m, computed as $, watch as F, openBlock as r, createElementBlock as h, createVNode as p, unref as t, createBlock as g, withCtx as n, createTextVNode as c, toDisplayString as i, Fragment as B, renderList as K, createCommentVNode as _, onMounted as se, createElementVNode as re } from "vue";
|
|
2
|
+
import { useRoute as oe } from "vue-router";
|
|
3
|
+
import { useAdmin as j, useTranslate as G, useErrorText as H, WxDate as S } from "@webx-ui/module-admin";
|
|
4
|
+
import { WxSegmented as ue, WxText as z, WxSkeleton as ie, WxLink as ce, WxButton as de, confirm as pe, toast as N, WxCard as R, WxAlert as U, WxTable as q, WxBadge as E } from "@webx-ui/core";
|
|
5
|
+
import { c as J, u as O, e as me, _ as Q } from "./index-BFYHJYU_.js";
|
|
6
|
+
import { _ as ge } from "./AuditLayout.vue_vue_type_script_setup_true_lang-C8H5jlTe.js";
|
|
7
|
+
const fe = { class: "wx-audit-compare" }, ve = /* @__PURE__ */ L({
|
|
8
|
+
__name: "AuditCompareIssues",
|
|
9
|
+
props: {
|
|
10
|
+
from: {},
|
|
11
|
+
to: {},
|
|
12
|
+
row: {}
|
|
13
|
+
},
|
|
14
|
+
setup(I) {
|
|
15
|
+
const b = I, C = J(j());
|
|
16
|
+
O();
|
|
17
|
+
const k = G("webx-audit"), T = H(), e = ["new", "fixed", "persisting"], x = m(e.find((u) => b.row[u] > 0) ?? "new"), f = m(null), w = m(1), v = m(!1), s = m(null), A = $(
|
|
18
|
+
() => e.map((u) => ({
|
|
19
|
+
value: u,
|
|
20
|
+
label: `${k(`page.kind-${u}`)} · ${b.row[u]}`,
|
|
21
|
+
disabled: b.row[u] === 0
|
|
22
|
+
}))
|
|
23
|
+
);
|
|
24
|
+
async function W(u = 1) {
|
|
25
|
+
s.value = null;
|
|
26
|
+
try {
|
|
27
|
+
const o = await C.compareIssues({
|
|
28
|
+
from: b.from,
|
|
29
|
+
to: b.to,
|
|
30
|
+
kind: x.value,
|
|
31
|
+
check: b.row.check,
|
|
32
|
+
page: u,
|
|
33
|
+
per_page: 50
|
|
34
|
+
});
|
|
35
|
+
f.value = u === 1 ? o.data : [...f.value ?? [], ...o.data], w.value = o.current_page, v.value = o.current_page < o.last_page;
|
|
36
|
+
} catch (o) {
|
|
37
|
+
s.value = T(o);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return F(
|
|
41
|
+
x,
|
|
42
|
+
() => {
|
|
43
|
+
f.value = null, W();
|
|
44
|
+
},
|
|
45
|
+
{ immediate: !0 }
|
|
46
|
+
), (u, o) => (r(), h("div", fe, [
|
|
47
|
+
p(t(ue), {
|
|
48
|
+
modelValue: x.value,
|
|
49
|
+
"onUpdate:modelValue": o[0] || (o[0] = (y) => x.value = y),
|
|
50
|
+
options: A.value,
|
|
51
|
+
size: "sm",
|
|
52
|
+
"aria-label": t(k)("page.compare")
|
|
53
|
+
}, null, 8, ["modelValue", "options", "aria-label"]),
|
|
54
|
+
s.value ? (r(), g(t(z), {
|
|
55
|
+
key: 0,
|
|
56
|
+
size: "sm",
|
|
57
|
+
tone: "danger"
|
|
58
|
+
}, {
|
|
59
|
+
default: n(() => [
|
|
60
|
+
c(i(s.value), 1)
|
|
61
|
+
]),
|
|
62
|
+
_: 1
|
|
63
|
+
})) : f.value ? (r(), h(B, { key: 2 }, [
|
|
64
|
+
(r(!0), h(B, null, K(f.value, (y) => (r(), h("div", {
|
|
65
|
+
key: y.id,
|
|
66
|
+
class: "wx-audit-compare__item"
|
|
67
|
+
}, [
|
|
68
|
+
y.url ? (r(), g(t(ce), {
|
|
69
|
+
key: 0,
|
|
70
|
+
href: y.url,
|
|
71
|
+
target: "_blank",
|
|
72
|
+
class: "wx-audit-compare__url"
|
|
73
|
+
}, {
|
|
74
|
+
default: n(() => [
|
|
75
|
+
c(i(y.url), 1)
|
|
76
|
+
]),
|
|
77
|
+
_: 2
|
|
78
|
+
}, 1032, ["href"])) : _("", !0),
|
|
79
|
+
p(me, {
|
|
80
|
+
details: y.details
|
|
81
|
+
}, null, 8, ["details"])
|
|
82
|
+
]))), 128)),
|
|
83
|
+
v.value ? (r(), g(t(de), {
|
|
84
|
+
key: 0,
|
|
85
|
+
size: "sm",
|
|
86
|
+
variant: "text",
|
|
87
|
+
onClick: o[1] || (o[1] = (y) => W(w.value + 1))
|
|
88
|
+
}, {
|
|
89
|
+
default: n(() => [...o[2] || (o[2] = [
|
|
90
|
+
c("…", -1)
|
|
91
|
+
])]),
|
|
92
|
+
_: 1
|
|
93
|
+
})) : _("", !0)
|
|
94
|
+
], 64)) : (r(), g(t(ie), {
|
|
95
|
+
key: 1,
|
|
96
|
+
rows: 2
|
|
97
|
+
}))
|
|
98
|
+
]));
|
|
99
|
+
}
|
|
100
|
+
}), ye = /* @__PURE__ */ Q(ve, [["__scopeId", "data-v-02d42bdb"]]), _e = { class: "wx-audit-runs" }, be = {
|
|
101
|
+
key: 0,
|
|
102
|
+
class: "wx-audit-runs__counts"
|
|
103
|
+
}, xe = /* @__PURE__ */ L({
|
|
104
|
+
__name: "AuditRunsPage",
|
|
105
|
+
props: {
|
|
106
|
+
base: {}
|
|
107
|
+
},
|
|
108
|
+
setup(I) {
|
|
109
|
+
const b = I, C = j(), k = J(C), T = oe();
|
|
110
|
+
O();
|
|
111
|
+
const e = G("webx-audit"), x = H(), f = m(null), w = m(!1), v = m([]), s = m(null), A = m(!1), W = m([]), u = m(!1), o = C.can("audit.manage"), y = {
|
|
112
|
+
queued: "info",
|
|
113
|
+
running: "primary",
|
|
114
|
+
done: "success",
|
|
115
|
+
failed: "danger",
|
|
116
|
+
cancelled: "warning"
|
|
117
|
+
}, M = {
|
|
118
|
+
error: "danger",
|
|
119
|
+
warning: "warning",
|
|
120
|
+
notice: "info"
|
|
121
|
+
}, X = $(() => [
|
|
122
|
+
{ key: "id", label: e("page.run-id"), width: 90 },
|
|
123
|
+
{ key: "created_at", label: e("page.started-at"), minWidth: 160 },
|
|
124
|
+
{ key: "scope", label: e("page.scope"), width: 120 },
|
|
125
|
+
{ key: "status", label: e("page.status"), width: 130 },
|
|
126
|
+
{ key: "health", label: e("page.health"), width: 100, align: "right" },
|
|
127
|
+
{ key: "severity", label: e("page.severity"), minWidth: 170, hideBelow: 640 },
|
|
128
|
+
{ key: "started_by", label: e("page.started-by"), minWidth: 130, hideBelow: 760 }
|
|
129
|
+
]), Y = $(() => [
|
|
130
|
+
{ key: "severity", label: e("page.severity"), width: 130 },
|
|
131
|
+
{ key: "title", label: e("page.check") },
|
|
132
|
+
{ key: "new", label: e("page.kind-new"), width: 90, align: "right" },
|
|
133
|
+
{ key: "fixed", label: e("page.kind-fixed"), width: 100, align: "right" },
|
|
134
|
+
{ key: "persisting", label: e("page.kind-persisting"), width: 120, align: "right" }
|
|
135
|
+
]), V = $(() => {
|
|
136
|
+
const l = v.value.map(Number).sort((d, a) => d - a);
|
|
137
|
+
return l.length === 0 ? null : l.length === 1 ? { to: l[0], from: null } : { to: l[l.length - 1], from: l[0] };
|
|
138
|
+
}), Z = $(
|
|
139
|
+
() => s.value !== null && s.value.from.scope !== s.value.to.scope
|
|
140
|
+
);
|
|
141
|
+
function ee(l) {
|
|
142
|
+
return l.started_by === "schedule" ? e("page.by-schedule") : l.started_by === "mcp" ? e("page.by-mcp") : l.started_by === "console" ? e("page.by-console") : l.started_by ? e("page.by-person") : "";
|
|
143
|
+
}
|
|
144
|
+
async function P(l) {
|
|
145
|
+
w.value = !0;
|
|
146
|
+
try {
|
|
147
|
+
f.value = await k.runs({ page: l?.page ?? 1, per_page: l?.perPage ?? 20 });
|
|
148
|
+
} catch (d) {
|
|
149
|
+
N.danger(x(d));
|
|
150
|
+
} finally {
|
|
151
|
+
w.value = !1;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function ae() {
|
|
155
|
+
const l = V.value;
|
|
156
|
+
if (s.value = null, W.value = [], !!l) {
|
|
157
|
+
A.value = !0;
|
|
158
|
+
try {
|
|
159
|
+
s.value = await k.compare(l.to, l.from);
|
|
160
|
+
} catch (d) {
|
|
161
|
+
N.danger(x(d));
|
|
162
|
+
} finally {
|
|
163
|
+
A.value = !1;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const te = $(
|
|
168
|
+
() => o && f.value?.total ? [
|
|
169
|
+
{
|
|
170
|
+
key: "clear",
|
|
171
|
+
label: e("page.clear"),
|
|
172
|
+
icon: "trash",
|
|
173
|
+
danger: !0,
|
|
174
|
+
disabled: u.value,
|
|
175
|
+
run: () => {
|
|
176
|
+
le();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
] : []
|
|
180
|
+
);
|
|
181
|
+
async function le() {
|
|
182
|
+
if (await pe({
|
|
183
|
+
title: e("page.clear-title"),
|
|
184
|
+
message: e("page.clear-text"),
|
|
185
|
+
confirmText: e("page.clear-confirm"),
|
|
186
|
+
cancelText: e("page.clear-cancel"),
|
|
187
|
+
tone: "danger"
|
|
188
|
+
})) {
|
|
189
|
+
u.value = !0;
|
|
190
|
+
try {
|
|
191
|
+
await k.clear(), v.value = [], N.success(e("page.cleared")), await P();
|
|
192
|
+
} catch (d) {
|
|
193
|
+
N.danger(x(d));
|
|
194
|
+
} finally {
|
|
195
|
+
u.value = !1;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return se(() => {
|
|
200
|
+
const l = Number(T.query.to);
|
|
201
|
+
Number.isInteger(l) && l > 0 && (v.value = [l]);
|
|
202
|
+
}), F(v, (l) => {
|
|
203
|
+
l.length > 2 ? v.value = l.slice(-2) : ae();
|
|
204
|
+
}), (l, d) => (r(), g(ge, {
|
|
205
|
+
base: b.base,
|
|
206
|
+
current: "runs",
|
|
207
|
+
card: !1,
|
|
208
|
+
actions: te.value
|
|
209
|
+
}, {
|
|
210
|
+
default: n(() => [
|
|
211
|
+
re("div", _e, [
|
|
212
|
+
p(t(R), null, {
|
|
213
|
+
default: n(() => [
|
|
214
|
+
!V.value && f.value?.total ? (r(), g(t(U), {
|
|
215
|
+
key: 0,
|
|
216
|
+
type: "info",
|
|
217
|
+
description: t(e)("page.compare-help"),
|
|
218
|
+
class: "wx-audit-runs__note"
|
|
219
|
+
}, null, 8, ["description"])) : _("", !0),
|
|
220
|
+
p(t(q), {
|
|
221
|
+
selected: v.value,
|
|
222
|
+
"onUpdate:selected": d[0] || (d[0] = (a) => v.value = a),
|
|
223
|
+
data: f.value,
|
|
224
|
+
columns: X.value,
|
|
225
|
+
"row-key": "id",
|
|
226
|
+
selectable: "",
|
|
227
|
+
"selectable-if": (a) => a.status === "done",
|
|
228
|
+
flush: "",
|
|
229
|
+
loading: w.value,
|
|
230
|
+
"empty-text": t(e)("page.runs-empty"),
|
|
231
|
+
onStateChange: P
|
|
232
|
+
}, {
|
|
233
|
+
"cell-created_at": n(({ row: a }) => [
|
|
234
|
+
p(t(S), {
|
|
235
|
+
value: a.created_at
|
|
236
|
+
}, null, 8, ["value"])
|
|
237
|
+
]),
|
|
238
|
+
"cell-scope": n(({ row: a }) => [
|
|
239
|
+
c(i(t(e)(`page.scope-${a.scope}`)), 1)
|
|
240
|
+
]),
|
|
241
|
+
"cell-status": n(({ row: a }) => [
|
|
242
|
+
p(t(E), {
|
|
243
|
+
type: y[a.status],
|
|
244
|
+
dot: ""
|
|
245
|
+
}, {
|
|
246
|
+
default: n(() => [
|
|
247
|
+
c(i(t(e)(`page.status-${a.status}`)), 1)
|
|
248
|
+
]),
|
|
249
|
+
_: 2
|
|
250
|
+
}, 1032, ["type"])
|
|
251
|
+
]),
|
|
252
|
+
"cell-health": n(({ row: a }) => [
|
|
253
|
+
c(i(a.counts ? `${a.counts.health}%` : ""), 1)
|
|
254
|
+
]),
|
|
255
|
+
"cell-severity": n(({ row: a }) => [
|
|
256
|
+
a.counts ? (r(), h("span", be, [
|
|
257
|
+
(r(), h(B, null, K(M, (ne, D) => (r(), h(B, { key: D }, [
|
|
258
|
+
a.counts.severity[D] ? (r(), g(t(E), {
|
|
259
|
+
key: 0,
|
|
260
|
+
type: ne,
|
|
261
|
+
size: "sm"
|
|
262
|
+
}, {
|
|
263
|
+
default: n(() => [
|
|
264
|
+
c(i(a.counts.severity[D]), 1)
|
|
265
|
+
]),
|
|
266
|
+
_: 2
|
|
267
|
+
}, 1032, ["type"])) : _("", !0)
|
|
268
|
+
], 64))), 64))
|
|
269
|
+
])) : _("", !0)
|
|
270
|
+
]),
|
|
271
|
+
"cell-started_by": n(({ row: a }) => [
|
|
272
|
+
c(i(ee(a)), 1)
|
|
273
|
+
]),
|
|
274
|
+
_: 1
|
|
275
|
+
}, 8, ["selected", "data", "columns", "selectable-if", "loading", "empty-text"])
|
|
276
|
+
]),
|
|
277
|
+
_: 1
|
|
278
|
+
}),
|
|
279
|
+
V.value ? (r(), g(t(R), {
|
|
280
|
+
key: 0,
|
|
281
|
+
title: t(e)("page.compare")
|
|
282
|
+
}, {
|
|
283
|
+
default: n(() => [
|
|
284
|
+
s.value ? (r(), g(t(z), {
|
|
285
|
+
key: 0,
|
|
286
|
+
size: "sm",
|
|
287
|
+
tone: "muted",
|
|
288
|
+
class: "wx-audit-runs__pair"
|
|
289
|
+
}, {
|
|
290
|
+
default: n(() => [
|
|
291
|
+
c(i(t(e)("page.compare-from")) + " #" + i(s.value.from.id) + " · ", 1),
|
|
292
|
+
p(t(S), {
|
|
293
|
+
value: s.value.from.created_at
|
|
294
|
+
}, null, 8, ["value"]),
|
|
295
|
+
c(" → " + i(t(e)("page.compare-to")) + " #" + i(s.value.to.id) + " · ", 1),
|
|
296
|
+
p(t(S), {
|
|
297
|
+
value: s.value.to.created_at
|
|
298
|
+
}, null, 8, ["value"])
|
|
299
|
+
]),
|
|
300
|
+
_: 1
|
|
301
|
+
})) : _("", !0),
|
|
302
|
+
Z.value ? (r(), g(t(U), {
|
|
303
|
+
key: 1,
|
|
304
|
+
type: "info",
|
|
305
|
+
description: t(e)("page.compare-scopes"),
|
|
306
|
+
class: "wx-audit-runs__note"
|
|
307
|
+
}, null, 8, ["description"])) : _("", !0),
|
|
308
|
+
p(t(q), {
|
|
309
|
+
expanded: W.value,
|
|
310
|
+
"onUpdate:expanded": d[1] || (d[1] = (a) => W.value = a),
|
|
311
|
+
data: s.value?.checks ?? [],
|
|
312
|
+
columns: Y.value,
|
|
313
|
+
"row-key": "check",
|
|
314
|
+
expandable: "",
|
|
315
|
+
flush: "",
|
|
316
|
+
pagination: !1,
|
|
317
|
+
loading: A.value,
|
|
318
|
+
"empty-text": t(e)("page.compare-none")
|
|
319
|
+
}, {
|
|
320
|
+
"cell-severity": n(({ row: a }) => [
|
|
321
|
+
p(t(E), {
|
|
322
|
+
type: M[a.severity],
|
|
323
|
+
dot: ""
|
|
324
|
+
}, {
|
|
325
|
+
default: n(() => [
|
|
326
|
+
c(i(t(e)(`page.severity-${a.severity}`)), 1)
|
|
327
|
+
]),
|
|
328
|
+
_: 2
|
|
329
|
+
}, 1032, ["type"])
|
|
330
|
+
]),
|
|
331
|
+
"cell-new": n(({ row: a }) => [
|
|
332
|
+
p(t(z), {
|
|
333
|
+
tone: a.new ? "danger" : "muted",
|
|
334
|
+
size: "sm"
|
|
335
|
+
}, {
|
|
336
|
+
default: n(() => [
|
|
337
|
+
c(i(a.new), 1)
|
|
338
|
+
]),
|
|
339
|
+
_: 2
|
|
340
|
+
}, 1032, ["tone"])
|
|
341
|
+
]),
|
|
342
|
+
"cell-fixed": n(({ row: a }) => [
|
|
343
|
+
p(t(z), {
|
|
344
|
+
tone: a.fixed ? "success" : "muted",
|
|
345
|
+
size: "sm"
|
|
346
|
+
}, {
|
|
347
|
+
default: n(() => [
|
|
348
|
+
c(i(a.fixed), 1)
|
|
349
|
+
]),
|
|
350
|
+
_: 2
|
|
351
|
+
}, 1032, ["tone"])
|
|
352
|
+
]),
|
|
353
|
+
expanded: n(({ row: a }) => [
|
|
354
|
+
s.value ? (r(), g(ye, {
|
|
355
|
+
key: 0,
|
|
356
|
+
from: s.value.from.id,
|
|
357
|
+
to: s.value.to.id,
|
|
358
|
+
row: a
|
|
359
|
+
}, null, 8, ["from", "to", "row"])) : _("", !0)
|
|
360
|
+
]),
|
|
361
|
+
_: 1
|
|
362
|
+
}, 8, ["expanded", "data", "columns", "loading", "empty-text"])
|
|
363
|
+
]),
|
|
364
|
+
_: 1
|
|
365
|
+
}, 8, ["title"])) : _("", !0)
|
|
366
|
+
])
|
|
367
|
+
]),
|
|
368
|
+
_: 1
|
|
369
|
+
}, 8, ["base", "actions"]));
|
|
370
|
+
}
|
|
371
|
+
}), Ce = /* @__PURE__ */ Q(xe, [["__scopeId", "data-v-bbf74c27"]]);
|
|
372
|
+
export {
|
|
373
|
+
Ce as default
|
|
374
|
+
};
|
|
375
|
+
//# sourceMappingURL=AuditRunsPage-BbWsuATw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditRunsPage-BbWsuATw.js","sources":["../src/AuditCompareIssues.vue","../src/AuditRunsPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport { WxButton, WxLink, WxSegmented, WxSkeleton, WxText } from '@webx-ui/core'\nimport AuditDetails from './AuditDetails.vue'\nimport { createAuditApi } from './api'\nimport { useAuditMessages } from './i18n'\nimport type { AuditComparisonKind, AuditComparisonRow, AuditIssue } from './types'\n\n/**\n * One check of a comparison opened: its new, fixed or persisting findings, fifty at a time —\n * fixed ones as the earlier run stored them, the others from the later run.\n */\nconst props = defineProps<{ from: number; to: number; row: AuditComparisonRow }>()\n\nconst api = createAuditApi(useAdmin())\nuseAuditMessages()\n\nconst t = useTranslate('webx-audit')\nconst message = useErrorText()\n\nconst KINDS: AuditComparisonKind[] = ['new', 'fixed', 'persisting']\n\n/* Open on what changed: new first, then fixed — persisting only when nothing else is there. */\nconst kind = ref<AuditComparisonKind>(KINDS.find((one) => props.row[one] > 0) ?? 'new')\nconst issues = ref<AuditIssue[] | null>(null)\nconst page = ref(1)\nconst more = ref(false)\nconst failure = ref<string | null>(null)\n\nconst options = computed(() =>\n KINDS.map((value) => ({\n value,\n label: `${t(`page.kind-${value}`)} · ${props.row[value]}`,\n disabled: props.row[value] === 0,\n })),\n)\n\nasync function load(next = 1): Promise<void> {\n failure.value = null\n\n try {\n const answer = await api.compareIssues({\n from: props.from,\n to: props.to,\n kind: kind.value,\n check: props.row.check,\n page: next,\n per_page: 50,\n })\n\n issues.value = next === 1 ? answer.data : [...(issues.value ?? []), ...answer.data]\n page.value = answer.current_page\n more.value = answer.current_page < answer.last_page\n } catch (error) {\n failure.value = message(error)\n }\n}\n\nwatch(\n kind,\n () => {\n issues.value = null\n void load()\n },\n { immediate: true },\n)\n</script>\n\n<template>\n <div class=\"wx-audit-compare\">\n <wx-segmented v-model=\"kind\" :options=\"options\" size=\"sm\" :aria-label=\"t('page.compare')\" />\n\n <wx-text v-if=\"failure\" size=\"sm\" tone=\"danger\">{{ failure }}</wx-text>\n <wx-skeleton v-else-if=\"!issues\" :rows=\"2\" />\n\n <template v-else>\n <div v-for=\"issue in issues\" :key=\"issue.id\" class=\"wx-audit-compare__item\">\n <wx-link v-if=\"issue.url\" :href=\"issue.url\" target=\"_blank\" class=\"wx-audit-compare__url\">{{\n issue.url\n }}</wx-link>\n <audit-details :details=\"issue.details\" />\n </div>\n\n <wx-button v-if=\"more\" size=\"sm\" variant=\"text\" @click=\"load(page + 1)\">…</wx-button>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-audit-compare {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n min-width: 0;\n}\n\n.wx-audit-compare__item {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n min-width: 0;\n}\n\n.wx-audit-compare__url {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { useRoute } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxDate,\n type ScreenAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n toast,\n WxAlert,\n WxBadge,\n WxCard,\n WxTable,\n WxText,\n type BadgeType,\n type RowKey,\n type TableColumn,\n type TableState,\n} from '@webx-ui/core'\nimport AuditCompareIssues from './AuditCompareIssues.vue'\nimport AuditLayout from './AuditLayout.vue'\nimport { createAuditApi } from './api'\nimport { useAuditMessages } from './i18n'\nimport type {\n AuditComparison,\n AuditComparisonRow,\n AuditPage,\n AuditRun,\n AuditRunStatus,\n AuditSeverity,\n} from './types'\n\n/**\n * The history (§8 «Runs»): every run kept, newest first, with its health and counts. Ticking a\n * run compares it with the one it was analysed against; ticking two compares those two — by\n * fingerprint (decision 8): what is new in the later one, what both have, what is gone. `?to=`\n * opens on one run already ticked — the way the page card's recheck leads here. In the head, for\n * whoever manages the section, the way to clear every run at once, behind a warning.\n */\nconst props = defineProps<{ base: string }>()\n\nconst context = useAdmin()\nconst api = createAuditApi(context)\nconst route = useRoute()\nuseAuditMessages()\n\nconst t = useTranslate('webx-audit')\nconst message = useErrorText()\n\nconst runs = ref<AuditPage<AuditRun> | null>(null)\nconst loading = ref(false)\nconst selected = ref<RowKey[]>([])\nconst comparison = ref<AuditComparison | null>(null)\nconst comparing = ref(false)\nconst expanded = ref<RowKey[]>([])\nconst clearing = ref(false)\n\n// A boolean, not a computed: the permissions do not change while the screen is open.\nconst canManage = context.can('audit.manage')\n\nconst statuses: Record<AuditRunStatus, BadgeType> = {\n queued: 'info',\n running: 'primary',\n done: 'success',\n failed: 'danger',\n cancelled: 'warning',\n}\n\nconst severities: Record<AuditSeverity, BadgeType> = {\n error: 'danger',\n warning: 'warning',\n notice: 'info',\n}\n\nconst columns = computed<TableColumn<AuditRun>[]>(() => [\n { key: 'id', label: t('page.run-id'), width: 90 },\n { key: 'created_at', label: t('page.started-at'), minWidth: 160 },\n { key: 'scope', label: t('page.scope'), width: 120 },\n { key: 'status', label: t('page.status'), width: 130 },\n { key: 'health', label: t('page.health'), width: 100, align: 'right' },\n { key: 'severity', label: t('page.severity'), minWidth: 170, hideBelow: 640 },\n { key: 'started_by', label: t('page.started-by'), minWidth: 130, hideBelow: 760 },\n])\n\nconst compareColumns = computed<TableColumn<AuditComparisonRow>[]>(() => [\n { key: 'severity', label: t('page.severity'), width: 130 },\n { key: 'title', label: t('page.check') },\n { key: 'new', label: t('page.kind-new'), width: 90, align: 'right' },\n { key: 'fixed', label: t('page.kind-fixed'), width: 100, align: 'right' },\n { key: 'persisting', label: t('page.kind-persisting'), width: 120, align: 'right' },\n])\n\n/* What the selection means: one run against its own previous, or two against each other. */\nconst pair = computed<{ to: number; from: number | null } | null>(() => {\n const ids = selected.value.map(Number).sort((a, b) => a - b)\n\n if (ids.length === 0) return null\n\n return ids.length === 1\n ? { to: ids[0]!, from: null }\n : { to: ids[ids.length - 1]!, from: ids[0]! }\n})\n\nconst scopesDiffer = computed(\n () => comparison.value !== null && comparison.value.from.scope !== comparison.value.to.scope,\n)\n\nfunction who(run: AuditRun): string {\n if (run.started_by === 'schedule') return t('page.by-schedule')\n if (run.started_by === 'mcp') return t('page.by-mcp')\n if (run.started_by === 'console') return t('page.by-console')\n\n return run.started_by ? t('page.by-person') : ''\n}\n\nasync function load(state?: TableState): Promise<void> {\n loading.value = true\n\n try {\n runs.value = await api.runs({ page: state?.page ?? 1, per_page: state?.perPage ?? 20 })\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nasync function compare(): Promise<void> {\n const current = pair.value\n\n comparison.value = null\n expanded.value = []\n\n if (!current) return\n\n comparing.value = true\n\n try {\n comparison.value = await api.compare(current.to, current.from)\n } catch (error) {\n toast.danger(message(error))\n } finally {\n comparing.value = false\n }\n}\n\n// Danger, so the head puts it in its `···`: never a red button beside the section's name.\nconst actions = computed<ScreenAction[]>(() =>\n canManage && runs.value?.total\n ? [\n {\n key: 'clear',\n label: t('page.clear'),\n icon: 'trash',\n danger: true,\n disabled: clearing.value,\n run: () => void clear(),\n },\n ]\n : [],\n)\n\nasync function clear(): Promise<void> {\n const agreed = await confirm({\n title: t('page.clear-title'),\n message: t('page.clear-text'),\n confirmText: t('page.clear-confirm'),\n cancelText: t('page.clear-cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n clearing.value = true\n\n try {\n await api.clear()\n selected.value = []\n toast.success(t('page.cleared'))\n await load()\n } catch (error) {\n toast.danger(message(error))\n } finally {\n clearing.value = false\n }\n}\n\nonMounted(() => {\n const to = Number(route.query.to)\n\n if (Number.isInteger(to) && to > 0) selected.value = [to]\n})\n\nwatch(selected, (keys) => {\n /* Two at most: a third tick replaces the oldest one. */\n if (keys.length > 2) selected.value = keys.slice(-2)\n else void compare()\n})\n</script>\n\n<template>\n <audit-layout :base=\"props.base\" current=\"runs\" :card=\"false\" :actions=\"actions\">\n <div class=\"wx-audit-runs\">\n <wx-card>\n <!-- Above the table, not under it: read before ticking, not found after scrolling. -->\n <wx-alert\n v-if=\"!pair && runs?.total\"\n type=\"info\"\n :description=\"t('page.compare-help')\"\n class=\"wx-audit-runs__note\"\n />\n\n <wx-table\n v-model:selected=\"selected\"\n :data=\"runs\"\n :columns=\"columns\"\n row-key=\"id\"\n selectable\n :selectable-if=\"(row: AuditRun) => row.status === 'done'\"\n flush\n :loading=\"loading\"\n :empty-text=\"t('page.runs-empty')\"\n @state-change=\"load\"\n >\n <template #cell-created_at=\"{ row }\"><wx-date :value=\"row.created_at\" /></template>\n <template #cell-scope=\"{ row }\">{{ t(`page.scope-${row.scope}`) }}</template>\n <template #cell-status=\"{ row }\">\n <wx-badge :type=\"statuses[row.status]\" dot>{{\n t(`page.status-${row.status}`)\n }}</wx-badge>\n </template>\n <template #cell-health=\"{ row }\">{{\n row.counts ? `${row.counts.health}%` : ''\n }}</template>\n <template #cell-severity=\"{ row }\">\n <span v-if=\"row.counts\" class=\"wx-audit-runs__counts\">\n <template v-for=\"(type, key) in severities\" :key=\"key\">\n <wx-badge v-if=\"row.counts.severity[key]\" :type=\"type\" size=\"sm\">{{\n row.counts.severity[key]\n }}</wx-badge>\n </template>\n </span>\n </template>\n <template #cell-started_by=\"{ row }\">{{ who(row) }}</template>\n </wx-table>\n </wx-card>\n\n <wx-card v-if=\"pair\" :title=\"t('page.compare')\">\n <wx-text v-if=\"comparison\" size=\"sm\" tone=\"muted\" class=\"wx-audit-runs__pair\">\n {{ t('page.compare-from') }} #{{ comparison.from.id }} ·\n <wx-date :value=\"comparison.from.created_at\" /> → {{ t('page.compare-to') }} #{{\n comparison.to.id\n }}\n · <wx-date :value=\"comparison.to.created_at\" />\n </wx-text>\n\n <wx-alert\n v-if=\"scopesDiffer\"\n type=\"info\"\n :description=\"t('page.compare-scopes')\"\n class=\"wx-audit-runs__note\"\n />\n\n <wx-table\n v-model:expanded=\"expanded\"\n :data=\"comparison?.checks ?? []\"\n :columns=\"compareColumns\"\n row-key=\"check\"\n expandable\n flush\n :pagination=\"false\"\n :loading=\"comparing\"\n :empty-text=\"t('page.compare-none')\"\n >\n <template #cell-severity=\"{ row }\">\n <wx-badge :type=\"severities[row.severity]\" dot>{{\n t(`page.severity-${row.severity}`)\n }}</wx-badge>\n </template>\n <template #cell-new=\"{ row }\">\n <wx-text :tone=\"row.new ? 'danger' : 'muted'\" size=\"sm\">{{ row.new }}</wx-text>\n </template>\n <template #cell-fixed=\"{ row }\">\n <wx-text :tone=\"row.fixed ? 'success' : 'muted'\" size=\"sm\">{{ row.fixed }}</wx-text>\n </template>\n <template #expanded=\"{ row }\">\n <audit-compare-issues\n v-if=\"comparison\"\n :from=\"comparison.from.id\"\n :to=\"comparison.to.id\"\n :row=\"row\"\n />\n </template>\n </wx-table>\n </wx-card>\n </div>\n </audit-layout>\n</template>\n\n<style scoped>\n.wx-audit-runs {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n min-width: 0;\n}\n\n.wx-audit-runs__counts {\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--wx-space-4);\n}\n\n.wx-audit-runs__pair {\n display: block;\n margin-bottom: var(--wx-space-12);\n}\n\n.wx-audit-runs__note {\n margin-bottom: var(--wx-space-12);\n}\n</style>\n"],"names":["props","__props","api","createAuditApi","useAdmin","useAuditMessages","t","useTranslate","message","useErrorText","KINDS","kind","ref","one","issues","page","more","failure","options","computed","value","load","next","answer","error","watch","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","WxSegmented","$event","_createBlock","WxText","_Fragment","_renderList","issue","WxLink","_createTextVNode","_toDisplayString","AuditDetails","WxButton","_cache","WxSkeleton","context","route","useRoute","runs","loading","selected","comparison","comparing","expanded","clearing","canManage","statuses","severities","columns","compareColumns","pair","ids","a","b","scopesDiffer","who","run","state","toast","compare","current","actions","clear","confirm","onMounted","to","keys","AuditLayout","_createElementVNode","WxCard","WxAlert","WxTable","row","_withCtx","WxDate","WxBadge","_hoisted_2","type","key","AuditCompareIssues"],"mappings":";;;;;;;;;;;;;;AAaA,UAAMA,IAAQC,GAERC,IAAMC,EAAeC,GAAU;AACrC,IAAAC,EAAA;AAEA,UAAMC,IAAIC,EAAa,YAAY,GAC7BC,IAAUC,EAAA,GAEVC,IAA+B,CAAC,OAAO,SAAS,YAAY,GAG5DC,IAAOC,EAAyBF,EAAM,KAAK,CAACG,MAAQb,EAAM,IAAIa,CAAG,IAAI,CAAC,KAAK,KAAK,GAChFC,IAASF,EAAyB,IAAI,GACtCG,IAAOH,EAAI,CAAC,GACZI,IAAOJ,EAAI,EAAK,GAChBK,IAAUL,EAAmB,IAAI,GAEjCM,IAAUC;AAAA,MAAS,MACvBT,EAAM,IAAI,CAACU,OAAW;AAAA,QACpB,OAAAA;AAAA,QACA,OAAO,GAAGd,EAAE,aAAac,CAAK,EAAE,CAAC,MAAMpB,EAAM,IAAIoB,CAAK,CAAC;AAAA,QACvD,UAAUpB,EAAM,IAAIoB,CAAK,MAAM;AAAA,MAAA,EAC/B;AAAA,IAAA;AAGJ,mBAAeC,EAAKC,IAAO,GAAkB;AAC3C,MAAAL,EAAQ,QAAQ;AAEhB,UAAI;AACF,cAAMM,IAAS,MAAMrB,EAAI,cAAc;AAAA,UACrC,MAAMF,EAAM;AAAA,UACZ,IAAIA,EAAM;AAAA,UACV,MAAMW,EAAK;AAAA,UACX,OAAOX,EAAM,IAAI;AAAA,UACjB,MAAMsB;AAAA,UACN,UAAU;AAAA,QAAA,CACX;AAED,QAAAR,EAAO,QAAQQ,MAAS,IAAIC,EAAO,OAAO,CAAC,GAAIT,EAAO,SAAS,CAAA,GAAK,GAAGS,EAAO,IAAI,GAClFR,EAAK,QAAQQ,EAAO,cACpBP,EAAK,QAAQO,EAAO,eAAeA,EAAO;AAAA,MAC5C,SAASC,GAAO;AACd,QAAAP,EAAQ,QAAQT,EAAQgB,CAAK;AAAA,MAC/B;AAAA,IACF;AAEA,WAAAC;AAAA,MACEd;AAAA,MACA,MAAM;AACJ,QAAAG,EAAO,QAAQ,MACVO,EAAA;AAAA,MACP;AAAA,MACA,EAAE,WAAW,GAAA;AAAA,IAAK,cAKlBK,EAAA,GAAAC,EAgBM,OAhBNC,IAgBM;AAAA,MAfJC,EAA4FC,EAAAC,EAAA,GAAA;AAAA,oBAArEpB,EAAA;AAAA,sDAAAA,EAAI,QAAAqB;AAAA,QAAG,SAASd,EAAA;AAAA,QAAS,MAAK;AAAA,QAAM,cAAYY,EAAAxB,CAAA,EAAC,cAAA;AAAA,MAAA;MAEzDW,EAAA,cAAfgB,EAAuEH,EAAAI,CAAA,GAAA;AAAA;QAA/C,MAAK;AAAA,QAAK,MAAK;AAAA,MAAA;mBAAS,MAAa;AAAA,cAAVjB,EAAA,KAAO,GAAA,CAAA;AAAA,QAAA;;YACjCH,EAAA,cAEzBa,EASWQ,GAAA,EAAA,KAAA,KAAA;AAAA,gBARTR,EAKMQ,GAAA,MAAAC,EALetB,EAAA,OAAM,CAAfuB,YAAZV,EAKM,OAAA;AAAA,UALwB,KAAKU,EAAM;AAAA,UAAI,OAAM;AAAA,QAAA;UAClCA,EAAM,YAArBJ,EAEYH,EAAAQ,EAAA,GAAA;AAAA;YAFe,MAAMD,EAAM;AAAA,YAAK,QAAO;AAAA,YAAS,OAAM;AAAA,UAAA;uBAAwB,MAExF;AAAA,cADAE,EAAAC,EAAAH,EAAM,GAAG,GAAA,CAAA;AAAA,YAAA;;;UAEXR,EAA0CY,IAAA;AAAA,YAA1B,SAASJ,EAAM;AAAA,UAAA;;QAGhBrB,EAAA,cAAjBiB,EAAqFH,EAAAY,EAAA,GAAA;AAAA;UAA9D,MAAK;AAAA,UAAK,SAAQ;AAAA,UAAQ,SAAKC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAX,MAAEX,EAAKN,EAAA,QAAI,CAAA;AAAA,QAAA;qBAAO,MAAC,CAAA,GAAA4B,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAD,KAAC,EAAA;AAAA,UAAA;;;sBAV3EV,EAA6CH,EAAAc,EAAA,GAAA;AAAA;QAAX,MAAM;AAAA,MAAA;;;;;;;;;;;;AC/B5C,UAAM5C,IAAQC,GAER4C,IAAUzC,EAAA,GACVF,IAAMC,EAAe0C,CAAO,GAC5BC,IAAQC,GAAA;AACd,IAAA1C,EAAA;AAEA,UAAMC,IAAIC,EAAa,YAAY,GAC7BC,IAAUC,EAAA,GAEVuC,IAAOpC,EAAgC,IAAI,GAC3CqC,IAAUrC,EAAI,EAAK,GACnBsC,IAAWtC,EAAc,EAAE,GAC3BuC,IAAavC,EAA4B,IAAI,GAC7CwC,IAAYxC,EAAI,EAAK,GACrByC,IAAWzC,EAAc,EAAE,GAC3B0C,IAAW1C,EAAI,EAAK,GAGpB2C,IAAYV,EAAQ,IAAI,cAAc,GAEtCW,IAA8C;AAAA,MAClD,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW;AAAA,IAAA,GAGPC,IAA+C;AAAA,MACnD,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IAAA,GAGJC,IAAUvC,EAAkC,MAAM;AAAA,MACtD,EAAE,KAAK,MAAM,OAAOb,EAAE,aAAa,GAAG,OAAO,GAAA;AAAA,MAC7C,EAAE,KAAK,cAAc,OAAOA,EAAE,iBAAiB,GAAG,UAAU,IAAA;AAAA,MAC5D,EAAE,KAAK,SAAS,OAAOA,EAAE,YAAY,GAAG,OAAO,IAAA;AAAA,MAC/C,EAAE,KAAK,UAAU,OAAOA,EAAE,aAAa,GAAG,OAAO,IAAA;AAAA,MACjD,EAAE,KAAK,UAAU,OAAOA,EAAE,aAAa,GAAG,OAAO,KAAK,OAAO,QAAA;AAAA,MAC7D,EAAE,KAAK,YAAY,OAAOA,EAAE,eAAe,GAAG,UAAU,KAAK,WAAW,IAAA;AAAA,MACxE,EAAE,KAAK,cAAc,OAAOA,EAAE,iBAAiB,GAAG,UAAU,KAAK,WAAW,IAAA;AAAA,IAAI,CACjF,GAEKqD,IAAiBxC,EAA4C,MAAM;AAAA,MACvE,EAAE,KAAK,YAAY,OAAOb,EAAE,eAAe,GAAG,OAAO,IAAA;AAAA,MACrD,EAAE,KAAK,SAAS,OAAOA,EAAE,YAAY,EAAA;AAAA,MACrC,EAAE,KAAK,OAAO,OAAOA,EAAE,eAAe,GAAG,OAAO,IAAI,OAAO,QAAA;AAAA,MAC3D,EAAE,KAAK,SAAS,OAAOA,EAAE,iBAAiB,GAAG,OAAO,KAAK,OAAO,QAAA;AAAA,MAChE,EAAE,KAAK,cAAc,OAAOA,EAAE,sBAAsB,GAAG,OAAO,KAAK,OAAO,QAAA;AAAA,IAAQ,CACnF,GAGKsD,IAAOzC,EAAqD,MAAM;AACtE,YAAM0C,IAAMX,EAAS,MAAM,IAAI,MAAM,EAAE,KAAK,CAACY,GAAGC,MAAMD,IAAIC,CAAC;AAE3D,aAAIF,EAAI,WAAW,IAAU,OAEtBA,EAAI,WAAW,IAClB,EAAE,IAAIA,EAAI,CAAC,GAAI,MAAM,KAAA,IACrB,EAAE,IAAIA,EAAIA,EAAI,SAAS,CAAC,GAAI,MAAMA,EAAI,CAAC,EAAA;AAAA,IAC7C,CAAC,GAEKG,IAAe7C;AAAA,MACnB,MAAMgC,EAAW,UAAU,QAAQA,EAAW,MAAM,KAAK,UAAUA,EAAW,MAAM,GAAG;AAAA,IAAA;AAGzF,aAASc,GAAIC,GAAuB;AAClC,aAAIA,EAAI,eAAe,aAAmB5D,EAAE,kBAAkB,IAC1D4D,EAAI,eAAe,QAAc5D,EAAE,aAAa,IAChD4D,EAAI,eAAe,YAAkB5D,EAAE,iBAAiB,IAErD4D,EAAI,aAAa5D,EAAE,gBAAgB,IAAI;AAAA,IAChD;AAEA,mBAAee,EAAK8C,GAAmC;AACrD,MAAAlB,EAAQ,QAAQ;AAEhB,UAAI;AACF,QAAAD,EAAK,QAAQ,MAAM9C,EAAI,KAAK,EAAE,MAAMiE,GAAO,QAAQ,GAAG,UAAUA,GAAO,WAAW,IAAI;AAAA,MACxF,SAAS3C,GAAO;AACd,QAAA4C,EAAM,OAAO5D,EAAQgB,CAAK,CAAC;AAAA,MAC7B,UAAA;AACE,QAAAyB,EAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AAEA,mBAAeoB,KAAyB;AACtC,YAAMC,IAAUV,EAAK;AAKrB,UAHAT,EAAW,QAAQ,MACnBE,EAAS,QAAQ,CAAA,GAEb,EAACiB,GAEL;AAAA,QAAAlB,EAAU,QAAQ;AAElB,YAAI;AACF,UAAAD,EAAW,QAAQ,MAAMjD,EAAI,QAAQoE,EAAQ,IAAIA,EAAQ,IAAI;AAAA,QAC/D,SAAS9C,GAAO;AACd,UAAA4C,EAAM,OAAO5D,EAAQgB,CAAK,CAAC;AAAA,QAC7B,UAAA;AACE,UAAA4B,EAAU,QAAQ;AAAA,QACpB;AAAA;AAAA,IACF;AAGA,UAAMmB,KAAUpD;AAAA,MAAyB,MACvCoC,KAAaP,EAAK,OAAO,QACrB;AAAA,QACE;AAAA,UACE,KAAK;AAAA,UACL,OAAO1C,EAAE,YAAY;AAAA,UACrB,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,UAAUgD,EAAS;AAAA,UACnB,KAAK,MAAA;AAAM,YAAKkB,GAAA;AAAA;AAAA,QAAM;AAAA,MACxB,IAEF,CAAA;AAAA,IAAC;AAGP,mBAAeA,KAAuB;AASpC,UARe,MAAMC,GAAQ;AAAA,QAC3B,OAAOnE,EAAE,kBAAkB;AAAA,QAC3B,SAASA,EAAE,iBAAiB;AAAA,QAC5B,aAAaA,EAAE,oBAAoB;AAAA,QACnC,YAAYA,EAAE,mBAAmB;AAAA,QACjC,MAAM;AAAA,MAAA,CACP,GAID;AAAA,QAAAgD,EAAS,QAAQ;AAEjB,YAAI;AACF,gBAAMpD,EAAI,MAAA,GACVgD,EAAS,QAAQ,CAAA,GACjBkB,EAAM,QAAQ9D,EAAE,cAAc,CAAC,GAC/B,MAAMe,EAAA;AAAA,QACR,SAASG,GAAO;AACd,UAAA4C,EAAM,OAAO5D,EAAQgB,CAAK,CAAC;AAAA,QAC7B,UAAA;AACE,UAAA8B,EAAS,QAAQ;AAAA,QACnB;AAAA;AAAA,IACF;AAEA,WAAAoB,GAAU,MAAM;AACd,YAAMC,IAAK,OAAO7B,EAAM,MAAM,EAAE;AAEhC,MAAI,OAAO,UAAU6B,CAAE,KAAKA,IAAK,MAAGzB,EAAS,QAAQ,CAACyB,CAAE;AAAA,IAC1D,CAAC,GAEDlD,EAAMyB,GAAU,CAAC0B,MAAS;AAExB,MAAIA,EAAK,SAAS,MAAY,QAAQA,EAAK,MAAM,EAAE,IACzCP,GAAA;AAAA,IACZ,CAAC,mBAICpC,EA+Fe4C,IAAA;AAAA,MA/FA,MAAM7E,EAAM;AAAA,MAAM,SAAQ;AAAA,MAAQ,MAAM;AAAA,MAAQ,SAASuE,GAAA;AAAA,IAAA;iBACtE,MA6FM;AAAA,QA7FNO,GA6FM,OA7FNlD,IA6FM;AAAA,UA5FJC,EA0CUC,EAAAiD,CAAA,GAAA,MAAA;AAAA,uBAxCR,MAKE;AAAA,eAJOnB,EAAA,SAAQZ,EAAA,OAAM,cADvBf,EAKEH,EAAAkD,CAAA,GAAA;AAAA;gBAHA,MAAK;AAAA,gBACJ,aAAalD,EAAAxB,CAAA,EAAC,mBAAA;AAAA,gBACf,OAAM;AAAA,cAAA;cAGRuB,EAgCWC,EAAAmD,CAAA,GAAA;AAAA,gBA/BD,UAAU/B,EAAA;AAAA,4DAAAA,EAAQ,QAAAlB;AAAA,gBACzB,MAAMgB,EAAA;AAAA,gBACN,SAASU,EAAA;AAAA,gBACV,WAAQ;AAAA,gBACR,YAAA;AAAA,gBACC,iBAAa,CAAGwB,MAAkBA,EAAI,WAAM;AAAA,gBAC7C,OAAA;AAAA,gBACC,SAASjC,EAAA;AAAA,gBACT,cAAYnB,EAAAxB,CAAA,EAAC,iBAAA;AAAA,gBACb,eAAce;AAAA,cAAA;gBAEJ,mBAAe8D,EAAW,CAAmC,EAA1C,KAAAD,QAAG;AAAA,kBAAIrD,EAAmCC,EAAAsD,CAAA,GAAA;AAAA,oBAAzB,OAAOF,EAAI;AAAA,kBAAA;;gBAC/C,cAAUC,EAAW,CAAkC,EAAzC,KAAAD,QAAG;AAAA,sBAAOpD,EAAAxB,CAAA,EAAC,cAAe4E,EAAI,KAAK,EAAA,CAAA,GAAA,CAAA;AAAA,gBAAA;gBACjD,eAAWC,EACpB,CAEa,EAHW,KAAAD,QAAG;AAAA,kBAC3BrD,EAEaC,EAAAuD,CAAA,GAAA;AAAA,oBAFF,MAAM7B,EAAS0B,EAAI,MAAM;AAAA,oBAAG,KAAA;AAAA,kBAAA;+BAAI,MAEzC;AAAA,0BADApD,EAAAxB,CAAA,EAAC,eAAgB4E,EAAI,MAAM,EAAA,CAAA,GAAA,CAAA;AAAA,oBAAA;;;;gBAGpB,eAAWC,EAAW,CAE/B,EAFwB,KAAAD,QAAG;AAAA,kBAC3B3C,EAAAC,EAAA0C,EAAI,SAAM,GAAMA,EAAI,OAAO,MAAM,MAAA,EAAA,GAAA,CAAA;AAAA,gBAAA;gBAExB,iBAAaC,EACtB,CAMO,EAPmB,KAAAD,QAAG;AAAA,kBACjBA,EAAI,UAAhBxD,EAAA,GAAAC,EAMO,QANP2D,IAMO;AAAA,qBALL5D,EAAA,GAAAC,EAIWQ,GAAA,MAAAC,EAJqBqB,GAAU,CAAxB8B,IAAMC,6BAA6B;AAAA,sBACnCN,EAAI,OAAO,SAASM,CAAG,UAAvCvD,EAEaH,EAAAuD,CAAA,GAAA;AAAA;wBAF8B,MAAAE;AAAA,wBAAY,MAAK;AAAA,sBAAA;mCAAK,MAE/D;AAAA,0BADAhD,EAAAC,EAAA0C,EAAI,OAAO,SAASM,CAAG,CAAA,GAAA,CAAA;AAAA,wBAAA;;;;;;gBAKpB,mBAAeL,EAAW,CAAc,EAArB,KAAAD,QAAG;AAAA,kBAAO3C,EAAAC,EAAAyB,GAAIiB,CAAG,CAAA,GAAA,CAAA;AAAA,gBAAA;;;;;;UAIpCtB,EAAA,cAAf3B,EA+CUH,EAAAiD,CAAA,GAAA;AAAA;YA/CY,OAAOjD,EAAAxB,CAAA,EAAC,cAAA;AAAA,UAAA;uBAC5B,MAMU;AAAA,cANK6C,EAAA,cAAflB,EAMUH,EAAAI,CAAA,GAAA;AAAA;gBANiB,MAAK;AAAA,gBAAK,MAAK;AAAA,gBAAQ,OAAM;AAAA,cAAA;2BACtD,MAA4B;AAAA,sBAAzBJ,EAAAxB,CAAA,EAAC,mBAAA,CAAA,IAAwB,OAAEkC,EAAGW,EAAA,MAAW,KAAK,EAAE,IAAG,OACtD,CAAA;AAAA,kBAAAtB,EAA+CC,EAAAsD,CAAA,GAAA;AAAA,oBAArC,OAAOjC,EAAA,MAAW,KAAK;AAAA,kBAAA;oBAAc,QAAGX,EAAGV,EAAAxB,CAAA,EAAC,iBAAA,CAAA,IAAsB,OAAEkC,EAC5EW,EAAA,MAAW,GAAG,EAAE,IAChB,OACA,CAAA;AAAA,kBAAAtB,EAA6CC,EAAAsD,CAAA,GAAA;AAAA,oBAAnC,OAAOjC,EAAA,MAAW,GAAG;AAAA,kBAAA;;;;cAI3Ba,EAAA,cADR/B,EAKEH,EAAAkD,CAAA,GAAA;AAAA;gBAHA,MAAK;AAAA,gBACJ,aAAalD,EAAAxB,CAAA,EAAC,qBAAA;AAAA,gBACf,OAAM;AAAA,cAAA;cAGRuB,EA8BWC,EAAAmD,CAAA,GAAA;AAAA,gBA7BD,UAAU5B,EAAA;AAAA,4DAAAA,EAAQ,QAAArB;AAAA,gBACzB,MAAMmB,EAAA,OAAY,UAAM,CAAA;AAAA,gBACxB,SAASQ,EAAA;AAAA,gBACV,WAAQ;AAAA,gBACR,YAAA;AAAA,gBACA,OAAA;AAAA,gBACC,YAAY;AAAA,gBACZ,SAASP,EAAA;AAAA,gBACT,cAAYtB,EAAAxB,CAAA,EAAC,mBAAA;AAAA,cAAA;gBAEH,iBAAa6E,EACtB,CAEa,EAHa,KAAAD,QAAG;AAAA,kBAC7BrD,EAEaC,EAAAuD,CAAA,GAAA;AAAA,oBAFF,MAAM5B,EAAWyB,EAAI,QAAQ;AAAA,oBAAG,KAAA;AAAA,kBAAA;+BAAI,MAE7C;AAAA,0BADApD,EAAAxB,CAAA,EAAC,iBAAkB4E,EAAI,QAAQ,EAAA,CAAA,GAAA,CAAA;AAAA,oBAAA;;;;gBAGxB,YAAQC,EACjB,CAA+E,EAD1D,KAAAD,QAAG;AAAA,kBACxBrD,EAA+EC,EAAAI,CAAA,GAAA;AAAA,oBAArE,MAAMgD,EAAI,MAAG,WAAA;AAAA,oBAAuB,MAAK;AAAA,kBAAA;+BAAK,MAAa;AAAA,sBAAV3C,EAAAC,EAAA0C,EAAI,GAAG,GAAA,CAAA;AAAA,oBAAA;;;;gBAEzD,cAAUC,EACnB,CAAoF,EAD7D,KAAAD,QAAG;AAAA,kBAC1BrD,EAAoFC,EAAAI,CAAA,GAAA;AAAA,oBAA1E,MAAMgD,EAAI,QAAK,YAAA;AAAA,oBAAwB,MAAK;AAAA,kBAAA;+BAAK,MAAe;AAAA,sBAAZ3C,EAAAC,EAAA0C,EAAI,KAAK,GAAA,CAAA;AAAA,oBAAA;;;;gBAE9D,UAAQC,EACjB,CAKE,EANmB,KAAAD,QAAG;AAAA,kBAEhB/B,EAAA,cADRlB,EAKEwD,IAAA;AAAA;oBAHC,MAAMtC,EAAA,MAAW,KAAK;AAAA,oBACtB,IAAIA,EAAA,MAAW,GAAG;AAAA,oBAClB,KAAA+B;AAAA,kBAAA;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { defineComponent as N, ref as n, onMounted as W, openBlock as o, createBlock as r, withCtx as u, createElementVNode as M, unref as e, createVNode as T, createTextVNode as x, toDisplayString as b, createCommentVNode as k } from "vue";
|
|
2
|
+
import { useRouter as h } from "vue-router";
|
|
3
|
+
import { useAdmin as E, useTranslate as w, useErrorText as P, WxScreen as $ } from "@webx-ui/module-admin";
|
|
4
|
+
import { toast as d, WxSkeleton as D, WxActionBar as I, WxButton as A } from "@webx-ui/core";
|
|
5
|
+
import { _ as R } from "./AuditLayout.vue_vue_type_script_setup_true_lang-C8H5jlTe.js";
|
|
6
|
+
import { c as U, u as j, _ as q } from "./index-BFYHJYU_.js";
|
|
7
|
+
const z = { class: "wx-audit-settings" }, F = /* @__PURE__ */ N({
|
|
8
|
+
__name: "AuditSettingsPage",
|
|
9
|
+
props: {
|
|
10
|
+
base: {}
|
|
11
|
+
},
|
|
12
|
+
setup(V) {
|
|
13
|
+
const m = V, f = E(), p = U(f);
|
|
14
|
+
j();
|
|
15
|
+
const v = w("webx-audit"), S = w("webx-admin"), C = h(), g = P(), a = n({}), l = n({}), i = n(!0), c = n(!1), _ = f.can("audit.manage");
|
|
16
|
+
W(async () => {
|
|
17
|
+
try {
|
|
18
|
+
a.value = await p.settings();
|
|
19
|
+
} catch (s) {
|
|
20
|
+
d.danger(g(s));
|
|
21
|
+
} finally {
|
|
22
|
+
i.value = !1;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
async function B() {
|
|
26
|
+
c.value = !0, l.value = {};
|
|
27
|
+
try {
|
|
28
|
+
a.value = await p.saveSettings(a.value), d.success(v("page.saved"));
|
|
29
|
+
} catch (s) {
|
|
30
|
+
const t = s.body;
|
|
31
|
+
t?.errors && (l.value = t.errors), d.danger(g(s));
|
|
32
|
+
} finally {
|
|
33
|
+
c.value = !1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return (s, t) => (o(), r(R, {
|
|
37
|
+
base: m.base,
|
|
38
|
+
current: "settings",
|
|
39
|
+
card: !1
|
|
40
|
+
}, {
|
|
41
|
+
default: u(() => [
|
|
42
|
+
M("div", z, [
|
|
43
|
+
i.value ? (o(), r(e(D), {
|
|
44
|
+
key: 0,
|
|
45
|
+
rows: 6
|
|
46
|
+
})) : (o(), r(e($), {
|
|
47
|
+
key: 1,
|
|
48
|
+
modelValue: a.value,
|
|
49
|
+
"onUpdate:modelValue": t[0] || (t[0] = (y) => a.value = y),
|
|
50
|
+
name: "audit.settings",
|
|
51
|
+
errors: l.value,
|
|
52
|
+
disabled: !e(_)
|
|
53
|
+
}, null, 8, ["modelValue", "errors", "disabled"])),
|
|
54
|
+
i.value ? k("", !0) : (o(), r(e(I), { key: 2 }, {
|
|
55
|
+
default: u(() => [
|
|
56
|
+
T(e(A), {
|
|
57
|
+
icon: "arrow-left",
|
|
58
|
+
onClick: t[1] || (t[1] = (y) => e(C).push(m.base))
|
|
59
|
+
}, {
|
|
60
|
+
default: u(() => [
|
|
61
|
+
x(b(e(S)("editor.back")), 1)
|
|
62
|
+
]),
|
|
63
|
+
_: 1
|
|
64
|
+
}),
|
|
65
|
+
e(_) ? (o(), r(e(A), {
|
|
66
|
+
key: 0,
|
|
67
|
+
type: "primary",
|
|
68
|
+
loading: c.value,
|
|
69
|
+
onClick: B
|
|
70
|
+
}, {
|
|
71
|
+
default: u(() => [
|
|
72
|
+
x(b(e(v)("page.save")), 1)
|
|
73
|
+
]),
|
|
74
|
+
_: 1
|
|
75
|
+
}, 8, ["loading"])) : k("", !0)
|
|
76
|
+
]),
|
|
77
|
+
_: 1
|
|
78
|
+
}))
|
|
79
|
+
])
|
|
80
|
+
]),
|
|
81
|
+
_: 1
|
|
82
|
+
}, 8, ["base"]));
|
|
83
|
+
}
|
|
84
|
+
}), Q = /* @__PURE__ */ q(F, [["__scopeId", "data-v-37901757"]]);
|
|
85
|
+
export {
|
|
86
|
+
Q as default
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=AuditSettingsPage-HwfdLU_s.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditSettingsPage-HwfdLU_s.js","sources":["../src/AuditSettingsPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { useAdmin, useErrorText, useTranslate, WxScreen } from '@webx-ui/module-admin'\nimport { toast, WxActionBar, WxButton, WxSkeleton } from '@webx-ui/core'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport AuditLayout from './AuditLayout.vue'\nimport { createAuditApi } from './api'\nimport { useAuditMessages } from './i18n'\n\n/**\n * The section's settings (§8): where the site is and which hosts are its stands, the limits of\n * the crawl and the paths it leaves out, the thresholds, the nightly run and how much history\n * to keep. The form is the screen the server describes (`audit.settings`), so a project patches\n * a field in the way it does everywhere else; saving is this page's own. «Back» beside «Save» returns\n * to the overview — the tabs above cannot, their «Overview» is already the lit one.\n */\nconst props = defineProps<{ base: string }>()\n\nconst context = useAdmin()\nconst api = createAuditApi(context)\nuseAuditMessages()\n\nconst t = useTranslate('webx-audit')\nconst panel = useTranslate('webx-admin')\nconst router = useRouter()\nconst message = useErrorText()\n\nconst values = ref<ScreenModel>({})\nconst errors = ref<Record<string, string[]>>({})\nconst loading = ref(true)\nconst saving = ref(false)\n\n// A boolean, not a computed: the permissions do not change while the screen is open.\nconst canManage = context.can('audit.manage')\n\nonMounted(async () => {\n try {\n values.value = (await api.settings()) as ScreenModel\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n})\n\nasync function save(): Promise<void> {\n saving.value = true\n errors.value = {}\n\n try {\n values.value = (await api.saveSettings(values.value)) as ScreenModel\n toast.success(t('page.saved'))\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n\n if (body?.errors) errors.value = body.errors\n\n toast.danger(message(error))\n } finally {\n saving.value = false\n }\n}\n</script>\n\n<template>\n <audit-layout :base=\"props.base\" current=\"settings\" :card=\"false\">\n <div class=\"wx-audit-settings\">\n <wx-skeleton v-if=\"loading\" :rows=\"6\" />\n <wx-screen\n v-else\n v-model=\"values\"\n name=\"audit.settings\"\n :errors=\"errors\"\n :disabled=\"!canManage\"\n />\n\n <wx-action-bar v-if=\"!loading\">\n <wx-button icon=\"arrow-left\" @click=\"router.push(props.base)\">{{\n panel('editor.back')\n }}</wx-button>\n <wx-button v-if=\"canManage\" type=\"primary\" :loading=\"saving\" @click=\"save\">{{\n t('page.save')\n }}</wx-button>\n </wx-action-bar>\n </div>\n </audit-layout>\n</template>\n\n<style scoped>\n.wx-audit-settings {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n}\n</style>\n"],"names":["props","__props","context","useAdmin","api","createAuditApi","useAuditMessages","t","useTranslate","panel","router","useRouter","message","useErrorText","values","ref","errors","loading","saving","canManage","onMounted","error","toast","save","body","_createBlock","AuditLayout","_createElementVNode","_hoisted_1","_unref","WxSkeleton","WxScreen","$event","WxActionBar","_createVNode","WxButton"],"mappings":";;;;;;;;;;;;AAiBA,UAAMA,IAAQC,GAERC,IAAUC,EAAA,GACVC,IAAMC,EAAeH,CAAO;AAClC,IAAAI,EAAA;AAEA,UAAMC,IAAIC,EAAa,YAAY,GAC7BC,IAAQD,EAAa,YAAY,GACjCE,IAASC,EAAA,GACTC,IAAUC,EAAA,GAEVC,IAASC,EAAiB,EAAE,GAC5BC,IAASD,EAA8B,EAAE,GACzCE,IAAUF,EAAI,EAAI,GAClBG,IAASH,EAAI,EAAK,GAGlBI,IAAYjB,EAAQ,IAAI,cAAc;AAE5C,IAAAkB,EAAU,YAAY;AACpB,UAAI;AACF,QAAAN,EAAO,QAAS,MAAMV,EAAI,SAAA;AAAA,MAC5B,SAASiB,GAAO;AACd,QAAAC,EAAM,OAAOV,EAAQS,CAAK,CAAC;AAAA,MAC7B,UAAA;AACE,QAAAJ,EAAQ,QAAQ;AAAA,MAClB;AAAA,IACF,CAAC;AAED,mBAAeM,IAAsB;AACnC,MAAAL,EAAO,QAAQ,IACfF,EAAO,QAAQ,CAAA;AAEf,UAAI;AACF,QAAAF,EAAO,QAAS,MAAMV,EAAI,aAAaU,EAAO,KAAK,GACnDQ,EAAM,QAAQf,EAAE,YAAY,CAAC;AAAA,MAC/B,SAASc,GAAO;AACd,cAAMG,IAAQH,EAA2D;AAEzE,QAAIG,GAAM,WAAQR,EAAO,QAAQQ,EAAK,SAEtCF,EAAM,OAAOV,EAAQS,CAAK,CAAC;AAAA,MAC7B,UAAA;AACE,QAAAH,EAAO,QAAQ;AAAA,MACjB;AAAA,IACF;2BAIEO,EAoBeC,GAAA;AAAA,MApBA,MAAM1B,EAAM;AAAA,MAAM,SAAQ;AAAA,MAAY,MAAM;AAAA,IAAA;iBACzD,MAkBM;AAAA,QAlBN2B,EAkBM,OAlBNC,GAkBM;AAAA,UAjBeX,EAAA,cAAnBQ,EAAwCI,EAAAC,CAAA,GAAA;AAAA;YAAX,MAAM;AAAA,UAAA,YACnCL,EAMEI,EAAAE,CAAA,GAAA;AAAA;wBAJSjB,EAAA;AAAA,0DAAAA,EAAM,QAAAkB;AAAA,YACf,MAAK;AAAA,YACJ,QAAQhB,EAAA;AAAA,YACR,WAAWa,EAAAV,CAAA;AAAA,UAAA;UAGQF,EAAA,0BAAtBQ,EAOgBI,EAAAI,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,uBANd,MAEc;AAAA,cAFdC,EAEcL,EAAAM,CAAA,GAAA;AAAA,gBAFH,MAAK;AAAA,gBAAc,gCAAON,EAAAnB,CAAA,EAAO,KAAKV,EAAM,IAAI;AAAA,cAAA;2BAAG,MAE5D;AAAA,sBADA6B,EAAApB,CAAA,EAAK,aAAA,CAAA,GAAA,CAAA;AAAA,gBAAA;;;cAEUoB,EAAAV,CAAA,UAAjBM,EAEcI,EAAAM,CAAA,GAAA;AAAA;gBAFc,MAAK;AAAA,gBAAW,SAASjB,EAAA;AAAA,gBAAS,SAAOK;AAAA,cAAA;2BAAM,MAEzE;AAAA,sBADAM,EAAAtB,CAAA,EAAC,WAAA,CAAA,GAAA,CAAA;AAAA,gBAAA;;;;;;;;;;;;"}
|