[feature] Kanban: add task status update (column move) via RPC #27

Closed
opened 2026-05-05 08:06:40 +00:00 by casper-stevens · 4 comments
Member

Context

Identified in home#211: users get an RPC error ["Method not found"] when trying to move tasks between kanban columns. Currently the kanban is read-only.

Current state

projects_kanban handler (handlers/mod.rs:4829) loads all tasks and the template (ProjectsKanbanTemplate) renders them grouped by status. There is no endpoint to update a task's status — no PATCH/POST for column moves.

The kanban card renders a link to task detail but no client-side interaction for drag-and-drop or button-based column moves.

Work required

  • Add a PATCH /c/:context/tasks/:id/status endpoint that accepts { "status": "in_progress" } and saves the updated task
  • Wire this up in the kanban template: either drag-and-drop (via JS dragstart/drop events) or per-card "move" buttons with fetch()
  • The RPC call should update the task in the OSIS store and return the new status
  • Consider filtering the kanban by project (currently shows all tasks across all projects mixed together)

Notes

  • Keep it simple first: button-based status cycling is acceptable before drag-and-drop
  • Filtering by project (a dropdown at the top of the kanban) would pair well with this
## Context Identified in home#211: users get an RPC error `["Method not found"]` when trying to move tasks between kanban columns. Currently the kanban is read-only. ## Current state `projects_kanban` handler (`handlers/mod.rs:4829`) loads all tasks and the template (`ProjectsKanbanTemplate`) renders them grouped by status. There is no endpoint to update a task's status — no PATCH/POST for column moves. The kanban card renders a link to task detail but no client-side interaction for drag-and-drop or button-based column moves. ## Work required - Add a `PATCH /c/:context/tasks/:id/status` endpoint that accepts `{ "status": "in_progress" }` and saves the updated task - Wire this up in the kanban template: either drag-and-drop (via JS `dragstart`/`drop` events) or per-card "move" buttons with `fetch()` - The RPC call should update the task in the OSIS store and return the new status - Consider filtering the kanban by project (currently shows all tasks across all projects mixed together) ## Notes - Keep it simple first: button-based status cycling is acceptable before drag-and-drop - Filtering by project (a dropdown at the top of the kanban) would pair well with this
Author
Member

Implementation Spec for Issue #27

Objective

Make the Kanban board interactive by adding a POST /c/:context/tasks/:id/status endpoint that accepts a JSON body { "status": "<status_string>" }, updates the task in the OSIS store, and returns a JSON result. Wire this endpoint into the Kanban card HTML so each card gains "move forward" and "move back" buttons that call fetch() and refresh the page on success.

Requirements

  • Add a new HTTP handler task_update_status in handlers/mod.rs that accepts POST /c/:context/tasks/:id/status, deserializes { "status": "..." }, loads the existing task, updates only the status, saves it via store.save_task, and returns JSON
  • Register the new route in server.rs
  • Modify ProjectsKanbanTemplate to add per-card left/right arrow buttons that call fetch() on the new endpoint and reload on success
  • Add a project filter dropdown above the board; the projects_kanban handler reads an optional ?project=<sid> query param and filters tasks before passing to the template

Files to Modify

File Change
crates/hero_biz_ui/src/web/handlers/mod.rs Add TaskStatusUpdateRequest struct and task_update_status handler
crates/hero_biz_ui/src/web/server.rs Register new POST .../tasks/:id/status route
crates/hero_biz_ui/src/web/templates/mod.rs Update ProjectsKanbanTemplate, add project filter dropdown, add move buttons

Implementation Plan

Step 1 — Add handler (handlers/mod.rs)

  • Add TaskStatusUpdateRequest { status: String } struct
  • Add task_update_status async handler: loads task, mutates status, saves, returns JSON
  • Dependencies: none

Step 2 — Register route (server.rs)

  • Add .route("/c/:context/tasks/:id/status", post(handlers::task_update_status))
  • Dependencies: Step 1

Step 3 — Update kanban handler with project filter (handlers/mod.rs)

  • Add Query(params) extractor to projects_kanban
  • Filter tasks by ?project= param when present
  • Pass selected_project field to template
  • Dependencies: Step 4 (template struct field added)

Step 4 — Update ProjectsKanbanTemplate (templates/mod.rs)

  • Add selected_project: String field to struct
  • Add project filter dropdown (form with select, auto-submits on change)
  • Extend render_task_card closure with prev/next arrow buttons
  • Add moveTask() JS function using fetch() + window.location.reload()
  • Dependencies: Steps 1 and 2

Acceptance Criteria

  • POST /c/:context/tasks/:id/status with {"status":"in_progress"} returns 200 {"success":true}
  • Invalid status returns HTTP 400; non-existent task returns HTTP 404
  • Kanban cards have left/right arrow buttons; clicking moves the card and the page reloads with the card in the new column
  • Leftmost column cards have no left arrow; rightmost column cards have no right arrow
  • Project filter dropdown appears at the top of the board; selecting a project re-renders with only that project's tasks
  • Filter selection is preserved across page reloads
  • Application compiles without errors

Notes

  • Using POST (not PATCH) for consistency with existing codebase routing patterns
  • The five-column order used for move buttons: backlog → todo → in_progress → review → done
  • load_task_for_space(&id, &context) fetches by SID, consistent with existing task_edit/task_update handlers
  • Template file is large (~5560+ lines); make targeted edits to the struct definition and render() method only
## Implementation Spec for Issue #27 ### Objective Make the Kanban board interactive by adding a `POST /c/:context/tasks/:id/status` endpoint that accepts a JSON body `{ "status": "<status_string>" }`, updates the task in the OSIS store, and returns a JSON result. Wire this endpoint into the Kanban card HTML so each card gains "move forward" and "move back" buttons that call `fetch()` and refresh the page on success. ### Requirements - Add a new HTTP handler `task_update_status` in `handlers/mod.rs` that accepts `POST /c/:context/tasks/:id/status`, deserializes `{ "status": "..." }`, loads the existing task, updates only the status, saves it via `store.save_task`, and returns JSON - Register the new route in `server.rs` - Modify `ProjectsKanbanTemplate` to add per-card left/right arrow buttons that call `fetch()` on the new endpoint and reload on success - Add a project filter dropdown above the board; the `projects_kanban` handler reads an optional `?project=<sid>` query param and filters tasks before passing to the template ### Files to Modify | File | Change | |---|---| | `crates/hero_biz_ui/src/web/handlers/mod.rs` | Add `TaskStatusUpdateRequest` struct and `task_update_status` handler | | `crates/hero_biz_ui/src/web/server.rs` | Register new `POST .../tasks/:id/status` route | | `crates/hero_biz_ui/src/web/templates/mod.rs` | Update `ProjectsKanbanTemplate`, add project filter dropdown, add move buttons | ### Implementation Plan #### Step 1 — Add handler (`handlers/mod.rs`) - Add `TaskStatusUpdateRequest { status: String }` struct - Add `task_update_status` async handler: loads task, mutates status, saves, returns JSON - Dependencies: none #### Step 2 — Register route (`server.rs`) - Add `.route("/c/:context/tasks/:id/status", post(handlers::task_update_status))` - Dependencies: Step 1 #### Step 3 — Update kanban handler with project filter (`handlers/mod.rs`) - Add `Query(params)` extractor to `projects_kanban` - Filter tasks by `?project=` param when present - Pass `selected_project` field to template - Dependencies: Step 4 (template struct field added) #### Step 4 — Update `ProjectsKanbanTemplate` (`templates/mod.rs`) - Add `selected_project: String` field to struct - Add project filter dropdown (form with select, auto-submits on change) - Extend `render_task_card` closure with prev/next arrow buttons - Add `moveTask()` JS function using `fetch()` + `window.location.reload()` - Dependencies: Steps 1 and 2 ### Acceptance Criteria - [ ] `POST /c/:context/tasks/:id/status` with `{"status":"in_progress"}` returns 200 `{"success":true}` - [ ] Invalid status returns HTTP 400; non-existent task returns HTTP 404 - [ ] Kanban cards have left/right arrow buttons; clicking moves the card and the page reloads with the card in the new column - [ ] Leftmost column cards have no left arrow; rightmost column cards have no right arrow - [ ] Project filter dropdown appears at the top of the board; selecting a project re-renders with only that project's tasks - [ ] Filter selection is preserved across page reloads - [ ] Application compiles without errors ### Notes - Using `POST` (not `PATCH`) for consistency with existing codebase routing patterns - The five-column order used for move buttons: backlog → todo → in_progress → review → done - `load_task_for_space(&id, &context)` fetches by SID, consistent with existing `task_edit`/`task_update` handlers - Template file is large (~5560+ lines); make targeted edits to the struct definition and `render()` method only
Author
Member

