fix(sites): show Secrets card before Resources on site detail
Build / build (push) Successful in 10m30s
Build / build (push) Successful in 10m30s
Secrets is the more frequently edited section than Resources/logs; reorder so it appears right after Site Info on /sites/[id].
This commit is contained in:
@@ -283,6 +283,67 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Secrets -->
|
||||
<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-base font-semibold text-[var(--text-primary)]">{$t('sites.secrets')}</h2>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => { showSecretForm = !showSecretForm; }}
|
||||
class="inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-[var(--color-brand-600)] hover:bg-[var(--surface-card-hover)] transition-colors"
|
||||
>
|
||||
<IconPlus size={14} />
|
||||
{$t('sites.addSecret')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if showSecretForm}
|
||||
<div class="mb-4 space-y-3 rounded-lg bg-[var(--surface-card-hover)] p-4">
|
||||
<FormField label={$t('sites.secretKey')} name="secretKey" bind:value={secretKey} placeholder="API_KEY" required />
|
||||
<FormField label={$t('sites.secretValue')} name="secretValue" bind:value={secretValue} placeholder="sk-..." />
|
||||
<div class="flex items-center gap-2 text-sm text-[var(--text-secondary)]">
|
||||
<ToggleSwitch bind:checked={secretEncrypted} label={$t('sites.encryptSecret')} />
|
||||
<span>{$t('sites.encryptSecret')}</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
disabled={!secretKey.trim() || secretSubmitting}
|
||||
onclick={handleAddSecret}
|
||||
class="rounded-lg bg-[var(--color-brand-600)] px-3 py-2 text-sm font-medium text-white hover:bg-[var(--color-brand-700)] disabled:opacity-50 transition-colors"
|
||||
>
|
||||
{secretSubmitting ? $t('common.saving') : $t('sites.saveSecret')}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if secrets.length === 0}
|
||||
<p class="text-sm text-[var(--text-tertiary)]">{$t('sites.noSecrets')}</p>
|
||||
{:else}
|
||||
<div class="space-y-2">
|
||||
{#each secrets as secret (secret.id)}
|
||||
<div class="flex items-center justify-between rounded-lg border border-[var(--border-secondary)] px-3 py-2">
|
||||
<div class="flex items-center gap-2">
|
||||
{#if secret.encrypted}
|
||||
<IconLock size={14} class="text-[var(--text-tertiary)]" />
|
||||
{:else}
|
||||
<IconUnlock size={14} class="text-[var(--text-tertiary)]" />
|
||||
{/if}
|
||||
<span class="font-mono text-sm text-[var(--text-primary)]">{secret.key}</span>
|
||||
<span class="text-xs text-[var(--text-tertiary)]">{secret.value}</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => { confirmDeleteSecretId = secret.id; }}
|
||||
class="rounded p-1 text-[var(--text-tertiary)] hover:text-[var(--color-danger)] transition-colors"
|
||||
>
|
||||
<IconTrash size={14} />
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Resource usage + logs for deployed sites. -->
|
||||
{#if site.container_id}
|
||||
<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-6">
|
||||
@@ -357,67 +418,6 @@
|
||||
disableSigning={() => api.disableStaticSiteNotificationSigning(siteId!)}
|
||||
sendTest={() => api.testStaticSiteNotification(siteId!)}
|
||||
/>
|
||||
|
||||
<!-- Secrets -->
|
||||
<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-base font-semibold text-[var(--text-primary)]">{$t('sites.secrets')}</h2>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => { showSecretForm = !showSecretForm; }}
|
||||
class="inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-[var(--color-brand-600)] hover:bg-[var(--surface-card-hover)] transition-colors"
|
||||
>
|
||||
<IconPlus size={14} />
|
||||
{$t('sites.addSecret')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if showSecretForm}
|
||||
<div class="mb-4 space-y-3 rounded-lg bg-[var(--surface-card-hover)] p-4">
|
||||
<FormField label={$t('sites.secretKey')} name="secretKey" bind:value={secretKey} placeholder="API_KEY" required />
|
||||
<FormField label={$t('sites.secretValue')} name="secretValue" bind:value={secretValue} placeholder="sk-..." />
|
||||
<div class="flex items-center gap-2 text-sm text-[var(--text-secondary)]">
|
||||
<ToggleSwitch bind:checked={secretEncrypted} label={$t('sites.encryptSecret')} />
|
||||
<span>{$t('sites.encryptSecret')}</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
disabled={!secretKey.trim() || secretSubmitting}
|
||||
onclick={handleAddSecret}
|
||||
class="rounded-lg bg-[var(--color-brand-600)] px-3 py-2 text-sm font-medium text-white hover:bg-[var(--color-brand-700)] disabled:opacity-50 transition-colors"
|
||||
>
|
||||
{secretSubmitting ? $t('common.saving') : $t('sites.saveSecret')}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if secrets.length === 0}
|
||||
<p class="text-sm text-[var(--text-tertiary)]">{$t('sites.noSecrets')}</p>
|
||||
{:else}
|
||||
<div class="space-y-2">
|
||||
{#each secrets as secret (secret.id)}
|
||||
<div class="flex items-center justify-between rounded-lg border border-[var(--border-secondary)] px-3 py-2">
|
||||
<div class="flex items-center gap-2">
|
||||
{#if secret.encrypted}
|
||||
<IconLock size={14} class="text-[var(--text-tertiary)]" />
|
||||
{:else}
|
||||
<IconUnlock size={14} class="text-[var(--text-tertiary)]" />
|
||||
{/if}
|
||||
<span class="font-mono text-sm text-[var(--text-primary)]">{secret.key}</span>
|
||||
<span class="text-xs text-[var(--text-tertiary)]">{secret.value}</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => { confirmDeleteSecretId = secret.id; }}
|
||||
class="rounded p-1 text-[var(--text-tertiary)] hover:text-[var(--color-danger)] transition-colors"
|
||||
>
|
||||
<IconTrash size={14} />
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Storage -->
|
||||
|
||||
Reference in New Issue
Block a user