158 lines
4.3 KiB
Svelte
158 lines
4.3 KiB
Svelte
<script lang="ts">
|
|
import RelativeTime from '$ui/components/RelativeTime.svelte';
|
|
import { launchFileVersionLabel } from '$lib/artifact-version.js';
|
|
import type { LaunchRecipeSummary } from '$lib/deployment-plan.js';
|
|
let { recipe, historical = false }: { recipe: LaunchRecipeSummary; historical?: boolean } =
|
|
$props();
|
|
</script>
|
|
|
|
<div class="recipe">
|
|
<div class="recipe-heading">
|
|
<div>
|
|
{#if !historical}<span class="eyebrow">Current promoted setup</span>{/if}
|
|
<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>
|
|
{#if !historical}<p>
|
|
Each server uses the latest promoted scripts, plugins, and configuration when
|
|
provisioning begins, including promotions made after this preview or while queued.
|
|
</p>{/if}
|
|
<details>
|
|
<summary
|
|
>{recipe.files.length} managed file{recipe.files.length === 1 ? '' : 's'}
|
|
{historical ? 'recorded for this deployment' : 'in the current setup'}</summary
|
|
>
|
|
<ul>
|
|
{#each recipe.files as file}<li>
|
|
<div>
|
|
<strong>{file.name}</strong><span
|
|
>{launchFileVersionLabel(file)} · {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>
|
|
{#if !historical}<p>
|
|
Previewed <RelativeTime value={recipe.capturedAt} />. This preview shows the
|
|
promoted setup at the time above. The deployment history records the files selected
|
|
when provisioning begins.
|
|
</p>{/if}
|
|
<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: 0.12em;
|
|
color: var(--text-secondary);
|
|
margin-bottom: 6px;
|
|
}
|
|
h3 {
|
|
margin: 0;
|
|
font-size: var(--text-xl);
|
|
letter-spacing: -0.03em;
|
|
}
|
|
.game {
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: 99px;
|
|
padding: 5px 10px;
|
|
font-size: var(--text-xs);
|
|
white-space: nowrap;
|
|
}
|
|
dl {
|
|
display: grid;
|
|
gap: 12px;
|
|
margin: 0;
|
|
}
|
|
dt {
|
|
color: var(--text-secondary);
|
|
font-size: var(--text-xs);
|
|
}
|
|
dd {
|
|
margin: 4px 0 0;
|
|
font-size: var(--text-sm);
|
|
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: var(--text-sm);
|
|
}
|
|
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: var(--text-sm);
|
|
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: var(--text-xs);
|
|
line-height: 1.6;
|
|
}
|
|
</style>
|