feat(application): restore last project on startup (#3439)#3541
feat(application): restore last project on startup (#3439)#3541ashwinvaidya17 wants to merge 14 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds Anomalib Studio support for restoring the “startup project” deterministically on app launch by introducing backend selection/persistence endpoints and wiring the UI router to consume them.
Changes:
- Backend: add project selection service + endpoints to resolve startup project and persist “last used” project in DB.
- UI: redirect root route based on
/api/projects/startup-selectionand persist last used project when a project route is active. - Tests: add unit tests for backend service/endpoints and UI hooks; update Playwright fixtures.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| application/ui/tests/fixtures.ts | Adds MSW handlers for startup-selection and last-used persistence in component tests. |
| application/ui/src/routes/welcome.tsx | Uses shared inspect-project path helper for navigation after project creation. |
| application/ui/src/routes/router.tsx | Redirects startup route based on useStartupProjectSelection() instead of first project. |
| application/ui/src/routes/paths.ts | Introduces getInspectProjectPath helper to centralize inspect navigation URL. |
| application/ui/src/routes/layout.tsx | Persists last-used project on project-route mounts via a hook. |
| application/ui/src/hooks/use-project-selection.hook.ts | Adds hooks to fetch startup selection and persist last-used project. |
| application/ui/src/hooks/use-project-selection.hook.test.tsx | Adds tests for the new hooks (read + persist). |
| application/ui/src/hooks/index.ts | Exports the new project-selection hooks. |
| application/ui/src/features/inspect/projects-management/project-list-item/project-list-item.component.tsx | Uses shared inspect-project path helper for navigation. |
| application/backend/tests/unit/services/test_project_selection_service.py | Adds unit coverage for startup selection priority + last-used persistence. |
| application/backend/tests/unit/endpoints/test_project_selection.py | Adds endpoint tests for startup-selection and last-used update. |
| application/backend/src/services/project_selection_service.py | Implements startup project resolution and last-used persistence. |
| application/backend/src/services/init.py | Exports ProjectSelectionService. |
| application/backend/src/repositories/project_repo.py | Adds deterministic get_first_project() helper. |
| application/backend/src/repositories/app_state_repo.py | Adds repository for persisted app-wide state (last_used_project_id). |
| application/backend/src/repositories/init.py | Exports AppStateRepository. |
| application/backend/src/pydantic_models/project_selection.py | Adds request/response models for project selection endpoints. |
| application/backend/src/pydantic_models/init.py | Re-exports the new project selection models. |
| application/backend/src/main.py | Registers the project selection router. |
| application/backend/src/db/schema.py | Adds AppStateDB schema. |
| application/backend/src/api/endpoints/project_selection_endpoints.py | Adds GET startup-selection and PUT last-used endpoints. |
| application/backend/src/api/dependencies/dependencies.py | Adds dependency provider for ProjectSelectionService. |
| application/backend/src/api/dependencies/init.py | Re-exports get_project_selection_service. |
| application/backend/src/alembic/versions/7a213a27d666_initial_schema.py | Adds app_state table creation/drop (currently by editing initial migration). |
| application/backend/.gitignore | Ignores data-local/. |
Comments suppressed due to low confidence (1)
application/ui/tests/fixtures.ts:40
- The MSW fixture returns
id: '1'from/api/projects/{project_id}while the project list/startup selection usesa1b2c3d4-e5f6-7890-abcd-ef1234567890. This inconsistency can mask UI bugs (or cause confusing failures) when components assume the returned project matches the requestedproject_id. Please make the detail response ID consistent with the selected project ID.
http.get('/api/projects/{project_id}', ({ response }) => {
return response(200).json({
id: '1',
name: 'Project #1',
});
There was a problem hiding this comment.
Pull request overview
Adds “restore last project on startup” support to Anomalib Studio by introducing backend endpoints to resolve/persist the startup project, and wiring the UI router/layout to use that selection and persist the current project as “last used”.
Changes:
- Backend: add
GET /api/projects/startup-selectionandPUT /api/projects/last-used, plus service/repo/model support to resolve/persist startup project selection deterministically. - UI: redirect root route based on backend startup-selection and persist last-used project when entering a project route.
- Tests: add backend unit tests (service + endpoints) and UI hook tests; update Playwright MSW fixtures for the new endpoints.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| application/ui/tests/fixtures.ts | Adds MSW handlers for startup-selection + last-used persistence used by component tests. |
| application/ui/src/routes/router.tsx | Uses useStartupProjectSelection to redirect / to the resolved startup project. |
| application/ui/src/routes/layout.tsx | Persists the current projectId as “last used” when inside a project route. |
| application/ui/src/hooks/use-project-selection.hook.ts | New hooks to fetch startup-selection and persist last-used project via REST. |
| application/ui/src/hooks/use-project-selection.hook.test.tsx | Adds unit tests for the new hooks (startup read + last-used persistence). |
| application/ui/src/hooks/index.ts | Re-exports the new project selection hooks. |
| application/backend/tests/unit/services/test_project_selection_service.py | Adds unit tests for selection priority/fallback behavior and persistence validation. |
| application/backend/tests/unit/endpoints/test_project_selection.py | Adds endpoint tests for startup-selection and last-used update. |
| application/backend/src/services/project_selection_service.py | Implements deterministic startup project resolution and last-used persistence. |
| application/backend/src/services/init.py | Exposes ProjectSelectionService from the services package. |
| application/backend/src/repositories/project_repo.py | Adds get_first_project() with deterministic ordering. |
| application/backend/src/repositories/app_state_repo.py | New repository to store/clear “last used project id” in DB. |
| application/backend/src/repositories/init.py | Exports AppStateRepository. |
| application/backend/src/pydantic_models/project_selection.py | Adds Pydantic models/enums for startup selection + last-used update body. |
| application/backend/src/pydantic_models/init.py | Re-exports the new project selection models. |
| application/backend/src/main.py | Registers the new project selection router. |
| application/backend/src/db/schema.py | Adds AppStateDB table mapping. |
| application/backend/src/api/endpoints/project_selection_endpoints.py | New FastAPI router for startup-selection and last-used update endpoints. |
| application/backend/src/api/dependencies/dependencies.py | Adds DI provider for ProjectSelectionService. |
| application/backend/src/api/dependencies/init.py | Exports the new DI provider. |
| application/backend/src/alembic/versions/7a213a27d666_initial_schema.py | Modifies initial migration to create/drop the new app_state table. |
Docker Image SizesCPU
CUDA
XPU
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
Implements “restore last project on startup” for Anomalib Studio by introducing a backend-driven startup project resolution flow and persisting the current project as “last used” from the UI.
Changes:
- UI: Replace “pick first project” redirect with a startup-selection query and persist last-used project on project routes.
- Backend: Add project selection service + endpoints to resolve startup project and update last-used project.
- Persistence: Introduce an
app_statetable/repository and a deterministic “first project” query fallback.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| application/ui/tests/fixtures.ts | Updates MSW/Playwright fixtures for startup-selection + last-used persistence. |
| application/ui/src/routes/router.tsx | Redirect now uses useStartupProjectSelection instead of listing projects. |
| application/ui/src/routes/layout.tsx | Persists last-used project whenever a project route is active. |
| application/ui/src/hooks/use-project-selection.hook.ts | Adds hooks for startup selection and persisting last-used project. |
| application/ui/src/hooks/use-project-selection.hook.test.tsx | Adds hook tests for both read and persist behavior. |
| application/ui/src/hooks/index.ts | Re-exports the new project-selection hooks. |
| application/backend/tests/unit/services/test_project_selection_service.py | Adds unit coverage for selection priority/fallback behavior and persistence validation. |
| application/backend/tests/unit/endpoints/test_project_selection.py | Adds endpoint tests for startup-selection + last-used update. |
| application/backend/src/services/project_selection_service.py | Implements deterministic startup project selection and last-used persistence. |
| application/backend/src/services/init.py | Exports ProjectSelectionService. |
| application/backend/src/repositories/project_repo.py | Adds deterministic get_first_project fallback method. |
| application/backend/src/repositories/app_state_repo.py | Adds repository for persisted application-wide state (last used project). |
| application/backend/src/repositories/init.py | Exports AppStateRepository. |
| application/backend/src/pydantic_models/project_selection.py | Adds request/response models for project selection endpoints. |
| application/backend/src/pydantic_models/init.py | Exports the new project selection pydantic models. |
| application/backend/src/main.py | Registers the project selection router. |
| application/backend/src/db/schema.py | Adds AppStateDB ORM table definition. |
| application/backend/src/api/endpoints/project_selection_endpoints.py | Adds /projects/startup-selection and /projects/last-used endpoints. |
| application/backend/src/api/dependencies/dependencies.py | Adds DI provider for ProjectSelectionService. |
| application/backend/src/api/dependencies/init.py | Re-exports the new dependency. |
| application/backend/src/alembic/versions/7a213a27d666_initial_schema.py | Attempts to add app_state table via migration changes. |
Comments suppressed due to low confidence (1)
application/ui/tests/fixtures.ts:40
- The mocked project detail response returns
id: '1', but the project list/startup-selection usea1b2c3d4-e5f6-7890-abcd-ef1234567890. If any UI logic compares the requestedproject_idto the returnedid, tests will behave incorrectly. Please align the returnedidwith the mocked project ID (or echo back the path param).
http.get('/api/projects/{project_id}', ({ response }) => {
return response(200).json({
id: '1',
name: 'Project #1',
});
b0d98dd to
e7e9d87
Compare
There was a problem hiding this comment.
Pull request overview
This PR restores Anomalib Studio’s “last project” behavior by introducing a backend project-selection service + endpoints, persisting the last-used project in app state, and updating the UI router/layout to use that selection on startup.
Changes:
- Backend: add
app_statepersistence + deterministic startup project selection API (/api/projects/startup-selection) and last-used update API (/api/projects/last-used). - UI: redirect from
/now uses the startup-selection endpoint; layout persists the current project as last-used. - Tests: add backend unit tests for service/endpoints and UI hook tests; update Playwright MSW fixtures.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| application/ui/tests/fixtures.ts | Adds MSW handlers for the new startup-selection and last-used endpoints used by UI tests. |
| application/ui/src/routes/router.tsx | Changes initial redirect logic to use useStartupProjectSelection instead of fetching the project list. |
| application/ui/src/routes/layout.tsx | Persists current projectId as “last used” on project routes. |
| application/ui/src/hooks/use-project-selection.hook.ts | Introduces hooks to fetch startup selection and persist last-used project. |
| application/ui/src/hooks/use-project-selection.hook.test.tsx | Adds unit tests for the new UI hooks. |
| application/ui/src/hooks/index.ts | Exports the new project-selection hooks. |
| application/backend/tests/unit/services/test_project_selection_service.py | Adds unit tests for deterministic startup selection logic and last-used persistence behavior. |
| application/backend/tests/unit/endpoints/test_project_selection.py | Adds unit tests for the new project-selection API endpoints. |
| application/backend/src/services/project_selection_service.py | Implements deterministic startup selection and last-used project persistence. |
| application/backend/src/services/init.py | Exposes ProjectSelectionService from the services package. |
| application/backend/src/repositories/project_repo.py | Adds deterministic get_first_project fallback query. |
| application/backend/src/repositories/app_state_repo.py | Adds repository for persisted application-wide state (last_used_project_id). |
| application/backend/src/repositories/init.py | Exports AppStateRepository. |
| application/backend/src/pydantic_models/project_selection.py | Adds Pydantic models/enums for startup selection and last-used update payload. |
| application/backend/src/pydantic_models/init.py | Exports the new project-selection Pydantic models. |
| application/backend/src/main.py | Includes the new project-selection router in the FastAPI app. |
| application/backend/src/db/schema.py | Adds the AppStateDB SQLAlchemy model. |
| application/backend/src/api/endpoints/project_selection_endpoints.py | Adds /api/projects/startup-selection and /api/projects/last-used endpoints. |
| application/backend/src/api/dependencies/dependencies.py | Adds dependency provider for ProjectSelectionService. |
| application/backend/src/api/dependencies/init.py | Re-exports the new dependency provider. |
| application/backend/src/alembic/versions/1f4f5b1d9f6f_add_app_state_table.py | Adds Alembic migration creating the app_state table. |
| application/backend/data-local/anomalib_studio.db | Adds a local SQLite DB file reflecting the new schema. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Ashwin Vaidya <ashwin.vaidya@intel.com>
2405e81 to
9991d61
Compare
Signed-off-by: Ashwin Vaidya <ashwin.vaidya@intel.com>
9991d61 to
fc39430
Compare
There was a problem hiding this comment.
Pull request overview
Adds Anomalib Studio “restore last project on startup” behavior by introducing backend endpoints and UI hooks to deterministically select a startup project and persist the last-used project.
Changes:
- Backend: add
app_statepersistence + service/endpoint to resolve startup project via fallback order (last used → active pipeline → first project → none). - Frontend: route root redirect via
useStartupProjectSelectionand persistlast-usedproject from the project layout. - Tests: add unit coverage for backend service/endpoints and new UI hook.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| application/ui/tests/fixtures.ts | Adds MSW handlers for startup-selection and last-used persistence for UI tests. |
| application/ui/src/routes/router.tsx | Switches root redirect logic to use backend startup-selection endpoint. |
| application/ui/src/routes/layout.tsx | Persists last-used project on layout render via new hook. |
| application/ui/src/hooks/use-project-selection.hook.ts | Introduces hooks for startup selection and persisting last-used project. |
| application/ui/src/hooks/use-project-selection.hook.test.tsx | Adds tests validating the new hooks. |
| application/ui/src/hooks/index.ts | Exports the new project-selection hooks. |
| application/backend/src/services/project_selection_service.py | Implements deterministic startup project resolution + persist API. |
| application/backend/src/api/endpoints/project_selection_endpoints.py | Adds GET startup-selection and PUT last-used endpoints. |
| application/backend/src/api/dependencies/* | Wires ProjectSelectionService into dependency injection. |
| application/backend/src/repositories/app_state_repo.py | Adds repository for persisted application state. |
| application/backend/src/repositories/project_repo.py | Adds deterministic “first project” query helper. |
| application/backend/src/db/schema.py | Adds AppStateDB table schema. |
| application/backend/src/alembic/versions/1f4f5b1d9f6f_add_app_state_table.py | Adds Alembic migration for app_state. |
| application/backend/src/pydantic_models/project_selection.py | Adds request/response models for project selection endpoints. |
| application/backend/src/pydantic_models/init.py | Exports new project selection pydantic models. |
| application/backend/src/services/init.py | Exports ProjectSelectionService. |
| application/backend/src/repositories/init.py | Exports AppStateRepository. |
| application/backend/src/main.py | Registers the project selection router. |
| application/backend/tests/unit/services/test_project_selection_service.py | Unit tests for service fallback and persistence behavior. |
| application/backend/tests/unit/endpoints/test_project_selection.py | Unit tests for new endpoints. |
Comments suppressed due to low confidence (1)
application/ui/tests/fixtures.ts:40
/api/projects/{project_id}MSW handler returns a hard-coded project (id: '1') while the fixture now routes the app to project12. This can make component tests inconsistent (requesting project 12 but receiving project 1) and may hide bugs. Consider returning theproject_idpath param (and matching name) in the response so the handler aligns with the requested project.
http.get('/api/projects/{project_id}', ({ response }) => {
return response(200).json({
id: '1',
name: 'Project #1',
});
| useEffect(() => { | ||
| mutation.mutate( | ||
| { | ||
| body: { | ||
| project_id: projectId, | ||
| }, | ||
| }, | ||
| { | ||
| onError: (error) => { | ||
| console.error('Failed to persist last used project:', error); | ||
| }, | ||
| }, | ||
| ); | ||
| }, [mutation, projectId]); | ||
| }; |
Signed-off-by: Ashwin Vaidya <ashwin.vaidya@intel.com>
📝 Description
✨ Changes
Select what type of change your PR is:
✅ Checklist
Before you submit your pull request, please make sure you have completed the following steps:
For more information about code review checklists, see the Code Review Checklist.