Build Results

Status: Success

All crates compiled without errors on branch development_casper.

Compiling hero_biz_ui v0.5.0
Compiling hero_biz_app v0.1.0
Compiling hero_biz v0.5.0
Finished `dev` profile [unoptimized + debuginfo] target(s) in 59.32s
## Build Results Status: Success All crates compiled without errors on branch `development_casper`. ``` Compiling hero_biz_ui v0.5.0 Compiling hero_biz_app v0.1.0 Compiling hero_biz v0.5.0 Finished `dev` profile [unoptimized + debuginfo] target(s) in 59.32s ```
Author
Member

Implementation Summary

Changes Made

crates/hero_biz_ui/src/web/handlers/mod.rs

  • Added TaskStatusUpdateRequest { status: String } struct
  • Added task_update_status handler: loads task by SID, maps status string to TaskStatus enum, saves via store.save_task, returns JSON {success, status} — HTTP 400 for unknown status, 404 for missing task, 500 for save failure
  • Added KanbanQuery { project: Option<String> } struct for the kanban filter
  • Updated projects_kanban handler to accept ?project=<sid> query param and filter tasks before passing to the template; passes selected_project to the template

crates/hero_biz_ui/src/web/server.rs

  • Registered POST /c/:context/tasks/:id/status route mapped to task_update_status

crates/hero_biz_ui/src/web/templates/mod.rs

  • Added selected_project: String field to ProjectsKanbanTemplate
  • Added project filter <form> with auto-submitting <select> dropdown above the board; pre-selects the active filter
  • Made each task card draggable: draggable="true" + ondragstart handler
  • Added ondragover/ondrop handlers to each kanban column, using the column's status string
  • Added dragStart() and drop() JavaScript functions; drop() POSTs to the status endpoint via fetch() and reloads the page on success
  • Added CSS cursor: grab on cards and a drag-over highlight on columns

Build Results

All crates compiled successfully with no errors.

## Implementation Summary ### Changes Made **`crates/hero_biz_ui/src/web/handlers/mod.rs`** - Added `TaskStatusUpdateRequest { status: String }` struct - Added `task_update_status` handler: loads task by SID, maps status string to `TaskStatus` enum, saves via `store.save_task`, returns JSON `{success, status}` — HTTP 400 for unknown status, 404 for missing task, 500 for save failure - Added `KanbanQuery { project: Option<String> }` struct for the kanban filter - Updated `projects_kanban` handler to accept `?project=<sid>` query param and filter tasks before passing to the template; passes `selected_project` to the template **`crates/hero_biz_ui/src/web/server.rs`** - Registered `POST /c/:context/tasks/:id/status` route mapped to `task_update_status` **`crates/hero_biz_ui/src/web/templates/mod.rs`** - Added `selected_project: String` field to `ProjectsKanbanTemplate` - Added project filter `<form>` with auto-submitting `<select>` dropdown above the board; pre-selects the active filter - Made each task card draggable: `draggable="true"` + `ondragstart` handler - Added `ondragover`/`ondrop` handlers to each kanban column, using the column's status string - Added `dragStart()` and `drop()` JavaScript functions; `drop()` POSTs to the status endpoint via `fetch()` and reloads the page on success - Added CSS `cursor: grab` on cards and a drag-over highlight on columns ### Build Results All crates compiled successfully with no errors.
Author
Member

Implemented in commit 9e796a9 on development_casper.

Implemented in commit 9e796a9 on development_casper.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_biz#27
No description provided.