Skip to content

feat(saved-views): add organization and private saved views across API and UI#2160

Open
niemyjski wants to merge 1 commit intomainfrom
feature/filters
Open

feat(saved-views): add organization and private saved views across API and UI#2160
niemyjski wants to merge 1 commit intomainfrom
feature/filters

Conversation

@niemyjski
Copy link
Member

@niemyjski niemyjski commented Mar 16, 2026

Summary

  • Add end-to-end Saved Views support across backend and frontend for events, issues, and stream dashboards.
  • Add Mapperly-based SavedView mappings and mapping tests to align with the repository migration away from AutoMapper.
  • Add API endpoints, repository/index support, generated client updates, and UI integration for creating/selecting saved views.

Key Decisions (moved from AGENTS into owned skills)

  • Saved view scoping model: UserId null means organization-wide and UserId set means user-private.
  • Saved view routes are object-id based (saved-views/{id}), not slug based.
  • Frontend uses query param binding for selected saved view and keeps saved-view logic in feature slices.
  • Code-quality rules previously captured in AGENTS are now preserved in owned skills:
    • .agents/skills/dotnet-conventions/SKILL.md
    • .agents/skills/typescript-conventions/SKILL.md
    • .agents/skills/frontend-architecture/SKILL.md

Why

  • Brings reusable dashboard filters to users with clear organization/private ownership semantics.
  • Keeps mapping and validation behavior consistent with current architecture.
  • Preserves valuable code-style guidance without leaving AGENTS diffs in the PR.

Test Plan

  • dotnet build
  • dotnet test -- --filter-class Exceptionless.Tests.Controllers.SavedViewControllerTests
  • dotnet test -- --filter-class Exceptionless.Tests.Mapping.SavedViewMapperTests

Dogfood

Browser artifacts

  • dogfood-output/saved-views/screenshots/01-home.png
  • dogfood-output/saved-views/screenshots/02-login-page.png
  • dogfood-output/saved-views/screenshots/03-after-login-click.png
  • dogfood-output/saved-views/screenshots/04-login-filled.png
  • dogfood-output/saved-views/screenshots/05-post-login.png
  • dogfood-output/saved-views/screenshots/06-after-logo-click.png
  • dogfood-output/saved-views/screenshots/07-login-page-fresh.png
  • dogfood-output/saved-views/screenshots/08-login-form.png
  • dogfood-output/saved-views/screenshots/09-login-form-filled.png
  • dogfood-output/saved-views/screenshots/10-after-login-attempt.png
  • dogfood-output/saved-views/screenshots/11-login-blocker-annotated.png

API flow verification

  • Enable saved-views feature: 200
  • Create organization-wide view: 201
  • Create private view: 201
  • List by organization: 200
  • Patch invalid column key: 422
  • Delete saved view: 202
  • Disable saved-views feature: 200
  • Full command output artifact: dogfood-output/saved-views/api-dogfood.txt

Follow-up for attachments

  • User will attach selected screenshots directly to the PR.

Notes

  • No AGENTS.md changes are included in this PR.

Copilot AI review requested due to automatic review settings March 16, 2026 14:04
@niemyjski niemyjski self-assigned this Mar 16, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 SavedView domain 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.
@github-actions
Copy link

Code Coverage

Package Line Rate Branch Rate Complexity Health
Exceptionless.Insulation 24% 23% 208
Exceptionless.Core 66% 60% 7603
Exceptionless.AppHost 26% 14% 55
Exceptionless.Web 59% 45% 3735
Summary 62% (12208 / 19691) 55% (6091 / 11138) 11601

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants