diff --git a/src/api/dashboard/static/index.html b/src/api/dashboard/static/index.html index 102b1b4..840d451 100644 --- a/src/api/dashboard/static/index.html +++ b/src/api/dashboard/static/index.html @@ -567,6 +567,51 @@ color: white; } + /* Navigation Controls */ + .nav-controls { + position: absolute; + left: 50%; + transform: translateX(-50%); + bottom: 10px; + display: flex; + flex-direction: row; + gap: 4px; + z-index: 10; + opacity: 0; + transition: opacity 0.2s; + } + + .chart-wrapper.show-nav .nav-controls { + opacity: 1; + } + + .nav-btn { + width: 28px; + height: 28px; + background: rgba(42, 46, 57, 0.9); + border: 1px solid #363c4e; + color: #d1d4dc; + font-size: 14px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + transition: all 0.2s; + padding: 0; + } + + .nav-btn:hover { + background: #363c4e; + border-color: #4a4f5e; + } + + .nav-btn:active { + background: #2962ff; + border-color: #2962ff; + color: white; + } + .ha-header { display: flex; justify-content: space-between; @@ -995,12 +1040,17 @@
-
+
+
diff --git a/src/api/dashboard/static/js/ui/chart.js b/src/api/dashboard/static/js/ui/chart.js index 3c6982d..245d936 100644 --- a/src/api/dashboard/static/js/ui/chart.js +++ b/src/api/dashboard/static/js/ui/chart.js @@ -105,6 +105,7 @@ export class TradingDashboard { }); this.initPriceScaleControls(); + this.initNavigationControls(); this.chart.timeScale().subscribeVisibleLogicalRangeChange(this.onVisibleRangeChange.bind(this)); @@ -204,6 +205,57 @@ export class TradingDashboard { }); } + initNavigationControls() { + const chartWrapper = document.getElementById('chartWrapper'); + const navLeft = document.getElementById('navLeft'); + const navRight = document.getElementById('navRight'); + const navRecent = document.getElementById('navRecent'); + + if (!chartWrapper || !navLeft || !navRight || !navRecent) return; + + chartWrapper.addEventListener('mousemove', (e) => { + const rect = chartWrapper.getBoundingClientRect(); + const distanceFromBottom = rect.bottom - e.clientY; + chartWrapper.classList.toggle('show-nav', distanceFromBottom < 30); + }); + + chartWrapper.addEventListener('mouseleave', () => { + chartWrapper.classList.remove('show-nav'); + }); + + navLeft.addEventListener('click', () => this.navigateLeft()); + navRight.addEventListener('click', () => this.navigateRight()); + navRecent.addEventListener('click', () => this.navigateToRecent()); + } + + navigateLeft() { + const visibleRange = this.chart.timeScale().getVisibleLogicalRange(); + if (!visibleRange) return; + + const visibleBars = visibleRange.to - visibleRange.from; + const shift = visibleBars * 0.8; + const newFrom = visibleRange.from - shift; + const newTo = visibleRange.to - shift; + + this.chart.timeScale().setVisibleLogicalRange({ from: newFrom, to: newTo }); + } + + navigateRight() { + const visibleRange = this.chart.timeScale().getVisibleLogicalRange(); + if (!visibleRange) return; + + const visibleBars = visibleRange.to - visibleRange.from; + const shift = visibleBars * 0.8; + const newFrom = visibleRange.from + shift; + const newTo = visibleRange.to + shift; + + this.chart.timeScale().setVisibleLogicalRange({ from: newFrom, to: newTo }); + } + + navigateToRecent() { + this.chart.timeScale().scrollToRealTime(); + } + initEventListeners() { document.addEventListener('keydown', (e) => { if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return; @@ -217,6 +269,14 @@ export class TradingDashboard { if (shortcuts[e.key]) { this.switchTimeframe(shortcuts[e.key]); } + + if (e.key === 'ArrowLeft') { + this.navigateLeft(); + } else if (e.key === 'ArrowRight') { + this.navigateRight(); + } else if (e.key === 'ArrowUp') { + this.navigateToRecent(); + } }); }