Seed weather app + settings capability

LXC 131, base_path '/weather/admin' (portal card opens the authed status
page directly; the app's bare root '/weather/' is the public, no-auth
reception display). Single 'settings' capability, not auto-granted to
Staff — grant via Admin -> Roles.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-08-25 12:23:02 +00:00
parent d48701fcd0
commit 5a004bd606

View file

@ -489,6 +489,83 @@ export async function initDb() {
sort_order = EXCLUDED.sort_order
`)
// Seed tasks app + capabilities. LXC 130 — personal task planner (lists,
// reminders, recurring to-dos). 'use' granted to Staff so everyone gets their
// own tasks; 'assign'/'admin' reserved for phase-2 cross-user assignment.
await pool.query(`
INSERT INTO apps (slug, name, description, base_path, icon, theme_color, category, internal_host, internal_port)
VALUES ('tasks', 'Tasks', 'Personal task planner — lists, reminders and recurring to-dos', '/tasks', 'ListChecks', '#0d9488', 'Operations', '10.10.10.130', 3080)
ON CONFLICT (slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
base_path = EXCLUDED.base_path,
icon = EXCLUDED.icon,
theme_color = EXCLUDED.theme_color,
category = EXCLUDED.category,
internal_host = EXCLUDED.internal_host,
internal_port = EXCLUDED.internal_port
`)
await pool.query(`
INSERT INTO app_capabilities (app_id, slug, name, description, sort_order)
SELECT a.id, c.slug, c.name, c.description, c.sort_order
FROM apps a
CROSS JOIN (VALUES
('use', 'Use Tasks', 'Create and manage your own lists and tasks', 1),
('assign', 'Assign Tasks', 'Assign tasks to other users (phase 2)', 2),
('admin', 'Manage All', 'View and manage every user''s tasks (phase 2)', 3),
('settings', 'Settings', 'Configure tasks app settings', 4)
) AS c(slug, name, description, sort_order)
WHERE a.slug = 'tasks'
ON CONFLICT (app_id, slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
sort_order = EXCLUDED.sort_order
`)
await pool.query(`
INSERT INTO role_capabilities (role_id, capability_id)
SELECT r.id, ac.id
FROM roles r
JOIN app_capabilities ac ON ac.slug = 'use'
JOIN apps a ON a.id = ac.app_id AND a.slug = 'tasks'
WHERE r.slug = 'staff'
ON CONFLICT DO NOTHING
`)
// Seed weather app + capability. LXC 131 — reception forecast display. base_path
// is '/weather/admin', not '/weather': the portal card takes staff to the authed
// status/refresh page, while the app's bare root ('/weather/') is a deliberately
// public, no-auth full-screen display for the reception kiosk (see project_weather
// memory). 'settings' is the only capability and is NOT auto-granted to Staff —
// grant it to the appropriate role via the portal (Admin → Roles).
await pool.query(`
INSERT INTO apps (slug, name, description, base_path, icon, theme_color, category, internal_host, internal_port)
VALUES ('weather', 'Weather', 'Reception forecast display — today hourly, next 2 days, 7-day outlook', '/weather/admin', 'CloudSun', '#0ea5e9', 'Hotel', '10.10.10.131', 3080)
ON CONFLICT (slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
base_path = EXCLUDED.base_path,
icon = EXCLUDED.icon,
theme_color = EXCLUDED.theme_color,
category = EXCLUDED.category,
internal_host = EXCLUDED.internal_host,
internal_port = EXCLUDED.internal_port
`)
await pool.query(`
INSERT INTO app_capabilities (app_id, slug, name, description, sort_order)
SELECT a.id, c.slug, c.name, c.description, c.sort_order
FROM apps a, (VALUES
('settings', 'Settings', 'View forecast fetch status and trigger a manual refresh', 1)
) AS c(slug, name, description, sort_order)
WHERE a.slug = 'weather'
ON CONFLICT (app_id, slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
sort_order = EXCLUDED.sort_order
`)
// Seed first admin user if table is empty
const { rows } = await pool.query('SELECT COUNT(*) FROM users')
if (parseInt(rows[0].count) === 0) {