@webx-ui/module-audit 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. package/dist/{AuditHostsPage-YFRORYHZ.js → AuditHostsPage-DZ1vYvZR.js} +3 -3
  2. package/dist/{AuditHostsPage-YFRORYHZ.js.map → AuditHostsPage-DZ1vYvZR.js.map} +1 -1
  3. package/dist/AuditIssuesPage-CdWydT5i.js +718 -0
  4. package/dist/AuditIssuesPage-CdWydT5i.js.map +1 -0
  5. package/dist/{AuditLayout.vue_vue_type_script_setup_true_lang-C8H5jlTe.js → AuditLayout.vue_vue_type_script_setup_true_lang-BIj7GvJb.js} +2 -2
  6. package/dist/{AuditLayout.vue_vue_type_script_setup_true_lang-C8H5jlTe.js.map → AuditLayout.vue_vue_type_script_setup_true_lang-BIj7GvJb.js.map} +1 -1
  7. package/dist/{AuditOverviewPage-gVpdBOAY.js → AuditOverviewPage-BqTU-JnS.js} +3 -3
  8. package/dist/{AuditOverviewPage-gVpdBOAY.js.map → AuditOverviewPage-BqTU-JnS.js.map} +1 -1
  9. package/dist/{AuditPagesPage-DNgZo-K-.js → AuditPagesPage-CsizUOgz.js} +3 -3
  10. package/dist/{AuditPagesPage-DNgZo-K-.js.map → AuditPagesPage-CsizUOgz.js.map} +1 -1
  11. package/dist/{AuditRunsPage-BbWsuATw.js → AuditRunsPage-D9hzlpID.js} +3 -3
  12. package/dist/{AuditRunsPage-BbWsuATw.js.map → AuditRunsPage-D9hzlpID.js.map} +1 -1
  13. package/dist/{AuditSettingsPage-HwfdLU_s.js → AuditSettingsPage-R9qoNgbJ.js} +3 -3
  14. package/dist/{AuditSettingsPage-HwfdLU_s.js.map → AuditSettingsPage-R9qoNgbJ.js.map} +1 -1
  15. package/dist/{index-BFYHJYU_.js → index-BxS_t2W2.js} +435 -419
  16. package/dist/index-BxS_t2W2.js.map +1 -0
  17. package/dist/index.js +1 -1
  18. package/dist/style.css +1 -1
  19. package/package.json +4 -4
  20. package/dist/AuditIssuesPage-BjTPgAnD.js +0 -693
  21. package/dist/AuditIssuesPage-BjTPgAnD.js.map +0 -1
  22. package/dist/index-BFYHJYU_.js.map +0 -1
@@ -1 +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":"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"}
1
+ {"version":3,"file":"AuditRunsPage-D9hzlpID.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":"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"}
@@ -2,8 +2,8 @@ import { defineComponent as N, ref as n, onMounted as W, openBlock as o, createB
2
2
  import { useRouter as h } from "vue-router";
3
3
  import { useAdmin as E, useTranslate as w, useErrorText as P, WxScreen as $ } from "@webx-ui/module-admin";
4
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";
5
+ import { _ as R } from "./AuditLayout.vue_vue_type_script_setup_true_lang-BIj7GvJb.js";
6
+ import { c as U, u as j, _ as q } from "./index-BxS_t2W2.js";
7
7
  const z = { class: "wx-audit-settings" }, F = /* @__PURE__ */ N({
8
8
  __name: "AuditSettingsPage",
9
9
  props: {
@@ -85,4 +85,4 @@ const z = { class: "wx-audit-settings" }, F = /* @__PURE__ */ N({
85
85
  export {
86
86
  Q as default
87
87
  };
88
- //# sourceMappingURL=AuditSettingsPage-HwfdLU_s.js.map
88
+ //# sourceMappingURL=AuditSettingsPage-R9qoNgbJ.js.map
@@ -1 +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;;;;;;;;;;;;"}
1
+ {"version":3,"file":"AuditSettingsPage-R9qoNgbJ.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;;;;;;;;;;;;"}