Skip to content

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

Open
niemyjski wants to merge 18 commits intomainfrom
feature/filters
Open

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

Conversation

@niemyjski
Copy link
Copy Markdown
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
Comment thread src/Exceptionless.Web/Models/SavedView/NewSavedView.cs Fixed
Comment thread src/Exceptionless.Web/Models/SavedView/NewSavedView.cs Fixed
Copy link
Copy Markdown
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 thread src/Exceptionless.Web/Controllers/SavedViewController.cs
Comment thread src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte Outdated
Comment thread tests/Exceptionless.Tests/Controllers/Data/openapi.json
…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.
Copilot AI review requested due to automatic review settings March 28, 2026 23:20
Copy link
Copy Markdown
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 (org-wide and user-private) across the Exceptionless API and Svelte UI, including persistence/indexing, mappings, and tests, plus an admin-only organization feature toggle UI.

Changes:

  • Introduces SavedView domain model + Elasticsearch index/repository, API controller endpoints, and Mapperly mappings.
  • Adds organization feature-flag storage and admin endpoints/UI to toggle feature-saved-views.
  • Integrates Saved Views selection/creation into Events/Issues/Stream dashboards and updates generated OpenAPI/client artifacts.

Reviewed changes

Copilot reviewed 40 out of 42 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/http/saved-views.http Adds HTTP scratch workflow for feature toggle + CRUD of saved views.
tests/Exceptionless.Tests/Mapping/SavedViewMapperTests.cs Verifies Mapperly mappings for SavedView DTOs.
tests/Exceptionless.Tests/Controllers/SavedViewControllerTests.cs Integration tests for saved-views CRUD, scoping, defaults, validation, and feature gating.
tests/Exceptionless.Tests/Controllers/OrganizationControllerTests.cs Adds tests for org feature enable/disable endpoints and DTO features field.
tests/Exceptionless.Tests/Controllers/Data/openapi.json Updates OpenAPI snapshot with saved-views endpoints/schemas and org features field.
src/Exceptionless.Web/Models/SavedView/ViewSavedView.cs Adds SavedView response DTO.
src/Exceptionless.Web/Models/SavedView/UpdateSavedView.cs Adds update DTO + column-key validation hook.
src/Exceptionless.Web/Models/SavedView/NewSavedView.cs Adds create DTO + view/JSON/column validation.
src/Exceptionless.Web/Models/Organization/ViewOrganization.cs Exposes organization Features set to clients.
src/Exceptionless.Web/Mapping/SavedViewMapper.cs Adds Mapperly mapper for SavedView <-> DTOs.
src/Exceptionless.Web/Mapping/ApiMapper.cs Wires SavedView mappings into API mapper facade.
src/Exceptionless.Web/Controllers/SavedViewController.cs Implements saved-views endpoints with feature gating, scoping, and default handling.
src/Exceptionless.Web/Controllers/OrganizationController.cs Removes private saved views on org user removal; adds feature enable/disable endpoints.
src/Exceptionless.Web/ClientApp/src/routes/routes.svelte.ts Extends navigation types to support dashboard children entries.
src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte Adds saved-view query param + picker integration for Stream dashboard.
src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/routes.svelte.ts Adds “Features” admin route entry.
src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/features/+page.svelte New UI page for toggling org feature flags.
src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte Adds saved-view query param + picker integration for Issues dashboard.
src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte Adds saved-view query param + picker integration for Events dashboard.
src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte Subscribes to SavedView websocket invalidation + builds sidebar children from saved views.
src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar.svelte Renders collapsible dashboard submenu for saved views.
src/Exceptionless.Web/ClientApp/src/lib/generated/schemas.ts Adds generated schemas/types for saved views and org features.
src/Exceptionless.Web/ClientApp/src/lib/generated/api.ts Adds generated API types for saved views and org features.
src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/use-saved-views.svelte.ts Adds saved-view state management (hydrate/reset/modified/default restore).
src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/models.ts Adds saved-views feature-layer types over generated client types.
src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/index.ts Re-exports saved-views APIs/models for feature consumers.
src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/components/saved-view-picker.svelte Adds UI for selecting/saving/renaming/deleting/defaulting saved views.
src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/api.svelte.ts Adds saved-views queries/mutations + websocket invalidation behavior.
src/Exceptionless.Web/ClientApp/src/lib/features/organizations/api.svelte.ts Adds org feature toggle mutations.
src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/helpers.svelte.ts Adds filter serialization/deserialization for saved-view persistence.
src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/helpers.svelte.test.ts Adds unit tests for filter (de)serialization + round-trips.
src/Exceptionless.Core/Services/OrganizationService.cs Removes saved views on org deletion; removes private views when user leaves org.
src/Exceptionless.Core/Repositories/SavedViewRepository.cs Adds repository queries for org/user/view scoping and cleanup operations.
src/Exceptionless.Core/Repositories/Interfaces/ISavedViewRepository.cs Adds saved-view repository contract.
src/Exceptionless.Core/Repositories/Configuration/Indexes/SavedViewIndex.cs Adds ES index/mapping for saved views.
src/Exceptionless.Core/Repositories/Configuration/Indexes/OrganizationIndex.cs Adds ES mapping for organization features field.
src/Exceptionless.Core/Repositories/Configuration/ExceptionlessElasticConfiguration.cs Registers SavedViews index in elastic configuration.
src/Exceptionless.Core/Models/SavedView.cs Adds SavedView core model + allowed 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 project-specific frontend conventions.
.agents/skills/frontend-architecture/SKILL.md Captures project Svelte/architecture guidance (query param binding, $derived/$effect).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Exceptionless.Web/Controllers/OrganizationController.cs Outdated
Comment thread src/Exceptionless.Web/Controllers/OrganizationController.cs Outdated
Comment thread tests/Exceptionless.Tests/Controllers/Data/openapi.json
Fixes for code quality and correctness issues identified in saved-views PR review:

- OrganizationController: Add post-trim validation to prevent empty feature flags from whitespace-only input (closes security gap in minlength route constraint)
- DeltaSchemaTransformer: Fix Dictionary schema generation to emit object with additionalProperties instead of array (IDictionary detection must run before IEnumerable check)
- helpers.svelte.ts: Replace vague `as []` casts with concrete types (LogLevel[], StackStatus[], PersistentEventKnownTypes[]) for type safety
- +layout.svelte: Resolve duplicate currentOrganization declaration by renaming Intercom-specific variable
- OrganizationControllerTests: Add whitespace-only feature name test coverage
- openapi.json: Regenerate snapshot to reflect Dictionary schema fix
Fixes for code quality and correctness issues identified in saved-views PR review:

- OrganizationController: Add post-trim validation to prevent empty feature flags from whitespace-only input (closes security gap in minlength route constraint)
- DeltaSchemaTransformer: Fix Dictionary schema generation to emit object with additionalProperties instead of array (IDictionary detection must run before IEnumerable check)
- helpers.svelte.ts: Replace vague `as []` casts with concrete types (LogLevel[], StackStatus[], PersistentEventKnownTypes[]) for type safety
- +layout.svelte: Resolve duplicate currentOrganization declaration by renaming Intercom-specific variable
- OrganizationControllerTests: Add whitespace-only feature name test coverage
- openapi.json: Regenerate snapshot to reflect Dictionary schema fix
Sidebar and picker now update immediately when creating or saving views by
writing to both queryKeys.view and queryKeys.organization caches optimistically.
Delayed websocket invalidation still provides ES-refresh-safe reconciliation.
Copilot AI review requested due to automatic review settings March 30, 2026 13:44
Copy link
Copy Markdown
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

Copilot reviewed 43 out of 45 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Resolve conflict in AGENTS.md — keep both feature/filters frontend notes and main constraints.
Comment on lines +13 to +27
/// <summary>The set of valid dashboard view identifiers.</summary>
public static readonly string[] ValidViews = ["events", "issues", "stream"];

/// <summary>Valid column IDs per view, matching the TanStack Table column definitions.</summary>
public static readonly IReadOnlyDictionary<string, IReadOnlySet<string>> ValidColumnIds =
new Dictionary<string, IReadOnlySet<string>>
{
["events"] = new HashSet<string> { "user", "date" },
["issues"] = new HashSet<string> { "status", "users", "events", "first", "last" },
["stream"] = new HashSet<string> { "user", "date" }
};

