Skip to content

fix: add unarchive support for archived tasks#1894

Open
ahmed-hassan19 wants to merge 3 commits intoAndyMik90:developfrom
ahmed-hassan19:fix/unarchive-support-archived-tasks
Open

fix: add unarchive support for archived tasks#1894
ahmed-hassan19 wants to merge 3 commits intoAndyMik90:developfrom
ahmed-hassan19:fix/unarchive-support-archived-tasks

Conversation

@ahmed-hassan19
Copy link

@ahmed-hassan19 ahmed-hassan19 commented Feb 23, 2026

Base Branch

  • This PR targets the develop branch (required for all feature/fix PRs)

Description

Adds unarchive support for archived tasks: an "Unarchive" button on archived task cards, and auto-unarchive when dragging archived tasks from Done to another column. Includes error handling with toast notifications and i18n keys for English and French.

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 📚 Documentation
  • ♻️ Refactor
  • 🧪 Test

Area

  • Frontend
  • Backend
  • Fullstack

AI Disclosure

  • This PR includes AI-generated code (Claude, Codex, Copilot, etc.)

Tool(s) used: Claude Code (Claude Opus 4.6)
Testing level:

  • Untested -- AI output not yet verified

  • Lightly tested -- ran the app / spot-checked key paths

  • Fully tested -- all tests pass, manually verified behavior

  • I understand what this PR does and how the underlying code works

Checklist

  • I've synced with develop branch
  • I've tested my changes locally
  • I've followed the code principles (SOLID, DRY, KISS)
  • My PR is small and focused (< 400 lines ideally)

Platform Testing Checklist

  • Windows tested (either on Windows or via CI)
  • macOS tested (either on macOS or via CI)
  • Linux tested (CI covers this)
  • Used centralized platform/ module instead of direct process.platform checks
  • No hardcoded paths (used findExecutable() or platform abstractions)

If you only have access to one OS: CI now tests on all platforms. Ensure all checks pass before submitting.

CI/Testing Requirements

  • All CI checks pass on all platforms (Windows, macOS, Linux)
  • All existing tests pass
  • New features include test coverage
  • Bug fixes include regression tests

Test Plan

  • Toggle "Show archived" in Done column, verify unarchive button appears on archived tasks
  • Click unarchive button — task should lose archived badge and show toast on failure
  • Drag an archived task from Done to Backlog — task should auto-unarchive and show toast on failure
  • Drag a non-archived task between columns — no change in behavior
  • Typecheck, lint, and unit tests pass

Feature Toggle

  • N/A - Feature is complete and ready for all users

Breaking Changes

Breaking: No

🤖 Generated with Claude Code

@CLAassistant
Copy link

CLAassistant commented Feb 23, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

Adds unarchive support: exported unarchiveTasks in task-store, unarchive UI and handlers in TaskCard, automatic unarchive after successful status changes in KanbanBoard, and English/French i18n keys for the unarchive action.

Changes

Cohort / File(s) Summary
Components
apps/frontend/src/renderer/components/TaskCard.tsx, apps/frontend/src/renderer/components/KanbanBoard.tsx
TaskCard: add Unarchive UI (ArchiveRestore icon) and handleUnarchive calling unarchiveTasks; show unarchive controls when metadata.archivedAt is truthy. KanbanBoard: call unarchiveTasks(projectId, [taskId]) after successful status change when task is archived; show destructive toast on failure.
Store
apps/frontend/src/renderer/stores/task-store.ts
Add exported unarchiveTasks(projectId, taskIds) that calls window.electronAPI.unarchiveTasks, reloads tasks via loadTasks(projectId) on success, and returns structured success/error responses.
I18n
apps/frontend/src/shared/i18n/locales/en/tasks.json, apps/frontend/src/shared/i18n/locales/fr/tasks.json
Add actions.unarchive and tooltips.unarchiveTask translations in English and French.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant TaskCard
    participant TaskStore
    participant IPC as electronAPI
    participant Backend

    User->>TaskCard: Click "Unarchive"
    TaskCard->>TaskCard: handleUnarchive()
    TaskCard->>TaskStore: unarchiveTasks(projectId, [taskId])
    TaskStore->>IPC: window.electronAPI.unarchiveTasks(...)
    IPC->>Backend: RPC unarchiveTasks
    Backend-->>IPC: success
    IPC-->>TaskStore: response
    TaskStore->>TaskStore: loadTasks(projectId)
    TaskStore-->>TaskCard: tasks reloaded / updated
    TaskCard->>User: UI reflects unarchived task
