Conversation
…frontend-archive-ui
…anagement into mode-scoped bundles
…s and specific table columns
…des in the testset management system
…luators UI components
…ort to archived Testset and Workflow tables
…lity in TestsetsTable
…tor cache supporting archived workflows and persistent metadata entries.
…and consolidate paginated store logic with shared helpers
…w toggle to application management header
…e with custom row merging
…paginated store with shared helpers and factory functions
…hecks for routing and deletion
…frontend-archive-ui
…lecule-based pattern and add unarchive support
…AI/agenta into feat/frontend-archive-ui
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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds frontend "archived" views for Apps, Evaluators, and Testsets: shared ArchivedEntityLayout, archived pages, mode-aware table columns and stores, archive/unarchive lifecycle APIs, UI copy/icons switched from delete→archive, shared pagination utilities, Playwright test updates, and repo manifest version bumps 0.97.0→0.98.0. ChangesArchived-entities feature (apps, evaluators, testsets)
Version bump cohort
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser UI
participant Table as Table Component
participant Molecule as lifecycle Molecule
participant API as Backend API
participant Cache as Query Client
participant Store as Paginated Store
Browser->>Table: User clicks "Archive" on row
Table->>Molecule: lifecycle.archive(id, {projectId})
Molecule->>API: POST /.../archive
API-->>Molecule: 200 OK
Molecule->>Cache: invalidate relevant queries (active & archived lists, item cache)
Cache-->>Store: refetch/clear caches
Store-->>Table: updated data
Table-->>Browser: updated UI
Browser->>Table: User clicks "Restore" in Archived view
Table->>Molecule: lifecycle.unarchive(id, {projectId})
Molecule->>API: POST /.../unarchive
API-->>Molecule: 200 OK
Molecule->>Cache: invalidate archived+active caches
Cache-->>Store: refetch
Store-->>Table: refreshed rows
Table-->>Browser: item appears in active view
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
feat: `frontend` `archive` UI
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
web/oss/src/components/TestsetsTable/TestsetsTable.tsx (1)
127-129:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse the management invalidator for archive/delete mutations.
mutate()only refreshes the currently mounted store. The archived table now has its own in-memory cache inweb/oss/src/state/entities/testset/paginatedStore.ts, so archiving from the active view or deleting from the archived view can leave the other mode stale until reload.DeleteTestsetModalstill calls this callback.🧹 Suggested fix
- const mutate = useCallback(() => { - setRefreshTrigger() - }, [setRefreshTrigger]) + const mutate = useCallback(() => { + invalidateTestsetManagementQueries() + }, [])web/oss/src/components/pages/prompts/PromptsPage.tsx (1)
419-425:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAbort the retry if archiving the failed prompt did not succeed.
catch(console.error)swallows the cleanup failure and the code immediately retries creation anyway. If the partial workflow is still present, the retry can collide on the same slug/name and leave orphaned failed prompts behind.Suggested fix
const {projectId} = getProjectValues() - await workflowMolecule.lifecycle - .archive(statusData.appId, {projectId}) - .catch(console.error) - refetchWorkflows() + try { + await workflowMolecule.lifecycle.archive(statusData.appId, {projectId}) + refetchWorkflows() + } catch (error) { + console.error("Failed to archive prompt before retry:", error) + message.error("Couldn't clean up the failed prompt. Please try again.") + return + } }
🧹 Nitpick comments (6)
docs/design/archive-workflows/archived-entities-view-design.md (1)
65-92: 💤 Low valueConsider adding a language specifier to the fenced code block.
The architecture diagram uses an unspecified code block. Adding a language like
textorplaintextwould satisfy markdown linting and improve rendering consistency.Suggested fix
-``` +```text web/oss/src/components/ArchivedEntityLayout/ ← NEW (shared OSS layout)web/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsx (1)
66-72: ⚖️ Poor tradeoffConsider typing revision-specific fields in
TestsetTableRow.The repeated
(record as any).__isRevision,(record as any).__version, and(record as any).__commitMessagecasts suggest these fields exist on revision rows but aren't typed. Adding optional fields toTestsetTableRow(or a discriminated union) would provide type safety and eliminate the casts.Suggested approach
// In TestsetTableRow or as a separate type: interface TestsetRevisionRow extends TestsetTableRow { __isRevision: true __version?: number | null __commitMessage?: string | null } // Then use a type guard: function isRevisionRow(row: TestsetTableRow): row is TestsetRevisionRow { return Boolean((row as any).__isRevision) }web/oss/src/state/entities/testset/paginatedStore.ts (1)
37-42: ⚡ Quick winUse the OSS alias for the shared entity helpers.
This new import reaches into shared state via a relative path, which makes the module boundary brittle and diverges from the repo’s alias convention.
♻️ Suggested cleanup
import { createDateDescComparator, createPaginatedEntityStore, emptyFetchResult, getCursorOffset, -} from "../shared" +} from "@/oss/state/entities/shared"As per coding guidelines, "Prefer
@/oss/*import alias for shared utilities, helpers, types, hooks, and state that work the same in both EE and OSS".web/oss/src/components/pages/app-management/components/ApplicationManagementSection.tsx (2)
54-65: 💤 Low valueType assertion
as neverbypasses type safety.The
as nevercast ondatasetStoresuppresses type checking. Consider either:
- Fixing the type mismatch at the source (store type definitions)
- Using a more specific type assertion that preserves some safety
Suggested improvement
const table = useTableManager<AppWorkflowRow>({ - datasetStore: tableState.paginatedStore.store as never, + datasetStore: tableState.paginatedStore.store, scopeId: isArchived ? "archived-app-workflows" : "app-workflows",If the types don't align, investigate why
getAppWorkflowTableStatereturns a store with incompatible types and fix at the definition level.
172-175: 💤 Low valueMinor: Redundant conditional check.
When
isArchivedis true,primaryActionsNodeis alreadyundefined(line 112), so the additional!isArchived &&check is redundant.Simplified expression
primaryActions={ - !isArchived && primaryActionsNode ? primaryActionsNode : undefined + primaryActionsNode }web/oss/src/components/pages/app-management/store/appWorkflowStore.ts (1)
60-71: ⚖️ Poor tradeoffConsider caching archived workflows to avoid duplicate fetches.
fetchArchivedAppWorkflowsis called both in the paginated store'sfetchPage(line 224) and in the count query (line 256). Each call makes a full API request and filters client-side. For archived views, this means two network requests for the same data.This is acceptable if archived workflow volumes are low, but could be optimized with a shared cache or by extracting the count from the paginated store's first fetch.
Also applies to: 249-262
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: fe1bf0f6-7819-4019-84f3-a3465b0ee2a4
📒 Files selected for processing (60)
docs/design/archive-workflows/archived-entities-view-design.mdweb/ee/src/pages/w/[workspace_id]/p/[project_id]/apps/archived/index.tsxweb/ee/src/pages/w/[workspace_id]/p/[project_id]/evaluators/archived/index.tsxweb/ee/src/pages/w/[workspace_id]/p/[project_id]/testsets/archived/index.tsxweb/oss/src/components/ArchivedEntityLayout/index.tsxweb/oss/src/components/ArchivedEntityLayout/types.tsweb/oss/src/components/Evaluators/ArchivedEvaluatorsPage.tsxweb/oss/src/components/Evaluators/Table/EvaluatorsTable.tsxweb/oss/src/components/Evaluators/Table/assets/evaluatorColumns.tsxweb/oss/src/components/Evaluators/assets/cells/TableDropdownMenu/index.tsxweb/oss/src/components/Evaluators/components/DeleteEvaluatorsModal/assets/DeleteEvaluatorsModalContent/index.tsxweb/oss/src/components/Evaluators/components/DeleteEvaluatorsModal/index.tsxweb/oss/src/components/Evaluators/index.tsxweb/oss/src/components/Evaluators/store/evaluatorsPaginatedStore.tsweb/oss/src/components/TestcasesTableNew/hooks/api.tsweb/oss/src/components/TestsetsTable/TestsetsTable.tsxweb/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsxweb/oss/src/components/TestsetsTable/components/TestsetsFiltersContent.tsxweb/oss/src/components/TestsetsTable/components/TestsetsFiltersSummary.tsxweb/oss/src/components/TestsetsTable/components/TestsetsHeaderFilters.tsxweb/oss/src/components/TestsetsTable/hooks/useTestsetsColumns.tsxweb/oss/src/components/pages/app-management/ArchivedAppsPage.tsxweb/oss/src/components/pages/app-management/components/ApplicationManagementSection.tsxweb/oss/src/components/pages/app-management/components/appWorkflowColumns.tsxweb/oss/src/components/pages/app-management/index.tsxweb/oss/src/components/pages/app-management/modals/DeleteAppModal/index.tsxweb/oss/src/components/pages/app-management/modals/DeleteAppModal/store/deleteAppModalStore.tsweb/oss/src/components/pages/app-management/store/appWorkflowStore.tsweb/oss/src/components/pages/app-management/store/index.tsweb/oss/src/components/pages/prompts/PromptsPage.tsxweb/oss/src/components/pages/prompts/components/PromptsTableSection.tsxweb/oss/src/components/pages/prompts/hooks/usePromptsColumns.tsxweb/oss/src/components/pages/prompts/store.tsweb/oss/src/components/pages/testset/ArchivedTestsetsPage.tsxweb/oss/src/components/pages/testset/modals/DeleteTestset.tsxweb/oss/src/pages/w/[workspace_id]/p/[project_id]/apps/archived/index.tsxweb/oss/src/pages/w/[workspace_id]/p/[project_id]/evaluators/archived/index.tsxweb/oss/src/pages/w/[workspace_id]/p/[project_id]/testsets/archived/index.tsxweb/oss/src/services/testsets/api/index.tsweb/oss/src/state/app/atoms/fetcher.tsweb/oss/src/state/app/selectors/app.tsweb/oss/src/state/appState/parse.tsweb/oss/src/state/entities/shared/createPaginatedEntityStore.tsweb/oss/src/state/entities/shared/index.tsweb/oss/src/state/entities/shared/utils.tsweb/oss/src/state/entities/testset/index.tsweb/oss/src/state/entities/testset/paginatedStore.tsweb/oss/src/state/entities/testset/store.tsweb/oss/src/state/entities/testset/testsetController.tsweb/oss/tests/playwright/acceptance/evaluators/tests.tsweb/oss/tests/playwright/acceptance/testsset/testset-management.tsweb/packages/agenta-entities/src/shared/user/UserAuthorLabel.tsxweb/packages/agenta-entities/src/testset/api/index.tsweb/packages/agenta-entities/src/testset/api/mutations.tsweb/packages/agenta-entities/src/testset/index.tsweb/packages/agenta-entities/src/testset/state/testsetMolecule.tsweb/packages/agenta-entities/src/workflow/api/api.tsweb/packages/agenta-entities/src/workflow/core/types.tsweb/packages/agenta-entities/src/workflow/state/evaluatorUtils.tsweb/packages/agenta-entities/src/workflow/state/molecule.ts
💤 Files with no reviewable changes (1)
- web/packages/agenta-entities/src/shared/user/UserAuthorLabel.tsx
✅ Files skipped from review due to trivial changes (9)
- web/oss/src/components/ArchivedEntityLayout/types.ts
- web/oss/src/components/Evaluators/components/DeleteEvaluatorsModal/index.tsx
- web/ee/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/pages/w/[workspace_id]/p/[project_id]/apps/archived/index.tsx
- web/oss/src/components/pages/testset/ArchivedTestsetsPage.tsx
- web/oss/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/ee/src/pages/w/[workspace_id]/p/[project_id]/apps/archived/index.tsx
Railway Preview Environment
Updated at 2026-05-04T11:54:30.687Z |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
web/oss/src/components/Evaluators/index.tsx (1)
257-259: 💤 Low valueConsider using
extractApiErrorMessagefor consistent error handling.The
handleRestorecallback (line 228) usesextractApiErrorMessage(error)for user-friendly error messages, but this handler uses a generic string. For consistency and better debugging, consider using the same pattern here.♻️ Suggested fix
} catch (error) { console.error(error) - message.error("Failed to archive evaluators") + message.error(extractApiErrorMessage(error)) } finally {web/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsx (1)
66-67: Extract revision metadata properties into a typed helper to eliminate repeatedanycasts.The
TestsetTableRowtype doesn't include__isRevision,__version, and__commitMessageproperties—they're added at runtime for revision rows. Currently, accessing them requires repeated(record as any)casts (15 total instances), bypassing TypeScript checks. Introduce a typed revision view helper instead:Suggested refactor
+type TestsetRevisionMeta = { + __isRevision?: boolean + __version?: string | number | null + __commitMessage?: string | null +} + +const asRevisionMeta = (record: TestsetTableRow) => + record as TestsetTableRow & TestsetRevisionMeta ... - const isRevision = Boolean((record as any).__isRevision) + const revision = asRevisionMeta(record) + const isRevision = Boolean(revision.__isRevision) ... - const version = (record as any).__version + const version = revision.__version ... - const isRevision = Boolean((record as any).__isRevision) + const revision = asRevisionMeta(record) + const isRevision = Boolean(revision.__isRevision) ... - const commitMessage = (record as any).__commitMessage + const commitMessage = revision.__commitMessageAlso applies to: 72, 119, 125, 190, 197, 202, 210, 220, 228, 236, 241, 250, 257, 262, 271
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: ae71bb91-71b5-477f-b92e-b234a96c693d
📒 Files selected for processing (2)
web/oss/src/components/Evaluators/index.tsxweb/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsx
New version v0.98.0 in