mirror of
https://github.com/hansjone/netx.git
synced 2026-10-15 18:23:18 +08:00
Compare template editor: compact field table, nav matches pane height.
- Value map collapses to a "+ / N 条" toggle that expands a detail row, instead of a scope select + textarea on every field row. - Unused mode/tolerance/normalize cells show "—" instead of disabled inputs; the not_worse rank input moves into the tolerance column. - Key/compare rows get a left accent; sheet options sit in one row with hints moved to tooltips. - Sheet nav stretches to the pane height and scrolls its own list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
51cfb41237
commit
e8f77440ca
5 changed files with 96 additions and 42 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { Button, Input, Modal } from "@heroui/react";
|
||||
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||
import { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||
import type { KeyboardEvent as ReactKeyboardEvent } from "react";
|
||||
import {
|
||||
parseTemplateImport, parseIfaceNormText, formatIfaceNormText, parseValueMapText, formatValueMapText,
|
||||
|
|
@ -639,16 +639,13 @@ const FILTER_OPS = [
|
|||
|
||||
/** Value-map editor for one field: text is parsed on blur so half-typed lines never clobber the rule. */
|
||||
function ValueMapCell({
|
||||
field, value, scope, onScope, onCommit, rank, onRank, showRank, t,
|
||||
field, value, scope, onScope, onCommit, t,
|
||||
}: {
|
||||
field: string;
|
||||
value: Record<string, string>;
|
||||
scope: Side;
|
||||
onScope: (s: Side) => void;
|
||||
onCommit: (map: Record<string, string>) => void;
|
||||
rank: string[];
|
||||
onRank: (rank: string[]) => void;
|
||||
showRank: boolean;
|
||||
t: (k: string, vars?: Record<string, string | number>) => string;
|
||||
}) {
|
||||
const external = formatValueMapText(value);
|
||||
|
|
@ -660,14 +657,6 @@ function ValueMapCell({
|
|||
}, [external, scope]);
|
||||
return (
|
||||
<div className="ct-valuemap">
|
||||
{showRank ? (
|
||||
<Input
|
||||
aria-label={`${field} ${t("bizCompare.rankLabel")}`}
|
||||
placeholder={t("bizCompare.rankPlaceholder")}
|
||||
value={rank.join(",")}
|
||||
onChange={(e) => onRank(e.target.value.split(",").map((x) => x.trim()).filter(Boolean))}
|
||||
/>
|
||||
) : null}
|
||||
<select
|
||||
className="mt-select"
|
||||
aria-label={`${field} ${t("bizCompare.valueMapScope")}`}
|
||||
|
|
@ -682,8 +671,9 @@ function ValueMapCell({
|
|||
className={`bs-cmp-mapping__editor ct-valuemap__text${error ? " is-invalid" : ""}`}
|
||||
aria-label={`${field} ${t("bizCompare.valueMap")}`}
|
||||
placeholder={t("bizCompare.valueMapPlaceholder")}
|
||||
rows={2}
|
||||
rows={3}
|
||||
spellCheck={false}
|
||||
autoFocus
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
onBlur={() => {
|
||||
|
|
@ -899,6 +889,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
const [tplSheets, setTplSheets] = useState<MetricSheet[]>([]);
|
||||
const [tplSheetIdx, setTplSheetIdx] = useState(0);
|
||||
const [valueMapScope, setValueMapScope] = useState<Record<string, Side>>({});
|
||||
const [vmOpen, setVmOpen] = useState<string | null>(null);
|
||||
const [tplPaneTab, setTplPaneTab] = useState<"fields" | "filters">("fields");
|
||||
const [showMetricPicker, setShowMetricPicker] = useState(true);
|
||||
|
||||
|
|
@ -1618,6 +1609,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
setTplSheetIdx(0);
|
||||
setTplPaneTab("fields");
|
||||
setValueMapScope({});
|
||||
setVmOpen(null);
|
||||
setShowMetricPicker(true);
|
||||
setTplOpen(true);
|
||||
};
|
||||
|
|
@ -1633,6 +1625,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
setTplSheetIdx(0);
|
||||
setTplPaneTab("fields");
|
||||
setValueMapScope({});
|
||||
setVmOpen(null);
|
||||
setShowMetricPicker(!sheets.length);
|
||||
setTplOpen(true);
|
||||
};
|
||||
|
|
@ -2909,6 +2902,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
className={`ct-editor__nav-item${tplSheetIdx === i ? " is-active" : ""}`}
|
||||
onClick={() => {
|
||||
setTplSheetIdx(i);
|
||||
setVmOpen(null);
|
||||
setTplPaneTab("fields");
|
||||
}}
|
||||
>
|
||||
|
|
@ -2998,21 +2992,21 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<FieldSelect label={t("bizCompare.portPolicy")} value={activeTplSheet.ignore_port_changes == null ? "auto" : activeTplSheet.ignore_port_changes ? "ignore" : "strict"} onChange={(e) => updateActiveSheet({ignore_port_changes: e.target.value === "auto" ? null : e.target.value === "ignore"})} hint={t("bizCompare.portPolicyHint")}>
|
||||
<option value="auto">{t("bizCompare.portPolicyAuto")}</option><option value="strict">{t("bizCompare.portPolicyStrict")}</option><option value="ignore">{t("bizCompare.portPolicyIgnore")}</option>
|
||||
</FieldSelect>
|
||||
<div className="ct-sheet-options">
|
||||
<FieldSelect label={t("bizCompare.unmappedPortPolicy")} value={activeTplSheet.unmapped_port_policy || "by_name"} hint={t("bizCompare.unmappedPortPolicyHint")}
|
||||
<FieldSelect label={t("bizCompare.portPolicy")} title={t("bizCompare.portPolicyHint")} value={activeTplSheet.ignore_port_changes == null ? "auto" : activeTplSheet.ignore_port_changes ? "ignore" : "strict"} onChange={(e) => updateActiveSheet({ignore_port_changes: e.target.value === "auto" ? null : e.target.value === "ignore"})}>
|
||||
<option value="auto">{t("bizCompare.portPolicyAuto")}</option><option value="strict">{t("bizCompare.portPolicyStrict")}</option><option value="ignore">{t("bizCompare.portPolicyIgnore")}</option>
|
||||
</FieldSelect>
|
||||
<FieldSelect label={t("bizCompare.unmappedPortPolicy")} title={t("bizCompare.unmappedPortPolicyHint")} value={activeTplSheet.unmapped_port_policy || "by_name"}
|
||||
onChange={(e) => updateActiveSheet({ unmapped_port_policy: e.target.value as "by_name" | "ignore_port" })}>
|
||||
<option value="by_name">{t("bizCompare.unmappedByName")}</option>
|
||||
<option value="ignore_port">{t("bizCompare.unmappedIgnorePort")}</option>
|
||||
</FieldSelect>
|
||||
<FieldSelect label={t("bizCompare.duplicatePairing")} value={activeTplSheet.duplicate_pairing || "sorted"} hint={t("bizCompare.duplicatePairingHint")}
|
||||
<FieldSelect label={t("bizCompare.duplicatePairing")} title={t("bizCompare.duplicatePairingHint")} value={activeTplSheet.duplicate_pairing || "sorted"}
|
||||
onChange={(e) => updateActiveSheet({ duplicate_pairing: e.target.value as "sorted" | "ordered" })}>
|
||||
<option value="sorted">{t("bizCompare.pairSorted")}</option>
|
||||
<option value="ordered">{t("bizCompare.pairOrdered")}</option>
|
||||
</FieldSelect>
|
||||
<label className="ct-sheet-options__check">
|
||||
<label className="ct-sheet-options__check" title={t("bizCompare.builtinVendorCanonicalHint")}>
|
||||
<input type="checkbox" checked={activeTplSheet.builtin_vendor_canonical !== false}
|
||||
onChange={(e) => updateActiveSheet({ builtin_vendor_canonical: e.target.checked ? undefined : false })} />
|
||||
<span>{t("bizCompare.builtinVendorCanonical")}</span>
|
||||
|
|
@ -3027,7 +3021,6 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
/>
|
||||
)) : (
|
||||
<>
|
||||
<p className="muted ct-field-hint">{t("bizCompare.fieldsHintShort")}</p>
|
||||
<div className="pt-list-table-wrap ct-field-table-wrap">
|
||||
<table className="data-table pt-list-table ct-field-table">
|
||||
<thead>
|
||||
|
|
@ -3035,7 +3028,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
<th>{t("bizCompare.field")}</th>
|
||||
<th title={t("bizCompare.keyFields")}>{t("bizCompare.keyFields")}</th>
|
||||
<th title={t("bizCompare.ifaceFields")}>{t("bizCompare.ifaceFields")}</th>
|
||||
<th title={t("bizCompare.compareFields")}>{t("bizCompare.compareFields")}</th>
|
||||
<th title={t("bizCompare.fieldsHintShort")}>{t("bizCompare.compareFields")}</th>
|
||||
<th>{t("bizCompare.compareMode")}</th>
|
||||
<th>{t("bizCompare.tolerance")}</th>
|
||||
<th>{t("bizCompare.displayField")}</th>
|
||||
|
|
@ -3056,8 +3049,11 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
const norm = rawNorm === "strip" ? "none" : rawNorm;
|
||||
const needsTol = ["numeric", "percent", "numeric_min", "numeric_max"].includes(cmpMode);
|
||||
const vmScope = valueMapScope[f.name] || "both";
|
||||
const vmCount = (["both", "before", "after"] as Side[]).reduce((n, sc) => n + Object.keys(valueMapFor(activeTplSheet, f.name, sc)).length, 0);
|
||||
const vmExpanded = vmOpen === f.name;
|
||||
return (
|
||||
<tr key={f.name}>
|
||||
<Fragment key={f.name}>
|
||||
<tr className={`${isKey ? "is-key" : isCompare ? "is-compare" : ""}${vmExpanded ? " is-expanded" : ""}`}>
|
||||
<td>
|
||||
<code className="ct-field-name">{f.name}</code>
|
||||
</td>
|
||||
|
|
@ -3111,11 +3107,11 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
/>
|
||||
</td>
|
||||
<td>
|
||||
{!isCompare ? <span className="ct-na">—</span> : (
|
||||
<select
|
||||
className="mt-select"
|
||||
value={cmpMode === "ignore" ? "eq" : cmpMode}
|
||||
aria-label={`${f.name} ${t("bizCompare.compareMode")}`}
|
||||
disabled={!isCompare}
|
||||
onChange={(e) => {
|
||||
const mode = e.target.value;
|
||||
updateActiveSheet({
|
||||
|
|
@ -3134,8 +3130,18 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
<option value="numeric_min">{t("bizCompare.modeNumericMin")}</option>
|
||||
<option value="numeric_max">{t("bizCompare.modeNumericMax")}</option>
|
||||
</select>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{isCompare && cmpMode === "not_worse" ? (
|
||||
<Input
|
||||
aria-label={`${f.name} ${t("bizCompare.rankLabel")}`}
|
||||
placeholder={t("bizCompare.rankPlaceholder")}
|
||||
title={t("bizCompare.rankLabel")}
|
||||
value={(rule.rank || []).join(",")}
|
||||
onChange={(e) => updateActiveSheet({ field_rules: upsertFieldRule(activeTplSheet, f.name, { compare: "not_worse", rank: e.target.value.split(",").map((x) => x.trim()).filter(Boolean) }) })}
|
||||
/>
|
||||
) : !isCompare || !needsTol ? <span className="ct-na">—</span> : (
|
||||
<Input
|
||||
type="number"
|
||||
min={0}
|
||||
|
|
@ -3149,7 +3155,6 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
: ""
|
||||
}
|
||||
placeholder={["percent", "numeric_min", "numeric_max"].includes(cmpMode) ? "%" : ""}
|
||||
disabled={!isCompare || !needsTol}
|
||||
onChange={(e) => {
|
||||
const raw = e.target.value.trim();
|
||||
const tol = raw === "" ? undefined : Number(raw);
|
||||
|
|
@ -3163,6 +3168,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
|
|
@ -3182,11 +3188,11 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
/>
|
||||
</td>
|
||||
<td>
|
||||
{!isCompare && !isKey ? <span className="ct-na">—</span> : (
|
||||
<select
|
||||
className="mt-select"
|
||||
value={norm}
|
||||
aria-label={`${f.name} ${t("bizCompare.normalizeField")}`}
|
||||
disabled={!isCompare && !isKey}
|
||||
onChange={(e) =>
|
||||
updateActiveSheet({
|
||||
field_rules: upsertFieldRule(activeTplSheet, f.name, {
|
||||
|
|
@ -3203,21 +3209,35 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
|||
{t("bizCompare.normalizeEmpty")}
|
||||
</option>
|
||||
</select>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<ValueMapCell
|
||||
field={f.name}
|
||||
t={t}
|
||||
scope={vmScope}
|
||||
onScope={(sc) => setValueMapScope((prev) => ({ ...prev, [f.name]: sc }))}
|
||||
value={valueMapFor(activeTplSheet, f.name, vmScope)}
|
||||
onCommit={(map) => updateActiveSheet({ field_rules: setValueMapFor(activeTplSheet, f.name, vmScope, map) })}
|
||||
showRank={cmpMode === "not_worse"}
|
||||
rank={rule.rank || []}
|
||||
onRank={(rank) => updateActiveSheet({ field_rules: upsertFieldRule(activeTplSheet, f.name, { compare: "not_worse", rank }) })}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className={`ct-vm-toggle${vmCount ? " has-value" : ""}`}
|
||||
aria-expanded={vmExpanded}
|
||||
aria-label={`${f.name} ${t("bizCompare.valueMapEdit")}`}
|
||||
onClick={() => setVmOpen(vmExpanded ? null : f.name)}
|
||||
>
|
||||
{vmCount ? t("bizCompare.valueMapCount", { n: String(vmCount) }) : "+"}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{vmExpanded ? (
|
||||
<tr className="ct-field-table__detail">
|
||||
<td colSpan={9}>
|
||||
<ValueMapCell
|
||||
field={f.name}
|
||||
t={t}
|
||||
scope={vmScope}
|
||||
onScope={(sc) => setValueMapScope((prev) => ({ ...prev, [f.name]: sc }))}
|
||||
value={valueMapFor(activeTplSheet, f.name, vmScope)}
|
||||
onCommit={(map) => updateActiveSheet({ field_rules: setValueMapFor(activeTplSheet, f.name, vmScope, map) })}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
) : null}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
{!activeTplFields.length ? (
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ const bizCompare = {
|
|||
valueMap: "Value map",
|
||||
valueMapScope: "value map scope",
|
||||
valueMapPlaceholder: "One per line: source,canonical\nestab,established",
|
||||
valueMapEdit: "edit value map",
|
||||
valueMapCount: "{{n}} rules",
|
||||
rankLabel: "best→worst",
|
||||
rankPlaceholder: "up,down (earlier is better)",
|
||||
modeNotWorse: "Not worse",
|
||||
|
|
@ -153,7 +155,8 @@ const bizCompare = {
|
|||
pairSorted: "Pair by sorted value (recommended)",
|
||||
pairOrdered: "Pair by collection order (legacy)",
|
||||
duplicatePairingHint: "When one key has several rows (ECMP, multipath), CLI ordering changes must not create false differences.",
|
||||
builtinVendorCanonical: "Built-in per-vendor interface names (GigabitEthernet↔GE …)",
|
||||
builtinVendorCanonical: "Built-in vendor interface names",
|
||||
builtinVendorCanonicalHint: "Unify vendor interface names (GigabitEthernet↔GE …)",
|
||||
mappingNeedBatches: "Pick the before and after batches first",
|
||||
preflight: {
|
||||
"run": "Validate mapping",
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ const bizCompare = {
|
|||
valueMap: "值映射",
|
||||
valueMapScope: "值映射范围",
|
||||
valueMapPlaceholder: "每行:原值,规范值\nestab,established",
|
||||
valueMapEdit: "编辑值映射",
|
||||
valueMapCount: "{{n}} 条",
|
||||
rankLabel: "好→坏顺序",
|
||||
rankPlaceholder: "up,down(靠前更好)",
|
||||
modeNotWorse: "不劣于",
|
||||
|
|
@ -152,7 +154,8 @@ const bizCompare = {
|
|||
pairSorted: "按取值排序后配对(推荐)",
|
||||
pairOrdered: "按采集顺序配对(旧行为)",
|
||||
duplicatePairingHint: "ECMP、多路径等同一个键出现多行时,CLI 输出顺序变化不应产生假差异。",
|
||||
builtinVendorCanonical: "启用内置厂商接口名称统一(GigabitEthernet↔GE 等)",
|
||||
builtinVendorCanonical: "内置厂商接口名称统一",
|
||||
builtinVendorCanonicalHint: "GigabitEthernet↔GE 等厂商接口名自动统一",
|
||||
mappingNeedBatches: "请先选择前后批次",
|
||||
preflight: {
|
||||
"run": "校验映射",
|
||||
|
|
|
|||
|
|
@ -905,7 +905,9 @@
|
|||
.bs-template-editor .ct-editor__norm summary { cursor: pointer; color: #c4ddfa; }
|
||||
.bs-template-editor .ct-editor__norm-area { width: 100%; max-width: 100%; resize: vertical; font: 12px/1.6 ui-monospace, Consolas, monospace; }
|
||||
.bs-template-editor .ct-editor__main { grid-template-columns: 190px minmax(0, 1fr); min-width: 0; }
|
||||
.bs-template-editor .ct-editor__nav { max-height: 560px; }
|
||||
/* Nav takes the pane's height (contain: size keeps it from driving the row) and scrolls its own list. */
|
||||
.bs-template-editor .ct-editor__nav { max-height: none; contain: size; overflow: hidden; }
|
||||
.bs-template-editor .ct-editor__nav-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
|
||||
.bs-template-editor .ct-editor__nav-item { border-radius: 3px; font-size: 12px; }
|
||||
.bs-template-editor .ct-editor__nav-item.is-active { background: #1b2c43; border-color: #526f94; }
|
||||
.bs-template-editor .ct-editor__meta { font: 11px/1.6 ui-monospace, Consolas, monospace; overflow-wrap: anywhere; }
|
||||
|
|
@ -914,7 +916,29 @@
|
|||
.bs-template-editor .ct-field-table { min-width: 800px; }
|
||||
.bs-template-editor .ct-field-table td { font-size: 12px; }
|
||||
.bs-template-editor .ct-field-table th { font-size: 11px; }
|
||||
.bs-template-editor .ct-field-table .input { max-width: 100px; }
|
||||
.bs-template-editor .ct-field-table .input { max-width: 110px; height: 28px; padding: 2px 8px; font-size: 12px; }
|
||||
.bs-template-editor .ct-field-table td { padding-top: 5px; padding-bottom: 5px; height: 38px; }
|
||||
.bs-template-editor .ct-field-table .mt-select { width: 112px; height: 28px; padding: 2px 6px; }
|
||||
.bs-template-editor .ct-field-table input[type="checkbox"] { width: 15px; height: 15px; cursor: pointer; }
|
||||
.bs-template-editor .ct-field-table input[type="checkbox"]:disabled { cursor: default; opacity: 0.45; }
|
||||
.bs-template-editor .ct-field-table tbody tr > td:first-child { box-shadow: inset 2px 0 0 transparent; }
|
||||
.bs-template-editor .ct-field-table tbody tr.is-key > td:first-child { box-shadow: inset 2px 0 0 #6f8db3; }
|
||||
.bs-template-editor .ct-field-table tbody tr.is-compare > td:first-child { box-shadow: inset 2px 0 0 var(--nx-accent); }
|
||||
.bs-template-editor .ct-field-table tbody tr.is-compare > td { background: rgb(var(--nx-accent-rgb) / 0.05); }
|
||||
.bs-template-editor .ct-field-table tbody tr.is-expanded > td { border-bottom-color: transparent; }
|
||||
.bs-template-editor .ct-na { color: var(--nx-text-muted); opacity: 0.6; }
|
||||
.bs-template-editor .ct-vm-toggle { min-width: 52px; height: 26px; padding: 0 10px; border: 1px dashed var(--nx-line); border-radius: 13px; background: transparent; color: var(--nx-text-muted); font-size: 12px; cursor: pointer; }
|
||||
.bs-template-editor .ct-vm-toggle:hover { border-color: #526f94; color: #9cc7f7; }
|
||||
.bs-template-editor .ct-vm-toggle.has-value { border-style: solid; border-color: #3d5878; background: #16263a; color: #9cc7f7; }
|
||||
.bs-template-editor .ct-vm-toggle[aria-expanded="true"] { border-style: solid; border-color: var(--nx-accent); color: #9cc7f7; }
|
||||
.bs-template-editor .ct-field-table__detail > td { background: var(--nx-surface-1); padding: 8px 12px 10px; text-align: left !important; white-space: normal !important; height: auto; }
|
||||
.bs-template-editor .ct-field-table__detail .ct-valuemap { flex-direction: row; align-items: flex-start; gap: 8px; }
|
||||
.bs-template-editor .ct-field-table__detail .ct-valuemap > .mt-select { flex: 0 0 112px; }
|
||||
.bs-template-editor .ct-field-table__detail .ct-valuemap__text { flex: 1 1 auto; min-height: 64px; max-width: 520px; resize: vertical; font: 12px/1.6 ui-monospace, Consolas, monospace; }
|
||||
.bs-template-editor .ct-sheet-options { display: grid; grid-template-columns: repeat(3, minmax(0, 220px)) auto; align-items: end; gap: 10px 14px; padding: 10px 12px; border: 1px solid var(--nx-line); border-radius: 4px; background: var(--nx-surface-1); }
|
||||
.bs-template-editor .ct-sheet-options .ui-field__label { font-size: 11px; color: var(--nx-text-muted); }
|
||||
.bs-template-editor .ct-sheet-options .ui-field__select { height: 30px; font-size: 12px; }
|
||||
.bs-template-editor .ct-sheet-options__check { height: 30px; color: var(--nx-text-muted); white-space: nowrap; }
|
||||
.bs-template-editor .ct-filter-row { min-width: 0; }
|
||||
.bs-template-editor .ct-filter-row .mt-select { min-width: 0; max-width: 100%; }
|
||||
.bs-template-editor .ct-complex-filters pre { max-height: 360px; overflow: auto; background: var(--nx-surface-1); border: 1px solid var(--nx-line); border-radius: 4px; padding: 10px; font: 11px/1.6 ui-monospace, Consolas, monospace; }
|
||||
|
|
@ -925,7 +949,8 @@
|
|||
.bs-template-editor .ct-editor__main { grid-template-columns: minmax(0, 1fr); }
|
||||
.bs-template-editor .ct-editor__nav-list { flex-direction: row; overflow-x: auto; }
|
||||
.bs-template-editor .ct-editor__nav-item { flex: 0 0 160px; }
|
||||
.bs-template-editor .ct-editor__nav { max-height: none; }
|
||||
.bs-template-editor .ct-editor__nav { max-height: none; contain: none; }
|
||||
.bs-template-editor .ct-sheet-options { grid-template-columns: minmax(0, 1fr); }
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.bs-template-editor .ct-editor__pane { padding: 10px; }
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ try {
|
|||
await stateRow.locator('input[type="checkbox"]').nth(2).check();
|
||||
await editor().getByLabel("state 方式", { exact: true }).selectOption("not_worse");
|
||||
await editor().getByLabel("state 好→坏顺序", { exact: true }).fill("up,down");
|
||||
await editor().getByRole("button", { name: "state 编辑值映射", exact: true }).click();
|
||||
await editor().getByLabel("state 值映射", { exact: true }).fill("estab,established\n*down,down");
|
||||
await editor().getByLabel("state 值映射", { exact: true }).blur();
|
||||
await editor().getByLabel("state 值映射范围", { exact: true }).selectOption("before");
|
||||
|
|
@ -185,6 +186,8 @@ try {
|
|||
// ... and come back unchanged when the template is opened again.
|
||||
await openEditor();
|
||||
await editor().getByRole("tab", { name: /^字段规则/ }).click();
|
||||
assert.equal(await editor().getByRole("button", { name: "state 编辑值映射", exact: true }).textContent(), "3 条");
|
||||
await editor().getByRole("button", { name: "state 编辑值映射", exact: true }).click();
|
||||
assert.equal(await editor().getByLabel("state 值映射", { exact: true }).inputValue(), "estab,established\n*down,down");
|
||||
assert.equal(await editor().getByLabel("未映射端口", { exact: true }).inputValue(), "ignore_port");
|
||||
await page.keyboard.press("Escape");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue