web: Improve sidebar in domain/services/checks
This commit is contained in:
parent
7cb67c452f
commit
98ceb57175
2 changed files with 184 additions and 163 deletions
|
|
@ -80,8 +80,7 @@
|
|||
let selectedHistory: string | undefined = $derived(page.data.history);
|
||||
|
||||
let isZonePage = $derived(
|
||||
page.route.id === "/domains/[dn]" ||
|
||||
page.route.id === "/domains/[dn]/[[historyid]]",
|
||||
page.route.id === "/domains/[dn]" || page.route.id === "/domains/[dn]/[[historyid]]",
|
||||
);
|
||||
let showPublishFooter = $derived(
|
||||
isZonePage &&
|
||||
|
|
@ -150,10 +149,10 @@
|
|||
sm={4}
|
||||
md={3}
|
||||
class="py-2 sticky-top d-flex flex-column"
|
||||
style="background-color: #edf5f2; overflow-y: auto; max-height: 100vh; z-index: 0"
|
||||
style="background-color: #edf5f2; z-index: 0; max-height: 100vh; overflow-y: auto;"
|
||||
>
|
||||
{#if $domains_idx[selectedDomain]}
|
||||
<!-- Header: back button + domain selector -->
|
||||
<!-- Header: back button + domain selector (always visible) -->
|
||||
<div class="d-flex">
|
||||
<Button href={isZonePage ? "/domains/" : ".."} class="fw-bolder" color="link">
|
||||
<Icon name={isZonePage ? "chevron-up" : "chevron-left"} />
|
||||
|
|
@ -161,75 +160,90 @@
|
|||
<SelectDomain bind:selectedDomain />
|
||||
</div>
|
||||
|
||||
<!-- Main content: routed sidebar -->
|
||||
<div class="flex-fill d-flex flex-column">
|
||||
{#if page.route.id && page.route.id.startsWith("/domains/[dn]/checks")}
|
||||
<ChecksSidebarContent
|
||||
domain={data.domain}
|
||||
checksBase={"/domains/" +
|
||||
encodeURIComponent(domainLink(selectedDomain)) +
|
||||
"/checks"}
|
||||
backHref={"/domains/" + encodeURIComponent(domainLink(selectedDomain))}
|
||||
/>
|
||||
{:else if page.route.id && (page.route.id.startsWith("/domains/[dn]/history") || page.route.id.startsWith("/domains/[dn]/logs") || page.route.id.startsWith("/domains/[dn]/[[historyid]]/export"))}
|
||||
<a
|
||||
href="/domains/{encodeURIComponent(domainLink(selectedDomain))}"
|
||||
class="sidebar-back d-flex align-items-center gap-1 mt-3 text-muted text-decoration-none fw-semibold"
|
||||
>
|
||||
<Icon name="chevron-left" />
|
||||
{$t("zones.return-to")}
|
||||
</a>
|
||||
{:else if page.route.id && page.route.id.startsWith("/domains/[dn]/[[historyid]]/[subdomain]/[serviceid]/checks")}
|
||||
<ChecksSidebarContent
|
||||
domain={data.domain}
|
||||
checksBase={"/domains/" +
|
||||
encodeURIComponent(domainLink(selectedDomain)) +
|
||||
"/" +
|
||||
encodeURIComponent(page.data.history ?? "") +
|
||||
"/" +
|
||||
encodeURIComponent(page.params.subdomain ?? "") +
|
||||
"/" +
|
||||
encodeURIComponent(page.data.serviceid ?? "") +
|
||||
"/checks"}
|
||||
backHref={"/domains/" +
|
||||
encodeURIComponent(domainLink(selectedDomain)) +
|
||||
"/" +
|
||||
encodeURIComponent(page.data.history ?? "") +
|
||||
"/" +
|
||||
encodeURIComponent(page.params.subdomain ?? "") +
|
||||
"/" +
|
||||
encodeURIComponent(page.data.serviceid ?? "")}
|
||||
serviceContext={{
|
||||
zoneId: page.data.zoneId ?? "",
|
||||
subdomain: page.data.subdomain ?? "",
|
||||
serviceid: page.data.serviceid ?? "",
|
||||
}}
|
||||
/>
|
||||
{:else if page.route.id === "/domains/[dn]/[[historyid]]/[subdomain]/[serviceid]"}
|
||||
<ServiceSidebar
|
||||
origin={data.domain}
|
||||
subdomain={page.data.subdomain ?? ""}
|
||||
serviceid={page.data.serviceid ?? ""}
|
||||
historyId={page.data.history ?? ""}
|
||||
/>
|
||||
{:else}
|
||||
<ZoneSidebar
|
||||
origin={data.domain}
|
||||
{selectedDomain}
|
||||
{selectedHistory}
|
||||
onretrieveZoneDone={retrieveZoneDone}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
<!-- Main content: routed sidebar (scrolls along with the Col itself) -->
|
||||
{#if page.route.id && page.route.id.startsWith("/domains/[dn]/checks")}
|
||||
<ChecksSidebarContent
|
||||
domain={data.domain}
|
||||
checksBase={"/domains/" +
|
||||
encodeURIComponent(domainLink(selectedDomain)) +
|
||||
"/checks"}
|
||||
backHref={"/domains/" + encodeURIComponent(domainLink(selectedDomain))}
|
||||
/>
|
||||
{:else if page.route.id && (page.route.id.startsWith("/domains/[dn]/history") || page.route.id.startsWith("/domains/[dn]/logs") || page.route.id.startsWith("/domains/[dn]/[[historyid]]/export"))}
|
||||
<a
|
||||
href="/domains/{encodeURIComponent(domainLink(selectedDomain))}"
|
||||
class="sidebar-back d-flex align-items-center gap-1 mt-3 text-muted text-decoration-none fw-semibold"
|
||||
>
|
||||
<Icon name="chevron-left" />
|
||||
{$t("zones.return-to")}
|
||||
</a>
|
||||
{:else if page.route.id && page.route.id.startsWith("/domains/[dn]/[[historyid]]/[subdomain]/[serviceid]/checks")}
|
||||
<ChecksSidebarContent
|
||||
domain={data.domain}
|
||||
checksBase={"/domains/" +
|
||||
encodeURIComponent(domainLink(selectedDomain)) +
|
||||
"/" +
|
||||
encodeURIComponent(page.data.history ?? "") +
|
||||
"/" +
|
||||
encodeURIComponent(page.params.subdomain ?? "") +
|
||||
"/" +
|
||||
encodeURIComponent(page.data.serviceid ?? "") +
|
||||
"/checks"}
|
||||
backHref={"/domains/" +
|
||||
encodeURIComponent(domainLink(selectedDomain)) +
|
||||
"/" +
|
||||
encodeURIComponent(page.data.history ?? "") +
|
||||
"/" +
|
||||
encodeURIComponent(page.params.subdomain ?? "") +
|
||||
"/" +
|
||||
encodeURIComponent(page.data.serviceid ?? "")}
|
||||
serviceContext={{
|
||||
zoneId: page.data.zoneId ?? "",
|
||||
subdomain: page.data.subdomain ?? "",
|
||||
serviceid: page.data.serviceid ?? "",
|
||||
}}
|
||||
/>
|
||||
{:else if page.route.id === "/domains/[dn]/[[historyid]]/[subdomain]/[serviceid]"}
|
||||
<ServiceSidebar
|
||||
origin={data.domain}
|
||||
subdomain={page.data.subdomain ?? ""}
|
||||
serviceid={page.data.serviceid ?? ""}
|
||||
historyId={page.data.history ?? ""}
|
||||
/>
|
||||
{:else}
|
||||
<ZoneSidebar
|
||||
origin={data.domain}
|
||||
{selectedDomain}
|
||||
{selectedHistory}
|
||||
onretrieveZoneDone={retrieveZoneDone}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<!-- Footer: only on the main zone view -->
|
||||
<!-- Spacer so the last sidebar item isn't hidden behind the fixed footer -->
|
||||
{#if showPublishFooter || showDetachFooter}
|
||||
<div class="sidebar-footer-spacer"></div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="mt-4 text-center">
|
||||
<Spinner color="primary" />
|
||||
</div>
|
||||
{/if}
|
||||
</Col>
|
||||
|
||||
<!-- Fixed footer pinned to the bottom of the viewport, matching sidebar width -->
|
||||
{#if $domains_idx[selectedDomain] && (showPublishFooter || showDetachFooter)}
|
||||
<div class="sidebar-footer-fixed col-sm-4 col-md-3">
|
||||
{#if showPublishFooter}
|
||||
<ButtonZonePublish domain={data.domain} history={selectedHistory} />
|
||||
{:else if showDetachFooter}
|
||||
<ButtonZonePublish
|
||||
class="w-100 border-top border-muted pt-2"
|
||||
domain={data.domain}
|
||||
history={selectedHistory}
|
||||
/>
|
||||
{:else}
|
||||
<Button
|
||||
color="danger"
|
||||
class="mt-3"
|
||||
outline
|
||||
class="w-100"
|
||||
disabled={deleteInProgress}
|
||||
on:click={() => ctrlDomainDelete.Open()}
|
||||
>
|
||||
|
|
@ -241,17 +255,15 @@
|
|||
{$t("domains.stop")}
|
||||
</Button>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="mt-4 text-center">
|
||||
<Spinner color="primary" />
|
||||
</div>
|
||||
{/if}
|
||||
</Col>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
class="col-sm-8 col-md-9 d-flex"
|
||||
class:p-0={page.route &&
|
||||
(page.route.id == "/domains/[dn]/checks/[checkerId]/executions/[execId]" ||
|
||||
page.route.id == "/domains/[dn]/[[historyid]]/[subdomain]/[serviceid]/checks/[checkerId]/executions/[execId]")}
|
||||
page.route.id ==
|
||||
"/domains/[dn]/[[historyid]]/[subdomain]/[serviceid]/checks/[checkerId]/executions/[execId]")}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
|
@ -273,3 +285,18 @@
|
|||
<ModalDiffZone domain={data.domain} {selectedHistory} />
|
||||
|
||||
<ServiceDetailsOffcanvas domain={data.domain} {selectedHistory} />
|
||||
|
||||
<style>
|
||||
.sidebar-footer-fixed {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 0.75rem;
|
||||
background-color: #edf5f2;
|
||||
z-index: 10;
|
||||
}
|
||||
.sidebar-footer-spacer {
|
||||
flex-shrink: 0;
|
||||
height: 3.5rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -34,11 +34,12 @@
|
|||
import { controls as ctrlDomainDelete } from "./ModalDomainDelete.svelte";
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
domain: Domain;
|
||||
history: string;
|
||||
}
|
||||
|
||||
let { domain, history }: Props = $props();
|
||||
let { class: className = "", domain, history }: Props = $props();
|
||||
|
||||
async function getDomain(id: string): Promise<Domain> {
|
||||
return await APIGetDomain(id);
|
||||
|
|
@ -54,95 +55,88 @@
|
|||
</script>
|
||||
|
||||
{#if $domains_idx[domain.id] && $thisZone}
|
||||
{#if $domains_idx[domain.id].zone_history && history === $domains_idx[domain.id].zone_history[0]}
|
||||
{#key $zoneDiffVersion}
|
||||
{#await getCachedDiffZoneSummary(domain, "@", $thisZone.id)}
|
||||
<Button
|
||||
class="mt-2 mb-3"
|
||||
size="lg"
|
||||
color="success"
|
||||
outline
|
||||
title={$t("domains.actions.propagate")}
|
||||
on:click={showDiff}
|
||||
>
|
||||
<Spinner size="sm" />
|
||||
{$t("domains.actions.propagate")}
|
||||
</Button>
|
||||
{:then zoneDiffSummary}
|
||||
<Button
|
||||
class="mt-2 mb-3"
|
||||
size="lg"
|
||||
color="success"
|
||||
outline={zoneDiffSummary && !zoneDiffSummary.nbDiffs}
|
||||
title={$t("domains.actions.propagate")}
|
||||
on:click={showDiff}
|
||||
>
|
||||
<Icon name="cloud-upload" aria-hidden="true" />
|
||||
{$t("domains.actions.propagate")}
|
||||
{#if zoneDiffSummary && zoneDiffSummary.nbDiffs}
|
||||
<small class="text-muted">({zoneDiffSummary.nbDiffs})</small>
|
||||
{/if}
|
||||
</Button>
|
||||
{:catch err}
|
||||
<p class="mb-0 text-center">
|
||||
<Icon name="exclamation-triangle" class="text-danger" />
|
||||
{err}
|
||||
</p>
|
||||
<Button
|
||||
color="danger"
|
||||
class="mt-3"
|
||||
outline
|
||||
on:click={() => ctrlDomainDelete.Open()}
|
||||
>
|
||||
<Icon name="trash" />
|
||||
{$t("domains.stop")}
|
||||
</Button>
|
||||
{/await}
|
||||
{/key}
|
||||
{:else}
|
||||
<Button
|
||||
size="lg"
|
||||
color="warning"
|
||||
title={$t("domains.actions.rollback")}
|
||||
on:click={showDiff}
|
||||
>
|
||||
<Icon name="cloud-upload" aria-hidden="true" />
|
||||
{$t("domains.actions.rollback")}
|
||||
</Button>
|
||||
<p class="mt-2 mb-1 text-center">
|
||||
{#await getDomain(domain.id)}
|
||||
Chargement des informations de l'historique
|
||||
{:then domain}
|
||||
{#if domain.zone_meta && domain.zone_meta[history]}
|
||||
{@const history_meta = domain.zone_meta[history]}
|
||||
<span class="d-block text-truncate">
|
||||
{#if history_meta.published}
|
||||
Publiée le
|
||||
{new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "long",
|
||||
timeStyle: "long",
|
||||
}).format(new Date(history_meta.published))}
|
||||
{:else if history_meta.commit_date}
|
||||
Enregistrée le
|
||||
{new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "long",
|
||||
timeStyle: "long",
|
||||
}).format(new Date(history_meta.commit_date))}
|
||||
{:else}
|
||||
Dernière modification le
|
||||
{new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "long",
|
||||
timeStyle: "long",
|
||||
}).format(new Date(history_meta.last_modified))}
|
||||
<div class="d-flex flex-column {className}">
|
||||
{#if $domains_idx[domain.id].zone_history && history === $domains_idx[domain.id].zone_history[0]}
|
||||
{#key $zoneDiffVersion}
|
||||
{#await getCachedDiffZoneSummary(domain, "@", $thisZone.id)}
|
||||
<Button
|
||||
color="primary"
|
||||
outline
|
||||
title={$t("domains.actions.propagate")}
|
||||
on:click={showDiff}
|
||||
>
|
||||
<Spinner size="sm" />
|
||||
{$t("domains.actions.propagate")}
|
||||
</Button>
|
||||
{:then zoneDiffSummary}
|
||||
<Button
|
||||
color="primary"
|
||||
outline={zoneDiffSummary && !zoneDiffSummary.nbDiffs}
|
||||
title={$t("domains.actions.propagate")}
|
||||
on:click={showDiff}
|
||||
>
|
||||
<Icon name="cloud-upload" aria-hidden="true" />
|
||||
{$t("domains.actions.propagate")}
|
||||
{#if zoneDiffSummary && zoneDiffSummary.nbDiffs}
|
||||
<small class="text-muted">({zoneDiffSummary.nbDiffs})</small>
|
||||
{/if}
|
||||
</span>
|
||||
{#if history_meta.commit_message}
|
||||
<span class="d-block text-truncate" title={history_meta.commit_message}>
|
||||
{history_meta.commit_message}
|
||||
</Button>
|
||||
{:catch err}
|
||||
<p class="mb-0 text-center">
|
||||
<Icon name="exclamation-triangle" class="text-danger" />
|
||||
{err}
|
||||
</p>
|
||||
<Button
|
||||
color="danger"
|
||||
class="mt-3"
|
||||
outline
|
||||
on:click={() => ctrlDomainDelete.Open()}
|
||||
>
|
||||
<Icon name="trash" />
|
||||
{$t("domains.stop")}
|
||||
</Button>
|
||||
{/await}
|
||||
{/key}
|
||||
{:else}
|
||||
<Button color="warning" title={$t("domains.actions.rollback")} on:click={showDiff}>
|
||||
<Icon name="cloud-upload" aria-hidden="true" />
|
||||
{$t("domains.actions.rollback")}
|
||||
</Button>
|
||||
<p class="mt-2 mb-1 text-center">
|
||||
{#await getDomain(domain.id)}
|
||||
Chargement des informations de l'historique
|
||||
{:then domain}
|
||||
{#if domain.zone_meta && domain.zone_meta[history]}
|
||||
{@const history_meta = domain.zone_meta[history]}
|
||||
<span class="d-block text-truncate">
|
||||
{#if history_meta.published}
|
||||
Publiée le
|
||||
{new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "long",
|
||||
timeStyle: "long",
|
||||
}).format(new Date(history_meta.published))}
|
||||
{:else if history_meta.commit_date}
|
||||
Enregistrée le
|
||||
{new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "long",
|
||||
timeStyle: "long",
|
||||
}).format(new Date(history_meta.commit_date))}
|
||||
{:else}
|
||||
Dernière modification le
|
||||
{new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "long",
|
||||
timeStyle: "long",
|
||||
}).format(new Date(history_meta.last_modified))}
|
||||
{/if}
|
||||
</span>
|
||||
{#if history_meta.commit_message}
|
||||
<span class="d-block text-truncate" title={history_meta.commit_message}>
|
||||
{history_meta.commit_message}
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
{/await}
|
||||
</p>
|
||||
{/if}
|
||||
{/await}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue