Clean up and finalize indicator persistence on TF change
- Remove multiple delayed redraw calls from app.js (now handled in chart.js) - Remove excessive diagnostic logging throughout codebase - Keep useful debug warning for old indicators-panel.js module - Indicator list, parameters, and visibility now persist across TF switches - Indicators automatically recalculate with new TF candles when they load
This commit is contained in:
@ -64,8 +64,7 @@ window.deleteSavedSimulation = deleteSavedSimulation;
|
|||||||
window.clearSimulationResults = clearSimulationResults;
|
window.clearSimulationResults = clearSimulationResults;
|
||||||
window.updateTimeframeDisplay = updateTimeframeDisplay;
|
window.updateTimeframeDisplay = updateTimeframeDisplay;
|
||||||
window.renderIndicatorList = function() {
|
window.renderIndicatorList = function() {
|
||||||
// Legacy function - replaced by initIndicatorPanel
|
// This function is no longer needed for sidebar indicators
|
||||||
window.initIndicatorPanel();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Export init function for global access
|
// Export init function for global access
|
||||||
@ -88,30 +87,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
|
|
||||||
await loadStrategies();
|
await loadStrategies();
|
||||||
|
|
||||||
// Initialize new indicator panel
|
// Initialize indicator panel
|
||||||
window.initIndicatorPanel();
|
window.initIndicatorPanel();
|
||||||
|
|
||||||
const originalSwitchTimeframe = window.dashboard.switchTimeframe.bind(window.dashboard);
|
|
||||||
window.dashboard.switchTimeframe = function(interval) {
|
|
||||||
originalSwitchTimeframe(interval);
|
|
||||||
|
|
||||||
// Force redraw indicators after TF switch with multiple attempts
|
|
||||||
setTimeout(() => {
|
|
||||||
if (window.drawIndicatorsOnChart) {
|
|
||||||
window.drawIndicatorsOnChart();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
if (window.drawIndicatorsOnChart) {
|
|
||||||
window.drawIndicatorsOnChart();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
if (window.drawIndicatorsOnChart) {
|
|
||||||
window.drawIndicatorsOnChart();
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -87,15 +87,10 @@ function groupPlotsByColor(plots) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function initIndicatorPanel() {
|
export function initIndicatorPanel() {
|
||||||
console.log('[IndicatorPanel] Initializing...');
|
|
||||||
console.log('[IndicatorPanel] Current activeIndicators count:', activeIndicators.length);
|
|
||||||
console.trace('[IndicatorPanel] initIndicatorPanel call stack:');
|
|
||||||
renderIndicatorPanel();
|
renderIndicatorPanel();
|
||||||
console.log('[IndicatorPanel] Initialized');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getActiveIndicators() {
|
export function getActiveIndicators() {
|
||||||
console.log('getActiveIndicators:', activeIndicators.map(i => ({id: i.id, visible: i.visible})));
|
|
||||||
return activeIndicators;
|
return activeIndicators;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,12 +105,9 @@ export function setActiveIndicators(indicators) {
|
|||||||
export function renderIndicatorPanel() {
|
export function renderIndicatorPanel() {
|
||||||
const container = document.getElementById('indicatorPanel');
|
const container = document.getElementById('indicatorPanel');
|
||||||
if (!container) {
|
if (!container) {
|
||||||
console.error('[IndicatorPanel] Container #indicatorPanel not found!');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[IndicatorPanel] Rendering panel, searchQuery:', searchQuery, 'selectedCategory:', selectedCategory);
|
|
||||||
|
|
||||||
const available = getAvailableIndicators();
|
const available = getAvailableIndicators();
|
||||||
const catalog = available.filter(ind => {
|
const catalog = available.filter(ind => {
|
||||||
if (searchQuery && !ind.name.toLowerCase().includes(searchQuery.toLowerCase())) return false;
|
if (searchQuery && !ind.name.toLowerCase().includes(searchQuery.toLowerCase())) return false;
|
||||||
@ -124,8 +116,10 @@ export function renderIndicatorPanel() {
|
|||||||
const cat = CATEGORY_MAP[ind.type] || 'trend';
|
const cat = CATEGORY_MAP[ind.type] || 'trend';
|
||||||
return cat === selectedCategory;
|
return cat === selectedCategory;
|
||||||
});
|
});
|
||||||
|
if (selectedCategory === 'favorites') return false;
|
||||||
console.log("[IndicatorPanel] Total indicators:", available.length, "Filtered to:", catalog.length);
|
const cat = CATEGORY_MAP[ind.type] || 'trend';
|
||||||
|
return cat === selectedCategory;
|
||||||
|
});
|
||||||
|
|
||||||
const favoriteIds = new Set(userPresets.favorites || []);
|
const favoriteIds = new Set(userPresets.favorites || []);
|
||||||
|
|
||||||
@ -377,7 +371,6 @@ function setupEventListeners() {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const type = addBtn.dataset.type;
|
const type = addBtn.dataset.type;
|
||||||
if (type && window.addIndicator) {
|
if (type && window.addIndicator) {
|
||||||
console.log('[IndicatorPanel] Add button clicked for type:', type);
|
|
||||||
window.addIndicator(type);
|
window.addIndicator(type);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -496,26 +489,15 @@ window.clearAllIndicators = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removeIndicatorById(id) {
|
function removeIndicatorById(id) {
|
||||||
console.log(`[removeIndicatorById] Attempting to remove indicator: ${id}`);
|
|
||||||
console.log('Call stack:', console.trace());
|
|
||||||
|
|
||||||
const idx = activeIndicators.findIndex(a => a.id === id);
|
const idx = activeIndicators.findIndex(a => a.id === id);
|
||||||
if (idx < 0) {
|
if (idx < 0) return;
|
||||||
console.warn(`[removeIndicatorById] Indicator ${id} not found in array`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`[removeIndicatorById] Removing indicator at index ${idx}`);
|
|
||||||
|
|
||||||
activeIndicators[idx].series?.forEach(s => {
|
activeIndicators[idx].series?.forEach(s => {
|
||||||
try { window.dashboard?.chart?.removeSeries(s); } catch(e) {}
|
try { window.dashboard?.chart?.removeSeries(s); } catch(e) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove the specific indicator, don't clear the whole array
|
|
||||||
activeIndicators.splice(idx, 1);
|
activeIndicators.splice(idx, 1);
|
||||||
|
|
||||||
console.log(`[removeIndicatorById] After removal, array now has ${activeIndicators.length} indicators`);
|
|
||||||
|
|
||||||
if (configuringId === id) {
|
if (configuringId === id) {
|
||||||
configuringId = null;
|
configuringId = null;
|
||||||
}
|
}
|
||||||
@ -639,9 +621,6 @@ function addIndicator(type) {
|
|||||||
params[input.name] = input.default;
|
params[input.name] = input.default;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`[addIndicator] Adding ${id} to array, current count: ${activeIndicators.length}`);
|
|
||||||
console.trace('Call stack:');
|
|
||||||
|
|
||||||
activeIndicators.push({
|
activeIndicators.push({
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
@ -652,8 +631,6 @@ function addIndicator(type) {
|
|||||||
visible: true
|
visible: true
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`[addIndicator] After push, array count: ${activeIndicators.length}`);
|
|
||||||
|
|
||||||
// Don't set configuringId so indicators are NOT expanded by default
|
// Don't set configuringId so indicators are NOT expanded by default
|
||||||
renderIndicatorPanel();
|
renderIndicatorPanel();
|
||||||
drawIndicatorsOnChart();
|
drawIndicatorsOnChart();
|
||||||
@ -664,19 +641,15 @@ function saveUserPresets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderIndicatorOnPane(indicator, meta, instance, candles, paneIndex, lineStyleMap) {
|
function renderIndicatorOnPane(indicator, meta, instance, candles, paneIndex, lineStyleMap) {
|
||||||
console.log(`renderIndicatorOnPane for ${indicator.id}, candles.length=${candles.length}, paneIndex=${paneIndex}`);
|
|
||||||
|
|
||||||
// Recalculate with current TF candles
|
// Recalculate with current TF candles
|
||||||
const results = instance.calculate(candles);
|
const results = instance.calculate(candles);
|
||||||
console.log(`Calculated results for ${indicator.id}:`, results?.length || 0, 'values');
|
|
||||||
|
|
||||||
// Clear previous series for this indicator
|
// Clear previous series for this indicator
|
||||||
if (indicator.series && indicator.series.length > 0) {
|
if (indicator.series && indicator.series.length > 0) {
|
||||||
indicator.series.forEach(s => {
|
indicator.series.forEach(s => {
|
||||||
try {
|
try {
|
||||||
window.dashboard.chart.removeSeries(s);
|
window.dashboard.chart.removeSeries(s);
|
||||||
console.log(`Removed series for ${indicator.id}`);
|
} catch(e) {}
|
||||||
} catch(e) { console.error('Error removing series:', e); }
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
indicator.series = [];
|
indicator.series = [];
|
||||||
@ -691,10 +664,7 @@ function renderIndicatorOnPane(indicator, meta, instance, candles, paneIndex, li
|
|||||||
meta.plots.forEach((plot, plotIdx) => {
|
meta.plots.forEach((plot, plotIdx) => {
|
||||||
if (isObjectResult) {
|
if (isObjectResult) {
|
||||||
const hasData = results.some(r => r && r[plot.id] !== undefined && r[plot.id] !== null);
|
const hasData = results.some(r => r && r[plot.id] !== undefined && r[plot.id] !== null);
|
||||||
if (!hasData) {
|
if (!hasData) return;
|
||||||
console.log(`No data for plot ${plot.id} in ${indicator.id}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const plotColor = indicator.params[`_color_${plotIdx}`] || plot.color || '#2962ff';
|
const plotColor = indicator.params[`_color_${plotIdx}`] || plot.color || '#2962ff';
|
||||||
@ -716,7 +686,6 @@ function renderIndicatorOnPane(indicator, meta, instance, candles, paneIndex, li
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Plot ${plot.id} has ${data.length} data points`);
|
|
||||||
if (data.length === 0) return;
|
if (data.length === 0) return;
|
||||||
|
|
||||||
let series;
|
let series;
|
||||||
@ -805,26 +774,14 @@ export function drawIndicatorsOnChart() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeIndicators.length === 0) {
|
|
||||||
console.error('⚠️ drawIndicatorsOnChart: activeIndicators is EMPTY!');
|
|
||||||
console.error('⚠️ This means indicators were lost during TF switch!');
|
|
||||||
console.trace('Call stack showing where we are:');
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentInterval = window.dashboard.currentInterval;
|
const currentInterval = window.dashboard.currentInterval;
|
||||||
const candles = window.dashboard.allData.get(currentInterval);
|
const candles = window.dashboard.allData.get(currentInterval);
|
||||||
|
|
||||||
console.log(`drawIndicatorsOnChart called: interval=${currentInterval}, candles=${candles?.length || 0}, activeIndicators=${activeIndicators.length}`);
|
|
||||||
console.log('Active indicators visibility:', activeIndicators.map(i => ({id: i.id, visible: i.visible})));
|
|
||||||
console.trace('[drawIndicatorsOnChart] Call stack:');
|
|
||||||
|
|
||||||
if (!candles || candles.length === 0) {
|
if (!candles || candles.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[drawIndicatorsOnChart] Removing series complete, remaining indicators:', activeIndicators.length);
|
// Remove all existing series
|
||||||
|
|
||||||
// First, remove all existing series
|
|
||||||
activeIndicators.forEach(ind => {
|
activeIndicators.forEach(ind => {
|
||||||
ind.series?.forEach(s => {
|
ind.series?.forEach(s => {
|
||||||
try { window.dashboard.chart.removeSeries(s); } catch(e) {}
|
try { window.dashboard.chart.removeSeries(s); } catch(e) {}
|
||||||
@ -832,8 +789,6 @@ export function drawIndicatorsOnChart() {
|
|||||||
ind.series = [];
|
ind.series = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('[drawIndicatorsOnChart] Series arrays cleared, indicator count:', activeIndicators.length);
|
|
||||||
|
|
||||||
const lineStyleMap = {
|
const lineStyleMap = {
|
||||||
'solid': LightweightCharts.LineStyle.Solid,
|
'solid': LightweightCharts.LineStyle.Solid,
|
||||||
'dotted': LightweightCharts.LineStyle.Dotted,
|
'dotted': LightweightCharts.LineStyle.Dotted,
|
||||||
@ -848,9 +803,7 @@ export function drawIndicatorsOnChart() {
|
|||||||
|
|
||||||
// Process all indicators, filtering by visibility
|
// Process all indicators, filtering by visibility
|
||||||
activeIndicators.forEach(ind => {
|
activeIndicators.forEach(ind => {
|
||||||
console.log(`Checking indicator ${ind.id} for rendering - visible=${ind.visible}, type=${typeof ind.visible}`);
|
|
||||||
if (ind.visible === false || ind.visible === 'false') {
|
if (ind.visible === false || ind.visible === 'false') {
|
||||||
console.log(`Skipping invisible indicator ${ind.id}`);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,8 +820,6 @@ export function drawIndicatorsOnChart() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Rendering indicators:', { overlayCount: overlayIndicators.length, paneCount: paneIndicators.length });
|
|
||||||
|
|
||||||
// Calculate heights based on VISIBLE indicators only
|
// Calculate heights based on VISIBLE indicators only
|
||||||
const totalPanes = 1 + paneIndicators.length;
|
const totalPanes = 1 + paneIndicators.length;
|
||||||
const mainPaneHeight = paneIndicators.length > 0 ? 60 : 100;
|
const mainPaneHeight = paneIndicators.length > 0 ? 60 : 100;
|
||||||
@ -876,28 +827,21 @@ export function drawIndicatorsOnChart() {
|
|||||||
|
|
||||||
window.dashboard.chart.panes()[0]?.setHeight(mainPaneHeight);
|
window.dashboard.chart.panes()[0]?.setHeight(mainPaneHeight);
|
||||||
|
|
||||||
let totalSeriesCreated = 0;
|
|
||||||
overlayIndicators.forEach(({ indicator, meta, instance }) => {
|
overlayIndicators.forEach(({ indicator, meta, instance }) => {
|
||||||
const oldLen = indicator.series.length;
|
|
||||||
renderIndicatorOnPane(indicator, meta, instance, candles, 0, lineStyleMap);
|
renderIndicatorOnPane(indicator, meta, instance, candles, 0, lineStyleMap);
|
||||||
totalSeriesCreated += indicator.series.length - oldLen;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
paneIndicators.forEach(({ indicator, meta, instance }, idx) => {
|
paneIndicators.forEach(({ indicator, meta, instance }, idx) => {
|
||||||
const paneIndex = nextPaneIndex++;
|
const paneIndex = nextPaneIndex++;
|
||||||
indicatorPanes.set(indicator.id, paneIndex);
|
indicatorPanes.set(indicator.id, paneIndex);
|
||||||
|
|
||||||
const oldLen = indicator.series.length;
|
|
||||||
renderIndicatorOnPane(indicator, meta, instance, candles, paneIndex, lineStyleMap);
|
renderIndicatorOnPane(indicator, meta, instance, candles, paneIndex, lineStyleMap);
|
||||||
totalSeriesCreated += indicator.series.length - oldLen;
|
|
||||||
|
|
||||||
const pane = window.dashboard.chart.panes()[paneIndex];
|
const pane = window.dashboard.chart.panes()[paneIndex];
|
||||||
if (pane) {
|
if (pane) {
|
||||||
pane.setHeight(paneHeight);
|
pane.setHeight(paneHeight);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`drawIndicatorsOnChart complete - created ${totalSeriesCreated} series for ${overlayIndicators.length + paneIndicators.length} visible indicators`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetIndicator(id) {
|
function resetIndicator(id) {
|
||||||
|
|||||||
Reference in New Issue
Block a user