Compare commits

6 Commits

32 changed files with 198 additions and 59 deletions

View File

@@ -9,6 +9,12 @@ from repos.tickets import Ticket, TicketRepo
from repos.baskets import Basket, BasketRepo from repos.baskets import Basket, BasketRepo
from repos.template import Repo from repos.template import Repo
def chunk_list(in_lst: list, chunk_size: int):
chunks = []
for i in range(0, len(in_lst), chunk_size):
chunks.append(in_lst[i:i + chunk_size])
return chunks
@dataclass @dataclass
class BackupFile: class BackupFile:
prefixes: List[Prefix] = field(default_factory=list) prefixes: List[Prefix] = field(default_factory=list)
@@ -21,8 +27,10 @@ class BackupFileRepo:
return new_file return new_file
def post_file(self, uploaded_file: BackupFile) -> str: def post_file(self, uploaded_file: BackupFile) -> str:
PrefixRepo().add_list(uploaded_file.prefixes) PrefixRepo().add_list(uploaded_file.prefixes)
TicketRepo().post_list(uploaded_file.tickets) for ticket_chunk in chunk_list(uploaded_file.tickets, 300):
BasketRepo().post_list(uploaded_file.baskets) TicketRepo().post_list(ticket_chunk)
for basket_chunk in chunk_list(uploaded_file.baskets, 300):
BasketRepo().post_list(basket_chunk)
return "File posted successfully." return "File posted successfully."
backup_router = APIRouter(prefix="/api/backuprestore") backup_router = APIRouter(prefix="/api/backuprestore")

View File

@@ -10,7 +10,7 @@ services:
MARIADB_USER: tam3 MARIADB_USER: tam3
MARIADB_PASSWORD: tam3 MARIADB_PASSWORD: tam3
volumes: volumes:
- "tam3-db:/var/lib/mysql" - "tam3-db:/var/lib/mysql:rw,z"
ports: ports:
- 127.0.0.1:3306:3306 - 127.0.0.1:3306:3306
adminer: adminer:

View File

@@ -9,9 +9,9 @@ if [ $rmserver = "y" -o $rmserver = "Y" ]; then
read -p "Enter the protocol, server host/ip, and port like "https://ip_or_host:8443" w/o quotes: " serveraddr read -p "Enter the protocol, server host/ip, and port like "https://ip_or_host:8443" w/o quotes: " serveraddr
read -p "Paste in (Ctrl + Shift + V on most terminal emulators) or enter the api key you generated for your server: " serverapi read -p "Paste in (Ctrl + Shift + V on most terminal emulators) or enter the api key you generated for your server: " serverapi
if [ -x "$(command -v docker)" ]; then if [ -x "$(command -v docker)" ]; then
docker run -d --name=tam3-webclient --restart=always -v ~/.config/TAM3/data:/data:rw,z -e TAM3_REMOTE=$serveraddr -e TAM3_REMOTE_KEY=$serverapi -e NODE_TLS_REJECT_UNAUTHORIZED=0 -e PUBLIC_TAM3_VENUE="$venuename" -p 127.0.0.1:8300:3000 docker.io/dbob16/tam3-webclient:0.1.1 docker run -d --name=tam3-webclient --restart=always -v ~/.config/TAM3/data:/data:rw,z -e TAM3_REMOTE=$serveraddr -e TAM3_REMOTE_KEY=$serverapi -e PUBLIC_TAM3_VENUE="$venuename" -p 127.0.0.1:8300:3000 docker.io/dbob16/tam3-webclient:0.2.0
elif [ -x "$(command -v podman)" ]; then elif [ -x "$(command -v podman)" ]; then
podman run -d --name=tam3-webclient --restart=always -v ~/.config/TAM3/data:/data:rw,z -e TAM3_REMOTE=$serveraddr -e TAM3_REMOTE_KEY=$serverapi -e NODE_TLS_REJECT_UNAUTHORIZED=0 -e PUBLIC_TAM3_VENUE="$venuename" -p 127.0.0.1:8300:3000 docker.io/dbob16/tam3-webclient:0.1.1 podman run -d --name=tam3-webclient --restart=always -v ~/.config/TAM3/data:/data:rw,z -e TAM3_REMOTE=$serveraddr -e TAM3_REMOTE_KEY=$serverapi -e PUBLIC_TAM3_VENUE="$venuename" -p 127.0.0.1:8300:3000 docker.io/dbob16/tam3-webclient:0.2.0
runin_podman="true" runin_podman="true"
else else
echo "Neither Docker nor Podman are installed. Please install whichever you prefer and try again." echo "Neither Docker nor Podman are installed. Please install whichever you prefer and try again."
@@ -19,9 +19,9 @@ exit 1
fi fi
else else
if [ -x "$(command -v docker)" ]; then if [ -x "$(command -v docker)" ]; then
docker run -d --name=tam3-webclient --restart=always -v ~/.config/TAM3/data:/data:rw,z -e PUBLIC_TAM3_VENUE="$venuename" -p 127.0.0.1:8300:3000 docker.io/dbob16/tam3-webclient:0.1.1 docker run -d --name=tam3-webclient --restart=always -v ~/.config/TAM3/data:/data:rw,z -e PUBLIC_TAM3_VENUE="$venuename" -p 127.0.0.1:8300:3000 docker.io/dbob16/tam3-webclient:0.2.0
elif [ -x "$(command -v podman )" ]; then elif [ -x "$(command -v podman )" ]; then
podman run -d --name=tam3-webclient --restart=always -v ~/.config/TAM3/data:/data:rw,z -e PUBLIC_TAM3_VENUE="$venuename" -p 127.0.0.1:8300:3000 docker.io/dbob16/tam3-webclient:0.1.1 podman run -d --name=tam3-webclient --restart=always -v ~/.config/TAM3/data:/data:rw,z -e PUBLIC_TAM3_VENUE="$venuename" -p 127.0.0.1:8300:3000 docker.io/dbob16/tam3-webclient:0.2.0
runin_podman="true" runin_podman="true"
else else
echo "Neither Docker nor Podman are installed. Please install whichever you prefer and try again." echo "Neither Docker nor Podman are installed. Please install whichever you prefer and try again."

