Remove standalone Activity log page (Refs #153)

This commit is contained in:
2026-10-13 15:39:05 -04:00
parent 82e07ea33e
commit eceb38a6bc
21 changed files with 260 additions and 132 deletions
+44
View File
@@ -0,0 +1,44 @@
const historyFilters = ['host', 'type', 'source', 'state', 'days', 'q', 'limit', 'offset'];
/** Route retired activity bookmarks to the existing history that owns their scope. */
export function activityRedirectHref(url: URL): string {
const params = new URLSearchParams();
const copy = (keys: string[]) => {
for (const key of keys) {
const value = url.searchParams.get(key);
if (value) params.set(key, value);
}
};
const server = url.searchParams.get('server')?.trim();
const host = url.searchParams.get('host')?.trim();
const source = url.searchParams.get('source');
let path: string;
let hash = '';
if (server) {
path = `/servers/${encodeURIComponent(server)}`;
params.set('tab', 'history');
copy(historyFilters);
hash = url.hash;
} else if (host || source === 'host') {
path = '/hosts/operations';
if (host) params.set('host', host);
} else if (source === 'maintenance' || source === 'recovery') {
path = '/maintenance';
params.set('view', 'activity');
copy(historyFilters);
hash = url.hash;
} else if (source === 'campaign') {
path = '/campaigns';
copy(['q']);
} else if (source === 'beta') {
path = '/betas';
params.set('view', 'history');
copy(['q']);
} else {
path = '/provisioning';
params.set('view', 'history');
if (source === 'autoscaling') params.set('source', source);
}
copy(['returnTo']);
return path + (params.size ? `?${params}` : '') + hash;
}
+4 -2
View File
@@ -1,3 +1,5 @@
import { activityRedirectHref } from './activity-redirect.js';
const origin = 'https://electric-cherry.invalid';
const pagePath =
/^\/(?:$|activity|operations|autoscaling|account|bank|capacity|metrics|server-keys|settings(?:\/users)?|servers\/[^/]+|hosts(?:\/[^/]+)?|collections(?:\/launches\/[^/]+)?|(?:scripts|configs|plugins|betas|campaigns|maintenance|provisioning|matches)(?:\/[^/]+)?|game-files|leaderboard(?:\/players\/[^/]+(?:\/[^/]+)?)?)$/;
@@ -16,6 +18,8 @@ export function safeReturnHref(value: string | null | undefined, fallback: strin
try {
const url = new URL(value, origin);
if (url.origin !== origin || !pagePath.test(url.pathname)) return fallback;
if (url.pathname === '/activity' || url.pathname === '/operations')
return activityRedirectHref(url);
return url.pathname + url.search + url.hash;
} catch {
return fallback;
@@ -45,8 +49,6 @@ export function returnLabel(href: string): string {
if (path.startsWith('/hosts/')) return 'Back to host';
const names: Record<string, string> = {
'': 'Servers',
activity: 'Activity',
operations: 'Activity',
autoscaling: 'Autoscaling',
collections: 'Collections',
hosts: 'Hosts',
+1 -9
View File
@@ -28,8 +28,7 @@ export const navigationGroups: NavigationGroup[] = [
label: 'Hosts',
href: '/hosts',
shortcut: 'o',
matches: (path) =>
path === '/hosts' || /^\/hosts\/(?!operations(?:\/|$))/.test(path)
matches: (path) => path === '/hosts' || path.startsWith('/hosts/')
},
{ label: 'Capacity', href: '/capacity' },
{ label: 'Autoscaling', href: '/autoscaling' },
@@ -52,13 +51,6 @@ export const navigationGroups: NavigationGroup[] = [
id: 'activity',
label: 'Activity',
items: [
{
label: 'Activity log',
href: '/activity',
shortcut: 'd',
matches: (path) =>
path === '/activity' || path === '/operations' || path === '/hosts/operations'
},
{
label: 'Provisioning',
href: '/provisioning',
+3 -9
View File
@@ -1,12 +1,6 @@
import { parseActivityQuery } from '$lib/activity.js';
import { activityHistory } from '$lib/server/activity.js';
import { redirect } from '@sveltejs/kit';
import { activityRedirectHref } from '$lib/activity-redirect.js';
export function load({ url }: { url: URL }) {
return {
activity: activityHistory({
...parseActivityQuery(url.searchParams),
excludeProvisioning: true,
excludeMaintenance: true
})
};
redirect(308, activityRedirectHref(url));
}
-23
View File
@@ -1,23 +0,0 @@
<script lang="ts">
import ActivityLog from '$ui/components/ActivityLog.svelte';
import SectionHeader from '$ui/components/primitives/SectionHeader.svelte';
let { data }: { data: import('./$types').PageData } = $props();
</script>
<svelte:head><title>Activity · Electric Cherry</title></svelte:head>
<div class="page">
<SectionHeader
title="Activity"
subtitle="Releases and host activity. Server jobs are in Provisioning; maintenance and recovery are in Maintenance history."
/>
<ActivityLog initial={data.activity} excludeProvisioning excludeMaintenance />
</div>
<style>
.page {
display: grid;
gap: var(--space-6);
min-width: 0;
}
</style>
+2 -1
View File
@@ -86,7 +86,8 @@
<svelte:head><title>Hosts · Electric Cherry</title></svelte:head>
<section class="page">
<SectionHeader title="Hosts">
{#snippet actions()}<Button href="/capacity?rebalance=1">Rebalance</Button
{#snippet actions()}<Button href="/hosts/operations">Operation history</Button><Button
href="/capacity?rebalance=1">Rebalance</Button
>{#if canManage}<Button variant="primary" onclick={() => (addOpen = true)}
>Add host</Button
>{/if}{/snippet}
+2 -2
View File
@@ -141,7 +141,7 @@
<section class="page" aria-busy={changingPage}>
<SectionHeader
title="Host operation history"
eyebrow="Operations"
eyebrow="Hosts"
subtitle="Remote operations, newest first. Filtered views retain their host and server context."
>
{#snippet actions()}<Freshness
@@ -152,7 +152,7 @@
/>{/snippet}
</SectionHeader>
{#if data.scope.operation || $page.url.searchParams.has('returnTo')}<BackLink
fallback={data.scope.operation ? '/activity' : '/hosts'}
fallback={data.scope.operation ? allOperationsHref : '/hosts'}
/>{/if}
{#if data.scope.operation}<div class="selected-operation">
<div><strong>Selected host operation</strong><code>{data.scope.operation}</code></div>
+3 -2
View File
@@ -1,5 +1,6 @@
import { redirect } from '@sveltejs/kit';
import { activityRedirectHref } from '$lib/activity-redirect.js';
export function load() {
redirect(308, '/activity');
export function load({ url }: { url: URL }) {
redirect(308, activityRedirectHref(url));
}
-10
View File
@@ -837,11 +837,6 @@
{:else if activeSection === 'matches'}
{#key name}<MatchHistory server={name} />{/key}
{:else if activeSection === 'history'}
<div class="history-links">
<a href={contextHref(`/activity?server=${encodeURIComponent(name)}`, $page.url)}
>Open in Activity</a
>
</div>
{#key name}<ActivityLog server={name} />{/key}
{/if}
</div>
@@ -866,11 +861,6 @@
min-width: 0;
scroll-margin-top: 80px;
}
.history-links {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.server-actions {
text-align: right;
}