Compare commits
6
Commits
0.1.0
...
19eab77cc6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19eab77cc6 | ||
|
|
17061e5c37 | ||
|
|
56d7d1068d | ||
|
|
103f1cf3c4 | ||
|
|
a11c313a8e | ||
|
|
1b3c97516c |
No files matched your search
+16
-16
@@ -17,27 +17,27 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
"@sveltejs/adapter-node": "^5.5.4",
|
"@sveltejs/adapter-node": "^5.5.7",
|
||||||
"@sveltejs/kit": "^2.63.0",
|
"@sveltejs/kit": "^2.70.3",
|
||||||
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
||||||
"@tailwindcss/vite": "^4.3.0",
|
"@tailwindcss/vite": "^4.3.3",
|
||||||
"@types/better-sqlite3": "^7.6.13",
|
"@types/better-sqlite3": "^7.6.13",
|
||||||
"@types/node": "^24",
|
"@types/node": "^24.13.4",
|
||||||
"drizzle-kit": "^0.31.10",
|
"drizzle-kit": "^0.31.10",
|
||||||
"drizzle-orm": "^0.45.2",
|
"drizzle-orm": "^0.45.2",
|
||||||
"eslint": "^10.4.1",
|
"eslint": "^10.10.0",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-svelte": "^3.19.0",
|
"eslint-plugin-svelte": "^3.23.0",
|
||||||
"globals": "^17.6.0",
|
"globals": "^17.12.0",
|
||||||
"prettier": "^3.8.3",
|
"prettier": "^3.9.6",
|
||||||
"prettier-plugin-svelte": "^4.1.0",
|
"prettier-plugin-svelte": "^4.1.1",
|
||||||
"prettier-plugin-tailwindcss": "^0.8.0",
|
"prettier-plugin-tailwindcss": "^0.8.1",
|
||||||
"svelte": "^5.56.1",
|
"svelte": "^5.57.0",
|
||||||
"tailwindcss": "^4.3.0",
|
"tailwindcss": "^4.3.3",
|
||||||
"vite": "^8.0.16"
|
"vite": "^8.3.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^12.10.0",
|
"better-sqlite3": "^12.11.1",
|
||||||
"hotkeys-js": "^4.0.4"
|
"hotkeys-js": "^4.0.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+843
-680
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,18 @@
|
|||||||
import { db } from "$lib/server/db";
|
import { db } from '$lib/server/db';
|
||||||
|
import { env } from '$env/dynamic/public';
|
||||||
|
import { randomUUID } from 'crypto';
|
||||||
|
|
||||||
export const init = async () => {
|
export const init = async () => {
|
||||||
await db.run(`CREATE TABLE IF NOT EXISTS baskets (
|
env.PUBLIC_TAM_CLIENT_ID = randomUUID();
|
||||||
|
const originalEmitWarning = process.emitWarning;
|
||||||
|
process.emitWarning = (warning, ...args) => {
|
||||||
|
if (typeof warning === 'string' && warning.includes('NODE_TLS_REJECT_UNAUTHORIZED')) {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
originalEmitWarning.call(process, warning, ...args);
|
||||||
|
};
|
||||||
|
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
|
||||||
|
await db.run(`CREATE TABLE IF NOT EXISTS baskets (
|
||||||
prefix text,
|
prefix text,
|
||||||
b_id integer,
|
b_id integer,
|
||||||
description text,
|
description text,
|
||||||
@@ -9,12 +20,12 @@ export const init = async () => {
|
|||||||
winning_ticket integer,
|
winning_ticket integer,
|
||||||
PRIMARY KEY(prefix, b_id)
|
PRIMARY KEY(prefix, b_id)
|
||||||
)`);
|
)`);
|
||||||
await db.run(`CREATE TABLE IF NOT EXISTS prefixes (
|
await db.run(`CREATE TABLE IF NOT EXISTS prefixes (
|
||||||
prefix text PRIMARY KEY NOT NULL,
|
prefix text PRIMARY KEY NOT NULL,
|
||||||
color text,
|
color text,
|
||||||
weight integer
|
weight integer
|
||||||
)`);
|
)`);
|
||||||
await db.run(`CREATE TABLE IF NOT EXISTS tickets (
|
await db.run(`CREATE TABLE IF NOT EXISTS tickets (
|
||||||
prefix text,
|
prefix text,
|
||||||
t_id integer,
|
t_id integer,
|
||||||
first_name text,
|
first_name text,
|
||||||
@@ -23,19 +34,39 @@ export const init = async () => {
|
|||||||
pref text,
|
pref text,
|
||||||
PRIMARY KEY(prefix, t_id)
|
PRIMARY KEY(prefix, t_id)
|
||||||
)`);
|
)`);
|
||||||
await db.run(`CREATE VIEW IF NOT EXISTS drawing AS SELECT b.prefix, b.b_id, b.description, b.winning_ticket, t.last_name, t.first_name, t.phone_number
|
await db.run(`CREATE VIEW IF NOT EXISTS drawing AS SELECT b.prefix, b.b_id, b.description, b.winning_ticket, t.last_name, t.first_name, t.phone_number
|
||||||
FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id
|
FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id
|
||||||
ORDER BY b.prefix, b.b_id`);
|
ORDER BY b.prefix, b.b_id`);
|
||||||
await db.run(`CREATE VIEW IF NOT EXISTS report_by_basket AS SELECT b.prefix, b.b_id, b.description, b.donors, b.winning_ticket, t.last_name, t.first_name, t.phone_number, t.pref
|
await db.run(`CREATE VIEW IF NOT EXISTS report_by_basket AS SELECT b.prefix, b.b_id, b.description, b.donors, b.winning_ticket, t.last_name, t.first_name, t.phone_number, t.pref
|
||||||
FROM baskets b LEFT JOIN tickets t on b.prefix = t.prefix AND b.winning_ticket = t.t_id
|
FROM baskets b LEFT JOIN tickets t on b.prefix = t.prefix AND b.winning_ticket = t.t_id
|
||||||
ORDER BY b.prefix, b.b_id`);
|
ORDER BY b.prefix, b.b_id`);
|
||||||
await db.run(`CREATE VIEW IF NOT EXISTS report_by_name AS SELECT t.last_name, t.first_name, t.phone_number, t.pref, b.prefix, b.b_id, b.description, b.donors, b.winning_ticket
|
await db.run(`CREATE VIEW IF NOT EXISTS report_by_name AS SELECT t.last_name, t.first_name, t.phone_number, t.pref, b.prefix, b.b_id, b.description, b.donors, b.winning_ticket
|
||||||
FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id
|
FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id
|
||||||
ORDER BY t.last_name, t.first_name, t.phone_number, b.prefix, b.b_id`)
|
ORDER BY t.last_name, t.first_name, t.phone_number, b.prefix, b.b_id`);
|
||||||
await db.run(`CREATE VIEW IF NOT EXISTS report_counts AS SELECT prefix, COUNT(DISTINCT(CONCAT(first_name, last_name, phone_number))) AS unique_buyers, COUNT(*) AS total_buys
|
await db.run(`CREATE VIEW IF NOT EXISTS report_counts AS SELECT prefix, COUNT(DISTINCT(CONCAT(first_name, last_name, phone_number))) AS unique_buyers, COUNT(*) AS total_buys
|
||||||
FROM tickets
|
FROM tickets
|
||||||
GROUP BY prefix
|
GROUP BY prefix
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT 'Total', COUNT(DISTINCT(CONCAT(first_name, last_name, phone_number))), COUNT(*)
|
SELECT 'Total', COUNT(DISTINCT(CONCAT(first_name, last_name, phone_number))), COUNT(*)
|
||||||
FROM tickets`);
|
FROM tickets`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const handle = async ({ event, resolve }) => {
|
||||||
|
if (event.url.pathname.startsWith('/api')) {
|
||||||
|
const clientID = event.request.headers.get('TAM-CLIENT-ID');
|
||||||
|
if (env.PUBLIC_TAM_CLIENT_ID == clientID) {
|
||||||
|
const response = await resolve(event);
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
return new Response(JSON.stringify({detail: "Unauthorized"}), { status: 401 })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const response = await resolve(event);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handleFetch = async ({ request, fetch }) => {
|
||||||
|
request.headers.set('TAM-CLIENT-ID', env.PUBLIC_TAM_CLIENT_ID);
|
||||||
|
return fetch(request);
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-row gap-1 py-1 justify-between">
|
<div class="flex flex-row justify-between gap-1 py-1">
|
||||||
<div class="flex flex-row gap-1">
|
<div class="flex flex-row gap-1">
|
||||||
{#if functions.dupDown}
|
{#if functions.dupDown}
|
||||||
<button class={bS[prefix.color]} title="Alt + J" onclick={() => functions.dupDown()}
|
<button class={bS[prefix.color]} title="Alt + J" onclick={() => functions.dupDown()}
|
||||||
@@ -78,5 +78,19 @@
|
|||||||
>Save Marked</button
|
>Save Marked</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if functions.cancel}
|
||||||
|
<button
|
||||||
|
class={bS[prefix.color]}
|
||||||
|
title="Alt + S"
|
||||||
|
onclick={() => {
|
||||||
|
const yes_no = confirm(
|
||||||
|
'This will cancel all pending changes. Are you sure you want to cancel?'
|
||||||
|
);
|
||||||
|
if (yes_no) {
|
||||||
|
functions.cancel();
|
||||||
|
}
|
||||||
|
}}>Cancel Marked</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -43,6 +43,11 @@
|
|||||||
oninput={() => {
|
oninput={() => {
|
||||||
if (functions.pagerFromUpdate) functions.pagerFromUpdate();
|
if (functions.pagerFromUpdate) functions.pagerFromUpdate();
|
||||||
}}
|
}}
|
||||||
|
onkeydown={(e) => {
|
||||||
|
if (e.key == "Enter") {
|
||||||
|
functions.getPage()
|
||||||
|
}
|
||||||
|
}}
|
||||||
bind:value={pager.idFrom}
|
bind:value={pager.idFrom}
|
||||||
/>
|
/>
|
||||||
<div>-</div>
|
<div>-</div>
|
||||||
@@ -54,6 +59,11 @@
|
|||||||
onclick={(e) => {
|
onclick={(e) => {
|
||||||
e.target.select();
|
e.target.select();
|
||||||
}}
|
}}
|
||||||
|
onkeydown={(e) => {
|
||||||
|
if (e.key == "Enter") {
|
||||||
|
functions.getPage()
|
||||||
|
}
|
||||||
|
}}
|
||||||
bind:value={pager.idTo}
|
bind:value={pager.idTo}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { env } from '$env/dynamic/private';
|
import { env } from '$env/dynamic/private';
|
||||||
import { readFileSync, writeFileSync, mkdirSync } from 'fs';
|
import { readFileSync, writeFileSync } from 'fs';
|
||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
remote_server: '',
|
remote_server: '',
|
||||||
@@ -7,7 +7,8 @@ const defaultSettings = {
|
|||||||
remote_port: '8000',
|
remote_port: '8000',
|
||||||
remote_tls: false,
|
remote_tls: false,
|
||||||
default_pref: 'CALL',
|
default_pref: 'CALL',
|
||||||
venue_name: 'TAM'
|
venue_name: 'Venue Name',
|
||||||
|
disable_attrib: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSettings = () => {
|
export const getSettings = () => {
|
||||||
@@ -16,7 +17,6 @@ export const getSettings = () => {
|
|||||||
const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
||||||
return settings;
|
return settings;
|
||||||
} catch {
|
} catch {
|
||||||
mkdirSync(env.TAM_DATA_DIR || './data', { recursive: true });
|
|
||||||
writeFileSync(settingsPath, JSON.stringify(defaultSettings, null, 2), 'utf-8');
|
writeFileSync(settingsPath, JSON.stringify(defaultSettings, null, 2), 'utf-8');
|
||||||
return defaultSettings;
|
return defaultSettings;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { env } from "$env/dynamic/public"
|
||||||
|
|
||||||
|
export const load = async () => {
|
||||||
|
const tamClientID = `${env.PUBLIC_TAM_CLIENT_ID}`;
|
||||||
|
return { tamClientID }
|
||||||
|
}
|
||||||
@@ -2,9 +2,10 @@ import { getSettings } from '$lib/server/settings';
|
|||||||
|
|
||||||
export const load = async ({ fetch }) => {
|
export const load = async ({ fetch }) => {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
|
const disableAttrib = settings.disable_attrib || false;
|
||||||
const res = await fetch('/api');
|
const res = await fetch('/api');
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const resPrefixes = await fetch('/api/prefixes');
|
const resPrefixes = await fetch('/api/prefixes');
|
||||||
const dataPrefixes = await resPrefixes.json();
|
const dataPrefixes = await resPrefixes.json();
|
||||||
return { ...data, venueName: settings.venue_name, prefixes: dataPrefixes };
|
return { ...data, venueName: settings.venue_name, prefixes: dataPrefixes, disableAttrib };
|
||||||
};
|
};
|
||||||
@@ -134,12 +134,15 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<div class="text-center text-xs">
|
<div class="text-center text-xs">
|
||||||
<p>© 2026 Ticket Auction Manager</p>
|
<p>© 2026 Ticket Auction Manager</p>
|
||||||
|
{#if !data.disableAttrib}
|
||||||
<p>
|
<p>
|
||||||
Created by Dilan Gilluly. Support me on <a
|
Created by Dilan Gilluly. <a
|
||||||
href="https://ko-fi.com/techguydilan"
|
href="https://ko-fi.com/techguydilan"
|
||||||
class="text-blue-500">Ko-Fi</a
|
class="text-blue-500"
|
||||||
|
target="_blank">My Ko-Fi</a
|
||||||
>.
|
>.
|
||||||
</p>
|
</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -15,44 +15,50 @@ export const GET = async () => {
|
|||||||
|
|
||||||
export const POST = async ({ request }) => {
|
export const POST = async ({ request }) => {
|
||||||
const reqData = await request.json();
|
const reqData = await request.json();
|
||||||
for (let i = 0; i < reqData.prefixes.length; i += chunk_size) {
|
if (reqData.prefixes) {
|
||||||
const chunk = reqData.prefixes.slice(i, i + chunk_size);
|
for (let i = 0; i < reqData.prefixes.length; i += chunk_size) {
|
||||||
await db
|
const chunk = reqData.prefixes.slice(i, i + chunk_size);
|
||||||
.insert(prefixes)
|
await db
|
||||||
.values(chunk)
|
.insert(prefixes)
|
||||||
.onConflictDoUpdate({
|
.values(chunk)
|
||||||
target: prefixes.prefix,
|
.onConflictDoUpdate({
|
||||||
set: { color: sql`EXCLUDED.color`, weight: sql`EXCLUDED.weight` }
|
target: prefixes.prefix,
|
||||||
});
|
set: { color: sql`EXCLUDED.color`, weight: sql`EXCLUDED.weight` }
|
||||||
}
|
});
|
||||||
for (let i = 0; i < reqData.baskets.length; i += chunk_size) {
|
};
|
||||||
const chunk = reqData.baskets.slice(i, i + chunk_size);
|
};
|
||||||
await db
|
if (reqData.baskets) {
|
||||||
.insert(baskets)
|
for (let i = 0; i < reqData.baskets.length; i += chunk_size) {
|
||||||
.values(chunk)
|
const chunk = reqData.baskets.slice(i, i + chunk_size);
|
||||||
.onConflictDoUpdate({
|
await db
|
||||||
target: [baskets.prefix, baskets.b_id],
|
.insert(baskets)
|
||||||
set: {
|
.values(chunk)
|
||||||
description: sql`EXCLUDED.description`,
|
.onConflictDoUpdate({
|
||||||
donors: sql`EXCLUDED.donors`,
|
target: [baskets.prefix, baskets.b_id],
|
||||||
winning_ticket: sql`EXCLUDED.winning_ticket`
|
set: {
|
||||||
}
|
description: sql`EXCLUDED.description`,
|
||||||
});
|
donors: sql`EXCLUDED.donors`,
|
||||||
}
|
winning_ticket: sql`EXCLUDED.winning_ticket`
|
||||||
for (let i = 0; i < reqData.tickets.length; i += chunk_size) {
|
}
|
||||||
const chunk = reqData.tickets.slice(i, i + chunk_size);
|
});
|
||||||
await db
|
};
|
||||||
.insert(tickets)
|
};
|
||||||
.values(chunk)
|
if (reqData.tickets) {
|
||||||
.onConflictDoNothing({
|
for (let i = 0; i < reqData.tickets.length; i += chunk_size) {
|
||||||
target: [tickets.prefix, tickets.t_id],
|
const chunk = reqData.tickets.slice(i, i + chunk_size);
|
||||||
set: {
|
await db
|
||||||
first_name: sql`EXCLUDED.first_name`,
|
.insert(tickets)
|
||||||
last_name: sql`EXCLUDED.last_name`,
|
.values(chunk)
|
||||||
phone_number: sql`EXCLUDED.phone_number`,
|
.onConflictDoNothing({
|
||||||
pref: sql`EXCLUDED.pref`
|
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`,
|
||||||
|
pref: sql`EXCLUDED.pref`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
return json({ details: 'Data loaded successfully.' });
|
return json({ details: 'Data loaded successfully.' });
|
||||||
};
|
};
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
import CommandBar from '$lib/client/components/CommandBar.svelte';
|
import CommandBar from '$lib/client/components/CommandBar.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let { prefix, prefixes } = $derived(data);
|
let { prefix, prefixes, tamClientID } = $derived(data);
|
||||||
|
|
||||||
let pageTitle = $derived(`${prefix.prefix} Baskets | TAM`);
|
let pageTitle = $derived(`${prefix.prefix} Baskets | TAM`);
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
let itemsLength = $derived(items.length || 1);
|
let itemsLength = $derived(items.length || 1);
|
||||||
let itemsBuffer = $derived(items.filter((i) => i.changed));
|
let itemsBuffer = $derived(items.filter((i) => i.changed));
|
||||||
const functions = {
|
const functions = {
|
||||||
async getPage(){
|
async getPage() {
|
||||||
this.save();
|
this.save();
|
||||||
if (pager.idFrom > pager.idTo) {
|
if (pager.idFrom > pager.idTo) {
|
||||||
[pager.idFrom, pager.idTo] = [pager.idTo, pager.idFrom];
|
[pager.idFrom, pager.idTo] = [pager.idTo, pager.idFrom];
|
||||||
@@ -38,20 +38,25 @@
|
|||||||
if (pager.idTo - pager.idFrom > 300) {
|
if (pager.idTo - pager.idFrom > 300) {
|
||||||
pager.idTo = pager.idFrom + 300;
|
pager.idTo = pager.idFrom + 300;
|
||||||
}
|
}
|
||||||
const res = await fetch(`/api/baskets/${prefix.prefix}/${pager.idFrom}/${pager.idTo}`);
|
const res = await fetch(`/api/baskets/${prefix.prefix}/${pager.idFrom}/${pager.idTo}`, {
|
||||||
|
headers: { 'TAM-CLIENT-ID': tamClientID }
|
||||||
|
});
|
||||||
const resData = await res.json();
|
const resData = await res.json();
|
||||||
resData.map((i) => (i.changed = false));
|
resData.map((i) => (i.changed = false));
|
||||||
items = [...resData];
|
items = [...resData];
|
||||||
setTimeout(() => focusIdx(0));
|
setTimeout(() => focusIdx(0));
|
||||||
},
|
},
|
||||||
pagerFromUpdate(){
|
pagerFromUpdate() {
|
||||||
pager.idTo = pager.idFrom + (itemsLength - 1);
|
pager.idTo = pager.idFrom + (itemsLength - 1);
|
||||||
},
|
},
|
||||||
async save(){
|
async save() {
|
||||||
if (itemsBuffer.length > 0) {
|
if (itemsBuffer.length > 0) {
|
||||||
const res = await fetch('/api/baskets', {
|
const res = await fetch('/api/baskets', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'TAM-CLIENT-ID': tamClientID
|
||||||
|
},
|
||||||
body: JSON.stringify(itemsBuffer)
|
body: JSON.stringify(itemsBuffer)
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -64,15 +69,21 @@
|
|||||||
focusIdx(0);
|
focusIdx(0);
|
||||||
}, 1);
|
}, 1);
|
||||||
},
|
},
|
||||||
prevPage(){
|
cancel() {
|
||||||
|
if (itemsBuffer.length > 0) {
|
||||||
|
itemsBuffer.forEach((i) => (i.changed = false));
|
||||||
|
this.getPage();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prevPage() {
|
||||||
((pager.idFrom -= itemsLength), (pager.idTo -= itemsLength));
|
((pager.idFrom -= itemsLength), (pager.idTo -= itemsLength));
|
||||||
this.getPage();
|
this.getPage();
|
||||||
},
|
},
|
||||||
nextPage(){
|
nextPage() {
|
||||||
((pager.idFrom += itemsLength), (pager.idTo += itemsLength));
|
((pager.idFrom += itemsLength), (pager.idTo += itemsLength));
|
||||||
this.getPage();
|
this.getPage();
|
||||||
},
|
},
|
||||||
nextLine(){
|
nextLine() {
|
||||||
if (items[nextIdx]) {
|
if (items[nextIdx]) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
focusIdx(nextIdx);
|
focusIdx(nextIdx);
|
||||||
@@ -83,7 +94,7 @@
|
|||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
prevLine(){
|
prevLine() {
|
||||||
if (curIdx > 0) {
|
if (curIdx > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
focusIdx(prevIdx);
|
focusIdx(prevIdx);
|
||||||
@@ -94,7 +105,7 @@
|
|||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dupDown(){
|
dupDown() {
|
||||||
if (items[nextIdx]) {
|
if (items[nextIdx]) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -104,7 +115,7 @@
|
|||||||
focusIdx(curIdx);
|
focusIdx(curIdx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dupUp(){
|
dupUp() {
|
||||||
if (curIdx > 0) {
|
if (curIdx > 0) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -114,7 +125,7 @@
|
|||||||
focusIdx(curIdx);
|
focusIdx(curIdx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
copy(){
|
copy() {
|
||||||
if (items[curIdx]) {
|
if (items[curIdx]) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 't_id'].forEach((key) => delete buffer[key]);
|
['prefix', 't_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -122,7 +133,7 @@
|
|||||||
}
|
}
|
||||||
focusIdx(curIdx);
|
focusIdx(curIdx);
|
||||||
},
|
},
|
||||||
paste(){
|
paste() {
|
||||||
if (items[curIdx]) {
|
if (items[curIdx]) {
|
||||||
const buffer = JSON.parse(window.localStorage.getItem('tam-basket'));
|
const buffer = JSON.parse(window.localStorage.getItem('tam-basket'));
|
||||||
items[curIdx] = { ...items[curIdx], ...buffer, changed: true };
|
items[curIdx] = { ...items[curIdx], ...buffer, changed: true };
|
||||||
@@ -133,8 +144,8 @@
|
|||||||
const headers = ['Basket ID', 'Description', 'Donors', 'Save?'];
|
const headers = ['Basket ID', 'Description', 'Donors', 'Save?'];
|
||||||
|
|
||||||
if (browser) {
|
if (browser) {
|
||||||
window.addEventListener('beforeunload', (e) => {
|
window.addEventListener('beforeunload', () => {
|
||||||
if (itemsBuffer.length > 0) e.preventDefault();
|
if (itemsBuffer.length > 0) functions.save();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import CommandBar from '$lib/client/components/CommandBar.svelte';
|
import CommandBar from '$lib/client/components/CommandBar.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let { prefix, prefixes } = $derived(data);
|
let { prefix, prefixes, tamClientID } = $derived(data);
|
||||||
|
|
||||||
let pageTitle = $derived(`${prefix.prefix} Drawing Form | TAM`);
|
let pageTitle = $derived(`${prefix.prefix} Drawing Form | TAM`);
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
let itemsLength = $derived(items.length || 1);
|
let itemsLength = $derived(items.length || 1);
|
||||||
let itemsBuffer = $derived(items.filter((i) => i.changed));
|
let itemsBuffer = $derived(items.filter((i) => i.changed));
|
||||||
const functions = {
|
const functions = {
|
||||||
async getPage(){
|
async getPage() {
|
||||||
this.save();
|
this.save();
|
||||||
if (pager.idFrom > pager.idTo) {
|
if (pager.idFrom > pager.idTo) {
|
||||||
[pager.idFrom, pager.idTo] = [pager.idTo, pager.idFrom];
|
[pager.idFrom, pager.idTo] = [pager.idTo, pager.idFrom];
|
||||||
@@ -38,17 +38,19 @@
|
|||||||
if (pager.idTo - pager.idFrom > 300) {
|
if (pager.idTo - pager.idFrom > 300) {
|
||||||
pager.idTo = pager.idFrom + 300;
|
pager.idTo = pager.idFrom + 300;
|
||||||
}
|
}
|
||||||
const res = await fetch(`/api/drawing/${prefix.prefix}/${pager.idFrom}/${pager.idTo}`);
|
const res = await fetch(`/api/drawing/${prefix.prefix}/${pager.idFrom}/${pager.idTo}`, {
|
||||||
|
headers: { 'TAM-CLIENT-ID': tamClientID }
|
||||||
|
});
|
||||||
const resData = await res.json();
|
const resData = await res.json();
|
||||||
resData.map((i) => (i.changed = false));
|
resData.map((i) => (i.changed = false));
|
||||||
items = [...resData];
|
items = [...resData];
|
||||||
setTimeout(() => focusIdx(0));
|
setTimeout(() => focusIdx(0));
|
||||||
},
|
},
|
||||||
async save(){
|
async save() {
|
||||||
if (itemsBuffer.length > 0) {
|
if (itemsBuffer.length > 0) {
|
||||||
const res = await fetch('/api/drawing', {
|
const res = await fetch('/api/drawing', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json', 'TAM-CLIENT-ID': tamClientID },
|
||||||
body: JSON.stringify(itemsBuffer)
|
body: JSON.stringify(itemsBuffer)
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -61,18 +63,24 @@
|
|||||||
focusIdx(0);
|
focusIdx(0);
|
||||||
}, 1);
|
}, 1);
|
||||||
},
|
},
|
||||||
pagerFromUpdate(){
|
cancel() {
|
||||||
pager.idTo = pager.idFrom + (itemsLength - 1);
|
if (itemsBuffer.length > 0) {
|
||||||
|
itemsBuffer.forEach((i) => (i.changed = false));
|
||||||
|
this.getPage();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
prevPage(){
|
pagerFromUpdate() {
|
||||||
|
pager.idTo = pager.idFrom + (itemsLength - 1);
|
||||||
|
},
|
||||||
|
prevPage() {
|
||||||
((pager.idFrom -= itemsLength), (pager.idTo -= itemsLength));
|
((pager.idFrom -= itemsLength), (pager.idTo -= itemsLength));
|
||||||
this.getPage();
|
this.getPage();
|
||||||
},
|
},
|
||||||
nextPage(){
|
nextPage() {
|
||||||
((pager.idFrom += itemsLength), (pager.idTo += itemsLength));
|
((pager.idFrom += itemsLength), (pager.idTo += itemsLength));
|
||||||
this.getPage();
|
this.getPage();
|
||||||
},
|
},
|
||||||
nextLine(){
|
nextLine() {
|
||||||
if (items[nextIdx]) {
|
if (items[nextIdx]) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
focusIdx(nextIdx);
|
focusIdx(nextIdx);
|
||||||
@@ -83,7 +91,7 @@
|
|||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
prevLine(){
|
prevLine() {
|
||||||
if (curIdx > 0) {
|
if (curIdx > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
focusIdx(prevIdx);
|
focusIdx(prevIdx);
|
||||||
@@ -94,7 +102,7 @@
|
|||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dupDown(){
|
dupDown() {
|
||||||
if (items[nextIdx]) {
|
if (items[nextIdx]) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -104,7 +112,7 @@
|
|||||||
focusIdx(curIdx);
|
focusIdx(curIdx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dupUp(){
|
dupUp() {
|
||||||
if (curIdx > 0) {
|
if (curIdx > 0) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -114,7 +122,7 @@
|
|||||||
focusIdx(curIdx);
|
focusIdx(curIdx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
copy(){
|
copy() {
|
||||||
if (items[curIdx]) {
|
if (items[curIdx]) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
['prefix', 'b_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -122,7 +130,7 @@
|
|||||||
}
|
}
|
||||||
focusIdx(curIdx);
|
focusIdx(curIdx);
|
||||||
},
|
},
|
||||||
paste(){
|
paste() {
|
||||||
if (items[curIdx]) {
|
if (items[curIdx]) {
|
||||||
const buffer = JSON.parse(window.localStorage.getItem('tam-drawing'));
|
const buffer = JSON.parse(window.localStorage.getItem('tam-drawing'));
|
||||||
items[curIdx] = { ...items[curIdx], ...buffer, changed: true };
|
items[curIdx] = { ...items[curIdx], ...buffer, changed: true };
|
||||||
@@ -133,8 +141,8 @@
|
|||||||
const headers = ['Basket ID', 'Description', 'Winning Ticket', 'Winner', 'Save?'];
|
const headers = ['Basket ID', 'Description', 'Winning Ticket', 'Winner', 'Save?'];
|
||||||
|
|
||||||
if (browser) {
|
if (browser) {
|
||||||
window.addEventListener('beforeunload', (e) => {
|
window.addEventListener('beforeunload', () => {
|
||||||
if (itemsBuffer.length > 0) e.preventDefault();
|
if (itemsBuffer.length > 0) functions.save();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -185,7 +193,9 @@
|
|||||||
id="{idx}_first"
|
id="{idx}_first"
|
||||||
oninput={async () => {
|
oninput={async () => {
|
||||||
item.changed = true;
|
item.changed = true;
|
||||||
const res = await fetch(`/api/tickets/${prefix.prefix}/${item.winning_ticket}`);
|
const res = await fetch(`/api/tickets/${prefix.prefix}/${item.winning_ticket}`, {
|
||||||
|
headers: { 'TAM-CLIENT-ID': tamClientID }
|
||||||
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
[item.last_name, item.first_name, item.phone_number] = [
|
[item.last_name, item.first_name, item.phone_number] = [
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { tS, bS } from '$lib/client/styles';
|
import { tS, bS } from '$lib/client/styles';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let prefixes = $derived(data.prefixes);
|
let { prefixes, tamClientID } = $derived(data);
|
||||||
let tableData = $state([]);
|
let tableData = $state([]);
|
||||||
let currentTimeout = $state();
|
let currentTimeout = $state();
|
||||||
let lastRefreshed = $state('');
|
let lastRefreshed = $state('');
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
const loadCounts = async () => {
|
const loadCounts = async () => {
|
||||||
const rtnData = {};
|
const rtnData = {};
|
||||||
const res = await fetch('/api/reports/counts');
|
const res = await fetch('/api/reports/counts', {headers: {'TAM-CLIENT-ID': tamClientID}});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
prefixes.forEach((p) => (rtnData[p.prefix] = { ...p }));
|
prefixes.forEach((p) => (rtnData[p.prefix] = { ...p }));
|
||||||
const resData = await res.json();
|
const resData = await res.json();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import TicketSearchBar from '$lib/client/components/TicketSearchBar.svelte';
|
import TicketSearchBar from '$lib/client/components/TicketSearchBar.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let { prefix, prefixes } = $derived(data);
|
let { prefix, prefixes, tamClientID } = $derived(data);
|
||||||
|
|
||||||
let pageTitle = 'Ticket Search | TAM';
|
let pageTitle = 'Ticket Search | TAM';
|
||||||
|
|
||||||
@@ -34,20 +34,22 @@
|
|||||||
let items = $state([]);
|
let items = $state([]);
|
||||||
let itemsBuffer = $derived(items.filter((i) => i.changed));
|
let itemsBuffer = $derived(items.filter((i) => i.changed));
|
||||||
const functions = {
|
const functions = {
|
||||||
async search(){
|
async search() {
|
||||||
const searchParams = new URLSearchParams({ ...searchForm });
|
const searchParams = new URLSearchParams({ ...searchForm });
|
||||||
const res = await fetch(`/api/search/tickets?${searchParams.toString()}`);
|
const res = await fetch(`/api/search/tickets?${searchParams.toString()}`, {
|
||||||
|
headers: { 'TAM-CLIENT-ID': tamClientID }
|
||||||
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const resData = await res.json();
|
const resData = await res.json();
|
||||||
items = [...resData];
|
items = [...resData];
|
||||||
setTimeout(() => focusIdx(0), 1);
|
setTimeout(() => focusIdx(0), 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async save(){
|
async save() {
|
||||||
if (itemsBuffer.length > 0) {
|
if (itemsBuffer.length > 0) {
|
||||||
const res = await fetch('/api/search/tickets', {
|
const res = await fetch('/api/search/tickets', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json', 'TAM-CLIENT-ID': tamClientID },
|
||||||
body: JSON.stringify(itemsBuffer)
|
body: JSON.stringify(itemsBuffer)
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -60,7 +62,7 @@
|
|||||||
focusIdx(0);
|
focusIdx(0);
|
||||||
}, 1);
|
}, 1);
|
||||||
},
|
},
|
||||||
nextLine(){
|
nextLine() {
|
||||||
if (items[nextIdx]) {
|
if (items[nextIdx]) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
focusIdx(nextIdx);
|
focusIdx(nextIdx);
|
||||||
@@ -71,7 +73,7 @@
|
|||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
prevLine(){
|
prevLine() {
|
||||||
if (curIdx > 0) {
|
if (curIdx > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
focusIdx(prevIdx);
|
focusIdx(prevIdx);
|
||||||
@@ -82,7 +84,7 @@
|
|||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dupDown(){
|
dupDown() {
|
||||||
if (items[nextIdx]) {
|
if (items[nextIdx]) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 't_id'].forEach((key) => delete buffer[key]);
|
['prefix', 't_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -92,7 +94,7 @@
|
|||||||
focusIdx(curIdx);
|
focusIdx(curIdx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dupUp(){
|
dupUp() {
|
||||||
if (curIdx > 0) {
|
if (curIdx > 0) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 't_id'].forEach((key) => delete buffer[key]);
|
['prefix', 't_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -102,7 +104,7 @@
|
|||||||
focusIdx(curIdx);
|
focusIdx(curIdx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
copy(){
|
copy() {
|
||||||
if (items[curIdx]) {
|
if (items[curIdx]) {
|
||||||
const buffer = { ...items[curIdx] };
|
const buffer = { ...items[curIdx] };
|
||||||
['prefix', 't_id'].forEach((key) => delete buffer[key]);
|
['prefix', 't_id'].forEach((key) => delete buffer[key]);
|
||||||
@@ -110,7 +112,7 @@
|
|||||||
}
|
}
|
||||||
setTimeout(() => focusIdx(curIdx), 1);
|
setTimeout(() => focusIdx(curIdx), 1);
|
||||||
},
|
},
|
||||||
paste(){
|
paste() {
|
||||||
if (items[curIdx]) {
|
if (items[curIdx]) {
|
||||||
const buffer = JSON.parse(window.localStorage.getItem('tam-ticket'));
|
const buffer = JSON.parse(window.localStorage.getItem('tam-ticket'));
|
||||||
items[curIdx] = { ...items[curIdx], ...buffer, changed: true };
|
items[curIdx] = { ...items[curIdx], ...buffer, changed: true };
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
import HeaderBar from '$lib/client/components/HeaderBar.svelte';
|
import HeaderBar from '$lib/client/components/HeaderBar.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
let { tamClientID } = $derived(data);
|
||||||
let settings = $state({});
|
let settings = $state({});
|
||||||
let status = $state({
|
let status = $state({
|
||||||
message: '',
|
message: '',
|
||||||
@@ -73,6 +74,17 @@
|
|||||||
<div>Venue Name:</div>
|
<div>Venue Name:</div>
|
||||||
<input type="text" id="venue_name" class={iS.normal} bind:value={settings.venue_name} />
|
<input type="text" id="venue_name" class={iS.normal} bind:value={settings.venue_name} />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex flex-row gap-1 items-center">
|
||||||
|
<div>Disable Attribution:</div>
|
||||||
|
<button
|
||||||
|
class={bS.gray}
|
||||||
|
onclick={() => {
|
||||||
|
settings.disable_attrib
|
||||||
|
? (settings.disable_attrib = false)
|
||||||
|
: (settings.disable_attrib = true);
|
||||||
|
}}>{settings.disable_attrib ? 'Yes' : 'No'}</button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
<div class="flex flex-row gap-1 items-center">
|
<div class="flex flex-row gap-1 items-center">
|
||||||
<button
|
<button
|
||||||
class={bS.gray}
|
class={bS.gray}
|
||||||
@@ -80,7 +92,7 @@
|
|||||||
const res = await fetch('/api/settings', {
|
const res = await fetch('/api/settings', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(settings),
|
body: JSON.stringify(settings),
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json', 'TAM-CLIENT-ID': tamClientID }
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
status.message = `Error Code: ${res.status}`;
|
status.message = `Error Code: ${res.status}`;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script>
|
<script>
|
||||||
import HeaderBar from '$lib/client/components/HeaderBar.svelte';
|
import HeaderBar from '$lib/client/components/HeaderBar.svelte';
|
||||||
import { resolve } from '$app/paths';
|
import { resolve } from '$app/paths';
|
||||||
import { bS, iS } from '$lib/client/styles';
|
import { bS, iS, tS } from '$lib/client/styles';
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
let { tamClientID } = $derived(data);
|
||||||
|
|
||||||
const pageTitle = 'Auth Keys | TAM';
|
const pageTitle = 'Auth Keys | TAM';
|
||||||
|
|
||||||
@@ -14,10 +15,11 @@
|
|||||||
let authKeys = $state([]);
|
let authKeys = $state([]);
|
||||||
let newDesc = $state('');
|
let newDesc = $state('');
|
||||||
let curKey = $state('');
|
let curKey = $state('');
|
||||||
|
let errorStatus = $state('');
|
||||||
|
|
||||||
async function getKeys() {
|
async function getKeys() {
|
||||||
const res = await fetch('/api/auth', {
|
const res = await fetch('/api/auth', {
|
||||||
headers: { 'TAM-PWD': auth.pwd }
|
headers: { 'TAM-PWD': auth.pwd, 'TAM-CLIENT-ID': tamClientID }
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
auth.toggle = true;
|
auth.toggle = true;
|
||||||
@@ -25,8 +27,8 @@
|
|||||||
authKeys = [...resData];
|
authKeys = [...resData];
|
||||||
curKey = data.authKey;
|
curKey = data.authKey;
|
||||||
} else {
|
} else {
|
||||||
auth.pwd = 'Invalid Password!';
|
errorStatus = 'Invalid Password!';
|
||||||
setTimeout(() => (auth.pwd = ''), 3000);
|
setTimeout(() => (errorStatus = ''), 7000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -45,9 +47,22 @@
|
|||||||
{#if !auth.toggle}
|
{#if !auth.toggle}
|
||||||
<div class="flex flex-row gap-1 items-center py-1">
|
<div class="flex flex-row gap-1 items-center py-1">
|
||||||
<div>Password:</div>
|
<div>Password:</div>
|
||||||
<input type="password" id="pwd_input" class={iS.normal} bind:value={auth.pwd} />
|
<input
|
||||||
|
type="password"
|
||||||
|
id="pwd_input"
|
||||||
|
class={iS.normal}
|
||||||
|
onkeydown={(event) => {
|
||||||
|
if (event.key == 'Enter') {
|
||||||
|
getKeys();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
bind:value={auth.pwd}
|
||||||
|
/>
|
||||||
<button class={bS.gray} onclick={getKeys}>Login</button>
|
<button class={bS.gray} onclick={getKeys}>Login</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="py-1">
|
||||||
|
<p class={tS.red}>{errorStatus}</p>
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<table class="w-full my-1">
|
<table class="w-full my-1">
|
||||||
<thead class="text-left">
|
<thead class="text-left">
|
||||||
@@ -72,7 +87,10 @@
|
|||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
const res = await fetch('/api/settings', {
|
const res = await fetch('/api/settings', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'TAM-CLIENT-ID': tamClientID
|
||||||
|
},
|
||||||
body: JSON.stringify({ remote_key: key.auth_key })
|
body: JSON.stringify({ remote_key: key.auth_key })
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -86,7 +104,7 @@
|
|||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
const res = await fetch(`/api/auth?key_to_del=${key.auth_key}`, {
|
const res = await fetch(`/api/auth?key_to_del=${key.auth_key}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: { 'TAM-PWD': auth.pwd }
|
headers: { 'TAM-PWD': auth.pwd, 'TAM-CLIENT-ID': tamClientID }
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -112,7 +130,11 @@
|
|||||||
if (newDesc) {
|
if (newDesc) {
|
||||||
const res = await fetch('/api/auth', {
|
const res = await fetch('/api/auth', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'TAM-PWD': auth.pwd, 'Content-Type': 'application/json' },
|
headers: {
|
||||||
|
'TAM-PWD': auth.pwd,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'TAM-CLIENT-ID': tamClientID
|
||||||
|
},
|
||||||
body: JSON.stringify({ description: newDesc })
|
body: JSON.stringify({ description: newDesc })
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
const pageTitle = 'Backup and Restore | TAM';
|
const pageTitle = 'Backup and Restore | TAM';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let remoteServer = $derived(data.remoteServer);
|
let { remoteServer, tamClientID } = $derived(data);
|
||||||
let uploadFile = $state();
|
let uploadFile = $state();
|
||||||
let contents = $state('');
|
let contents = $state('');
|
||||||
let results = $state('');
|
let results = $state('');
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
hour: String(now.getHours()).padStart(2, '0'),
|
hour: String(now.getHours()).padStart(2, '0'),
|
||||||
minutes: String(now.getMinutes()).padStart(2, '0')
|
minutes: String(now.getMinutes()).padStart(2, '0')
|
||||||
};
|
};
|
||||||
const res = await fetch(fetch_url);
|
const res = await fetch(fetch_url, { headers: { 'TAM-CLIENT-ID': tamClientID } });
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const jsonString = JSON.stringify(data, null, 2);
|
const jsonString = JSON.stringify(data, null, 2);
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
const res = await fetch(`/api/backuprestore/${target}`, {
|
const res = await fetch(`/api/backuprestore/${target}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json', 'TAM-CLIENT-ID': tamClientID },
|
||||||
body: contents
|
body: contents
|
||||||
});
|
});
|
||||||
if (res.ok) setResult('File uploaded successfully. Check to see if your data exists.');
|
if (res.ok) setResult('File uploaded successfully. Check to see if your data exists.');
|
||||||
@@ -67,7 +67,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function pushData(target) {
|
async function pushData(target) {
|
||||||
const res = await fetch(`/api/backuprestore/push/${target}`, { method: 'HEAD' });
|
const res = await fetch(`/api/backuprestore/push/${target}`, {
|
||||||
|
method: 'HEAD',
|
||||||
|
headers: { 'TAM-CLIENT-ID': tamClientID }
|
||||||
|
});
|
||||||
const targetStr = target.charAt(0).toUpperCase() + target.slice(1);
|
const targetStr = target.charAt(0).toUpperCase() + target.slice(1);
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
setResult(`${targetStr} pushed successfully.`);
|
setResult(`${targetStr} pushed successfully.`);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
import { resolve } from '$app/paths';
|
import { resolve } from '$app/paths';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
let { tamClientID } = $derived(data);
|
||||||
|
|
||||||
const pageTitle = 'Prefixes | TAM';
|
const pageTitle = 'Prefixes | TAM';
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@
|
|||||||
if (editPrefix.prefix) {
|
if (editPrefix.prefix) {
|
||||||
const req = await fetch('/api/prefixes', {
|
const req = await fetch('/api/prefixes', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json', 'TAM-CLIENT-ID': tamClientID },
|
||||||
body: JSON.stringify([editPrefix])
|
body: JSON.stringify([editPrefix])
|
||||||
});
|
});
|
||||||
if (req.ok) window.location.reload();
|
if (req.ok) window.location.reload();
|
||||||
@@ -125,7 +126,8 @@
|
|||||||
class={bS[prefix.color]}
|
class={bS[prefix.color]}
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
const res = await fetch(`/api/prefixes?p=${prefix.prefix}`, {
|
const res = await fetch(`/api/prefixes?p=${prefix.prefix}`, {
|
||||||
method: 'DELETE'
|
method: 'DELETE',
|
||||||
|
headers: { 'TAM-CLIENT-ID': tamClientID }
|
||||||
});
|
});
|
||||||
if (res.ok) window.location.reload();
|
if (res.ok) window.location.reload();
|
||||||
}}>Delete</button
|
}}>Delete</button
|
||||||
|
|||||||
@@ -26,9 +26,12 @@
|
|||||||
<thead class="sticky top-0">
|
<thead class="sticky top-0">
|
||||||
<tr class="print:hidden">
|
<tr class="print:hidden">
|
||||||
<td colspan="50">
|
<td colspan="50">
|
||||||
<HeaderBar>
|
<HeaderBar />
|
||||||
<div>{pageTitle}</div>
|
</td>
|
||||||
</HeaderBar>
|
</tr>
|
||||||
|
<tr class="print:hidden">
|
||||||
|
<td colspan="50">
|
||||||
|
<h1 class="text-lg font-bold">{pageTitle}</h1>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="print:hidden">
|
<tr class="print:hidden">
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import CommandBar from '$lib/client/components/CommandBar.svelte';
|
import CommandBar from '$lib/client/components/CommandBar.svelte';
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
let { prefix, prefixes } = $derived(data);
|
let { prefix, prefixes, tamClientID } = $derived(data);
|
||||||
|
|
||||||
let pageTitle = $derived(`${prefix.prefix} Tickets | TAM`);
|
let pageTitle = $derived(`${prefix.prefix} Tickets | TAM`);
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
if (pager.idTo - pager.idFrom > 300) {
|
if (pager.idTo - pager.idFrom > 300) {
|
||||||
pager.idTo = pager.idFrom + 300;
|
pager.idTo = pager.idFrom + 300;
|
||||||
}
|
}
|
||||||
const res = await fetch(`/api/tickets/${prefix.prefix}/${pager.idFrom}/${pager.idTo}`);
|
const res = await fetch(`/api/tickets/${prefix.prefix}/${pager.idFrom}/${pager.idTo}`, {headers: {'TAM-CLIENT-ID': tamClientID}});
|
||||||
const resData = await res.json();
|
const resData = await res.json();
|
||||||
resData.map((i) => (i.changed = false));
|
resData.map((i) => (i.changed = false));
|
||||||
items = [...resData];
|
items = [...resData];
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
if (itemsBuffer.length > 0) {
|
if (itemsBuffer.length > 0) {
|
||||||
const res = await fetch('/api/tickets', {
|
const res = await fetch('/api/tickets', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json', 'TAM-CLIENT-ID': tamClientID },
|
||||||
body: JSON.stringify(itemsBuffer)
|
body: JSON.stringify(itemsBuffer)
|
||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -64,6 +64,12 @@
|
|||||||
focusIdx(0);
|
focusIdx(0);
|
||||||
}, 1);
|
}, 1);
|
||||||
},
|
},
|
||||||
|
cancel(){
|
||||||
|
if (itemsBuffer.length > 0) {
|
||||||
|
itemsBuffer.forEach((i) => (i.changed = false));
|
||||||
|
this.getPage();
|
||||||
|
};
|
||||||
|
},
|
||||||
prevPage(){
|
prevPage(){
|
||||||
((pager.idFrom -= itemsLength), (pager.idTo -= itemsLength));
|
((pager.idFrom -= itemsLength), (pager.idTo -= itemsLength));
|
||||||
this.getPage();
|
this.getPage();
|
||||||
@@ -133,8 +139,8 @@
|
|||||||
const headers = ['Ticket ID', 'First Name', 'Last Name', 'Phone Number', 'Pref', 'Save?'];
|
const headers = ['Ticket ID', 'First Name', 'Last Name', 'Phone Number', 'Pref', 'Save?'];
|
||||||
|
|
||||||
if (browser) {
|
if (browser) {
|
||||||
window.addEventListener('beforeunload', (e) => {
|
window.addEventListener('beforeunload', () => {
|
||||||
if (itemsBuffer.length > 0) e.preventDefault();
|
if (itemsBuffer.length > 0) functions.save();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -212,10 +218,10 @@
|
|||||||
item.changed = true;
|
item.changed = true;
|
||||||
}}
|
}}
|
||||||
onkeydown={(e) => {
|
onkeydown={(e) => {
|
||||||
if (e.key == 't') {
|
if (e.key == 't' || e.key == 'T') {
|
||||||
if (item.pref != 'TEXT') item.changed = true;
|
if (item.pref != 'TEXT') item.changed = true;
|
||||||
item.pref = 'TEXT';
|
item.pref = 'TEXT';
|
||||||
} else if (e.key == 'c') {
|
} else if (e.key == 'c' || e.key == 'C') {
|
||||||
if (item.pref != 'CALL') item.changed = true;
|
if (item.pref != 'CALL') item.changed = true;
|
||||||
item.pref = 'CALL';
|
item.pref = 'CALL';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
if [ ! -d "./data" ]; then
|
if [ ! -d "./data" ]; then
|
||||||
mkdir ./data
|
mkdir ./data
|
||||||
fi
|
fi
|
||||||
HOST=127.0.0.1 PORT=3000 ./exe/bin/node ./build
|
NODE_TLS_REJECT_UNAUTHORIZED=0 BODY_SIZE_LIMIT=Infinity HOST=localhost PORT=3000 ./exe/bin/node ./build
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
{ config, pkgs, ... }
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
networking.hosts = {
|
||||||
|
"192.168.1.1" = [ "tam.lan" ]; # Change the IP of this line to the IP of the TAM server if applicable.
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users."tam" = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "Ticket Auction Manager";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.displayManager.sddm.settings.Autologin = {
|
||||||
|
Session = "plasma.desktop";
|
||||||
|
User = "tam";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
chromium
|
||||||
|
];
|
||||||
|
|
||||||
|
virtualisation.docker.enable = true;
|
||||||
|
|
||||||
|
virtualisation.oci-containers = {
|
||||||
|
backend = "docker";
|
||||||
|
containers."tam-client" = {
|
||||||
|
image = "dbob16/tam-client:0.1.0"; # Change image to local repo to avoid pull limits.
|
||||||
|
volumes = [
|
||||||
|
"tam-data:/data"
|
||||||
|
];
|
||||||
|
environment = {
|
||||||
|
HOST = "localhost";
|
||||||
|
PORT = "3000";
|
||||||
|
};
|
||||||
|
extraOptions = ["--network=host"]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Reference in new issue
Block a user