Skip to content

feat: frontend archive UI#4229

Merged
bekossy merged 32 commits intorelease/v0.98.0from
feat/frontend-archive-ui
May 4, 2026
Merged

feat: frontend archive UI#4229
bekossy merged 32 commits intorelease/v0.98.0from
feat/frontend-archive-ui

Conversation

@ashrafchowdury
Copy link
Copy Markdown
Contributor

@ashrafchowdury ashrafchowdury commented Apr 27, 2026

What's new

Implemented an archived view for workflows, to restore the archived workflows.

Implemented archived UI for:

  • Apps
  • Evaluators
  • Testset

Chnages

  • Introduced a ArchivePageLayout component for UI consistency
  • Added the archive and unarchive actions to molecule level
  • Added a parameter include_archive on the existing queryWorkflow for fetching the archive data
  • Updated on the workflow view components to add the flag archive to render some view conditionally
  • Renamed the word Delete -> Archive for better understanding about the action

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment May 4, 2026 10:24am

Request Review

@ashrafchowdury ashrafchowdury changed the title Feat/frontend archive UI feat: frontend archive UI Apr 27, 2026
…tor cache supporting archived workflows and persistent metadata entries.
…and consolidate paginated store logic with shared helpers
…paginated store with shared helpers and factory functions
@ashrafchowdury ashrafchowdury marked this pull request as ready for review April 28, 2026 07:16
@dosubot dosubot Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Apr 28, 2026
Previously the archived apps page briefly displayed the "no archived
apps" empty state before swapping to the loaded table. Render the table
(with skeleton rows) while the archived count query is in flight so the
empty state only appears once we know the list is actually empty.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 2, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fbcd4107-e794-491b-8dba-62d406f637f7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds frontend archived-entity views for Apps, Evaluators, and Testsets: a shared ArchivedEntityLayout, mode-aware tables/columns, archived paginated stores that fetch with includeArchived and filter/sort by deleted_at client-side, detail fetchers updated to accept includeArchived, archive/unarchive lifecycle wiring on molecules, route re-exports, and updated UI copy/tests.


Changes

Archived Entities Feature Implementation

