Show network config content in a dark modal dialog.

Move the inline config viewer into the shared modal chrome so viewing stays consistent with other network management dialogs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-05 09:50:39 +08:00
parent 54747d9afb
commit 5a77e36839
2 changed files with 77 additions and 24 deletions

View file

@ -8100,25 +8100,61 @@ pre {
color: #94a3b8;
}
.network-main .nm-config-view {
margin-top: 14px;
padding-top: 14px;
border-top: 1px solid #e2e8f0;
.nm-config-modal {
display: flex;
flex-direction: column;
width: min(960px, 100%);
max-height: min(90vh, 840px);
overflow: hidden;
}
.network-main .nm-config-view textarea {
.nm-config-modal__head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 12px;
}
.nm-config-modal__title h3 {
margin: 0 0 4px;
}
.nm-config-modal__title .muted {
margin: 0;
font-size: 13px;
}
.nm-config-modal__actions {
flex: 0 0 auto;
}
.nm-config-modal__tabs {
margin-bottom: 10px;
}
.nm-config-modal__body {
flex: 1 1 auto;
width: 100%;
min-height: 420px;
min-height: min(52vh, 480px);
margin: 0;
padding: 12px 14px;
border: 1px solid #e2e8f0;
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 8px;
background: #0b1220;
color: #e2e8f0;
font-family: ui-monospace, SFMono-Regular, Consolas, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
background: #0b1220 !important;
color: #e2e8f0 !important;
font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
font-size: 12px;
line-height: 1.45;
resize: vertical;
overflow: auto;
}
.nm-config-modal__meta {
margin: 10px 0 0;
font-size: 12px;
word-break: break-all;
}
.network-main:has(.topo-page),

View file

@ -216,17 +216,29 @@ export function NetworkConfigsPage() {
</button>
</div>
</div>
</div>
{selected ? (
<div className="nm-config-view">
<div className="panel__toolbar">
<h3>
{detail?.ne_name || selected.id}{" "}
<span className="muted">
({selected.source} / {detail?.ne_ip || "—"})
</span>
</h3>
<div className="btn-row">
{selected ? (
<div
className="modal-backdrop"
role="presentation"
onClick={() => setSelected(null)}
>
<div
className="modal modal--wide nm-config-modal"
role="dialog"
aria-modal="true"
aria-label={t("networkConfigs.view")}
onClick={(e) => e.stopPropagation()}
>
<div className="nm-config-modal__head">
<div className="nm-config-modal__title">
<h3>{detail?.ne_name || selected.id}</h3>
<p className="muted">
{selected.source} · {detail?.ne_ip || "—"} · {detail?.vendor || "—"}
</p>
</div>
<div className="btn-row nm-config-modal__actions">
<button
type="button"
disabled={Boolean(exporting)}
@ -254,9 +266,11 @@ export function NetworkConfigsPage() {
</button>
</div>
</div>
{detailQuery.isLoading ? <p className="muted">{t("common.refreshing")}</p> : null}
{showAlt ? (
<div className="btn-row" style={{ marginBottom: 8 }}>
<div className="btn-row nm-config-modal__tabs">
<button
type="button"
className={tab === "primary" ? "btn-primary" : undefined}
@ -273,17 +287,20 @@ export function NetworkConfigsPage() {
</button>
</div>
) : null}
<textarea
className="nm-config-modal__body"
readOnly
spellCheck={false}
value={tab === "alt" ? detail?.config_alt_text || "" : detail?.config_text || ""}
/>
<p className="muted" style={{ marginTop: 8 }}>
<p className="muted nm-config-modal__meta">
SHA-256: {tab === "alt" ? detail?.config_alt_sha256 : detail?.config_sha256} ·{" "}
{fmtBytes(tab === "alt" ? detail?.plain_alt_size || 0 : detail?.plain_size || 0)}
</p>
</div>
) : null}
</div>
</div>
) : null}
</section>
);
}