MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-980

2.9.3 Archived work items view UI + per-item Restore (unarchive)

Done
Description

Estimate: 55m · Type: code · Depends on: 2.9.1, 2.9.2

Build the archived work items view + per-item Restore, at the placement 2.9.1 decides, reading 2.9.2.

  • Render the flat, paginated archived list per the 2.9.1 design (rows: key, type glyph, title, status, archived-by/at; reuse IssueListPager, the issues-row vocabulary, and the empty/loading states).
  • Restore per row → call the EXISTING client helper unarchiveWorkItem in components/issues/actions/workItemActionsClient.ts (→ DELETE /api/work-items/[id]/archiveworkItemsService.unarchiveWorkItem). Do not add a new write path — the service/route/MCP already exist.
  • Page state after restore (CLAUDE.md § page-state): the restored row leaves the archived list (optimistic remove or refetch the page, seq-guarded) AND active views must reflect it — if the archived view is a client island, bump the existing CreateIssueProvider.issuesChangedAt-style tick the board/issues watch; otherwise router.refresh() the server surfaces. Wait on the unarchive 200 before asserting persisted state.
  • Gating: Restore visible only to editors (useProjectAccess().canEdit, matching the shipped assertCanEdit); view per the 2.9.1 decision.
  • Copy in the existing namespace (en + zh).

Acceptance criteria

  • The archived view lists archived items (paginated) at the 2.9.1 placement; clicking Restore removes the row and returns the item to active views; activity shows "restored".
  • Restore is hidden/disabled for non-editors; the view obeys the 2.9.1 access decision.
  • No new write endpoint — reuses unarchiveWorkItem. Component test covers render + restore (page-state) + gating; per-file coverage gate holds.

Context refs

  • 2.9.1 design (design/work-items/ archived asset) · 2.9.2 read path (listArchivedWorkItems)
  • components/issues/actions/workItemActionsClient.ts (unarchiveWorkItem); app/api/work-items/[id]/archive/route.ts (DELETE = unarchive)
  • app/(authed)/issues/_components/IssueListPager.tsx, WorkItemRowActions.tsx (row vocabulary + notifyIssuesChanged tick pattern)
  • motir-core/CLAUDE.md § "Page state after a mutation" + § "E2E waits on the authoritative signal"