Layer / File(s) Summary
Design & Architecture
docs/design/archive-workflows/archived-entities-view-design.md
Design spec for a frontend archived-list UI reusing live-table primitives; defines ArchivedEntityLayout, sibling paginated stores, deletedAt/deletedById row fields, column factory mode support, CSV/export behavior, testing and rollout notes.
Shared Layout Component
web/oss/src/components/ArchivedEntityLayout/index.tsx, web/oss/src/components/ArchivedEntityLayout/types.ts
Adds ArchivedEntityLayout component and props type for back navigation, title/subtitle, conditional empty-state rendering.
Archived Page Entrypoints (thin wrappers)
web/oss/src/components/pages/app-management/ArchivedAppsPage.tsx, web/oss/src/components/Evaluators/ArchivedEvaluatorsPage.tsx, web/oss/src/components/pages/testset/ArchivedTestsetsPage.tsx, web/ee/src/pages/.../archived/index.tsx, web/oss/src/pages/w/.../archived/index.tsx
New archived page components and EE/OSS route re-exports that render ArchivedEntityLayout containing existing sections/tables with mode="archived".
Shared Utils & Paginated Store helpers
web/oss/src/state/entities/shared/utils.ts, web/oss/src/state/entities/shared/index.ts, web/oss/src/state/entities/shared/createPaginatedEntityStore.ts
Adds emptyFetchResult, getCursorOffset, createDateDescComparator; changes skeleton→API merge behavior to use customMerge for transformRow.
Backend API helpers
web/oss/src/services/testsets/api/index.ts, web/packages/agenta-entities/src/testset/api/mutations.ts, web/packages/agenta-entities/src/testset/api/index.ts
Adds unarchiveTestset API helper and re-exports; testset mutation exports updated.
Paginated Stores / Data Layer
web/oss/src/components/Evaluators/store/evaluatorsPaginatedStore.ts, web/oss/src/state/entities/testset/paginatedStore.ts, web/oss/src/components/pages/app-management/store/appWorkflowStore.ts
Adds archived paginated stores and meta atoms, extends row types with soft-delete fields (deletedAt/deletedById), client-side filtering/sorting by deleted_at, shared row transformers, and exposes get*TableState(mode) and invalidate helpers.
Table State / Fetchers / Router state
web/oss/src/state/app/atoms/fetcher.ts, web/oss/src/state/app/selectors/app.ts, web/oss/src/state/appState/parse.ts
Adds currentAppQueryAtom (fetches workflow with includeArchived when needed), currentAppAtom now derives from that query, and reserves archived as a non-app route segment to avoid collisions.
Table Components & Column Factories
web/oss/src/components/Evaluators/Table/EvaluatorsTable.tsx, web/oss/src/components/Evaluators/Table/assets/evaluatorColumns.tsx, web/oss/src/components/TestsetsTable/TestsetsTable.tsx, web/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsx, web/oss/src/components/pages/app-management/components/appWorkflowColumns.tsx
Tables and column factories accept `mode?: "active"
Registry / Section Components
web/oss/src/components/Evaluators/index.tsx, web/oss/src/components/pages/app-management/components/ApplicationManagementSection.tsx, web/oss/src/components/pages/app-management/index.tsx
Registry and section components accept mode, hide creation UI in archived mode, add restore handlers that call molecule lifecycle unarchive and invalidate management queries, and adjust header/primary action behavior.
Lifecycle Molecules & Cache Invalidation
web/packages/agenta-entities/src/workflow/state/molecule.ts, web/packages/agenta-entities/src/testset/state/testsetMolecule.ts, web/packages/agenta-entities/src/workflow/state/evaluatorUtils.ts
Adds workflowMolecule.lifecycle and testsetMolecule.lifecycle with archive/unarchive methods that call API endpoints and invalidate relevant caches; evaluator cache invalidation extended to paginated query keys.
Filters & Header Components (mode-aware)
web/oss/src/components/TestsetsTable/components/TestsetsFiltersContent.tsx, .../TestsetsFiltersSummary.tsx, .../TestsetsHeaderFilters.tsx
Filter atoms and UI now derived from getTestsetTableState(tableMode) so active and archived views maintain isolated filter/search/date state.
Detail / Revision Fetch API changes
web/oss/src/components/TestcasesTableNew/hooks/api.ts, web/oss/src/state/entities/testset/store.ts
Revision/testset fetchers accept optional options?.includeArchived and forward include_archived to backend requests; RevisionListParams extended accordingly.
UI Copy / Actions / Modals
web/oss/src/components/Evaluators/assets/cells/TableDropdownMenu/index.tsx, web/oss/src/components/Evaluators/components/DeleteEvaluatorsModal/*, web/oss/src/components/pages/testset/modals/DeleteTestset.tsx, web/oss/src/components/pages/app-management/modals/DeleteAppModal/*
Switched UI text/icons from Delete→Archive in menus and modals; archive modal flows updated to call lifecycle archive and show archive-focused messaging and callbacks.
Prompts / App Management Integration
web/oss/src/components/pages/prompts/PromptsPage.tsx, .../PromptsTableSection.tsx, .../usePromptsColumns.tsx, .../store.ts
Prompts listing filters out deleted workflows, archives via molecule lifecycle, and wires onArchived callbacks to refresh UI and clear selections.
Tests
web/oss/tests/playwright/acceptance/evaluators/tests.ts, web/oss/tests/playwright/acceptance/testsset/testset-management.ts
Playwright acceptance tests updated to expect "Archive" menu item, archive modal title, and archive success messages.
Exports / Index Changes
web/oss/src/state/entities/testset/index.ts, web/oss/src/components/pages/app-management/store/index.ts, web/oss/src/pages/w/...
Added re-exports for mode helpers (getTestsetTableState, getAppWorkflowTableState) and updated archived page route re-exports.
Misc
web/packages/agenta-entities/src/shared/user/UserAuthorLabel.tsx
Removed unused React import.

Sequence Diagrams

sequenceDiagram
    participant User
    participant Page as Archived Page
    participant Table as Table/Columns
    participant Store as Paginated Store
    participant API as Backend API
    
    User->>Page: Navigate to /archived
    activate Page
    Page->>Store: getTestsetTableState("archived")
    activate Store
    Store->>API: Fetch items with include_archived=true
    activate API
    API-->>Store: Return items with deleted_at
    deactivate API
    Store->>Store: Filter rows by deleted_at, sort desc
    Store->>Store: Slice by cursor offset
    Store-->>Page: Return paginated archived rows
    deactivate Store
    Page->>Table: Render with mode="archived"
    activate Table
    Table->>Table: Show archived-only columns (deletedAt, deletedBy)
    Table->>Table: Show Restore action
    Table-->>Page: Render table
    deactivate Table
    Page-->>User: Display archived entities
    deactivate Page
Loading
sequenceDiagram
    participant User
    participant Table as Table
    participant Molecule as Lifecycle Molecule
    participant API as Backend API
    participant Store as Paginated Store
    
    User->>Table: Click Restore on a row
    activate Table
    Table->>Molecule: lifecycle.unarchive(entityId, {projectId})
    activate Molecule
    Molecule->>API: POST /.../unarchive
    activate API
    API-->>Molecule: Success
    deactivate API
    Molecule->>Store: Invalidate archived & active stores / clear caches
    Molecule-->>Table: Return success
    deactivate Molecule
    Table-->>User: Show success message
    Table->>Store: Refresh archived list
    activate Store
    Store->>API: Fetch updated archived list
    API-->>Store: Return updated list
    Store-->>Table: Updated paginated data (row removed)
    deactivate Store
    Table-->>User: Update table (row removed)
    deactivate Table
Loading
sequenceDiagram
    participant User
    participant ActivePage as Active Page
    participant Modal as Archive Modal
    participant Molecule as Lifecycle Molecule
    participant API as Backend API
    participant Stores as Active + Archived Stores
    
    User->>ActivePage: Click Archive action on row
    activate ActivePage
    ActivePage->>Modal: Open archive confirmation modal
    activate Modal
    Modal-->>User: Show "Archive {name}?" dialog
    User->>Modal: Confirm "Archive"
    Modal->>Molecule: lifecycle.archive(workflowId, {projectId})
    activate Molecule
    Molecule->>API: POST /.../archive
    activate API
    API-->>Molecule: Success
    deactivate API
    Molecule->>Stores: Invalidate active & archived paginated stores and counts
    Molecule-->>Modal: Return success
    deactivate Molecule
    Modal-->>User: Show "Archived" success message
    Modal->>ActivePage: onArchived callback
    deactivate Modal
    ActivePage->>ActivePage: Refetch active list
    ActivePage-->>User: Remove archived row from active view
    deactivate ActivePage
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/frontend-archive-ui

Copy link
Copy Markdown

@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: 15

Caution

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

⚠️ Outside diff range comments (3)
web/oss/src/components/Evaluators/index.tsx (1)

216-262: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Invalidate the evaluator table after archive/unarchive.

These handlers call workflowMolecule.lifecycle.archive/unarchive(), but this screen is driven by getEvaluatorsTableState(mode).paginatedStore. Without invalidateEvaluatorsListCache() / refetchAll() after success, the row can remain in the active or archived table until a manual reload.

Suggested fix
 const handleRestore = useCallback(async (record: EvaluatorTableRow) => {
     try {
         const {projectId} = getProjectValues()
         if (!projectId || !record.workflowId) return

         await workflowMolecule.lifecycle.unarchive(record.workflowId, {projectId})
+        refetchAll()
         message.success("Evaluator restored")
     } catch (error) {
         message.error(extractApiErrorMessage(error))
     }
-}, [])
+}, [refetchAll])

 const handleConfirmDelete = useCallback(async () => {
     if (!deleteTargetIds.length) return

     try {
         setIsDeleting(true)
         const {projectId} = getProjectValues()
         if (!projectId) return
@@
             await Promise.all(
                 deleteTargetIds.map((id) => workflowMolecule.lifecycle.archive(id, {projectId})),
             )
+            refetchAll()

             message.success(
web/oss/src/components/pages/app-management/modals/DeleteAppModal/index.tsx (1)

44-46: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Surface archive failures to the user.

The failure path only logs to the console, so a rejected archive request leaves the modal open with no visible explanation. Please show an error toast here as well.

Minimal fix
         } catch (error) {
             console.error("Failed to archive app:", error)
+            message.error("Failed to archive app")
         } finally {
web/oss/src/components/pages/prompts/PromptsPage.tsx (1)

419-425: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't continue template retry after a failed archive.

catch(console.error) consumes the cleanup failure, and Line 425 can create a new app anyway. That leaves the timed-out app unarchived and makes duplicate prompts possible.

Suggested fix
-            await workflowMolecule.lifecycle
-                .archive(statusData.appId, {projectId})
-                .catch(console.error)
+            try {
+                await workflowMolecule.lifecycle.archive(statusData.appId, {projectId})
+            } catch (error) {
+                console.error(error)
+                setStatusData((prev) => ({...prev, status: "error", details: error}))
+                return
+            }
             refetchWorkflows()
🧹 Nitpick comments (5)
web/packages/agenta-entities/src/workflow/core/types.ts (1)

22-26: ⚡ Quick win

Require an actual identifier in workflowRefs.

WorkflowReference currently allows {}, so queryWorkflows({ workflowRefs: [{}] }) type-checks even though the backend has nothing to resolve. Tightening this new public type to require at least id or slug will prevent invalid requests from escaping the client.

♻️ Proposed type tightening
-export interface WorkflowReference {
-    id?: string
-    slug?: string
-    version?: string
-}
+type WorkflowReferenceBase = {
+    version?: string
+}
+
+export type WorkflowReference =
+    | (WorkflowReferenceBase & {id: string; slug?: string})
+    | (WorkflowReferenceBase & {id?: string; slug: string})
web/oss/src/services/testsets/api/index.ts (1)

271-281: ⚡ Quick win

Use shared API utilities for new endpoint helpers.

For newly added API helper paths, route through @agenta/shared/api (axios, getAgentaApiUrl) to keep OSS/EE behavior aligned and avoid duplicate API plumbing patterns.

As per coding guidelines, "Use @agenta/shared/api for API utilities like axios, getAgentaApiUrl, getEnv, configureAxios".

web/oss/src/components/Evaluators/index.tsx (1)

333-343: ⚡ Quick win

Debounce the search term before writing it into table state.

setSearchTerm() runs on every keypress, and searchDeps={[searchTerm]} will make the table react to each one. Please debounce the input before updating the atom.

As per coding guidelines, "Use @agenta/shared/hooks for shared React hooks like useDebounceInput" and "Debounce search inputs and filters; throttle scroll and resize handlers."

web/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsx (1)

1-1: ⚡ Quick win

Avoid the deep @agenta/entities/shared/user import.

Please pull UserAuthorLabel from the package’s public export surface here instead of reaching into an internal path. That keeps this table from depending on @agenta/entities folder structure.

As per coding guidelines, "Use @agenta/entities clean named exports for entity state management (molecules), bridges, and UI components".

web/oss/tests/playwright/acceptance/testsset/testset-management.ts (1)

445-447: 🏗️ Heavy lift

Add a round-trip archive → restore acceptance case.

This now exercises the renamed archive action, but the new restore path is still untested. A regression in the archived table wiring or unarchive invalidation would slip through this suite.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c2f15224-8560-41a2-8284-85aa4c1537ce

📥 Commits

Reviewing files that changed from the base of the PR and between 213b41c and 44c7f8f.

📒 Files selected for processing (60)
  • docs/design/archive-workflows/archived-entities-view-design.md
  • web/ee/src/pages/w/[workspace_id]/p/[project_id]/apps/archived/index.tsx
  • web/ee/src/pages/w/[workspace_id]/p/[project_id]/evaluators/archived/index.tsx
  • web/ee/src/pages/w/[workspace_id]/p/[project_id]/testsets/archived/index.tsx
  • web/oss/src/components/ArchivedEntityLayout/index.tsx
  • web/oss/src/components/ArchivedEntityLayout/types.ts
  • web/oss/src/components/Evaluators/ArchivedEvaluatorsPage.tsx
  • web/oss/src/components/Evaluators/Table/EvaluatorsTable.tsx
  • web/oss/src/components/Evaluators/Table/assets/evaluatorColumns.tsx
  • web/oss/src/components/Evaluators/assets/cells/TableDropdownMenu/index.tsx
  • web/oss/src/components/Evaluators/components/DeleteEvaluatorsModal/assets/DeleteEvaluatorsModalContent/index.tsx
  • web/oss/src/components/Evaluators/components/DeleteEvaluatorsModal/index.tsx
  • web/oss/src/components/Evaluators/index.tsx
  • web/oss/src/components/Evaluators/store/evaluatorsPaginatedStore.ts
  • web/oss/src/components/TestcasesTableNew/hooks/api.ts
  • web/oss/src/components/TestsetsTable/TestsetsTable.tsx
  • web/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsx
  • web/oss/src/components/TestsetsTable/components/TestsetsFiltersContent.tsx
  • web/oss/src/components/TestsetsTable/components/TestsetsFiltersSummary.tsx
  • web/oss/src/components/TestsetsTable/components/TestsetsHeaderFilters.tsx
  • web/oss/src/components/TestsetsTable/hooks/useTestsetsColumns.tsx
  • web/oss/src/components/pages/app-management/ArchivedAppsPage.tsx
  • web/oss/src/components/pages/app-management/components/ApplicationManagementSection.tsx
  • web/oss/src/components/pages/app-management/components/appWorkflowColumns.tsx
  • web/oss/src/components/pages/app-management/index.tsx
  • web/oss/src/components/pages/app-management/modals/DeleteAppModal/index.tsx
  • web/oss/src/components/pages/app-management/modals/DeleteAppModal/store/deleteAppModalStore.ts
  • web/oss/src/components/pages/app-management/store/appWorkflowStore.ts
  • web/oss/src/components/pages/app-management/store/index.ts
  • web/oss/src/components/pages/prompts/PromptsPage.tsx
  • web/oss/src/components/pages/prompts/components/PromptsTableSection.tsx
  • web/oss/src/components/pages/prompts/hooks/usePromptsColumns.tsx
  • web/oss/src/components/pages/prompts/store.ts
  • web/oss/src/components/pages/testset/ArchivedTestsetsPage.tsx
  • web/oss/src/components/pages/testset/modals/DeleteTestset.tsx
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/apps/archived/index.tsx
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/evaluators/archived/index.tsx
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/testsets/archived/index.tsx
  • web/oss/src/services/testsets/api/index.ts
  • web/oss/src/state/app/atoms/fetcher.ts
  • web/oss/src/state/app/selectors/app.ts
  • web/oss/src/state/appState/parse.ts
  • web/oss/src/state/entities/shared/createPaginatedEntityStore.ts
  • web/oss/src/state/entities/shared/index.ts
  • web/oss/src/state/entities/shared/utils.ts
  • web/oss/src/state/entities/testset/index.ts
  • web/oss/src/state/entities/testset/paginatedStore.ts
  • web/oss/src/state/entities/testset/store.ts
  • web/oss/src/state/entities/testset/testsetController.ts
  • web/oss/tests/playwright/acceptance/evaluators/tests.ts
  • web/oss/tests/playwright/acceptance/testsset/testset-management.ts
  • web/packages/agenta-entities/src/shared/user/UserAuthorLabel.tsx
  • web/packages/agenta-entities/src/testset/api/index.ts
  • web/packages/agenta-entities/src/testset/api/mutations.ts
  • web/packages/agenta-entities/src/testset/index.ts
  • web/packages/agenta-entities/src/testset/state/testsetMolecule.ts
  • web/packages/agenta-entities/src/workflow/api/api.ts
  • web/packages/agenta-entities/src/workflow/core/types.ts
  • web/packages/agenta-entities/src/workflow/state/evaluatorUtils.ts
  • web/packages/agenta-entities/src/workflow/state/molecule.ts
💤 Files with no reviewable changes (1)
  • web/packages/agenta-entities/src/shared/user/UserAuthorLabel.tsx

Comment thread docs/design/archive-workflows/archived-entities-view-design.md
Comment thread docs/design/archive-workflows/archived-entities-view-design.md
Comment thread web/oss/src/components/Evaluators/index.tsx Outdated
Comment thread web/oss/src/components/Evaluators/store/evaluatorsPaginatedStore.ts Outdated
Comment thread web/oss/src/state/app/atoms/fetcher.ts
Comment thread web/oss/src/state/app/selectors/app.ts
Comment thread web/oss/src/state/entities/testset/paginatedStore.ts
Comment thread web/packages/agenta-entities/src/testset/state/testsetMolecule.ts
Comment thread web/packages/agenta-entities/src/workflow/state/molecule.ts
Copy link
Copy Markdown

@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


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ae80848f-cfea-42fd-8cdb-be926b01a46f

📥 Commits

Reviewing files that changed from the base of the PR and between 44c7f8f and a4b5bf0.

📒 Files selected for processing (3)
  • web/oss/src/components/ArchivedEntityLayout/index.tsx
  • web/oss/src/components/Evaluators/index.tsx
  • web/oss/src/components/Evaluators/store/evaluatorsPaginatedStore.ts
✅ Files skipped from review due to trivial changes (1)
  • web/oss/src/components/ArchivedEntityLayout/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/oss/src/components/Evaluators/index.tsx

Comment thread web/oss/src/components/Evaluators/store/evaluatorsPaginatedStore.ts
@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label May 4, 2026
@bekossy bekossy changed the base branch from main to release/v0.98.0 May 4, 2026 10:23
@bekossy bekossy merged commit beef379 into release/v0.98.0 May 4, 2026
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Frontend lgtm This PR has been approved by a maintainer size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants