Skip to content

Commit 2d7236e

Browse files
committed
Allow to link to plots
1 parent d7cb8a7 commit 2d7236e

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

js/analysis.js

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,110 @@
409409
});
410410
}
411411

412+
function copyShareableLink() {
413+
const selected = getSelectedModels();
414+
if (selected.length === 0) {
415+
alert('Please select at least one model to share.');
416+
return;
417+
}
418+
419+
const chartType = document.getElementById('compare-chart-type');
420+
const chartTypeValue = chartType ? chartType.value : 'bar';
421+
422+
// Get current leaderboard
423+
const container = document.getElementById('leaderboard-container');
424+
const active = container ? container.querySelector('.tabcontent.active') : null;
425+
const leaderboardId = active ? active.id.replace('leaderboard-', '') : 'verified';
426+
427+
// Build URL parameters
428+
const params = new URLSearchParams();
429+
params.set('leaderboard', leaderboardId);
430+
params.set('chart', chartTypeValue);
431+
params.set('models', selected.map(m => m.name).join(','));
432+
433+
// Create full URL
434+
const baseUrl = window.location.origin + window.location.pathname;
435+
const shareUrl = `${baseUrl}?${params.toString()}`;
436+
437+
// Copy to clipboard
438+
if (navigator.clipboard && navigator.clipboard.writeText) {
439+
navigator.clipboard.writeText(shareUrl).then(() => {
440+
// Visual feedback
441+
const btn = document.getElementById('copy-link-btn');
442+
if (btn) {
443+
const originalHTML = btn.innerHTML;
444+
btn.innerHTML = '<i class="fa fa-check"></i>&nbsp;Copied!';
445+
btn.classList.add('btn-success');
446+
btn.classList.remove('btn-outline-secondary');
447+
setTimeout(() => {
448+
btn.innerHTML = originalHTML;
449+
btn.classList.remove('btn-success');
450+
btn.classList.add('btn-outline-secondary');
451+
}, 2000);
452+
}
453+
}).catch(err => {
454+
console.error('Failed to copy link:', err);
455+
alert('Failed to copy link to clipboard. Please copy manually:\n' + shareUrl);
456+
});
457+
} else {
458+
// Fallback for older browsers
459+
alert('Copy this link:\n' + shareUrl);
460+
}
461+
}
462+
463+
function restoreStateFromURL() {
464+
const params = new URLSearchParams(window.location.search);
465+
466+
if (!params.has('models')) {
467+
return; // No state to restore
468+
}
469+
470+
const leaderboardName = params.get('leaderboard') || 'verified';
471+
const chartType = params.get('chart') || 'bar';
472+
const modelNames = params.get('models').split(',').filter(m => m.trim());
473+
474+
if (modelNames.length === 0) {
475+
return;
476+
}
477+
478+
// Switch to the correct leaderboard tab
479+
const leaderboardTab = document.querySelector(`[data-leaderboard="${leaderboardName}"]`);
480+
if (leaderboardTab) {
481+
leaderboardTab.click();
482+
}
483+
484+
// Wait a bit for the tab to load, then select models
485+
setTimeout(() => {
486+
const container = document.getElementById('leaderboard-container');
487+
const active = container ? container.querySelector('.tabcontent.active') : null;
488+
if (!active) return;
489+
490+
// Deselect all first
491+
const allCheckboxes = active.querySelectorAll('input.row-select');
492+
allCheckboxes.forEach(cb => cb.checked = false);
493+
494+
// Select the models from URL
495+
modelNames.forEach(modelName => {
496+
const checkbox = active.querySelector(`input.row-select[data-model="${modelName}"]`);
497+
if (checkbox) {
498+
checkbox.checked = true;
499+
}
500+
});
501+
502+
// Open the compare modal
503+
openModal();
504+
505+
// Set the chart type
506+
const chartTypeSelect = document.getElementById('compare-chart-type');
507+
if (chartTypeSelect) {
508+
chartTypeSelect.value = chartType;
509+
}
510+
511+
// Render the chart
512+
renderChart();
513+
}, 300);
514+
}
515+
412516
function initEvents() {
413517
// Listen for global theme changes (e.g., from sidebar toggle)
414518
const observer = new MutationObserver((mutations) => {
@@ -509,6 +613,15 @@
509613
});
510614
}
511615

616+
// Copy link button handler
617+
const copyLinkBtn = document.getElementById('copy-link-btn');
618+
if (copyLinkBtn) {
619+
copyLinkBtn.addEventListener('click', (e) => {
620+
e.preventDefault();
621+
copyShareableLink();
622+
});
623+
}
624+
512625
// No selection modal close handlers
513626
const noSelectionModal = document.getElementById('no-selection-modal');
514627
if (noSelectionModal) {
@@ -549,6 +662,9 @@
549662
}
550663
}
551664
});
665+
666+
// Restore state from URL if present
667+
restoreStateFromURL();
552668
}
553669

554670
if (document.readyState === 'loading') {

templates/_leaderboard_table.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ <h3 id="compare-modal-title" class="m-0">Compare results</h3>
108108
<button id="download-png-btn" class="btn btn-sm btn-outline-secondary" type="button" title="Download chart as PNG">
109109
<i class="fa fa-download"></i>&nbsp;PNG
110110
</button>
111+
<button id="copy-link-btn" class="btn btn-sm btn-outline-secondary" type="button" title="Copy shareable link">
112+
<i class="fa fa-link"></i>&nbsp;Copy Link
113+
</button>
111114
</div>
112115
<div class="d-flex align-items-center gap-2 mb-2 flex-wrap">
113116
<select id="matrix-chunk-selector" class="form-control form-select" style="flex: 1 1 200px; display: none;">

0 commit comments

Comments
 (0)