/// <summary>Union of all valid column IDs across all views.</summary>
public static readonly IReadOnlySet<string> AllValidColumnIds =
new HashSet<string>(ValidColumnIds.Values.SelectMany(ids => ids));
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Really don't like this @ejsmith

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a question for @ejsmith about the model design. The ValidViews set and ValidColumnIds dictionary on the domain model serve as the single source of truth for valid view identifiers and column keys, referenced by both the API validation and frontend.

Comment thread src/Exceptionless.Core/Repositories/SavedViewRepository.cs Outdated
Comment thread src/Exceptionless.Core/Repositories/SavedViewRepository.cs Outdated
Comment thread src/Exceptionless.Core/Repositories/SavedViewRepository.cs
Comment thread src/Exceptionless.Core/Services/OrganizationService.cs Outdated
Comment thread src/Exceptionless.Core/Services/OrganizationService.cs Outdated
Comment thread src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/api.svelte.ts Outdated
Comment thread src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/models.ts Outdated
Comment thread src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte
Comment thread src/Exceptionless.Web/Controllers/SavedViewController.cs
Comment thread src/Exceptionless.Web/Controllers/SavedViewController.cs Outdated
Comment thread src/Exceptionless.Web/Controllers/SavedViewController.cs Outdated
Comment thread src/Exceptionless.Web/Models/SavedView/NewSavedView.cs
Comment thread src/Exceptionless.Web/Models/SavedView/NewSavedView.cs Outdated
…se mutations in components

- Replace raw NEST Query<T> operators with Foundatio FilterExpression for OR logic
- Rename 'view' parameter to 'dashboardView' for clarity in SavedViewRepository
- Remove delayedInvalidate, ES_INDEXING_DELAY_MS, and all delay-based workarounds
- Move all API client calls from saved-view-picker component to api.svelte.ts mutations
- Use typography Muted component for form helper text
- Rename deleteTarget to viewToDelete for clarity
- Add guard in organization feature mutations for undefined route.id
- Remove redundant XML doc comment from OrganizationService
Copy link
Copy Markdown
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

Copilot reviewed 44 out of 46 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +8 to +16
export function invalidateSavedViewQueries(queryClient: QueryClient, message: WebSocketMessageValue<'SavedViewChanged'>) {
const { organization_id } = message;

if (organization_id) {
return queryClient.invalidateQueries({ queryKey: queryKeys.organization(organization_id) });
}

return queryClient.invalidateQueries({ queryKey: queryKeys.type });
}
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

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

invalidateSavedViewQueries currently invalidates immediately regardless of change_type, but the new tests (and the documented behavior) require delaying invalidation for Added/Saved events (~1.5s) to avoid stale Elasticsearch reads overwriting optimistic cache updates. Update this helper to conditionally await a delay based on message.change_type before calling queryClient.invalidateQueries(...) (while keeping Removed immediate).

Copilot uses AI. Check for mistakes.
- Table types: Table<TData> → Table<StockFeatures, TData>
- ColumnDef/Cell/Header/Column: add StockFeatures type parameter
- getCoreRowModel() → createCoreRowModel(), getSortedRowModel() → createSortedRowModel(sortFns)
- VisibilityState → ColumnVisibilityState
- table.getState() → table.store.state
- FlexRender: content/context props → header/cell props
- RowData constraint on generic data-table components
- layerchart: BrushEventPayload.xDomain → brush.xDomainMin/xDomainMax
- layerchart: getTooltipContext → getChartContext, TooltipPayload type
- Fix ViewOrganization storybook features property
Split auth guard and WebSocket into separate effects so page navigation
doesn't tear down and recreate the WebSocket connection, which caused
unnecessary query invalidation and data refetching.
@github-actions
Copy link
Copy Markdown

Code Coverage

Package Line Rate Branch Rate Complexity Health
Exceptionless.AppHost 26% 14% 55
Exceptionless.Core 66% 60% 7671
Exceptionless.Insulation 25% 23% 203
Exceptionless.Web 59% 45% 3849
Summary 62% (12335 / 19851) 55% (6182 / 11318) 11778

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