This commit is contained in:
jarek committed 2026-05-09 09:55:18 +02:00
1 parent 91ef3e3c9b
commit 002d969a5d
46 files changed
+7202 -233

No files matched your search

+11 -2
View File
@@ -90,18 +90,27 @@
}
function formatChangelogDate(dateStr: string): string {
if (!dateStr) return 'Unreleased';
try {
const date = new Date(dateStr);
if (isNaN(date.getTime())) return 'Unreleased';
return date.toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
} catch {
return dateStr;
return 'Unreleased';
}
}
function sortedChanges(changes: ChangelogChange[]): ChangelogChange[] {
return [...changes].sort((a, b) => {
if (a.type === b.type) return 0;
return a.type === 'feature' ? -1 : 1;
});
}
// Build info - injected at build time
declare const __BUILD_BRANCH__: string | null;
const BUILD_DATE = __BUILD_DATE__ ?? null;
@@ -867,7 +876,7 @@
{#if isExpanded}
<div class="px-4 pb-4">
<ul class="space-y-1.5 text-sm text-muted-foreground mb-3">
{#each release.changes as change}
{#each sortedChanges(release.changes) as change}
<li class="flex items-start gap-2">
{#if change.type === 'feature'}
<span class="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-2xs font-medium bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 shrink-0">
@@ -751,7 +751,7 @@
labels: formLabels,
connectionType: formConnectionType,
hawserToken: formHawserToken || undefined,
publicIp: formConnectionType !== 'hawser-edge' ? (stripHostProtocol(formPublicIp.trim()) || undefined) : undefined
publicIp: stripHostProtocol(formPublicIp.trim()) || undefined
})
});
@@ -869,7 +869,7 @@
labels: formLabels,
connectionType: formConnectionType,
hawserToken: formHawserToken || undefined,
publicIp: formConnectionType !== 'hawser-edge' ? (stripHostProtocol(formPublicIp.trim()) || null) : null
publicIp: stripHostProtocol(formPublicIp.trim()) || null
})
});
@@ -2160,31 +2160,29 @@
</div>
{/if}
<!-- Public IP field (for all types except hawser-edge) -->
{#if formConnectionType !== 'hawser-edge'}
<div class="space-y-2 pt-4 border-t">
<div class="flex items-center gap-2">
<Label for="edit-env-public-ip">Public IP</Label>
<Tooltip.Root>
<Tooltip.Trigger>
<HelpCircle class="w-3.5 h-3.5 text-muted-foreground" />
</Tooltip.Trigger>
<Tooltip.Content side="bottom" class="w-72">
<p>IP address or hostname where container ports are accessible from your browser. For local Docker, use the server's LAN IP.</p>
</Tooltip.Content>
</Tooltip.Root>
</div>
<Input
id="edit-env-public-ip"
bind:value={formPublicIp}
placeholder="e.g., 192.168.1.4"
class="w-full"
/>
<p class="text-xs text-muted-foreground">
Used for clickable port links on the containers page
</p>
<!-- Public IP field -->
<div class="space-y-2 pt-4 border-t">
<div class="flex items-center gap-2">
<Label for="edit-env-public-ip">Public IP</Label>
<Tooltip.Root>
<Tooltip.Trigger>
<HelpCircle class="w-3.5 h-3.5 text-muted-foreground" />
</Tooltip.Trigger>
<Tooltip.Content side="bottom" class="w-72">
<p>IP address or hostname where container ports are accessible from your browser. For local Docker, use the server's LAN IP.</p>
</Tooltip.Content>
</Tooltip.Root>
</div>
{/if}
<Input
id="edit-env-public-ip"
bind:value={formPublicIp}
placeholder="e.g., 192.168.1.4"
class="w-full"
/>
<p class="text-xs text-muted-foreground">
Used for clickable port links on the containers page
</p>
</div>
</Tabs.Content>
<!-- Updates Tab -->
@@ -74,6 +74,8 @@ services:
let eventCleanupCron = $derived($appSettings.eventCleanupCron);
let scheduleCleanupEnabled = $derived($appSettings.scheduleCleanupEnabled);
let eventCleanupEnabled = $derived($appSettings.eventCleanupEnabled);
let scannerCleanupCron = $derived($appSettings.scannerCleanupCron);
let scannerCleanupEnabled = $derived($appSettings.scannerCleanupEnabled);
let logBufferSizeKb = $derived($appSettings.logBufferSizeKb);
let formatLogTimestamps = $derived($appSettings.formatLogTimestamps);
let defaultTimezone = $derived($appSettings.defaultTimezone);
@@ -146,6 +148,17 @@ services:
toast.success(newState ? 'Event cleanup enabled' : 'Event cleanup disabled');
}
function handleScannerCleanupCronChange(cron: string) {
appSettings.setScannerCleanupCron(cron);
toast.success('Scanner cleanup cron updated');
}
function handleScannerCleanupEnabledChange() {
const newState = !scannerCleanupEnabled;
appSettings.setScannerCleanupEnabled(newState);
toast.success(newState ? 'Scanner cleanup enabled' : 'Scanner cleanup disabled');
}
function handleGrypeImageBlur(e: Event) {
const value = (e.target as HTMLInputElement).value.trim();
if (value && value !== defaultGrypeImage) {
@@ -758,6 +771,26 @@ services:
Runs every 30 minutes and on startup.
</p>
</div>
<div class="space-y-1 pt-2 border-t">
<div class="flex items-center gap-3">
<Label>Scanner cache cleanup</Label>
<TogglePill
checked={scannerCleanupEnabled}
onchange={handleScannerCleanupEnabledChange}
disabled={!$canAccess('settings', 'edit')}
/>
</div>
<p class="text-xs text-muted-foreground">Remove cached vulnerability databases to reclaim disk space</p>
<div class="flex items-center gap-2 mt-2">
<div class="ml-auto">
<CronEditor
value={scannerCleanupCron}
onchange={handleScannerCleanupCronChange}
disabled={!$canAccess('settings', 'edit') || !scannerCleanupEnabled}
/>
</div>
</div>
</div>
</Card.Content>
</Card.Root>
@@ -422,6 +422,8 @@ mmost://hostname/webhook-token
tgram://bot_token/chat_id
tgram://bot_token/chat_id:topic_id
ntfy://my-topic
ntfy://host/topic?auth=base64token
ntfys://host/topic?auth=base64token
pushover://user_key/api_token
workflows://hostname/workflow/signature
jsons://hostname/webhook/path"