From 12d1e356fa8785dce276a1005f2215a03296c48d Mon Sep 17 00:00:00 2001 From: pptx704 Date: Thu, 26 Mar 2026 03:58:12 +0600 Subject: [PATCH] Minor UI copy updates across capsules and templates pages --- .../lib/components/CreateCapsuleDialog.svelte | 5 +- .../routes/dashboard/capsules/+layout.svelte | 2 +- .../routes/dashboard/capsules/+page.svelte | 22 +++++--- .../dashboard/capsules/[id]/+page.svelte | 2 +- .../routes/dashboard/snapshots/+page.svelte | 53 ++++++++++--------- 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/frontend/src/lib/components/CreateCapsuleDialog.svelte b/frontend/src/lib/components/CreateCapsuleDialog.svelte index b570f2b..2bd027d 100644 --- a/frontend/src/lib/components/CreateCapsuleDialog.svelte +++ b/frontend/src/lib/components/CreateCapsuleDialog.svelte @@ -56,6 +56,7 @@ class="w-full rounded-[var(--radius-input)] border border-[var(--color-border)] bg-[var(--color-bg-4)] px-3 py-2 font-mono text-ui text-[var(--color-text-bright)] outline-none placeholder:text-[var(--color-text-muted)] transition-colors duration-150 focus:border-[var(--color-accent)]" placeholder="minimal" /> +

Name of a snapshot or base image to boot from.

@@ -85,14 +86,16 @@
- + +

Seconds of inactivity before the capsule pauses. Set to 0 to keep it running indefinitely.

diff --git a/frontend/src/routes/dashboard/capsules/+layout.svelte b/frontend/src/routes/dashboard/capsules/+layout.svelte index d9f93f8..5c400b9 100644 --- a/frontend/src/routes/dashboard/capsules/+layout.svelte +++ b/frontend/src/routes/dashboard/capsules/+layout.svelte @@ -47,7 +47,7 @@ Capsules

- Isolated VMs. Start cold in under a second — pause, snapshot, or destroy at will. + All active and recent capsules across your team.

