feat: implement persistence for settings and indicators

This commit is contained in:
DiTus
2026-03-20 08:32:52 +01:00
parent 5efd652456
commit 5624e3a8b7
2 changed files with 86 additions and 3 deletions

View File

@ -140,7 +140,10 @@ export class TradingDashboard {
constructor() {
this.chart = null;
this.candleSeries = null;
this.currentInterval = '1d';
// Load settings from local storage or defaults
this.symbol = localStorage.getItem('winterfail_symbol') || 'BTC';
this.currentInterval = localStorage.getItem('winterfail_interval') || '1d';
this.intervals = INTERVALS;
this.allData = new Map();
this.isLoading = false;
@ -164,7 +167,7 @@ constructor() {
let candles = this.allData.get(interval);
if (!candles || candles.length < 125) {
const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/candles?symbol=BTC&interval=${interval}&limit=1000`);
const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/candles?symbol=${this.symbol}&interval=${interval}&limit=1000`);
const data = await response.json();
if (data.candles && data.candles.length > 0) {
candles = data.candles.reverse().map(c => ({
@ -1044,6 +1047,7 @@ switchTimeframe(interval) {
const oldInterval = this.currentInterval;
this.currentInterval = interval;
localStorage.setItem('winterfail_interval', interval); // Save setting
this.hasInitialLoad = false;
document.querySelectorAll('.timeframe-btn').forEach(btn => {

View File

@ -3,6 +3,72 @@ import { getAvailableIndicators, IndicatorRegistry as IR } from '../indicators/i
// State management
let activeIndicators = [];
// Persistence Logic
function saveActiveIndicators() {
try {
const toSave = activeIndicators.map(ind => ({
id: ind.id,
type: ind.type,
name: ind.name,
params: ind.params,
visible: ind.visible,
paneHeight: ind.paneHeight
}));
console.log('[Persistence] Saving indicators:', toSave.length);
localStorage.setItem('winterfail_active_indicators', JSON.stringify(toSave));
} catch (e) {
console.error('Failed to save active indicators:', e);
}
}
function loadActiveIndicators() {
try {
const saved = localStorage.getItem('winterfail_active_indicators');
console.log('[Persistence] Loading from storage:', saved ? 'data found' : 'empty');
if (!saved) return;
const parsed = JSON.parse(saved);
if (!Array.isArray(parsed)) return;
const restored = [];
parsed.forEach(savedInd => {
const IndicatorClass = IR?.[savedInd.type];
if (!IndicatorClass) {
console.warn(`[Persistence] Unknown indicator type: ${savedInd.type}`);
return;
}
const instance = new IndicatorClass({ type: savedInd.type, params: savedInd.params, name: savedInd.name });
const metadata = instance.getMetadata();
restored.push({
id: savedInd.id,
type: savedInd.type,
name: savedInd.name || metadata.name,
params: savedInd.params,
plots: metadata.plots,
series: [],
visible: savedInd.visible !== undefined ? savedInd.visible : true,
paneHeight: savedInd.paneHeight || 120,
cachedResults: null,
cachedMeta: null
});
const parts = savedInd.id.split('_');
const idNum = parseInt(parts[parts.length - 1]);
if (!isNaN(idNum) && idNum >= nextInstanceId) {
nextInstanceId = idNum + 1;
}
});
activeIndicators = restored;
console.log(`[Persistence] Successfully restored ${activeIndicators.length} indicators`);
} catch (e) {
console.error('Failed to load active indicators:', e);
}
}
console.log('[Module] indicators-panel-new.js loaded - activeIndicators count:', activeIndicators?.length || 0);
let configuringId = null;
let searchQuery = '';
@ -96,7 +162,12 @@ function groupPlotsByColor(plots) {
}
export function initIndicatorPanel() {
loadActiveIndicators(); // Load persisted indicators
renderIndicatorPanel();
// Also trigger initial draw if dashboard exists (it might be too early, but safe to try)
if (window.dashboard && window.dashboard.hasInitialLoad) {
drawIndicatorsOnChart();
}
}
export function getActiveIndicators() {
@ -107,6 +178,7 @@ export function setActiveIndicators(indicators) {
console.warn('setActiveIndicators() called with', indicators.length, 'indicators - this will replace activeIndicators array!');
console.trace('Call stack:');
activeIndicators = indicators;
saveActiveIndicators();
renderIndicatorPanel();
}
@ -557,6 +629,7 @@ window.updateIndicatorColor = function(id, index, color) {
if (!indicator) return;
indicator.params[`_color_${index}`] = color;
saveActiveIndicators();
drawIndicatorsOnChart();
};
@ -568,6 +641,7 @@ window.updateIndicatorSetting = function(id, key, value) {
indicator.lastSignalTimestamp = null;
indicator.lastSignalType = null;
indicator.cachedResults = null; // Clear cache when params change
saveActiveIndicators();
drawIndicatorsOnChart();
};
@ -579,6 +653,7 @@ window.clearAllIndicators = function() {
});
activeIndicators = [];
configuringId = null;
saveActiveIndicators();
renderIndicatorPanel();
drawIndicatorsOnChart();
}
@ -590,6 +665,7 @@ window.toggleAllIndicatorsVisibility = function() {
ind.visible = !allVisible;
});
saveActiveIndicators();
drawIndicatorsOnChart();
renderIndicatorPanel();
}
@ -608,6 +684,7 @@ function removeIndicatorById(id) {
configuringId = null;
}
saveActiveIndicators();
renderIndicatorPanel();
drawIndicatorsOnChart();
}
@ -808,7 +885,7 @@ function addIndicator(type) {
paneHeight: 120 // default 120px
});
// Don't set configuringId so indicators are NOT expanded by default
saveActiveIndicators();
renderIndicatorPanel();
drawIndicatorsOnChart();
};
@ -1286,6 +1363,7 @@ function resetIndicator(id) {
indicator.params[input.name] = input.default;
});
saveActiveIndicators();
renderIndicatorPanel();
drawIndicatorsOnChart();
}
@ -1302,6 +1380,7 @@ function toggleIndicatorVisibility(id) {
indicator.visible = indicator.visible === false;
saveActiveIndicators();
// Full redraw to ensure all indicators render correctly
if (typeof drawIndicatorsOnChart === 'function') {
drawIndicatorsOnChart();