View File

@@ -1,6 +1,6 @@
services: services:
tam3-db: tam3-db:
image: docker.io/dbob16/tam3-db:0.1.1 image: docker.io/dbob16/tam3-db:0.2.0
restart: always restart: always
environment: environment:
MARIADB_RANDOM_ROOT_PASSWORD: 1 MARIADB_RANDOM_ROOT_PASSWORD: 1
@@ -16,7 +16,7 @@ services:
timeout: 5s timeout: 5s
retries: 3 retries: 3
tam3-api: tam3-api:
image: docker.io/dbob16/tam3-api:0.1.1 image: docker.io/dbob16/tam3-api:0.2.0
restart: always restart: always
environment: environment:
TAM3_DATA_PATH: /data TAM3_DATA_PATH: /data

View File

@@ -1,6 +1,6 @@
services: services:
tam3-db: tam3-db:
image: docker.io/dbob16/tam3-db:0.1.1 image: docker.io/dbob16/tam3-db:0.2.0
restart: always restart: always
environment: environment:
MARIADB_RANDOM_ROOT_PASSWORD: 1 MARIADB_RANDOM_ROOT_PASSWORD: 1
@@ -16,7 +16,7 @@ services:
timeout: 5s timeout: 5s
retries: 3 retries: 3
tam3-api: tam3-api:
image: docker.io/dbob16/tam3-api:0.1.1 image: docker.io/dbob16/tam3-api:0.2.0
restart: always restart: always
environment: environment:
TAM3_DATA_PATH: /data TAM3_DATA_PATH: /data

1
webapp/.gitignore vendored
View File

@@ -17,6 +17,7 @@ Thumbs.db
.env.* .env.*
!.env.example !.env.example
!.env.test !.env.test
settings.json
# Vite # Vite
vite.config.js.timestamp-* vite.config.js.timestamp-*

View File

@@ -7,6 +7,7 @@ COPY . .
RUN npm install && npm run build RUN npm install && npm run build
ENV DATABASE_URL=file:/data/local.db ENV DATABASE_URL=file:/data/local.db
ENV SETTINGS_PATH=/data/settings.json
ENV BODY_SIZE_LIMIT=100M ENV BODY_SIZE_LIMIT=100M
ENV NODE_TLS_REJECT_UNAUTHORIZED=0 ENV NODE_TLS_REJECT_UNAUTHORIZED=0

View File

@@ -1,12 +1,19 @@
:root { :root {
font-family: serif;
font-size: 14pt;
--button-fg: #333333; --button-fg: #333333;
--button-bg: #eeeeee; --button-bg: #eeeeee;
--button-border: #333333; --button-border: #333333;
} }
button, input, select, option {
font-family: serif;
font-size: 14pt;
}
a.styled, button.styled { a.styled, button.styled {
display: block; display: block;
font: bold 12pt Arial; font-weight: bold;
text-decoration: none; text-decoration: none;
background-color: var(--button-bg); background-color: var(--button-bg);
color: var(--button-fg); color: var(--button-fg);
@@ -20,7 +27,7 @@ a.styled, button.styled {
} }
.active { .active {
border: 1px solid #000000; border: 2px solid #000000;
border-radius: 0.13rem; border-radius: 0.13rem;
} }

View File

@@ -0,0 +1,7 @@
export function chunkArray(arr, chunkSize) {
const chunks = [];
for (let i = 0; i < arr.length; i += chunkSize) {
chunks.push(arr.slice(i, i + chunkSize));
}
return chunks;
}

View File

@@ -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."
}

View File

@@ -74,6 +74,7 @@
<div class="flex-row"> <div class="flex-row">
<a href="/prefixes" target="_blank" class="styled">Prefix Editor</a> <a href="/prefixes" target="_blank" class="styled">Prefix Editor</a>
<a href="/backuprestore" target="_blank" class="styled">Backup/Restore</a> <a href="/backuprestore" target="_blank" class="styled">Backup/Restore</a>
<a href="/settings" target="_blank" class="styled">Settings</a>
</div> </div>
{/if} {/if}

View File

@@ -1,6 +1,7 @@
import { env } from "$env/dynamic/private"; import { readSettings } from "$lib/server/settings";
export async function GET() { export async function GET() {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {

View File

@@ -1,17 +1,11 @@
import { env } from "$env/dynamic/private"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { prefixes, tickets, baskets } from "$lib/server/db/schema"; import { prefixes, tickets, baskets } from "$lib/server/db/schema";
import { sql } from "drizzle-orm"; import { sql } from "drizzle-orm";
import { chunkArray } from "$lib/server/chunkArray";
function chunkArray(arr, chunkSize) {
const chunks = [];
for (let i = 0; i < arr.length; i += chunkSize) {
chunks.push(arr.slice(i, i + chunkSize));
}
return chunks;
}
export async function GET() { export async function GET() {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/backuprestore/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/backuprestore/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {
@@ -28,6 +22,7 @@ export async function GET() {
} }
export async function POST({ request }) { export async function POST({ request }) {
const env = readSettings();
const req = await request.json(); const req = await request.json();
for (let prefixChunk of chunkArray(req.prefixes, 300)) { 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`}}); await db.insert(prefixes).values(prefixChunk).onConflictDoUpdate({target: prefixes.name, set: {color: sql`excluded.color`, weight: sql`excluded.weight`}});

View File

@@ -1,8 +1,11 @@
import { env } from "$env/dynamic/private"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { sql } from "drizzle-orm";
import { baskets } from "$lib/server/db/schema"; import { baskets } from "$lib/server/db/schema";
import { chunkArray } from "$lib/server/chunkArray";
export async function GET() { export async function GET() {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/baskets/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/baskets/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {
@@ -25,19 +28,20 @@ export async function GET() {
} }
export async function POST({ request }) { export async function POST({ request }) {
const i_baskets = await request.json(); const env = readSettings();
for (let basket of i_baskets) { const i_baskets = await request.json();
await db.insert(baskets).values({prefix: basket.prefix, b_id: basket.b_id, description: basket.description, donors: basket.donors, winning_ticket: basket.winning_ticket}) for (let basketChunk of chunkArray(i_baskets, 300)) {
.onConflictDoUpdate({target: [baskets.prefix, baskets.b_id], set: {description: basket.description, donors: basket.donors, winning_ticket: basket.winning_ticket}}) 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 data = await res.json();
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'} return new Response(JSON.stringify({details: "Posted baskets successfully."}), {status: 200, statusText: "Posted baskets successfully."})
});
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."})
} }

View File

@@ -1,9 +1,10 @@
import { env } from "$env/dynamic/private"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { baskets } from "$lib/server/db/schema"; import { baskets } from "$lib/server/db/schema";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
export async function GET({ params }) { export async function GET({ params }) {
const env = readSettings();
let n_b_from = parseInt(params.b_from), n_b_to = parseInt(params.b_to); let n_b_from = parseInt(params.b_from), n_b_to = parseInt(params.b_to);
if (env.TAM3_REMOTE) { 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}`); const res = await fetch(`${env.TAM3_REMOTE}/api/baskets/${params.prefix}/${n_b_from}/${n_b_to}/?api_key=${env.TAM3_REMOTE_KEY}`);

View File

@@ -1,8 +1,11 @@
import { env } from "$env/dynamic/private"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { sql } from "drizzle-orm";
import { baskets, combined } from "$lib/server/db/schema"; import { baskets, combined } from "$lib/server/db/schema";
import { chunkArray } from "$lib/server/chunkArray";
export async function GET() { export async function GET() {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/combined/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/combined/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {
@@ -20,10 +23,11 @@ export async function GET() {
} }
export async function POST({ request }) { export async function POST({ request }) {
const env = readSettings();
const r_data = await request.json() const r_data = await request.json()
for (let winner of r_data) { for (let winnerChunk of chunkArray(r_data, 300)) {
await db.insert(baskets).values({prefix: winner.prefix, b_id: winner.b_id, winning_ticket: winner.winning_ticket}) await db.insert(baskets).values(winnerChunk)
.onConflictDoUpdate({target: [baskets.prefix, baskets.b_id], set: {winning_ticket: winner.winning_ticket}}) .onConflictDoUpdate({target: [baskets.prefix, baskets.b_id], set: {winning_ticket: sql`excluded.winning_ticket`}})
} }
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/combined/?api_key=${env.TAM3_REMOTE_KEY}`, { const res = await fetch(`${env.TAM3_REMOTE}/api/combined/?api_key=${env.TAM3_REMOTE_KEY}`, {

View File

@@ -1,9 +1,10 @@
import { env } from "process"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { combined } from "$lib/server/db/schema"; import { combined } from "$lib/server/db/schema";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
export async function GET({ params }) { export async function GET({ params }) {
const env = readSettings();
const n_b_from = parseInt(params.b_from), n_b_to = parseInt(params.b_to); const n_b_from = parseInt(params.b_from), n_b_to = parseInt(params.b_to);
if (env.TAM3_REMOTE) { 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}`); const res = await fetch(`${env.TAM3_REMOTE}/api/combined/${params.prefix}/${n_b_from}/${n_b_to}/?api_key=${env.TAM3_REMOTE_KEY}`);

View File

@@ -1,9 +1,10 @@
import { env } from "$env/dynamic/private"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { combined } from "$lib/server/db/schema"; import { combined } from "$lib/server/db/schema";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
export async function GET({ params }) { export async function GET({ params }) {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/combined/${params.prefix}/${params.b_id}/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/combined/${params.prefix}/${params.b_id}/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {

View File

@@ -1,8 +1,9 @@
import { env } from "$env/dynamic/private"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { counts } from "$lib/server/db/schema"; import { counts } from "$lib/server/db/schema";
export async function GET() { export async function GET() {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/counts/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/counts/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {

View File

@@ -1,8 +1,9 @@
import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { prefixes } from "$lib/server/db/schema"; import { prefixes } from "$lib/server/db/schema";
import { env } from "$env/dynamic/private";
export async function GET() { export async function GET() {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/prefixes/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/prefixes/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {
@@ -17,6 +18,7 @@ export async function GET() {
} }
export async function POST({ request }) { export async function POST({ request }) {
const env = readSettings();
const { name, color, weight } = await request.json(); 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}}); await db.insert(prefixes).values({name: name, color: color, weight: weight}).onConflictDoUpdate({target: prefixes.name, set: {color: color, weight: weight}});
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {

View File

@@ -1,9 +1,10 @@
import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { prefixes } from "$lib/server/db/schema"; import { prefixes } from "$lib/server/db/schema";
import { env } from "$env/dynamic/private";
export async function GET({ params }) { export async function GET({ params }) {
const env = readSettings();
let { name } = params; let { name } = params;
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/prefixes/${name}/?api_key=${env.TAM3_REMOTE_KEY}`); 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 }) { export async function DELETE({ params }) {
const env = readSettings();
let { name } = params; let { name } = params;
await db.delete(prefixes).where(eq(prefixes.name, name)) await db.delete(prefixes).where(eq(prefixes.name, name))
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {

View File

@@ -1,9 +1,10 @@
import { env } from "process"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { report } from "$lib/server/db/schema"; import { report } from "$lib/server/db/schema";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
export async function GET({ params }) { export async function GET({ params }) {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/reports/bybasket/${params.prefix}/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/reports/bybasket/${params.prefix}/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {

View File

@@ -1,9 +1,10 @@
import { env } from "process"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { report } from "$lib/server/db/schema"; import { report } from "$lib/server/db/schema";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
export async function GET({ params }) { export async function GET({ params }) {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/reports/byname/${params.prefix}/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/reports/byname/${params.prefix}/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {

View File

@@ -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."})
}

View File

@@ -1,8 +1,11 @@
import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { sql } from "drizzle-orm";
import { tickets } from "$lib/server/db/schema"; import { tickets } from "$lib/server/db/schema";
import { env } from "$env/dynamic/private"; import { chunkArray } from "$lib/server/chunkArray";
export async function GET() { export async function GET() {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {
@@ -29,10 +32,11 @@ export async function GET() {
}; };
export async function POST({ request }) { export async function POST({ request }) {
const env = readSettings();
const i_tickets = await request.json(); const i_tickets = await request.json();
for (let ticket of i_tickets) { for (let ticketChunk of chunkArray(i_tickets, 300)) {
await db.insert(tickets).values({prefix: ticket.prefix, t_id: ticket.t_id, first_name: ticket.first_name, last_name: ticket.last_name, phone_number: ticket.phone_number, preference: ticket.preference}) await db.insert(tickets).values(ticketChunk)
.onConflictDoUpdate({target: [tickets.prefix, tickets.t_id], set: {first_name: ticket.first_name, last_name: ticket.last_name, phone_number: ticket.phone_number, preference: ticket.preference}}); .onConflictDoUpdate({target: [tickets.prefix, tickets.t_id], set: {first_name: sql`excluded.first_name`, last_name: sql`excluded.last_name`, phone_number: sql`excluded.phone_number`, preference: sql`excluded.preference`}});
}; };
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/?api_key=${env.TAM3_REMOTE_KEY}`, { const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/?api_key=${env.TAM3_REMOTE_KEY}`, {

View File

@@ -1,9 +1,10 @@
import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { tickets } from "$lib/server/db/schema"; import { tickets } from "$lib/server/db/schema";
import { env } from "$env/dynamic/private";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
export async function GET({ params }) { export async function GET({ params }) {
const env = readSettings();
let n_t_from = parseInt(params.t_from), n_t_to = parseInt(params.t_to); let n_t_from = parseInt(params.t_from), n_t_to = parseInt(params.t_to);
if (env.TAM3_REMOTE) { 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}`); const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/${params.prefix}/${n_t_from}/${n_t_to}/?api_key=${env.TAM3_REMOTE_KEY}`);

View File

@@ -1,9 +1,10 @@
import { env } from "$env/dynamic/private"; import { readSettings } from "$lib/server/settings";
import { db } from "$lib/server/db"; import { db } from "$lib/server/db";
import { tickets } from "$lib/server/db/schema"; import { tickets } from "$lib/server/db/schema";
import { eq, and } from "drizzle-orm"; import { eq, and } from "drizzle-orm";
export async function GET({ params }) { export async function GET({ params }) {
const env = readSettings();
if (env.TAM3_REMOTE) { if (env.TAM3_REMOTE) {
const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/${params.prefix}/${params.t_id}/?api_key=${env.TAM3_REMOTE_KEY}`); const res = await fetch(`${env.TAM3_REMOTE}/api/tickets/${params.prefix}/${params.t_id}/?api_key=${env.TAM3_REMOTE_KEY}`);
if (!res.ok) { if (!res.ok) {

View File

@@ -20,7 +20,7 @@
const functions = { const functions = {
refreshPage: async () => { refreshPage: async () => {
if (current_baskets.length > 0) { if (current_baskets.filter(basket => basket.changed === true).length > 0) {
functions.saveAll() functions.saveAll()
} }
const res = await fetch(`/api/baskets/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`); const res = await fetch(`/api/baskets/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`);
@@ -136,6 +136,8 @@
} }
tbody tr:focus-within td:first-child { tbody tr:focus-within td:first-child {
font-weight: bold; font-weight: bold;
border-top: solid 1px;
border-bottom: solid 1px;
} }
input { input {
background: transparent; background: transparent;

View File

@@ -19,7 +19,7 @@
const functions = { const functions = {
refreshPage: async () => { refreshPage: async () => {
if (current_drawings.length > 0) { if (current_drawings.filter(drawing => drawing.changed === true).length > 0) {
functions.saveAll() functions.saveAll()
} }
const res = await fetch(`/api/combined/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`); const res = await fetch(`/api/combined/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`);
@@ -142,6 +142,8 @@
} }
tbody tr:focus-within td:first-child { tbody tr:focus-within td:first-child {
font-weight: bold; font-weight: bold;
border-top: solid 1px;
border-bottom: solid 1px;
} }
input { input {
background: transparent; background: transparent;

View File

@@ -0,0 +1,5 @@
export async function load({ fetch }) {
const res = await fetch('/api/settings');
const settingsData = await res.json();
return {settings: settingsData};
}

View File

@@ -0,0 +1,53 @@
<script>
import { browser } from '$app/environment';
const { data } = $props();
let stagingSettings = $state({...data.settings});
let status = $state("")
async function saveChanges() {
const res = await fetch('/api/settings', {method: 'POST', body: JSON.stringify(stagingSettings), headers: {'Content-Type': 'application/json'}});
if (res.ok) {
status = "Changes saved successfully";
setTimeout(() => {status = ""}, 5000);
} else {
status = "Error saving changes, check config file path, make sure folder exists";
setTimeout(() => {status = ""}, 5000);
}
}
function cancelChanges() {
stagingSettings = {...data.settings};
}
if (browser) {
document.title = "TAM3 - Settings"
}
</script>
<h1>Settings</h1>
<div>
<h2>Remote Server</h2>
<div><strong>Address:</strong></div>
<div><em>For example: https://ip_or_hostname:8443</em></div>
<div><input type="text" bind:value={stagingSettings.TAM3_REMOTE}></div>
<div><strong>API Key:</strong></div>
<div class="flex-row">
<input type="password" bind:value={stagingSettings.TAM3_REMOTE_KEY}>
<button class="styled" onclick={() => {stagingSettings.TAM3_REMOTE_KEY = ""}}>Clear</button>
</div>
</div>
<br />
<div class="flex-row">
<button class="styled" onclick={saveChanges}>Save</button>
<button class="styled" onclick={cancelChanges}>Cancel</button>
</div>
<br />
<div class="status">
<div>{status}</div>
</div>

View File

@@ -19,7 +19,7 @@
const functions = { const functions = {
refreshPage: async () => { refreshPage: async () => {
if (current_tickets.length > 0) { if (current_tickets.filter(ticket => ticket.changed === true).length > 0) {
functions.saveAll(); functions.saveAll();
}; };
const res = await fetch(`/api/tickets/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`); const res = await fetch(`/api/tickets/${prefix.name}/${pagerForm.id_from}/${pagerForm.id_to}`);
@@ -144,6 +144,8 @@
} }
tbody tr:focus-within td:first-child { tbody tr:focus-within td:first-child {
font-weight: bold; font-weight: bold;
border-top: solid 1px;
border-bottom: solid 1px;
} }
input { input {
background: transparent; background: transparent;