259 lines
10 KiB
PL/PgSQL
259 lines
10 KiB
PL/PgSQL
-- Department Dashboards: composable workspace for event departments
|
|
-- Each department gets a dashboard with configurable module panels
|
|
|
|
-- ============================================================
|
|
-- 1. Module types enum
|
|
-- ============================================================
|
|
CREATE TYPE module_type AS ENUM (
|
|
'kanban',
|
|
'files',
|
|
'checklist',
|
|
'notes',
|
|
'schedule',
|
|
'contacts'
|
|
);
|
|
|
|
-- ============================================================
|
|
-- 2. Layout presets enum
|
|
-- ============================================================
|
|
CREATE TYPE layout_preset AS ENUM (
|
|
'single',
|
|
'split',
|
|
'grid',
|
|
'focus_sidebar',
|
|
'custom'
|
|
);
|
|
|
|
-- ============================================================
|
|
-- 3. Department Dashboards
|
|
-- ============================================================
|
|
CREATE TABLE department_dashboards (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
|
layout layout_preset NOT NULL DEFAULT 'split',
|
|
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ DEFAULT now(),
|
|
updated_at TIMESTAMPTZ DEFAULT now(),
|
|
UNIQUE(department_id)
|
|
);
|
|
|
|
CREATE INDEX idx_dept_dashboards_dept ON department_dashboards(department_id);
|
|
|
|
-- ============================================================
|
|
-- 4. Dashboard Panels (modules placed on a dashboard)
|
|
-- ============================================================
|
|
CREATE TABLE dashboard_panels (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
dashboard_id UUID NOT NULL REFERENCES department_dashboards(id) ON DELETE CASCADE,
|
|
module module_type NOT NULL,
|
|
position INT NOT NULL DEFAULT 0,
|
|
width TEXT NOT NULL DEFAULT 'half' CHECK (width IN ('full', 'half', 'third', 'two_thirds')),
|
|
config JSONB DEFAULT '{}',
|
|
created_at TIMESTAMPTZ DEFAULT now(),
|
|
UNIQUE(dashboard_id, position)
|
|
);
|
|
|
|
CREATE INDEX idx_dashboard_panels_dashboard ON dashboard_panels(dashboard_id);
|
|
|
|
-- ============================================================
|
|
-- 5. Checklists (scoped to department)
|
|
-- ============================================================
|
|
CREATE TABLE department_checklists (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL DEFAULT 'Checklist',
|
|
sort_order INT NOT NULL DEFAULT 0,
|
|
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX idx_dept_checklists_dept ON department_checklists(department_id);
|
|
|
|
CREATE TABLE department_checklist_items (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
checklist_id UUID NOT NULL REFERENCES department_checklists(id) ON DELETE CASCADE,
|
|
content TEXT NOT NULL,
|
|
is_completed BOOLEAN NOT NULL DEFAULT false,
|
|
assigned_to UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
due_date TIMESTAMPTZ,
|
|
sort_order INT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ DEFAULT now(),
|
|
updated_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX idx_dept_checklist_items_checklist ON department_checklist_items(checklist_id);
|
|
CREATE INDEX idx_dept_checklist_items_assigned ON department_checklist_items(assigned_to);
|
|
|
|
-- ============================================================
|
|
-- 6. Department Notes (simple rich text notes)
|
|
-- ============================================================
|
|
CREATE TABLE department_notes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL DEFAULT 'Untitled Note',
|
|
content TEXT DEFAULT '',
|
|
sort_order INT NOT NULL DEFAULT 0,
|
|
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ DEFAULT now(),
|
|
updated_at TIMESTAMPTZ DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX idx_dept_notes_dept ON department_notes(department_id);
|
|
|
|
-- ============================================================
|
|
-- 7. Add enabled_modules to event_departments
|
|
-- ============================================================
|
|
ALTER TABLE event_departments
|
|
ADD COLUMN enabled_modules module_type[] NOT NULL DEFAULT ARRAY['kanban'::module_type, 'files'::module_type, 'checklist'::module_type];
|
|
|
|
-- ============================================================
|
|
-- 8. RLS Policies
|
|
-- ============================================================
|
|
ALTER TABLE department_dashboards ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE dashboard_panels ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE department_checklists ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE department_checklist_items ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE department_notes ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Helper: check if user is org member for a department
|
|
-- (department → event → org → org_members)
|
|
|
|
-- Department Dashboards
|
|
CREATE POLICY "Org members can view department dashboards" ON department_dashboards FOR SELECT
|
|
USING (EXISTS (
|
|
SELECT 1 FROM event_departments ed
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE ed.id = department_dashboards.department_id AND om.user_id = auth.uid()
|
|
));
|
|
|
|
CREATE POLICY "Editors can manage department dashboards" ON department_dashboards FOR ALL
|
|
USING (EXISTS (
|
|
SELECT 1 FROM event_departments ed
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE ed.id = department_dashboards.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
|
));
|
|
|
|
-- Dashboard Panels
|
|
CREATE POLICY "Org members can view dashboard panels" ON dashboard_panels FOR SELECT
|
|
USING (EXISTS (
|
|
SELECT 1 FROM department_dashboards dd
|
|
JOIN event_departments ed ON dd.department_id = ed.id
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE dd.id = dashboard_panels.dashboard_id AND om.user_id = auth.uid()
|
|
));
|
|
|
|
CREATE POLICY "Editors can manage dashboard panels" ON dashboard_panels FOR ALL
|
|
USING (EXISTS (
|
|
SELECT 1 FROM department_dashboards dd
|
|
JOIN event_departments ed ON dd.department_id = ed.id
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE dd.id = dashboard_panels.dashboard_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
|
));
|
|
|
|
-- Department Checklists
|
|
CREATE POLICY "Org members can view department checklists" ON department_checklists FOR SELECT
|
|
USING (EXISTS (
|
|
SELECT 1 FROM event_departments ed
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE ed.id = department_checklists.department_id AND om.user_id = auth.uid()
|
|
));
|
|
|
|
CREATE POLICY "Editors can manage department checklists" ON department_checklists FOR ALL
|
|
USING (EXISTS (
|
|
SELECT 1 FROM event_departments ed
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE ed.id = department_checklists.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
|
));
|
|
|
|
-- Department Checklist Items
|
|
CREATE POLICY "Org members can view dept checklist items" ON department_checklist_items FOR SELECT
|
|
USING (EXISTS (
|
|
SELECT 1 FROM department_checklists dc
|
|
JOIN event_departments ed ON dc.department_id = ed.id
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE dc.id = department_checklist_items.checklist_id AND om.user_id = auth.uid()
|
|
));
|
|
|
|
CREATE POLICY "Editors can manage dept checklist items" ON department_checklist_items FOR ALL
|
|
USING (EXISTS (
|
|
SELECT 1 FROM department_checklists dc
|
|
JOIN event_departments ed ON dc.department_id = ed.id
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE dc.id = department_checklist_items.checklist_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
|
));
|
|
|
|
-- Department Notes
|
|
CREATE POLICY "Org members can view department notes" ON department_notes FOR SELECT
|
|
USING (EXISTS (
|
|
SELECT 1 FROM event_departments ed
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE ed.id = department_notes.department_id AND om.user_id = auth.uid()
|
|
));
|
|
|
|
CREATE POLICY "Editors can manage department notes" ON department_notes FOR ALL
|
|
USING (EXISTS (
|
|
SELECT 1 FROM event_departments ed
|
|
JOIN events e ON ed.event_id = e.id
|
|
JOIN org_members om ON e.org_id = om.org_id
|
|
WHERE ed.id = department_notes.department_id AND om.user_id = auth.uid() AND om.role IN ('owner', 'admin', 'editor')
|
|
));
|
|
|
|
-- ============================================================
|
|
-- 9. Enable realtime
|
|
-- ============================================================
|
|
ALTER PUBLICATION supabase_realtime ADD TABLE department_checklists;
|
|
ALTER PUBLICATION supabase_realtime ADD TABLE department_checklist_items;
|
|
ALTER PUBLICATION supabase_realtime ADD TABLE department_notes;
|
|
ALTER PUBLICATION supabase_realtime ADD TABLE dashboard_panels;
|
|
|
|
-- ============================================================
|
|
-- 10. Auto-create dashboard when department is created
|
|
-- ============================================================
|
|
CREATE OR REPLACE FUNCTION public.create_department_dashboard()
|
|
RETURNS TRIGGER AS $$
|
|
DECLARE
|
|
dash_id UUID;
|
|
mod module_type;
|
|
pos INT := 0;
|
|
BEGIN
|
|
-- Create dashboard
|
|
INSERT INTO public.department_dashboards (department_id, layout)
|
|
VALUES (NEW.id, 'split')
|
|
RETURNING id INTO dash_id;
|
|
|
|
-- Create panels for each enabled module
|
|
FOREACH mod IN ARRAY NEW.enabled_modules LOOP
|
|
INSERT INTO public.dashboard_panels (dashboard_id, module, position, width)
|
|
VALUES (dash_id, mod, pos, CASE WHEN pos = 0 THEN 'half' ELSE 'half' END);
|
|
pos := pos + 1;
|
|
END LOOP;
|
|
|
|
-- Auto-create a default checklist if checklist module is enabled
|
|
IF 'checklist' = ANY(NEW.enabled_modules) THEN
|
|
INSERT INTO public.department_checklists (department_id, title, sort_order)
|
|
VALUES (NEW.id, 'General', 0);
|
|
END IF;
|
|
|
|
-- Auto-create a default note if notes module is enabled
|
|
IF 'notes' = ANY(NEW.enabled_modules) THEN
|
|
INSERT INTO public.department_notes (department_id, title, content, sort_order)
|
|
VALUES (NEW.id, 'Meeting Notes', '', 0);
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
|
|
CREATE TRIGGER on_department_created_setup_dashboard
|
|
AFTER INSERT ON event_departments
|
|
FOR EACH ROW EXECUTE FUNCTION public.create_department_dashboard();
|