mirror of
https://github.com/hansjone/netx.git
synced 2026-10-12 17:53:21 +08:00
Fix compare board scroll sticky headers and CSS fullscreen interactions.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
28aa7cd87e
commit
83be9110c8
2 changed files with 238 additions and 135 deletions
|
|
@ -11279,9 +11279,26 @@ html.login-page--paused .login-page__flare {
|
||||||
max-width: min(96vw, 1600px) !important;
|
max-width: min(96vw, 1600px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-board-modal .app-heroui-modal__dialog [data-slot="modal-body"],
|
.bs-cmp-board-modal .app-heroui-modal__dialog [data-slot="modal-body"].bs-cmp-job-body,
|
||||||
.bs-cmp-board-modal .app-heroui-modal__dialog .modal__body {
|
.bs-cmp-board-modal .app-heroui-modal__dialog .modal__body.bs-cmp-job-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
max-height: min(90vh, 980px);
|
max-height: min(90vh, 980px);
|
||||||
|
min-height: min(64vh, 680px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-board-modal .bs-cmp-job-body > .nm-config-modal__tabs {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-board-modal .app-heroui-modal__dialog [data-slot="modal-body"].bs-cmp-job-body > .bs-cmp-board,
|
||||||
|
.bs-cmp-board-modal .app-heroui-modal__dialog .modal__body.bs-cmp-job-body > .bs-cmp-board,
|
||||||
|
.bs-cmp-board-modal .bs-cmp-job-body > .bs-cmp-board {
|
||||||
|
flex: 1 1 auto !important;
|
||||||
|
flex-shrink: 1 !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-board {
|
.bs-cmp-board {
|
||||||
|
|
@ -11304,16 +11321,28 @@ html.login-page--paused .login-page__flare {
|
||||||
rgba(8, 13, 24, 0.4);
|
rgba(8, 13, 24, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-board.is-fullscreen,
|
/* CSS immersive board — avoids native Fullscreen + modal focus-trap breaking clicks */
|
||||||
.bs-cmp-board:fullscreen {
|
.bs-cmp-board.is-fullscreen {
|
||||||
--bs-cmp-surface: rgba(15, 23, 42, 0.92);
|
--bs-cmp-surface: rgba(15, 23, 42, 0.92);
|
||||||
background: #0b1220;
|
position: fixed;
|
||||||
color: #e2e8f0;
|
inset: 0;
|
||||||
|
z-index: 12000;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
max-height: 100vh;
|
||||||
|
min-height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-height: 100%;
|
background: #0b1220;
|
||||||
height: 100%;
|
color: #e2e8f0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:has(.bs-cmp-board.is-fullscreen) {
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-board__toolbar {
|
.bs-cmp-board__toolbar {
|
||||||
|
|
@ -11478,6 +11507,7 @@ html.login-page--paused .login-page__flare {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
|
overflow: hidden;
|
||||||
transition: grid-template-columns 0.18s ease;
|
transition: grid-template-columns 0.18s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -11726,6 +11756,12 @@ html.login-page--paused .login-page__flare {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-main > .pt-list-pager,
|
||||||
|
.bs-cmp-main > .pager {
|
||||||
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run-level overview: never changes when switching sheets */
|
/* Run-level overview: never changes when switching sheets */
|
||||||
|
|
@ -12075,21 +12111,28 @@ html.login-page--paused .login-page__flare {
|
||||||
|
|
||||||
.bs-cmp-result-table {
|
.bs-cmp-result-table {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
min-height: 240px;
|
min-height: 0;
|
||||||
max-height: none;
|
max-height: none;
|
||||||
|
overflow: auto;
|
||||||
border-color: var(--bs-cmp-border);
|
border-color: var(--bs-cmp-border);
|
||||||
background: rgba(8, 13, 24, 0.4);
|
background: rgba(8, 13, 24, 0.4);
|
||||||
transition: opacity 0.15s ease;
|
transition: opacity 0.15s ease;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-result-table.bs-sheet-table {
|
||||||
|
max-height: none;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-result-table.is-loading {
|
.bs-cmp-result-table.is-loading {
|
||||||
opacity: 0.55;
|
opacity: 0.55;
|
||||||
pointer-events: none;
|
/* Keep header/filters clickable; only mute row hit-testing via opacity cue */
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-board.is-fullscreen .bs-cmp-result-table,
|
.bs-cmp-board.is-fullscreen .bs-cmp-result-table {
|
||||||
.bs-cmp-board:fullscreen .bs-cmp-result-table {
|
|
||||||
max-height: none;
|
max-height: none;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
|
@ -12154,19 +12197,59 @@ html.login-page--paused .login-page__flare {
|
||||||
.bs-cmp-diff-table {
|
.bs-cmp-diff-table {
|
||||||
border-collapse: separate;
|
border-collapse: separate;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
|
--bs-cmp-group-h: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-diff-table thead th {
|
.bs-cmp-diff-table thead th {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
background: rgba(15, 23, 42, 0.98);
|
background: rgba(15, 23, 42, 0.98);
|
||||||
color: #94a3b8;
|
color: #94a3b8;
|
||||||
box-shadow: 0 1px 0 rgba(148, 163, 184, 0.22);
|
box-shadow: 0 1px 0 rgba(148, 163, 184, 0.22);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 7px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-diff-table thead tr.bs-cmp-group-row th {
|
||||||
|
top: 0;
|
||||||
|
z-index: 3;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
padding: 5px 10px;
|
||||||
|
height: var(--bs-cmp-group-h);
|
||||||
|
box-shadow:
|
||||||
|
0 1px 0 rgba(148, 163, 184, 0.18),
|
||||||
|
inset 0 -1px 0 rgba(148, 163, 184, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-diff-table thead tr.bs-cmp-field-row th {
|
||||||
|
top: var(--bs-cmp-group-h);
|
||||||
|
z-index: 2;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
padding: 8px 10px;
|
padding-top: 6px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-group--key {
|
||||||
|
background: rgba(37, 99, 235, 0.18) !important;
|
||||||
|
color: #93c5fd !important;
|
||||||
|
border-bottom: 2px solid rgba(59, 130, 246, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-group--compare {
|
||||||
|
background: rgba(245, 158, 11, 0.16) !important;
|
||||||
|
color: #fcd34d !important;
|
||||||
|
border-bottom: 2px solid rgba(245, 158, 11, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-group--display {
|
||||||
|
background: rgba(148, 163, 184, 0.12) !important;
|
||||||
|
color: #cbd5e1 !important;
|
||||||
|
border-bottom: 2px solid rgba(148, 163, 184, 0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-diff-table tbody td {
|
.bs-cmp-diff-table tbody td {
|
||||||
|
|
@ -12191,8 +12274,16 @@ html.login-page--paused .login-page__flare {
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-diff-table thead th.bs-cmp-sticky-kind {
|
.bs-cmp-diff-table thead th.bs-cmp-sticky-kind {
|
||||||
z-index: 3;
|
z-index: 4;
|
||||||
background: rgba(15, 23, 42, 0.98);
|
background: rgba(15, 23, 42, 0.98);
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-diff-table thead th.bs-cmp-col-fail {
|
||||||
|
z-index: 3;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-diff-table tbody tr:nth-child(even) td.bs-cmp-sticky-kind {
|
.bs-cmp-diff-table tbody tr:nth-child(even) td.bs-cmp-sticky-kind {
|
||||||
|
|
@ -12203,51 +12294,23 @@ html.login-page--paused .login-page__flare {
|
||||||
background: rgba(30, 48, 80, 0.98);
|
background: rgba(30, 48, 80, 0.98);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bs-cmp-th {
|
|
||||||
display: inline-flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 3px;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bs-cmp-th__role {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 5px;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 10px;
|
|
||||||
font-weight: 700;
|
|
||||||
line-height: 1.5;
|
|
||||||
letter-spacing: 0.02em;
|
|
||||||
min-height: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bs-cmp-th__role--spacer {
|
|
||||||
visibility: hidden;
|
|
||||||
padding: 0;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bs-cmp-th__role--key {
|
|
||||||
background: rgba(59, 130, 246, 0.2);
|
|
||||||
color: #93c5fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bs-cmp-th__role--compare {
|
|
||||||
background: rgba(245, 158, 11, 0.22);
|
|
||||||
color: #fcd34d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bs-cmp-th__role--display {
|
|
||||||
background: rgba(148, 163, 184, 0.16);
|
|
||||||
color: #cbd5e1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bs-cmp-th__name {
|
.bs-cmp-th__name {
|
||||||
color: #e2e8f0;
|
color: #e2e8f0;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bs-cmp-diff-table thead tr.bs-cmp-field-row th.bs-cmp-col-key {
|
||||||
|
background: rgba(22, 36, 66, 0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-diff-table thead tr.bs-cmp-field-row th.bs-cmp-col-compare {
|
||||||
|
background: rgba(42, 32, 16, 0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bs-cmp-diff-table thead tr.bs-cmp-field-row th.bs-cmp-col-display {
|
||||||
|
background: rgba(15, 23, 42, 0.98);
|
||||||
|
}
|
||||||
|
|
||||||
.bs-cmp-col-key {
|
.bs-cmp-col-key {
|
||||||
background: rgba(59, 130, 246, 0.05);
|
background: rgba(59, 130, 246, 0.05);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Button, Input, Modal } from "@heroui/react";
|
import { Button, Input, Modal } from "@heroui/react";
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||||
import { ListPager } from "../../components/ListPager";
|
import { ListPager } from "../../components/ListPager";
|
||||||
import { AppModalShell } from "../../components/ui/AppModalShell";
|
import { AppModalShell } from "../../components/ui/AppModalShell";
|
||||||
import { FieldSelect } from "../../components/ui/FieldSelect";
|
import { FieldSelect } from "../../components/ui/FieldSelect";
|
||||||
|
|
@ -829,6 +829,8 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
||||||
const [pagedDiffs, setPagedDiffs] = useState<DiffRow[]>([]);
|
const [pagedDiffs, setPagedDiffs] = useState<DiffRow[]>([]);
|
||||||
const [diffsLoading, setDiffsLoading] = useState(false);
|
const [diffsLoading, setDiffsLoading] = useState(false);
|
||||||
const boardRef = useRef<HTMLDivElement | null>(null);
|
const boardRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const tableScrollRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const tableScrollPosRef = useRef({ top: 0, left: 0 });
|
||||||
const [boardFs, setBoardFs] = useState(false);
|
const [boardFs, setBoardFs] = useState(false);
|
||||||
const [navCollapsed, setNavCollapsed] = useState(false);
|
const [navCollapsed, setNavCollapsed] = useState(false);
|
||||||
const tplImportRef = useRef<HTMLInputElement | null>(null);
|
const tplImportRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
|
@ -1207,24 +1209,38 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
||||||
(showFailCol ? 1 : 0) +
|
(showFailCol ? 1 : 0) +
|
||||||
resultColumns.keys.length +
|
resultColumns.keys.length +
|
||||||
Math.max(resultColumns.extras.length, 0);
|
Math.max(resultColumns.extras.length, 0);
|
||||||
useEffect(() => {
|
|
||||||
const syncFs = () => {
|
const rememberTableScroll = useCallback(() => {
|
||||||
const el = boardRef.current;
|
const wrap = tableScrollRef.current;
|
||||||
setBoardFs(Boolean(el && document.fullscreenElement === el));
|
if (!wrap) return;
|
||||||
};
|
tableScrollPosRef.current = { top: wrap.scrollTop, left: wrap.scrollLeft };
|
||||||
document.addEventListener("fullscreenchange", syncFs);
|
|
||||||
return () => document.removeEventListener("fullscreenchange", syncFs);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const toggleBoardFullscreen = async () => {
|
useEffect(() => {
|
||||||
const el = boardRef.current;
|
if (!boardFs) return;
|
||||||
if (!el) return;
|
const onKey = (e: KeyboardEvent) => {
|
||||||
try {
|
if (e.key !== "Escape") return;
|
||||||
if (document.fullscreenElement === el) await document.exitFullscreen();
|
e.preventDefault();
|
||||||
else await el.requestFullscreen();
|
e.stopPropagation();
|
||||||
} catch (e) {
|
rememberTableScroll();
|
||||||
showError(formatErr(e));
|
setBoardFs(false);
|
||||||
}
|
};
|
||||||
|
document.addEventListener("keydown", onKey, true);
|
||||||
|
return () => document.removeEventListener("keydown", onKey, true);
|
||||||
|
}, [boardFs, rememberTableScroll]);
|
||||||
|
|
||||||
|
// Keep table scroll across fullscreen enter/exit (layout swap otherwise jumps to top).
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const wrap = tableScrollRef.current;
|
||||||
|
if (!wrap) return;
|
||||||
|
const { top, left } = tableScrollPosRef.current;
|
||||||
|
wrap.scrollTop = top;
|
||||||
|
wrap.scrollLeft = left;
|
||||||
|
}, [boardFs]);
|
||||||
|
|
||||||
|
const toggleBoardFullscreen = () => {
|
||||||
|
rememberTableScroll();
|
||||||
|
setBoardFs((v) => !v);
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadRunTables = async () => {
|
const downloadRunTables = async () => {
|
||||||
|
|
@ -1689,6 +1705,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeJob = () => {
|
const closeJob = () => {
|
||||||
|
setBoardFs(false);
|
||||||
setJobId("");
|
setJobId("");
|
||||||
setRuns([]);
|
setRuns([]);
|
||||||
setRunDetail(null);
|
setRunDetail(null);
|
||||||
|
|
@ -2657,6 +2674,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
||||||
<AppModalShell
|
<AppModalShell
|
||||||
open={Boolean(jobId)}
|
open={Boolean(jobId)}
|
||||||
onClose={closeJob}
|
onClose={closeJob}
|
||||||
|
dismissible={!boardFs}
|
||||||
size={jobDetailTab === "result" ? "cover" : "lg"}
|
size={jobDetailTab === "result" ? "cover" : "lg"}
|
||||||
className={`app-heroui-modal--xl${jobDetailTab === "result" ? " bs-cmp-board-modal" : ""}`}
|
className={`app-heroui-modal--xl${jobDetailTab === "result" ? " bs-cmp-board-modal" : ""}`}
|
||||||
>
|
>
|
||||||
|
|
@ -2811,7 +2829,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
isDisabled={!runDetail}
|
isDisabled={!runDetail}
|
||||||
onPress={() => void toggleBoardFullscreen()}
|
onPress={() => toggleBoardFullscreen()}
|
||||||
>
|
>
|
||||||
{boardFs ? t("bizCompare.exitFullscreen") : t("bizCompare.fullscreen")}
|
{boardFs ? t("bizCompare.exitFullscreen") : t("bizCompare.fullscreen")}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -3020,76 +3038,98 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
ref={tableScrollRef}
|
||||||
|
onScroll={rememberTableScroll}
|
||||||
className={`pt-list-table-wrap bs-sheet-table bs-cmp-result-table${
|
className={`pt-list-table-wrap bs-sheet-table bs-cmp-result-table${
|
||||||
diffsLoading ? " is-loading" : ""
|
diffsLoading ? " is-loading" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<table className="data-table pt-list-table bs-cmp-diff-table">
|
<table className="data-table pt-list-table bs-cmp-diff-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
{(() => {
|
||||||
<th className="bs-cmp-col-kind bs-cmp-sticky-kind">
|
const keyCols = resultColumns.keys;
|
||||||
{t("bizCompare.colKind")}
|
const compareCols = resultColumns.extras.filter((f) =>
|
||||||
</th>
|
resultColumns.compareSet.has(f),
|
||||||
{showFailCol ? (
|
);
|
||||||
<th className="bs-cmp-col-fail">{t("bizCompare.colFailFields")}</th>
|
const displayCols = resultColumns.extras.filter(
|
||||||
) : null}
|
(f) => !resultColumns.compareSet.has(f),
|
||||||
{resultColumns.keys.map((k, ki) => (
|
);
|
||||||
<th key={k} className="bs-cmp-col-key">
|
const hasGroups =
|
||||||
<span className="bs-cmp-th">
|
keyCols.length + compareCols.length + displayCols.length > 0;
|
||||||
{ki === 0 ? (
|
return (
|
||||||
<span className="bs-cmp-th__role bs-cmp-th__role--key">
|
<>
|
||||||
{t("bizCompare.keyFields")}
|
{hasGroups ? (
|
||||||
</span>
|
<tr className="bs-cmp-group-row">
|
||||||
) : (
|
<th
|
||||||
<span className="bs-cmp-th__role bs-cmp-th__role--spacer" aria-hidden>
|
rowSpan={2}
|
||||||
|
className="bs-cmp-col-kind bs-cmp-sticky-kind"
|
||||||
</span>
|
>
|
||||||
)}
|
{t("bizCompare.colKind")}
|
||||||
<span className="bs-cmp-th__name">{k}</span>
|
</th>
|
||||||
</span>
|
{showFailCol ? (
|
||||||
</th>
|
<th rowSpan={2} className="bs-cmp-col-fail">
|
||||||
))}
|
{t("bizCompare.colFailFields")}
|
||||||
{resultColumns.extras.map((f, fi) => {
|
</th>
|
||||||
const isCmp = resultColumns.compareSet.has(f);
|
) : null}
|
||||||
const prev = resultColumns.extras[fi - 1];
|
{keyCols.length ? (
|
||||||
const prevCmp = prev
|
<th
|
||||||
? resultColumns.compareSet.has(prev)
|
colSpan={keyCols.length}
|
||||||
: null;
|
className="bs-cmp-group bs-cmp-group--key"
|
||||||
const showRole = fi === 0 || prevCmp !== isCmp;
|
|
||||||
return (
|
|
||||||
<th
|
|
||||||
key={f}
|
|
||||||
className={
|
|
||||||
isCmp ? "bs-cmp-col-compare" : "bs-cmp-col-display"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span className="bs-cmp-th">
|
|
||||||
{showRole ? (
|
|
||||||
<span
|
|
||||||
className={`bs-cmp-th__role ${
|
|
||||||
isCmp
|
|
||||||
? "bs-cmp-th__role--compare"
|
|
||||||
: "bs-cmp-th__role--display"
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{isCmp
|
{t("bizCompare.keyFields")}
|
||||||
? t("bizCompare.compareFields")
|
</th>
|
||||||
: t("bizCompare.displayField")}
|
) : null}
|
||||||
</span>
|
{compareCols.length ? (
|
||||||
) : (
|
<th
|
||||||
<span
|
colSpan={compareCols.length}
|
||||||
className="bs-cmp-th__role bs-cmp-th__role--spacer"
|
className="bs-cmp-group bs-cmp-group--compare"
|
||||||
aria-hidden
|
|
||||||
>
|
>
|
||||||
|
{t("bizCompare.compareFields")}
|
||||||
</span>
|
</th>
|
||||||
)}
|
) : null}
|
||||||
<span className="bs-cmp-th__name">{f}</span>
|
{displayCols.length ? (
|
||||||
</span>
|
<th
|
||||||
</th>
|
colSpan={displayCols.length}
|
||||||
);
|
className="bs-cmp-group bs-cmp-group--display"
|
||||||
})}
|
>
|
||||||
</tr>
|
{t("bizCompare.displayField")}
|
||||||
|
</th>
|
||||||
|
) : null}
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<th className="bs-cmp-col-kind bs-cmp-sticky-kind">
|
||||||
|
{t("bizCompare.colKind")}
|
||||||
|
</th>
|
||||||
|
{showFailCol ? (
|
||||||
|
<th className="bs-cmp-col-fail">
|
||||||
|
{t("bizCompare.colFailFields")}
|
||||||
|
</th>
|
||||||
|
) : null}
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
{hasGroups ? (
|
||||||
|
<tr className="bs-cmp-field-row">
|
||||||
|
{keyCols.map((k) => (
|
||||||
|
<th key={k} className="bs-cmp-col-key">
|
||||||
|
<span className="bs-cmp-th__name">{k}</span>
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
{compareCols.map((f) => (
|
||||||
|
<th key={f} className="bs-cmp-col-compare">
|
||||||
|
<span className="bs-cmp-th__name">{f}</span>
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
{displayCols.map((f) => (
|
||||||
|
<th key={f} className="bs-cmp-col-display">
|
||||||
|
<span className="bs-cmp-th__name">{f}</span>
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{pagedDiffs.map((d, i) => {
|
{pagedDiffs.map((d, i) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue