From: Max Value Date: Mon, 30 Mar 2026 14:46:58 +0000 (+0100) Subject: Build updater for TS & start of admin page template X-Git-Url: https://git.ozva.co.uk/?a=commitdiff_plain;h=4d90450a994ff720ab8fd39d284f5eafd825f6a1;p=delta-velorum Build updater for TS & start of admin page template --- diff --git a/.gitignore b/.gitignore index 3d43339..a44e81e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ __pycache__/ +data/ diff --git a/director/__init__.py b/director/__init__.py index dd366a6..58b1e7a 100644 --- a/director/__init__.py +++ b/director/__init__.py @@ -1,10 +1,9 @@ from flask import Flask, render_template, send_from_directory +from flask_socketio import SocketIO, emit import os app = Flask(__name__, instance_relative_config=False) -app.config.from_mapping( - DATABASE=os.path.join(app.root_path, 'flaskr.sqlite') -) +socketio = SocketIO(app, logger=True, engineio_logger=True) @app.route("/", methods=['get']) def index(): @@ -13,3 +12,9 @@ def index(): @app.route("/script/", methods=["get"]) def script(filename): return send_from_directory(os.path.join(app.root_path, "build"), filename) + +@app.route("/test") +def test(): + #emit("update", ["data__product", {"data":{"product":{"currentPrice":100}}}], json=True, namespace="/", broadcast=True) + + return "" diff --git a/director/src/price.ts b/director/src/price.ts new file mode 100644 index 0000000..e91bd50 --- /dev/null +++ b/director/src/price.ts @@ -0,0 +1,31 @@ +const unstablePriceChance: number = 0.7; + +export function renderPrice(): void { + const el: HTMLCollectionOf = + document.getElementsByClassName("price"); + + for (let e of el) { + if (e instanceof HTMLElement) { + if (typeof e.dataset.raw === "string") { + e.innerHTML = String(parseFloat(e.dataset.raw).toFixed(2)); + } + } + } +} + +export function renderUnstablePrice(): void { + const el: HTMLCollectionOf = + document.getElementsByClassName("unstablePrice"); + + for (let e of el) { + if (e instanceof HTMLElement) { + if (typeof e.dataset.raw === "string") { + if (Math.random() < unstablePriceChance) { + e.innerHTML = String(parseFloat(e.dataset.raw).toFixed(2)); + } else { + e.innerHTML = String(parseFloat(e.dataset.raw)); + } + } + } + } +} diff --git a/director/src/text.ts b/director/src/text.ts new file mode 100644 index 0000000..d7a6032 --- /dev/null +++ b/director/src/text.ts @@ -0,0 +1,10 @@ +export function renderText(): void { + const el = document.querySelectorAll(".text,.title"); + for (let e of el) { + if (e instanceof HTMLElement) { + if (typeof e.dataset.raw === "string") { + e.innerHTML = e.dataset.raw; + } + } + } +} diff --git a/director/src/title.ts b/director/src/title.ts deleted file mode 100644 index 123811b..0000000 --- a/director/src/title.ts +++ /dev/null @@ -1,7 +0,0 @@ -export default function renderTitle(): void { - const el: HTMLCollectionOf = document.getElementsByClassName("title"); - - for (let e of el) { - console.log(e); - } -} diff --git a/director/src/update.ts b/director/src/update.ts index fa3dfc5..275921d 100644 --- a/director/src/update.ts +++ b/director/src/update.ts @@ -1,8 +1,37 @@ -import renderTitle from "./title.js"; -export {}; +import { renderText } from "./text.js"; +import { renderPrice, renderUnstablePrice } from "./price.js" +import { io } from "socket.io-client"; -function update(): void { - renderTitle(); +// apply a number of sequential keys to an object +function objectPath(obj: any, path: string[]): any { + let key: string|undefined = path.shift(); + if (typeof key === "undefined") { + return obj + } else { + return objectPath(obj[key], path) + } } -update(); +export default function setupUpdate(): void { + const socket = io(); + socket.on("update", ([namespace, data]) => { + const el = document.querySelectorAll(`.update[class*='${namespace}']`); + + for (let e of el) { + let c: string|undefined = Array.from(e.classList) + .find((c) => c.startsWith(namespace)) + + if (typeof c === "string") { + let path = c.split("__"); + let result = objectPath(data, path); + + if (typeof result !== "undefined" && e instanceof HTMLElement) { + e.dataset.raw = result; + } + } + } + + renderPrice(); + renderUnstablePrice(); + }) +} diff --git a/director/static/style.css b/director/static/style.css new file mode 100644 index 0000000..892f158 --- /dev/null +++ b/director/static/style.css @@ -0,0 +1 @@ +title { text-transform: capitalize; } diff --git a/director/templates/admin.html b/director/templates/admin.html new file mode 100644 index 0000000..ab7de6b --- /dev/null +++ b/director/templates/admin.html @@ -0,0 +1,12 @@ +{# + + builds the admin page + +#} + + +
+ {% include "admin/list.html" %} + + + diff --git a/director/templates/admin/list.html b/director/templates/admin/list.html new file mode 100644 index 0000000..a5788c5 --- /dev/null +++ b/director/templates/admin/list.html @@ -0,0 +1,18 @@ +{# + + interates through the state variable and includes the relevant template for + each element. not tested more than double nested + +#} +{% for element in state %} + {% if element.tag == "textarea" %} + {% include "admin/textarea.html" %} + {% elif element.tag == "select" %} + {% include "admin/select.html" %} + {% elif element.tag == "text" %} + {% include "admin/text.html" %} + {% elif element.tag == "number" %} + {% include "admin/number.html" %} + {% endif %} +
+{% endfor %} diff --git a/director/templates/admin/number.html b/director/templates/admin/number.html new file mode 100644 index 0000000..6beaef2 --- /dev/null +++ b/director/templates/admin/number.html @@ -0,0 +1,2 @@ +
+ diff --git a/director/templates/admin/select.html b/director/templates/admin/select.html new file mode 100644 index 0000000..0fe6770 --- /dev/null +++ b/director/templates/admin/select.html @@ -0,0 +1,10 @@ +
+ {{ element.name }} + +
+ {% block list %} + {% set state = element.elements %} + {% include "admin/list.html" %} + {% endblock %} +
+
diff --git a/director/templates/admin/text.html b/director/templates/admin/text.html new file mode 100644 index 0000000..3ea4709 --- /dev/null +++ b/director/templates/admin/text.html @@ -0,0 +1,3 @@ +
+ + diff --git a/director/templates/admin/textarea.html b/director/templates/admin/textarea.html new file mode 100644 index 0000000..f22eb50 --- /dev/null +++ b/director/templates/admin/textarea.html @@ -0,0 +1,4 @@ +
+ diff --git a/director/templates/index.html b/director/templates/index.html index f1e0771..5f9cbf8 100644 --- a/director/templates/index.html +++ b/director/templates/index.html @@ -1,9 +1,22 @@ - + + + - + This is some text diff --git a/requirements.txt b/requirements.txt index 7e10602..34b5c1d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ +flask_socketio flask diff --git a/tsconfig.json b/tsconfig.json index e0bf5b8..3c138d2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,45 +1,15 @@ { - // Visit https://aka.ms/tsconfig to read more about this file - "include": ["./director/src"], + "include": ["./director/src","./director/static"], + "compilerOptions": { - // File Layout "rootDir": "./director/src", "outDir": "./director/build", - // Environment Settings - // See also https://aka.ms/tsconfig/module - "module": "nodenext", + "module": "esnext", "target": "esnext", - "types": [], - // For nodejs: - // "lib": ["esnext"], - // "types": ["node"], - // and npm install -D @types/node - - // Other Outputs - "sourceMap": true, - "declaration": true, - "declarationMap": true, - - // Stricter Typechecking Options - "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": true, - - // Style Options - // "noImplicitReturns": true, - // "noImplicitOverride": true, - // "noUnusedLocals": true, - // "noUnusedParameters": true, - // "noFallthroughCasesInSwitch": true, - // "noPropertyAccessFromIndexSignature": true, - // Recommended Options - "strict": true, - "jsx": "react-jsx", - "verbatimModuleSyntax": false, - "isolatedModules": true, - "noUncheckedSideEffectImports": true, - "moduleDetection": "force", - "skipLibCheck": true, + "allowJs": true, + "checkJs": false, + "resolveJsonModule": true } }