feat(migrations): canonical nav schema + apps seed + menu-items template

Three SQL files for apps to copy into their own migrations directory:

- nav-schema.up.sql      — schema "nav" + enum menu_type + tables
                            menu_items, menu_role_requirements,
                            menu_permission_requirements,
                            menu_product_requirements, apps. Apply
                            verbatim; the kit owns it.
- nav-apps-seed.up.sql   — canonical cross-app browse-apps list,
                            idempotent INSERT … ON CONFLICT DO UPDATE.
                            Updates flow via kit version bumps; apps
                            re-apply to receive new entries.
- nav-menu-items-template.sql — TEMPLATE only. Each app copies once,
                            renames to its next migration number, and
                            edits the seed rows for its own sidebar/
                            topbar/subbar items.

Adoption pattern documented in the kit README.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude
2026-05-12 11:24:46 +02:00
parent 440f815df7
commit 960dfeba7c
3 changed files with 217 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
-- @gsc/web-kit nav.menu_items TEMPLATE — copy once, then adapt per app
--
-- Each app curates its own sidebar/topbar/subbar items. Copy this file into
-- your app's migrations directory (e.g. apps/gscFoo/migrations/00X_nav_menu_items.up.sql),
-- replace the example rows below with your app's real menu, and apply.
--
-- The kit will NOT update this file in subsequent versions — once you've
-- copied and adapted it, it's yours. The DDL (nav-schema.up.sql) and the
-- canonical apps list (nav-apps-seed.up.sql) are kit-owned and re-copied
-- on every kit upgrade; menu_items rows belong to the app.
--
-- Notes on columns:
-- - key: unique stable identifier (used by ON CONFLICT)
-- - translation_key: dotted i18n key, e.g. "menu.dashboard"
-- (resolved via next-intl namespace "menu")
-- - url: "/dashboard" — pass "#" for parent items with children
-- - icon: Phosphor CSS class, e.g. "ph-house"
-- - menu_type: 'sidebar' (left nav), 'topbar' (user dropdown), 'subbar' (settings dropdown)
-- - parent_id: UUID of parent menu_item for nested items (or NULL)
-- - sort_order: ascending; render order within type/parent
-- - is_system_required: cannot be hidden/removed by user customization
-- ============================================================================
-- SIDEBAR (left navigation)
-- ============================================================================
INSERT INTO nav.menu_items (menu_type, key, translation_key, url, icon, sort_order, is_active, is_system_required)
VALUES
-- Replace these example rows with your app's sidebar items.
('sidebar', 'dashboard', 'menu.dashboard', '/dashboard', 'ph-house', 10, TRUE, TRUE),
('sidebar', 'example-1', 'menu.example1', '/example-1', 'ph-folder-open', 20, TRUE, FALSE),
('sidebar', 'example-2', 'menu.example2', '/example-2', 'ph-list', 30, TRUE, FALSE)
ON CONFLICT (key) DO NOTHING;
-- ============================================================================
-- TOPBAR (user dropdown in navbar)
-- ============================================================================
INSERT INTO nav.menu_items (menu_type, key, translation_key, url, icon, sort_order, is_active, is_system_required)
VALUES
('topbar', 'profile', 'menu.profile', '/profile', 'ph-user', 10, TRUE, TRUE),
('topbar', 'settings', 'menu.settings', '/settings', 'ph-gear', 20, TRUE, TRUE)
ON CONFLICT (key) DO NOTHING;
-- ============================================================================
-- SUBBAR (Settings dropdown items)
-- ============================================================================
-- Uncomment / customize if your app exposes a Settings dropdown in the subbar.
--
-- INSERT INTO nav.menu_items (menu_type, key, translation_key, url, icon, sort_order, is_active, is_system_required)
-- VALUES
-- ('subbar', 'general-settings', 'menu.generalSettings', '/settings/general', 'ph-sliders', 10, TRUE, FALSE),
-- ('subbar', 'notifications', 'menu.notifications', '/settings/notifications', 'ph-bell', 20, TRUE, FALSE)
-- ON CONFLICT (key) DO NOTHING;
-- ============================================================================
-- NESTED EXAMPLES (parent + children)
-- ============================================================================
-- For nested sidebar items, set url='#' on the parent and reference its id
-- via parent_id on children. Example:
--
-- WITH parent AS (
-- INSERT INTO nav.menu_items (menu_type, key, translation_key, url, icon, sort_order)
-- VALUES ('sidebar', 'reports', 'menu.reports', '#', 'ph-chart-bar', 90)
-- ON CONFLICT (key) DO UPDATE SET sort_order = EXCLUDED.sort_order
-- RETURNING id
-- )
-- INSERT INTO nav.menu_items (menu_type, parent_id, key, translation_key, url, icon, sort_order)
-- SELECT 'sidebar', parent.id, 'reports-sales', 'menu.reportsSales', '/reports/sales', 'ph-chart-line', 10 FROM parent
-- UNION ALL
-- SELECT 'sidebar', parent.id, 'reports-leads', 'menu.reportsLeads', '/reports/leads', 'ph-chart-pie', 20 FROM parent
-- ON CONFLICT (key) DO NOTHING;