{ if (isOpen) { focusFirstInput(); } else { // Prevent closing if there are unsaved changes (stack edits OR a half-edited // backup schedule in the embedded panel) - show confirmation instead if (isDirty || backupPanelRef?.isDirty()) { // Re-open the dialog and show confirmation open = true; showConfirmClose = true; } else { // No unsaved changes - reset state handleClose(); } } }} >
{#if mode === 'create'} Create compose stack {:else} {stackName} {/if} {#if $currentEnvironment} on {$currentEnvironment.name} {/if} {#if mode === 'create'} Create a new Docker Compose stack {:else if readonly} View compose file and dependency graph {:else} Edit compose file and environment variables {/if}
{#if mode === 'edit' && $page.data.backupsEnabled && !needsFileLocation} {/if}
{#if errors.compose} {errors.compose} {/if} {#if mode === 'edit' && loading}
Loading compose file...
{:else} {#if mode === 'create'}
errors.stackName = undefined} /> {#if errors.stackName}

{errors.stackName}

{/if}
{/if} {#if mode === 'edit' && needsFileLocation && !readonly}

Untracked stack — this stack is running in Docker but Dockhand doesn't know where its compose file is stored on disk. Browse to locate the file to start editing and managing it.

{#if stackContainers.length > 0}
Running containers:
{#each stackContainers as container} {container.name} {/each}
{/if}
{/if}
{#if activeTab === 'editor'}
{#if readonly} Git · read-only {#if gitInfo && (gitInfo.commit || gitInfo.url || gitInfo.branch)}
{#if gitInfo.commit} {gitInfo.commit} {/if} {#if gitInfo.url} {gitInfo.url} {/if} {#if gitInfo.branch} {gitInfo.branch} {/if}
{/if} {/if}
copyText(workingComposePath, (v) => composePathCopied = v)} onBrowse={readonly ? undefined : openComposeBrowser} onChangeLocation={mode === 'edit' && !needsFileLocation && !readonly ? openChangeLocationBrowser : undefined} defaultText={mode === 'create' ? 'Enter stack name above' : 'Not specified'} sourceHint={pathSourceHint} />
copyText(displayEnvPath, (v) => envPathCopied = v)} onBrowse={readonly ? undefined : openEnvBrowser} isEditable={!readonly} isCustom={!!workingEnvPath} defaultText={mode === 'create' ? 'Enter stack name above' : 'Not specified'} isSuggested={isEnvPathSuggested} onPathChange={(value) => { workingEnvPath = value; isDirty = true; }} />
{#if open}
{#if readonly && needsFileLocation && !composeContent}

Compose file not available

Deploy or sync this Git stack first so Dockhand has a local copy of its compose file.

{:else if needsFileLocation && !composeContent}

No compose file selected

Browse to locate the compose file for this stack. The editor will load the file contents once selected.

What happens when you select a file: Dockhand will track this compose file, letting you edit, start, and stop the stack from the UI. Your files stay in their current location.
{:else}
{/if}
{/if}
{ markDirty(); debouncedValidate(); }} theme={editorTheme} infoText="These variables will be written to a .env file in the stack directory and passed to the compose command." />
{:else if activeTab === 'graph'} {:else if activeTab === 'backups' && !needsFileLocation}
(backupTally = t)} />
{/if}
{/if}
{#if readonly} Read-only {:else if isDirty} Unsaved changes {:else} No changes {/if}
{#if readonly} {:else} {/if} {#if !readonly && mode === 'create'} {:else if !readonly} {/if}
Unsaved changes You have unsaved changes. Are you sure you want to close without saving?
Move stack files? You've changed the stack location. There {pathChangeFileCount === 1 ? 'is' : 'are'} {pathChangeFileCount} file{pathChangeFileCount === 1 ? '' : 's'} in the old location that can be moved to the new location. {#if pathChangeOldDir}
{pathChangeOldDir}
{/if}

Would you like to move all files to the new location, or leave them in place?

Replace editor content? Loading a different compose file will replace the current editor content.
Current: {workingComposePath || '(unsaved)'}
New: {pendingBrowsePath}
Relocate stack? All {changeLocationFileCount} file{changeLocationFileCount === 1 ? '' : 's'} in the stack folder will be moved.
From {changeLocationOldDir}
To {pendingNewLocation}
Stack already exists A stack named "{newStackName}" already exists. Please choose a different name.
{#if operationError} {@const errorDialogOpen = true} operationError = null} /> {/if} showFileBrowser = false} />