Loading
sequenceDiagram
    participant User
    participant KanbanBoard
    participant TaskStore
    participant IPC as electronAPI
    participant Backend

    User->>KanbanBoard: Change task status (drag/drop)
    KanbanBoard->>TaskStore: apply status change
    TaskStore-->>KanbanBoard: status update success
    note over KanbanBoard,TaskStore: if task.metadata.archivedAt && projectId
    KanbanBoard->>TaskStore: unarchiveTasks(projectId, [taskId])
    TaskStore->>IPC: window.electronAPI.unarchiveTasks(...)
    IPC->>Backend: RPC unarchiveTasks
    Backend-->>IPC: success
    IPC-->>TaskStore: response
    TaskStore->>TaskStore: loadTasks(projectId)
    TaskStore-->>KanbanBoard: refreshed
    KanbanBoard->>User: UI updated
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

bug, area/frontend, size/M

Suggested reviewers

  • AndyMik90

Poem

🐰 I nudged a task from its dusty bed,
Patted its back, shook cobwebs from its head.
A tiny hop, a click — it’s free,
Back on the board where it’s meant to be.
Hooray! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding unarchive functionality for archived tasks across the UI and KanbanBoard components.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ahmed-hassan19, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances task management by providing two intuitive ways to unarchive tasks. Users can now explicitly unarchive tasks via a dedicated button on archived task cards or implicitly by dragging an archived task from the 'Done' column back into an active workflow state. These changes improve the flexibility and user experience for managing task lifecycles within the application.

Highlights

  • Unarchive Button: Introduced an 'Unarchive' button on archived task cards, allowing users to directly restore tasks from an archived state.
  • Auto-Unarchive on Drag: Implemented automatic unarchiving of tasks when they are dragged from the 'Done' column to any other active column (backlog, queue, in_progress), signaling the user's intent to reactivate them.
Changelog
  • apps/frontend/src/renderer/components/KanbanBoard.tsx
    • Added logic to automatically unarchive a task if it was previously archived and successfully moved to a new column.
  • apps/frontend/src/renderer/components/TaskCard.tsx
    • Imported the ArchiveRestore icon for the unarchive action.
    • Imported the unarchiveTasks function from the task store.
    • Implemented handleUnarchive function to call the unarchiveTasks store action.
    • Conditionally rendered an 'Unarchive' button with the ArchiveRestore icon on archived task cards.
    • Added a larger 'Unarchive' button with text for archived tasks in the 'Done' column.
  • apps/frontend/src/renderer/stores/task-store.ts
    • Added a new asynchronous function unarchiveTasks to remove the archivedAt timestamp from task metadata and reload tasks.
  • apps/frontend/src/shared/i18n/locales/en/tasks.json
    • Added 'unarchive' action text and 'unarchiveTask' tooltip text.
  • apps/frontend/src/shared/i18n/locales/fr/tasks.json
    • Added 'Désarchiver' action text and 'Désarchiver la tâche' tooltip text.
Activity
  • The pull request was created with AI assistance using Claude Code.
  • Manual verification of the UI flow was performed as part of the testing.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 Thanks for your first PR!

A maintainer will review it soon. Please make sure:

  • Your branch is synced with develop
  • CI checks pass
  • You've followed our contribution guide

Welcome to the Auto Claude community!

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces functionality to unarchive tasks, both through a manual button and automatically when a task is moved from the 'Done' column. The implementation is sound, covering both UI and state management. My feedback focuses on improving performance by optimizing state updates to avoid full data reloads, and enhancing robustness by adding user-facing error handling for a more resilient user experience.

@sentry
Copy link

sentry bot commented Feb 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/frontend/src/renderer/components/KanbanBoard.tsx (1)

32-32: ⚠️ Potential issue | 🔴 Critical

unarchiveTasks is called on line 992 but missing from the import on line 32 — TypeScript compile error.

unarchiveTasks is not present in the task-store import on line 32. This causes a compile-time error (unarchiveTasks is not defined) and breaks the build.

