Skip to content

Commit d6f4e5f

Browse files
feat(compare): enhance trace comparison experience
2 parents 41c3047 + 172fcdc commit d6f4e5f

7 files changed

Lines changed: 964 additions & 165 deletions

File tree

DebugProbe.AspNetCore/Assets/css/debugprobe.css

Lines changed: 168 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,51 @@ h4 {
365365
margin-top: 22px;
366366
}
367367

368+
.compare-page .compare-card {
369+
margin-top: 0;
370+
}
371+
372+
.compare-header-actions {
373+
display: inline-flex;
374+
align-items: center;
375+
gap: 6px;
376+
}
377+
378+
.compare-icon-action {
379+
display: inline-flex;
380+
align-items: center;
381+
justify-content: center;
382+
flex: 0 0 30px;
383+
width: 30px;
384+
height: 30px;
385+
padding: 0;
386+
background: #fff;
387+
border: 1px solid #e5e7eb;
388+
border-radius: 6px;
389+
color: #6b7280;
390+
cursor: pointer;
391+
}
392+
393+
.compare-icon-action:hover {
394+
background: #f9fafb;
395+
border-color: #d1d5db;
396+
color: #111827;
397+
}
398+
399+
.compare-icon-action[hidden] {
400+
display: none;
401+
}
402+
403+
.compare-icon-action svg {
404+
width: 15px;
405+
height: 15px;
406+
stroke: currentColor;
407+
stroke-width: 2;
408+
stroke-linecap: round;
409+
stroke-linejoin: round;
410+
fill: none;
411+
}
412+
368413
.mono-value {
369414
overflow: hidden;
370415
max-width: min(520px, 58vw);
@@ -477,9 +522,11 @@ tbody tr:last-child td {
477522

478523
#compareResult:not(:empty) {
479524
margin: 0 10px 10px;
480-
overflow: hidden;
525+
display: grid;
526+
gap: 8px;
481527
border: 1px solid #eceff3;
482528
border-radius: 6px;
529+
padding: 8px;
483530
}
484531

485532
.payload-panel {
@@ -634,24 +681,29 @@ tbody tr:last-child td {
634681

635682
.code-block {
636683
position: relative;
684+
min-width: 0;
637685
border-top: 1px solid #2d3748;
638686
}
639687

640688
.code-block pre {
641689
min-height: 18px;
642-
max-height: 360px;
690+
max-height: 420px;
643691
margin: 0;
644692
}
645693

646694
pre {
647-
overflow: auto;
695+
box-sizing: border-box;
696+
max-width: 100%;
697+
overflow-x: auto;
698+
overflow-y: auto;
648699
margin: 0;
649700
padding: 12px 84px 12px 12px;
650701
background: #1e1e1e;
651702
border-radius: 0 0 6px 6px;
652703
color: #dcdcdc;
653704
font-size: 13px;
654705
line-height: 1.4;
706+
white-space: pre;
655707
tab-size: 2;
656708
}
657709

@@ -662,6 +714,7 @@ pre {
662714
.json-compare {
663715
display: grid;
664716
grid-template-columns: repeat(2, minmax(0, 1fr));
717+
align-items: stretch;
665718
gap: 10px;
666719
}
667720

@@ -685,7 +738,7 @@ pre {
685738

686739
.compare-row {
687740
display: grid;
688-
grid-template-columns: minmax(120px, 0.8fr) minmax(0, 1fr) minmax(0, 1fr);
741+
grid-template-columns: minmax(120px, 0.8fr) minmax(0, 1fr) minmax(0, 1fr) minmax(100px, 0.45fr);
689742
gap: 12px;
690743
padding: 8px 10px;
691744
border-bottom: 1px solid #f2f4f7;
@@ -715,6 +768,11 @@ pre {
715768
font-size: 12px;
716769
}
717770

771+
.compare-row strong {
772+
color: #4b5563;
773+
font-size: 12px;
774+
}
775+
718776
.compare-row-changed {
719777
background: rgba(255, 200, 0, 0.12);
720778
}
@@ -724,7 +782,30 @@ pre {
724782
}
725783

726784
.compare-pane {
785+
display: flex;
786+
flex-direction: column;
727787
min-width: 0;
788+
min-height: 0;
789+
}
790+
791+
.compare-pane .code-block {
792+
display: flex;
793+
flex: 1 1 auto;
794+
flex-direction: column;
795+
min-height: 0;
796+
max-height: 420px;
797+
overflow: hidden;
798+
border-radius: 0 0 6px 6px;
799+
}
800+
801+
.compare-pane .code-block pre {
802+
flex: 1 1 auto;
803+
height: 100%;
804+
max-height: none;
805+
}
806+
807+
.compare-pane .compare-empty {
808+
flex: 1 1 auto;
728809
}
729810

730811
.compare-pane-title {
@@ -764,6 +845,85 @@ pre {
764845
color: #b42318;
765846
}
766847

848+
.compare-summary {
849+
display: grid;
850+
gap: 8px;
851+
padding: 10px;
852+
background: #fff;
853+
border: 1px solid #eceff3;
854+
border-radius: 6px;
855+
}
856+
857+
.compare-summary-head {
858+
display: flex;
859+
align-items: center;
860+
justify-content: space-between;
861+
gap: 12px;
862+
padding-bottom: 8px;
863+
border-bottom: 1px solid #f2f4f7;
864+
}
865+
866+
.compare-summary-head strong {
867+
color: #111827;
868+
font-size: 15px;
869+
}
870+
871+
.compare-summary-head span,
872+
.compare-summary-empty {
873+
color: #6b7280;
874+
font-size: 12px;
875+
font-weight: 700;
876+
}
877+
878+
.compare-summary-group {
879+
display: grid;
880+
gap: 6px;
881+
}
882+
883+
.compare-summary-group h4,
884+
.compare-subhead {
885+
margin: 0;
886+
color: #4b5563;
887+
font-size: 12px;
888+
font-weight: 800;
889+
text-transform: uppercase;
890+
}
891+
892+
.compare-summary-item {
893+
display: grid;
894+
grid-template-columns: minmax(110px, auto) minmax(160px, 0.8fr) minmax(0, 1fr);
895+
gap: 10px;
896+
align-items: center;
897+
padding: 7px 8px;
898+
background: #fbfbfc;
899+
border: 1px solid #f2f4f7;
900+
border-radius: 6px;
901+
font-size: 12px;
902+
}
903+
904+
.compare-summary-item strong {
905+
color: #111827;
906+
}
907+
908+
.compare-summary-item small {
909+
overflow-wrap: anywhere;
910+
color: #4b5563;
911+
font-size: 12px;
912+
}
913+
914+
.compare-tag {
915+
display: inline-flex;
916+
align-items: center;
917+
justify-content: center;
918+
min-height: 22px;
919+
padding: 0 8px;
920+
background: #eef2ff;
921+
border-radius: 999px;
922+
color: #3730a3;
923+
font-size: 11px;
924+
font-weight: 800;
925+
}
926+
767927
/* =========================
768928
Badges
769929
========================= */
@@ -792,10 +952,13 @@ pre {
792952
========================= */
793953

794954
.diff-line {
955+
box-sizing: border-box;
956+
width: max-content;
795957
min-height: 18px;
796-
padding-left: 6px;
958+
padding: 0 6px;
797959
background: rgba(255, 200, 0, 0.12);
798960
border-left: 3px solid #f1c40f;
961+
white-space: pre;
799962
}
800963

801964
.diff-line-added {

DebugProbe.AspNetCore/Assets/html/details.html

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,33 @@
105105
<div class="trace-card-title">
106106
<span class="trace-dot" aria-hidden="true"></span>
107107
<span class="trace-label">Compare Trace</span>
108-
<strong>Remote environment</strong>
108+
</div>
109+
<div class="compare-header-actions">
110+
<button id="copyCompareLink"
111+
class="compare-icon-action"
112+
type="button"
113+
title="Copy share link"
114+
aria-label="Copy share link"
115+
onclick="copyCompareShareLink()"
116+
hidden>
117+
<svg viewBox="0 0 24 24" aria-hidden="true">
118+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
119+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
120+
</svg>
121+
</button>
122+
<button id="openCompareTab"
123+
class="compare-icon-action"
124+
type="button"
125+
title="Open in new tab"
126+
aria-label="Open in new tab"
127+
onclick="openCompareInNewTab()"
128+
hidden>
129+
<svg viewBox="0 0 24 24" aria-hidden="true">
130+
<path d="M14 3h7v7"></path>
131+
<path d="M10 14 21 3"></path>
132+
<path d="M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"></path>
133+
</svg>
134+
</button>
109135
</div>
110136
</div>
111137

DebugProbe.AspNetCore/Assets/js/debugprobe-compare-engine.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@
1515

1616
if ((!local.ok && !localEmpty) || (!remote.ok && !remoteEmpty)) {
1717
return {
18-
local: (localEmpty ? '(empty)' : local.raw)
19-
.split('\n')
18+
local: linesForParsedOrRaw(local, localEmpty)
2019
.map(x => ({
2120
text: x,
2221
state: !local.ok && !localEmpty ? 'invalid' : ''
2322
})),
2423

25-
remote: (remoteEmpty ? '(empty)' : remote.raw)
26-
.split('\n')
24+
remote: linesForParsedOrRaw(remote, remoteEmpty)
2725
.map(x => ({
2826
text: x,
2927
state: !remote.ok && !remoteEmpty ? 'invalid' : ''
@@ -68,6 +66,16 @@
6866
return rows;
6967
}
7068

69+
function linesForParsedOrRaw(payload, empty) {
70+
if (empty) {
71+
return ['(empty)'];
72+
}
73+
74+
return payload.ok
75+
? stringifyLines(payload.value, 0, false)
76+
: payload.raw.split('\n');
77+
}
78+
7179
function parseJson(json) {
7280
if (!json || json.trim() === '') {
7381
return {
@@ -816,4 +824,4 @@ function indent(depth) {
816824
return ' '.repeat(depth);
817825
}
818826

819-
window.compareJsonBodies = compareJsonBodies;
827+
window.compareJsonBodies = compareJsonBodies;

0 commit comments

Comments
 (0)