@webx-ui/module-audit 0.5.4 → 0.5.6
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-DZ1vYvZR.js → AuditHostsPage-MLODrjlQ.js} +3 -3
- package/dist/{AuditHostsPage-DZ1vYvZR.js.map → AuditHostsPage-MLODrjlQ.js.map} +1 -1
- package/dist/{AuditIssuesPage-CdWydT5i.js → AuditIssuesPage-CGyEXQoj.js} +3 -3
- package/dist/{AuditIssuesPage-CdWydT5i.js.map → AuditIssuesPage-CGyEXQoj.js.map} +1 -1
- package/dist/{AuditLayout.vue_vue_type_script_setup_true_lang-BIj7GvJb.js → AuditLayout.vue_vue_type_script_setup_true_lang-EVgQHRlA.js} +2 -2
- package/dist/{AuditLayout.vue_vue_type_script_setup_true_lang-BIj7GvJb.js.map → AuditLayout.vue_vue_type_script_setup_true_lang-EVgQHRlA.js.map} +1 -1
- package/dist/{AuditOverviewPage-BqTU-JnS.js → AuditOverviewPage-DeLwz3V9.js} +3 -3
- package/dist/{AuditOverviewPage-BqTU-JnS.js.map → AuditOverviewPage-DeLwz3V9.js.map} +1 -1
- package/dist/{AuditPagesPage-CsizUOgz.js → AuditPagesPage-Dolrp-sC.js} +3 -3
- package/dist/{AuditPagesPage-CsizUOgz.js.map → AuditPagesPage-Dolrp-sC.js.map} +1 -1
- package/dist/{AuditRunsPage-D9hzlpID.js → AuditRunsPage-D4SVqAAb.js} +3 -3
- package/dist/{AuditRunsPage-D9hzlpID.js.map → AuditRunsPage-D4SVqAAb.js.map} +1 -1
- package/dist/{AuditSettingsPage-R9qoNgbJ.js → AuditSettingsPage-CAHxMpDT.js} +3 -3
- package/dist/{AuditSettingsPage-R9qoNgbJ.js.map → AuditSettingsPage-CAHxMpDT.js.map} +1 -1
- package/dist/{index-BxS_t2W2.js → index-DSuojSPF.js} +19 -8
- package/dist/index-DSuojSPF.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/index-BxS_t2W2.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditOverviewPage-BqTU-JnS.js","sources":["../src/AuditOverviewPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate, WxDate } from '@webx-ui/module-admin'\nimport {\n toast,\n WxAlert,\n WxBadge,\n WxButton,\n WxCard,\n WxEmpty,\n WxPopover,\n WxProgress,\n WxSegmented,\n WxSkeleton,\n WxStatistic,\n WxText,\n type ProgressStatus,\n} from '@webx-ui/core'\nimport AuditLayout from './AuditLayout.vue'\nimport { createAuditApi } from './api'\nimport { useAuditMessages } from './i18n'\nimport type { AuditLatest, AuditRun, AuditScope, AuditSeverity } from './types'\n\n/**\n * The last run at a glance (§8): health and what it is made of, the counts by severity and by\n * group, what is new and what got fixed since the run before, and the button that starts the next one. While a run is\n * going the page asks for it every couple of seconds and shows the stage it is in.\n */\nconst props = defineProps<{ base: string }>()\n\nconst context = useAdmin()\nconst api = createAuditApi(context)\nuseAuditMessages()\n\nconst t = useTranslate('webx-audit')\nconst message = useErrorText()\n\nconst POLL_MS = 2000\n\nconst latest = ref<AuditLatest | null>(null)\nconst scope = ref<AuditScope>('quick')\nconst starting = ref(false)\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nconst canRun = context.can('audit.run') || context.can('audit.manage')\n\nconst active = computed(() => latest.value?.active ?? null)\nconst done = computed(() => latest.value?.done ?? null)\nconst counts = computed(() => done.value?.counts ?? null)\n\nconst scopes = computed(() => [\n { value: 'quick', label: t('page.scope-quick') },\n { value: 'full', label: t('page.scope-full') },\n])\n\nconst severities: { key: AuditSeverity; label: string; tone: 'danger' | 'warning' | 'info' }[] = [\n { key: 'error', label: 'page.errors', tone: 'danger' },\n { key: 'warning', label: 'page.warnings', tone: 'warning' },\n { key: 'notice', label: 'page.notices', tone: 'info' },\n]\n\nconst parts = computed(() => counts.value?.health_parts ?? null)\n\nconst healthStatus = computed<ProgressStatus>(() => {\n const health = counts.value?.health ?? 0\n\n if (health >= 90) return 'success'\n if (health >= 60) return 'warning'\n\n return 'danger'\n})\n\n/* The groups this package has words for; a module's own group reads as «Other». */\nconst GROUPS = [\n 'config',\n 'host',\n 'hosts',\n 'indexing',\n 'page',\n 'content',\n 'links',\n 'images',\n 'a11y',\n 'structure',\n]\n\nconst groups = computed(() =>\n Object.entries(counts.value?.groups ?? {}).map(([id, bySeverity]) => ({\n id,\n label: t(`page.group-${GROUPS.includes(id) ? id : 'other'}`),\n bySeverity,\n })),\n)\n\nfunction stageLabel(run: AuditRun): string {\n if (run.status === 'queued') return t('page.status-queued')\n\n return run.progress.stage ? t(`page.stage-${run.progress.stage}`) : t('page.status-running')\n}\n\nasync function load(): Promise<void> {\n try {\n latest.value = await api.latest()\n } catch (error) {\n toast.danger(message(error))\n }\n\n clearTimeout(timer)\n\n if (latest.value?.active) {\n timer = setTimeout(() => void load(), POLL_MS)\n }\n}\n\nasync function start(): Promise<void> {\n starting.value = true\n\n try {\n await api.start(scope.value)\n toast.success(t('page.started'))\n await load()\n } catch (error) {\n toast.danger(message(error))\n } finally {\n starting.value = false\n }\n}\n\nasync function cancel(run: AuditRun): Promise<void> {\n try {\n await api.cancel(run.id)\n await load()\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nonMounted(load)\nonBeforeUnmount(() => clearTimeout(timer))\n</script>\n\n<template>\n <audit-layout :base=\"props.base\" current=\"overview\" :card=\"false\">\n <div class=\"wx-audit-overview\">\n <wx-card v-if=\"!latest\"><wx-skeleton :rows=\"4\" /></wx-card>\n\n <template v-else>\n <wx-alert v-if=\"latest.queue.sync\" type=\"warning\" :description=\"t('page.sync-queue')\" />\n\n <wx-alert\n v-if=\"latest.last && latest.last.status === 'failed'\"\n type=\"danger\"\n :description=\"t('page.last-failed', { error: latest.last.error ?? '' })\"\n />\n\n <wx-card v-if=\"active\" class=\"wx-audit-overview__active\">\n <div class=\"wx-audit-overview__row\">\n <wx-text weight=\"semibold\">{{ stageLabel(active) }}</wx-text>\n <wx-text size=\"sm\" tone=\"muted\" class=\"wx-audit-overview__url\">{{\n active.base_url\n }}</wx-text>\n <wx-button\n v-if=\"canRun\"\n size=\"sm\"\n class=\"wx-audit-overview__end\"\n @click=\"cancel(active)\"\n >{{ t('page.cancel') }}</wx-button\n >\n </div>\n <wx-progress indeterminate :aria-label=\"stageLabel(active)\" />\n <wx-text v-if=\"active.progress.resources\" size=\"sm\" tone=\"muted\">{{\n t('page.resources-progress', {\n checked: active.progress.resources.checked,\n total: active.progress.resources.total,\n })\n }}</wx-text>\n <wx-text v-else-if=\"active.progress.stage === 'crawl'\" size=\"sm\" tone=\"muted\">{{\n t('page.pages-progress', {\n crawled: active.progress.pages.crawled,\n limit: active.progress.pages.limit,\n })\n }}</wx-text>\n </wx-card>\n\n <wx-card v-else-if=\"canRun && !latest.queue.sync\">\n <div class=\"wx-audit-overview__row\">\n <wx-segmented v-model=\"scope\" :options=\"scopes\" :aria-label=\"t('page.scope')\" />\n <wx-text size=\"sm\" tone=\"muted\">{{\n scope === 'full' ? t('page.scope-full-help') : t('page.scope-quick-help')\n }}</wx-text>\n <wx-button\n type=\"primary\"\n icon=\"refresh\"\n :loading=\"starting\"\n class=\"wx-audit-overview__end\"\n @click=\"start\"\n >{{ t('page.run') }}</wx-button\n >\n </div>\n </wx-card>\n\n <wx-card v-if=\"!done && !active\">\n <wx-empty\n icon=\"check-circle\"\n :title=\"t('page.never')\"\n :description=\"t('page.never-help')\"\n />\n </wx-card>\n\n <template v-if=\"done && counts\">\n <wx-card>\n <div class=\"wx-audit-overview__summary\">\n <div class=\"wx-audit-overview__health\">\n <wx-progress\n type=\"circle\"\n :value=\"counts.health\"\n :status=\"healthStatus\"\n show-value\n :formatter=\"(value: number) => `${value}%`\"\n :aria-label=\"t('page.health')\"\n />\n <div v-if=\"parts\" class=\"wx-audit-overview__parts\">\n <wx-text v-if=\"parts.pages > 0\" size=\"sm\">{{\n t('page.health-pages', { clean: parts.clean, pages: parts.pages })\n }}</wx-text>\n <wx-text v-if=\"parts.site_errors > 0\" size=\"sm\" tone=\"danger\">{{\n t('page.health-site', { count: parts.site_errors })\n }}</wx-text>\n <wx-text v-if=\"parts.warnings > 0\" size=\"sm\" tone=\"warning\">{{\n t('page.health-warnings', { count: parts.warnings })\n }}</wx-text>\n <wx-text size=\"xs\" tone=\"muted\">{{ t('page.health-help') }}</wx-text>\n </div>\n </div>\n <div class=\"wx-audit-overview__stats\">\n <wx-statistic\n v-for=\"severity in severities\"\n :key=\"severity.key\"\n :title=\"t(severity.label)\"\n :value=\"counts.severity[severity.key] ?? 0\"\n :tone=\"(counts.severity[severity.key] ?? 0) > 0 ? severity.tone : 'muted'\"\n />\n <wx-statistic :title=\"t('page.new')\" :value=\"counts.new\" />\n <wx-statistic :title=\"t('page.fixed')\" :value=\"counts.fixed\" tone=\"success\" />\n </div>\n </div>\n <div class=\"wx-audit-overview__meta\">\n <wx-text size=\"sm\" tone=\"muted\">\n {{ t('page.last-run') }} <wx-date :value=\"done.finished_at\" /> ·\n {{ t(`page.scope-${done.scope}`) }} ·\n </wx-text>\n <wx-text size=\"sm\" tone=\"muted\" class=\"wx-audit-overview__url\">{{\n done.base_url\n }}</wx-text>\n </div>\n </wx-card>\n\n <wx-card v-if=\"groups.length\" :title=\"t('page.by-group')\">\n <ul class=\"wx-audit-overview__groups\">\n <li v-for=\"group in groups\" :key=\"group.id\">\n <wx-text size=\"sm\">{{ group.label }}</wx-text>\n <span class=\"wx-audit-overview__badges\">\n <template v-for=\"severity in severities\" :key=\"severity.key\">\n <wx-badge\n v-if=\"(group.bySeverity[severity.key] ?? 0) > 0\"\n :type=\"severity.tone\"\n size=\"sm\"\n >{{ t(severity.label) }} · {{ group.bySeverity[severity.key] }}</wx-badge\n >\n </template>\n </span>\n </li>\n </ul>\n </wx-card>\n\n <wx-card v-else>\n <wx-empty icon=\"check-circle\" :title=\"t('page.clean')\" size=\"sm\" />\n </wx-card>\n\n <wx-card>\n <template #header>\n <span class=\"wx-audit-overview__title\">\n {{ t('page.sources') }}\n <wx-popover :title=\"t('page.sources')\" :width=\"360\" teleport>\n <template #trigger>\n <wx-button\n variant=\"text\"\n size=\"sm\"\n icon=\"question\"\n :aria-label=\"t('page.sources-help-label')\"\n />\n </template>\n <wx-text size=\"sm\">{{ t('page.sources-help') }}</wx-text>\n </wx-popover>\n </span>\n </template>\n <div class=\"wx-audit-overview__badges\">\n <wx-badge v-for=\"source in counts.sources.searched\" :key=\"source\" type=\"success\">{{\n source\n }}</wx-badge>\n </div>\n <div v-if=\"counts.sources.missing.length\" class=\"wx-audit-overview__missing\">\n <wx-text size=\"sm\" tone=\"warning\">{{ t('page.sources-missing') }}</wx-text>\n <wx-badge v-for=\"source in counts.sources.missing\" :key=\"source\" type=\"warning\">{{\n source\n }}</wx-badge>\n </div>\n </wx-card>\n </template>\n </template>\n </div>\n </audit-layout>\n</template>\n\n<style scoped>\n.wx-audit-overview {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n container-type: inline-size;\n}\n\n.wx-audit-overview__row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-8) var(--wx-space-12);\n margin-bottom: var(--wx-space-8);\n}\n\n.wx-audit-overview__end {\n margin-left: auto;\n}\n\n.wx-audit-overview__summary {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-24);\n}\n\n.wx-audit-overview__health {\n display: flex;\n flex: 1 1 20rem;\n align-items: center;\n gap: var(--wx-space-16);\n min-width: 0;\n}\n\n/* The help is a sentence; it wraps beside the circle rather than stretching the card. */\n.wx-audit-overview__parts {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n max-width: 36ch;\n min-width: 0;\n}\n\n.wx-audit-overview__stats {\n display: flex;\n flex: 1 1 auto;\n flex-wrap: wrap;\n gap: var(--wx-space-16) var(--wx-space-32);\n}\n\n.wx-audit-overview__meta {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-4);\n margin-top: var(--wx-space-16);\n}\n\n/* A long domain breaks rather than pushing the card sideways on a phone. */\n.wx-audit-overview__url {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.wx-audit-overview__groups {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.wx-audit-overview__groups li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n}\n\n.wx-audit-overview__badges,\n.wx-audit-overview__missing {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-6);\n}\n\n.wx-audit-overview__missing {\n margin-top: var(--wx-space-12);\n}\n\n.wx-audit-overview__title {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n}\n</style>\n"],"names":["POLL_MS","props","__props","context","useAdmin","api","createAuditApi","useAuditMessages","t","useTranslate","message","useErrorText","latest","ref","scope","starting","timer","canRun","active","computed","done","counts","scopes","severities","parts","healthStatus","health","GROUPS","groups","id","bySeverity","stageLabel","run","load","error","toast","start","cancel","onMounted","onBeforeUnmount","_createBlock","AuditLayout","_createElementVNode","_hoisted_1","_createElementBlock","_Fragment","_unref","WxAlert","WxCard","_hoisted_2","_createVNode","WxText","_createTextVNode","_toDisplayString","WxButton","_cache","$event","WxProgress","_hoisted_3","WxSegmented","WxEmpty","_hoisted_4","_hoisted_5","value","_openBlock","_hoisted_6","_hoisted_7","_renderList","severity","WxStatistic","_hoisted_8","WxDate","_hoisted_9","group","_hoisted_10","WxBadge","_hoisted_11","WxPopover","_hoisted_12","source","_hoisted_13","WxSkeleton"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuditOverviewPage-DeLwz3V9.js","sources":["../src/AuditOverviewPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate, WxDate } from '@webx-ui/module-admin'\nimport {\n toast,\n WxAlert,\n WxBadge,\n WxButton,\n WxCard,\n WxEmpty,\n WxPopover,\n WxProgress,\n WxSegmented,\n WxSkeleton,\n WxStatistic,\n WxText,\n type ProgressStatus,\n} from '@webx-ui/core'\nimport AuditLayout from './AuditLayout.vue'\nimport { createAuditApi } from './api'\nimport { useAuditMessages } from './i18n'\nimport type { AuditLatest, AuditRun, AuditScope, AuditSeverity } from './types'\n\n/**\n * The last run at a glance (§8): health and what it is made of, the counts by severity and by\n * group, what is new and what got fixed since the run before, and the button that starts the next one. While a run is\n * going the page asks for it every couple of seconds and shows the stage it is in.\n */\nconst props = defineProps<{ base: string }>()\n\nconst context = useAdmin()\nconst api = createAuditApi(context)\nuseAuditMessages()\n\nconst t = useTranslate('webx-audit')\nconst message = useErrorText()\n\nconst POLL_MS = 2000\n\nconst latest = ref<AuditLatest | null>(null)\nconst scope = ref<AuditScope>('quick')\nconst starting = ref(false)\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nconst canRun = context.can('audit.run') || context.can('audit.manage')\n\nconst active = computed(() => latest.value?.active ?? null)\nconst done = computed(() => latest.value?.done ?? null)\nconst counts = computed(() => done.value?.counts ?? null)\n\nconst scopes = computed(() => [\n { value: 'quick', label: t('page.scope-quick') },\n { value: 'full', label: t('page.scope-full') },\n])\n\nconst severities: { key: AuditSeverity; label: string; tone: 'danger' | 'warning' | 'info' }[] = [\n { key: 'error', label: 'page.errors', tone: 'danger' },\n { key: 'warning', label: 'page.warnings', tone: 'warning' },\n { key: 'notice', label: 'page.notices', tone: 'info' },\n]\n\nconst parts = computed(() => counts.value?.health_parts ?? null)\n\nconst healthStatus = computed<ProgressStatus>(() => {\n const health = counts.value?.health ?? 0\n\n if (health >= 90) return 'success'\n if (health >= 60) return 'warning'\n\n return 'danger'\n})\n\n/* The groups this package has words for; a module's own group reads as «Other». */\nconst GROUPS = [\n 'config',\n 'host',\n 'hosts',\n 'indexing',\n 'page',\n 'content',\n 'links',\n 'images',\n 'a11y',\n 'structure',\n]\n\nconst groups = computed(() =>\n Object.entries(counts.value?.groups ?? {}).map(([id, bySeverity]) => ({\n id,\n label: t(`page.group-${GROUPS.includes(id) ? id : 'other'}`),\n bySeverity,\n })),\n)\n\nfunction stageLabel(run: AuditRun): string {\n if (run.status === 'queued') return t('page.status-queued')\n\n return run.progress.stage ? t(`page.stage-${run.progress.stage}`) : t('page.status-running')\n}\n\nasync function load(): Promise<void> {\n try {\n latest.value = await api.latest()\n } catch (error) {\n toast.danger(message(error))\n }\n\n clearTimeout(timer)\n\n if (latest.value?.active) {\n timer = setTimeout(() => void load(), POLL_MS)\n }\n}\n\nasync function start(): Promise<void> {\n starting.value = true\n\n try {\n await api.start(scope.value)\n toast.success(t('page.started'))\n await load()\n } catch (error) {\n toast.danger(message(error))\n } finally {\n starting.value = false\n }\n}\n\nasync function cancel(run: AuditRun): Promise<void> {\n try {\n await api.cancel(run.id)\n await load()\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nonMounted(load)\nonBeforeUnmount(() => clearTimeout(timer))\n</script>\n\n<template>\n <audit-layout :base=\"props.base\" current=\"overview\" :card=\"false\">\n <div class=\"wx-audit-overview\">\n <wx-card v-if=\"!latest\"><wx-skeleton :rows=\"4\" /></wx-card>\n\n <template v-else>\n <wx-alert v-if=\"latest.queue.sync\" type=\"warning\" :description=\"t('page.sync-queue')\" />\n\n <wx-alert\n v-if=\"latest.last && latest.last.status === 'failed'\"\n type=\"danger\"\n :description=\"t('page.last-failed', { error: latest.last.error ?? '' })\"\n />\n\n <wx-card v-if=\"active\" class=\"wx-audit-overview__active\">\n <div class=\"wx-audit-overview__row\">\n <wx-text weight=\"semibold\">{{ stageLabel(active) }}</wx-text>\n <wx-text size=\"sm\" tone=\"muted\" class=\"wx-audit-overview__url\">{{\n active.base_url\n }}</wx-text>\n <wx-button\n v-if=\"canRun\"\n size=\"sm\"\n class=\"wx-audit-overview__end\"\n @click=\"cancel(active)\"\n >{{ t('page.cancel') }}</wx-button\n >\n </div>\n <wx-progress indeterminate :aria-label=\"stageLabel(active)\" />\n <wx-text v-if=\"active.progress.resources\" size=\"sm\" tone=\"muted\">{{\n t('page.resources-progress', {\n checked: active.progress.resources.checked,\n total: active.progress.resources.total,\n })\n }}</wx-text>\n <wx-text v-else-if=\"active.progress.stage === 'crawl'\" size=\"sm\" tone=\"muted\">{{\n t('page.pages-progress', {\n crawled: active.progress.pages.crawled,\n limit: active.progress.pages.limit,\n })\n }}</wx-text>\n </wx-card>\n\n <wx-card v-else-if=\"canRun && !latest.queue.sync\">\n <div class=\"wx-audit-overview__row\">\n <wx-segmented v-model=\"scope\" :options=\"scopes\" :aria-label=\"t('page.scope')\" />\n <wx-text size=\"sm\" tone=\"muted\">{{\n scope === 'full' ? t('page.scope-full-help') : t('page.scope-quick-help')\n }}</wx-text>\n <wx-button\n type=\"primary\"\n icon=\"refresh\"\n :loading=\"starting\"\n class=\"wx-audit-overview__end\"\n @click=\"start\"\n >{{ t('page.run') }}</wx-button\n >\n </div>\n </wx-card>\n\n <wx-card v-if=\"!done && !active\">\n <wx-empty\n icon=\"check-circle\"\n :title=\"t('page.never')\"\n :description=\"t('page.never-help')\"\n />\n </wx-card>\n\n <template v-if=\"done && counts\">\n <wx-card>\n <div class=\"wx-audit-overview__summary\">\n <div class=\"wx-audit-overview__health\">\n <wx-progress\n type=\"circle\"\n :value=\"counts.health\"\n :status=\"healthStatus\"\n show-value\n :formatter=\"(value: number) => `${value}%`\"\n :aria-label=\"t('page.health')\"\n />\n <div v-if=\"parts\" class=\"wx-audit-overview__parts\">\n <wx-text v-if=\"parts.pages > 0\" size=\"sm\">{{\n t('page.health-pages', { clean: parts.clean, pages: parts.pages })\n }}</wx-text>\n <wx-text v-if=\"parts.site_errors > 0\" size=\"sm\" tone=\"danger\">{{\n t('page.health-site', { count: parts.site_errors })\n }}</wx-text>\n <wx-text v-if=\"parts.warnings > 0\" size=\"sm\" tone=\"warning\">{{\n t('page.health-warnings', { count: parts.warnings })\n }}</wx-text>\n <wx-text size=\"xs\" tone=\"muted\">{{ t('page.health-help') }}</wx-text>\n </div>\n </div>\n <div class=\"wx-audit-overview__stats\">\n <wx-statistic\n v-for=\"severity in severities\"\n :key=\"severity.key\"\n :title=\"t(severity.label)\"\n :value=\"counts.severity[severity.key] ?? 0\"\n :tone=\"(counts.severity[severity.key] ?? 0) > 0 ? severity.tone : 'muted'\"\n />\n <wx-statistic :title=\"t('page.new')\" :value=\"counts.new\" />\n <wx-statistic :title=\"t('page.fixed')\" :value=\"counts.fixed\" tone=\"success\" />\n </div>\n </div>\n <div class=\"wx-audit-overview__meta\">\n <wx-text size=\"sm\" tone=\"muted\">\n {{ t('page.last-run') }} <wx-date :value=\"done.finished_at\" /> ·\n {{ t(`page.scope-${done.scope}`) }} ·\n </wx-text>\n <wx-text size=\"sm\" tone=\"muted\" class=\"wx-audit-overview__url\">{{\n done.base_url\n }}</wx-text>\n </div>\n </wx-card>\n\n <wx-card v-if=\"groups.length\" :title=\"t('page.by-group')\">\n <ul class=\"wx-audit-overview__groups\">\n <li v-for=\"group in groups\" :key=\"group.id\">\n <wx-text size=\"sm\">{{ group.label }}</wx-text>\n <span class=\"wx-audit-overview__badges\">\n <template v-for=\"severity in severities\" :key=\"severity.key\">\n <wx-badge\n v-if=\"(group.bySeverity[severity.key] ?? 0) > 0\"\n :type=\"severity.tone\"\n size=\"sm\"\n >{{ t(severity.label) }} · {{ group.bySeverity[severity.key] }}</wx-badge\n >\n </template>\n </span>\n </li>\n </ul>\n </wx-card>\n\n <wx-card v-else>\n <wx-empty icon=\"check-circle\" :title=\"t('page.clean')\" size=\"sm\" />\n </wx-card>\n\n <wx-card>\n <template #header>\n <span class=\"wx-audit-overview__title\">\n {{ t('page.sources') }}\n <wx-popover :title=\"t('page.sources')\" :width=\"360\" teleport>\n <template #trigger>\n <wx-button\n variant=\"text\"\n size=\"sm\"\n icon=\"question\"\n :aria-label=\"t('page.sources-help-label')\"\n />\n </template>\n <wx-text size=\"sm\">{{ t('page.sources-help') }}</wx-text>\n </wx-popover>\n </span>\n </template>\n <div class=\"wx-audit-overview__badges\">\n <wx-badge v-for=\"source in counts.sources.searched\" :key=\"source\" type=\"success\">{{\n source\n }}</wx-badge>\n </div>\n <div v-if=\"counts.sources.missing.length\" class=\"wx-audit-overview__missing\">\n <wx-text size=\"sm\" tone=\"warning\">{{ t('page.sources-missing') }}</wx-text>\n <wx-badge v-for=\"source in counts.sources.missing\" :key=\"source\" type=\"warning\">{{\n source\n }}</wx-badge>\n </div>\n </wx-card>\n </template>\n </template>\n </div>\n </audit-layout>\n</template>\n\n<style scoped>\n.wx-audit-overview {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n container-type: inline-size;\n}\n\n.wx-audit-overview__row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-8) var(--wx-space-12);\n margin-bottom: var(--wx-space-8);\n}\n\n.wx-audit-overview__end {\n margin-left: auto;\n}\n\n.wx-audit-overview__summary {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-24);\n}\n\n.wx-audit-overview__health {\n display: flex;\n flex: 1 1 20rem;\n align-items: center;\n gap: var(--wx-space-16);\n min-width: 0;\n}\n\n/* The help is a sentence; it wraps beside the circle rather than stretching the card. */\n.wx-audit-overview__parts {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n max-width: 36ch;\n min-width: 0;\n}\n\n.wx-audit-overview__stats {\n display: flex;\n flex: 1 1 auto;\n flex-wrap: wrap;\n gap: var(--wx-space-16) var(--wx-space-32);\n}\n\n.wx-audit-overview__meta {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-4);\n margin-top: var(--wx-space-16);\n}\n\n/* A long domain breaks rather than pushing the card sideways on a phone. */\n.wx-audit-overview__url {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.wx-audit-overview__groups {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.wx-audit-overview__groups li {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n}\n\n.wx-audit-overview__badges,\n.wx-audit-overview__missing {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-6);\n}\n\n.wx-audit-overview__missing {\n margin-top: var(--wx-space-12);\n}\n\n.wx-audit-overview__title {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n}\n</style>\n"],"names":["POLL_MS","props","__props","context","useAdmin","api","createAuditApi","useAuditMessages","t","useTranslate","message","useErrorText","latest","ref","scope","starting","timer","canRun","active","computed","done","counts","scopes","severities","parts","healthStatus","health","GROUPS","groups","id","bySeverity","stageLabel","run","load","error","toast","start","cancel","onMounted","onBeforeUnmount","_createBlock","AuditLayout","_createElementVNode","_hoisted_1","_createElementBlock","_Fragment","_unref","WxAlert","WxCard","_hoisted_2","_createVNode","WxText","_createTextVNode","_toDisplayString","WxButton","_cache","$event","WxProgress","_hoisted_3","WxSegmented","WxEmpty","_hoisted_4","_hoisted_5","value","_openBlock","_hoisted_6","_hoisted_7","_renderList","severity","WxStatistic","_hoisted_8","WxDate","_hoisted_9","group","_hoisted_10","WxBadge","_hoisted_11","WxPopover","_hoisted_12","source","_hoisted_13","WxSkeleton"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { defineComponent as fe, ref as p, watch as G, computed as b, onMounted as be, openBlock as u, createBlock as m, withCtx as i, unref as l, createTextVNode as f, toDisplayString as g, createSlots as xe, createElementVNode as he, createVNode as v, createElementBlock as w, Fragment as T, renderList as J, createCommentVNode as F, normalizeClass as _e } from "vue";
|
|
2
2
|
import { useAdmin as ye, useTranslate as q, useErrorText as we, useDates as Ce } from "@webx-ui/module-admin";
|
|
3
3
|
import { toast as H, WxText as N, WxTable as Se, WxSelect as h, WxInput as ke, WxButton as O, WxPopover as Ve, WxCheckboxGroup as Oe, WxBadge as Ue } from "@webx-ui/core";
|
|
4
|
-
import { _ as Ae } from "./AuditLayout.vue_vue_type_script_setup_true_lang-
|
|
5
|
-
import { c as ze, u as Ee, P as r, D as $e, C as K, W as I, S as Pe, b as We, g as Te, O as Q, _ as Fe } from "./index-
|
|
4
|
+
import { _ as Ae } from "./AuditLayout.vue_vue_type_script_setup_true_lang-EVgQHRlA.js";
|
|
5
|
+
import { c as ze, u as Ee, P as r, D as $e, C as K, W as I, S as Pe, b as We, g as Te, O as Q, _ as Fe } from "./index-DSuojSPF.js";
|
|
6
6
|
const Ne = { class: "wx-audit-pages__filters" }, X = "webx-audit.pages.columns", Ie = /* @__PURE__ */ fe({
|
|
7
7
|
__name: "AuditPagesPage",
|
|
8
8
|
props: {
|
|
@@ -352,4 +352,4 @@ const Ne = { class: "wx-audit-pages__filters" }, X = "webx-audit.pages.columns",
|
|
|
352
352
|
export {
|
|
353
353
|
je as default
|
|
354
354
|
};
|
|
355
|
-
//# sourceMappingURL=AuditPagesPage-
|
|
355
|
+
//# sourceMappingURL=AuditPagesPage-Dolrp-sC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditPagesPage-CsizUOgz.js","sources":["../src/AuditPagesPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { useAdmin, useDates, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n WxBadge,\n WxButton,\n WxCheckboxGroup,\n WxInput,\n WxPopover,\n WxSelect,\n WxTable,\n WxText,\n type SelectValue,\n type TableColumn,\n type TableState,\n} from '@webx-ui/core'\nimport AuditLayout from './AuditLayout.vue'\nimport AuditPageCard from './AuditPageCard.vue'\nimport { createAuditApi } from './api'\nimport {\n COMPUTED_FIELDS,\n DEFAULT_COLUMNS,\n OPERATIONS,\n PAGE_FIELDS,\n SOURCES,\n WITH_VALUE,\n} from './fields'\nimport AuditStatus from './AuditStatus.vue'\nimport { useAuditMessages } from './i18n'\nimport type {\n AuditFieldFilter,\n AuditFilterOp,\n AuditPage,\n AuditPageField,\n AuditPageQuery,\n AuditPageRow,\n AuditRun,\n} from './types'\n\n/**\n * Every address the last full run crawled (§8, «Pages»): any field of the snapshot as a column,\n * a filter on any of them, the list as CSV, and a row that opens the page's card.\n */\nconst props = defineProps<{ base: string }>()\n\nconst api = createAuditApi(useAdmin())\nuseAuditMessages()\n\nconst t = useTranslate('webx-audit')\nconst panel = useTranslate('webx-admin')\nconst message = useErrorText()\nconst dates = useDates()\n\nconst STORAGE = 'webx-audit.pages.columns'\n\nconst run = ref<AuditRun | null>(null)\nconst ready = ref(false)\nconst page = ref<AuditPage<AuditPageRow> | null>(null)\nconst loading = ref(false)\nconst opened = ref<number | null>(null)\nconst titles = ref<Record<string, string>>({})\n\nconst status = ref<string | null>(null)\nconst indexable = ref<string | null>(null)\nconst check = ref<string | null>(null)\nconst filters = ref<AuditFieldFilter[]>([])\nlet last: TableState = { page: 1, perPage: 50, sort: null, search: '' }\n\nconst visible = ref<AuditPageField[]>(restore())\n\nfunction restore(): AuditPageField[] {\n try {\n const saved: unknown = JSON.parse(window.localStorage.getItem(STORAGE) ?? 'null')\n\n if (Array.isArray(saved)) {\n const known = saved.filter((key): key is AuditPageField => key in PAGE_FIELDS)\n\n if (known.length) return known\n }\n } catch {\n // A private window or a broken value: the default columns, as for anyone else.\n }\n\n return [...DEFAULT_COLUMNS]\n}\n\nwatch(visible, (keys) => {\n try {\n window.localStorage.setItem(STORAGE, JSON.stringify(keys))\n } catch {\n // Not remembered — still shown.\n }\n})\n\nconst fields = Object.keys(PAGE_FIELDS) as AuditPageField[]\n\nconst columnOptions = computed(() =>\n fields.map((key) => ({ value: key, label: t(`page.field-${key}`) })),\n)\n\nconst filterFields = computed(() =>\n fields\n .filter((key) => !COMPUTED_FIELDS.includes(key))\n .map((key) => ({ value: key, label: t(`page.field-${key}`) })),\n)\n\nconst columns = computed<TableColumn<AuditPageRow>[]>(() =>\n /* The picker keeps the order things were ticked in; the table keeps the card's order. */\n fields\n .filter((key) => visible.value.includes(key))\n .map((key) => ({\n key,\n label: t(`page.field-${key}`),\n sortable: !COMPUTED_FIELDS.includes(key),\n minWidth: PAGE_FIELDS[key] === 'url' || PAGE_FIELDS[key] === 'text' ? 220 : undefined,\n align: PAGE_FIELDS[key] === 'number' ? 'right' : undefined,\n })),\n)\n\nconst statusOptions = computed(() => [\n ...['2xx', '3xx', '4xx', '5xx'].map((value) => ({ value, label: value })),\n { value: 'none', label: t('page.status-none') },\n])\n\nconst indexableOptions = computed(() => [\n { value: '1', label: t('page.indexable-yes') },\n { value: '0', label: t('page.indexable-no') },\n])\n\nconst checkOptions = computed(() =>\n Object.entries(titles.value).map(([value, label]) => ({ value, label })),\n)\n\nconst filtersCount = computed(\n () =>\n [status.value, indexable.value, check.value].filter(Boolean).length +\n filters.value.filter(complete).length,\n)\n\nconst query = computed<AuditPageQuery>(() => ({\n status: status.value,\n indexable: indexable.value === null ? null : indexable.value === '1',\n check: check.value,\n filters: filters.value.filter(complete),\n}))\n\nfunction complete(filter: AuditFieldFilter): boolean {\n return !WITH_VALUE.includes(filter.op) || (filter.value ?? '').trim() !== ''\n}\n\nfunction pick(value: SelectValue | SelectValue[] | null | undefined): string | null {\n return typeof value === 'string' && value !== '' ? value : null\n}\n\nfunction operations(field: AuditPageField) {\n return OPERATIONS[PAGE_FIELDS[field]].map((op) => ({ value: op, label: t(`page.op-${op}`) }))\n}\n\nfunction addFilter(): void {\n filters.value = [...filters.value, { field: 'title', op: 'empty' }]\n}\n\nfunction setField(index: number, value: SelectValue | SelectValue[] | null | undefined): void {\n const field = pick(value) as AuditPageField | null\n\n if (!field) return\n\n filters.value = filters.value.map((filter, at) =>\n at === index ? { field, op: OPERATIONS[PAGE_FIELDS[field]][0]!, value: '' } : filter,\n )\n}\n\nfunction setOp(index: number, value: SelectValue | SelectValue[] | null | undefined): void {\n const op = pick(value) as AuditFilterOp | null\n\n if (op)\n filters.value = filters.value.map((filter, at) => (at === index ? { ...filter, op } : filter))\n}\n\nfunction setValue(index: number, value: string): void {\n filters.value = filters.value.map((filter, at) => (at === index ? { ...filter, value } : filter))\n}\n\nfunction removeFilter(index: number): void {\n filters.value = filters.value.filter((_, at) => at !== index)\n}\n\nfunction setColumns(keys: unknown[]): void {\n const next = keys.filter((key): key is AuditPageField => String(key) in PAGE_FIELDS)\n\n /* A table without columns is a blank card; the address stays at least. */\n visible.value = next.length ? next : ['url']\n}\n\nfunction text(value: unknown): string {\n return value === null || value === undefined || value === '' ? '—' : String(value)\n}\n\nasync function load(state: TableState = last): Promise<void> {\n last = state\n\n if (run.value === null) return\n\n loading.value = true\n\n try {\n page.value = await api.pages(run.value.id, {\n ...query.value,\n search: state.search,\n sort: state.sort ? `${state.sort.order === 'desc' ? '-' : ''}${state.sort.key}` : null,\n page: state.page,\n per_page: state.perPage,\n })\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nfunction download(): void {\n if (run.value === null) return\n\n window.location.assign(\n api.pagesFile(\n run.value.id,\n { ...query.value, search: last.search },\n columns.value.map((column) => column.key),\n ),\n )\n}\n\nwatch(query, () => void load({ ...last, page: 1 }), { deep: true })\n\nonMounted(async () => {\n try {\n run.value = (await api.latest()).crawled\n\n if (run.value !== null) {\n const checks = await api.checks(run.value.id)\n titles.value = Object.fromEntries(checks.map((row) => [row.id, row.title]))\n }\n } catch (error) {\n toast.danger(message(error))\n } finally {\n ready.value = true\n }\n\n void load()\n})\n</script>\n\n<template>\n <audit-layout :base=\"props.base\" current=\"pages\">\n <wx-text v-if=\"ready && run === null\" tone=\"muted\" class=\"wx-audit-pages__none\">{{\n t('page.pages-none')\n }}</wx-text>\n\n <wx-table\n v-else\n :data=\"page\"\n :columns=\"columns\"\n row-key=\"id\"\n searchable\n clickable\n hover\n flush\n :loading=\"loading || !ready\"\n :per-page-options=\"[50, 100, 200]\"\n :search-placeholder=\"t('page.search-url')\"\n :filters-count=\"filtersCount\"\n :filters-label=\"panel('filters.title')\"\n :filters-width=\"420\"\n :empty-text=\"t('page.empty')\"\n @state-change=\"load\"\n @row-click=\"(row) => (opened = row.id)\"\n >\n <template #title>\n <wx-text v-if=\"run\" size=\"sm\" tone=\"muted\">{{\n t('page.pages-run', { date: dates.short(run.finished_at) })\n }}</wx-text>\n </template>\n\n <template #actions>\n <wx-popover :title=\"t('page.columns')\" width=\"300\">\n <template #trigger>\n <wx-button size=\"sm\" variant=\"text\" icon=\"sliders\">{{ t('page.columns') }}</wx-button>\n </template>\n <wx-checkbox-group\n :model-value=\"visible\"\n :options=\"columnOptions\"\n size=\"sm\"\n class=\"wx-audit-pages__picker\"\n @update:model-value=\"setColumns\"\n />\n </wx-popover>\n <wx-button size=\"sm\" variant=\"text\" icon=\"download\" :disabled=\"!run\" @click=\"download\">{{\n t('page.export')\n }}</wx-button>\n </template>\n\n <template #filters>\n <div class=\"wx-audit-pages__filters\">\n <wx-select\n :model-value=\"status\"\n :options=\"statusOptions\"\n :placeholder=\"t('page.any-status')\"\n clearable\n @update:model-value=\"status = pick($event)\"\n />\n <wx-select\n :model-value=\"indexable\"\n :options=\"indexableOptions\"\n :placeholder=\"t('page.any-indexable')\"\n clearable\n @update:model-value=\"indexable = pick($event)\"\n />\n <wx-select\n :model-value=\"check\"\n :options=\"checkOptions\"\n :placeholder=\"t('page.any-check')\"\n clearable\n filterable\n @update:model-value=\"check = pick($event)\"\n />\n\n <div v-for=\"(filter, index) in filters\" :key=\"index\" class=\"wx-audit-pages__filter\">\n <wx-select\n :model-value=\"filter.field\"\n :options=\"filterFields\"\n filterable\n size=\"sm\"\n @update:model-value=\"setField(index, $event)\"\n />\n <wx-select\n :model-value=\"filter.op\"\n :options=\"operations(filter.field)\"\n size=\"sm\"\n @update:model-value=\"setOp(index, $event)\"\n />\n <wx-select\n v-if=\"WITH_VALUE.includes(filter.op) && PAGE_FIELDS[filter.field] === 'source'\"\n :model-value=\"filter.value ?? null\"\n :options=\"SOURCES.map((value) => ({ value, label: t(`page.source-${value}`) }))\"\n size=\"sm\"\n @update:model-value=\"setValue(index, pick($event) ?? '')\"\n />\n <wx-input\n v-else-if=\"WITH_VALUE.includes(filter.op)\"\n :model-value=\"filter.value ?? ''\"\n :placeholder=\"t('page.value')\"\n size=\"sm\"\n @update:model-value=\"setValue(index, String($event ?? ''))\"\n />\n <wx-button\n size=\"sm\"\n variant=\"text\"\n icon=\"close\"\n :aria-label=\"t('page.remove-filter')\"\n @click=\"removeFilter(index)\"\n />\n </div>\n\n <wx-button size=\"sm\" variant=\"text\" icon=\"plus\" @click=\"addFilter\">{{\n t('page.add-filter')\n }}</wx-button>\n </div>\n </template>\n\n <template v-for=\"key in visible\" :key=\"key\" #[`cell-${key}`]=\"{ row }\">\n <audit-status\n v-if=\"PAGE_FIELDS[key] === 'status' && row[key] !== null\"\n :code=\"Number(row[key])\"\n />\n <wx-text v-else-if=\"PAGE_FIELDS[key] === 'status'\" size=\"sm\" tone=\"danger\">{{\n t('page.status-none')\n }}</wx-text>\n <template v-else-if=\"PAGE_FIELDS[key] === 'bool'\">{{\n row[key] ? t('page.yes') : t('page.no')\n }}</template>\n <template v-else-if=\"PAGE_FIELDS[key] === 'source'\">{{\n t(`page.source-${row[key]}`)\n }}</template>\n <wx-badge v-else-if=\"key === 'issues' && row.issues > 0\" type=\"warning\" size=\"sm\">{{\n row.issues\n }}</wx-badge>\n <span v-else :class=\"{ 'wx-audit-pages__long': PAGE_FIELDS[key] === 'url' }\">{{\n text(row[key])\n }}</span>\n </template>\n </wx-table>\n\n <audit-page-card\n v-if=\"run\"\n :run=\"run.id\"\n :base=\"props.base\"\n :page-id=\"opened\"\n :titles=\"titles\"\n @close=\"opened = null\"\n />\n </audit-layout>\n</template>\n\n<style scoped>\n.wx-audit-pages__none {\n display: block;\n padding: var(--wx-space-24);\n}\n\n.wx-audit-pages__filters {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-audit-pages__filter {\n display: grid;\n grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) auto;\n gap: var(--wx-space-4);\n align-items: center;\n}\n\n.wx-audit-pages__picker {\n max-height: 360px;\n overflow-y: auto;\n}\n\n.wx-audit-pages__long {\n overflow-wrap: anywhere;\n}\n</style>\n"],"names":["STORAGE","props","__props","api","createAuditApi","useAdmin","useAuditMessages","t","useTranslate","panel","message","useErrorText","dates","useDates","run","ref","ready","page","loading","opened","titles","status","indexable","check","filters","last","visible","restore","saved","known","key","PAGE_FIELDS","DEFAULT_COLUMNS","watch","keys","fields","columnOptions","computed","filterFields","COMPUTED_FIELDS","columns","statusOptions","value","indexableOptions","checkOptions","label","filtersCount","complete","query","filter","WITH_VALUE","pick","operations","field","OPERATIONS","op","addFilter","setField","index","at","setOp","setValue","removeFilter","_","setColumns","next","text","load","state","error","toast","download","column","onMounted","checks","row","_createBlock","AuditLayout","_unref","WxText","WxTable","_createTextVNode","_toDisplayString","_createVNode","WxPopover","WxButton","WxCheckboxGroup","_createElementVNode","_hoisted_1","WxSelect","_cache","$event","_openBlock","_createElementBlock","_Fragment","_renderList","SOURCES","WxInput","_withCtx","AuditStatus","WxBadge","_normalizeClass","AuditPageCard"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuditPagesPage-Dolrp-sC.js","sources":["../src/AuditPagesPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, ref, watch } from 'vue'\nimport { useAdmin, useDates, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n WxBadge,\n WxButton,\n WxCheckboxGroup,\n WxInput,\n WxPopover,\n WxSelect,\n WxTable,\n WxText,\n type SelectValue,\n type TableColumn,\n type TableState,\n} from '@webx-ui/core'\nimport AuditLayout from './AuditLayout.vue'\nimport AuditPageCard from './AuditPageCard.vue'\nimport { createAuditApi } from './api'\nimport {\n COMPUTED_FIELDS,\n DEFAULT_COLUMNS,\n OPERATIONS,\n PAGE_FIELDS,\n SOURCES,\n WITH_VALUE,\n} from './fields'\nimport AuditStatus from './AuditStatus.vue'\nimport { useAuditMessages } from './i18n'\nimport type {\n AuditFieldFilter,\n AuditFilterOp,\n AuditPage,\n AuditPageField,\n AuditPageQuery,\n AuditPageRow,\n AuditRun,\n} from './types'\n\n/**\n * Every address the last full run crawled (§8, «Pages»): any field of the snapshot as a column,\n * a filter on any of them, the list as CSV, and a row that opens the page's card.\n */\nconst props = defineProps<{ base: string }>()\n\nconst api = createAuditApi(useAdmin())\nuseAuditMessages()\n\nconst t = useTranslate('webx-audit')\nconst panel = useTranslate('webx-admin')\nconst message = useErrorText()\nconst dates = useDates()\n\nconst STORAGE = 'webx-audit.pages.columns'\n\nconst run = ref<AuditRun | null>(null)\nconst ready = ref(false)\nconst page = ref<AuditPage<AuditPageRow> | null>(null)\nconst loading = ref(false)\nconst opened = ref<number | null>(null)\nconst titles = ref<Record<string, string>>({})\n\nconst status = ref<string | null>(null)\nconst indexable = ref<string | null>(null)\nconst check = ref<string | null>(null)\nconst filters = ref<AuditFieldFilter[]>([])\nlet last: TableState = { page: 1, perPage: 50, sort: null, search: '' }\n\nconst visible = ref<AuditPageField[]>(restore())\n\nfunction restore(): AuditPageField[] {\n try {\n const saved: unknown = JSON.parse(window.localStorage.getItem(STORAGE) ?? 'null')\n\n if (Array.isArray(saved)) {\n const known = saved.filter((key): key is AuditPageField => key in PAGE_FIELDS)\n\n if (known.length) return known\n }\n } catch {\n // A private window or a broken value: the default columns, as for anyone else.\n }\n\n return [...DEFAULT_COLUMNS]\n}\n\nwatch(visible, (keys) => {\n try {\n window.localStorage.setItem(STORAGE, JSON.stringify(keys))\n } catch {\n // Not remembered — still shown.\n }\n})\n\nconst fields = Object.keys(PAGE_FIELDS) as AuditPageField[]\n\nconst columnOptions = computed(() =>\n fields.map((key) => ({ value: key, label: t(`page.field-${key}`) })),\n)\n\nconst filterFields = computed(() =>\n fields\n .filter((key) => !COMPUTED_FIELDS.includes(key))\n .map((key) => ({ value: key, label: t(`page.field-${key}`) })),\n)\n\nconst columns = computed<TableColumn<AuditPageRow>[]>(() =>\n /* The picker keeps the order things were ticked in; the table keeps the card's order. */\n fields\n .filter((key) => visible.value.includes(key))\n .map((key) => ({\n key,\n label: t(`page.field-${key}`),\n sortable: !COMPUTED_FIELDS.includes(key),\n minWidth: PAGE_FIELDS[key] === 'url' || PAGE_FIELDS[key] === 'text' ? 220 : undefined,\n align: PAGE_FIELDS[key] === 'number' ? 'right' : undefined,\n })),\n)\n\nconst statusOptions = computed(() => [\n ...['2xx', '3xx', '4xx', '5xx'].map((value) => ({ value, label: value })),\n { value: 'none', label: t('page.status-none') },\n])\n\nconst indexableOptions = computed(() => [\n { value: '1', label: t('page.indexable-yes') },\n { value: '0', label: t('page.indexable-no') },\n])\n\nconst checkOptions = computed(() =>\n Object.entries(titles.value).map(([value, label]) => ({ value, label })),\n)\n\nconst filtersCount = computed(\n () =>\n [status.value, indexable.value, check.value].filter(Boolean).length +\n filters.value.filter(complete).length,\n)\n\nconst query = computed<AuditPageQuery>(() => ({\n status: status.value,\n indexable: indexable.value === null ? null : indexable.value === '1',\n check: check.value,\n filters: filters.value.filter(complete),\n}))\n\nfunction complete(filter: AuditFieldFilter): boolean {\n return !WITH_VALUE.includes(filter.op) || (filter.value ?? '').trim() !== ''\n}\n\nfunction pick(value: SelectValue | SelectValue[] | null | undefined): string | null {\n return typeof value === 'string' && value !== '' ? value : null\n}\n\nfunction operations(field: AuditPageField) {\n return OPERATIONS[PAGE_FIELDS[field]].map((op) => ({ value: op, label: t(`page.op-${op}`) }))\n}\n\nfunction addFilter(): void {\n filters.value = [...filters.value, { field: 'title', op: 'empty' }]\n}\n\nfunction setField(index: number, value: SelectValue | SelectValue[] | null | undefined): void {\n const field = pick(value) as AuditPageField | null\n\n if (!field) return\n\n filters.value = filters.value.map((filter, at) =>\n at === index ? { field, op: OPERATIONS[PAGE_FIELDS[field]][0]!, value: '' } : filter,\n )\n}\n\nfunction setOp(index: number, value: SelectValue | SelectValue[] | null | undefined): void {\n const op = pick(value) as AuditFilterOp | null\n\n if (op)\n filters.value = filters.value.map((filter, at) => (at === index ? { ...filter, op } : filter))\n}\n\nfunction setValue(index: number, value: string): void {\n filters.value = filters.value.map((filter, at) => (at === index ? { ...filter, value } : filter))\n}\n\nfunction removeFilter(index: number): void {\n filters.value = filters.value.filter((_, at) => at !== index)\n}\n\nfunction setColumns(keys: unknown[]): void {\n const next = keys.filter((key): key is AuditPageField => String(key) in PAGE_FIELDS)\n\n /* A table without columns is a blank card; the address stays at least. */\n visible.value = next.length ? next : ['url']\n}\n\nfunction text(value: unknown): string {\n return value === null || value === undefined || value === '' ? '—' : String(value)\n}\n\nasync function load(state: TableState = last): Promise<void> {\n last = state\n\n if (run.value === null) return\n\n loading.value = true\n\n try {\n page.value = await api.pages(run.value.id, {\n ...query.value,\n search: state.search,\n sort: state.sort ? `${state.sort.order === 'desc' ? '-' : ''}${state.sort.key}` : null,\n page: state.page,\n per_page: state.perPage,\n })\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nfunction download(): void {\n if (run.value === null) return\n\n window.location.assign(\n api.pagesFile(\n run.value.id,\n { ...query.value, search: last.search },\n columns.value.map((column) => column.key),\n ),\n )\n}\n\nwatch(query, () => void load({ ...last, page: 1 }), { deep: true })\n\nonMounted(async () => {\n try {\n run.value = (await api.latest()).crawled\n\n if (run.value !== null) {\n const checks = await api.checks(run.value.id)\n titles.value = Object.fromEntries(checks.map((row) => [row.id, row.title]))\n }\n } catch (error) {\n toast.danger(message(error))\n } finally {\n ready.value = true\n }\n\n void load()\n})\n</script>\n\n<template>\n <audit-layout :base=\"props.base\" current=\"pages\">\n <wx-text v-if=\"ready && run === null\" tone=\"muted\" class=\"wx-audit-pages__none\">{{\n t('page.pages-none')\n }}</wx-text>\n\n <wx-table\n v-else\n :data=\"page\"\n :columns=\"columns\"\n row-key=\"id\"\n searchable\n clickable\n hover\n flush\n :loading=\"loading || !ready\"\n :per-page-options=\"[50, 100, 200]\"\n :search-placeholder=\"t('page.search-url')\"\n :filters-count=\"filtersCount\"\n :filters-label=\"panel('filters.title')\"\n :filters-width=\"420\"\n :empty-text=\"t('page.empty')\"\n @state-change=\"load\"\n @row-click=\"(row) => (opened = row.id)\"\n >\n <template #title>\n <wx-text v-if=\"run\" size=\"sm\" tone=\"muted\">{{\n t('page.pages-run', { date: dates.short(run.finished_at) })\n }}</wx-text>\n </template>\n\n <template #actions>\n <wx-popover :title=\"t('page.columns')\" width=\"300\">\n <template #trigger>\n <wx-button size=\"sm\" variant=\"text\" icon=\"sliders\">{{ t('page.columns') }}</wx-button>\n </template>\n <wx-checkbox-group\n :model-value=\"visible\"\n :options=\"columnOptions\"\n size=\"sm\"\n class=\"wx-audit-pages__picker\"\n @update:model-value=\"setColumns\"\n />\n </wx-popover>\n <wx-button size=\"sm\" variant=\"text\" icon=\"download\" :disabled=\"!run\" @click=\"download\">{{\n t('page.export')\n }}</wx-button>\n </template>\n\n <template #filters>\n <div class=\"wx-audit-pages__filters\">\n <wx-select\n :model-value=\"status\"\n :options=\"statusOptions\"\n :placeholder=\"t('page.any-status')\"\n clearable\n @update:model-value=\"status = pick($event)\"\n />\n <wx-select\n :model-value=\"indexable\"\n :options=\"indexableOptions\"\n :placeholder=\"t('page.any-indexable')\"\n clearable\n @update:model-value=\"indexable = pick($event)\"\n />\n <wx-select\n :model-value=\"check\"\n :options=\"checkOptions\"\n :placeholder=\"t('page.any-check')\"\n clearable\n filterable\n @update:model-value=\"check = pick($event)\"\n />\n\n <div v-for=\"(filter, index) in filters\" :key=\"index\" class=\"wx-audit-pages__filter\">\n <wx-select\n :model-value=\"filter.field\"\n :options=\"filterFields\"\n filterable\n size=\"sm\"\n @update:model-value=\"setField(index, $event)\"\n />\n <wx-select\n :model-value=\"filter.op\"\n :options=\"operations(filter.field)\"\n size=\"sm\"\n @update:model-value=\"setOp(index, $event)\"\n />\n <wx-select\n v-if=\"WITH_VALUE.includes(filter.op) && PAGE_FIELDS[filter.field] === 'source'\"\n :model-value=\"filter.value ?? null\"\n :options=\"SOURCES.map((value) => ({ value, label: t(`page.source-${value}`) }))\"\n size=\"sm\"\n @update:model-value=\"setValue(index, pick($event) ?? '')\"\n />\n <wx-input\n v-else-if=\"WITH_VALUE.includes(filter.op)\"\n :model-value=\"filter.value ?? ''\"\n :placeholder=\"t('page.value')\"\n size=\"sm\"\n @update:model-value=\"setValue(index, String($event ?? ''))\"\n />\n <wx-button\n size=\"sm\"\n variant=\"text\"\n icon=\"close\"\n :aria-label=\"t('page.remove-filter')\"\n @click=\"removeFilter(index)\"\n />\n </div>\n\n <wx-button size=\"sm\" variant=\"text\" icon=\"plus\" @click=\"addFilter\">{{\n t('page.add-filter')\n }}</wx-button>\n </div>\n </template>\n\n <template v-for=\"key in visible\" :key=\"key\" #[`cell-${key}`]=\"{ row }\">\n <audit-status\n v-if=\"PAGE_FIELDS[key] === 'status' && row[key] !== null\"\n :code=\"Number(row[key])\"\n />\n <wx-text v-else-if=\"PAGE_FIELDS[key] === 'status'\" size=\"sm\" tone=\"danger\">{{\n t('page.status-none')\n }}</wx-text>\n <template v-else-if=\"PAGE_FIELDS[key] === 'bool'\">{{\n row[key] ? t('page.yes') : t('page.no')\n }}</template>\n <template v-else-if=\"PAGE_FIELDS[key] === 'source'\">{{\n t(`page.source-${row[key]}`)\n }}</template>\n <wx-badge v-else-if=\"key === 'issues' && row.issues > 0\" type=\"warning\" size=\"sm\">{{\n row.issues\n }}</wx-badge>\n <span v-else :class=\"{ 'wx-audit-pages__long': PAGE_FIELDS[key] === 'url' }\">{{\n text(row[key])\n }}</span>\n </template>\n </wx-table>\n\n <audit-page-card\n v-if=\"run\"\n :run=\"run.id\"\n :base=\"props.base\"\n :page-id=\"opened\"\n :titles=\"titles\"\n @close=\"opened = null\"\n />\n </audit-layout>\n</template>\n\n<style scoped>\n.wx-audit-pages__none {\n display: block;\n padding: var(--wx-space-24);\n}\n\n.wx-audit-pages__filters {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-audit-pages__filter {\n display: grid;\n grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) auto;\n gap: var(--wx-space-4);\n align-items: center;\n}\n\n.wx-audit-pages__picker {\n max-height: 360px;\n overflow-y: auto;\n}\n\n.wx-audit-pages__long {\n overflow-wrap: anywhere;\n}\n</style>\n"],"names":["STORAGE","props","__props","api","createAuditApi","useAdmin","useAuditMessages","t","useTranslate","panel","message","useErrorText","dates","useDates","run","ref","ready","page","loading","opened","titles","status","indexable","check","filters","last","visible","restore","saved","known","key","PAGE_FIELDS","DEFAULT_COLUMNS","watch","keys","fields","columnOptions","computed","filterFields","COMPUTED_FIELDS","columns","statusOptions","value","indexableOptions","checkOptions","label","filtersCount","complete","query","filter","WITH_VALUE","pick","operations","field","OPERATIONS","op","addFilter","setField","index","at","setOp","setValue","removeFilter","_","setColumns","next","text","load","state","error","toast","download","column","onMounted","checks","row","_createBlock","AuditLayout","_unref","WxText","WxTable","_createTextVNode","_toDisplayString","_createVNode","WxPopover","WxButton","WxCheckboxGroup","_createElementVNode","_hoisted_1","WxSelect","_cache","$event","_openBlock","_createElementBlock","_Fragment","_renderList","SOURCES","WxInput","_withCtx","AuditStatus","WxBadge","_normalizeClass","AuditPageCard"],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@ import { defineComponent as L, ref as m, computed as $, watch as F, openBlock as
|
|
|
2
2
|
import { useRoute as oe } from "vue-router";
|
|
3
3
|
import { useAdmin as j, useTranslate as G, useErrorText as H, WxDate as S } from "@webx-ui/module-admin";
|
|
4
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-
|
|
6
|
-
import { _ as ge } from "./AuditLayout.vue_vue_type_script_setup_true_lang-
|
|
5
|
+
import { c as J, u as O, e as me, _ as Q } from "./index-DSuojSPF.js";
|
|
6
|
+
import { _ as ge } from "./AuditLayout.vue_vue_type_script_setup_true_lang-EVgQHRlA.js";
|
|
7
7
|
const fe = { class: "wx-audit-compare" }, ve = /* @__PURE__ */ L({
|
|
8
8
|
__name: "AuditCompareIssues",
|
|
9
9
|
props: {
|
|
@@ -372,4 +372,4 @@ const fe = { class: "wx-audit-compare" }, ve = /* @__PURE__ */ L({
|
|
|
372
372
|
export {
|
|
373
373
|
Ce as default
|
|
374
374
|
};
|
|
375
|
-
//# sourceMappingURL=AuditRunsPage-
|
|
375
|
+
//# sourceMappingURL=AuditRunsPage-D4SVqAAb.js.map
|
|
@@ -1 +1 @@
|
|
|
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":";;;;;;;;;;;;;;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;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"AuditRunsPage-D4SVqAAb.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-
|
|
6
|
-
import { c as U, u as j, _ as q } from "./index-
|
|
5
|
+
import { _ as R } from "./AuditLayout.vue_vue_type_script_setup_true_lang-EVgQHRlA.js";
|
|
6
|
+
import { c as U, u as j, _ as q } from "./index-DSuojSPF.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-
|
|
88
|
+
//# sourceMappingURL=AuditSettingsPage-CAHxMpDT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditSettingsPage-
|
|
1
|
+
{"version":3,"file":"AuditSettingsPage-CAHxMpDT.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;;;;;;;;;;;;"}
|
|
@@ -8,35 +8,46 @@ function la(i = {}) {
|
|
|
8
8
|
id: "audit",
|
|
9
9
|
path: n,
|
|
10
10
|
routes: [
|
|
11
|
-
{
|
|
11
|
+
{
|
|
12
|
+
path: n,
|
|
13
|
+
name: "webx.audit",
|
|
14
|
+
meta: { help: "audit.index" },
|
|
15
|
+
component: () => import("./AuditOverviewPage-DeLwz3V9.js"),
|
|
16
|
+
props: o
|
|
17
|
+
},
|
|
12
18
|
{
|
|
13
19
|
path: `${n}/issues`,
|
|
14
20
|
name: "webx.audit.issues",
|
|
15
|
-
|
|
21
|
+
meta: { help: "audit.issues" },
|
|
22
|
+
component: () => import("./AuditIssuesPage-CGyEXQoj.js"),
|
|
16
23
|
props: o
|
|
17
24
|
},
|
|
18
25
|
{
|
|
19
26
|
path: `${n}/pages`,
|
|
20
27
|
name: "webx.audit.pages",
|
|
21
|
-
|
|
28
|
+
meta: { help: "audit.pages" },
|
|
29
|
+
component: () => import("./AuditPagesPage-Dolrp-sC.js"),
|
|
22
30
|
props: o
|
|
23
31
|
},
|
|
24
32
|
{
|
|
25
33
|
path: `${n}/hosts`,
|
|
26
34
|
name: "webx.audit.hosts",
|
|
27
|
-
|
|
35
|
+
meta: { help: "audit.hosts" },
|
|
36
|
+
component: () => import("./AuditHostsPage-MLODrjlQ.js"),
|
|
28
37
|
props: o
|
|
29
38
|
},
|
|
30
39
|
{
|
|
31
40
|
path: `${n}/runs`,
|
|
32
41
|
name: "webx.audit.runs",
|
|
33
|
-
|
|
42
|
+
meta: { help: "audit.runs" },
|
|
43
|
+
component: () => import("./AuditRunsPage-D4SVqAAb.js"),
|
|
34
44
|
props: o
|
|
35
45
|
},
|
|
36
46
|
{
|
|
37
47
|
path: `${n}/settings`,
|
|
38
48
|
name: "webx.audit.settings",
|
|
39
|
-
|
|
49
|
+
meta: { help: "audit.settings" },
|
|
50
|
+
component: () => import("./AuditSettingsPage-CAHxMpDT.js"),
|
|
40
51
|
props: o
|
|
41
52
|
}
|
|
42
53
|
]
|
|
@@ -1865,7 +1876,7 @@ const xt = { class: "wx-audit-card__title" }, $t = { class: "wx-audit-card__url"
|
|
|
1865
1876
|
status: ["eq", "gt", "lt", "empty"],
|
|
1866
1877
|
bool: ["yes", "no"],
|
|
1867
1878
|
source: ["eq"]
|
|
1868
|
-
}, fa = ["contains", "eq", "gt", "lt"], _a = ["home", "sitemap", "registry", "link"], ma = D(() => import("./AuditOverviewPage-
|
|
1879
|
+
}, fa = ["contains", "eq", "gt", "lt"], _a = ["home", "sitemap", "registry", "link"], ma = D(() => import("./AuditOverviewPage-DeLwz3V9.js")), va = D(() => import("./AuditIssuesPage-CGyEXQoj.js")), ya = D(() => import("./AuditPagesPage-Dolrp-sC.js")), ka = D(() => import("./AuditHostsPage-MLODrjlQ.js")), ba = D(() => import("./AuditRunsPage-D4SVqAAb.js")), wa = D(() => import("./AuditSettingsPage-CAHxMpDT.js"));
|
|
1869
1880
|
export {
|
|
1870
1881
|
fe as A,
|
|
1871
1882
|
pa as C,
|
|
@@ -1893,4 +1904,4 @@ export {
|
|
|
1893
1904
|
ge as p,
|
|
1894
1905
|
G as u
|
|
1895
1906
|
};
|
|
1896
|
-
//# sourceMappingURL=index-
|
|
1907
|
+
//# sourceMappingURL=index-DSuojSPF.js.map
|