From c1b0421650f216adb410b29b9a862d30630fd1f2 Mon Sep 17 00:00:00 2001 From: Dilan Gilluly Date: Fri, 7 Nov 2025 15:01:36 -0500 Subject: [PATCH] settings file and screen --- webapp/.gitignore | 1 + webapp/Dockerfile | 1 + webapp/src/lib/server/settings.js | 19 +++++++ webapp/src/routes/+page.svelte | 1 + webapp/src/routes/api/+server.js | 3 +- .../src/routes/api/backuprestore/+server.js | 4 +- webapp/src/routes/api/baskets/+server.js | 32 +++++------ .../[prefix]/[b_from]/[b_to]/+server.js | 3 +- webapp/src/routes/api/combined/+server.js | 4 +- .../[prefix]/[b_from]/[b_to]/+server.js | 3 +- .../api/combined/[prefix]/[b_id]/+server.js | 3 +- webapp/src/routes/api/counts/+server.js | 3 +- webapp/src/routes/api/prefixes/+server.js | 4 +- .../src/routes/api/prefixes/[name]/+server.js | 4 +- .../api/reports/bybasket/[prefix]/+server.js | 3 +- .../api/reports/byname/[prefix]/+server.js | 3 +- webapp/src/routes/api/settings/+server.js | 11 ++++ webapp/src/routes/api/tickets/+server.js | 4 +- .../[prefix]/[t_from]/[t_to]/+server.js | 3 +- .../api/tickets/[prefix]/[t_id]/+server.js | 3 +- webapp/src/routes/settings/+page.js | 5 ++ webapp/src/routes/settings/+page.svelte | 53 +++++++++++++++++++ 22 files changed, 141 insertions(+), 29 deletions(-) create mode 100644 webapp/src/lib/server/settings.js create mode 100644 webapp/src/routes/api/settings/+server.js create mode 100644 webapp/src/routes/settings/+page.js create mode 100644 webapp/src/routes/settings/+page.svelte diff --git a/webapp/.gitignore b/webapp/.gitignore index 171f629..28f262a 100644 --- a/webapp/.gitignore +++ b/webapp/.gitignore @@ -17,6 +17,7 @@ Thumbs.db .env.* !.env.example !.env.test +settings.json # Vite vite.config.js.timestamp-* diff --git a/webapp/Dockerfile b/webapp/Dockerfile index 7451286..8795f86 100644 --- a/webapp/Dockerfile +++ b/webapp/Dockerfile @@ -7,6 +7,7 @@ COPY . . RUN npm install && npm run build ENV DATABASE_URL=file:/data/local.db +ENV SETTINGS_PATH=/data/settings.json ENV BODY_SIZE_LIMIT=100M ENV NODE_TLS_REJECT_UNAUTHORIZED=0 diff --git a/webapp/src/lib/server/settings.js b/webapp/src/lib/server/settings.js new file mode 100644 index 0000000..a98a411 --- /dev/null +++ b/webapp/src/lib/server/settings.js @@ -0,0 +1,19 @@ +import { env } from "$env/dynamic/private"; +import fs from "fs"; + +export function readSettings() { + if (fs.existsSync(env.SETTINGS_PATH)) { + const rawFileData = fs.readFileSync(env.SETTINGS_PATH, 'utf-8'); + const fileData = JSON.parse(rawFileData); + return fileData; + } else { + const fileData = {TAM3_REMOTE: env.TAM3_REMOTE || "", TAM3_REMOTE_KEY: env.TAM3_REMOTE_KEY || ""}; + fs.writeFileSync(env.SETTINGS_PATH, JSON.stringify(fileData, null, 2)); + return fileData; + } +} + +export function writeSettings(settingsObj) { + fs.writeFileSync(env.SETTINGS_PATH, JSON.stringify(settingsObj, null, 2)); + return "File written successfully." +} \ No newline at end of file diff --git a/webapp/src/routes/+page.svelte b/webapp/src/routes/+page.svelte index 08a2382..0d22169 100644 --- a/webapp/src/routes/+page.svelte +++ b/webapp/src/routes/+page.svelte @@ -74,6 +74,7 @@
Prefix Editor Backup/Restore + Settings
{/if} diff --git a/webapp/src/routes/api/+server.js b/webapp/src/routes/api/+server.js index 46b8328..5efa732 100644 --- a/webapp/src/routes/api/+server.js +++ b/webapp/src/routes/api/+server.js @@ -1,6 +1,7 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; export async function GET() { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { diff --git a/webapp/src/routes/api/backuprestore/+server.js b/webapp/src/routes/api/backuprestore/+server.js index 80563b8..3774ce7 100644 --- a/webapp/src/routes/api/backuprestore/+server.js +++ b/webapp/src/routes/api/backuprestore/+server.js @@ -1,10 +1,11 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { prefixes, tickets, baskets } from "$lib/server/db/schema"; import { sql } from "drizzle-orm"; import { chunkArray } from "$lib/server/chunkArray"; export async function GET() { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/backuprestore/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { @@ -21,6 +22,7 @@ export async function GET() { } export async function POST({ request }) { + const env = readSettings(); const req = await request.json(); for (let prefixChunk of chunkArray(req.prefixes, 300)) { await db.insert(prefixes).values(prefixChunk).onConflictDoUpdate({target: prefixes.name, set: {color: sql`excluded.color`, weight: sql`excluded.weight`}}); diff --git a/webapp/src/routes/api/baskets/+server.js b/webapp/src/routes/api/baskets/+server.js index 4c2af80..5a46765 100644 --- a/webapp/src/routes/api/baskets/+server.js +++ b/webapp/src/routes/api/baskets/+server.js @@ -1,10 +1,11 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { sql } from "drizzle-orm"; import { baskets } from "$lib/server/db/schema"; import { chunkArray } from "$lib/server/chunkArray"; export async function GET() { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/baskets/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { @@ -27,19 +28,20 @@ export async function GET() { } export async function POST({ request }) { - const i_baskets = await request.json(); - for (let basketChunk of chunkArray(i_baskets, 300)) { - await db.insert(baskets).values(basketChunk) - .onConflictDoUpdate({target: [baskets.prefix, baskets.b_id], set: {description: sql`excluded.description`, donors: sql`excluded.donors`, winning_ticket: sql`excluded.winning_ticket`}}) + const env = readSettings(); + const i_baskets = await request.json(); + for (let basketChunk of chunkArray(i_baskets, 300)) { + await db.insert(baskets).values(basketChunk) + .onConflictDoUpdate({target: [baskets.prefix, baskets.b_id], set: {description: sql`excluded.description`, donors: sql`excluded.donors`, winning_ticket: sql`excluded.winning_ticket`}}) + }; + if (env.TAM3_REMOTE) { + const res = await fetch(`${env.TAM3_REMOTE}/api/baskets/?api_key=${env.TAM3_REMOTE_KEY}`, { + body: JSON.stringify([...i_baskets]), method: 'POST', headers: {'Content-Type': 'application/json'} + }); + if (!res.ok) { + return new Response(JSON.stringify({details: "Issue posting baskets to remote."}), {status: res.status, statusText: res.statusText}) }; - if (env.TAM3_REMOTE) { - const res = await fetch(`${env.TAM3_REMOTE}/api/baskets/?api_key=${env.TAM3_REMOTE_KEY}`, { - body: JSON.stringify([...i_baskets]), method: 'POST', headers: {'Content-Type': 'application/json'} - }); - if (!res.ok) { - return new Response(JSON.stringify({details: "Issue posting baskets to remote."}), {status: res.status, statusText: res.statusText}) - }; - const data = await res.json(); - }; - return new Response(JSON.stringify({details: "Posted baskets successfully."}), {status: 200, statusText: "Posted baskets successfully."}) + const data = await res.json(); + }; + return new Response(JSON.stringify({details: "Posted baskets successfully."}), {status: 200, statusText: "Posted baskets successfully."}) } \ No newline at end of file diff --git a/webapp/src/routes/api/baskets/[prefix]/[b_from]/[b_to]/+server.js b/webapp/src/routes/api/baskets/[prefix]/[b_from]/[b_to]/+server.js index d10a07b..707fca3 100644 --- a/webapp/src/routes/api/baskets/[prefix]/[b_from]/[b_to]/+server.js +++ b/webapp/src/routes/api/baskets/[prefix]/[b_from]/[b_to]/+server.js @@ -1,9 +1,10 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { baskets } from "$lib/server/db/schema"; import { eq, and } from "drizzle-orm"; export async function GET({ params }) { + const env = readSettings(); let n_b_from = parseInt(params.b_from), n_b_to = parseInt(params.b_to); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/baskets/${params.prefix}/${n_b_from}/${n_b_to}/?api_key=${env.TAM3_REMOTE_KEY}`); diff --git a/webapp/src/routes/api/combined/+server.js b/webapp/src/routes/api/combined/+server.js index fd9f1fc..7750d35 100644 --- a/webapp/src/routes/api/combined/+server.js +++ b/webapp/src/routes/api/combined/+server.js @@ -1,10 +1,11 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { sql } from "drizzle-orm"; import { baskets, combined } from "$lib/server/db/schema"; import { chunkArray } from "$lib/server/chunkArray"; export async function GET() { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/combined/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { @@ -22,6 +23,7 @@ export async function GET() { } export async function POST({ request }) { + const env = readSettings(); const r_data = await request.json() for (let winnerChunk of chunkArray(r_data, 300)) { await db.insert(baskets).values(winnerChunk) diff --git a/webapp/src/routes/api/combined/[prefix]/[b_from]/[b_to]/+server.js b/webapp/src/routes/api/combined/[prefix]/[b_from]/[b_to]/+server.js index d7e69d8..5d4adf3 100644 --- a/webapp/src/routes/api/combined/[prefix]/[b_from]/[b_to]/+server.js +++ b/webapp/src/routes/api/combined/[prefix]/[b_from]/[b_to]/+server.js @@ -1,9 +1,10 @@ -import { env } from "process"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { combined } from "$lib/server/db/schema"; import { eq, and } from "drizzle-orm"; export async function GET({ params }) { + const env = readSettings(); const n_b_from = parseInt(params.b_from), n_b_to = parseInt(params.b_to); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/combined/${params.prefix}/${n_b_from}/${n_b_to}/?api_key=${env.TAM3_REMOTE_KEY}`); diff --git a/webapp/src/routes/api/combined/[prefix]/[b_id]/+server.js b/webapp/src/routes/api/combined/[prefix]/[b_id]/+server.js index 53e2c2d..3997987 100644 --- a/webapp/src/routes/api/combined/[prefix]/[b_id]/+server.js +++ b/webapp/src/routes/api/combined/[prefix]/[b_id]/+server.js @@ -1,9 +1,10 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { combined } from "$lib/server/db/schema"; import { eq, and } from "drizzle-orm"; export async function GET({ params }) { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/combined/${params.prefix}/${params.b_id}/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { diff --git a/webapp/src/routes/api/counts/+server.js b/webapp/src/routes/api/counts/+server.js index 5ea47f9..ea90e30 100644 --- a/webapp/src/routes/api/counts/+server.js +++ b/webapp/src/routes/api/counts/+server.js @@ -1,8 +1,9 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { counts } from "$lib/server/db/schema"; export async function GET() { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/counts/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { diff --git a/webapp/src/routes/api/prefixes/+server.js b/webapp/src/routes/api/prefixes/+server.js index b8f2d87..35a4cfa 100644 --- a/webapp/src/routes/api/prefixes/+server.js +++ b/webapp/src/routes/api/prefixes/+server.js @@ -1,8 +1,9 @@ +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { prefixes } from "$lib/server/db/schema"; -import { env } from "$env/dynamic/private"; export async function GET() { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/prefixes/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { @@ -17,6 +18,7 @@ export async function GET() { } export async function POST({ request }) { + const env = readSettings(); const { name, color, weight } = await request.json(); await db.insert(prefixes).values({name: name, color: color, weight: weight}).onConflictDoUpdate({target: prefixes.name, set: {color: color, weight: weight}}); if (env.TAM3_REMOTE) { diff --git a/webapp/src/routes/api/prefixes/[name]/+server.js b/webapp/src/routes/api/prefixes/[name]/+server.js index dcf1f52..1be583e 100644 --- a/webapp/src/routes/api/prefixes/[name]/+server.js +++ b/webapp/src/routes/api/prefixes/[name]/+server.js @@ -1,9 +1,10 @@ +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { eq } from "drizzle-orm"; import { prefixes } from "$lib/server/db/schema"; -import { env } from "$env/dynamic/private"; export async function GET({ params }) { + const env = readSettings(); let { name } = params; if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/prefixes/${name}/?api_key=${env.TAM3_REMOTE_KEY}`); @@ -23,6 +24,7 @@ export async function GET({ params }) { }; export async function DELETE({ params }) { + const env = readSettings(); let { name } = params; await db.delete(prefixes).where(eq(prefixes.name, name)) if (env.TAM3_REMOTE) { diff --git a/webapp/src/routes/api/reports/bybasket/[prefix]/+server.js b/webapp/src/routes/api/reports/bybasket/[prefix]/+server.js index 7e2d06e..d88e8f1 100644 --- a/webapp/src/routes/api/reports/bybasket/[prefix]/+server.js +++ b/webapp/src/routes/api/reports/bybasket/[prefix]/+server.js @@ -1,9 +1,10 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { report } from "$lib/server/db/schema"; import { eq } from "drizzle-orm"; export async function GET({ params }) { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/reports/bybasket/${params.prefix}/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { diff --git a/webapp/src/routes/api/reports/byname/[prefix]/+server.js b/webapp/src/routes/api/reports/byname/[prefix]/+server.js index 3d56987..3bf8ab1 100644 --- a/webapp/src/routes/api/reports/byname/[prefix]/+server.js +++ b/webapp/src/routes/api/reports/byname/[prefix]/+server.js @@ -1,9 +1,10 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { report } from "$lib/server/db/schema"; import { eq } from "drizzle-orm"; export async function GET({ params }) { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/reports/byname/${params.prefix}/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { diff --git a/webapp/src/routes/api/settings/+server.js b/webapp/src/routes/api/settings/+server.js new file mode 100644 index 0000000..db41f0c --- /dev/null +++ b/webapp/src/routes/api/settings/+server.js @@ -0,0 +1,11 @@ +import { readSettings, writeSettings } from "$lib/server/settings"; + +export async function GET() { + return new Response(JSON.stringify(readSettings()), {status: 200, statusText: "Settings returned successfully"}); +} + +export async function POST({ request }) { + const params = await request.json(); + await writeSettings(params); + return new Response(JSON.stringify({detail: "Settings saved successfully."}), {status: 200, statusText: "Settings saved successfully."}) +} \ No newline at end of file diff --git a/webapp/src/routes/api/tickets/+server.js b/webapp/src/routes/api/tickets/+server.js index 5f93c6a..d664f38 100644 --- a/webapp/src/routes/api/tickets/+server.js +++ b/webapp/src/routes/api/tickets/+server.js @@ -1,10 +1,11 @@ +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { sql } from "drizzle-orm"; import { tickets } from "$lib/server/db/schema"; -import { env } from "$env/dynamic/private"; import { chunkArray } from "$lib/server/chunkArray"; export async function GET() { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { @@ -31,6 +32,7 @@ export async function GET() { }; export async function POST({ request }) { + const env = readSettings(); const i_tickets = await request.json(); for (let ticketChunk of chunkArray(i_tickets, 300)) { await db.insert(tickets).values(ticketChunk) diff --git a/webapp/src/routes/api/tickets/[prefix]/[t_from]/[t_to]/+server.js b/webapp/src/routes/api/tickets/[prefix]/[t_from]/[t_to]/+server.js index 4adf0c4..6f27379 100644 --- a/webapp/src/routes/api/tickets/[prefix]/[t_from]/[t_to]/+server.js +++ b/webapp/src/routes/api/tickets/[prefix]/[t_from]/[t_to]/+server.js @@ -1,9 +1,10 @@ +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { tickets } from "$lib/server/db/schema"; -import { env } from "$env/dynamic/private"; import { eq, and } from "drizzle-orm"; export async function GET({ params }) { + const env = readSettings(); let n_t_from = parseInt(params.t_from), n_t_to = parseInt(params.t_to); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/${params.prefix}/${n_t_from}/${n_t_to}/?api_key=${env.TAM3_REMOTE_KEY}`); diff --git a/webapp/src/routes/api/tickets/[prefix]/[t_id]/+server.js b/webapp/src/routes/api/tickets/[prefix]/[t_id]/+server.js index 218345a..3c1e446 100644 --- a/webapp/src/routes/api/tickets/[prefix]/[t_id]/+server.js +++ b/webapp/src/routes/api/tickets/[prefix]/[t_id]/+server.js @@ -1,9 +1,10 @@ -import { env } from "$env/dynamic/private"; +import { readSettings } from "$lib/server/settings"; import { db } from "$lib/server/db"; import { tickets } from "$lib/server/db/schema"; import { eq, and } from "drizzle-orm"; export async function GET({ params }) { + const env = readSettings(); if (env.TAM3_REMOTE) { const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/${params.prefix}/${params.t_id}/?api_key=${env.TAM3_REMOTE_KEY}`); if (!res.ok) { diff --git a/webapp/src/routes/settings/+page.js b/webapp/src/routes/settings/+page.js new file mode 100644 index 0000000..fcac448 --- /dev/null +++ b/webapp/src/routes/settings/+page.js @@ -0,0 +1,5 @@ +export async function load({ fetch }) { + const res = await fetch('/api/settings'); + const settingsData = await res.json(); + return {settings: settingsData}; +} \ No newline at end of file diff --git a/webapp/src/routes/settings/+page.svelte b/webapp/src/routes/settings/+page.svelte new file mode 100644 index 0000000..ddeecaf --- /dev/null +++ b/webapp/src/routes/settings/+page.svelte @@ -0,0 +1,53 @@ + + +

Settings

+ +
+

Remote Server

+
Address:
+
For example: https://ip_or_hostname:8443
+
+
API Key:
+
+ + +
+
+ +
+ +
+ + +
+ +
+ +
+
{status}
+
\ No newline at end of file