Remove standalone Activity log page (Refs #153)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user