Skip to content

Commit 8fc0064

Browse files
feat(compare): add copy share link action
1 parent ec67c7a commit 8fc0064

3 files changed

Lines changed: 81 additions & 27 deletions

File tree

DebugProbe.AspNetCore/Assets/css/debugprobe.css

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,13 @@ h4 {
369369
margin-top: 0;
370370
}
371371

372-
.compare-open-tab {
372+
.compare-header-actions {
373+
display: inline-flex;
374+
align-items: center;
375+
gap: 6px;
376+
}
377+
378+
.compare-icon-action {
373379
display: inline-flex;
374380
align-items: center;
375381
justify-content: center;
@@ -384,17 +390,17 @@ h4 {
384390
cursor: pointer;
385391
}
386392

387-
.compare-open-tab:hover {
393+
.compare-icon-action:hover {
388394
background: #f9fafb;
389395
border-color: #d1d5db;
390396
color: #111827;
391397
}
392398

393-
.compare-open-tab[hidden] {
399+
.compare-icon-action[hidden] {
394400
display: none;
395401
}
396402

397-
.compare-open-tab svg {
403+
.compare-icon-action svg {
398404
width: 15px;
399405
height: 15px;
400406
stroke: currentColor;

DebugProbe.AspNetCore/Assets/html/details.html

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,19 +106,33 @@
106106
<span class="trace-dot" aria-hidden="true"></span>
107107
<span class="trace-label">Compare Trace</span>
108108
</div>
109-
<button id="openCompareTab"
110-
class="compare-open-tab"
111-
type="button"
112-
title="Open in new tab"
113-
aria-label="Open in new tab"
114-
onclick="openCompareInNewTab()"
115-
hidden>
116-
<svg viewBox="0 0 24 24" aria-hidden="true">
117-
<path d="M14 3h7v7"></path>
118-
<path d="M10 14 21 3"></path>
119-
<path d="M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"></path>
120-
</svg>
121-
</button>
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>
135+
</div>
122136
</div>
123137

124138
<div class="compare-controls">

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

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ window.runCompare = async function () {
1010
}
1111

1212
setCompareResult('<div class="compare-message">Comparing...</div>');
13-
setOpenCompareButtonVisible(false);
13+
setCompareActionsVisible(false);
1414

1515
try {
1616
const res = await fetch(`/debug/compare/${id}?baseUrl=${encodeURIComponent(base)}&remoteTraceId=${encodeURIComponent(remoteId)}`);
@@ -22,24 +22,50 @@ window.runCompare = async function () {
2222
}
2323

2424
setCompareResult(renderCompare(await res.json()));
25-
setOpenCompareButtonVisible(true);
25+
setCompareActionsVisible(true);
2626
} catch (error) {
2727
setCompareResult(`<div class="compare-message compare-message-error">${escapeHtml(error.message || 'Compare failed')}</div>`);
2828
}
2929
};
3030

3131
window.openCompareInNewTab = function () {
32+
const url = getCompareShareUrl();
33+
34+
if (url) {
35+
window.open(url, '_blank', 'noopener');
36+
}
37+
};
38+
39+
window.copyCompareShareLink = async function () {
40+
const url = getCompareShareUrl();
41+
const button = document.getElementById('copyCompareLink');
42+
43+
if (!url || !button) {
44+
return;
45+
}
46+
47+
await navigator.clipboard.writeText(url);
48+
49+
button.title = 'Copied!';
50+
button.setAttribute('aria-label', 'Copied!');
51+
52+
window.setTimeout(() => {
53+
button.title = 'Copy share link';
54+
button.setAttribute('aria-label', 'Copy share link');
55+
}, 1800);
56+
};
57+
58+
function getCompareShareUrl() {
3259
const localTraceId = getLocalTraceId();
3360
const base = document.getElementById('baseUrl').value.trim();
3461
const traceId = document.getElementById('compareId').value.trim();
3562

3663
if (!base || !traceId) {
37-
return;
64+
return '';
3865
}
3966

40-
const url = `/compare?baseUrl=${encodeURIComponent(base)}&traceId=${encodeURIComponent(traceId)}&localTraceId=${encodeURIComponent(localTraceId)}`;
41-
window.open(url, '_blank', 'noopener');
42-
};
67+
return `${window.location.origin}/compare?baseUrl=${encodeURIComponent(base)}&traceId=${encodeURIComponent(traceId)}&localTraceId=${encodeURIComponent(localTraceId)}`;
68+
}
4369

4470
document.addEventListener('DOMContentLoaded', () => {
4571
const baseInput = document.getElementById('baseUrl');
@@ -71,10 +97,18 @@ function getLocalTraceId() {
7197
return input?.value || window.location.pathname.split('/').pop();
7298
}
7399

74-
function setOpenCompareButtonVisible(visible) {
75-
const button = document.getElementById('openCompareTab');
76-
if (button) {
77-
button.hidden = !visible;
100+
function setCompareActionsVisible(visible) {
101+
['copyCompareLink', 'openCompareTab'].forEach(id => {
102+
const button = document.getElementById(id);
103+
if (button) {
104+
button.hidden = !visible;
105+
}
106+
});
107+
108+
const copyButton = document.getElementById('copyCompareLink');
109+
if (copyButton) {
110+
copyButton.title = 'Copy share link';
111+
copyButton.setAttribute('aria-label', 'Copy share link');
78112
}
79113
}
80114

0 commit comments

Comments
 (0)