Categories move from a hard-coded list to a feedback_categories table (migration 0062), seeded with the four existing keys, labels and descriptions so production feedback is untouched; any other key already in use gets an archived category. Keys are fixed, so renames relabel past feedback. Archive hides a category from the form; only unused categories can be deleted. Submissions are validated against active categories, and feedback responses carry category_label. New: GET /feedback/categories (public); /admin/feedback/categories CRUD + reorder behind the new feedback:categories permission (granted to Admin). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
42 lines
2.2 KiB
SQL
42 lines
2.2 KiB
SQL
-- Feedback categories, managed from the admin panel instead of hard-coded in
|
|
-- the app and the BFF.
|
|
--
|
|
-- `key` is what feedback.category stores, and never changes once created —
|
|
-- so renaming a category in the admin relabels every past submission too.
|
|
-- Archiving hides a category from the /feedback form while existing feedback
|
|
-- keeps its label. There is deliberately no foreign key from feedback: the
|
|
-- column predates this table, and the admin only hard-deletes categories
|
|
-- nothing uses.
|
|
CREATE TABLE IF NOT EXISTS feedback_categories (
|
|
key TEXT PRIMARY KEY,
|
|
label TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
archived_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- The four categories the app offered until now, with the exact labels and
|
|
-- descriptions its form showed, in the form's order. Production feedback
|
|
-- already uses these keys, so they must stay byte-for-byte the same.
|
|
INSERT INTO feedback_categories (key, label, description, sort_order) VALUES
|
|
('general', 'General feedback', 'Thoughts, impressions, suggestions — anything else.', 0),
|
|
('bug', 'Bug report', 'Something is broken or behaving unexpectedly.', 1),
|
|
('feature', 'Feature request', 'An idea for something new on the site.', 2),
|
|
('other', 'Other', 'Doesn''t fit the above? Use this.', 3)
|
|
ON CONFLICT (key) DO NOTHING;
|
|
|
|
-- Safety net: any other key already present in feedback (from an older
|
|
-- client) gets a category too — archived, so it isn't offered on the form,
|
|
-- but its submissions still carry a readable label.
|
|
INSERT INTO feedback_categories (key, label, sort_order, archived_at)
|
|
SELECT DISTINCT f.category, initcap(replace(f.category, '_', ' ')), 100, now()
|
|
FROM feedback f
|
|
WHERE NOT EXISTS (SELECT 1 FROM feedback_categories c WHERE c.key = f.category)
|
|
ON CONFLICT (key) DO NOTHING;
|
|
|
|
-- The Admin role may manage them; Superadmin already has '*'.
|
|
UPDATE admin_roles
|
|
SET permissions = array_append(permissions, 'feedback:categories')
|
|
WHERE key = 'admin' AND NOT ('feedback:categories' = ANY(permissions));
|