diff --git a/migrations/0008_roadmap_planned.sql b/migrations/0008_roadmap_planned.sql new file mode 100644 index 0000000..6be6420 --- /dev/null +++ b/migrations/0008_roadmap_planned.sql @@ -0,0 +1,39 @@ +-- Roadmap status enum gains a fifth value `planned` for items that are +-- committed and scheduled but not yet started — sitting between `in_beta` +-- and `exploring` in the progression. +-- +-- SQLite can't widen a CHECK constraint in place, so this is a full table +-- rebuild (same approach as 0006). roadmap_attributions has an ON DELETE +-- CASCADE FK to roadmap_items(id), so foreign keys are toggled off around +-- the rebuild to preserve attribution rows across the DROP/RENAME. The +-- metadata_text column added in 0007 is carried through. + +PRAGMA foreign_keys = OFF; + +CREATE TABLE roadmap_items_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + description TEXT NOT NULL DEFAULT '', + status TEXT NOT NULL DEFAULT 'exploring' + CHECK(status IN ('shipping','in_beta','planned','exploring','considering')), + target TEXT, + display_order INTEGER NOT NULL DEFAULT 0, + shipped_at TEXT, + metadata_text TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now')), + updated_at TEXT NOT NULL DEFAULT (datetime('now')) +); + +INSERT INTO roadmap_items_new + (id, title, description, status, target, display_order, shipped_at, metadata_text, created_at, updated_at) +SELECT + id, title, description, status, target, display_order, shipped_at, metadata_text, created_at, updated_at +FROM roadmap_items; + +DROP TABLE roadmap_items; +ALTER TABLE roadmap_items_new RENAME TO roadmap_items; + +CREATE INDEX idx_roadmap_status ON roadmap_items(status, display_order); +CREATE INDEX idx_roadmap_shipped ON roadmap_items(shipped_at); + +PRAGMA foreign_keys = ON; diff --git a/src/admin/admin.css b/src/admin/admin.css index 89f05a5..ede93a7 100644 --- a/src/admin/admin.css +++ b/src/admin/admin.css @@ -802,6 +802,7 @@ .pill-declined { background: rgba(0, 0, 0, 0.04); color: var(--on-surface-muted); } .pill-shipping { background: rgba(109, 140, 124, 0.18); color: #5a7268; } .pill-in-beta { background: rgba(185, 107, 88, 0.10); color: #b96b58; } +.pill-planned { background: rgba(90, 109, 131, 0.12); color: #5a6d83; } .pill-exploring { background: rgba(186, 186, 176, 0.20); color: var(--on-surface-variant); } .pill-considering{ background: rgba(186, 186, 176, 0.10); color: var(--on-surface-muted); } .pill-active { background: rgba(109, 140, 124, 0.15); color: #6d8c7c; } diff --git a/src/admin/resources/roadmap.ts b/src/admin/resources/roadmap.ts index 01c0450..8b32e61 100644 --- a/src/admin/resources/roadmap.ts +++ b/src/admin/resources/roadmap.ts @@ -48,6 +48,7 @@ export const roadmapResource: Resource = { pillVariants: { shipping: { label: 'Shipping', class: 'pill-shipping' }, in_beta: { label: 'In beta', class: 'pill-in-beta' }, + planned: { label: 'Planned', class: 'pill-planned' }, exploring: { label: 'Exploring', class: 'pill-exploring' }, considering: { label: 'Considering', class: 'pill-considering' }, }, @@ -69,6 +70,7 @@ export const roadmapResource: Resource = { { key: 'all', label: 'All', predicate: () => true, isDefault: true }, { key: 'shipping', label: 'Shipping', predicate: (i) => i.status === 'shipping' }, { key: 'in_beta', label: 'In beta', predicate: (i) => i.status === 'in_beta' }, + { key: 'planned', label: 'Planned', predicate: (i) => i.status === 'planned' }, { key: 'exploring', label: 'Exploring', predicate: (i) => i.status === 'exploring' }, { key: 'considering', label: 'Considering', predicate: (i) => i.status === 'considering' }, ], @@ -99,6 +101,7 @@ export const roadmapResource: Resource = { options: [ { value: 'shipping', label: 'Shipping' }, { value: 'in_beta', label: 'In beta' }, + { value: 'planned', label: 'Planned' }, { value: 'exploring', label: 'Exploring' }, { value: 'considering', label: 'Considering' }, ], diff --git a/src/components/RoadmapCarousel.astro b/src/components/RoadmapCarousel.astro index 94ecf5e..f62abf6 100644 --- a/src/components/RoadmapCarousel.astro +++ b/src/components/RoadmapCarousel.astro @@ -10,6 +10,7 @@ const { items } = Astro.props; const STATUS_LABEL: Record = { shipping: 'SHIPPING', in_beta: 'IN BETA', + planned: 'PLANNED', exploring: 'EXPLORING', considering: 'CONSIDERING', }; @@ -17,6 +18,7 @@ const STATUS_LABEL: Record = { const STATUS_LABEL_COLOR: Record = { shipping: 'var(--pigment-copper)', in_beta: 'var(--pigment-terracotta)', + planned: 'var(--pigment-indigo)', exploring: '#b4b2a9', considering: '#b4b2a9', }; @@ -24,6 +26,7 @@ const STATUS_LABEL_COLOR: Record = { const STATUS_DOT_COLOR: Record = { shipping: 'var(--pigment-copper)', in_beta: 'var(--pigment-terracotta)', + planned: 'var(--pigment-indigo)', exploring: '#b4b2a9', considering: '#d4d2c8', }; diff --git a/src/components/RoadmapRoute.astro b/src/components/RoadmapRoute.astro index 53e490e..f6fce0c 100644 --- a/src/components/RoadmapRoute.astro +++ b/src/components/RoadmapRoute.astro @@ -25,18 +25,21 @@ const travelledStop = travelledStopFor(items.map(i => i.status)); const STATUS_LABEL: Record = { shipping: 'SHIPPING', in_beta: 'IN BETA', + planned: 'PLANNED', exploring: 'EXPLORING', considering: 'CONSIDERING', }; const STATUS_LABEL_COLOR: Record = { shipping: '#6d8c7c', in_beta: '#b96b58', + planned: '#5a6d83', exploring: '#b4b2a9', considering: '#b4b2a9', }; const STATUS_DOT_COLOR: Record = { shipping: '#6d8c7c', in_beta: '#b96b58', + planned: '#5a6d83', exploring: '#b4b2a9', considering: '#d4d2c8', }; diff --git a/src/lib/db.ts b/src/lib/db.ts index cf9ff94..30f3321 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -688,7 +688,7 @@ export function countPulseParticipants(pulseId: number): number { // ── Roadmap items ──────────────────────────────────────────────── -export type RoadmapStatus = 'shipping' | 'in_beta' | 'exploring' | 'considering'; +export type RoadmapStatus = 'shipping' | 'in_beta' | 'planned' | 'exploring' | 'considering'; export interface RoadmapItem { id: number; diff --git a/src/lib/roadmap-layout.ts b/src/lib/roadmap-layout.ts index da82424..4b19497 100644 --- a/src/lib/roadmap-layout.ts +++ b/src/lib/roadmap-layout.ts @@ -113,7 +113,7 @@ export function computeRouteLayout(opts: LayoutOpts): LayoutResult { * - Clamped to [0, 0.98] so the fade-to-ahead is always visible */ export function travelledStopFor( - statuses: ReadonlyArray<'shipping' | 'in_beta' | 'exploring' | 'considering'>, + statuses: ReadonlyArray<'shipping' | 'in_beta' | 'planned' | 'exploring' | 'considering'>, ): number { if (statuses.length === 0) return 0; let last = -1; diff --git a/src/pages/roadmap.astro b/src/pages/roadmap.astro index 7e4e54d..6b74c1e 100644 --- a/src/pages/roadmap.astro +++ b/src/pages/roadmap.astro @@ -28,6 +28,7 @@ const items = getAllRoadmapItems()
Shipping In beta + Planned Exploring Considering