commit a51d3f8d7bcdc566cab959bf60090010b813c503
parent 27eb2ccb45b34570b308d02cd55ece43f97e1bf0
Author: Emily Doherty <git@emily.sh>
Date: Sun, 13 Oct 2024 23:23:31 -0700
Start the process of splitting JS files
I am a JS noob so this is probably poorly thought out. But it is a wip and I dont really care about the quality, just more the learning experience.
Diffstat:
7 files changed, 257 insertions(+), 79 deletions(-)
diff --git a/src/datum.js b/src/datum.js
@@ -0,0 +1,22 @@
+export default class Datum {
+ constructor(time, price) {
+ this._time = time;
+ this._price = price;
+ }
+
+ getTime() {
+ return this._time;
+ }
+
+ getPrice() {
+ return this._price;
+ }
+
+ getX() {
+ return this.getTime();
+ }
+
+ getY() {
+ return this.getPrice();
+ }
+}
+\ No newline at end of file
diff --git a/src/fetchCurrent.js b/src/fetchCurrent.js
@@ -0,0 +1,4 @@
+export default async function fetchCurrent() {
+ const resp = await fetch("https://data.wowtoken.app/token/current.json");
+ return await resp.json();
+}
diff --git a/src/fetchData.js b/src/fetchData.js
@@ -0,0 +1,13 @@
+import Datum from "./datum";
+import urlBuilder from "./urlBuilder";
+
+export default async function fetchData(currentRegionSelection, currentTimeSelection, currentAggregateSelection) {
+ const data = [];
+ const resp = await fetch(urlBuilder(currentRegionSelection, currentTimeSelection, currentAggregateSelection));
+ const respData = await resp.json();
+ for (let i = 0, l = respData.length; i < l; i++) {
+ let datum = new Datum(Date.parse(respData[i]['time']), respData[i]['value']);
+ data.push(datum);
+ }
+ return data;
+}
+\ No newline at end of file
diff --git a/src/index.js b/src/index.js
@@ -12,6 +12,12 @@ import {
import 'chartjs-adapter-dayjs-3';
import "./style.css"
+import fetchCurrent from "./fetchCurrent";
+import fetchData from "./fetchData";
+import {addLoader, removeLoader} from "./loader";
+import TokenChart from "./tokenChart";
+import Datum from "./datum";
+
// TODO: This file should be seperated into multiple with better ownership
Chart.register(
@@ -29,13 +35,14 @@ let currentRegionSelection = '';
let currentTimeSelection = '';
let currentAggregateSelection = '';
let startYAtZero = false;
+let chart;
const currentPriceHash = {
us: 0,
eu: 0,
kr: 0,
tw: 0
};
-let chartData = {
+const chartData = {
us: [],
eu: [],
kr: [],
@@ -68,7 +75,7 @@ function populateChart() {
datasets: [{
borderColor: 'gold',
label: currentRegionSelection.toUpperCase() + " WoW Token Price",
- data: chartJsData,
+ data: [],
cubicInterpolationMode: 'monotone',
pointRadius: 0
}]
@@ -122,42 +129,35 @@ function lookupTimeUnit(query){
return lookup[query.charAt(query.length - 1)]
}
-
async function callUpdateURL() {
- let resp = await fetch("https://data.wowtoken.app/token/current.json");
- let data = await resp.json();
- updateTokens(data);
+ await updateTokens(await fetchCurrent());
}
-function updateTokens(data) {
- updateRegionalToken('us', data);
- updateRegionalToken('eu', data);
- updateRegionalToken('kr', data);
- updateRegionalToken('tw', data);
+async function updateTokens(data) {
+ await Promise.all([
+ updateRegionalToken('us', data),
+ updateRegionalToken('eu', data),
+ updateRegionalToken('kr', data),
+ updateRegionalToken('tw', data)
+ ]);
}
-function updateRegionalToken(region, data) {
+async function updateRegionalToken(region, data) {
if (currentPriceHash[region] !== data['price_data'][region]) {
currentPriceHash[region] = data['price_data'][region];
if (region === currentRegionSelection) {
formatToken();
- if (currentAggregateSelection === 'none') {
- addDataToChart(region, data);
+ const datum = new Datum(data['current_time'], data['price']);
+ if (currentAggregateSelection === 'none' && chart.active()) {
+ await chart.addDataToChart(datum);
+ }
+ else if (currentAggregateSelection === 'none' && !chart.active()) {
+ await chart.lateUpdate(datum);
}
}
}
}
-function addDataToChart(region, data) {
- if (tokenChart) {
- const datum = {x: data['current_time'], y: data['price_data'][region]}
- tokenChart.data.datasets.forEach((dataset) => {
- dataset.data.push(datum);
- })
- tokenChart.update();
- }
-}
-
async function aggregateFunctionToggle() {
// TODO: We should probably make these global or something
// so if the need to be updated in the future we can do so easily
@@ -177,54 +177,33 @@ async function aggregateFunctionToggle() {
}
}
-function addLoader() {
- let loader = document.getElementById('loader');
- if (!loader) {
- const blank_div = document.createElement('div');
- let loaderNode = blank_div.cloneNode();
- loaderNode.id = 'loader';
- loaderNode.className = 'lds-ripple';
- loaderNode.appendChild(blank_div.cloneNode());
- loaderNode.appendChild(blank_div.cloneNode());
- let chartNode = document.getElementById('token-chart');
- chartNode.before(loaderNode);
- }
-}
-
-function removeLoader () {
- let loader = document.getElementById('loader');
- if (loader) {
- loader.remove();
- }
-}
-
-function updateRegionPreference(newRegion) {
+async function updateRegionPreference(newRegion) {
if (newRegion !== currentRegionSelection) {
- tokenChart.destroy();
+ await chart.destroyChart();
addLoader();
currentRegionSelection = newRegion;
}
formatToken();
- pullChartData().then(populateChart);
+ await pullChartData();
}
-function updateTimePreference(newTime) {
+async function updateTimePreference(newTime) {
if (newTime !== currentTimeSelection) {
- tokenChart.destroy();
+ await chart.destroyChart();
addLoader();
currentTimeSelection = newTime;
- aggregateFunctionToggle();
+ await aggregateFunctionToggle();
}
- pullChartData().then(populateChart);
+ await pullChartData();
}
-function updateAggregatePreference(newAggregate) {
+async function updateAggregatePreference(newAggregate) {
if (newAggregate !== currentAggregateSelection) {
- tokenChart.destroy();
+ await chart.destroyChart();
addLoader();
currentAggregateSelection = newAggregate;
}
- pullChartData().then(populateChart);
+ await pullChartData();
}
function toggleAdvancedSetting() {
@@ -241,33 +220,19 @@ function toggleAdvancedSetting() {
function toggleStartYAtZero(){
startYAtZero = document.getElementById('y-start').checked;
- if (tokenChart){
- tokenChart.options.scales.y.beginAtZero = startYAtZero;
- tokenChart.update();
- }
-}
-
-function urlBuilder() {
- let url = "https://data.wowtoken.app/token/history/";
- if (currentAggregateSelection !== 'none') {
- url += `${currentAggregateSelection}/`
- }
- url += `${currentRegionSelection}/${currentTimeSelection}.json`
- return url;
+ chart.toggleYStart(startYAtZero);
}
async function pullChartData() {
- let resp = await fetch(urlBuilder());
- let chartData = await resp.json();
- let newChartJSData = [];
- for (let i = 0; i < chartData.length; i++) {
- let datum = {
- x: chartData[i]['time'],
- y: chartData[i]['value']
- };
- newChartJSData.push(datum);
+ chartData[currentRegionSelection] = await fetchData(currentRegionSelection, currentTimeSelection, currentAggregateSelection);
+ if (!chart.active()) {
+ await chart.createChart(currentRegionSelection, currentTimeSelection, startYAtZero, chartData[currentRegionSelection]);
+ }
+ else {
+ for (let i = 0; i < chartData[currentRegionSelection].length; i++) {
+ await chart.addDataToChart(chartData[currentRegionSelection][i]);
+ }
}
- chartJsData = newChartJSData;
removeLoader();
}
@@ -428,7 +393,11 @@ function registerOptionHandlers() {
document.addEventListener('DOMContentLoaded', function () {
registerEventHandles();
detectURLQuery();
- Promise.all([callUpdateURL(), pullChartData()]).then(populateChart)
+ chart = new TokenChart();
+ Promise.all([
+ callUpdateURL(),
+ ]).then(pullChartData);
+
setInterval(callUpdateURL, 60*1000);
}, false);
diff --git a/src/loader.js b/src/loader.js
@@ -0,0 +1,22 @@
+function addLoader() {
+ let loader = document.getElementById('loader');
+ if (!loader) {
+ const blank_div = document.createElement('div');
+ let loaderNode = blank_div.cloneNode();
+ loaderNode.id = 'loader';
+ loaderNode.className = 'lds-ripple';
+ loaderNode.appendChild(blank_div.cloneNode());
+ loaderNode.appendChild(blank_div.cloneNode());
+ let chartNode = document.getElementById('token-chart');
+ chartNode.before(loaderNode);
+ }
+}
+
+function removeLoader () {
+ let loader = document.getElementById('loader');
+ if (loader) {
+ loader.remove();
+ }
+}
+
+export {addLoader, removeLoader};
+\ No newline at end of file
diff --git a/src/tokenChart.js b/src/tokenChart.js
@@ -0,0 +1,135 @@
+import {
+ Chart,
+ Legend,
+ LinearScale,
+ LineController,
+ LineElement,
+ PointElement,
+ TimeSeriesScale,
+ Title,
+ Tooltip
+} from 'chart.js';
+import 'chartjs-adapter-dayjs-3';
+
+function lookupTimeUnit(query){
+ const lookup = {
+ 'h': 'day',
+ 'd': 'week',
+ 'm': 'month',
+ 'y': 'month',
+ 'l': 'year'
+ }
+ return lookup[query.charAt(query.length - 1)]
+}
+
+export default class TokenChart {
+ constructor() {
+ this._context = document.getElementById("token-chart").getContext('2d');
+ this._chartActive = false;
+ this._lastDatum = null;
+ this._lateUpdate = true
+ }
+
+ async createChart(region, time, yLevel, data = []) {
+ const chartData = [];
+ let lateUpdateData = this._lastDatum;
+
+ for (let i = 0; i < data.length; i++) {
+ this._lastDatum = data[i];
+ chartData.push({
+ x: data[i].getX(),
+ y: data[i].getY(),
+ })
+ }
+
+ if (this._lateUpdate) {
+ if (this._lastDatum.getPrice() !== lateUpdateData.getPrice() &&
+ this._lastDatum.getTime() < lateUpdateData.getTime()) {
+ chartData.push({
+ x: lateUpdateData.getX(),
+ y: lateUpdateData.getY(),
+ })
+ }
+ this._lateUpdate = false
+ }
+
+ this._chart = new Chart(this._context, {
+ type: 'line',
+ data: {
+ datasets: [{
+ borderColor: 'gold',
+ label: region.toUpperCase() + " WoW Token Price",
+ data: chartData,
+ cubicInterpolationMode: 'monotone',
+ pointRadius: 0
+ }]
+ },
+ options: {
+ interaction: {
+ intersect: false,
+ mode: "index"
+ },
+ scales: {
+ x: {
+ type: 'time',
+ grid: {
+ color: '#625f62',
+ },
+ ticks: {
+ color: '#a7a4ab',
+ font: {
+ size: 18,
+ }
+ },
+ time: {
+ unit: lookupTimeUnit(time)
+ }
+ },
+ y: {
+ beginAtZero: yLevel,
+ grid: {
+ color: '#2f2c2f',
+ },
+ ticks: {
+ color: '#a7a4ab',
+ font: {
+ size: 18,
+ }
+ }
+ }
+ },
+ }
+ });
+ this._chartActive = true;
+ }
+
+ async destroyChart() {
+ await this._chart.destroy();
+ this._chartActive = false;
+ }
+
+ async lateUpdate(datum){
+ this._lastDatum = datum;
+ this._lateUpdate = true;
+ }
+
+ async addDataToChart(datum) {
+ this._chart.data.datasets.forEach((dataset) => {
+ dataset.data.push({
+ x: datum.getX(),
+ y: datum.getY(),
+ })
+ });
+ this._chart.update();
+ }
+
+ active() {
+ return this._chartActive;
+ }
+
+ toggleYStart(startYAtZero) {
+ this._chart.options.scales.y.beginAtZero = startYAtZero;
+ this._chart.update();
+ }
+
+}
+\ No newline at end of file
diff --git a/src/urlBuilder.js b/src/urlBuilder.js
@@ -0,0 +1,8 @@
+export default function urlBuilder(currentRegionSelection, currentTimeSelection, currentAggregateSelection) {
+ let url = "https://data.wowtoken.app/token/history/";
+ if (currentAggregateSelection !== 'none') {
+ url += `${currentAggregateSelection}/`
+ }
+ url += `${currentRegionSelection}/${currentTimeSelection}.json`
+ return url;
+}
+\ No newline at end of file