-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- boost links so we don't load full page - implement "routing" - ensure setup event happens before load eventload partial pages
- Loading branch information
Showing
15 changed files
with
256 additions
and
219 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import functools | ||
import json | ||
|
||
import flask | ||
|
||
|
||
def hx_page(template): | ||
"""set response header to trigger event to initialise frontend assets (if needed)""" | ||
def decorator(f): | ||
@functools.wraps(f) | ||
def decorated_function(*args, **kwargs): | ||
template_name = template | ||
ctx = f(*args, **kwargs) | ||
resp = flask.Response(flask.render_template(template_name)) | ||
resp.headers['HX-Trigger-After-Settle'] = json.dumps({'initPage': ctx}) | ||
return resp | ||
return decorated_function | ||
return decorator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from app.api import bp | ||
from app.api import utils | ||
|
||
|
||
@bp.get('/') | ||
@utils.hx_page('index.html') | ||
def index(): | ||
return {'path': '/'} | ||
|
||
|
||
@bp.get('/analytics') | ||
@utils.hx_page('analytics.html') | ||
def analytics(): | ||
return {'path': '/analytics'} | ||
|
||
|
||
@bp.get('/yahoo') | ||
@utils.hx_page('yahoo.html') | ||
def yahoo(): | ||
return {'path': '/yahoo'} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
function updateChart(evt) { | ||
const chart = Chart.getChart(evt.detail.target); | ||
// https://www.reddit.com/r/htmx/comments/10sdk43/comment/j72m2j7/ | ||
const data = JSON.parse(document.getElementById(evt.detail.dataId).textContent); | ||
for (const dataset of data.datasets) { | ||
chart.data.datasets.push(dataset); | ||
} | ||
if (data.labels != null) { | ||
chart.data.labels = data.labels; | ||
} | ||
chart.update(); | ||
document.getElementById(evt.detail.dataId).remove(); | ||
} | ||
|
||
function displayPrices(evt) { | ||
const chart = Chart.getChart(evt.detail.target); | ||
const table = Tabulator.findTable("#priceTable")[0]; | ||
const data = JSON.parse(document.getElementById(evt.detail.dataId).textContent); | ||
const prices = data.indicators.quote[0].close; | ||
// ideally, should check overlap of labels between datasets | ||
table.updateOrAddData(data.timestamp.map((a, i) => ({ date: a, [data.meta.symbol]: prices[i] }))); | ||
if (!table.columnManager.columns.length) { | ||
table.addColumn({ title: "Date", field: "date", frozen: true }, true); | ||
} | ||
table.addColumn({ | ||
title: data.meta.symbol, | ||
field: data.meta.symbol, | ||
hozAlign: "right", | ||
headerSort: false, | ||
formatter: "money", | ||
formatterParams: { thousand: false }, | ||
}); | ||
chart.data.labels = data.timestamp; | ||
// change prices to percentage so it's comparable | ||
chart.data.datasets.push({ | ||
label: data.meta.symbol, | ||
data: prices.map((x) => ((x - prices[0]) / prices[0]) * 100), | ||
}); | ||
chart.update(); | ||
document.getElementById(evt.detail.dataId).remove(); | ||
} | ||
|
||
export { displayPrices, updateChart }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { displayPrices, updateChart } from "../../static/js/api.js"; | ||
import setupYahooPage from "../../static/js/page.yahoo.js"; | ||
|
||
const router = (evt) => { | ||
let func; | ||
switch (window.location.pathname) { | ||
case "/analytics": | ||
// dynamic modules example. not sure this is relevant if you bundle js | ||
import("../../static/js/page.analytics.js").then((module) => { | ||
module.default(); | ||
// custom trigger as this will lose race with load event | ||
htmx.trigger("body", "pageReady", {}); | ||
}); | ||
break; | ||
case "/yahoo": | ||
func = setupYahooPage(); | ||
// custom event so that setup logic doesn't race hx-trigger: load | ||
// technically not needed unless setup logic is absurdly long | ||
document.body.dispatchEvent(new Event("pageReady")); | ||
break; | ||
} | ||
}; | ||
|
||
// NOTE: addlistener should target named func to avoid dup listeners if called multiple times | ||
// handle full page load | ||
window.addEventListener("DOMContentLoaded", router); | ||
// handle swap load | ||
window.addEventListener("initPage", router); | ||
// handle browser back/fwd. location.reload() on popstate works as well but is terrible solution | ||
window.addEventListener("htmx:historyRestore", router); | ||
|
||
// TODO: use single event and process based on response/url | ||
window.addEventListener("displayPrices", displayPrices); | ||
window.addEventListener("drawChart", updateChart); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { arbLines } from "../../static/js/chart.plugins.arblines.js"; | ||
import { crosshairs } from "../../static/js/chart.plugins.crosshairs.js"; | ||
import { toggleView } from "../../static/js/chart.utils.js"; | ||
|
||
// https://stackoverflow.com/questions/67402685/vanilla-js-spa-how-to-load-specific-scripts-under-the-inserted-html-of-the-spa | ||
// https://stackoverflow.com/questions/68554391/how-to-load-javascript-after-all-dom-element-rendered-in-vanilla-javascript | ||
// https://stackoverflow.com/questions/54231533/how-to-create-a-vanilla-js-routing-for-spa | ||
export default function setupAnalyticsPage() { | ||
window.toggleView = toggleView; | ||
|
||
new Chart(document.getElementById("chartId"), { | ||
type: "bar", | ||
options: { | ||
responsive: true, | ||
title: { | ||
display: false, | ||
text: "", | ||
}, | ||
}, | ||
data: { | ||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], | ||
}, | ||
}); | ||
|
||
new Chart(document.getElementById("lineChartId"), { | ||
type: "line", | ||
plugins: [arbLines, crosshairs], | ||
options: { | ||
events: ["mousedown", "mouseup", "mousemove"], | ||
responsive: true, | ||
plugins: { | ||
colors: { | ||
forceOverride: true, | ||
}, | ||
legend: { | ||
position: "top", | ||
}, | ||
title: { | ||
display: true, | ||
text: "Vehicles Sales", | ||
}, | ||
tooltip: { | ||
position: "average", | ||
}, | ||
}, | ||
interaction: { | ||
axis: "x", | ||
intersect: false, | ||
mode: "nearest", | ||
}, | ||
}, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { crosshairs } from "../../static/js/chart.plugins.crosshairs.js"; | ||
|
||
export default function setupYahooPage() { | ||
new Chart(document.getElementById("priceChart"), { | ||
type: "line", | ||
plugins: [crosshairs], | ||
options: { | ||
events: ["mousedown", "mouseup", "mousemove"], | ||
responsive: true, | ||
layout: { | ||
padding: { | ||
left: 15, | ||
}, | ||
}, | ||
scales: { | ||
x: { | ||
parsing: false, | ||
type: "time", // to convert iso date to english | ||
time: { | ||
unit: "day", | ||
}, | ||
}, | ||
}, | ||
plugins: { | ||
colors: { | ||
forceOverride: true, | ||
}, | ||
legend: { | ||
position: "top", | ||
}, | ||
title: { | ||
display: false, | ||
text: "Security Prices", | ||
}, | ||
tooltip: { | ||
position: "nearest", | ||
}, | ||
}, | ||
interaction: { | ||
axis: "x", | ||
intersect: false, | ||
mode: "nearest", | ||
}, | ||
}, | ||
}); | ||
|
||
new Tabulator("#priceTable", { | ||
layout: "fitData", | ||
index: "date", | ||
pagination: true, //enable. | ||
paginationSize: 10, // this option can take any positive integer value | ||
placeholder: function () { | ||
//set placeholder based on if there are currently any header filters | ||
return this.initialised && this.getHeaderFilters().length ? "No Matching Data" : "No Data"; | ||
}, | ||
}); | ||
} |
Oops, something went wrong.