From 4ed01d6d32ecd7f0ee169c48e85997e3eadbe26b Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Thu, 30 Jan 2025 20:08:23 -0600 Subject: [PATCH] Next: Added New Organization Sidebar and filter selector (#1812) * Added breadcrumb * Added user and org sidebar * Delete src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Navbar.svelte * Delete src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Footer.svelte * Delete src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Sidebar.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/Summary.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Environment.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Request.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Bytes.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Duration.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Number.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Percentage.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Checkbox.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Switch.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.ts * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Blockquote.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Code.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H1.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H2.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H3.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H4.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Large.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Lead.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/List.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Muted.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/P.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Small.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Live.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Loading.svelte * Delete src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Logo.svelte * Fixed sidebar * Updated deps * Fixed email address form. * Updated deps * Added documentation * Updated deps * Fixed [svelte] transition_slide_display The `slide` transition does not work correctly for elements with `display: table-row` https://svelte.dev/e/transition_slide_display * next: show org switcher only if more than one org, moved current org into org feature context * migrated to $app/state * WIP: Removed organization filters as it's inferred from current selected organization. * next: fixed linting * upgrade deps * add sveltekit-search-params * updated deps * Updated Deps * WIP - Reworking filters * Updated packages * More cleanup to filters --- .../ClientApp/components.json | 2 +- .../ClientApp/package-lock.json | 689 +++++++++--------- src/Exceptionless.Web/ClientApp/package.json | 49 +- .../src/lib/features/auth/index.svelte.ts | 5 +- .../events/components/events-drawer.svelte | 11 +- .../boolean-faceted-filter-builder.svelte | 27 + .../boolean-faceted-filter-trigger.svelte} | 2 +- .../filters}/boolean-faceted-filter.svelte | 10 +- .../date-faceted-filter-builder.svelte | 27 + .../date-faceted-filter-trigger.svelte} | 2 +- .../filters}/date-faceted-filter.svelte | 10 +- .../{filters.ts => filters/helpers.ts} | 11 +- .../events/components/filters/index.ts | 112 +++ .../keyword-faceted-filter-builder.svelte | 26 + .../filters}/keyword-faceted-filter.svelte | 10 +- .../components/filters/models.svelte.ts} | 205 ++---- .../number-faceted-filter-builder.svelte | 27 + .../number-faceted-filter-trigger.svelte} | 2 +- .../filters}/number-faceted-filter.svelte | 10 +- ...ion-defaults-faceted-filter-builder.svelte | 99 +++ .../project-faceted-filter-builder.svelte | 26 + .../project-faceted-filter-trigger.svelte} | 8 +- .../filters}/project-faceted-filter.svelte | 18 +- .../reference-faceted-filter-builder.svelte | 26 + .../reference-faceted-filter-trigger.svelte} | 2 +- .../filters}/reference-faceted-filter.svelte | 10 +- .../session-faceted-filter-builder.svelte | 26 + .../session-faceted-filter-trigger.svelte} | 2 +- .../filters}/session-faceted-filter.svelte | 10 +- .../status-faceted-filter-builder.svelte | 26 + .../status-faceted-filter-trigger.svelte} | 2 +- .../filters}/status-faceted-filter.svelte | 12 +- .../string-faceted-filter-builder.svelte | 27 + .../string-faceted-filter-trigger.svelte} | 2 +- .../filters}/string-faceted-filter.svelte | 10 +- .../type-faceted-filter-builder.svelte | 26 + .../type-faceted-filter-trigger.svelte} | 2 +- .../filters}/type-faceted-filter.svelte | 14 +- .../version-faceted-filter-builder.svelte | 27 + .../version-faceted-filter-trigger.svelte} | 2 +- .../filters}/version-faceted-filter.svelte | 10 +- .../events/components/summary/Summary.svelte | 58 -- .../components/views/Environment.svelte | 132 ---- .../events/components/views/Error.svelte | 107 --- .../events/components/views/Overview.svelte | 282 ------- .../events/components/views/Request.svelte | 200 ----- .../components/views/environment.svelte | 14 +- .../events/components/views/error.svelte | 15 +- .../events/components/views/overview.svelte | 62 +- .../events/components/views/request.svelte | 30 +- .../features/organizations/context.svelte.ts | 3 + .../features/shared/components/Live.svelte | 19 - .../features/shared/components/Loading.svelte | 39 - .../features/shared/components/Logo.svelte | 12 - .../faceted-filter-boolean.svelte} | 0 .../faceted-filter-builder-context.svelte.ts | 14 + .../faceted-filter-builder.svelte | 88 ++- .../faceted-filter-drop-down.svelte} | 2 +- .../faceted-filter-keyword.svelte} | 0 .../faceted-filter-multi-select.svelte} | 2 +- .../faceted-filter-number.svelte} | 0 .../faceted-filter-string.svelte} | 0 .../shared/components/faceted-filter/index.ts | 27 +- .../components/faceted-filter/models.ts | 27 + .../clickable-organization-filter.svelte | 21 - .../shared/components/filters/facets/index.ts | 99 --- .../facets/organization-faceted-filter.svelte | 47 -- .../shared/components/formatters/Bytes.svelte | 19 - .../components/formatters/Duration.svelte | 71 -- .../components/formatters/Number.svelte | 11 - .../components/formatters/Percentage.svelte | 19 - .../components/primitives/Checkbox.svelte | 25 - .../components/primitives/Switch.svelte | 24 - .../shared/components/typography/A.svelte | 13 - .../shared/components/typography/A.ts | 24 - .../components/typography/Blockquote.svelte | 15 - .../shared/components/typography/Code.svelte | 15 - .../shared/components/typography/H1.svelte | 15 - .../shared/components/typography/H2.svelte | 15 - .../shared/components/typography/H3.svelte | 15 - .../shared/components/typography/H4.svelte | 15 - .../shared/components/typography/Large.svelte | 15 - .../shared/components/typography/Lead.svelte | 15 - .../shared/components/typography/List.svelte | 25 - .../shared/components/typography/Muted.svelte | 15 - .../shared/components/typography/P.svelte | 15 - .../shared/components/typography/Small.svelte | 15 - .../alert-dialog/alert-dialog-action.svelte | 2 +- .../alert-dialog/alert-dialog-cancel.svelte | 2 +- .../ui/breadcrumb/breadcrumb-ellipsis.svelte | 23 + .../ui/breadcrumb/breadcrumb-item.svelte | 16 + .../ui/breadcrumb/breadcrumb-link.svelte | 31 + .../ui/breadcrumb/breadcrumb-list.svelte | 23 + .../ui/breadcrumb/breadcrumb-page.svelte | 23 + .../ui/breadcrumb/breadcrumb-separator.svelte | 27 + .../ui/breadcrumb/breadcrumb.svelte | 15 + .../shared/components/ui/breadcrumb/index.ts | 25 + .../shared/components/ui/collapsible/index.ts | 15 + .../ui/command/command-dialog.svelte | 2 +- .../components/ui/form/form-button.svelte | 2 +- .../components/ui/form/form-label.svelte | 2 +- .../ui/select/select-separator.svelte | 2 +- .../shared/components/ui/sidebar/constants.ts | 2 +- .../ui/sidebar/sidebar-input.svelte | 2 +- .../ui/sidebar/sidebar-menu-button.svelte | 2 +- .../ui/sidebar/sidebar-menu-skeleton.svelte | 2 +- .../ui/sidebar/sidebar-provider.svelte | 2 +- .../ui/sidebar/sidebar-separator.svelte | 2 +- .../ui/sidebar/sidebar-trigger.svelte | 2 +- .../components/ui/sidebar/sidebar.svelte | 2 +- .../components/ui/table/table-row.svelte | 37 +- .../src/lib/features/shared/strings.ts | 19 + .../stacks/components/stack-card.svelte | 11 +- .../src/lib/features/users/api.svelte.ts | 4 +- .../src/lib/features/users/gravatar.svelte.ts | 21 +- .../src/lib/features/users/models.ts | 7 +- .../(app)/(components)/layouts/Footer.svelte | 47 -- .../(app)/(components)/layouts/Navbar.svelte | 127 ---- .../(app)/(components)/layouts/Sidebar.svelte | 39 - .../(app)/(components)/layouts/navbar.svelte | 78 -- .../sidebar-organization-switcher.svelte | 98 +++ .../(components)/layouts/sidebar-user.svelte | 150 ++++ .../(app)/(components)/layouts/sidebar.svelte | 26 +- .../(components)/navigation-command.svelte | 2 +- .../ClientApp/src/routes/(app)/+layout.svelte | 66 +- .../ClientApp/src/routes/(app)/+page.svelte | 52 +- .../src/routes/(app)/account/+layout.svelte | 4 +- .../routes/(app)/account/manage/+page.svelte | 21 +- .../src/routes/(app)/issues/+page.svelte | 58 +- .../ClientApp/src/routes/(app)/routes.ts | 32 + .../src/routes/(app)/stream/+page.svelte | 48 +- .../src/routes/(auth)/login/+page.svelte | 2 - .../ClientApp/src/routes/+layout.svelte | 7 +- .../ClientApp/src/routes/routes.ts | 1 + 134 files changed, 1956 insertions(+), 2547 deletions(-) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/boolean-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-boolean-filter.svelte => events/components/filters/boolean-faceted-filter-trigger.svelte} (92%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/boolean-faceted-filter.svelte (60%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-date-filter.svelte => events/components/filters/date-faceted-filter-trigger.svelte} (93%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/date-faceted-filter.svelte (82%) rename src/Exceptionless.Web/ClientApp/src/lib/features/events/components/{filters.ts => filters/helpers.ts} (74%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/index.ts create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/keyword-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/keyword-faceted-filter.svelte (62%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/filters.svelte.ts => events/components/filters/models.svelte.ts} (69%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-number-filter.svelte => events/components/filters/number-faceted-filter-trigger.svelte} (92%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/number-faceted-filter.svelte (60%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/organization-defaults-faceted-filter-builder.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-project-filter.svelte => events/components/filters/project-faceted-filter-trigger.svelte} (69%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/project-faceted-filter.svelte (67%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-reference-filter.svelte => events/components/filters/reference-faceted-filter-trigger.svelte} (92%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/reference-faceted-filter.svelte (62%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-session-filter.svelte => events/components/filters/session-faceted-filter-trigger.svelte} (92%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/session-faceted-filter.svelte (62%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-status-filter.svelte => events/components/filters/status-faceted-filter-trigger.svelte} (93%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/status-faceted-filter.svelte (69%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-string-filter.svelte => events/components/filters/string-faceted-filter-trigger.svelte} (93%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/string-faceted-filter.svelte (60%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-type-filter.svelte => events/components/filters/type-faceted-filter-trigger.svelte} (92%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/type-faceted-filter.svelte (61%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/clickable-version-filter.svelte => events/components/filters/version-faceted-filter-trigger.svelte} (92%) rename src/Exceptionless.Web/ClientApp/src/lib/features/{shared/components/filters/facets => events/components/filters}/version-faceted-filter.svelte (60%) delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/Summary.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Environment.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Request.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/organizations/context.svelte.ts delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Live.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Loading.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Logo.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/{filters/facets/base/boolean-faceted-filter.svelte => faceted-filter/faceted-filter-boolean.svelte} (100%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder-context.svelte.ts rename src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/{filters/facets/base/drop-down-faceted-filter.svelte => faceted-filter/faceted-filter-drop-down.svelte} (98%) rename src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/{filters/facets/base/keyword-faceted-filter.svelte => faceted-filter/faceted-filter-keyword.svelte} (100%) rename src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/{filters/facets/base/multiselect-faceted-filter.svelte => faceted-filter/faceted-filter-multi-select.svelte} (98%) rename src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/{filters/facets/base/number-faceted-filter.svelte => faceted-filter/faceted-filter-number.svelte} (100%) rename src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/{filters/facets/base/string-faceted-filter.svelte => faceted-filter/faceted-filter-string.svelte} (100%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/models.ts delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-organization-filter.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/index.ts delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/organization-faceted-filter.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Bytes.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Duration.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Number.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Percentage.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Checkbox.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Switch.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.ts delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Blockquote.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Code.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H1.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H2.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H3.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H4.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Large.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Lead.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/List.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Muted.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/P.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Small.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-ellipsis.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-item.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-link.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-list.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-page.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-separator.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/index.ts create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/collapsible/index.ts create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/strings.ts delete mode 100644 src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Footer.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Navbar.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Sidebar.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-organization-switcher.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte diff --git a/src/Exceptionless.Web/ClientApp/components.json b/src/Exceptionless.Web/ClientApp/components.json index dfc1302b47..0b6a21a8df 100644 --- a/src/Exceptionless.Web/ClientApp/components.json +++ b/src/Exceptionless.Web/ClientApp/components.json @@ -9,7 +9,7 @@ "aliases": { "components": "$comp", "utils": "$lib/utils", - "ui": "$lib/features/shared/components/ui", + "ui": "$comp/ui", "hooks": "$lib/hooks" }, "typescript": true, diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index 596de0c5f8..50c7ab1dee 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -9,59 +9,60 @@ "version": "8.0.0", "dependencies": { "@exceptionless/browser": "^3.1.0", - "@exceptionless/fetchclient": "^0.36.0", - "@iconify-json/mdi": "^1.2.2", + "@exceptionless/fetchclient": "^0.40.0", + "@iconify-json/mdi": "^1.2.3", "@tanstack/svelte-query": "https://pkg.pr.new/@tanstack/svelte-query@28f98f9", "@tanstack/svelte-query-devtools": "https://pkg.pr.new/@tanstack/svelte-query-devtools@28f98f9", "@tanstack/svelte-table": "^9.0.0-alpha.10", "@typeschema/class-validator": "^0.3.0", - "bits-ui": "^1.0.0-next.77", + "bits-ui": "^1.0.0-next.78", "class-validator": "^0.14.1", "clsx": "^2.1.1", "formsnap": "^2.0.0", - "lucide-svelte": "^0.471.0", - "mode-watcher": "^0.5.0", + "lucide-svelte": "^0.474.0", + "mode-watcher": "^0.5.1", "oidc-client-ts": "^3.1.0", "pretty-ms": "^9.2.0", - "runed": "^0.23.0", + "runed": "^0.23.2", "svelte-sonner": "^0.3.28", - "svelte-time": "^0.9.0", - "sveltekit-superforms": "^2.22.1", + "svelte-time": "^2.0.0", + "sveltekit-search-params": "^4.0.0-next.0", + "sveltekit-superforms": "^2.23.1", "tailwind-merge": "^2.6.0", - "tailwind-variants": "^0.3.0", + "tailwind-variants": "^0.3.1", "tailwindcss": "^3.4.17", "tailwindcss-animate": "^1.0.7", "throttle-debounce": "^5.0.2", "unplugin-icons": "^22.0.0" }, "devDependencies": { - "@iconify-json/lucide": "^1.2.22", - "@playwright/test": "^1.49.1", + "@iconify-json/lucide": "^1.2.25", + "@playwright/test": "^1.50.0", "@sveltejs/adapter-static": "^3.0.8", - "@sveltejs/kit": "^2.15.2", + "@sveltejs/kit": "^2.16.1", "@sveltejs/vite-plugin-svelte": "^5.0.3", "@types/eslint": "^9.6.1", - "@types/node": "^22.10.5", + "@types/node": "^22.12.0", "@types/throttle-debounce": "^5.0.2", "autoprefixer": "^10.4.20", "cross-env": "^7.0.3", - "eslint": "^9.17.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-perfectionist": "^4.6.0", + "eslint": "^9.19.0", + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-perfectionist": "^4.7.0", "eslint-plugin-svelte": "^2.46.1", "npm-run-all": "^4.1.5", - "postcss": "^8.4.49", + "postcss": "^8.5.1", "prettier": "^3.4.2", - "prettier-plugin-svelte": "^3.3.2", - "prettier-plugin-tailwindcss": "^0.6.9", - "svelte": "^5.17.1", - "svelte-check": "^4.1.3", + "prettier-plugin-svelte": "^3.3.3", + "prettier-plugin-tailwindcss": "^0.6.11", + "svelte": "^5.19.6", + "svelte-check": "^4.1.4", "swagger-typescript-api": "^13.0.23", "tslib": "^2.8.1", "typescript": "^5.7.3", - "typescript-eslint": "^8.19.1", - "vite": "^6.0.7", - "vitest": "2.1.6" + "typescript-eslint": "^8.22.0", + "vite": "^6.0.11", + "vitest": "3.0.4" } }, "node_modules/@alloc/quick-lru": { @@ -112,19 +113,19 @@ } }, "node_modules/@ark/schema": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@ark/schema/-/schema-0.26.0.tgz", - "integrity": "sha512-b6hk1+M0U4jgZK7ZOGsWKSXgjhfPAqqSCczViM/gQ0Hu0awKLx9SpZYsFhl0j67j3hwlY2+mVZQPKy6GlYDCbQ==", + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/@ark/schema/-/schema-0.35.0.tgz", + "integrity": "sha512-cV3tiYpIFIt4JB4ZrXSUJ6v2nnAzbX5DqaNWRMpk4pVQV15HMEawg6wYn+JKEI16vfRCIcGqxxdGBvE0zIxqKw==", "license": "MIT", "optional": true, "dependencies": { - "@ark/util": "0.26.0" + "@ark/util": "0.35.0" } }, "node_modules/@ark/util": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@ark/util/-/util-0.26.0.tgz", - "integrity": "sha512-6FSqj6xl3jQ9bD9EU25ThMVcsvaeq6c3gecONgPQ+wDYOUEqBBIAkpjA+LEZMiY0AxVhSF3UF6BlVFspXmef2Q==", + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/@ark/util/-/util-0.35.0.tgz", + "integrity": "sha512-KxhwMOGMoV605zcqoBVyNFEtKAc3PKy95IWmVz9dwuUzIQ+sh7Bk9KEnlGPXcPAD8DCDs/10deHeO1kfWWONvg==", "license": "MIT", "optional": true }, @@ -624,11 +625,14 @@ } }, "node_modules/@eslint/core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", - "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -658,9 +662,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", - "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, "license": "MIT", "engines": { @@ -678,12 +682,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", - "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, "license": "Apache-2.0", "dependencies": { + "@eslint/core": "^0.10.0", "levn": "^0.4.1" }, "engines": { @@ -707,9 +712,9 @@ "license": "Apache-2.0" }, "node_modules/@exceptionless/fetchclient": { - "version": "0.36.0", - "resolved": "https://registry.npmjs.org/@exceptionless/fetchclient/-/fetchclient-0.36.0.tgz", - "integrity": "sha512-/zjChNmPC5iS0kVnyaa+LckfE+5psOohwhRL2n440YEOPfkReWctYWVMAHyMhPHCsd9oceblOZ4PUQ7Ahvnisw==", + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@exceptionless/fetchclient/-/fetchclient-0.40.0.tgz", + "integrity": "sha512-hWFiSkLSW03YGdQOSSL6EhH/MyI+vF9d+MkOxkFbrE5hQP+/517q9lqrh8yTfIfJiJX9CvtY7MzZ7/p8ieTYLA==", "license": "Apache-2.0" }, "node_modules/@exodus/schemasafe": { @@ -852,9 +857,9 @@ } }, "node_modules/@iconify-json/lucide": { - "version": "1.2.22", - "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.22.tgz", - "integrity": "sha512-sHRN/UFVTPTKCA9dVdO34OydvAf5d3CmT16a/U2+VzogI1uIsBXoYILU5oHGFMMq12aMJ65zgr1YOJCI0glxeg==", + "version": "1.2.25", + "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.25.tgz", + "integrity": "sha512-OsHihLfqdjxwoLWDEnGesrYbCG6VCCoLvmb1U6UJhggsppW+D3DUY/LhhcppZM4Yw3AM4USDIn/gkzqjdRYgEw==", "dev": true, "license": "ISC", "dependencies": { @@ -862,9 +867,9 @@ } }, "node_modules/@iconify-json/mdi": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@iconify-json/mdi/-/mdi-1.2.2.tgz", - "integrity": "sha512-84aznJXzfGdbOXGe8xB7E5uNAb7Yo5IABwTgq2X3kczb819qZeS9eL31bTVn7wJdCLK5ieaoUc2GTS3QYIkJ6g==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@iconify-json/mdi/-/mdi-1.2.3.tgz", + "integrity": "sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg==", "license": "Apache-2.0", "dependencies": { "@iconify/types": "*" @@ -1037,13 +1042,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz", - "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.0.tgz", + "integrity": "sha512-ZGNXbt+d65EGjBORQHuYKj+XhCewlwpnSd/EDuLPZGSiEWmgOJB5RmMCCYGy5aMfTs9wx61RivfDKi8H/hcMvw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.1" + "playwright": "1.50.0" }, "bin": { "playwright": "cli.js" @@ -1059,9 +1064,9 @@ "license": "MIT" }, "node_modules/@poppinss/macroable": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@poppinss/macroable/-/macroable-1.0.3.tgz", - "integrity": "sha512-B4iV6QxW//Fn17+qF1EMZRmoThIUJlCtcO85yoRDJnMyHeAthjz4ig9OTkfGGXKtQhcdPX0me75gU5K9J897+w==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@poppinss/macroable/-/macroable-1.0.4.tgz", + "integrity": "sha512-ct43jurbe7lsUX5eIrj4ijO3j/6zIPp7CDnFWXDs7UPAbw1Pu1iH3oAmFdP4jcskKJBURH5M9oTtyeiUXyHX8Q==", "license": "MIT", "optional": true, "engines": { @@ -1327,9 +1332,9 @@ "optional": true }, "node_modules/@sinclair/typebox": { - "version": "0.34.12", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.12.tgz", - "integrity": "sha512-tNc3Z7OUqcneO14tYyUH2QMdvC2c5sQOY0+SDw70aZix7Qi4GkaOQc22LfaVFPn64enKU5ggV2ryLWykeMGEog==", + "version": "0.34.14", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.14.tgz", + "integrity": "sha512-TJ7Al17j3+by5y2QkTLcF/oBVMbgXBhILVgi9PuwpxQVZZvGh5BFRzWbJPmZVNKpbRLjuMzFuRwR+tdFPqCkvA==", "license": "MIT", "optional": true }, @@ -1344,24 +1349,22 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.15.2", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.15.2.tgz", - "integrity": "sha512-p208T1kdM6zd8k4YXIUM60pLWQ8dZqehXSiqn4NulXHyHibX53uIAL2xtNL8GjxX2IVPqPRT978MwVYhCKExdQ==", - "hasInstallScript": true, + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.16.1.tgz", + "integrity": "sha512-2pF5sgGJx9brYZ/9nNDYnh5KX0JguPF14dnvvtf/MqrvlWrDj/e7Rk3LBJPecFLLK1GRs6ZniD24gFPqZm/NFw==", "license": "MIT", "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", - "esm-env": "^1.2.1", + "esm-env": "^1.2.2", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", - "sirv": "^3.0.0", - "tiny-glob": "^0.2.9" + "sirv": "^3.0.0" }, "bin": { "svelte-kit": "svelte-kit.js" @@ -1539,9 +1542,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", - "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", + "version": "22.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.12.0.tgz", + "integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -1600,17 +1603,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.1.tgz", - "integrity": "sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.22.0.tgz", + "integrity": "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.19.1", - "@typescript-eslint/type-utils": "8.19.1", - "@typescript-eslint/utils": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/type-utils": "8.22.0", + "@typescript-eslint/utils": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1630,16 +1633,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.1.tgz", - "integrity": "sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.22.0.tgz", + "integrity": "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.19.1", - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/typescript-estree": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4" }, "engines": { @@ -1655,14 +1658,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.1.tgz", - "integrity": "sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1673,14 +1676,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.1.tgz", - "integrity": "sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.22.0.tgz", + "integrity": "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.19.1", - "@typescript-eslint/utils": "8.19.1", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/utils": "8.22.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, @@ -1697,9 +1700,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.1.tgz", - "integrity": "sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "dev": true, "license": "MIT", "engines": { @@ -1711,14 +1714,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.1.tgz", - "integrity": "sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1764,16 +1767,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.1.tgz", - "integrity": "sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", + "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.19.1", - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/typescript-estree": "8.19.1" + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1788,13 +1791,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.1.tgz", - "integrity": "sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1806,9 +1809,9 @@ } }, "node_modules/@vinejs/compiler": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@vinejs/compiler/-/compiler-2.5.1.tgz", - "integrity": "sha512-efiO/SCQSMCqz6LDZTI4R3Ceq1ik3K2IqefEbbch+ko4dZncaYmQWJpX/fXVwgmO78jTZuerzD4I2WphPJUCwg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vinejs/compiler/-/compiler-3.0.0.tgz", + "integrity": "sha512-v9Lsv59nR56+bmy2p0+czjZxsLHwaibJ+SV5iK9JJfehlJMa501jUJQqqz4X/OqKXrxtE3uTQmSqjUqzF3B2mw==", "license": "MIT", "optional": true, "engines": { @@ -1816,51 +1819,51 @@ } }, "node_modules/@vinejs/vine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vinejs/vine/-/vine-2.1.0.tgz", - "integrity": "sha512-09aJ2OauxpblqiNqd8qC9RAzzm5SV6fTqZhE4e25j4cM7fmNoXRTjM7Oo8llFADMO4eSA44HqYEO3mkRRYdbYw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vinejs/vine/-/vine-3.0.0.tgz", + "integrity": "sha512-GeCAHLzKkL2kMFqatgqyiiNh+FILOSAV8x8imBDo6AWQ91w30Kaxw4FnzUDqgcd9z8aCYOBQ7RJxBBGfyr+USQ==", "license": "MIT", "optional": true, "dependencies": { - "@poppinss/macroable": "^1.0.2", - "@types/validator": "^13.11.9", - "@vinejs/compiler": "^2.5.0", + "@poppinss/macroable": "^1.0.3", + "@types/validator": "^13.12.2", + "@vinejs/compiler": "^3.0.0", "camelcase": "^8.0.0", - "dayjs": "^1.11.11", + "dayjs": "^1.11.13", "dlv": "^1.1.3", "normalize-url": "^8.0.1", - "validator": "^13.11.0" + "validator": "^13.12.0" }, "engines": { "node": ">=18.16.0" } }, "node_modules/@vitest/expect": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.6.tgz", - "integrity": "sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.4.tgz", + "integrity": "sha512-Nm5kJmYw6P2BxhJPkO3eKKhGYKRsnqJqf+r0yOGRKpEP+bSCBDsjXgiu1/5QFrnPMEgzfC38ZEjvCFgaNBC0Eg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.6", - "@vitest/utils": "2.1.6", + "@vitest/spy": "3.0.4", + "@vitest/utils": "3.0.4", "chai": "^5.1.2", - "tinyrainbow": "^1.2.0" + "tinyrainbow": "^2.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.6.tgz", - "integrity": "sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.4.tgz", + "integrity": "sha512-gEef35vKafJlfQbnyOXZ0Gcr9IBUsMTyTLXsEQwuyYAerpHqvXhzdBnDFuHLpFqth3F7b6BaFr4qV/Cs1ULx5A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.6", + "@vitest/spy": "3.0.4", "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" + "magic-string": "^0.30.17" }, "funding": { "url": "https://opencollective.com/vitest" @@ -1879,64 +1882,65 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz", - "integrity": "sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.4.tgz", + "integrity": "sha512-ts0fba+dEhK2aC9PFuZ9LTpULHpY/nd6jhAQ5IMU7Gaj7crPCTdCFfgvXxruRBLFS+MLraicCuFXxISEq8C93g==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^1.2.0" + "tinyrainbow": "^2.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.6.tgz", - "integrity": "sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.4.tgz", + "integrity": "sha512-dKHzTQ7n9sExAcWH/0sh1elVgwc7OJ2lMOBrAm73J7AH6Pf9T12Zh3lNE1TETZaqrWFXtLlx3NVrLRb5hCK+iw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.6", - "pathe": "^1.1.2" + "@vitest/utils": "3.0.4", + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/runner/node_modules/pathe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", + "dev": true, + "license": "MIT" + }, "node_modules/@vitest/snapshot": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.6.tgz", - "integrity": "sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.4.tgz", + "integrity": "sha512-+p5knMLwIk7lTQkM3NonZ9zBewzVp9EVkVpvNta0/PlFWpiqLaRcF4+33L1it3uRUCh0BGLOaXPPGEjNKfWb4w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.6", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" + "@vitest/pretty-format": "3.0.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.6.tgz", - "integrity": "sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==", + "node_modules/@vitest/snapshot/node_modules/pathe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } + "license": "MIT" }, "node_modules/@vitest/spy": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.6.tgz", - "integrity": "sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.4.tgz", + "integrity": "sha512-sXIMF0oauYyUy2hN49VFTYodzEAu744MmGcPR3ZBsPM20G+1/cSW/n1U+3Yu/zHxX2bIDe1oJASOkml+osTU6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1947,28 +1951,15 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.6.tgz", - "integrity": "sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.4.tgz", + "integrity": "sha512-8BqC1ksYsHtbWH+DfpOAKrFw3jl3Uf9J7yeFh85Pz52IWuh1hBBtyfEbRNNZNjl8H8A5yMLH9/t+k7HIKzQcZQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.6", + "@vitest/pretty-format": "3.0.4", "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils/node_modules/@vitest/pretty-format": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.6.tgz", - "integrity": "sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^1.2.0" + "tinyrainbow": "^2.0.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2091,14 +2082,14 @@ } }, "node_modules/arktype": { - "version": "2.0.0-rc.26", - "resolved": "https://registry.npmjs.org/arktype/-/arktype-2.0.0-rc.26.tgz", - "integrity": "sha512-OdV40SQNY0CFJH+anT0N7Go9Tl+av+hxzMGPccv47sPHdekZuEPd61MfNmwn1J5H2SIrycdwGPD8jYBZSkhKjQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arktype/-/arktype-2.0.0.tgz", + "integrity": "sha512-LVuXndcKO+zB7Hg9laGJmXYD5BZYhm/cUFL5pgB/75/3sGnvN8fsQ/yuBlf4JSn90g4rOoU7+9aTvdn5lToWOg==", "license": "MIT", "optional": true, "dependencies": { - "@ark/schema": "0.26.0", - "@ark/util": "0.26.0" + "@ark/schema": "0.35.0", + "@ark/util": "0.35.0" } }, "node_modules/array-buffer-byte-length": { @@ -2233,9 +2224,9 @@ } }, "node_modules/bits-ui": { - "version": "1.0.0-next.77", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-1.0.0-next.77.tgz", - "integrity": "sha512-IV0AyVEvsRkXv4s/fl4iea5E9W2b9EBf98s9mRMKMc1xHxM9MmtM2r6MZMqftHQ/c+gHTIt3A9EKuTlh7uay8w==", + "version": "1.0.0-next.78", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-1.0.0-next.78.tgz", + "integrity": "sha512-jZjG2ObZ/CNyCNaXecpItC7hRXqJAgEfMhr06/eNrf3wHiiPyhdcy4OkzLcJyxeOrDyj+xma8cZTd3JRWqJdAw==", "license": "MIT", "dependencies": { "@floating-ui/core": "^1.6.4", @@ -2896,13 +2887,13 @@ "license": "MIT" }, "node_modules/effect": { - "version": "3.11.8", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.11.8.tgz", - "integrity": "sha512-N16cwqUDqG7lyYiFyt+in0+OS0Lg9pkMmGPSwxu2j9ZhRHI8S8D69+ffXX+afhl80r6syBSSkkIg/bYRjGGf7A==", + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.12.7.tgz", + "integrity": "sha512-BsDTgSjLbL12g0+vGn5xkOgOVhRSaR3VeHmjcUb0gLvpXACJ9OgmlfeH+/FaAZwM5+omIF3I/j1gC5KJrbK1Aw==", "license": "MIT", "optional": true, "dependencies": { - "fast-check": "^3.21.0" + "fast-check": "^3.23.1" } }, "node_modules/electron-to-chromium": { @@ -3032,9 +3023,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", "dev": true, "license": "MIT" }, @@ -3179,19 +3170,19 @@ } }, "node_modules/eslint": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", - "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", + "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.17.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/js": "9.19.0", + "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", @@ -3255,27 +3246,27 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.1.tgz", + "integrity": "sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==", "dev": true, "license": "MIT", "bin": { - "eslint-config-prettier": "bin/cli.js" + "eslint-config-prettier": "build/bin/cli.js" }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-plugin-perfectionist": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.6.0.tgz", - "integrity": "sha512-kOswTebUK0LlYExRwqz7YQtvyTUIRsKfp8XrwBBeHGh2e8MBOS6K+7VvG6HpmNckyKySi1I96uPeAlptMFGcRQ==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.7.0.tgz", + "integrity": "sha512-e2ODzm2SsAztFWY3ZRJd1K702vyl8Sapacjc3JluOW294CfA3+jfjin+UxjcrK48EvlNIMOp+JJB9N54YR2LRw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.19.0", - "@typescript-eslint/utils": "^8.19.0", + "@typescript-eslint/types": "^8.21.0", + "@typescript-eslint/utils": "^8.21.0", "natural-orderby": "^5.0.0" }, "engines": { @@ -3351,9 +3342,9 @@ } }, "node_modules/esm-env": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz", - "integrity": "sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", "license": "MIT" }, "node_modules/espree": { @@ -3388,9 +3379,9 @@ } }, "node_modules/esrap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.3.2.tgz", - "integrity": "sha512-C4PXusxYhFT98GjLSmb20k9PREuUdporer50dhzGuJu9IJXktbMddVCMLAERl5dAHyAi73GWWCE4FVHGP1794g==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.3.tgz", + "integrity": "sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -3875,18 +3866,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "license": "MIT" - }, - "node_modules/globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "license": "MIT" - }, "node_modules/gopd": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.1.0.tgz", @@ -4768,18 +4747,18 @@ "license": "ISC" }, "node_modules/lucide-svelte": { - "version": "0.471.0", - "resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.471.0.tgz", - "integrity": "sha512-z+C6G2K089iDGbl8HzTdD5G6i5BvuaBxdIPQDa650Kb8TXBJRODa7YfmaIHy78+Y+YaB75N0lzUIQEclzflJrQ==", + "version": "0.474.0", + "resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.474.0.tgz", + "integrity": "sha512-yOSqjXPoEDOXCceBIfDaed6RinOvhp03ShiTXH6O+vlXE/NsyjQpktL8gm2vGDxi9d81HMuPFN1dwhVURh6mGg==", "license": "ISC", "peerDependencies": { "svelte": "^3 || ^4 || ^5.0.0-next.42" } }, "node_modules/magic-string": { - "version": "0.30.15", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.15.tgz", - "integrity": "sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" @@ -4857,9 +4836,9 @@ } }, "node_modules/mode-watcher": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-0.5.0.tgz", - "integrity": "sha512-5E6fh/aXhAVv+U+DbeM0hCmskQE9u7WSmvnCRijJB/MJu7HtB73sjiCaZ9n1M8QHmzLrBFo8XBAUcWXkDm8Z9A==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-0.5.1.tgz", + "integrity": "sha512-adEC6T7TMX/kzQlaO/MtiQOSFekZfQu4MC+lXyoceQG+U5sKpJWZ4yKXqw846ExIuWJgedkOIPqAYYRk/xHm+w==", "license": "MIT", "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.1" @@ -5635,13 +5614,13 @@ } }, "node_modules/playwright": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", - "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.0.tgz", + "integrity": "sha512-+GinGfGTrd2IfX1TA4N2gNmeIksSb+IAe589ZH+FlmpV3MYTx6+buChGIuDLQwrGNCw2lWibqV50fU510N7S+w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.1" + "playwright-core": "1.50.0" }, "bin": { "playwright": "cli.js" @@ -5654,9 +5633,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", - "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.0.tgz", + "integrity": "sha512-CXkSSlr4JaZs2tZHI40DsZUN/NIwgaUPsyLuOAaIZp2CyF2sN5MM5NJsyB188lFSSozFxQ5fPT4qM+f0tH/6wQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5677,9 +5656,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", "funding": [ { "type": "opencollective", @@ -5696,7 +5675,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5895,9 +5874,9 @@ } }, "node_modules/prettier-plugin-svelte": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.2.tgz", - "integrity": "sha512-kRPjH8wSj2iu+dO+XaUv4vD8qr5mdDmlak3IT/7AOgGIMRG86z/EHOLauFcClKEnOUf4A4nOA7sre5KrJD4Raw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.3.tgz", + "integrity": "sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5906,9 +5885,9 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.9.tgz", - "integrity": "sha512-r0i3uhaZAXYP0At5xGfJH876W3HHGHDp+LCRUJrs57PBeQ6mYHMwr25KH8NPX44F2yGTvdnH7OqCshlQx183Eg==", + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.11.tgz", + "integrity": "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA==", "dev": true, "license": "MIT", "engines": { @@ -5919,7 +5898,7 @@ "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", - "@zackad/prettier-plugin-twig-melody": "*", + "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", @@ -5946,7 +5925,7 @@ "@trivago/prettier-plugin-sort-imports": { "optional": true }, - "@zackad/prettier-plugin-twig-melody": { + "@zackad/prettier-plugin-twig": { "optional": true }, "prettier-plugin-astro": { @@ -6266,9 +6245,9 @@ } }, "node_modules/runed": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.23.0.tgz", - "integrity": "sha512-WrZcFneb3CkFvujgss6WIvKmlSUvX2z8nYsH+zrd8eo55zO6nkEJ6fRL2QZW+2lAD4DVvAK/8x0dotIRVrnPJQ==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/runed/-/runed-0.23.2.tgz", + "integrity": "sha512-AhHCb5/B+YQW6ar1pzhGQOQy+byfjCH63ofuhrexSWwQKhC0EbQ60Z/wMYwETLo3ZubhwlNryxBt0seOMOrVFQ==", "funding": [ "https://github.com/sponsors/huntabyte", "https://github.com/sponsors/tglide" @@ -6910,9 +6889,9 @@ } }, "node_modules/svelte": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.17.1.tgz", - "integrity": "sha512-HitqD0XhU9OEytPuux/XYzxle4+7D8+fIb1tHbwMzOtBzDZZO+ESEuwMbahJ/3JoklfmRPB/Gzp74L87Qrxfpw==", + "version": "5.19.6", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.19.6.tgz", + "integrity": "sha512-6ydekB3qyqUal+UhfMjmVOjRGtxysR8vuiMhi2nwuBtPJWnctVlsGspjVFB05qmR+TXI1emuqtZt81c0XiFleA==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -6924,7 +6903,7 @@ "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", - "esrap": "^1.3.2", + "esrap": "^1.4.3", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -6935,9 +6914,9 @@ } }, "node_modules/svelte-check": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.1.3.tgz", - "integrity": "sha512-IEMoQDH+TrPKwKeIyJim+PU8FxnzQMXsFHR/ldErkHpPXEGHCujHUXiR8jg6qDMqzsif5BbDOUFORltu87ex7g==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.1.4.tgz", + "integrity": "sha512-v0j7yLbT29MezzaQJPEDwksybTE2Ups9rUxEXy92T06TiA0cbqcO8wAOwNUVkFW6B0hsYHA+oAX3BS8b/2oHtw==", "dev": true, "license": "MIT", "dependencies": { @@ -7074,12 +7053,12 @@ } }, "node_modules/svelte-time": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/svelte-time/-/svelte-time-0.9.0.tgz", - "integrity": "sha512-XLEflTNZCjJM2ltCJL0NTpN9J2KBZXxupfl9S2sRFx+utSuQXbs3YIM14DIuENsjG1Qn5NtzRb0gviIB7lCMxQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/svelte-time/-/svelte-time-2.0.0.tgz", + "integrity": "sha512-sMPmIs2XifPXtBQ6CAObuthLcMOPuGJS8HYDkYLghcpkLZzMAKUC2Kf6uCFOnW9cGy6U47WcYhFnJQ0xYgjDIg==", "license": "MIT", "dependencies": { - "dayjs": "^1.11.10" + "dayjs": "^1.11.13" } }, "node_modules/svelte-toolbelt": { @@ -7117,10 +7096,20 @@ "svelte": "^5.7.0" } }, + "node_modules/sveltekit-search-params": { + "version": "4.0.0-next.0", + "resolved": "https://registry.npmjs.org/sveltekit-search-params/-/sveltekit-search-params-4.0.0-next.0.tgz", + "integrity": "sha512-haFr5seakusriPePAv2F5/lsOa37rr9AOGDa5JOZ9CaB0Vrl8V8PdtqNWfh/kF0jlANdkdqz5gKK66nhhHT8tg==", + "license": "MIT", + "peerDependencies": { + "@sveltejs/kit": "^2.0.0", + "svelte": "^5.0.0" + } + }, "node_modules/sveltekit-superforms": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/sveltekit-superforms/-/sveltekit-superforms-2.22.1.tgz", - "integrity": "sha512-SSePlvvEAo0eChLw1V9R1XdwwbE/XAOWTfzQOM01bFNT2IQGH5gy0wQkBffPKbDLZ7HYoRVao7spblTPBwyylA==", + "version": "2.23.1", + "resolved": "https://registry.npmjs.org/sveltekit-superforms/-/sveltekit-superforms-2.23.1.tgz", + "integrity": "sha512-SPj5ac4SMg8SPyP0Zi3ynwXJa7r9U1CTyn+YSyck67zLsjt367Sro4SZnl3yASrLd5kJ6Y57cgIdYJ2aWNArXw==", "funding": [ { "type": "github", @@ -7144,17 +7133,17 @@ "optionalDependencies": { "@exodus/schemasafe": "^1.3.0", "@gcornut/valibot-json-schema": "^0.31.0", - "@sinclair/typebox": "^0.34.11", + "@sinclair/typebox": "^0.34.14", "@typeschema/class-validator": "^0.3.0", - "@vinejs/vine": "^2.1.0", - "arktype": "2.0.0-rc.26", + "@vinejs/vine": "^3.0.0", + "arktype": "^2.0.0", "class-validator": "^0.14.1", - "effect": "^3.11.7", + "effect": "^3.12.5", "joi": "^17.13.3", "json-schema-to-ts": "^3.1.1", "superstruct": "^2.0.2", - "valibot": "^1.0.0-beta.9", - "yup": "^1.5.0", + "valibot": "1.0.0-beta.11", + "yup": "^1.6.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.1" }, @@ -7163,7 +7152,7 @@ "@sinclair/typebox": "^0.34.9", "@sveltejs/kit": "1.x || 2.x", "@typeschema/class-validator": "^0.3.0", - "@vinejs/vine": "^1.8.0 || ^2.0.0", + "@vinejs/vine": "^1.8.0 || ^2.0.0 || ^3.0.0", "arktype": ">=2.0.0-rc.23", "class-validator": "^0.14.1", "effect": "^3.10.0", @@ -7172,7 +7161,7 @@ "svelte": "3.x || 4.x || >=5.0.0-next.51", "valibot": ">=1.0.0-beta.3", "yup": "^1.4.0", - "zod": "^3.23.8" + "zod": "^3.24.1" }, "peerDependenciesMeta": { "@exodus/schemasafe": { @@ -7327,12 +7316,12 @@ } }, "node_modules/tailwind-variants": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-0.3.0.tgz", - "integrity": "sha512-ho2k5kn+LB1fT5XdNS3Clb96zieWxbStE9wNLK7D0AV64kdZMaYzAKo0fWl6fXLPY99ffF9oBJnIj5escEl/8A==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-0.3.1.tgz", + "integrity": "sha512-krn67M3FpPwElg4FsZrOQd0U26o7UDH/QOkK8RNaiCCrr052f6YJPBUfNKnPo/s/xRzNPtv1Mldlxsg8Tb46BQ==", "license": "MIT", "dependencies": { - "tailwind-merge": "^2.5.4" + "tailwind-merge": "2.5.4" }, "engines": { "node": ">=16.x", @@ -7342,6 +7331,16 @@ "tailwindcss": "*" } }, + "node_modules/tailwind-variants/node_modules/tailwind-merge": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz", + "integrity": "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", @@ -7520,16 +7519,6 @@ "license": "MIT", "optional": true }, - "node_modules/tiny-glob": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", - "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "license": "MIT", - "dependencies": { - "globalyzer": "0.1.0", - "globrex": "^0.1.2" - } - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -7538,9 +7527,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", - "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "license": "MIT" }, "node_modules/tinypool": { @@ -7554,9 +7543,9 @@ } }, "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", "engines": { @@ -7768,15 +7757,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.1.tgz", - "integrity": "sha512-LKPUQpdEMVOeKluHi8md7rwLcoXHhwvWp3x+sJkMuq3gGm9yaYJtPo8sRZSblMFJ5pcOGCAak/scKf1mvZDlQw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.22.0.tgz", + "integrity": "sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.19.1", - "@typescript-eslint/parser": "8.19.1", - "@typescript-eslint/utils": "8.19.1" + "@typescript-eslint/eslint-plugin": "8.22.0", + "@typescript-eslint/parser": "8.22.0", + "@typescript-eslint/utils": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7926,9 +7915,9 @@ "license": "MIT" }, "node_modules/valibot": { - "version": "1.0.0-beta.9", - "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0-beta.9.tgz", - "integrity": "sha512-yEX8gMAZ2R1yI2uwOO4NCtVnJQx36zn3vD0omzzj9FhcoblvPukENIiRZXKZwCnqSeV80bMm8wNiGhQ0S8fiww==", + "version": "1.0.0-beta.11", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0-beta.11.tgz", + "integrity": "sha512-Ztl5Iks1Ql7Z6CwkS5oyqguN3G8tmUiNlsHpqbDt6DLMpm+eu+n8Q7f921gI3uHvNZ8xDVkd4cEJP5t+lELOfw==", "license": "MIT", "optional": true, "peerDependencies": { @@ -7961,9 +7950,9 @@ } }, "node_modules/vite": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.7.tgz", - "integrity": "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", + "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", "license": "MIT", "dependencies": { "esbuild": "^0.24.2", @@ -8032,16 +8021,16 @@ } }, "node_modules/vite-node": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.6.tgz", - "integrity": "sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.4.tgz", + "integrity": "sha512-7JZKEzcYV2Nx3u6rlvN8qdo3QV7Fxyt6hx+CCKz9fbWxdX5IvUOmTWEAxMrWxaiSf7CKGLJQ5rFu8prb/jBjOA==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.7", - "es-module-lexer": "^1.5.4", - "pathe": "^1.1.2", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.2", "vite": "^5.0.0 || ^6.0.0" }, "bin": { @@ -8054,6 +8043,13 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite-node/node_modules/pathe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", + "dev": true, + "license": "MIT" + }, "node_modules/vite/node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -8087,31 +8083,31 @@ } }, "node_modules/vitest": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.6.tgz", - "integrity": "sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.4.tgz", + "integrity": "sha512-6XG8oTKy2gnJIFTHP6LD7ExFeNLxiTkK3CfMvT7IfR8IN+BYICCf0lXUQmX7i7JoxUP8QmeP4mTnWXgflu4yjw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "2.1.6", - "@vitest/mocker": "2.1.6", - "@vitest/pretty-format": "^2.1.6", - "@vitest/runner": "2.1.6", - "@vitest/snapshot": "2.1.6", - "@vitest/spy": "2.1.6", - "@vitest/utils": "2.1.6", + "@vitest/expect": "3.0.4", + "@vitest/mocker": "3.0.4", + "@vitest/pretty-format": "^3.0.4", + "@vitest/runner": "3.0.4", + "@vitest/snapshot": "3.0.4", + "@vitest/spy": "3.0.4", + "@vitest/utils": "3.0.4", "chai": "^5.1.2", - "debug": "^4.3.7", + "debug": "^4.4.0", "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", + "magic-string": "^0.30.17", + "pathe": "^2.0.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", + "tinyexec": "^0.3.2", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "2.1.6", + "vite-node": "3.0.4", "why-is-node-running": "^2.3.0" }, "bin": { @@ -8125,9 +8121,10 @@ }, "peerDependencies": { "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "2.1.6", - "@vitest/ui": "2.1.6", + "@vitest/browser": "3.0.4", + "@vitest/ui": "3.0.4", "happy-dom": "*", "jsdom": "*" }, @@ -8135,6 +8132,9 @@ "@edge-runtime/vm": { "optional": true }, + "@types/debug": { + "optional": true + }, "@types/node": { "optional": true }, @@ -8152,6 +8152,13 @@ } } }, + "node_modules/vitest/node_modules/pathe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", + "dev": true, + "license": "MIT" + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -8500,9 +8507,9 @@ } }, "node_modules/yup": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.5.0.tgz", - "integrity": "sha512-NJfBIHnp1QbqZwxcgl6irnDMIsb/7d1prNhFx02f1kp8h+orpi4xs3w90szNpOh68a/iHPdMsYvhZWoDmUvXBQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz", + "integrity": "sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==", "license": "MIT", "optional": true, "dependencies": { diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index 9d61deb036..ffd78e20c3 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -23,56 +23,57 @@ "upgrade": "ncu -i" }, "devDependencies": { - "@iconify-json/lucide": "^1.2.22", - "@playwright/test": "^1.49.1", + "@iconify-json/lucide": "^1.2.25", + "@playwright/test": "^1.50.0", "@sveltejs/adapter-static": "^3.0.8", - "@sveltejs/kit": "^2.15.2", + "@sveltejs/kit": "^2.16.1", "@sveltejs/vite-plugin-svelte": "^5.0.3", "@types/eslint": "^9.6.1", - "@types/node": "^22.10.5", + "@types/node": "^22.12.0", "@types/throttle-debounce": "^5.0.2", "autoprefixer": "^10.4.20", "cross-env": "^7.0.3", - "eslint": "^9.17.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-perfectionist": "^4.6.0", + "eslint": "^9.19.0", + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-perfectionist": "^4.7.0", "eslint-plugin-svelte": "^2.46.1", "npm-run-all": "^4.1.5", - "postcss": "^8.4.49", + "postcss": "^8.5.1", "prettier": "^3.4.2", - "prettier-plugin-svelte": "^3.3.2", - "prettier-plugin-tailwindcss": "^0.6.9", - "svelte": "^5.17.1", - "svelte-check": "^4.1.3", + "prettier-plugin-svelte": "^3.3.3", + "prettier-plugin-tailwindcss": "^0.6.11", + "svelte": "^5.19.6", + "svelte-check": "^4.1.4", "swagger-typescript-api": "^13.0.23", "tslib": "^2.8.1", "typescript": "^5.7.3", - "typescript-eslint": "^8.19.1", - "vite": "^6.0.7", - "vitest": "2.1.6" + "typescript-eslint": "^8.22.0", + "vite": "^6.0.11", + "vitest": "3.0.4" }, "dependencies": { "@exceptionless/browser": "^3.1.0", - "@exceptionless/fetchclient": "^0.36.0", - "@iconify-json/mdi": "^1.2.2", + "@exceptionless/fetchclient": "^0.40.0", + "@iconify-json/mdi": "^1.2.3", "@tanstack/svelte-query": "https://pkg.pr.new/@tanstack/svelte-query@28f98f9", "@tanstack/svelte-query-devtools": "https://pkg.pr.new/@tanstack/svelte-query-devtools@28f98f9", "@tanstack/svelte-table": "^9.0.0-alpha.10", "@typeschema/class-validator": "^0.3.0", - "bits-ui": "^1.0.0-next.77", + "bits-ui": "^1.0.0-next.78", "class-validator": "^0.14.1", "clsx": "^2.1.1", "formsnap": "^2.0.0", - "lucide-svelte": "^0.471.0", - "mode-watcher": "^0.5.0", + "lucide-svelte": "^0.474.0", + "mode-watcher": "^0.5.1", "oidc-client-ts": "^3.1.0", "pretty-ms": "^9.2.0", - "runed": "^0.23.0", + "runed": "^0.23.2", "svelte-sonner": "^0.3.28", - "svelte-time": "^0.9.0", - "sveltekit-superforms": "^2.22.1", + "svelte-time": "^2.0.0", + "sveltekit-search-params": "^4.0.0-next.0", + "sveltekit-superforms": "^2.23.1", "tailwind-merge": "^2.6.0", - "tailwind-variants": "^0.3.0", + "tailwind-variants": "^0.3.1", "tailwindcss": "^3.4.17", "tailwindcss-animate": "^1.0.7", "throttle-debounce": "^5.0.2", diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/auth/index.svelte.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/auth/index.svelte.ts index 01869a36b9..ed9cd0aa2c 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/auth/index.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/auth/index.svelte.ts @@ -1,9 +1,8 @@ import { goto } from '$app/navigation'; -import { page } from '$app/stores'; +import { page } from '$app/state'; import { env } from '$env/dynamic/public'; import { useFetchClient } from '@exceptionless/fetchclient'; import { PersistedState } from 'runed'; -import { get } from 'svelte/store'; import type { Login, TokenResult } from './models'; @@ -84,7 +83,7 @@ export async function googleLogin(redirectUrl?: string) { } export async function gotoLogin() { - const { url } = get(page); + const url = page.url; const isAuthPath = url.pathname.startsWith('/next/login') || url.pathname.startsWith('/next/logout'); const redirect = url.pathname === '/next/' || isAuthPath ? '/next/login' : `/next/login?redirect=${url.pathname}`; await goto(redirect, { replaceState: true }); diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/events-drawer.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/events-drawer.svelte index 8e750d65cb..cedd3b05b9 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/events-drawer.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/events-drawer.svelte @@ -1,14 +1,14 @@ diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-boolean-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/boolean-faceted-filter-trigger.svelte similarity index 92% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-boolean-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/boolean-faceted-filter-trigger.svelte index 31078b30f7..2c7cf9afe1 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-boolean-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/boolean-faceted-filter-trigger.svelte @@ -3,7 +3,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { BooleanFilter } from './filters.svelte'; + import { BooleanFilter } from './models.svelte'; type Props = AProps & { changed: (filter: BooleanFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/boolean-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/boolean-faceted-filter.svelte similarity index 60% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/boolean-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/boolean-faceted-filter.svelte index dcf9d262cb..f09de76261 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/boolean-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/boolean-faceted-filter.svelte @@ -1,14 +1,14 @@ - { filter.value = value; filterChanged(filter); @@ -19,4 +19,4 @@ }} value={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter-builder.svelte new file mode 100644 index 0000000000..f03561e2cd --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter-builder.svelte @@ -0,0 +1,27 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-date-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter-trigger.svelte similarity index 93% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-date-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter-trigger.svelte index 1249e3c09b..e905bbd6ed 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-date-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter-trigger.svelte @@ -3,7 +3,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { DateFilter } from './filters.svelte'; + import { DateFilter } from './models.svelte'; type Props = AProps & { changed: (filter: DateFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/date-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter.svelte similarity index 82% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/date-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter.svelte index 90f4f1d992..024c9d0617 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/date-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/date-faceted-filter.svelte @@ -1,9 +1,9 @@ - { filter.value = value; filterChanged(filter); @@ -45,4 +45,4 @@ {title} value={filter.value as string} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/helpers.ts similarity index 74% rename from src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters.ts rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/helpers.ts index 480438854f..e482a27402 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/helpers.ts @@ -1,4 +1,8 @@ -import { getKeywordFilter, getOrganizationFilter, getProjectFilter, getStackFilter, type IFilter } from '$comp/filters/filters.svelte'; +import type { IFilter } from '$comp/faceted-filter'; + +import { organization } from '$features/organizations/context.svelte'; + +import { getKeywordFilter, getProjectFilter, getStackFilter } from './models.svelte'; export function shouldRefreshPersistentEventChanged( filters: IFilter[], @@ -37,10 +41,7 @@ export function shouldRefreshPersistentEventChanged( } if (organization_id) { - const organizationFilter = getOrganizationFilter(filters); - if (organizationFilter && !organizationFilter.isEmpty()) { - return organizationFilter.value === organization_id; - } + return organization.current === organization_id; } return true; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/index.ts new file mode 100644 index 0000000000..8f0b912b93 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/index.ts @@ -0,0 +1,112 @@ +import BooleanFacetedFilterBuilder from './boolean-faceted-filter-builder.svelte'; +import BooleanFacetedFilterTrigger from './boolean-faceted-filter-trigger.svelte'; +import BooleanFacetedFilter from './boolean-faceted-filter.svelte'; +import DateFacetedFilterBuilder from './date-faceted-filter-builder.svelte'; +import DateFacetedFilterTrigger from './date-faceted-filter-trigger.svelte'; +import DateFacetedFilter from './date-faceted-filter.svelte'; +import KeywordFacetedFilterBuilder from './keyword-faceted-filter-builder.svelte'; +import KeywordFacetedFilter from './keyword-faceted-filter.svelte'; +export { + type BooleanFilter, + type DateFilter, + KeywordFilter, + type NumberFilter, + ProjectFilter, + ReferenceFilter, + SessionFilter, + StatusFilter, + type StringFilter, + TypeFilter, + type VersionFilter +} from './models.svelte'; +import NumberFacetedFilterBuilder from './number-faceted-filter-builder.svelte'; +import NumberFacetedFilterTrigger from './number-faceted-filter-trigger.svelte'; +import NumberFacetedFilter from './number-faceted-filter.svelte'; +import ProjectFacetedFilterBuilder from './project-faceted-filter-builder.svelte'; +import ProjectFacetedFilterTrigger from './project-faceted-filter-trigger.svelte'; +import ProjectFacetedFilter from './project-faceted-filter.svelte'; +import ReferenceFacetedFilterBuilder from './reference-faceted-filter-builder.svelte'; +import ReferenceFacetedFilterTrigger from './reference-faceted-filter-trigger.svelte'; +import ReferenceFacetedFilter from './reference-faceted-filter.svelte'; +import SessionFacetedFilterBuilder from './session-faceted-filter-builder.svelte'; +import SessionFacetedFilterTrigger from './session-faceted-filter-trigger.svelte'; +import SessionFacetedFilter from './session-faceted-filter.svelte'; +import StatusFacetedFilterBuilder from './status-faceted-filter-builder.svelte'; +import StatusFacetedFilterTrigger from './status-faceted-filter-trigger.svelte'; +import StatusFacetedFilter from './status-faceted-filter.svelte'; +import StringFacetedFilterBuilder from './string-faceted-filter-builder.svelte'; +import StringFacetedFilterTrigger from './string-faceted-filter-trigger.svelte'; +import StringFacetedFilter from './string-faceted-filter.svelte'; +import TypeFacetedFilterBuilder from './type-faceted-filter-builder.svelte'; +import TypeFacetedFilterTrigger from './type-faceted-filter-trigger.svelte'; +import TypeFacetedFilter from './type-faceted-filter.svelte'; +import VersionFacetedFilterBuilder from './version-faceted-filter-builder.svelte'; +import VersionFacetedFilterTrigger from './version-faceted-filter-trigger.svelte'; +import VersionFacetedFilter from './version-faceted-filter.svelte'; + +export { + BooleanFacetedFilter as Boolean, + BooleanFacetedFilterBuilder as BooleanBuilder, + BooleanFacetedFilter, + BooleanFacetedFilterBuilder, + BooleanFacetedFilterTrigger, + BooleanFacetedFilterTrigger as BooleanTrigger, + DateFacetedFilter as Date, + DateFacetedFilterBuilder as DateBuilder, + DateFacetedFilter, + DateFacetedFilterBuilder, + DateFacetedFilterTrigger, + DateFacetedFilterTrigger as DateTrigger, + KeywordFacetedFilter as Keyword, + KeywordFacetedFilterBuilder as KeywordBuilder, + KeywordFacetedFilter, + KeywordFacetedFilterBuilder, + NumberFacetedFilter as Number, + NumberFacetedFilterBuilder as NumberBuilder, + NumberFacetedFilter, + NumberFacetedFilterBuilder, + NumberFacetedFilterTrigger, + NumberFacetedFilterTrigger as NumberTrigger, + ProjectFacetedFilter as Project, + ProjectFacetedFilterBuilder as ProjectBuilder, + ProjectFacetedFilter, + ProjectFacetedFilterBuilder, + ProjectFacetedFilterTrigger, + ProjectFacetedFilterTrigger as ProjectTrigger, + ReferenceFacetedFilter as Reference, + ReferenceFacetedFilterBuilder as ReferenceBuilder, + ReferenceFacetedFilter, + ReferenceFacetedFilterBuilder, + ReferenceFacetedFilterTrigger, + ReferenceFacetedFilterTrigger as ReferenceTrigger, + SessionFacetedFilter as Session, + SessionFacetedFilterBuilder as SessionBuilder, + SessionFacetedFilter, + SessionFacetedFilterBuilder, + SessionFacetedFilterTrigger, + SessionFacetedFilterTrigger as SessionTrigger, + StatusFacetedFilter as Status, + StatusFacetedFilterBuilder as StatusBuilder, + StatusFacetedFilter, + StatusFacetedFilterBuilder, + StatusFacetedFilterTrigger, + StatusFacetedFilterTrigger as StatusTrigger, + StringFacetedFilter as String, + StringFacetedFilterBuilder as StringBuilder, + StringFacetedFilter, + StringFacetedFilterBuilder, + StringFacetedFilterTrigger, + StringFacetedFilterTrigger as StringTrigger, + TypeFacetedFilter as Type, + TypeFacetedFilterBuilder as TypeBuilder, + TypeFacetedFilter, + TypeFacetedFilterBuilder, + TypeFacetedFilterTrigger, + TypeFacetedFilterTrigger as TypeTrigger, + VersionFacetedFilter as Version, + VersionFacetedFilterBuilder as VersionBuilder, + VersionFacetedFilter, + VersionFacetedFilterBuilder, + VersionFacetedFilterTrigger, + VersionFacetedFilterTrigger as VersionTrigger +}; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/keyword-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/keyword-faceted-filter-builder.svelte new file mode 100644 index 0000000000..eb785e12b1 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/keyword-faceted-filter-builder.svelte @@ -0,0 +1,26 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/keyword-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/keyword-faceted-filter.svelte similarity index 62% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/keyword-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/keyword-faceted-filter.svelte index 329f5d055a..7fa08a1dd0 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/keyword-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/keyword-faceted-filter.svelte @@ -1,14 +1,14 @@ - { filter.value = value; filterChanged(filter); @@ -20,4 +20,4 @@ {title} value={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/filters.svelte.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/models.svelte.ts similarity index 69% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/filters.svelte.ts rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/models.svelte.ts index 83193f8875..8f38404ce9 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/filters.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/models.svelte.ts @@ -1,22 +1,16 @@ +import type { IFilter } from '$comp/faceted-filter'; import type { PersistentEventKnownTypes } from '$features/events/models'; import type { StackStatus } from '$features/stacks/models'; -export interface IFilter { - isEmpty(): boolean; - readonly key: string; - reset(): void; - toFilter(): string; - readonly type: string; -} - export class BooleanFilter implements IFilter { + public id: string = crypto.randomUUID(); public term = $state(); public type: string = 'boolean'; public value = $state(); public get key(): string { - return `${this.type}:${this.term}`; + return `${this.type}-${this.term}`; } constructor(term?: string, value?: boolean) { @@ -54,13 +48,14 @@ export class BooleanFilter implements IFilter { } export class DateFilter implements IFilter { + public id: string = crypto.randomUUID(); public term = $state(); public type: string = 'date'; public value = $state(); public get key(): string { - return `${this.type}:${this.term}`; + return `${this.type}-${this.term}`; } constructor(term?: string, value?: Date | string) { @@ -99,6 +94,7 @@ export class DateFilter implements IFilter { } export class KeywordFilter implements IFilter { + public id: string = crypto.randomUUID(); public type: string = 'keyword'; public value = $state(); @@ -136,13 +132,14 @@ export class KeywordFilter implements IFilter { } export class NumberFilter implements IFilter { + public id: string = crypto.randomUUID(); public term = $state(); public type: string = 'number'; public value = $state(); public get key(): string { - return `${this.type}:${this.term}`; + return `${this.type}-${this.term}`; } constructor(term?: string, value?: number) { @@ -179,44 +176,8 @@ export class NumberFilter implements IFilter { } } -export class OrganizationFilter implements IFilter { - public type: string = 'organization'; - public value = $state(); - - public get key(): string { - return this.type; - } - - constructor(value?: string) { - this.value = value; - } - - public isEmpty(): boolean { - return !this.value?.trim(); - } - - public reset(): void { - this.value = undefined; - } - - public toFilter(): string { - if (this.isEmpty()) { - return ''; - } - - return `organization:${this.value}`; - } - - public toJSON() { - return { - type: this.type, - value: this.value - }; - } -} - export class ProjectFilter implements IFilter { - public organization = $state(); + public id: string = crypto.randomUUID(); public type: string = 'project'; public value = $state([]); @@ -225,8 +186,7 @@ export class ProjectFilter implements IFilter { return this.type; } - constructor(organization: string | undefined, value: string[] = []) { - this.organization = organization; + constructor(value: string[] = []) { this.value = value; } @@ -252,7 +212,6 @@ export class ProjectFilter implements IFilter { public toJSON() { return { - organization: this.organization, type: this.type, value: this.value }; @@ -260,6 +219,7 @@ export class ProjectFilter implements IFilter { } export class ReferenceFilter implements IFilter { + public id: string = crypto.randomUUID(); public type: string = 'reference'; public value = $state(); @@ -297,6 +257,7 @@ export class ReferenceFilter implements IFilter { } export class SessionFilter implements IFilter { + public id: string = crypto.randomUUID(); public type: string = 'session'; public value = $state(); @@ -335,6 +296,7 @@ export class SessionFilter implements IFilter { } export class StatusFilter implements IFilter { + public id: string = crypto.randomUUID(); public type: string = 'status'; public value = $state([]); @@ -376,13 +338,14 @@ export class StatusFilter implements IFilter { } export class StringFilter implements IFilter { + public id: string = crypto.randomUUID(); public term = $state(); public type: string = 'string'; public value = $state(); public get key(): string { - return `${this.type}:${this.term}`; + return `${this.type}-${this.term}`; } constructor(term?: string, value?: string) { @@ -420,6 +383,7 @@ export class StringFilter implements IFilter { } export class TypeFilter implements IFilter { + public id: string = crypto.randomUUID(); public type: string = 'type'; public value = $state([]); @@ -461,13 +425,14 @@ export class TypeFilter implements IFilter { } export class VersionFilter implements IFilter { + public id: string = crypto.randomUUID(); public term = $state(); public type: string = 'version'; public value = $state(); public get key(): string { - return `${this.type}:${this.term}`; + return `${this.type}-${this.term}`; } constructor(term?: string, value?: string) { @@ -504,8 +469,13 @@ export class VersionFilter implements IFilter { } } -export function filterChanged(filters: IFilter[], updated: IFilter): IFilter[] { - return processFilterRules(setFilter(filters, updated), updated); +export function filterChanged(filters: IFilter[], addedOrUpdated: IFilter): IFilter[] { + const index = filters.findIndex((f) => f.id === addedOrUpdated.id); + if (index === -1) { + return processFilterRules([...filters, addedOrUpdated]); + } + + return processFilterRules([...filters.slice(0, index), addedOrUpdated, ...filters.slice(index + 1)]); } export const filterSerializer = { @@ -528,31 +498,13 @@ export const filterSerializer = { serialize: JSON.stringify }; -export function filterRemoved(filters: IFilter[], defaultFilters: IFilter[], removed?: IFilter): IFilter[] { +export function filterRemoved(filters: IFilter[], removed?: IFilter): IFilter[] { // If detail is undefined, remove all filters. if (!removed) { - return defaultFilters; - } else if (defaultFilters.find((f) => f.key === removed.key)) { - return processFilterRules(setFilter(filters, removed), removed); - } else { - return processFilterRules( - filters.filter((f) => f.key !== removed.key), - removed - ); + return []; } -} -export function getDefaultFilters(includeDateFilter = true): IFilter[] { - return [ - new OrganizationFilter(), - new ProjectFilter(undefined, []), - new StatusFilter([]), - new TypeFilter([]), - new DateFilter('date', 'last week'), - new ReferenceFilter(), - new SessionFilter(), - new KeywordFilter() - ].filter((f) => includeDateFilter || f.type !== 'date'); + return filters.filter((f) => f.id !== removed.id); } export function getFilter(filter: Omit & Record): IFilter | undefined { @@ -565,10 +517,8 @@ export function getFilter(filter: Omit f.type === 'keyword') as KeywordFilter; } -export function getOrganizationFilter(filters: IFilter[]): OrganizationFilter | undefined { - return filters.find((f) => f.type === 'organization') as OrganizationFilter; -} - export function getProjectFilter(filters: IFilter[]): ProjectFilter { return filters.find((f) => f.type === 'project') as ProjectFilter; } @@ -602,41 +548,6 @@ export function getStackFilter(filters: IFilter[]): StringFilter | undefined { return filters.find((f) => f.type === 'string') as StringFilter; } -export function processFilterRules(filters: IFilter[], changed?: IFilter): IFilter[] { - // Allow only one filter per type and term. - const groupedFilters: Partial> = Object.groupBy(filters, (f: IFilter) => f.key); - const filtered: IFilter[] = []; - Object.entries(groupedFilters).forEach(([, items]) => { - if (items && items.length > 0) { - filtered.push(items[0] as IFilter); - } - }); - - const projectFilter = filtered.find((f) => f.type === 'project') as ProjectFilter; - if (projectFilter) { - let organizationFilter = filtered.find((f) => f.type === 'organization') as OrganizationFilter; - - // If there is a project filter, verify the organization filter is set - if (!organizationFilter) { - organizationFilter = new OrganizationFilter(projectFilter.organization); - filtered.push(organizationFilter); - } - - // If the organization filter changes and organization is not set on the project filter, clear the project filter - if (changed?.type === 'organization' && projectFilter.organization !== organizationFilter.value) { - projectFilter.organization = organizationFilter.value; - projectFilter.value = []; - } - - // If the project filter changes and the organization filter is not set, set it - if (organizationFilter.value !== projectFilter.organization) { - organizationFilter.value = projectFilter.organization; - } - } - - return filtered; -} - export function quote(value?: null | string): string | undefined { return value ? `"${value}"` : undefined; } @@ -652,33 +563,6 @@ export function quoteIfSpecialCharacters(value?: null | string): null | string | return value; } -/** - * Mutates the given array of filters by adding or updating the specified filter. - * If a filter with the same key and term already exists, it will be updated with the new filter's value. - * If the filter does not exist, it will be added to the array. - * @param filters - The array of filters to be mutated. - * @param filter - The filter to be added or updated. - * @returns The mutated array of filters. - */ -export function setFilter(filters: IFilter[], filter: IFilter): IFilter[] { - const existingFilter = filters.find((f) => f.key === filter.key && ('term' in f && 'term' in filter ? f.term === filter.term : true)); - if (existingFilter) { - if ('value' in existingFilter && 'value' in filter) { - if (Array.isArray(existingFilter.value) && Array.isArray(filter.value)) { - existingFilter.value = [...new Set([...existingFilter.value, ...filter.value])]; - } else { - existingFilter.value = filter.value; - } - } else { - Object.assign(existingFilter, filter); - } - } else { - filters.push(filter); - } - - return filters; -} - export function toFilter(filters: IFilter[]): string { return filters .map((f) => f.toFilter()) @@ -686,3 +570,34 @@ export function toFilter(filters: IFilter[]): string { .join(' ') .trim(); } + +function processFilterRules(filters: IFilter[]): IFilter[] { + // 1. There can only be one date filter by term at a time. + // 2. There can only be one project filter. + + const uniqueFilters = new Map(); + for (const filter of filters) { + if (filter.type === 'project' || filter.type === 'date') { + const existingFilter = uniqueFilters.get(filter.key); + if (existingFilter) { + if ('value' in existingFilter && 'value' in filter) { + if (Array.isArray(existingFilter.value) && Array.isArray(filter.value)) { + existingFilter.value = [...new Set([...existingFilter.value, ...filter.value])]; + } else if (filter.value !== undefined) { + existingFilter.value = filter.value; + } + } else { + const { id, ...props } = filter; + console.trace(`Filter with key ${existingFilter.type} (${id}) already exists. Merging properties`); + Object.assign(existingFilter, props); + } + } + + uniqueFilters.set(filter.key, existingFilter ?? filter); + } else { + uniqueFilters.set(filter.id, filter); + } + } + + return Array.from(uniqueFilters.values()); +} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter-builder.svelte new file mode 100644 index 0000000000..fb4dd719dd --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter-builder.svelte @@ -0,0 +1,27 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-number-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter-trigger.svelte similarity index 92% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-number-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter-trigger.svelte index ed168b272e..65f17e38d2 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-number-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter-trigger.svelte @@ -3,7 +3,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { NumberFilter } from './filters.svelte'; + import { NumberFilter } from './models.svelte'; type Props = AProps & { changed: (filter: NumberFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/number-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter.svelte similarity index 60% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/number-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter.svelte index 64513b8339..1dcdc6bbd6 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/number-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/number-faceted-filter.svelte @@ -1,14 +1,14 @@ - { filter.value = value; filterChanged(filter); @@ -19,4 +19,4 @@ }} value={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/organization-defaults-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/organization-defaults-faceted-filter-builder.svelte new file mode 100644 index 0000000000..7df844cc93 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/organization-defaults-faceted-filter-builder.svelte @@ -0,0 +1,99 @@ + + +{#each eventsBooleanFilters as { priority, term, title }} + +{/each} +{#if includeDateFacets} + {#each eventsDateFilters as { priority, term, title }} + + {/each} +{/if} +{#each eventsGeoFilters as { priority, term, title }} + +{/each} +{#each eventsNumberFilters as { priority, term, title }} + +{/each} + + + + +{#each eventsStringFilters as { priority, term, title }} + +{/each} + +{#each eventsVersionFilters as { priority, term, title }} + +{/each} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter-builder.svelte new file mode 100644 index 0000000000..69987ddc2c --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter-builder.svelte @@ -0,0 +1,26 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-project-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter-trigger.svelte similarity index 69% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-project-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter-trigger.svelte index ef89088642..02dd898c36 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-project-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter-trigger.svelte @@ -3,19 +3,17 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { ProjectFilter } from './filters.svelte'; + import { ProjectFilter } from './models.svelte'; type Props = AProps & { changed: (filter: ProjectFilter) => void; - organization: string; value: string[]; }; - let { changed, class: className, organization, value, ...props }: Props = $props(); - + let { changed, class: className, value, ...props }: Props = $props(); const title = `Search project:${value}`; - changed(new ProjectFilter(organization, value))} {title} {...props}> + changed(new ProjectFilter(value))} {title} {...props}> {#snippet children()} {/snippet} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/project-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter.svelte similarity index 67% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/project-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter.svelte index eea3c90565..81257c8cbb 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/project-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/project-faceted-filter.svelte @@ -1,17 +1,19 @@ - { filter.value = values; filterChanged(filter); @@ -51,4 +53,4 @@ {title} values={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter-builder.svelte new file mode 100644 index 0000000000..48101fa2f3 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter-builder.svelte @@ -0,0 +1,26 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-reference-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter-trigger.svelte similarity index 92% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-reference-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter-trigger.svelte index ff643a1103..0e54166a62 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-reference-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter-trigger.svelte @@ -3,7 +3,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { ReferenceFilter } from './filters.svelte'; + import { ReferenceFilter } from './models.svelte'; type Props = AProps & { changed: (filter: ReferenceFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/reference-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter.svelte similarity index 62% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/reference-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter.svelte index 72eac65d29..566e9d28df 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/reference-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/reference-faceted-filter.svelte @@ -1,14 +1,14 @@ - { filter.value = value; filterChanged(filter); @@ -20,4 +20,4 @@ {title} value={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter-builder.svelte new file mode 100644 index 0000000000..b49d83101d --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter-builder.svelte @@ -0,0 +1,26 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-session-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter-trigger.svelte similarity index 92% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-session-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter-trigger.svelte index 60299933d0..46eb65aa15 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-session-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter-trigger.svelte @@ -3,7 +3,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { SessionFilter } from './filters.svelte'; + import { SessionFilter } from './models.svelte'; type Props = AProps & { changed: (filter: SessionFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/session-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter.svelte similarity index 62% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/session-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter.svelte index 690f75dd13..74ded071eb 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/session-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/session-faceted-filter.svelte @@ -1,14 +1,14 @@ - { filter.value = value; filterChanged(filter); @@ -20,4 +20,4 @@ {title} value={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter-builder.svelte new file mode 100644 index 0000000000..87806b5f15 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter-builder.svelte @@ -0,0 +1,26 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-status-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter-trigger.svelte similarity index 93% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-status-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter-trigger.svelte index de7717cfe5..6e65f900a7 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-status-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter-trigger.svelte @@ -5,7 +5,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { StatusFilter } from './filters.svelte'; + import { StatusFilter } from './models.svelte'; type Props = AProps & { changed: (filter: StatusFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/status-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter.svelte similarity index 69% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/status-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter.svelte index 415625e9ca..8f56681d2f 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/status-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/status-faceted-filter.svelte @@ -1,16 +1,16 @@ - { filter.value = values as StackStatus[]; filterChanged(filter); @@ -23,4 +23,4 @@ {title} values={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter-builder.svelte new file mode 100644 index 0000000000..7cb57e32e3 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter-builder.svelte @@ -0,0 +1,27 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-string-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter-trigger.svelte similarity index 93% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-string-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter-trigger.svelte index d7a83c9df5..7b3bb5a4b8 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-string-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter-trigger.svelte @@ -3,7 +3,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { StringFilter } from './filters.svelte'; + import { StringFilter } from './models.svelte'; type Props = AProps & { changed: (filter: StringFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/string-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter.svelte similarity index 60% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/string-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter.svelte index e9f69cf3bd..161c2ddc9e 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/string-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/string-faceted-filter.svelte @@ -1,14 +1,14 @@ - { filter.value = value; filterChanged(filter); @@ -19,4 +19,4 @@ }} value={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter-builder.svelte new file mode 100644 index 0000000000..df0bfa57a1 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter-builder.svelte @@ -0,0 +1,26 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-type-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter-trigger.svelte similarity index 92% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-type-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter-trigger.svelte index 2b0c7c55ac..78426cb20c 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-type-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter-trigger.svelte @@ -3,7 +3,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { TypeFilter } from './filters.svelte'; + import { TypeFilter } from './models.svelte'; type Props = AProps & { changed: (filter: TypeFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/type-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter.svelte similarity index 61% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/type-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter.svelte index 3594f934dc..2c1a39621f 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/type-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/type-faceted-filter.svelte @@ -1,16 +1,16 @@ - { + { filter.value = values; filterChanged(filter); }} @@ -22,4 +22,4 @@ {title} values={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter-builder.svelte new file mode 100644 index 0000000000..1a8eabbfda --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter-builder.svelte @@ -0,0 +1,27 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-version-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter-trigger.svelte similarity index 92% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-version-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter-trigger.svelte index 30264300af..29804cbde7 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-version-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter-trigger.svelte @@ -3,7 +3,7 @@ import { cn } from '$lib/utils'; import Filter from 'lucide-svelte/icons/filter'; - import { VersionFilter } from './filters.svelte'; + import { VersionFilter } from './models.svelte'; type Props = AProps & { changed: (filter: VersionFilter) => void; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/version-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter.svelte similarity index 60% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/version-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter.svelte index 9cbd984d8d..d352a618e4 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/version-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/filters/version-faceted-filter.svelte @@ -1,14 +1,14 @@ - { filter.value = value; filterChanged(filter); @@ -19,4 +19,4 @@ }} value={filter.value} {...props} -> +> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/Summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/Summary.svelte deleted file mode 100644 index 3c13b75464..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/Summary.svelte +++ /dev/null @@ -1,58 +0,0 @@ - - -{#if summary.template_key === 'event-summary'} - -{:else if summary.template_key === 'stack-summary'} - -{:else if summary.template_key === 'event-simple-summary'} - -{:else if summary.template_key === 'stack-simple-summary'} - -{:else if summary.template_key === 'event-error-summary'} - -{:else if summary.template_key === 'stack-error-summary'} - -{:else if summary.template_key === 'event-session-summary'} - -{:else if summary.template_key === 'stack-session-summary'} - -{:else if summary.template_key === 'event-notfound-summary'} - -{:else if summary.template_key === 'stack-notfound-summary'} - -{:else if summary.template_key === 'event-feature-summary'} - -{:else if summary.template_key === 'stack-feature-summary'} - -{:else if summary.template_key === 'event-log-summary'} - -{:else} - -{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Environment.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Environment.svelte deleted file mode 100644 index 1c71b6beca..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Environment.svelte +++ /dev/null @@ -1,132 +0,0 @@ - - - - - {#if environment.machine_name} - - Machine Name - - {environment.machine_name} - - {/if} - {#if environment.ip_address} - - IP Address - - {environment.ip_address} - - {/if} - {#if environment.processor_count} - - Processor Count - - - - {/if} - {#if environment.total_physical_memory} - - Total Memory - - - - {/if} - {#if environment.available_physical_memory} - - Available Memory - - - - {/if} - {#if environment.process_memory_size} - - Process Memory - - - - {/if} - {#if environment.o_s_name} - - OS Name - - {environment.o_s_name} - - {/if} - {#if environment.o_s_version} - - OS Version - - {environment.o_s_version} - - {/if} - {#if environment.architecture} - - Architecture - - {environment.architecture} - - {/if} - {#if environment.runtime_version} - - Runtime Version - - {environment.runtime_version} - - {/if} - {#if environment.process_id} - - Process ID - - {environment.process_id} - - {/if} - {#if environment.process_name} - - Process Name - - {environment.process_name} - - {/if} - {#if environment.command_line} - - Command Line - - {environment.command_line} - - {/if} - - - -{#if environment.data} -
- -
-{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte deleted file mode 100644 index be536660e2..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - Error Type - - {errorType} - - {#if message} - - Message - - {message} - - {/if} - {#if code} - - Code - - {code} - - {/if} - {#if submissionMethod} - - Submission Method - - {submissionMethod} - - {/if} - - -
-

Stack Trace

-
- -
-
-
- {#if event.data?.['@error']} - - {:else if event.data?.['@simple_error']} - - {/if} -
- -{#each errorData as ed} -
- -
-{/each} - -{#if modules.length} -
-

Modules

-
- - - - Name - Version - - - - {#each modules as module} - - {module.name} - {module.version} - - {/each} - -{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte deleted file mode 100644 index 2165ab602d..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte +++ /dev/null @@ -1,282 +0,0 @@ - - - - - {#if isSessionStart} - - Duration - - - - - {#if event.data?.sessionend} - (ended ) - {/if} - - - {/if} - {#if event.reference_id} - - {#if isSessionStart} - Session - - {:else} - Reference - - {/if} - {event.reference_id} - - {/if} - {#each references as reference (reference.id)} - - {#if reference.name === 'session'} - Session - - {:else} - {reference.name} - - {/if} - {reference.id} - - {/each} - {#if level} - - Level - - - - {/if} - {#if event.type !== 'error'} - - Event Type - - {event.type} - - {/if} - {#if hasError} - - Error Type - - {errorType} - - {/if} - {#if event.source} - - Source - - {event.source} - - {/if} - {#if !isSessionStart && event.value} - - Value - - {event.value} - - {/if} - {#if message} - - Message - - {message} - - {/if} - {#if version} - - Version - - {version} - - {/if} - {#if location} - - Geo - - {location} - - {/if} - {#if event.tags?.length} - - Tags - - - {#each event.tags as tag (tag)} - {tag} - {/each} - - - {/if} - {#if requestUrl} - - URL - - {requestUrl} - - {/if} - - - -{#if userEmail || userIdentity || userName || userDescription} -

User Info

- - - {#if userEmail} - - User Email - - {userEmail}
- - {/if} - {#if userIdentity} - - User Identity - - {userIdentity} - - {/if} - {#if userName} - - User Name - - {userName} - - {/if} - {#if userDescription} - - User Description - - {userDescription} - - {/if} - -{/if} - -{#if hasError} -
-

Stack Trace

-
- -
-
-
- {#if event.data?.['@error']} - - {:else if event.data?.['@simple_error']} - - {/if} -
-{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Request.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Request.svelte deleted file mode 100644 index fe33fe94fa..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Request.svelte +++ /dev/null @@ -1,200 +0,0 @@ - - - - - {#if request.http_method} - - HTTP Method - - {request.http_method} - - {/if} - {#if requestUrl} - - URL - - {requestUrl} - - {:else if requestUrlPath} - - URL - - {requestUrlPath} - - {/if} - {#if request.referrer} - - Referrer - - {request.referrer} - - {/if} - {#if request.client_ip_address} - - Client IP Address - - {request.client_ip_address} - - {/if} - {#if request.user_agent} - - User Agent - - {request.user_agent} - - {/if} - {#if device} - - Device - - {device} - - {/if} - {#if browser} - - Browser - - {browser} - {#if browserMajorVersion}  - {browserVersion} - {/if} - - {/if} - {#if os} - - Browser OS - - {os} - {#if osMajorVersion}  - {osVersion} - {/if} - - {/if} - - - -{#if request.post_data} -
- -
-{/if} - -{#if hasHeaders} -

Headers

- - - - Name - Value - - - - {#each Object.entries(sortedHeaders) as [key, value] (key)} - - {key} - {value} - - {/each} - - -{/if} - -{#if hasCookies} -

Cookie Values

- - - - Name - Value - - - - {#each Object.entries(request.cookies || {}) as [key, value] (key)} - - {key} - {value} - - {/each} - - -{/if} - -{#if request.data} -
- -
-{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/environment.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/environment.svelte index 1c71b6beca..0389af689c 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/environment.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/environment.svelte @@ -1,10 +1,10 @@ - -{#if live} - -{:else} - -{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Loading.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Loading.svelte deleted file mode 100644 index 3c07cfa885..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Loading.svelte +++ /dev/null @@ -1,39 +0,0 @@ - - -
- - Loading... -
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Logo.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Logo.svelte deleted file mode 100644 index a70c3c9477..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/Logo.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - -Exceptionless Logo - diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/boolean-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-boolean.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/boolean-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-boolean.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder-context.svelte.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder-context.svelte.ts new file mode 100644 index 0000000000..0452ac73b6 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder-context.svelte.ts @@ -0,0 +1,14 @@ +import type { Component } from 'svelte'; + +import { SvelteMap } from 'svelte/reactivity'; + +import type { FacetedFilterProps, IFilter } from './models'; + +export interface FacetFilterBuilder { + component: Component>; + create: (filter?: TFilter) => TFilter; + priority: number; + title: string; +} + +export const builderContext = $state(new SvelteMap>()); diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder.svelte index cd1d12a0b4..744d97c941 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder.svelte @@ -1,35 +1,63 @@ @@ -77,8 +97,8 @@ No results found. - {#each facets as facet (facet.filter.key)} - onFacetSelected(facet)} value={facet.filter.key}>{facet.title} + {#each sortedBuilders as [key, builder]} + onFacetSelected(builder)} value={key}>{builder.title} {/each} @@ -86,7 +106,7 @@ - {#if visible.length > 0} + {#if facets.length > 0} Clear filters {/if} Close @@ -95,9 +115,11 @@ -{#each facets as facet (facet.filter.key)} - {#if isVisible(facet)} - {@const Facet = facet.component} - - {/if} +{#if children} + {@render children()} +{/if} + +{#each facets as facet (facet.filter.id)} + {@const Facet = facet.component} + {/each} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/drop-down-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-drop-down.svelte similarity index 98% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/drop-down-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-drop-down.svelte index f8de1dd0d1..478a365546 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/drop-down-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-drop-down.svelte @@ -60,7 +60,7 @@ return 1; } - var option = options.find((option) => option.value === value); + const option = options.find((option) => option.value === value); if (option?.label.toLowerCase().includes(search)) { return 1; } diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/keyword-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-keyword.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/keyword-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-keyword.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/multiselect-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-multi-select.svelte similarity index 98% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/multiselect-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-multi-select.svelte index a63a538aec..fba8b8ad35 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/multiselect-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-multi-select.svelte @@ -59,7 +59,7 @@ return 1; } - var option = options.find((option) => option.value === value); + const option = options.find((option) => option.value === value); if (option?.label.toLowerCase().includes(search)) { return 1; } diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/number-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-number.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/number-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-number.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/string-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-string.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/string-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-string.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/index.ts index 67d87950cf..d4ec0a5d57 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/index.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/index.ts @@ -1,19 +1,44 @@ +import type { FacetedFilterProps, IFilter } from './models'; + import Actions from './faceted-filter-actions.svelte'; import BadgeLoading from './faceted-filter-badge-loading.svelte'; import BadgeValue from './faceted-filter-badge-value.svelte'; import BadgeValues from './faceted-filter-badge-values.svelte'; +import Boolean from './faceted-filter-boolean.svelte'; +import { builderContext, type FacetFilterBuilder } from './faceted-filter-builder-context.svelte'; import Root from './faceted-filter-builder.svelte'; +import DropDown from './faceted-filter-drop-down.svelte'; +import Keyword from './faceted-filter-keyword.svelte'; +import MultiSelect from './faceted-filter-multi-select.svelte'; +import Number from './faceted-filter-number.svelte'; +import String from './faceted-filter-string.svelte'; +import { FacetedFilter } from './models'; export { Actions, BadgeLoading, BadgeValue, BadgeValues, + Boolean, + DropDown, Actions as FacetedFilterActions, BadgeLoading as FacetedFilterBadgeLoading, BadgeValue as FacetedFilterBadgeValue, BadgeValues as FacetedFilterBadgeValues, + Boolean as FacetedFilterBoolean, // Root as FacetedFilterBuilder, - Root + DropDown as FacetedFilterDropDown, + Keyword as FacetedFilterKeyword, + MultiSelect as FacetedFilterMultiSelect, + Number as FacetedFilterNumber, + String as FacetedFilterString, + Keyword, + MultiSelect, + Number, + Root, + String }; + +export { builderContext, FacetedFilter }; +export type { FacetedFilterProps, FacetFilterBuilder, IFilter }; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/models.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/models.ts new file mode 100644 index 0000000000..9e1e2b8e49 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/models.ts @@ -0,0 +1,27 @@ +import type { Component } from 'svelte'; + +export type FacetedFilterProps = { + filter: TFilter; + filterChanged: (filter: TFilter) => void; + filterRemoved: (filter: TFilter) => void; + open: boolean; + title: string; +}; + +export interface IFilter { + readonly id: string; + isEmpty(): boolean; + readonly key: string; + reset(): void; + toFilter(): string; + readonly type: string; +} + +export class FacetedFilter { + constructor( + public title: string, + public component: Component>, + public filter: TFilter, + public open: boolean = false + ) {} +} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-organization-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-organization-filter.svelte deleted file mode 100644 index 6de6844b45..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/clickable-organization-filter.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - - changed(new OrganizationFilter(value))} {title} {...props}> - {#snippet children()} - - {/snippet} - diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/index.ts deleted file mode 100644 index d686b87a71..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/index.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type { Component } from 'svelte'; - -import { - type BooleanFilter, - type DateFilter, - type IFilter, - KeywordFilter, - type NumberFilter, - OrganizationFilter, - ProjectFilter, - ReferenceFilter, - SessionFilter, - StatusFilter, - type StringFilter, - TypeFilter, - type VersionFilter -} from '../filters.svelte'; -import BooleanFacetedFilter from './boolean-faceted-filter.svelte'; -import DateFacetedFilter from './date-faceted-filter.svelte'; -import KeywordFacetedFilter from './keyword-faceted-filter.svelte'; -import NumberFacetedFilter from './number-faceted-filter.svelte'; -import OrganizationFacetedFilter from './organization-faceted-filter.svelte'; -import ProjectFacetedFilter from './project-faceted-filter.svelte'; -import ReferenceFacetedFilter from './reference-faceted-filter.svelte'; -import SessionFacetedFilter from './session-faceted-filter.svelte'; -import StatusFacetedFilter from './status-faceted-filter.svelte'; -import StringFacetedFilter from './string-faceted-filter.svelte'; -import TypeFacetedFilter from './type-faceted-filter.svelte'; -import VersionFacetedFilter from './version-faceted-filter.svelte'; - -export type FacetedFilterProps = { - filter: TFilter; - filterChanged: (filter: TFilter) => void; - filterRemoved: (filter: TFilter) => void; - open: boolean; - title: string; -}; - -export class FacetedFilter { - constructor( - public title: string, - public component: Component>, - public filter: TFilter, - public open: boolean = false - ) {} -} - -export function toFacetedFilters(filters: IFilter[]): FacetedFilter[] { - return filters.map((filter) => { - switch (filter.type) { - case 'boolean': { - const booleanFilter = filter as BooleanFilter; - return new FacetedFilter((booleanFilter.term as string) ?? 'Boolean', BooleanFacetedFilter, booleanFilter); - } - case 'date': { - const dateFilter = filter as DateFilter; - const title = dateFilter.term === 'date' ? 'Date Range' : (dateFilter.term ?? 'Date'); - return new FacetedFilter(title, DateFacetedFilter, dateFilter); - } - case 'keyword': { - return new FacetedFilter('Keyword', KeywordFacetedFilter, filter as KeywordFilter); - } - case 'number': { - const numberFilter = filter as NumberFilter; - return new FacetedFilter((numberFilter.term as string) ?? 'Number', NumberFacetedFilter, numberFilter); - } - case 'organization': { - return new FacetedFilter('Organization', OrganizationFacetedFilter, filter as OrganizationFilter); - } - case 'project': { - return new FacetedFilter('Project', ProjectFacetedFilter, filter as ProjectFilter); - } - case 'reference': { - return new FacetedFilter('Reference', ReferenceFacetedFilter, filter as ReferenceFilter); - } - case 'session': { - return new FacetedFilter('Session', SessionFacetedFilter, filter as SessionFilter); - } - case 'status': { - return new FacetedFilter('Status', StatusFacetedFilter, filter as StatusFilter); - } - case 'string': { - const stringFilter = filter as StringFilter; - return new FacetedFilter((stringFilter.term as string) ?? 'String', StringFacetedFilter, stringFilter); - } - case 'type': { - return new FacetedFilter('Type', TypeFacetedFilter, filter as TypeFilter); - } - case 'version': { - const versionFilter = filter as VersionFilter; - return new FacetedFilter((versionFilter.term as string) ?? 'Version', VersionFacetedFilter, versionFilter); - } - default: { - throw new Error(`Unknown filter type: ${filter.type}`); - } - } - }) as unknown as FacetedFilter[]; - // TODO: look into why unknown is required here. -} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/organization-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/organization-faceted-filter.svelte deleted file mode 100644 index f3517d3d32..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/organization-faceted-filter.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - - { - filter.value = value; - filterChanged(filter); - }} - loading={response.isLoading} - noOptionsText="No organizations found." - {options} - remove={() => { - filter.value = undefined; - filterRemoved(filter); - }} - {title} - value={filter.value} - {...props} -> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Bytes.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Bytes.svelte deleted file mode 100644 index ae57fe6ba4..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Bytes.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - -{#if !isNaN(parsedValue) && isFinite(parsedValue)} - {byteValueNumberFormatter.format(parsedValue)} -{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Duration.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Duration.svelte deleted file mode 100644 index 9a520cfe46..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Duration.svelte +++ /dev/null @@ -1,71 +0,0 @@ - - -{durationText} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Number.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Number.svelte deleted file mode 100644 index 143e197044..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Number.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - -{#if value !== null && !isNaN(value) && isFinite(value)} - {Intl.NumberFormat().format(value)} -{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Percentage.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Percentage.svelte deleted file mode 100644 index a1fbec8a33..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/formatters/Percentage.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - -{#if percent !== null && !isNaN(percent) && isFinite(percent)} - {Intl.NumberFormat(undefined, formatOptions).format(percent / 100)} -{:else} - {Intl.NumberFormat(undefined, formatOptions).format(0)} -{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Checkbox.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Checkbox.svelte deleted file mode 100644 index cd39cb0891..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Checkbox.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - -
- - -
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Switch.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Switch.svelte deleted file mode 100644 index e1ccc940bd..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/primitives/Switch.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - -
- - -
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.svelte deleted file mode 100644 index 566b78cb0a..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.svelte +++ /dev/null @@ -1,13 +0,0 @@ - - - - {#if children} - {@render children()} - {/if} - diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.ts deleted file mode 100644 index 10ea86bee2..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/A.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { HTMLAnchorAttributes } from 'svelte/elements'; - -import { tv, type VariantProps } from 'tailwind-variants'; - -export const variants = tv({ - base: 'underline-offset-4', - defaultVariants: { - variant: 'default' - }, - variants: { - variant: { - default: 'underline hover:text-primary', - ghost: 'no-underline hover:text-foreground', - navigation: 'text-muted-foreground no-underline hover:underline hover:text-foreground', - primary: 'text-primary hover:underline', - secondary: 'text-secondary-foreground hover:underline' - } - } -}); - -export type Props = HTMLAnchorAttributes & { - variant?: Variant; -}; -export type Variant = VariantProps['variant']; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Blockquote.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Blockquote.svelte deleted file mode 100644 index 1f1e351ba1..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Blockquote.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -
- {#if children} - {@render children()} - {/if} -
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Code.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Code.svelte deleted file mode 100644 index f7abb34acb..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Code.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - - {#if children} - {@render children()} - {/if} - diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H1.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H1.svelte deleted file mode 100644 index 6f768058ee..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H1.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

- {#if children} - {@render children()} - {/if} -

diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H2.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H2.svelte deleted file mode 100644 index 02233e2a2d..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H2.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

- {#if children} - {@render children()} - {/if} -

diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H3.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H3.svelte deleted file mode 100644 index dffd118eda..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H3.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

- {#if children} - {@render children()} - {/if} -

diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H4.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H4.svelte deleted file mode 100644 index a6935c9727..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/H4.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

- {#if children} - {@render children()} - {/if} -

diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Large.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Large.svelte deleted file mode 100644 index 63d47292c5..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Large.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -
- {#if children} - {@render children()} - {/if} -
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Lead.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Lead.svelte deleted file mode 100644 index 94fd974a9e..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Lead.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

- {#if children} - {@render children()} - {/if} -

diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/List.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/List.svelte deleted file mode 100644 index 4f0e05cf8a..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/List.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - - - -
    li]:mt-2', className)} {...props}> - {#each items as item} -
  • - {#if displayValue}{@render displayValue(item)}{:else}{item}{/if} -
  • - {/each} -
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Muted.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Muted.svelte deleted file mode 100644 index 859ebc41d0..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Muted.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

- {#if children} - {@render children()} - {/if} -

diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/P.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/P.svelte deleted file mode 100644 index 67a6415a47..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/P.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -

- {#if children} - {@render children()} - {/if} -

diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Small.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Small.svelte deleted file mode 100644 index 2ff7d1a3fe..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/typography/Small.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - - {#if children} - {@render children()} - {/if} - diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-action.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-action.svelte index 204e59e6df..de060ae74d 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-action.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-action.svelte @@ -1,6 +1,6 @@ + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-item.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-item.svelte new file mode 100644 index 0000000000..4e2a3ed861 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-item.svelte @@ -0,0 +1,16 @@ + + +
  • + {@render children?.()} +
  • diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-link.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-link.svelte new file mode 100644 index 0000000000..c6b10194bf --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-link.svelte @@ -0,0 +1,31 @@ + + +{#if child} + {@render child({ props: attrs })} +{:else} + + {@render children?.()} + +{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-list.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-list.svelte new file mode 100644 index 0000000000..77c4e327ff --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-list.svelte @@ -0,0 +1,23 @@ + + +
      + {@render children?.()} +
    diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-page.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-page.svelte new file mode 100644 index 0000000000..1db5a05739 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-page.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-separator.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-separator.svelte new file mode 100644 index 0000000000..e550e91a4e --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb-separator.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb.svelte new file mode 100644 index 0000000000..81d249f9bc --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/breadcrumb.svelte @@ -0,0 +1,15 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/index.ts new file mode 100644 index 0000000000..dc914ec345 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/breadcrumb/index.ts @@ -0,0 +1,25 @@ +import Root from "./breadcrumb.svelte"; +import Ellipsis from "./breadcrumb-ellipsis.svelte"; +import Item from "./breadcrumb-item.svelte"; +import Separator from "./breadcrumb-separator.svelte"; +import Link from "./breadcrumb-link.svelte"; +import List from "./breadcrumb-list.svelte"; +import Page from "./breadcrumb-page.svelte"; + +export { + Root, + Ellipsis, + Item, + Separator, + Link, + List, + Page, + // + Root as Breadcrumb, + Ellipsis as BreadcrumbEllipsis, + Item as BreadcrumbItem, + Separator as BreadcrumbSeparator, + Link as BreadcrumbLink, + List as BreadcrumbList, + Page as BreadcrumbPage, +}; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/collapsible/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/collapsible/index.ts new file mode 100644 index 0000000000..8e968f0aa4 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/collapsible/index.ts @@ -0,0 +1,15 @@ +import { Collapsible as CollapsiblePrimitive } from "bits-ui"; + +const Root: typeof CollapsiblePrimitive.Root = CollapsiblePrimitive.Root; +const Trigger: typeof CollapsiblePrimitive.Trigger = CollapsiblePrimitive.Trigger; +const Content: typeof CollapsiblePrimitive.Content = CollapsiblePrimitive.Content; + +export { + Root, + Content, + Trigger, + // + Root as Collapsible, + Content as CollapsibleContent, + Trigger as CollapsibleTrigger, +}; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/command/command-dialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/command/command-dialog.svelte index d99e35138c..8e7701a748 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/command/command-dialog.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/command/command-dialog.svelte @@ -6,7 +6,7 @@ } from "bits-ui"; import type { Snippet } from "svelte"; import Command from "./command.svelte"; - import * as Dialog from "$lib/features/shared/components/ui/dialog/index.js"; + import * as Dialog from "$comp/ui/dialog/index.js"; let { open = $bindable(false), diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/form/form-button.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/form/form-button.svelte index 9831ab0ea5..7268a4d1aa 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/form/form-button.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/form/form-button.svelte @@ -1,5 +1,5 @@ diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/form/form-label.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/form/form-label.svelte index dfa30ea9fb..5a42515705 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/form/form-label.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/form/form-label.svelte @@ -1,7 +1,7 @@ - - {@render children?.()} - +{#if shouldAnimate} + + {@render children?.()} + +{:else} + + {@render children?.()} + +{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/strings.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/strings.ts new file mode 100644 index 0000000000..65d617531b --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/strings.ts @@ -0,0 +1,19 @@ +export function getInitials(value: string | undefined, maxLength: number = 2, defaultValue: string = 'NA'): string { + if (!value) { + return defaultValue; + } + + const trimmedValue = value.trim(); + const initials = trimmedValue + .split(' ') + .map((v) => v.trim()) + .filter((v) => v.length > 0) + .map((v) => v[0]?.toLocaleUpperCase()) + .join(''); + + if (initials.length === 1 && trimmedValue.length > 1) { + return trimmedValue.substring(0, maxLength).toLocaleUpperCase(); + } + + return initials.length > maxLength ? initials.substring(0, maxLength) : initials; +} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/stack-card.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/stack-card.svelte index a0c8a6ce53..79ecf2e116 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/stack-card.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/stack-card.svelte @@ -1,7 +1,5 @@ - -
    - - -
    diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Navbar.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Navbar.svelte deleted file mode 100644 index dcf97a65c7..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Navbar.svelte +++ /dev/null @@ -1,127 +0,0 @@ - - - diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Sidebar.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Sidebar.svelte deleted file mode 100644 index e397cef23a..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/Sidebar.svelte +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - {#each dashboardRoutes as route (route.href)} - {@const Icon = route.icon} - - - {#snippet child({ props })} - - - {route.title} - - {/snippet} - - - {/each} - - - - - diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/navbar.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/navbar.svelte index dcf97a65c7..693909f825 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/navbar.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/navbar.svelte @@ -1,13 +1,9 @@ @@ -48,79 +43,6 @@ - - - - {#snippet children()} - - {/snippet} - - - My Account - - - Account - ⇧⌘P - - - - - Documentation - - - Documentation - Support - GitHub - API - - - - Sign out - ⇧⌘Q - - - diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-organization-switcher.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-organization-switcher.svelte new file mode 100644 index 0000000000..499b24b182 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-organization-switcher.svelte @@ -0,0 +1,98 @@ + + +{#if organizations && organizations.length > 1} + + + + + {#snippet child({ props })} + + + {getInitials(activeOrganization?.name)} + +
    + + {activeOrganization?.name} + + {activeOrganization?.plan_name} +
    + +
    + {/snippet} +
    + + Organizations + {#if organizations} + {#each organizations as organization, index (organization.name)} + onOrganizationSelected(organization)} + data-active={organization.id === selected} + class="gap-2 p-2 data-[active=true]:bg-accent data-[active=true]:text-accent-foreground" + > + + {getInitials(organization.name)} + + {organization.name} + ⌘{index + 1} + + {/each} + {/if} + + +
    + +
    +
    Add organization
    +
    +
    +
    +
    +
    +{:else if isLoading} + + + + + +
    + + +
    +
    +
    +
    +
    +{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte new file mode 100644 index 0000000000..9344bc48db --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte @@ -0,0 +1,150 @@ + + +{#if isLoading} + + + + +
    + + +
    +
    +
    +
    +{:else} + + + + + {#snippet child({ props })} + + + {#await gravatar.src} + {gravatar.initials} + {:then src} + + {/await} + {gravatar.initials} + +
    + {user?.full_name} + {user?.email_address} +
    + +
    + {/snippet} +
    + + +
    + + {#await gravatar.src} + {gravatar.initials} + {:then src} + + {/await} + {gravatar.initials} + +
    + {user?.full_name} + {user?.email_address} +
    +
    +
    + + + + + + Account + ⇧⌘ga + + + + + + + Help + + + + + Documentation + ⌘gw + + + + Support + ⌘gs + + + + GitHub + ⌘gg + + + + API Reference + + + + Keyboard shortcuts + ⌘K + + + + + + + Log out + ⇧⌘Q + +
    +
    +
    +
    +{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar.svelte index e397cef23a..0c97bd86b4 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar.svelte @@ -1,23 +1,32 @@ - - - + + + {#if header} + {@render header()} + {/if} + + + {#each dashboardRoutes as route (route.href)} {@const Icon = route.icon} @@ -36,4 +45,9 @@ + + {#if footer} + {@render footer()} + {/if} + diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/navigation-command.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/navigation-command.svelte index 1d397bb7a9..1376ed52a3 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/navigation-command.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/navigation-command.svelte @@ -27,7 +27,7 @@ {#each items as route (route.href)} - + {#if route.icon} {@const Icon = route.icon} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte index 9b875604af..2a7e076559 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte @@ -1,14 +1,16 @@ {#if isAuthenticated} - - + + + {#snippet header()} + + {/snippet} + + {#snippet footer()} + + {/snippet} +
    - {#key $page.url.pathname} + {#key page.url.pathname}
    {@render children()}
    {/key}
    - +
    {/if} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index 78c0f526bd..abaedabe51 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -4,13 +4,13 @@ import AutomaticRefreshIndicatorButton from '$comp/automatic-refresh-indicator-button.svelte'; import * as DataTable from '$comp/data-table'; import * as FacetedFilter from '$comp/faceted-filter'; - import { toFacetedFilters } from '$comp/filters/facets'; - import { DateFilter, filterChanged, filterRemoved, filterSerializer, getDefaultFilters, type IFilter, toFilter } from '$comp/filters/filters.svelte'; import { Button } from '$comp/ui/button'; import * as Card from '$comp/ui/card'; import * as Sheet from '$comp/ui/sheet'; import EventsDrawer from '$features/events/components/events-drawer.svelte'; - import { shouldRefreshPersistentEventChanged } from '$features/events/components/filters'; + import { shouldRefreshPersistentEventChanged } from '$features/events/components/filters/helpers'; + import { DateFilter, filterChanged, filterRemoved, toFilter } from '$features/events/components/filters/models.svelte'; + import OrganizationDefaultsFacetedFilterBuilder from '$features/events/components/filters/organization-defaults-faceted-filter-builder.svelte'; import EventsBulkActionsDropdownMenu from '$features/events/components/table/events-bulk-actions-dropdown-menu.svelte'; import EventsDataTable from '$features/events/components/table/events-data-table.svelte'; import { getTableContext } from '$features/events/components/table/options.svelte'; @@ -20,7 +20,8 @@ import { type FetchClientResponse, useFetchClient } from '@exceptionless/fetchclient'; import { createTable } from '@tanstack/svelte-table'; import ExternalLink from 'lucide-svelte/icons/external-link'; - import { PersistedState, useEventListener } from 'runed'; + import { useEventListener } from 'runed'; + import { queryParameters, ssp } from 'sveltekit-search-params'; import { throttle } from 'throttle-debounce'; let selectedEventId: null | string = $state(null); @@ -28,29 +29,32 @@ selectedEventId = row.id; } - const limit = new PersistedState('events.limit', 10); - const defaultFilters = getDefaultFilters(); - const persistedFilters = new PersistedState('events.filters', defaultFilters, { serializer: filterSerializer }); - persistedFilters.current.push(...defaultFilters.filter((df) => !persistedFilters.current.some((f) => f.key === df.key))); + // TODO: Default filters + const params = queryParameters({ filter: ssp.string(), limit: ssp.number(10), time: ssp.string() }); + let filters = $state([]); + const filter = $derived(toFilter(filters.filter((f) => f.type !== 'date'))); + const time = $derived((filters.find((f) => f.type === 'date') as DateFilter)?.value as string); - const filter = $derived(toFilter(persistedFilters.current.filter((f) => f.key !== 'date:date'))); - const facets = $derived(toFacetedFilters(persistedFilters.current)); - const time = $derived((persistedFilters.current.find((f) => f.key === 'date:date') as DateFilter).value as string); - - function onDrawerFilterChanged(filter: IFilter): void { - persistedFilters.current = filterChanged(persistedFilters.current, filter); + function onDrawerFilterChanged(added: FacetedFilter.IFilter): void { + filters = filterChanged(filters ?? [], added); + params.filter = filter; + params.time = time; selectedEventId = null; } - function onFilterChanged(filter: IFilter): void { - persistedFilters.current = filterChanged(persistedFilters.current, filter); + function onFilterChanged(addedOrUpdated: FacetedFilter.IFilter): void { + filters = filterChanged(filters ?? [], addedOrUpdated); + params.filter = filter; + params.time = time; } - function onFilterRemoved(filter?: IFilter): void { - persistedFilters.current = filterRemoved(persistedFilters.current, defaultFilters, filter); + function onFilterRemoved(removed?: FacetedFilter.IFilter): void { + filters = filterRemoved(filters ?? [], removed); + params.filter = filter; + params.time = time; } - const context = getTableContext>({ limit: limit.current, mode: 'summary' }); + const context = getTableContext>({ limit: params.limit, mode: 'summary' }); const table = createTable(context.options); const canRefresh = $derived(!table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected() && !table.getCanPreviousPage()); @@ -92,7 +96,7 @@ } // Do not refresh if the filter criteria doesn't match the web socket message. - if (!shouldRefreshPersistentEventChanged(persistedFilters.current, filter, message.organization_id, message.project_id, message.stack_id, message.id)) { + if (!shouldRefreshPersistentEventChanged(filters ?? [], filter, message.organization_id, message.project_id, message.stack_id, message.id)) { return; } @@ -119,9 +123,11 @@ - + {#snippet toolbarChildren()} - + + + {/snippet} {#snippet footerChildren()}
    @@ -130,7 +136,7 @@ {/if}
    - +
    diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/+layout.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/+layout.svelte index 0e5f259576..51a904bd71 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/+layout.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/+layout.svelte @@ -11,10 +11,10 @@ let { children } = $props(); - const userQuery = getMeQuery(); + const userResponse = getMeQuery(); let isAuthenticated = $derived(accessToken.current !== null); const filteredRoutes = $derived.by(() => { - const context: NavigationItemContext = { authenticated: isAuthenticated, user: userQuery.data }; + const context: NavigationItemContext = { authenticated: isAuthenticated, user: userResponse.data }; return routes.filter((route) => (route.show ? route.show(context) : true)); }); diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/manage/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/manage/+page.svelte index 1ec3e33671..d7ed33c147 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/manage/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/manage/+page.svelte @@ -1,6 +1,5 @@