From 5205bcc725733be7fced858c082d89ed75394b4d Mon Sep 17 00:00:00 2001 From: Tomek Zebrowski Date: Tue, 14 Jul 2026 21:23:41 +0200 Subject: [PATCH] feat(dyno): add "View on Chart" integration to highlight pull data --- src/dynomanager.js | 46 ++++++++++++++++++++++++++++++++++----- tests/dynomanager.test.js | 6 +++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/dynomanager.js b/src/dynomanager.js index 9163c38..5fdf9d8 100644 --- a/src/dynomanager.js +++ b/src/dynomanager.js @@ -1,6 +1,7 @@ import { AppState, DOM } from './config.js'; import { Chart } from 'chart.js'; import { PaletteManager } from './palettemanager.js'; +import { ChartManager } from './chartmanager.js'; export const DynoManager = { chartInstance: null, @@ -141,24 +142,59 @@ export const DynoManager = { } } - if (!document.getElementById('btn-export-dyno')) { + if (!document.getElementById('dyno-action-group')) { const closeBtn = modal.querySelector('.btn-close'); if (closeBtn && closeBtn.parentElement) { const mainHeader = closeBtn.parentElement; + const actionGroup = document.createElement('div'); + actionGroup.id = 'dyno-action-group'; + actionGroup.style.display = 'flex'; + actionGroup.style.gap = '10px'; + actionGroup.style.marginRight = 'auto'; + actionGroup.style.marginLeft = '15px'; + + const highlightBtn = document.createElement('button'); + highlightBtn.className = 'btn btn-sm'; + highlightBtn.style.backgroundColor = 'var(--brand-blue, #1c3d72)'; + highlightBtn.style.color = '#fff'; + highlightBtn.style.border = 'none'; + highlightBtn.innerHTML = + ' View on Chart'; + highlightBtn.onclick = () => this.highlightCurrentPull(); + const exportBtn = document.createElement('button'); - exportBtn.id = 'btn-export-dyno'; exportBtn.className = 'btn btn-sm btn-primary'; exportBtn.innerHTML = ' Save PNG'; - exportBtn.style.marginRight = 'auto'; - exportBtn.style.marginLeft = '15px'; exportBtn.onclick = () => this.exportChart(); - mainHeader.insertBefore(exportBtn, closeBtn); + actionGroup.appendChild(highlightBtn); + actionGroup.appendChild(exportBtn); + + mainHeader.insertBefore(actionGroup, closeBtn); } } }, + highlightCurrentPull() { + if (this.currentPulls.length === 0) return; + + const activePull = this.currentPulls[this.selectedPullIndex]; + const file = AppState.files[0]; + + if (activePull.time && activePull.time.length > 0) { + const startTimeMs = activePull.time[0]; + const endTimeMs = activePull.time[activePull.time.length - 1]; + + const startSec = (startTimeMs - file.startTime) / 1000; + const endSec = (endTimeMs - file.startTime) / 1000; + + this.closeModal(); + + ChartManager.zoomTo(startSec, endSec, 0); + } + }, + exportChart() { const canvas = document.getElementById('dynoCanvas'); if (!canvas) return; diff --git a/tests/dynomanager.test.js b/tests/dynomanager.test.js index 5be3cd5..e0bede3 100644 --- a/tests/dynomanager.test.js +++ b/tests/dynomanager.test.js @@ -19,6 +19,12 @@ const mockChartInstance = { options: { plugins: {}, scales: {} }, }; +await jest.unstable_mockModule('../src/chartmanager.js', () => ({ + ChartManager: { + zoomTo: jest.fn(), + }, +})); + await jest.unstable_mockModule('chart.js', () => { const MockChart = jest.fn((ctx, config) => { if (config && config.options) mockChartInstance.options = config.options;