Files
windmill/dev-dashboard/frontend/src/lib/CreateWorktreeDialog.svelte
centdix 268b5ee2a8 feat: add save as default checkbox for worktree profile selection
Persist the selected profile to localStorage when checked, and
preselect it on subsequent dialog opens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:04:58 +00:00

82 lines
3.0 KiB
Svelte

<script lang="ts">
import type { Profile } from "./api";
const PROFILES: { value: Profile; label: string }[] = [
{ value: "agent-only", label: "Agent only" },
{ value: "agent-yolo", label: "Agent (skip permissions)" },
{ value: "full", label: "Full (agent + backend + frontend)" },
];
let { loading = false, oncreate, oncancel }: {
loading?: boolean;
oncreate: (name: string, profile: Profile) => void;
oncancel: () => void;
} = $props();
const STORAGE_KEY = "wt-default-profile";
const savedProfile = localStorage.getItem(STORAGE_KEY) as Profile | null;
let name = $state("");
let profile = $state<Profile>(savedProfile ?? "agent-only");
let saveDefault = $state(false);
let dialogEl: HTMLDialogElement;
$effect(() => {
dialogEl?.showModal();
});
const btn = "px-3 py-1.5 rounded-md border border-edge bg-surface text-primary text-xs cursor-pointer hover:bg-hover";
</script>
<dialog bind:this={dialogEl} onclose={oncancel} class="bg-sidebar text-primary border border-edge rounded-xl p-6 max-w-[380px] w-[90%]">
<form method="dialog" onsubmit={(e) => {
e.preventDefault();
if (saveDefault) localStorage.setItem(STORAGE_KEY, profile);
else localStorage.removeItem(STORAGE_KEY);
oncreate(name.trim(), profile);
}}>
<h2 class="text-base mb-4">New Worktree</h2>
<div class="mb-4">
<label class="block text-xs text-muted mb-1.5" for="wt-name">Name <span class="opacity-60">(optional)</span></label>
<input
id="wt-name"
type="text"
class="w-full px-2.5 py-1.5 rounded-md border border-edge bg-surface text-primary text-[13px] placeholder:text-muted/50 outline-none focus:border-accent"
placeholder="auto-generated if empty"
bind:value={name}
/>
</div>
<div class="flex flex-col gap-2 mb-6">
{#each PROFILES as p}
<label
class="flex items-center gap-2.5 p-2.5 rounded-lg border cursor-pointer text-[13px] transition-colors
{profile === p.value ? 'border-accent bg-accent/10' : 'border-edge hover:bg-hover'}"
>
<input
type="radio"
name="profile"
value={p.value}
checked={profile === p.value}
onchange={() => (profile = p.value)}
class="accent-[var(--accent)]"
/>
{p.label}
</label>
{/each}
</div>
<label class="flex items-center gap-2 mb-4 text-[13px] text-muted cursor-pointer">
<input type="checkbox" bind:checked={saveDefault} class="accent-[var(--accent)]" />
Save as default
</label>
<div class="flex justify-end gap-2">
<button type="button" class={btn} onclick={oncancel} disabled={loading}>Cancel</button>
<button
type="submit"
class="{btn} !bg-accent !text-white !border-accent hover:!opacity-90 disabled:!opacity-50 disabled:!cursor-not-allowed flex items-center gap-1.5"
disabled={loading}
>{#if loading}<span class="spinner"></span>{/if} Create</button>
</div>
</form>
</dialog>