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.

(cherry picked from commit a51d3f8d7b)
This commit is contained in:
Emily Doherty 2024-10-13 23:23:31 -07:00
parent f207e36ccd
commit 7a17bb8821
7 changed files with 253 additions and 79 deletions

22
src/datum.js Normal file
View File

@ -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();
}
}

4
src/fetchCurrent.js Normal file
View File

@ -0,0 +1,4 @@
export default async function fetchCurrent() {
const resp = await fetch("https://data.wowtoken.app/classic/token/current.json");
return await resp.json();
}

13
src/fetchData.js Normal file
View File

@ -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;
}

View File

@ -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 Classic Token Price",
data: chartJsData,
data: [],
cubicInterpolationMode: 'monotone',
pointRadius: 0
}]
@ -117,47 +124,41 @@ function lookupTimeUnit(query){
'd': 'week',
'm': 'month',
'y': 'month',
'l': 'month'
'l': 'year'
}
return lookup[query.charAt(query.length - 1)]
}
async function callUpdateURL() {
let resp = await fetch("https://data.wowtoken.app/classic/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 +178,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 +221,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/classic/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 +394,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);

22
src/loader.js Normal file
View File

@ -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};

135
src/tokenChart.js Normal file
View File

@ -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();
}
}

8
src/urlBuilder.js Normal file
View File

@ -0,0 +1,8 @@
export default function urlBuilder(currentRegionSelection, currentTimeSelection, currentAggregateSelection) {
let url = "https://data.wowtoken.app/classic/token/history/";
if (currentAggregateSelection !== 'none') {
url += `${currentAggregateSelection}/`
}
url += `${currentRegionSelection}/${currentTimeSelection}.json`
return url;
}