ui: Correct date display chart. Various small fixes.

This commit is contained in:
gerlofvanek 2024-11-29 14:36:05 +01:00
parent cf92c5635d
commit f20a9fd75b
2 changed files with 78 additions and 79 deletions

View file

@ -1327,7 +1327,7 @@ async function fetchLatestPrices() {
return cachedData.value;
}
const url = 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,bitcoin-cash,dash,dogecoin,decred,litecoin,particl,pivx,monero,zano,wownero,zcoin&vs_currencies=USD,BTC';
const url = `${config.apiEndpoints.coinGecko}/simple/price?ids=bitcoin,bitcoin-cash,dash,dogecoin,decred,litecoin,particl,pivx,monero,zano,wownero,zcoin&vs_currencies=USD,BTC&api_key=${config.apiKeys.coinGecko}`;
try {
const data = await makePostRequest(url);

View file

@ -38,6 +38,13 @@ const config = {
currentResolution: 'year'
};
function getAPIKeys() {
return {
cryptoCompare: '{{chart_api_key}}',
coinGecko: '{{coingecko_api_key}}'
};
}
// Utils
const utils = {
formatNumber: (number, decimals = 2) =>
@ -139,7 +146,7 @@ const api = {
.filter(coin => coin.usesCoinGecko)
.map(coin => coin.name)
.join(',');
const url = `${config.apiEndpoints.coinGecko}/simple/price?ids=${coinIds}&vs_currencies=usd,btc&include_24hr_vol=true&include_24hr_change=true`;
const url = `${config.apiEndpoints.coinGecko}/simple/price?ids=${coinIds}&vs_currencies=usd,btc&include_24hr_vol=true&include_24hr_change=true&api_key=${config.apiKeys.coinGecko}`;
console.log(`Fetching data for multiple coins from CoinGecko: ${url}`);
@ -190,7 +197,7 @@ const api = {
}
if (coin === 'WOW') {
const url = `${config.apiEndpoints.coinGecko}/coins/wownero/market_chart?vs_currency=usd&days=1`;
const url = `${config.apiEndpoints.coinGecko}/coins/wownero/market_chart?vs_currency=usd&days=1&api_key=${config.apiKeys.coinGecko}`;
console.log(`CoinGecko URL for WOW: ${url}`);
try {
@ -507,7 +514,7 @@ const chartModule = {
}
},
initChart: () => {
initChart: () => {
const ctx = document.getElementById('coin-chart').getContext('2d');
if (!ctx) {
logger.error('Failed to get chart context. Make sure the canvas element exists.');
@ -518,11 +525,6 @@ initChart: () => {
gradient.addColorStop(0, 'rgba(77, 132, 240, 0.2)');
gradient.addColorStop(1, 'rgba(77, 132, 240, 0)');
const formatTime = (date) => {
const hours = date.getHours().toString().padStart(2, '0');
return `${hours}:00`;
};
chartModule.chart = new Chart(ctx, {
type: 'line',
data: {
@ -550,9 +552,15 @@ initChart: () => {
time: {
unit: 'hour',
displayFormats: {
hour: 'HH:00',
hour: 'h:mm a',
day: 'MMM d',
month: 'MMM yyyy'
},
tooltipFormat: 'MMM d, yyyy h:mm a'
},
adapters: {
date: {
zone: 'UTC'
}
},
ticks: {
@ -566,16 +574,24 @@ initChart: () => {
callback: function(value) {
const date = new Date(value);
if (config.currentResolution === 'day') {
return formatTime(date);
// Convert to AM/PM format
return date.toLocaleTimeString('en-US', {
hour: 'numeric',
minute: '2-digit',
hour12: true,
timeZone: 'UTC'
});
} else if (config.currentResolution === 'year') {
return date.toLocaleDateString('en-US', {
month: 'short',
year: 'numeric'
year: 'numeric',
timeZone: 'UTC'
});
} else {
return date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric'
day: 'numeric',
timeZone: 'UTC'
});
}
}
@ -618,26 +634,35 @@ initChart: () => {
title: (tooltipItems) => {
const date = new Date(tooltipItems[0].parsed.x);
if (config.currentResolution === 'day') {
return `${date.toLocaleDateString('en-US', {
return date.toLocaleString('en-US', {
month: 'short',
day: 'numeric'
})} ${formatTime(date)}`;
day: 'numeric',
hour: 'numeric',
minute: '2-digit',
hour12: true,
timeZone: 'UTC'
});
} else if (config.currentResolution === 'year') {
return date.toLocaleDateString('en-US', {
return date.toLocaleString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
day: 'numeric',
timeZone: 'UTC'
});
} else {
return date.toLocaleDateString('en-US', {
return date.toLocaleString('en-US', {
month: 'short',
day: 'numeric'
day: 'numeric',
timeZone: 'UTC'
});
}
},
label: (item) => {
const value = item.parsed.y;
return `${chartModule.currentCoin}: $${value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 8 })}`;
return `${chartModule.currentCoin}: $${value.toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 8
})}`;
}
}
},
@ -645,22 +670,6 @@ initChart: () => {
lineWidth: 1,
lineColor: 'rgba(77, 132, 240, 0.5)'
}
},
elements: {
point: {
backgroundColor: 'rgba(77, 132, 240, 1)',
borderColor: 'rgba(77, 132, 240, 1)',
borderWidth: 1,
radius: 2,
hoverRadius: 4,
hitRadius: 6,
hoverBorderWidth: 2
},
line: {
backgroundColor: gradient,
borderColor: 'rgba(77, 132, 240, 1)',
fill: true
}
}
},
plugins: [chartModule.verticalLinePlugin]
@ -669,7 +678,7 @@ initChart: () => {
console.log('Chart initialized:', chartModule.chart);
},
prepareChartData: (coinSymbol, data) => {
prepareChartData: (coinSymbol, data) => {
if (!data) {
console.error(`No data received for ${coinSymbol}`);
return [];
@ -680,8 +689,7 @@ prepareChartData: (coinSymbol, data) => {
if (coinSymbol === 'WOW' && Array.isArray(data)) {
const endTime = new Date(data[data.length - 1][0]);
// Convert to local time
endTime.setMinutes(0, 0, 0);
endTime.setUTCMinutes(0, 0, 0);
const endUnix = endTime.getTime();
const startUnix = endUnix - (24 * 3600000);
@ -689,7 +697,7 @@ prepareChartData: (coinSymbol, data) => {
for (let hourUnix = startUnix; hourUnix <= endUnix; hourUnix += 3600000) {
const targetHour = new Date(hourUnix);
targetHour.setMinutes(0, 0, 0);
targetHour.setUTCMinutes(0, 0, 0);
const closestPoint = data.reduce((prev, curr) => {
const prevTime = new Date(prev[0]);
@ -706,7 +714,7 @@ prepareChartData: (coinSymbol, data) => {
}
const lastTime = new Date(data[data.length - 1][0]);
if (lastTime.getMinutes() !== 0) {
if (lastTime.getUTCMinutes() !== 0) {
hourlyPoints.push({
x: lastTime,
y: data[data.length - 1][1]
@ -735,33 +743,38 @@ prepareChartData: (coinSymbol, data) => {
return [];
}
return preparedData;
return preparedData.map(point => ({
x: new Date(point.x).getTime(),
y: point.y
}));
} catch (error) {
console.error(`Error preparing chart data for ${coinSymbol}:`, error);
return [];
}
},
ensureHourlyData: (data) => {
const now = new Date();
const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
const hourlyData = [];
ensureHourlyData: (data) => {
const now = new Date();
now.setUTCMinutes(0, 0, 0);
const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
const hourlyData = [];
for (let i = 0; i < 24; i++) {
const targetTime = new Date(twentyFourHoursAgo.getTime() + i * 60 * 60 * 1000);
const closestDataPoint = data.reduce((prev, curr) =>
Math.abs(curr.x - targetTime) < Math.abs(prev.x - targetTime) ? curr : prev
);
hourlyData.push({
x: targetTime,
y: closestDataPoint.y
});
}
for (let i = 0; i < 24; i++) {
const targetTime = new Date(twentyFourHoursAgo.getTime() + i * 60 * 60 * 1000);
const closestDataPoint = data.reduce((prev, curr) =>
Math.abs(new Date(curr.x).getTime() - targetTime.getTime()) <
Math.abs(new Date(prev.x).getTime() - targetTime.getTime()) ? curr : prev
);
hourlyData.push({
x: targetTime.getTime(),
y: closestDataPoint.y
});
}
return hourlyData;
},
return hourlyData;
},
updateChart: async (coinSymbol, forceRefresh = false) => {
try {
chartModule.showChartLoader();
@ -797,16 +810,11 @@ ensureHourlyData: (data) => {
chartModule.chart.data.datasets[0].data = chartData;
chartModule.chart.data.datasets[0].label = `${coinSymbol} Price (USD)`;
// Special handling for Wownero
if (coinSymbol === 'WOW') {
chartModule.chart.options.scales.x.time.unit = 'hour';
chartModule.chart.options.scales.x.ticks.maxTicksLimit = 24;
chartModule.chart.options.plugins.tooltip.callbacks.title = (tooltipItems) => {
const date = new Date(tooltipItems[0].parsed.x);
return date.toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true, timeZone: 'UTC' });
};
} else {
const resolution = config.resolutions[config.currentResolution] || config.resolutions.year;
const resolution = config.resolutions[config.currentResolution];
chartModule.chart.options.scales.x.time.unit = resolution.interval === 'hourly' ? 'hour' : 'day';
if (config.currentResolution === 'year' || config.currentResolution === 'sixMonths') {
@ -814,21 +822,12 @@ ensureHourlyData: (data) => {
}
if (config.currentResolution === 'year') {
chartModule.chart.options.scales.x.ticks.maxTicksLimit = 12; // One tick per month
chartModule.chart.options.scales.x.ticks.maxTicksLimit = 12;
} else if (config.currentResolution === 'sixMonths') {
chartModule.chart.options.scales.x.ticks.maxTicksLimit = 6; // One tick every month
chartModule.chart.options.scales.x.ticks.maxTicksLimit = 6;
} else if (config.currentResolution === 'day') {
chartModule.chart.options.scales.x.ticks.maxTicksLimit = 24; // One tick every hour
chartModule.chart.options.scales.x.ticks.maxTicksLimit = 24;
}
chartModule.chart.options.plugins.tooltip.callbacks.title = (tooltipItems) => {
const date = new Date(tooltipItems[0].parsed.x);
if (config.currentResolution === 'year' || config.currentResolution === 'sixMonths') {
return date.toLocaleString('en-US', { year: 'numeric', month: 'short', day: 'numeric', timeZone: 'UTC' });
} else if (config.currentResolution === 'day') {
return date.toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true, timeZone: 'UTC' });
}
};
}
chartModule.chart.update('active');