diff --git a/frontend/src/routes/dashboard/capsules/+page.svelte b/frontend/src/routes/dashboard/capsules/+page.svelte index 4f27003..afb9de0 100644 --- a/frontend/src/routes/dashboard/capsules/+page.svelte +++ b/frontend/src/routes/dashboard/capsules/+page.svelte @@ -247,6 +247,13 @@ return `${Math.floor(seconds / 86400)}d ago`; } + function fmtTimeout(sec: number): string { + if (!sec) return 'None'; + if (sec < 60) return `${sec}s`; + if (sec < 3600) return `${Math.round(sec / 60)}m`; + return `${Math.round(sec / 3600)}h`; + } + function handleClickOutside(event: MouseEvent) { if (openMenuId && !(event.target as Element)?.closest('.status-menu-container')) { openMenuId = null; @@ -300,7 +307,7 @@ class="w-full rounded-[var(--radius-input)] border border-[var(--color-border)] bg-[var(--color-bg-2)] py-2 pl-9 pr-3 font-mono text-ui text-[var(--color-text-bright)] outline-none placeholder:text-[var(--color-text-muted)] transition-colors duration-150 focus:border-[var(--color-accent)]" /> - {filteredCapsules.length} total + {filteredCapsules.length} capsule{filteredCapsules.length !== 1 ? 's' : ''}
@@ -363,8 +370,11 @@ {#if error} -
- {error} +
+ + + + {error}. Try refreshing the page.
{/if} @@ -466,14 +476,14 @@
- {capsule.timeout_sec ? `${capsule.timeout_sec}s` : '—'} + {fmtTimeout(capsule.timeout_sec)}
{formatTime(capsule.started_at)} {#if capsule.last_active_at} - {timeAgo(capsule.last_active_at)} + active {timeAgo(capsule.last_active_at)} {/if}
@@ -612,7 +622,7 @@ -

This capsule will be paused first — memory state is captured at rest.

+

This capsule will be paused first, then its full state (memory + disk) will be captured.

{:else}

The capsule's current memory state will be captured and stored as a reusable snapshot.

diff --git a/frontend/src/routes/dashboard/capsules/[id]/+page.svelte b/frontend/src/routes/dashboard/capsules/[id]/+page.svelte index e932209..ed26426 100644 --- a/frontend/src/routes/dashboard/capsules/[id]/+page.svelte +++ b/frontend/src/routes/dashboard/capsules/[id]/+page.svelte @@ -512,7 +512,7 @@ - Failed to load metrics: {metricsError} + Could not load metrics: {metricsError}. Will retry automatically. {/if} diff --git a/frontend/src/routes/dashboard/snapshots/+page.svelte b/frontend/src/routes/dashboard/snapshots/+page.svelte index e39bf3b..6f86d4c 100644 --- a/frontend/src/routes/dashboard/snapshots/+page.svelte +++ b/frontend/src/routes/dashboard/snapshots/+page.svelte @@ -114,15 +114,15 @@ } function emptyHeading(f: TypeFilter): string { - if (f === 'snapshot') return 'No snapshots'; - if (f === 'base') return 'No images'; - return 'No templates yet'; + if (f === 'snapshot') return 'No snapshots yet'; + if (f === 'base') return 'No base images'; + return 'No snapshots yet'; } function emptyDescription(f: TypeFilter): string { - if (f === 'snapshot') return 'Pause a capsule from the Capsules page, then snapshot it to capture its state.'; - if (f === 'base') return 'Base images are added by the Wrenn team. Contact support to request a custom image.'; - return 'To create a snapshot, go to Capsules, pause a running capsule, then choose Snapshot.'; + if (f === 'snapshot') return 'Pause a running capsule, then choose Snapshot to save its state.'; + if (f === 'base') return 'Base images are provided by the Wrenn team. Contact support to request a custom one.'; + return 'Pause a running capsule, then choose Snapshot to save its state. You can launch new capsules from any snapshot.'; } onMount(fetchSnapshots); @@ -162,7 +162,7 @@ Templates

- Snapshots capture a live capsule state. Base images are the rootfs every capsule starts from. Launch a full VM from any template. + Snapshots capture a running capsule's state. Base images are the starting point for every new capsule. Launch from either.

@@ -206,8 +206,11 @@ {#if pageTab === 'snapshots'}
{#if error} -
- {error} +
+ + + + {error}. Try refreshing the page.
{/if} @@ -274,11 +277,11 @@
{filteredSnapshots.length} - {typeFilter === 'all' - ? filteredSnapshots.length === 1 ? 'template' : 'templates' - : typeFilter === 'snapshot' - ? filteredSnapshots.length === 1 ? 'snapshot' : 'snapshots' - : filteredSnapshots.length === 1 ? 'image' : 'images'} + {typeFilter === 'snapshot' + ? filteredSnapshots.length === 1 ? 'snapshot' : 'snapshots' + : typeFilter === 'base' + ? filteredSnapshots.length === 1 ? 'image' : 'images' + : filteredSnapshots.length === 1 ? 'item' : 'total'}
@@ -447,11 +450,11 @@

{filteredSnapshots.length} - {typeFilter === 'all' - ? filteredSnapshots.length === 1 ? 'template' : 'templates' - : typeFilter === 'snapshot' - ? filteredSnapshots.length === 1 ? 'snapshot' : 'snapshots' - : filteredSnapshots.length === 1 ? 'image' : 'images'} + {typeFilter === 'snapshot' + ? filteredSnapshots.length === 1 ? 'snapshot' : 'snapshots' + : typeFilter === 'base' + ? filteredSnapshots.length === 1 ? 'image' : 'images' + : filteredSnapshots.length === 1 ? 'item' : 'total'} {typeFilter !== 'all' ? '· filtered' : '· total'}

{/if} @@ -513,10 +516,10 @@ class="relative w-full max-w-[380px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both" > -

Delete Snapshot

+

Delete snapshot

Permanently delete {deleteTarget.name}. - Any capsule using this template will not be affected, but you won't be able to launch from it again. + Running capsules won't be affected, but you won't be able to launch new ones from it.

{#if deleteTarget.type === 'snapshot'} @@ -526,7 +529,7 @@

- This live capture includes saved memory state. Any capsule relying on it will be unable to resume. + This snapshot includes memory state. Paused capsules that depend on it won't be able to resume.

{/if} @@ -580,7 +583,7 @@ >

Launch Capsule

- Configure resources and launch. The VM will clone from this template and be ready in seconds. + Configure resources and launch a new capsule from this snapshot.

{#if launchError} @@ -655,14 +658,16 @@
- + +

Seconds of inactivity before the capsule pauses. Set to 0 to keep it running indefinitely.