🐛 Fix: add `unarchiveTasks` to the import
-import { persistTaskStatus, forceCompleteTask, archiveTasks, deleteTasks, useTaskStore, isQueueAtCapacity, DEFAULT_MAX_PARALLEL_TASKS } from '../stores/task-store';
+import { persistTaskStatus, forceCompleteTask, archiveTasks, unarchiveTasks, deleteTasks, useTaskStore, isQueueAtCapacity, DEFAULT_MAX_PARALLEL_TASKS } from '../stores/task-store';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/src/renderer/components/KanbanBoard.tsx` at line 32, The build
fails because unarchiveTasks is used in KanbanBoard.tsx but not imported; update
the existing import statement that currently lists persistTaskStatus,
forceCompleteTask, archiveTasks, deleteTasks, useTaskStore, isQueueAtCapacity,
DEFAULT_MAX_PARALLEL_TASKS to also include unarchiveTasks from
'../stores/task-store'; if unarchiveTasks is not exported from task-store,
export it there so the import resolves.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/frontend/src/renderer/components/KanbanBoard.tsx`:
- Around line 989-993: The call to unarchiveTasks is awaited but its
non-exception failure path is ignored, leaving the task moved but still
archived; update the block where unarchiveTasks(projectId, [taskId]) is called
(inside the auto-unarchive branch that checks result.success &&
task?.metadata?.archivedAt && projectId) to capture the returned value, check if
returned.success is false, and log an error (including projectId, taskId and the
returned response) — you can mirror handleArchiveAll’s behavior (console.error)
and optionally surface a user-visible notification if unarchive fails.

---

Outside diff comments:
In `@apps/frontend/src/renderer/components/KanbanBoard.tsx`:
- Line 32: The build fails because unarchiveTasks is used in KanbanBoard.tsx but
not imported; update the existing import statement that currently lists
persistTaskStatus, forceCompleteTask, archiveTasks, deleteTasks, useTaskStore,
isQueueAtCapacity, DEFAULT_MAX_PARALLEL_TASKS to also include unarchiveTasks
from '../stores/task-store'; if unarchiveTasks is not exported from task-store,
export it there so the import resolves.

ahmed-hassan19 and others added 2 commits February 23, 2026 04:06
Add an "Unarchive" button on archived task cards so users can restore
them directly. Includes the unarchiveTasks store action, ArchiveRestore
icon, and i18n keys for both English and French.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
When an archived task is dragged from Done to another column (backlog,
queue, in_progress), automatically unarchive it — moving an archived
task is a clear signal the user wants it active again.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@ahmed-hassan19 ahmed-hassan19 force-pushed the fix/unarchive-support-archived-tasks branch from ecacbc3 to 1378198 Compare February 23, 2026 02:06
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/frontend/src/renderer/components/KanbanBoard.tsx`:
- Around line 989-993: The call to unarchiveTasks discards its result so
non-exceptional failures leave task.archivedAt set while the UI shows it active;
update the block where you call unarchiveTasks (the code that checks
result.success and task?.metadata?.archivedAt with projectId and taskId) to
capture the returned value, verify its success flag, and on failure log an error
(e.g., console.error with context: taskId/projectId and the returned result) and
optionally revert the UI change or surface an error to the user to avoid
inconsistent state.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/frontend/src/renderer/components/KanbanBoard.tsx`:
- Around line 989-993: The auto-unarchive call to unarchiveTasks in
KanbanBoard.tsx is unchecked and can silently fail; update the block that runs
when result.success && task?.metadata?.archivedAt && projectId to capture the
return value of unarchiveTasks(taskId array) (e.g., const unarchiveResult =
await unarchiveTasks(projectId, [taskId])), check unarchiveResult.success, and
on failure mirror handleArchiveAll’s behavior by logging the error and/or
surfacing a user-facing error (toast or similar) and, if appropriate, revert the
UI change so the archived badge remains consistent.

Address PR review feedback: check unarchiveTasks() return value in
KanbanBoard and show a toast on failure, and replace console.error
with a toast in TaskCard since console output is invisible in bundled
Electron apps.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/frontend/src/renderer/components/KanbanBoard.tsx (1)

260-266: ⚠️ Potential issue | 🟡 Minor

Inconsistency: handleArchive still uses console.error instead of a toast.

