Add tasks multi-view dashboard design spec
This commit is contained in:
parent
dd6e5b7d64
commit
1a00f84364
1 changed files with 374 additions and 0 deletions
|
|
@ -0,0 +1,374 @@
|
|||
# Go Backend Tasks Multi-View Dashboard Design
|
||||
|
||||
**Date:** 2026-05-10
|
||||
|
||||
**Goal**
|
||||
|
||||
Replace the current simple `/tasks` CRUD page in `go-backend` with a richer owner-level tasks dashboard that aggregates tasks across every tablo owned by the signed-in user and renders three server-side views:
|
||||
|
||||
- `Tableau`
|
||||
- `Liste`
|
||||
- `Roadmap`
|
||||
|
||||
The page should use query params as the source of truth for view state and filtering, while keeping task creation, editing, and deletion inside the existing server-rendered and HTMX-friendly backend architecture.
|
||||
|
||||
**Context**
|
||||
|
||||
The current tasks vertical slice already exists in `go-backend`:
|
||||
|
||||
- owner-scoped task and etape persistence is implemented
|
||||
- `/tasks` already supports create, edit, update, and delete
|
||||
- the page is currently rendered as a simple grouped CRUD view
|
||||
|
||||
This work does not redesign the persistence model. It redesigns the `/tasks` page contract, its server-side view shaping, and the related create/edit flows so the route behaves like a personal cross-tablo dashboard.
|
||||
|
||||
**Scope**
|
||||
|
||||
- Work exclusively in `go-backend`
|
||||
- Replace the current `/tasks` page with a server-rendered dashboard
|
||||
- Aggregate tasks across all tablos owned by the current user
|
||||
- Support three server-rendered views on the same route:
|
||||
- `kanban`
|
||||
- `list`
|
||||
- `roadmap`
|
||||
- Support URL-driven state with query params
|
||||
- Implement functional filtering for:
|
||||
- `tablo`
|
||||
- `assignee`
|
||||
- `status`
|
||||
- Extend create and edit forms to include:
|
||||
- `tablo_id`
|
||||
- `parent_task_id`
|
||||
- `assignee_id`
|
||||
- `due_date`
|
||||
- `status`
|
||||
- `title`
|
||||
- `description`
|
||||
- Constrain selectable etapes to the chosen tablo during create and edit
|
||||
- Implement two roadmap sub-modes:
|
||||
- `week`
|
||||
- `month`
|
||||
|
||||
**Out Of Scope**
|
||||
|
||||
- Drag and drop
|
||||
- Client-only tab switching
|
||||
- Calendar view
|
||||
- Reordering tasks or etapes
|
||||
- Persisted synthetic "Sans étape" rows
|
||||
- New JSON API endpoints
|
||||
- Collaborator or RBAC expansion beyond owner-only access
|
||||
- Comments, attachments, activity feeds, or task detail pages
|
||||
|
||||
**Architecture**
|
||||
|
||||
The feature should stay inside the current Go server-rendered stack:
|
||||
|
||||
- HTTP handlers in `go-backend/internal/web/handlers/`
|
||||
- page and component rendering in `go-backend/internal/web/views/`
|
||||
- task shaping and task-related helpers in `go-backend/internal/tasks/` or closely related view-model code
|
||||
- existing repository methods reused or extended only as needed
|
||||
|
||||
The core architectural move is to split `/tasks` rendering into:
|
||||
|
||||
1. one shared page-state parser
|
||||
2. one shared filtered task dataset
|
||||
3. three pure view-specific shaping functions
|
||||
|
||||
Recommended shaping functions:
|
||||
|
||||
- `buildKanbanView(...)`
|
||||
- `buildListView(...)`
|
||||
- `buildRoadmapView(...)`
|
||||
|
||||
This keeps filtering and ownership logic centralized while isolating presentation-specific grouping rules.
|
||||
|
||||
**Route Contract**
|
||||
|
||||
The route remains `GET /tasks`, but the page state is now controlled by query params.
|
||||
|
||||
Supported query params:
|
||||
|
||||
- `view=kanban|list|roadmap`
|
||||
- `roadmap_mode=week|month`
|
||||
- `tablo=<tablo_id>` optional, repeatable
|
||||
- `assignee=<user_id>` optional, repeatable
|
||||
- `status=todo|in_progress|in_review|done` optional, repeatable
|
||||
|
||||
Default behavior:
|
||||
|
||||
- missing or invalid `view` falls back to `kanban`
|
||||
- missing or invalid `roadmap_mode` falls back to `week`
|
||||
- invalid filter values are ignored rather than breaking the page
|
||||
- `roadmap_mode` is ignored when `view` is not `roadmap`
|
||||
|
||||
The page should remain shareable and refresh-safe:
|
||||
|
||||
- filter changes submit with `GET /tasks`
|
||||
- tabs are links that preserve the current applicable filters
|
||||
- roadmap mode toggles are links or GET forms that preserve filters
|
||||
|
||||
**Data Scope**
|
||||
|
||||
All three views consume the same owner-scoped task set:
|
||||
|
||||
- every active task across every tablo owned by the signed-in user
|
||||
- every active etape required to label or group those tasks
|
||||
|
||||
This is intentionally not a single-tablo page. `/tasks` is a personal dashboard over the user’s full owned workload.
|
||||
|
||||
**Shared Page Shell**
|
||||
|
||||
The page shell should render:
|
||||
|
||||
- page title
|
||||
- `Nouvelle tâche` action
|
||||
- view tabs:
|
||||
- `Tableau`
|
||||
- `Liste`
|
||||
- `Roadmap`
|
||||
- roadmap sub-mode toggle when `view=roadmap`
|
||||
- filter controls for:
|
||||
- tablo
|
||||
- assignee
|
||||
- status
|
||||
|
||||
The shell also needs the option data required to render forms and filters:
|
||||
|
||||
- all owner tablos
|
||||
- all relevant assignee options
|
||||
- status options
|
||||
- tablo-scoped etape options for create and edit forms
|
||||
|
||||
**Kanban View Design**
|
||||
|
||||
The kanban view is status-driven and cross-tablo.
|
||||
|
||||
Columns:
|
||||
|
||||
- `À faire`
|
||||
- `En cours`
|
||||
- `Vérification`
|
||||
- `Terminé`
|
||||
|
||||
Each column contains task cards from all owned tablos matching that status.
|
||||
|
||||
Each card should show enough metadata to make a cross-tablo dashboard usable:
|
||||
|
||||
- title
|
||||
- tablo name
|
||||
- étape label, or `Sans étape`
|
||||
- due date if present
|
||||
- assignee if present
|
||||
|
||||
First pass interaction is explicit-action based:
|
||||
|
||||
- no drag and drop
|
||||
- status changes happen through edit actions or other explicit server-backed controls
|
||||
|
||||
**List View Design**
|
||||
|
||||
The list view is grouped by status across all owned tablos.
|
||||
|
||||
Groups:
|
||||
|
||||
- `À faire`
|
||||
- `En cours`
|
||||
- `Vérification`
|
||||
- `Terminé`
|
||||
|
||||
Inside each group, tasks are rendered as flat rows rather than nested by tablo or étape.
|
||||
|
||||
Each row should show:
|
||||
|
||||
- title
|
||||
- tablo
|
||||
- étape or `Sans étape`
|
||||
- assignee if present
|
||||
- due date if present
|
||||
- status actions and edit/delete access as appropriate
|
||||
|
||||
This view is intentionally a personal workload list rather than a single-tablo breakdown.
|
||||
|
||||
**Roadmap View Design**
|
||||
|
||||
The roadmap view is grouped horizontally by étape lanes and bucketed by due date.
|
||||
|
||||
Lane rules:
|
||||
|
||||
- lanes represent `tablo + étape`
|
||||
- the lane identity must include the tablo to avoid collisions between same-named etapes in different tablos
|
||||
- tasks without a parent etape go into a synthetic per-tablo lane:
|
||||
- `Tablo name / Sans étape`
|
||||
|
||||
Bucket rules:
|
||||
|
||||
- tasks are grouped inside each lane by due date
|
||||
- tasks without a due date go into a final `Sans date` bucket
|
||||
|
||||
Roadmap sub-modes:
|
||||
|
||||
- `week`
|
||||
- weekly buckets starting from today, May 10, 2026
|
||||
- `month`
|
||||
- monthly buckets starting from the current month containing May 10, 2026
|
||||
|
||||
Past-due tasks:
|
||||
|
||||
- tasks with due dates before the current starting point should still remain visible
|
||||
- they should be folded into the first visible bucket rather than disappearing into an unrendered past section
|
||||
|
||||
This preserves visibility without introducing a separate "past" axis in the first pass.
|
||||
|
||||
**Filter Behavior**
|
||||
|
||||
Filters must apply consistently across all three views.
|
||||
|
||||
Required filters:
|
||||
|
||||
- `tablo`
|
||||
- `assignee`
|
||||
- `status`
|
||||
|
||||
Behavior:
|
||||
|
||||
- filters are applied once to the shared task set before view-specific grouping
|
||||
- switching between `kanban`, `list`, and `roadmap` preserves active filters where possible
|
||||
- switching roadmap sub-modes preserves active filters
|
||||
|
||||
Invalid filters:
|
||||
|
||||
- unknown tablo IDs are dropped
|
||||
- unknown assignee IDs are dropped
|
||||
- unknown status values are dropped
|
||||
|
||||
The page should always normalize back to a valid state instead of failing.
|
||||
|
||||
**Create And Edit Flow**
|
||||
|
||||
Because `/tasks` is now cross-tablo, create and edit forms must include tablo selection.
|
||||
|
||||
Create form fields:
|
||||
|
||||
- `tablo_id`
|
||||
- `title`
|
||||
- `description`
|
||||
- `status`
|
||||
- `due_date`
|
||||
- `assignee_id`
|
||||
- `parent_task_id`
|
||||
|
||||
Edit form fields:
|
||||
|
||||
- `tablo_id`
|
||||
- `title`
|
||||
- `description`
|
||||
- `status`
|
||||
- `due_date`
|
||||
- `assignee_id`
|
||||
- `parent_task_id`
|
||||
|
||||
Tablo and étape coupling:
|
||||
|
||||
- once a tablo is chosen, selectable etapes must be limited to active etapes from that tablo only
|
||||
- `Sans étape` remains a runtime concept, represented by `parent_task_id = null`
|
||||
|
||||
The chosen tablo and étape combination must be enforced on the server even if the browser submits an invalid combination.
|
||||
|
||||
**Validation Rules**
|
||||
|
||||
The dashboard should reuse the current task invariants and add page-specific validation.
|
||||
|
||||
Required server-side rules:
|
||||
|
||||
- `parent_task_id` must be null or point to an active etape
|
||||
- `parent_task_id` must belong to the selected `tablo_id`
|
||||
- a task cannot point to an etape from another tablo
|
||||
- `assignee_id` must resolve to a valid selectable user
|
||||
- invalid `view` and `roadmap_mode` values fall back to defaults
|
||||
|
||||
When editing a task:
|
||||
|
||||
- if the selected tablo changes, the selected parent etape must be revalidated against the new tablo
|
||||
- if the current parent no longer belongs to the selected tablo, the mutation must be rejected
|
||||
|
||||
Delete behavior remains unchanged functionally:
|
||||
|
||||
- delete the task or etape
|
||||
- re-render the page in the current normalized query state
|
||||
|
||||
**Rendering Strategy**
|
||||
|
||||
The page should keep the current server-driven model:
|
||||
|
||||
- full-page render for normal requests
|
||||
- content fragment render for HTMX requests where appropriate
|
||||
- create and edit forms can continue to use modal or inline fragment responses
|
||||
|
||||
The important change is not the transport mechanism. It is the introduction of explicit page-state modeling and isolated per-view presenters.
|
||||
|
||||
Recommended internal page-state model:
|
||||
|
||||
- selected `view`
|
||||
- selected `roadmap_mode`
|
||||
- selected tablo filters
|
||||
- selected assignee filters
|
||||
- selected status filters
|
||||
|
||||
Recommended shared view-model layers:
|
||||
|
||||
- page shell view model
|
||||
- create/edit form view model
|
||||
- `kanban` view model
|
||||
- `list` view model
|
||||
- `roadmap` view model
|
||||
|
||||
**Testing**
|
||||
|
||||
Testing should cover both state parsing and view grouping behavior.
|
||||
|
||||
Handler tests:
|
||||
|
||||
- default `/tasks` render
|
||||
- `view=kanban`
|
||||
- `view=list`
|
||||
- `view=roadmap`
|
||||
- `roadmap_mode=week`
|
||||
- `roadmap_mode=month`
|
||||
- filter combinations for:
|
||||
- tablo
|
||||
- assignee
|
||||
- status
|
||||
- create flow with `tablo_id`
|
||||
- edit flow with `tablo_id`
|
||||
- invalid cross-tablo parent étape rejection
|
||||
|
||||
View-model tests where practical:
|
||||
|
||||
- kanban grouping by status across multiple tablos
|
||||
- list grouping by status across multiple tablos
|
||||
- roadmap lane identity uses `tablo + étape`
|
||||
- synthetic `Sans étape` lanes are created per tablo
|
||||
- `Sans date` bucket is rendered
|
||||
- overdue tasks are placed in the first visible roadmap bucket
|
||||
|
||||
**Implementation Slices**
|
||||
|
||||
1. Extend `/tasks` query parsing and normalized page-state handling.
|
||||
2. Build shared filter-option loading for tablos, assignees, and statuses.
|
||||
3. Introduce a shared owner-level filtered task dataset.
|
||||
4. Split rendering into `kanban`, `list`, and `roadmap` view-model builders.
|
||||
5. Replace the current simple `/tasks` view with a page shell and mode-specific renderers.
|
||||
6. Extend create and edit forms with `tablo_id` and tablo-scoped etape options.
|
||||
7. Add tests for filtering, grouping, roadmap bucketing, and invalid parent validation.
|
||||
|
||||
**Recommendation**
|
||||
|
||||
Use one `/tasks` route with shared filtering and separate presenter functions for each mode.
|
||||
|
||||
This approach fits the current Go backend architecture best because it:
|
||||
|
||||
- keeps the URL as the source of truth
|
||||
- avoids duplicated repository and filter logic
|
||||
- keeps each view’s grouping logic isolated
|
||||
- preserves server-rendered behavior without introducing a browser-side state machine
|
||||
Loading…
Reference in a new issue