checkpoint ISAC registries and system monitoring
This commit is contained in:
@@ -4,7 +4,7 @@ import { getSessionUser } from '$lib/server/auth/session';
|
||||
import { requirePermission } from '$lib/server/auth/authorization';
|
||||
import { getDatabase } from '$lib/server/database';
|
||||
import { deserializeProposal, refreshProposalDependencies } from '$lib/server/data-moderation';
|
||||
import { getPagination } from '$lib/server/pagination';
|
||||
import { getPagination, getRegistrySort } from '$lib/server/pagination';
|
||||
import { recordIsacAudit } from '$lib/server/audit';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
import { createNotification } from '$lib/server/notifications';
|
||||
@@ -121,6 +121,18 @@ export const load: PageServerLoad = async ({ cookies, url }) => {
|
||||
const status = statuses.includes(url.searchParams.get('status') ?? '') ? String(url.searchParams.get('status')) : 'pending';
|
||||
const module = modules.includes(url.searchParams.get('module') ?? '') ? String(url.searchParams.get('module')) : '';
|
||||
const search = (url.searchParams.get('search') ?? '').trim().slice(0, 100);
|
||||
const sort = getRegistrySort(url, {
|
||||
change: {
|
||||
asc: 'p.summary COLLATE NOCASE ASC,p.module COLLATE NOCASE ASC,p.action COLLATE NOCASE ASC',
|
||||
desc: 'p.summary COLLATE NOCASE DESC,p.module COLLATE NOCASE DESC,p.action COLLATE NOCASE DESC'
|
||||
},
|
||||
contributor: {
|
||||
asc: 'COALESCE(profile.display_name,proposer.username) COLLATE NOCASE ASC',
|
||||
desc: 'COALESCE(profile.display_name,proposer.username) COLLATE NOCASE DESC'
|
||||
},
|
||||
submitted: { asc: 'p.created_at ASC', desc: 'p.created_at DESC', defaultDirection: 'desc' },
|
||||
status: { asc: 'p.status COLLATE NOCASE ASC', desc: 'p.status COLLATE NOCASE DESC' }
|
||||
}, 'submitted', 'desc');
|
||||
const conditions = ['p.status=?'];
|
||||
const args: unknown[] = [status];
|
||||
if (module) { conditions.push('p.module=?'); args.push(module); }
|
||||
@@ -135,7 +147,7 @@ export const load: PageServerLoad = async ({ cookies, url }) => {
|
||||
LEFT JOIN user_profiles profile ON profile.user_id=proposer.id
|
||||
LEFT JOIN users reviewer ON reviewer.id=p.reviewed_by
|
||||
LEFT JOIN user_profiles reviewer_profile ON reviewer_profile.user_id=reviewer.id
|
||||
${where} ORDER BY p.created_at DESC LIMIT ? OFFSET ?`)).all(...args, pagination.perPage, pagination.offset);
|
||||
${where} ORDER BY ${sort.orderBy},p.id LIMIT ? OFFSET ?`)).all(...args, pagination.perPage, pagination.offset);
|
||||
const proposalsWithSnapshots = await Promise.all(proposals.map(async (proposal) => ({
|
||||
...proposal,
|
||||
current_snapshot: proposal.module === 'attributes' && proposal.entity_id
|
||||
@@ -149,7 +161,7 @@ export const load: PageServerLoad = async ({ cookies, url }) => {
|
||||
: null
|
||||
})));
|
||||
const summaryRows = await (await database.prepare('SELECT status,COUNT(*) AS count FROM data_change_proposals GROUP BY status')).all();
|
||||
return { proposals: proposalsWithSnapshots, pagination, status, module, search, summary: Object.fromEntries(summaryRows.map((row) => [String(row.status), Number(row.count)])), modules };
|
||||
return { proposals: proposalsWithSnapshots, pagination, status, module, search, sort, summary: Object.fromEntries(summaryRows.map((row) => [String(row.status), Number(row.count)])), modules };
|
||||
};
|
||||
|
||||
export const actions: Actions = {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import KpiFilters from '$lib/components/KpiFilters.svelte';
|
||||
import SearchableAssignment from '$lib/components/SearchableAssignment.svelte';
|
||||
import ProposalChangePreview from '$lib/components/ProposalChangePreview.svelte';
|
||||
import SortableColumnHeader from '$lib/components/SortableColumnHeader.svelte';
|
||||
let { data, form } = $props();
|
||||
let reviewing = $state<any>(null);
|
||||
let decision = $state<'approve' | 'correct' | 'reject'>('approve');
|
||||
@@ -52,7 +53,7 @@
|
||||
</form>
|
||||
<RegistryPagination pagination={data.pagination}/>
|
||||
<div class="dashboard-table moderation-queue">
|
||||
<div class="dashboard-row moderation-row table-heading"><span>CHANGE</span><span>CONTRIBUTOR</span><span>SUBMITTED</span><span>STATUS</span><span></span></div>
|
||||
<div class="dashboard-row moderation-row table-heading"><SortableColumnHeader label="CHANGE" column="change" sort={data.sort}/><SortableColumnHeader label="CONTRIBUTOR" column="contributor" sort={data.sort}/><SortableColumnHeader label="SUBMITTED" column="submitted" sort={data.sort} defaultDirection="desc"/><SortableColumnHeader label="STATUS" column="status" sort={data.sort}/><span></span></div>
|
||||
{#each data.proposals as proposal}
|
||||
<div class="dashboard-row moderation-row mobile-detail-row">
|
||||
<div class="change-identity"><span>{proposal.module === 'skillchips' ? 'CHIP' : proposal.module === 'specializations' ? 'CLASS' : proposal.module.slice(0,4).toUpperCase()}</span><div><strong>{proposal.summary}</strong><small>{moduleLabel(proposal.module)} / {operationLabel(proposal.action)}</small></div></div>
|
||||
|
||||
Reference in New Issue
Block a user