The new handleUnarchive (in TaskCard, line 268-278) and the auto-unarchive block (line 993-999) both surface failures via toasts, but handleArchive (line 263-265) logs to console.error. In bundled Electron apps, console.error is invisible to users. This was also noted in the commit message as the intended fix direction.

♻️ Suggested fix: surface archive failure via toast
   const handleArchive = async (e: React.MouseEvent) => {
     e.stopPropagation();
     const result = await archiveTasks(task.projectId, [task.id]);
     if (!result.success) {
-      console.error('[TaskCard] Failed to archive task:', task.id, result.error);
+      toast({
+        title: t('common:errors.operationFailed'),
+        description: result.error,
+        variant: 'destructive',
+      });
     }
   };

Note: this pre-existing console.error is in the handleArchive defined at lines 260-266 of TaskCard.tsx, not KanbanBoard.tsx. I'm flagging it here for visibility since it's the same pattern the PR is fixing elsewhere. As per coding guidelines: "Never use console.log for debugging production issues in the Electron app. Use Sentry for error tracking and diagnostics in production."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/src/renderer/components/KanbanBoard.tsx` around lines 260 -
266, The handleArchive function in TaskCard.tsx currently calls console.error on
failure; change it to surface errors via the same toast used by handleUnarchive
(e.g., toast.error with a user-friendly message) and also report the error to
Sentry (e.g., Sentry.captureException) or the app’s error-reporting utility,
mirroring the pattern in handleUnarchive and the auto-unarchive block so
failures are visible to users and tracked in production.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/frontend/src/renderer/components/TaskCard.tsx`:
- Around line 268-278: The toast on failure in handleUnarchive currently uses
the action label t('tasks:actions.unarchive') as the title; change it to a
generic error heading (use t('common:errors.operationFailed')) so the toast
reads like an error (update the toast call inside handleUnarchive that follows
the unarchiveTasks call and references toast, t, and result to use the common
error key instead of the action label).

---

Outside diff comments:
In `@apps/frontend/src/renderer/components/KanbanBoard.tsx`:
- Around line 260-266: The handleArchive function in TaskCard.tsx currently
calls console.error on failure; change it to surface errors via the same toast
used by handleUnarchive (e.g., toast.error with a user-friendly message) and
also report the error to Sentry (e.g., Sentry.captureException) or the app’s
error-reporting utility, mirroring the pattern in handleUnarchive and the
auto-unarchive block so failures are visible to users and tracked in production.

---

Duplicate comments:
In `@apps/frontend/src/renderer/components/KanbanBoard.tsx`:
- Around line 989-1000: The auto-unarchive code correctly checks result.success
and shows a destructive toast on failure; no code changes needed. Ensure the
block using result.success, task?.metadata?.archivedAt, projectId,
unarchiveTasks(projectId, [taskId]) and toast(...) remains as-is and that
unarchiveResult.error is a user-friendly string; if not, convert or localize the
error before passing it to toast.

Comment on lines +268 to +278
const handleUnarchive = async (e: React.MouseEvent) => {
e.stopPropagation();
const result = await unarchiveTasks(task.projectId, [task.id]);
if (!result.success) {
toast({
title: t('tasks:actions.unarchive'),
description: result.error,
variant: 'destructive',
});
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Toast title on failure uses the action label instead of an error message.

handleUnarchive uses t('tasks:actions.unarchive') (which resolves to "Unarchive") as the toast title on failure. This reads oddly as a toast heading — the user sees "Unarchive" with an error description below. For consistency with the KanbanBoard auto-unarchive toast (line 995), consider using t('common:errors.operationFailed').

♻️ Suggested fix
     if (!result.success) {
       toast({
-        title: t('tasks:actions.unarchive'),
+        title: t('common:errors.operationFailed'),
         description: result.error,
         variant: 'destructive',
       });
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/frontend/src/renderer/components/TaskCard.tsx` around lines 268 - 278,
The toast on failure in handleUnarchive currently uses the action label
t('tasks:actions.unarchive') as the title; change it to a generic error heading
(use t('common:errors.operationFailed')) so the toast reads like an error
(update the toast call inside handleUnarchive that follows the unarchiveTasks
call and references toast, t, and result to use the common error key instead of
the action label).

@AndyMik90 AndyMik90 self-assigned this Feb 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants