34 lines
2.8 KiB
Svelte
34 lines
2.8 KiB
Svelte
<script lang="ts">
|
||
import type { LaunchRecipeSummary } from '$lib/deployment-plan.js';
|
||
let { recipe }: { recipe: LaunchRecipeSummary } = $props();
|
||
</script>
|
||
|
||
<div class="recipe">
|
||
<div class="recipe-heading"><div><span class="eyebrow">Launch recipe</span><h3>{recipe.mapName}</h3></div><span class="game">{recipe.game === 't6' ? 'Black Ops II' : 'Black Ops I'}</span></div>
|
||
<dl>
|
||
<div><dt>Configuration</dt><dd>{recipe.configSource}</dd></div>
|
||
<div><dt>Container image</dt><dd class="mono">{recipe.image}</dd></div>
|
||
</dl>
|
||
<details>
|
||
<summary>{recipe.files.length} managed file{recipe.files.length === 1 ? '' : 's'} in this recipe</summary>
|
||
<ul>{#each recipe.files as file}<li><div><strong>{file.name}</strong><span>{file.version !== null ? `v${file.version}` : 'Generated'} · {file.kind} · {file.size.toLocaleString()} bytes</span></div><code>{file.path}</code><small title={file.sha256}>SHA-256 {file.sha256.slice(0, 12)}</small></li>{/each}</ul>
|
||
<p>Captured {new Date(recipe.capturedAt).toLocaleString()}. Managed file contents are saved with this recipe. Image tags and Plutainer defaults can change; use an image digest and a promoted baseline for more reproducible launches.</p>
|
||
<p>Future fleet promotions and drift repair still follow the server’s game and map.</p>
|
||
<small class="fingerprint" title={recipe.fingerprint}>Recipe {recipe.fingerprint.slice(0, 16)}</small>
|
||
</details>
|
||
</div>
|
||
|
||
<style>
|
||
.recipe { display: grid; gap: 16px; min-width: 0; }
|
||
.recipe-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
|
||
.eyebrow { display: block; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .12em; color: var(--text-secondary); margin-bottom: 6px; }
|
||
h3 { margin: 0; font-size: 22px; letter-spacing: -.03em; }
|
||
.game { border: 1px solid var(--border-strong); border-radius: 99px; padding: 5px 10px; font-size: 12px; white-space: nowrap; }
|
||
dl { display: grid; gap: 12px; margin: 0; } dt { color: var(--text-secondary); font-size: 12px; } dd { margin: 4px 0 0; font-size: 13px; overflow-wrap: anywhere; line-height: 1.5; }
|
||
.mono, code, .fingerprint { font-family: var(--font-mono); }
|
||
details { border-top: 1px solid var(--border-subtle); padding-top: 14px; } summary { cursor: pointer; font-size: 13px; }
|
||
ul { list-style: none; padding: 0; margin: 12px 0; } li { display: grid; gap: 5px; padding: 12px 0; border-bottom: 1px solid var(--border-subtle); overflow-wrap: anywhere; }
|
||
li > div { display: flex; justify-content: space-between; gap: 8px; flex-wrap: wrap; } strong { font-size: 13px; font-weight: 550; } span, code, small { font-size: var(--text-xs); } li span, small { color: var(--text-secondary); }
|
||
p { color: var(--text-secondary); font-size: 12px; line-height: 1.6; }
|
||
</style>
|