feat(saved-views): add organization and private saved views across API and UI#2160
Open
feat(saved-views): add organization and private saved views across API and UI#2160
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds end-to-end Saved Views support (organization-wide + user-private) across the .NET API, Elasticsearch persistence, generated OpenAPI/TS client artifacts, and Svelte UI integrations for Events/Issues/Stream dashboards, including feature-flag gating at the organization level.
Changes:
- Introduces
SavedViewdomain model + repository/index, plus API endpoints for CRUD and listing by org/view with default-view semantics. - Adds mapping (Mapperly) + backend integration tests + OpenAPI snapshot updates for saved views and org features.
- Integrates Saved Views into the Svelte app (picker, auto-load default, sidebar submenu, org “Features” admin page), plus filter (de)serialization helpers and tests.
Reviewed changes
Copilot reviewed 40 out of 42 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/http/saved-views.http | Adds HTTP scratchpad requests for login, feature enablement, and saved-views CRUD flows. |
| tests/Exceptionless.Tests/Mapping/SavedViewMapperTests.cs | Validates Mapperly mappings between saved-view DTOs and domain/view models. |
| tests/Exceptionless.Tests/Controllers/SavedViewControllerTests.cs | Adds integration coverage for scoping, feature gating, validation, default behavior, and access control. |
| tests/Exceptionless.Tests/Controllers/OrganizationControllerTests.cs | Adds tests for enabling/disabling feature flags and returning features in org DTOs. |
| tests/Exceptionless.Tests/Controllers/Data/openapi.json | Updates OpenAPI snapshot to include saved-views endpoints and schemas. |
| src/Exceptionless.Web/Models/SavedView/ViewSavedView.cs | Adds API response DTO for saved views. |
| src/Exceptionless.Web/Models/SavedView/UpdateSavedView.cs | Adds PATCH/PUT DTO with validation hooks. |
| src/Exceptionless.Web/Models/SavedView/NewSavedView.cs | Adds POST DTO with server-side validation (view + filter defs + columns). |
| src/Exceptionless.Web/Models/Organization/ViewOrganization.cs | Adds Features collection to org view model for UI gating. |
| src/Exceptionless.Web/Mapping/SavedViewMapper.cs | Adds Mapperly mapper for SavedView DTO ↔ domain ↔ view model. |
| src/Exceptionless.Web/Mapping/ApiMapper.cs | Wires SavedView mapping methods into the central ApiMapper. |
| src/Exceptionless.Web/Controllers/SavedViewController.cs | Adds saved-views API endpoints + permissions + feature gating + default clearing logic. |
| src/Exceptionless.Web/Controllers/OrganizationController.cs | Adds global-admin feature-flag toggle endpoints; removes user private saved views on membership removal. |
| src/Exceptionless.Web/ClientApp/src/routes/routes.svelte.ts | Extends navigation item types to support saved-view children/default metadata. |
| src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte | Integrates saved view query param + picker into Stream dashboard. |
| src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/routes.svelte.ts | Adds “Features” nav item for global admins. |
| src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/features/+page.svelte | Adds UI for toggling known org feature flags. |
| src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte | Integrates saved view query param + picker into Issues dashboard. |
| src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte | Integrates saved view query param + picker into Events dashboard. |
| src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte | Adds websocket invalidation and sidebar submenu building from saved views. |
| src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar.svelte | Renders dashboard submenu for saved views and active highlighting logic. |
| src/Exceptionless.Web/ClientApp/src/lib/generated/schemas.ts | Adds generated Zod schemas for SavedView DTOs + org features. |
| src/Exceptionless.Web/ClientApp/src/lib/generated/api.ts | Adds generated TS interfaces for SavedView DTOs + org features. |
| src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/use-saved-views.svelte.ts | Implements saved-view loading, hydration, default auto-load, and modified detection. |
| src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/models.ts | Adds local TS models for saved-view requests/responses. |
| src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/index.ts | Exposes saved-view slice API/models for feature consumption. |
| src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/components/saved-view-picker.svelte | Adds picker UI for create/select/update/rename/delete/default operations with optimistic caching. |
| src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/api.svelte.ts | Adds query/mutation helpers + websocket-driven invalidation for saved views. |
| src/Exceptionless.Web/ClientApp/src/lib/features/organizations/api.svelte.ts | Adds client mutations for org feature enable/disable. |
| src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/helpers.svelte.ts | Adds filter serialization/deserialization used by saved views. |
| src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/helpers.svelte.test.ts | Adds Vitest coverage for filter (de)serialization round-trips and defensive parsing. |
| src/Exceptionless.Core/Services/OrganizationService.cs | Adds saved-view cleanup on org deletion and user membership removal. |
| src/Exceptionless.Core/Repositories/SavedViewRepository.cs | Adds ES queries for view/org scoping and private cleanup. |
| src/Exceptionless.Core/Repositories/Interfaces/ISavedViewRepository.cs | Defines saved-view repository contract. |
| src/Exceptionless.Core/Repositories/Configuration/Indexes/SavedViewIndex.cs | Adds ES index mapping/settings for saved views. |
| src/Exceptionless.Core/Repositories/Configuration/Indexes/OrganizationIndex.cs | Indexes org Features as keyword array. |
| src/Exceptionless.Core/Repositories/Configuration/ExceptionlessElasticConfiguration.cs | Registers the SavedViews index with the ES configuration. |
| src/Exceptionless.Core/Models/SavedView.cs | Adds core SavedView domain model + valid views/columns definitions. |
| src/Exceptionless.Core/Models/Organization.cs | Adds Features set + OrganizationFeatures constants. |
| src/Exceptionless.Core/Bootstrapper.cs | Registers ISavedViewRepository in DI. |
| .agents/skills/typescript-conventions/SKILL.md | Captures/relocates frontend code-style rules into owned skills docs. |
| .agents/skills/frontend-architecture/SKILL.md | Captures/relocates frontend architecture guidance into owned skills docs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+148
to
+152
| [HttpPatch("{id:objectid}")] | ||
| [HttpPut("{id:objectid}")] | ||
| [Consumes("application/json")] | ||
| public Task<ActionResult<ViewSavedView>> PatchAsync(string id, Delta<UpdateSavedView> changes) | ||
| { |
| import { isEntityChangedType, type WebSocketMessageType } from '$features/websockets/models'; | ||
| import { WebSocketClient } from '$features/websockets/web-socket-client.svelte'; | ||
| import { useMiddleware } from '@exceptionless/fetchclient'; | ||
| import { useFetchClient, useMiddleware } from '@exceptionless/fetchclient'; |
Comment on lines
+274
to
+276
| return new TagFilter(data.value as [] | undefined); | ||
| case 'type': | ||
| return new TypeFilter(data.value as [] | undefined); |
Comment on lines
+8358
to
+8361
| }, | ||
| "columns": { | ||
| "type": "array" | ||
| }, |
Comment on lines
+259
to
+264
| case 'level': | ||
| return new LevelFilter(data.value as [] | undefined); | ||
| case 'number': | ||
| return new NumberFilter(data.term, data.value as number | undefined); | ||
| case 'project': | ||
| return new ProjectFilter(data.value as string[] | undefined); |
Comment on lines
+269
to
+272
| case 'status': | ||
| return new StatusFilter(data.value as [] | undefined); | ||
| case 'string': | ||
| return new StringFilter(data.term, data.value as string | undefined); |
…I and UI Implements saved views end-to-end with repository/index support, API endpoints, and Svelte integration for events/issues/stream dashboards. Adds coverage for controller behavior and Mapperly mappings, including organization-wide vs private visibility and default-view behavior.
f8028c4 to
67884ad
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Key Decisions (moved from AGENTS into owned skills)
Why
Test Plan
Dogfood
Browser artifacts
API flow verification
Follow-up for attachments
Notes