From e09534ce9ded0410ad1b4f6000271559ebcc6609 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 20 Feb 2024 08:08:26 -0600 Subject: [PATCH 01/86] WIP - Dynamic Grid Filters prototype, need to move this to a builder type pattern like bits-ui. --- .../data-table-faceted-filter-builder.svelte | 97 +++++++++++++++++++ .../data-table-faceted-filter.svelte | 8 +- .../src/lib/components/data-table/index.ts | 3 + .../src/lib/components/filters/filters.ts | 15 ++- .../ClientApp/src/lib/stores/events.ts | 31 +++++- .../ClientApp/src/routes/(app)/+page.svelte | 38 ++++++-- 6 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte new file mode 100644 index 0000000000..ea88ab684e --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte @@ -0,0 +1,97 @@ + + + + + + + + + + + No results found. + + {#each options as option (option.value)} + +
+ +
+ + {option.label} + +
+ {/each} +
+ {#if values.length > 0} + + Clear filters + {/if} +
+
+
+
+ +{#each values as type (type)} + +{/each} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte index aab29dc734..7621b08334 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte @@ -18,6 +18,7 @@ export let values: unknown[] = []; export let options: Option[] = []; export let onValueChange: (facetKey: string, updatedValues: unknown[]) => void; + export let onRemoveFilter: (() => void) | undefined = undefined; let open = false; @@ -84,10 +85,15 @@ {/each} - {#if values.length > 0} + {#if values.length > 0 || onRemoveFilter} + {/if} + {#if values.length > 0} Clear filters {/if} + {#if onRemoveFilter} + Remove filter + {/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts index 33caf4941c..59f23407c7 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts @@ -1,6 +1,7 @@ import Root from './data-table.svelte'; import Body from './data-table-body.svelte'; import Toolbar from './data-table-toolbar.svelte'; +import FacetedFilterBuilder from './data-table-faceted-filter-builder.svelte'; import FacetedFilterContainer from './data-table-faceted-filter-container.svelte'; import FacetedFilter from './data-table-faceted-filter.svelte'; import PageSize from './data-table-page-size.svelte'; @@ -10,6 +11,7 @@ export { Root, Body, Toolbar, + FacetedFilterBuilder, FacetedFilterContainer, FacetedFilter, PageSize, @@ -18,6 +20,7 @@ export { Root as DataTable, Body as DataTableBody, Toolbar as DataTableToolbar, + FacetedFilterBuilder as DataTableFacetedFilterBuilder, FacetedFilterContainer as DataTableFacetedFilterContainer, FacetedFilter as DataTableFacetedFilter, PageSize as DataTablePageSize, diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts index 72716bc26e..411e4a66a4 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts @@ -219,6 +219,7 @@ export function toggleFilter(filters: IFilter[], filter: IFilter): IFilter[] { */ export function upsertOrRemoveFacetFilter(filters: IFilter[], filter: IFacetedFilter): boolean { const index = filters.findIndex((f) => f.type === filter.type && isFaceted(f)); + console.log('upsertOrRemoveFacetFilter', filter, index, filters); // If the filter has no values, remove it. if (!filter.values || filter.values.length == 0) { @@ -288,7 +289,7 @@ export function parseFilter(filters: IFilter[], input: string): IFilter[] { return resolvedFilters; } -export function getFilter(filter: Record): IFilter | undefined { +export function getFilter(filter: Omit & Record): IFilter | undefined { switch (filter.type) { case 'boolean': return new BooleanFilter(filter.term as string, filter.value as boolean); @@ -318,6 +319,18 @@ function isFaceted(filter: IFilter): filter is IFacetedFilter { } const FACETED_FILTER_TYPES = ['status', 'type']; +export function toFilterTypes(filters: IFilter[]): string[] { + const types = new Set(); + for (const filter of filters) { + if (isFaceted(filter)) { + types.add(filter.type); + } + } + + console.log(Array.from(types)); + return Array.from(types); +} + export function toFacetedValues(filters: IFilter[]): Record { const values: Record = {}; for (const filterType of FACETED_FILTER_TYPES) { diff --git a/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts b/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts index ef17bf32cd..a6a733f350 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts @@ -8,7 +8,8 @@ import { type IFacetedFilter, toggleFilter, parseFilter, - resetFacetedValues + resetFacetedValues, + toFilterTypes } from '$comp/filters/filters'; import { persisted } from 'svelte-local-storage-store'; import { derived, get } from 'svelte/store'; @@ -21,6 +22,18 @@ export const filter = derived(filters, ($filters) => toFilter($filters)); export const filterWithFaceted = derived(filters, ($filters) => toFilter($filters, true)); export const filterValues = derived(filters, ($filters) => toFacetedValues($filters)); +export const selectedFilterTypes = derived(filters, ($filters) => toFilterTypes($filters)); +export const filterOptions: { value: string; label: string }[] = [ + { + value: 'status', + label: 'Status' + }, + { + value: 'type', + label: 'Type' + } +]; + export function updateFilter(filter: IFilter) { filters.set(toggleFilter(get(filters), filter)); } @@ -28,8 +41,10 @@ export function updateFilter(filter: IFilter) { export function updateFilterValues(key: string, values: unknown[]) { const filter = getFilter({ type: key, values }) as IFacetedFilter; const currentFilters = get(filters); + console.log('updateFilterValues', filter, currentFilters); if (filter && upsertOrRemoveFacetFilter(currentFilters, filter)) { filters.set(currentFilters); + console.log('updateFilterValues', currentFilters); } } @@ -53,3 +68,17 @@ export function onFilterInputChanged(event: Event) { export function onFacetValuesChanged(facetKey: string, updatedValues: unknown[]) { updateFilterValues(facetKey, updatedValues); } + +export function onToggleFacetFilterChanged(facetKey: string) { + const currentFilters = get(filters); + const filter = currentFilters.find((f) => f.type === facetKey); + console.log( + facetKey, + currentFilters.find((f) => f.type === facetKey) + ); + if (filter) { + toggleFilter(currentFilters, filter); + } else { + updateFilter(currentFilters, getFilter({ type: facetKey })); + } +} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index 9993d33a22..89f616c44a 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -13,12 +13,15 @@ import CustomEventMessage from '$comp/messaging/CustomEventMessage.svelte'; import { filter, + filterOptions, filterValues, filterWithFaceted, onFacetValuesChanged, onFilterChanged, onFilterInputChanged, + onToggleFacetFilterChanged, resetFilterValues, + selectedFilterTypes, time } from '$lib/stores/events'; import DateRangeDropdown from '$comp/DateRangeDropdown.svelte'; @@ -41,16 +44,31 @@ - - - + + {#if type === 'status'} + console.log('onRemoveFilter')} + > + {:else if type === 'type'} + + {/if} + From b7a4e428d4767ec80a80e19794281e7302a5652a Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 24 Feb 2024 13:16:21 -0500 Subject: [PATCH 02/86] Fixed recommend vi test extension update --- src/Exceptionless.Web/ClientApp/.vscode/extensions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exceptionless.Web/ClientApp/.vscode/extensions.json b/src/Exceptionless.Web/ClientApp/.vscode/extensions.json index e50aa07750..80d8f0e1f8 100644 --- a/src/Exceptionless.Web/ClientApp/.vscode/extensions.json +++ b/src/Exceptionless.Web/ClientApp/.vscode/extensions.json @@ -6,6 +6,6 @@ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "selemondev.vscode-shadcn-svelte", - "zixuanchen.vitest-explorer" + "vitest.explorer" ] } From 882c8839eb7c4f12eae0489eab149354a0e5d04c Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 24 Feb 2024 13:17:48 -0500 Subject: [PATCH 03/86] Fixed login is authenticated checks --- src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts b/src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts index 1d37f6286c..d4efa5452f 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/api/auth.ts @@ -8,7 +8,13 @@ import { globalFetchClient } from './FetchClient'; import type { Login, TokenResult } from '$lib/models/api'; -export const accessToken = persisted('satellizer_token', null); +export const accessToken = persisted('satellizer_token', null, { + serializer: { + parse: (s) => (s === 'null' ? null : s), + stringify: (s) => s as string + } +}); + export const isAuthenticated = derived(accessToken, ($accessToken) => $accessToken !== null); export const enableAccountCreation = env.PUBLIC_ENABLE_ACCOUNT_CREATION === 'true'; export const facebookClientId = env.PUBLIC_FACEBOOK_APPID; From d9b0c78296a34a0bc409dfd6b967d8df8dbd2ba9 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 24 Feb 2024 13:18:02 -0500 Subject: [PATCH 04/86] Updated deps --- .../ClientApp/package-lock.json | 80 +++++++++---------- src/Exceptionless.Web/ClientApp/package.json | 10 +-- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index d29b9f58fd..5e0494a776 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -14,7 +14,7 @@ "@tanstack/svelte-query-devtools": "^5.24.0", "@tanstack/svelte-table": "^8.12.0", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.18.1", + "bits-ui": "^0.18.2", "class-validator": "^0.14.1", "clsx": "^2.1.0", "cmdk-sv": "^0.0.13", @@ -35,13 +35,13 @@ "devDependencies": { "@playwright/test": "^1.41.2", "@sveltejs/adapter-static": "^3.0.1", - "@sveltejs/kit": "^2.5.0", + "@sveltejs/kit": "^2.5.1", "@sveltejs/vite-plugin-svelte": "^3.0.2", "@typescript-eslint/eslint-plugin": "^7.0.2", "@typescript-eslint/parser": "^7.0.2", "autoprefixer": "^10.4.17", "cross-env": "^7.0.3", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.35.1", "npm-run-all": "^4.1.5", @@ -49,12 +49,12 @@ "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.1", "prettier-plugin-tailwindcss": "^0.5.11", - "svelte": "^4.2.11", + "svelte": "^4.2.12", "svelte-check": "^3.6.4", "swagger-typescript-api": "^13.0.3", "tslib": "^2.6.2", "typescript": "^5.4.0-beta", - "vite": "^5.1.3", + "vite": "^5.1.4", "vitest": "^1.3.1" } }, @@ -698,9 +698,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -749,13 +749,13 @@ "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -776,9 +776,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@iconify-json/mdi": { @@ -982,9 +982,9 @@ } }, "node_modules/@melt-ui/svelte": { - "version": "0.71.2", - "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.71.2.tgz", - "integrity": "sha512-GDUErhAphEoEOLpcBjQ84BgzRR6M3344fQE4QYFffwT7aedWak7CvNsECgeig1Y5xvfDmeEaFnGlOQXIBucJYw==", + "version": "0.74.2", + "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.74.2.tgz", + "integrity": "sha512-bIfZakPK4h6mOeoeqFnpksUGxkGp5JO2xtfhv/eXjG2rTogsSeVZRPe8eTtE7HoCbokP1+mVM9LqWxipsYTjUA==", "dependencies": { "@floating-ui/core": "^1.3.1", "@floating-ui/dom": "^1.4.5", @@ -998,9 +998,9 @@ } }, "node_modules/@melt-ui/svelte/node_modules/nanoid": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.5.tgz", - "integrity": "sha512-/Veqm+QKsyMY3kqi4faWplnY1u+VuKO3dD2binyPIybP31DRO29bPF+1mszgLnrR2KqSLceFLBNw0zmvDzN1QQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.6.tgz", + "integrity": "sha512-rRq0eMHoGZxlvaFOUdK1Ev83Bd1IgzzR+WJ3IbDJ7QOSdAxYjlurSPqFs9s4lJg29RT6nPwizFtJhQS6V5xgiA==", "funding": [ { "type": "github", @@ -1264,9 +1264,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.0.tgz", - "integrity": "sha512-1uyXvzC2Lu1FZa30T4y5jUAC21R309ZMRG0TPt+PPPbNUoDpy8zSmSNVWYaBWxYDqLGQ5oPNWvjvvF2IjJ1jmA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.1.tgz", + "integrity": "sha512-TKj08o3mJCoQNLTdRdGkHPePTCPUGTgkew65RDqjVU3MtPVxljsofXQYfXndHfq0P7KoPRO/0/reF6HesU0Djw==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -2097,12 +2097,12 @@ } }, "node_modules/bits-ui": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.18.1.tgz", - "integrity": "sha512-6junivBQ3EIHeF9j8wDa5pgzegtOwaI61ny4X8F7h2SIJi4RJWwZknkT7O5qPLeGoIYNeYV7N6EOBrr1w9/Mxg==", + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.18.2.tgz", + "integrity": "sha512-N58gPRPmkWUjRZzxH69hPEPNYjGa+wvYGqdBSYhGp0DzfAkqNeXLN7YN3qqpJxF+DFFBz5kLia6LzNLX5djuPA==", "dependencies": { "@internationalized/date": "^3.5.1", - "@melt-ui/svelte": "0.71.2", + "@melt-ui/svelte": "0.74.2", "nanoid": "^5.0.5" }, "peerDependencies": { @@ -2935,16 +2935,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -6305,9 +6305,9 @@ } }, "node_modules/svelte": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.11.tgz", - "integrity": "sha512-YIQk3J4X89wOLhjsqIW8tqY3JHPuBdtdOIkASP2PZeAMcSW9RsIjQzMesCrxOF3gdWYC0mKknlKF7OqmLM+Zqg==", + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz", + "integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==", "dependencies": { "@ampproject/remapping": "^2.2.1", "@jridgewell/sourcemap-codec": "^1.4.15", @@ -7075,9 +7075,9 @@ } }, "node_modules/vite": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.3.tgz", - "integrity": "sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz", + "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==", "dev": true, "dependencies": { "esbuild": "^0.19.3", diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index 5dae95e2e4..996129a4fb 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -23,13 +23,13 @@ "devDependencies": { "@playwright/test": "^1.41.2", "@sveltejs/adapter-static": "^3.0.1", - "@sveltejs/kit": "^2.5.0", + "@sveltejs/kit": "^2.5.1", "@sveltejs/vite-plugin-svelte": "^3.0.2", "@typescript-eslint/eslint-plugin": "^7.0.2", "@typescript-eslint/parser": "^7.0.2", "autoprefixer": "^10.4.17", "cross-env": "^7.0.3", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.35.1", "npm-run-all": "^4.1.5", @@ -37,12 +37,12 @@ "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.1", "prettier-plugin-tailwindcss": "^0.5.11", - "svelte": "^4.2.11", + "svelte": "^4.2.12", "svelte-check": "^3.6.4", "swagger-typescript-api": "^13.0.3", "tslib": "^2.6.2", "typescript": "^5.4.0-beta", - "vite": "^5.1.3", + "vite": "^5.1.4", "vitest": "^1.3.1" }, "dependencies": { @@ -52,7 +52,7 @@ "@tanstack/svelte-query-devtools": "^5.24.0", "@tanstack/svelte-table": "^8.12.0", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.18.1", + "bits-ui": "^0.18.2", "class-validator": "^0.14.1", "clsx": "^2.1.0", "cmdk-sv": "^0.0.13", From da01cd84b536c09aa60e7e5d60899d71f645b99b Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 20 Feb 2024 08:08:26 -0600 Subject: [PATCH 05/86] WIP - Dynamic Grid Filters prototype, need to move this to a builder type pattern like bits-ui. --- .../data-table-faceted-filter-builder.svelte | 97 +++++++++++++++++++ .../data-table-faceted-filter.svelte | 8 +- .../src/lib/components/data-table/index.ts | 3 + .../src/lib/components/filters/filters.ts | 15 ++- .../ClientApp/src/lib/stores/events.ts | 31 +++++- .../ClientApp/src/routes/(app)/+page.svelte | 38 ++++++-- 6 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte new file mode 100644 index 0000000000..ea88ab684e --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte @@ -0,0 +1,97 @@ + + + + + + + + + + + No results found. + + {#each options as option (option.value)} + +
+ +
+ + {option.label} + +
+ {/each} +
+ {#if values.length > 0} + + Clear filters + {/if} +
+
+
+
+ +{#each values as type (type)} + +{/each} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte index aab29dc734..7621b08334 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte @@ -18,6 +18,7 @@ export let values: unknown[] = []; export let options: Option[] = []; export let onValueChange: (facetKey: string, updatedValues: unknown[]) => void; + export let onRemoveFilter: (() => void) | undefined = undefined; let open = false; @@ -84,10 +85,15 @@ {/each} - {#if values.length > 0} + {#if values.length > 0 || onRemoveFilter} + {/if} + {#if values.length > 0} Clear filters {/if} + {#if onRemoveFilter} + Remove filter + {/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts index 33caf4941c..59f23407c7 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts @@ -1,6 +1,7 @@ import Root from './data-table.svelte'; import Body from './data-table-body.svelte'; import Toolbar from './data-table-toolbar.svelte'; +import FacetedFilterBuilder from './data-table-faceted-filter-builder.svelte'; import FacetedFilterContainer from './data-table-faceted-filter-container.svelte'; import FacetedFilter from './data-table-faceted-filter.svelte'; import PageSize from './data-table-page-size.svelte'; @@ -10,6 +11,7 @@ export { Root, Body, Toolbar, + FacetedFilterBuilder, FacetedFilterContainer, FacetedFilter, PageSize, @@ -18,6 +20,7 @@ export { Root as DataTable, Body as DataTableBody, Toolbar as DataTableToolbar, + FacetedFilterBuilder as DataTableFacetedFilterBuilder, FacetedFilterContainer as DataTableFacetedFilterContainer, FacetedFilter as DataTableFacetedFilter, PageSize as DataTablePageSize, diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts index 72716bc26e..411e4a66a4 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts @@ -219,6 +219,7 @@ export function toggleFilter(filters: IFilter[], filter: IFilter): IFilter[] { */ export function upsertOrRemoveFacetFilter(filters: IFilter[], filter: IFacetedFilter): boolean { const index = filters.findIndex((f) => f.type === filter.type && isFaceted(f)); + console.log('upsertOrRemoveFacetFilter', filter, index, filters); // If the filter has no values, remove it. if (!filter.values || filter.values.length == 0) { @@ -288,7 +289,7 @@ export function parseFilter(filters: IFilter[], input: string): IFilter[] { return resolvedFilters; } -export function getFilter(filter: Record): IFilter | undefined { +export function getFilter(filter: Omit & Record): IFilter | undefined { switch (filter.type) { case 'boolean': return new BooleanFilter(filter.term as string, filter.value as boolean); @@ -318,6 +319,18 @@ function isFaceted(filter: IFilter): filter is IFacetedFilter { } const FACETED_FILTER_TYPES = ['status', 'type']; +export function toFilterTypes(filters: IFilter[]): string[] { + const types = new Set(); + for (const filter of filters) { + if (isFaceted(filter)) { + types.add(filter.type); + } + } + + console.log(Array.from(types)); + return Array.from(types); +} + export function toFacetedValues(filters: IFilter[]): Record { const values: Record = {}; for (const filterType of FACETED_FILTER_TYPES) { diff --git a/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts b/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts index ef17bf32cd..a6a733f350 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts @@ -8,7 +8,8 @@ import { type IFacetedFilter, toggleFilter, parseFilter, - resetFacetedValues + resetFacetedValues, + toFilterTypes } from '$comp/filters/filters'; import { persisted } from 'svelte-local-storage-store'; import { derived, get } from 'svelte/store'; @@ -21,6 +22,18 @@ export const filter = derived(filters, ($filters) => toFilter($filters)); export const filterWithFaceted = derived(filters, ($filters) => toFilter($filters, true)); export const filterValues = derived(filters, ($filters) => toFacetedValues($filters)); +export const selectedFilterTypes = derived(filters, ($filters) => toFilterTypes($filters)); +export const filterOptions: { value: string; label: string }[] = [ + { + value: 'status', + label: 'Status' + }, + { + value: 'type', + label: 'Type' + } +]; + export function updateFilter(filter: IFilter) { filters.set(toggleFilter(get(filters), filter)); } @@ -28,8 +41,10 @@ export function updateFilter(filter: IFilter) { export function updateFilterValues(key: string, values: unknown[]) { const filter = getFilter({ type: key, values }) as IFacetedFilter; const currentFilters = get(filters); + console.log('updateFilterValues', filter, currentFilters); if (filter && upsertOrRemoveFacetFilter(currentFilters, filter)) { filters.set(currentFilters); + console.log('updateFilterValues', currentFilters); } } @@ -53,3 +68,17 @@ export function onFilterInputChanged(event: Event) { export function onFacetValuesChanged(facetKey: string, updatedValues: unknown[]) { updateFilterValues(facetKey, updatedValues); } + +export function onToggleFacetFilterChanged(facetKey: string) { + const currentFilters = get(filters); + const filter = currentFilters.find((f) => f.type === facetKey); + console.log( + facetKey, + currentFilters.find((f) => f.type === facetKey) + ); + if (filter) { + toggleFilter(currentFilters, filter); + } else { + updateFilter(currentFilters, getFilter({ type: facetKey })); + } +} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index 9993d33a22..89f616c44a 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -13,12 +13,15 @@ import CustomEventMessage from '$comp/messaging/CustomEventMessage.svelte'; import { filter, + filterOptions, filterValues, filterWithFaceted, onFacetValuesChanged, onFilterChanged, onFilterInputChanged, + onToggleFacetFilterChanged, resetFilterValues, + selectedFilterTypes, time } from '$lib/stores/events'; import DateRangeDropdown from '$comp/DateRangeDropdown.svelte'; @@ -41,16 +44,31 @@ - - - + + {#if type === 'status'} + console.log('onRemoveFilter')} + > + {:else if type === 'type'} + + {/if} + From d23417f70d916d9e618224f4745efac0d93d9e1d Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Fri, 1 Mar 2024 07:41:52 -0600 Subject: [PATCH 06/86] Updated deps --- .../Exceptionless.Core.csproj | 2 +- .../Exceptionless.Insulation.csproj | 4 +- .../ClientApp/package-lock.json | 210 +++++++++--------- src/Exceptionless.Web/ClientApp/package.json | 22 +- .../Exceptionless.Tests.csproj | 2 +- 5 files changed, 120 insertions(+), 120 deletions(-) diff --git a/src/Exceptionless.Core/Exceptionless.Core.csproj b/src/Exceptionless.Core/Exceptionless.Core.csproj index 4fc6afdc0d..2a6599eb0c 100644 --- a/src/Exceptionless.Core/Exceptionless.Core.csproj +++ b/src/Exceptionless.Core/Exceptionless.Core.csproj @@ -30,7 +30,7 @@ - + diff --git a/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj b/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj index 660dc9137a..583b4d56d4 100644 --- a/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj +++ b/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj @@ -21,8 +21,8 @@ - - + + diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index 5e0494a776..ce47e3aff5 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -10,11 +10,11 @@ "dependencies": { "@exceptionless/browser": "^3.0.5", "@iconify-json/mdi": "^1.1.64", - "@tanstack/svelte-query": "^5.22.2", - "@tanstack/svelte-query-devtools": "^5.24.0", - "@tanstack/svelte-table": "^8.12.0", + "@tanstack/svelte-query": "^5.24.1", + "@tanstack/svelte-query-devtools": "^5.24.1", + "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.18.2", + "bits-ui": "^0.18.6", "class-validator": "^0.14.1", "clsx": "^2.1.0", "cmdk-sv": "^0.0.13", @@ -25,7 +25,7 @@ "svelte-echarts": "^0.1.1", "svelte-legos": "^0.2.2", "svelte-local-storage-store": "^0.6.4", - "svelte-sonner": "^0.3.18", + "svelte-sonner": "^0.3.19", "svelte-time": "^0.8.2", "tailwind-merge": "^2.2.1", "tailwind-variants": "^0.2.0", @@ -33,12 +33,12 @@ "unplugin-icons": "^0.18.5" }, "devDependencies": { - "@playwright/test": "^1.41.2", + "@playwright/test": "^1.42.0", "@sveltejs/adapter-static": "^3.0.1", - "@sveltejs/kit": "^2.5.1", + "@sveltejs/kit": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^7.0.2", - "@typescript-eslint/parser": "^7.0.2", + "@typescript-eslint/eslint-plugin": "^7.1.0", + "@typescript-eslint/parser": "^7.1.0", "autoprefixer": "^10.4.17", "cross-env": "^7.0.3", "eslint": "^8.57.0", @@ -47,10 +47,10 @@ "npm-run-all": "^4.1.5", "postcss": "^8.4.35", "prettier": "^3.2.5", - "prettier-plugin-svelte": "^3.2.1", + "prettier-plugin-svelte": "^3.2.2", "prettier-plugin-tailwindcss": "^0.5.11", "svelte": "^4.2.12", - "svelte-check": "^3.6.4", + "svelte-check": "^3.6.6", "swagger-typescript-api": "^13.0.3", "tslib": "^2.6.2", "typescript": "^5.4.0-beta", @@ -982,9 +982,9 @@ } }, "node_modules/@melt-ui/svelte": { - "version": "0.74.2", - "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.74.2.tgz", - "integrity": "sha512-bIfZakPK4h6mOeoeqFnpksUGxkGp5JO2xtfhv/eXjG2rTogsSeVZRPe8eTtE7HoCbokP1+mVM9LqWxipsYTjUA==", + "version": "0.74.4", + "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.74.4.tgz", + "integrity": "sha512-EeDP3C1grK+bPTezJQXKid2k4RRGZakyHTghD/zg//fM6Gqe4JykVtV0Yih4QJs+yGTgJq/EaNQMQ6JkTnvHxg==", "dependencies": { "@floating-ui/core": "^1.3.1", "@floating-ui/dom": "^1.4.5", @@ -1047,12 +1047,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz", - "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==", + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.0.tgz", + "integrity": "sha512-2k1HzC28Fs+HiwbJOQDUwrWMttqSLUVdjCqitBOjdCD0svWOMQUVqrXX6iFD7POps6xXAojsX/dGBpKnjZctLA==", "dev": true, "dependencies": { - "playwright": "1.41.2" + "playwright": "1.42.0" }, "bin": { "playwright": "cli.js" @@ -1264,9 +1264,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.1.tgz", - "integrity": "sha512-TKj08o3mJCoQNLTdRdGkHPePTCPUGTgkew65RDqjVU3MtPVxljsofXQYfXndHfq0P7KoPRO/0/reF6HesU0Djw==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.2.tgz", + "integrity": "sha512-1Pm2lsBYURQsjnLyZa+jw75eVD4gYHxGRwPyFe4DAmB3FjTVR8vRNWGeuDLGFcKMh/B1ij6FTUrc9GrerogCng==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -1343,9 +1343,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.22.2", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.22.2.tgz", - "integrity": "sha512-z3PwKFUFACMUqe1eyesCIKg3Jv1mysSrYfrEW5ww5DCDUD4zlpTKBvUDaEjsfZzL3ULrFLDM9yVUxI/fega1Qg==", + "version": "5.24.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.24.1.tgz", + "integrity": "sha512-DZ6Nx9p7BhjkG50ayJ+MKPgff+lMeol7QYXkvuU5jr2ryW/4ok5eanaS9W5eooA4xN0A/GPHdLGOZGzArgf5Cg==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -1361,11 +1361,11 @@ } }, "node_modules/@tanstack/svelte-query": { - "version": "5.22.2", - "resolved": "https://registry.npmjs.org/@tanstack/svelte-query/-/svelte-query-5.22.2.tgz", - "integrity": "sha512-7ZK/EoAAIB6KIKiSC3NSTJPJYo2meOZjsyBXLtbEpLYr7U/mCJwgJ0dXKOUt9n3eKwUyX9N/stqwyD10F+KS8Q==", + "version": "5.24.1", + "resolved": "https://registry.npmjs.org/@tanstack/svelte-query/-/svelte-query-5.24.1.tgz", + "integrity": "sha512-N1T15f1uwZJ2HADxupj+rDNmA7Ez7q+1D68Koqo7rAyWaRgl2V9gR7Oc/MLQM9LrFv6M768btwogDlE1LfvxLw==", "dependencies": { - "@tanstack/query-core": "5.22.2" + "@tanstack/query-core": "5.24.1" }, "funding": { "type": "github", @@ -1376,9 +1376,9 @@ } }, "node_modules/@tanstack/svelte-query-devtools": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/@tanstack/svelte-query-devtools/-/svelte-query-devtools-5.24.0.tgz", - "integrity": "sha512-XIIeyhvN4XjyBT3jmp3T448K30Ut4cFqR0EzHnbEYSyHkNrpl2K3YKj/PSHyksq5+yF3ACPbuwEwqaXmXAao6w==", + "version": "5.24.1", + "resolved": "https://registry.npmjs.org/@tanstack/svelte-query-devtools/-/svelte-query-devtools-5.24.1.tgz", + "integrity": "sha512-X7GbzmYJK/il6xkrYftx/HGdZ9DhV666ocJwPxLtGxTK/9eygHezFhelhsCwCeI0P+Wxs3E9LbC5C6eGQkklZA==", "dependencies": { "@tanstack/query-devtools": "5.24.0", "esm-env": "^1.0.0" @@ -1388,16 +1388,16 @@ "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "@tanstack/svelte-query": "^5.22.2", + "@tanstack/svelte-query": "^5.24.1", "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0" } }, "node_modules/@tanstack/svelte-table": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/@tanstack/svelte-table/-/svelte-table-8.12.0.tgz", - "integrity": "sha512-IgmCj4tVUgjQAUa895XommqNkNdlbi5K3MgcuyB7SbgRMXZXWUrz4chDSrFSseosLz+hcizXsoavmDcDm/WYwA==", + "version": "8.13.2", + "resolved": "https://registry.npmjs.org/@tanstack/svelte-table/-/svelte-table-8.13.2.tgz", + "integrity": "sha512-lA9xSVWBDFPy7cDH6bhA2OX8AZ5bZEcuG9+VBGLmGpCg78kXjr3VZMGaWUD+rTJM42Fp6zOmp1E1McSKVhUGww==", "dependencies": { - "@tanstack/table-core": "8.12.0" + "@tanstack/table-core": "8.13.2" }, "engines": { "node": ">=12" @@ -1411,9 +1411,9 @@ } }, "node_modules/@tanstack/table-core": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.12.0.tgz", - "integrity": "sha512-cq/ylWVrOwixmwNXQjgZaQw1Izf7+nPxjczum7paAnMtwPg1S2qRAJU+Jb8rEBUWm69voC/zcChmePlk2hc6ug==", + "version": "8.13.2", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.13.2.tgz", + "integrity": "sha512-/2saD1lWBUV6/uNAwrsg2tw58uvMJ07bO2F1IWMxjFRkJiXKQRuc3Oq2aufeobD3873+4oIM/DRySIw7+QsPPw==", "engines": { "node": ">=12" }, @@ -1454,9 +1454,9 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/swagger-schema-official": { @@ -1471,16 +1471,16 @@ "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.2.tgz", - "integrity": "sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz", + "integrity": "sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/type-utils": "7.0.2", - "@typescript-eslint/utils": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/type-utils": "7.1.0", + "@typescript-eslint/utils": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1532,15 +1532,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.2.tgz", - "integrity": "sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz", + "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4" }, "engines": { @@ -1560,13 +1560,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", - "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", + "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2" + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1577,13 +1577,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.2.tgz", - "integrity": "sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz", + "integrity": "sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.0.2", - "@typescript-eslint/utils": "7.0.2", + "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/utils": "7.1.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1630,9 +1630,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", - "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", + "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1643,13 +1643,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", - "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", + "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/visitor-keys": "7.1.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1721,17 +1721,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", - "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", + "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/scope-manager": "7.1.0", + "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.0", "semver": "^7.5.4" }, "engines": { @@ -1746,12 +1746,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", - "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", + "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/types": "7.1.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2097,12 +2097,12 @@ } }, "node_modules/bits-ui": { - "version": "0.18.2", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.18.2.tgz", - "integrity": "sha512-N58gPRPmkWUjRZzxH69hPEPNYjGa+wvYGqdBSYhGp0DzfAkqNeXLN7YN3qqpJxF+DFFBz5kLia6LzNLX5djuPA==", + "version": "0.18.6", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.18.6.tgz", + "integrity": "sha512-UbBFuyG7qEM+VA1rA/7GRy94rXRFCW+B1LfK7uiBd6fZiPZtPmPPW1RjTblGaJjCW2E6e/ruxbuKjxW2oXDP7g==", "dependencies": { "@internationalized/date": "^3.5.1", - "@melt-ui/svelte": "0.74.2", + "@melt-ui/svelte": "0.74.4", "nanoid": "^5.0.5" }, "peerDependencies": { @@ -5122,12 +5122,12 @@ } }, "node_modules/playwright": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", - "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0.tgz", + "integrity": "sha512-Ko7YRUgj5xBHbntrgt4EIw/nE//XBHOKVKnBjO1KuZkmkhlbgyggTe5s9hjqQ1LpN+Xg+kHsQyt5Pa0Bw5XpvQ==", "dev": true, "dependencies": { - "playwright-core": "1.41.2" + "playwright-core": "1.42.0" }, "bin": { "playwright": "cli.js" @@ -5140,9 +5140,9 @@ } }, "node_modules/playwright-core": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", - "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0.tgz", + "integrity": "sha512-0HD9y8qEVlcbsAjdpBaFjmaTHf+1FeIddy8VJLeiqwhcNqGCBe4Wp2e8knpqiYbzxtxarxiXyNDw2cG8sCaNMQ==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -5374,9 +5374,9 @@ } }, "node_modules/prettier-plugin-svelte": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.1.tgz", - "integrity": "sha512-ENAPbIxASf2R79IZwgkG5sBdeNA9kLRlXVvKKmTXh79zWTy0KKoT86XO2pHrTitUPINd+iXWy12MRmgzKGVckA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.2.tgz", + "integrity": "sha512-ZzzE/wMuf48/1+Lf2Ffko0uDa6pyCfgHV6+uAhtg2U0AAXGrhCSW88vEJNAkAxW5qyrFY1y1zZ4J8TgHrjW++Q==", "dev": true, "peerDependencies": { "prettier": "^3.0.0", @@ -6329,9 +6329,9 @@ } }, "node_modules/svelte-check": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.6.4.tgz", - "integrity": "sha512-mY/dqucqm46p72M8yZmn81WPZx9mN6uuw8UVfR3ZKQeLxQg5HDGO3HHm5AZuWZPYNMLJ+TRMn+TeN53HfQ/vsw==", + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.6.6.tgz", + "integrity": "sha512-b9q9rOHOMYF3U8XllK7LmXTq1LeWQ98waGfEJzrFutViadkNl1tgdEtxIQ8yuPx+VQ4l7YrknYol+0lfZocaZw==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", @@ -6340,7 +6340,7 @@ "import-fresh": "^3.2.1", "picocolors": "^1.0.0", "sade": "^1.7.4", - "svelte-preprocess": "^5.1.0", + "svelte-preprocess": "^5.1.3", "typescript": "^5.0.3" }, "bin": { @@ -6499,9 +6499,9 @@ } }, "node_modules/svelte-sonner": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/svelte-sonner/-/svelte-sonner-0.3.18.tgz", - "integrity": "sha512-DkpbeLB1yZ6CQ0vg/tpFUv2KGxdugODBjZYk9KWsxIAMOsnKg2VEyV2h1ycDztaEbiwoIGBObPvv+MG/4z1HSg==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/svelte-sonner/-/svelte-sonner-0.3.19.tgz", + "integrity": "sha512-jpPOgLtHwRaB6Vqo2dUQMv15/yUV/BQWTjKpEqQ11uqRSHKjAYUKZyGrHB2cQsGmyjR0JUzBD58btpgNqINQ/Q==", "peerDependencies": { "svelte": ">=3 <5" } diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index 996129a4fb..a692307ee0 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -21,12 +21,12 @@ "upgrade": "ncu -i" }, "devDependencies": { - "@playwright/test": "^1.41.2", + "@playwright/test": "^1.42.0", "@sveltejs/adapter-static": "^3.0.1", - "@sveltejs/kit": "^2.5.1", + "@sveltejs/kit": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^7.0.2", - "@typescript-eslint/parser": "^7.0.2", + "@typescript-eslint/eslint-plugin": "^7.1.0", + "@typescript-eslint/parser": "^7.1.0", "autoprefixer": "^10.4.17", "cross-env": "^7.0.3", "eslint": "^8.57.0", @@ -35,10 +35,10 @@ "npm-run-all": "^4.1.5", "postcss": "^8.4.35", "prettier": "^3.2.5", - "prettier-plugin-svelte": "^3.2.1", + "prettier-plugin-svelte": "^3.2.2", "prettier-plugin-tailwindcss": "^0.5.11", "svelte": "^4.2.12", - "svelte-check": "^3.6.4", + "svelte-check": "^3.6.6", "swagger-typescript-api": "^13.0.3", "tslib": "^2.6.2", "typescript": "^5.4.0-beta", @@ -48,11 +48,11 @@ "dependencies": { "@exceptionless/browser": "^3.0.5", "@iconify-json/mdi": "^1.1.64", - "@tanstack/svelte-query": "^5.22.2", - "@tanstack/svelte-query-devtools": "^5.24.0", - "@tanstack/svelte-table": "^8.12.0", + "@tanstack/svelte-query": "^5.24.1", + "@tanstack/svelte-query-devtools": "^5.24.1", + "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.18.2", + "bits-ui": "^0.18.6", "class-validator": "^0.14.1", "clsx": "^2.1.0", "cmdk-sv": "^0.0.13", @@ -63,7 +63,7 @@ "svelte-echarts": "^0.1.1", "svelte-legos": "^0.2.2", "svelte-local-storage-store": "^0.6.4", - "svelte-sonner": "^0.3.18", + "svelte-sonner": "^0.3.19", "svelte-time": "^0.8.2", "tailwind-merge": "^2.2.1", "tailwind-variants": "^0.2.0", diff --git a/tests/Exceptionless.Tests/Exceptionless.Tests.csproj b/tests/Exceptionless.Tests/Exceptionless.Tests.csproj index 531b59c563..e6364ae1aa 100644 --- a/tests/Exceptionless.Tests/Exceptionless.Tests.csproj +++ b/tests/Exceptionless.Tests/Exceptionless.Tests.csproj @@ -13,7 +13,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all From 03cb1101eaa3862971618f6ee0621485b44c2473 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Fri, 1 Mar 2024 08:02:24 -0600 Subject: [PATCH 07/86] Reduced usages of RefreshDataAsync in tests --- .../Controllers/EventControllerTests.cs | 2 +- .../Controllers/ProjectControllerTests.cs | 2 +- .../IntegrationTestsBase.cs | 2 - .../Pipeline/EventPipelineTests.cs | 16 +++-- .../Repositories/EventRepositoryTests.cs | 21 +++---- .../OrganizationRepositoryTests.cs | 10 +--- .../Repositories/TokenRepositoryTests.cs | 9 ++- .../Repositories/WebHookRepositoryTests.cs | 59 +++++++++---------- .../Services/StackServiceTests.cs | 3 +- .../Stats/AggregationTests.cs | 10 ++-- 10 files changed, 57 insertions(+), 77 deletions(-) diff --git a/tests/Exceptionless.Tests/Controllers/EventControllerTests.cs b/tests/Exceptionless.Tests/Controllers/EventControllerTests.cs index d85aeb6c44..439eda9ac4 100644 --- a/tests/Exceptionless.Tests/Controllers/EventControllerTests.cs +++ b/tests/Exceptionless.Tests/Controllers/EventControllerTests.cs @@ -503,7 +503,7 @@ await CreateDataAsync(d => [Fact] public async Task WillGetStackEvents() { - (List? stacks, _) = await CreateDataAsync(d => + (var stacks, _) = await CreateDataAsync(d => { d.Event().TestProject(); }); diff --git a/tests/Exceptionless.Tests/Controllers/ProjectControllerTests.cs b/tests/Exceptionless.Tests/Controllers/ProjectControllerTests.cs index 3c6781b533..ed05e404a4 100644 --- a/tests/Exceptionless.Tests/Controllers/ProjectControllerTests.cs +++ b/tests/Exceptionless.Tests/Controllers/ProjectControllerTests.cs @@ -118,7 +118,7 @@ public async Task CanGetProjectListStats() Assert.Equal(0, project.StackCount); Assert.Equal(0, project.EventCount); - (List? stacks, List? events) = await CreateDataAsync(d => + (var stacks, var events) = await CreateDataAsync(d => { d.Event().Message("test"); }); diff --git a/tests/Exceptionless.Tests/IntegrationTestsBase.cs b/tests/Exceptionless.Tests/IntegrationTestsBase.cs index 213bbabd05..8a207c463e 100644 --- a/tests/Exceptionless.Tests/IntegrationTestsBase.cs +++ b/tests/Exceptionless.Tests/IntegrationTestsBase.cs @@ -125,8 +125,6 @@ protected virtual void RegisterServices(IServiceCollection services) await stackRepository.AddAsync(stacks, o => o.ImmediateConsistency()); await eventRepository.AddAsync(events, o => o.ImmediateConsistency()); - await RefreshDataAsync(); - return (stacks.ToList(), events.ToList()); } diff --git a/tests/Exceptionless.Tests/Pipeline/EventPipelineTests.cs b/tests/Exceptionless.Tests/Pipeline/EventPipelineTests.cs index 35b10bd535..17d3c8dfdd 100644 --- a/tests/Exceptionless.Tests/Pipeline/EventPipelineTests.cs +++ b/tests/Exceptionless.Tests/Pipeline/EventPipelineTests.cs @@ -243,7 +243,7 @@ public async Task CloseExistingAutoSessionAsync() var contexts = await _pipeline.RunAsync(events, OrganizationData.GenerateSampleOrganization(_billingManager, _plans), ProjectData.GenerateSampleProject()); Assert.DoesNotContain(contexts, c => c.HasError); - Assert.Equal(1, contexts.Count(c => c.IsCancelled && c.IsDiscarded)); + Assert.Equal(1, contexts.Count(c => c is { IsCancelled: true, IsDiscarded: true })); Assert.Contains(contexts, c => c.IsProcessed); await RefreshDataAsync(); @@ -304,7 +304,7 @@ public async Task WillMarkAutoSessionHeartbeatStackHiddenAsync() var contexts = await _pipeline.RunAsync(events, OrganizationData.GenerateSampleOrganization(_billingManager, _plans), ProjectData.GenerateSampleProject()); Assert.DoesNotContain(contexts, c => c.HasError); - Assert.Equal(1, contexts.Count(c => c.IsCancelled && c.IsDiscarded)); + Assert.Equal(1, contexts.Count(c => c is { IsCancelled: true, IsDiscarded: true })); Assert.Equal(0, contexts.Count(c => c.IsProcessed)); await RefreshDataAsync(); @@ -459,7 +459,7 @@ public async Task CloseExistingManualSessionAsync() var contexts = await _pipeline.RunAsync(events, OrganizationData.GenerateSampleOrganization(_billingManager, _plans), ProjectData.GenerateSampleProject()); Assert.DoesNotContain(contexts, c => c.HasError); - Assert.Equal(1, contexts.Count(c => c.IsCancelled && c.IsDiscarded)); + Assert.Equal(1, contexts.Count(c => c is { IsCancelled: true, IsDiscarded: true })); Assert.Contains(contexts, c => c.IsProcessed); events = @@ -518,7 +518,7 @@ public async Task WillMarkManualSessionHeartbeatStackHiddenAsync() var contexts = await _pipeline.RunAsync(events, OrganizationData.GenerateSampleOrganization(_billingManager, _plans), ProjectData.GenerateSampleProject()); Assert.DoesNotContain(contexts, c => c.HasError); - Assert.Equal(1, contexts.Count(c => c.IsCancelled && c.IsDiscarded)); + Assert.Equal(1, contexts.Count(c => c is { IsCancelled: true, IsDiscarded: true })); Assert.Equal(0, contexts.Count(c => c.IsProcessed)); await RefreshDataAsync(); @@ -1164,10 +1164,10 @@ private async Task CreateProjectDataAsync(BillingPlan? plan = null) organization.SuspensionDate = SystemClock.UtcNow; } - await _organizationRepository.AddAsync(organization, o => o.Cache()); + await _organizationRepository.AddAsync(organization, o => o.ImmediateConsistency().Cache()); } - await _projectRepository.AddAsync(ProjectData.GenerateSampleProjects(), o => o.Cache()); + await _projectRepository.AddAsync(ProjectData.GenerateSampleProjects(), o => o.ImmediateConsistency().Cache()); foreach (var user in UserData.GenerateSampleUsers()) { @@ -1180,10 +1180,8 @@ private async Task CreateProjectDataAsync(BillingPlan? plan = null) if (!user.IsEmailAddressVerified) user.CreateVerifyEmailAddressToken(); - await _userRepository.AddAsync(user, o => o.Cache()); + await _userRepository.AddAsync(user, o => o.ImmediateConsistency().Cache()); } - - await RefreshDataAsync(); } private static PersistentEvent GenerateEvent(DateTimeOffset? occurrenceDate = null, string? userIdentity = null, string? type = null, string? sessionId = null) diff --git a/tests/Exceptionless.Tests/Repositories/EventRepositoryTests.cs b/tests/Exceptionless.Tests/Repositories/EventRepositoryTests.cs index b5e3b8434c..cba7c1fd38 100644 --- a/tests/Exceptionless.Tests/Repositories/EventRepositoryTests.cs +++ b/tests/Exceptionless.Tests/Repositories/EventRepositoryTests.cs @@ -133,7 +133,6 @@ public async Task GetNextEventIdInStackTestAsync() _logger.LogDebug(""); _logger.LogDebug("Tests:"); - await RefreshDataAsync(); Assert.Equal(_ids.Count, await _repository.CountAsync()); for (int i = 0; i < sortedIds.Count; i++) { @@ -164,9 +163,8 @@ public async Task CanGetPreviousAndNExtEventIdWithFilterTestAsync() public async Task GetByReferenceIdAsync() { string referenceId = ObjectId.GenerateNewId().ToString(); - await _repository.AddAsync(EventData.GenerateEvents(3, TestConstants.OrganizationId, TestConstants.ProjectId, TestConstants.StackId2, referenceId: referenceId).ToList()); + await _repository.AddAsync(EventData.GenerateEvents(3, TestConstants.OrganizationId, TestConstants.ProjectId, TestConstants.StackId2, referenceId: referenceId).ToList(), o => o.ImmediateConsistency()); - await RefreshDataAsync(); var results = await _repository.GetByReferenceIdAsync(TestConstants.ProjectId, referenceId); Assert.True(results.Total > 0); Assert.NotNull(results.Documents.First()); @@ -193,9 +191,8 @@ public async Task GetOpenSessionsAsync() closedSession }; - await _repository.AddAsync(events); + await _repository.AddAsync(events, o => o.ImmediateConsistency()); - await RefreshDataAsync(); var results = await _repository.GetOpenSessionsAsync(SystemClock.UtcNow.SubtractMinutes(30)); Assert.Equal(3, results.Total); } @@ -204,13 +201,12 @@ public async Task GetOpenSessionsAsync() public async Task RemoveAllByClientIpAndDateAsync() { const string _clientIpAddress = "123.123.12.255"; - const int NUMBER_OF_EVENTS_TO_CREATE = 50; + var events = EventData.GenerateEvents(NUMBER_OF_EVENTS_TO_CREATE, TestConstants.OrganizationId, TestConstants.ProjectId, TestConstants.StackId2, startDate: SystemClock.UtcNow.SubtractDays(2), endDate: SystemClock.UtcNow).ToList(); events.ForEach(e => e.AddRequestInfo(new RequestInfo { ClientIpAddress = _clientIpAddress })); - await _repository.AddAsync(events); + await _repository.AddAsync(events, o => o.ImmediateConsistency()); - await RefreshDataAsync(); events = (await _repository.GetByProjectIdAsync(TestConstants.ProjectId, o => o.PageLimit(NUMBER_OF_EVENTS_TO_CREATE))).Documents.ToList(); Assert.Equal(NUMBER_OF_EVENTS_TO_CREATE, events.Count); events.ForEach(e => @@ -220,9 +216,8 @@ public async Task RemoveAllByClientIpAndDateAsync() Assert.Equal(_clientIpAddress, ri.ClientIpAddress); }); - await _repository.RemoveAllAsync(TestConstants.OrganizationId, _clientIpAddress, SystemClock.UtcNow.SubtractDays(3), SystemClock.UtcNow.AddDays(2)); + await _repository.RemoveAllAsync(TestConstants.OrganizationId, _clientIpAddress, SystemClock.UtcNow.SubtractDays(3), SystemClock.UtcNow.AddDays(2), o => o.ImmediateConsistency()); - await RefreshDataAsync(); events = (await _repository.GetByProjectIdAsync(TestConstants.ProjectId, o => o.PageLimit(NUMBER_OF_EVENTS_TO_CREATE))).Documents.ToList(); Assert.Empty(events); } @@ -236,7 +231,7 @@ private async Task CreateDataAsync() var occurrenceDateMid = baseDate; var occurrenceDateEnd = baseDate.AddMinutes(30); - await _stackRepository.AddAsync(StackData.GenerateStack(id: TestConstants.StackId, organizationId: TestConstants.OrganizationId, projectId: TestConstants.ProjectId)); + await _stackRepository.AddAsync(StackData.GenerateStack(id: TestConstants.StackId, organizationId: TestConstants.OrganizationId, projectId: TestConstants.ProjectId), o => o.ImmediateConsistency()); var occurrenceDates = new List { occurrenceDateStart, @@ -255,10 +250,8 @@ private async Task CreateDataAsync() foreach (var date in occurrenceDates) { - var ev = await _repository.AddAsync(EventData.GenerateEvent(projectId: TestConstants.ProjectId, organizationId: TestConstants.OrganizationId, stackId: TestConstants.StackId, occurrenceDate: date)); + var ev = await _repository.AddAsync(EventData.GenerateEvent(projectId: TestConstants.ProjectId, organizationId: TestConstants.OrganizationId, stackId: TestConstants.StackId, occurrenceDate: date), o => o.ImmediateConsistency()); _ids.Add(Tuple.Create(ev.Id, date)); } - - await RefreshDataAsync(); } } diff --git a/tests/Exceptionless.Tests/Repositories/OrganizationRepositoryTests.cs b/tests/Exceptionless.Tests/Repositories/OrganizationRepositoryTests.cs index 5332a85310..7b92db1318 100644 --- a/tests/Exceptionless.Tests/Repositories/OrganizationRepositoryTests.cs +++ b/tests/Exceptionless.Tests/Repositories/OrganizationRepositoryTests.cs @@ -31,8 +31,7 @@ public async Task CanCreateUpdateRemoveAsync() var organization = new Organization { Name = "Test Organization", PlanId = _plans.FreePlan.Id }; Assert.Null(organization.Id); - await _repository.AddAsync(organization); - await RefreshDataAsync(); + await _repository.AddAsync(organization, o => o.ImmediateConsistency()); Assert.NotNull(organization.Id); organization = await _repository.GetByIdAsync(organization.Id); @@ -40,7 +39,6 @@ public async Task CanCreateUpdateRemoveAsync() organization.Name = "New organization"; await _repository.SaveAsync(organization); - await _repository.RemoveAsync(organization.Id); } @@ -51,8 +49,7 @@ public async Task CanAddAndGetByCachedAsync() Assert.Null(organization.Id); Assert.Equal(0, _cache.Count); - await _repository.AddAsync(organization, o => o.Cache()); - await RefreshDataAsync(); + await _repository.AddAsync(organization, o => o.ImmediateConsistency().Cache()); Assert.NotNull(organization.Id); Assert.Equal(1, _cache.Count); @@ -62,8 +59,7 @@ public async Task CanAddAndGetByCachedAsync() Assert.NotNull(organization.Id); Assert.Equal(1, _cache.Count); - await _repository.RemoveAllAsync(); - await RefreshDataAsync(); + await _repository.RemoveAllAsync(o => o.ImmediateConsistency()); Assert.Equal(0, _cache.Count); } } diff --git a/tests/Exceptionless.Tests/Repositories/TokenRepositoryTests.cs b/tests/Exceptionless.Tests/Repositories/TokenRepositoryTests.cs index 60c6057fb1..81042f8b5d 100644 --- a/tests/Exceptionless.Tests/Repositories/TokenRepositoryTests.cs +++ b/tests/Exceptionless.Tests/Repositories/TokenRepositoryTests.cs @@ -36,22 +36,22 @@ await _repository.AddAsync(new List { Assert.Equal(3, (await _repository.GetByProjectIdAsync(TestConstants.ProjectIdWithNoRoles)).Total); await _repository.RemoveAllByProjectIdAsync(TestConstants.OrganizationId, TestConstants.ProjectId); - await RefreshDataAsync(); + Assert.Equal(4, (await _repository.GetByOrganizationIdAsync(TestConstants.OrganizationId)).Total); Assert.Equal(1, (await _repository.GetByProjectIdAsync(TestConstants.ProjectId)).Total); Assert.Equal(3, (await _repository.GetByProjectIdAsync(TestConstants.ProjectIdWithNoRoles)).Total); await _repository.RemoveAllByProjectIdAsync(TestConstants.OrganizationId, TestConstants.ProjectIdWithNoRoles); - await RefreshDataAsync(); + Assert.Equal(3, (await _repository.GetByOrganizationIdAsync(TestConstants.OrganizationId)).Total); Assert.Equal(1, (await _repository.GetByProjectIdAsync(TestConstants.ProjectId)).Total); Assert.Equal(2, (await _repository.GetByProjectIdAsync(TestConstants.ProjectIdWithNoRoles)).Total); await _repository.RemoveAllByOrganizationIdAsync(TestConstants.OrganizationId); - await RefreshDataAsync(); + Assert.Equal(0, (await _repository.GetByOrganizationIdAsync(TestConstants.OrganizationId)).Total); Assert.Equal(0, (await _repository.GetByProjectIdAsync(TestConstants.ProjectId)).Total); Assert.Equal(1, (await _repository.GetByProjectIdAsync(TestConstants.ProjectIdWithNoRoles)).Total); @@ -68,8 +68,7 @@ await _repository.AddAsync(new List { Assert.Equal(1, (await _repository.GetByTypeAndUserIdAsync(TokenType.Access, TestConstants.UserId)).Total); Assert.Equal(1, (await _repository.GetByTypeAndUserIdAsync(TokenType.Authentication, TestConstants.UserId)).Total); - await _repository.RemoveAllByUserIdAsync(TestConstants.UserId); - await RefreshDataAsync(); + await _repository.RemoveAllByUserIdAsync(TestConstants.UserId, o => o.ImmediateConsistency()); Assert.Equal(0, (await _repository.GetByTypeAndUserIdAsync(TokenType.Access, TestConstants.UserId)).Total); Assert.Equal(0, (await _repository.GetByTypeAndUserIdAsync(TokenType.Authentication, TestConstants.UserId)).Total); Assert.Equal(1, (await _repository.GetByOrganizationIdAsync(TestConstants.OrganizationId)).Total); diff --git a/tests/Exceptionless.Tests/Repositories/WebHookRepositoryTests.cs b/tests/Exceptionless.Tests/Repositories/WebHookRepositoryTests.cs index 81c1718a60..7918fe2a0f 100644 --- a/tests/Exceptionless.Tests/Repositories/WebHookRepositoryTests.cs +++ b/tests/Exceptionless.Tests/Repositories/WebHookRepositoryTests.cs @@ -1,6 +1,7 @@ using Exceptionless.Core.Models; using Exceptionless.Core.Repositories; using Exceptionless.Tests.Utility; +using Foundatio.Repositories; using Xunit; using Xunit.Abstractions; @@ -18,34 +19,33 @@ public WebHookRepositoryTests(ITestOutputHelper output, AppWebHostFactory factor [Fact] public async Task GetByOrganizationIdOrProjectIdAsync() { - await _repository.AddAsync(new WebHook + await _repository.AddAsync([new WebHook { OrganizationId = TestConstants.OrganizationId, Url = "http://localhost:40000/test", EventTypes = [WebHook.KnownEventTypes.StackPromoted], Version = WebHook.KnownVersions.Version2 - }); - await _repository.AddAsync(new WebHook - { - OrganizationId = TestConstants.OrganizationId, - ProjectId = TestConstants.ProjectId, - Url = "http://localhost:40000/test1", - EventTypes = + }, + new WebHook + { + OrganizationId = TestConstants.OrganizationId, + ProjectId = TestConstants.ProjectId, + Url = "http://localhost:40000/test1", + EventTypes = [WebHook.KnownEventTypes.StackPromoted], - Version = WebHook.KnownVersions.Version2 - }); - await _repository.AddAsync(new WebHook - { - OrganizationId = TestConstants.OrganizationId, - ProjectId = TestConstants.ProjectIdWithNoRoles, - Url = "http://localhost:40000/test1", - EventTypes = + Version = WebHook.KnownVersions.Version2 + }, + new WebHook + { + OrganizationId = TestConstants.OrganizationId, + ProjectId = TestConstants.ProjectIdWithNoRoles, + Url = "http://localhost:40000/test1", + EventTypes = [WebHook.KnownEventTypes.StackPromoted], - Version = WebHook.KnownVersions.Version2 - }); + Version = WebHook.KnownVersions.Version2 + }], o => o.ImmediateConsistency()); - await RefreshDataAsync(); Assert.Equal(3, (await _repository.GetByOrganizationIdAsync(TestConstants.OrganizationId)).Total); Assert.Equal(2, (await _repository.GetByOrganizationIdOrProjectIdAsync(TestConstants.OrganizationId, TestConstants.ProjectId)).Total); Assert.Equal(1, (await _repository.GetByProjectIdAsync(TestConstants.ProjectId)).Total); @@ -55,7 +55,7 @@ await _repository.AddAsync(new WebHook [Fact] public async Task CanSaveWebHookVersionAsync() { - await _repository.AddAsync(new WebHook + await _repository.AddAsync([new WebHook { OrganizationId = TestConstants.OrganizationId, ProjectId = TestConstants.ProjectId, @@ -63,18 +63,17 @@ await _repository.AddAsync(new WebHook EventTypes = [WebHook.KnownEventTypes.StackPromoted], Version = WebHook.KnownVersions.Version1 - }); - await _repository.AddAsync(new WebHook - { - OrganizationId = TestConstants.OrganizationId, - ProjectId = TestConstants.ProjectIdWithNoRoles, - Url = "http://localhost:40000/test1", - EventTypes = + }, + new WebHook + { + OrganizationId = TestConstants.OrganizationId, + ProjectId = TestConstants.ProjectIdWithNoRoles, + Url = "http://localhost:40000/test1", + EventTypes = [WebHook.KnownEventTypes.StackPromoted], - Version = WebHook.KnownVersions.Version2 - }); + Version = WebHook.KnownVersions.Version2 + }], o => o.ImmediateConsistency()); - await RefreshDataAsync(); Assert.Equal(WebHook.KnownVersions.Version1, (await _repository.GetByProjectIdAsync(TestConstants.ProjectId)).Documents.First().Version); Assert.Equal(WebHook.KnownVersions.Version2, (await _repository.GetByProjectIdAsync(TestConstants.ProjectIdWithNoRoles)).Documents.First().Version); } diff --git a/tests/Exceptionless.Tests/Services/StackServiceTests.cs b/tests/Exceptionless.Tests/Services/StackServiceTests.cs index 8a2abdfa54..c19ba11037 100644 --- a/tests/Exceptionless.Tests/Services/StackServiceTests.cs +++ b/tests/Exceptionless.Tests/Services/StackServiceTests.cs @@ -43,8 +43,8 @@ public async Task IncrementUsage_OnlyChangeCache() Assert.True(occurrenceSet.IsNull || !occurrenceSet.HasValue || occurrenceSet.Value.Count == 0); var firstUtcNow = SystemClock.UtcNow.Floor(TimeSpan.FromMilliseconds(1)); - await RefreshDataAsync(); await _stackService.IncrementStackUsageAsync(TestConstants.OrganizationId, TestConstants.ProjectId, stack.Id, firstUtcNow, firstUtcNow, 1); + await RefreshDataAsync(); // Assert stack state has no change after increment usage stack = await _stackRepository.GetByIdAsync(TestConstants.StackId); @@ -60,7 +60,6 @@ public async Task IncrementUsage_OnlyChangeCache() Assert.Single(occurrenceSet.Value); var secondUtcNow = SystemClock.UtcNow.Floor(TimeSpan.FromMilliseconds(1)); - await RefreshDataAsync(); await _stackService.IncrementStackUsageAsync(TestConstants.OrganizationId, TestConstants.ProjectId, stack.Id, secondUtcNow, secondUtcNow, 2); // Assert state in cache has been changed after increment usage again diff --git a/tests/Exceptionless.Tests/Stats/AggregationTests.cs b/tests/Exceptionless.Tests/Stats/AggregationTests.cs index f33e5cb0ce..e15204fd5c 100644 --- a/tests/Exceptionless.Tests/Stats/AggregationTests.cs +++ b/tests/Exceptionless.Tests/Stats/AggregationTests.cs @@ -207,16 +207,14 @@ public async Task CanGetSessionAggregationsAsync() private async Task CreateDataAsync(int eventCount = 0, bool multipleProjects = true) { - var orgs = OrganizationData.GenerateSampleOrganizations(_billingManager, _plans); - await _organizationRepository.AddAsync(orgs, o => o.Cache()); + var organizations = OrganizationData.GenerateSampleOrganizations(_billingManager, _plans); + await _organizationRepository.AddAsync(organizations, o => o.ImmediateConsistency().Cache()); var projects = ProjectData.GenerateSampleProjects(); - await _projectRepository.AddAsync(projects, o => o.Cache()); - await RefreshDataAsync(); + await _projectRepository.AddAsync(projects, o => o.ImmediateConsistency().Cache()); if (eventCount > 0) - await CreateEventsAsync(eventCount, multipleProjects ? projects.Select(p => p.Id).ToArray() : [TestConstants.ProjectId - ]); + await CreateEventsAsync(eventCount, multipleProjects ? projects.Select(p => p.Id).ToArray() : [TestConstants.ProjectId]); } private async Task CreateEventsAsync(int eventCount, string[]? projectIds, decimal? value = -1) From 247a0fe1dc85c10b1488ec8ce13f9342df9cbf17 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Fri, 1 Mar 2024 09:34:58 -0600 Subject: [PATCH 08/86] Discard fixed stack events that don't regress --- .../Pipeline/030_CheckForRegressionAction.cs | 18 +++- .../Pipeline/EventPipelineTests.cs | 88 ++++++++++++++++++- 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/src/Exceptionless.Core/Pipeline/030_CheckForRegressionAction.cs b/src/Exceptionless.Core/Pipeline/030_CheckForRegressionAction.cs index ede8dc7eb1..d5b052ec72 100644 --- a/src/Exceptionless.Core/Pipeline/030_CheckForRegressionAction.cs +++ b/src/Exceptionless.Core/Pipeline/030_CheckForRegressionAction.cs @@ -23,7 +23,7 @@ public CheckForRegressionAction(IStackRepository stackRepository, SemanticVersio public override async Task ProcessBatchAsync(ICollection contexts) { var stacks = contexts - .Where(c => c.Stack is not null && c.Stack.Status != StackStatus.Regressed && c.Stack.DateFixed.HasValue) + .Where(c => c.Stack is { Status: StackStatus.Fixed, DateFixed: not null }) .OrderBy(c => c.Event.Date) .GroupBy(c => c.Event.StackId); @@ -52,7 +52,16 @@ public override async Task ProcessBatchAsync(ICollection contexts) { var version = _semanticVersionParser.Parse(versionGroup.Key, versionCache) ?? _semanticVersionParser.Default; if (version < fixedInVersion) + { + foreach (var ctx in stackGroup.Where(s => s.Organization.HasPremiumFeatures)) + { + _logger.LogDebug("Discarding fixed stack event: Version {Version} is older than fixed in version {FixedInVersion}", version, fixedInVersion); + ctx.IsDiscarded = true; + ctx.IsCancelled = true; + } + continue; + } regressedVersion = version; regressedContext = versionGroup.First(); @@ -63,7 +72,7 @@ public override async Task ProcessBatchAsync(ICollection contexts) if (regressedContext is null) return; - _logger.LogTrace("Marking stack and events as regressed in version: {Version}", regressedVersion); + _logger.LogDebug("Marking stack and events as regressed in version: {Version}", regressedVersion); stack.Status = StackStatus.Regressed; await _stackRepository.MarkAsRegressedAsync(stack.Id); @@ -79,7 +88,10 @@ public override async Task ProcessBatchAsync(ICollection contexts) { cont = HandleError(ex, context); } - catch { } + catch (Exception hex) + { + _logger.LogError(hex, "Error calling HandleError: {Message}", ex.Message); + } if (!cont) context.SetError(ex.Message, ex); diff --git a/tests/Exceptionless.Tests/Pipeline/EventPipelineTests.cs b/tests/Exceptionless.Tests/Pipeline/EventPipelineTests.cs index 17d3c8dfdd..42d2871cc7 100644 --- a/tests/Exceptionless.Tests/Pipeline/EventPipelineTests.cs +++ b/tests/Exceptionless.Tests/Pipeline/EventPipelineTests.cs @@ -12,6 +12,7 @@ using Exceptionless.Core.Queues.Models; using Exceptionless.Core.Repositories; using Exceptionless.Core.Repositories.Configuration; +using Exceptionless.Core.Utility; using Exceptionless.DateTimeExtensions; using Exceptionless.Tests.Utility; using Foundatio.Repositories; @@ -929,7 +930,7 @@ public async Task WillHandleDiscardedStack() var organization = OrganizationData.GenerateSampleOrganization(_billingManager, _plans); var project = ProjectData.GenerateSampleProject(); - var ev = EventData.GenerateEvent(organizationId: TestConstants.OrganizationId, projectId: TestConstants.ProjectId, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow); + var ev = EventData.GenerateEvent(organizationId: organization.Id, projectId: project.Id, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow); var context = await _pipeline.RunAsync(ev, organization, project); Assert.True(context.IsProcessed); Assert.False(context.HasError); @@ -944,8 +945,7 @@ public async Task WillHandleDiscardedStack() stack.Status = StackStatus.Discarded; stack = await _stackRepository.SaveAsync(stack, o => o.ImmediateConsistency()); - - ev = EventData.GenerateEvent(organizationId: TestConstants.OrganizationId, projectId: TestConstants.ProjectId, stackId: ev.StackId, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow); + ev = EventData.GenerateEvent(organizationId: organization.Id, projectId: project.Id, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow); context = await _pipeline.RunAsync(ev, organization, project); Assert.False(context.IsProcessed); Assert.False(context.HasError); @@ -953,13 +953,93 @@ public async Task WillHandleDiscardedStack() Assert.True(context.IsDiscarded); await RefreshDataAsync(); - ev = EventData.GenerateEvent(organizationId: TestConstants.OrganizationId, projectId: TestConstants.ProjectId, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow); + ev = EventData.GenerateEvent(organizationId: organization.Id, projectId: project.Id, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow); context = await _pipeline.RunAsync(ev, organization, project); Assert.False(context.IsProcessed); Assert.False(context.HasError); Assert.True(context.IsCancelled); Assert.True(context.IsDiscarded); + } + + [Theory] + [InlineData(StackStatus.Regressed, false, null, null)] + [InlineData(StackStatus.Fixed, true, "1.0.0", null)] // A fixed stack should not be marked as regressed if the event has no version. + [InlineData(StackStatus.Regressed, false, null, "1.0.0")] + [InlineData(StackStatus.Regressed, false, "1.0.0", "1.0.0")] // A fixed stack should not be marked as regressed if the event has the same version. + [InlineData(StackStatus.Fixed, true, "2.0.0", "1.0.0")] + [InlineData(StackStatus.Regressed, false, null, "1.0.1")] + [InlineData(StackStatus.Regressed, false, "1.0.0", "1.0.1")] + public async Task CanDiscardStackEventsBasedOnEventVersion(StackStatus expectedStatus, bool expectedDiscard, string? stackFixedInVersion, string? eventSemanticVersion) + { + var organization = await _organizationRepository.GetByIdAsync(TestConstants.OrganizationId, o => o.Cache()); + var project = await _projectRepository.GetByIdAsync(TestConstants.ProjectId, o => o.Cache()); + + var ev = EventData.GenerateEvent(organizationId: organization.Id, projectId: project.Id, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow); + var context = await _pipeline.RunAsync(ev, organization, project); + + var stack = context.Stack; + Assert.NotNull(stack); + Assert.Equal(StackStatus.Open, stack.Status); + + Assert.True(context.IsProcessed); + Assert.False(context.HasError); + Assert.False(context.IsCancelled); + Assert.False(context.IsDiscarded); + + var semanticVersionParser = GetService(); + var fixedInVersion = semanticVersionParser.Parse(stackFixedInVersion); + stack.MarkFixed(fixedInVersion); + await _stackRepository.SaveAsync(stack, o => o.ImmediateConsistency()); + + await RefreshDataAsync(); + ev = EventData.GenerateEvent(organizationId: organization.Id, projectId: project.Id, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow, semver: eventSemanticVersion); + context = await _pipeline.RunAsync(ev, organization, project); + + stack = context.Stack; + Assert.NotNull(stack); + Assert.Equal(expectedStatus, stack.Status); + Assert.Equal(expectedDiscard, context.IsCancelled); + Assert.Equal(expectedDiscard, context.IsDiscarded); + } + + [Theory] + [InlineData("1.0.0", null)] // A fixed stack should not be marked as regressed if the event has no version. + [InlineData("2.0.0", "1.0.0")] + public async Task WillNotDiscardStackEventsBasedOnEventVersionWithFreePlan(string stackFixedInVersion, string? eventSemanticVersion) + { + var organization = await _organizationRepository.GetByIdAsync(TestConstants.OrganizationId3, o => o.Cache()); + + var plans = GetService(); + Assert.Equal(plans.FreePlan.Id, organization.PlanId); + + var project = await _projectRepository.AddAsync(ProjectData.GenerateProject(organizationId: organization.Id), o => o.ImmediateConsistency().Cache()); + + var ev = EventData.GenerateEvent(organizationId: organization.Id, projectId: project.Id, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow); + var context = await _pipeline.RunAsync(ev, organization, project); + + var stack = context.Stack; + Assert.NotNull(stack); + Assert.Equal(StackStatus.Open, stack.Status); + + Assert.True(context.IsProcessed); + Assert.False(context.HasError); + Assert.False(context.IsCancelled); + Assert.False(context.IsDiscarded); + + var semanticVersionParser = GetService(); + var fixedInVersion = semanticVersionParser.Parse(stackFixedInVersion); + stack.MarkFixed(fixedInVersion); + await _stackRepository.SaveAsync(stack, o => o.ImmediateConsistency()); + await RefreshDataAsync(); + ev = EventData.GenerateEvent(organizationId: organization.Id, projectId: project.Id, type: Event.KnownTypes.Log, source: "test", occurrenceDate: SystemClock.OffsetNow, semver: eventSemanticVersion); + context = await _pipeline.RunAsync(ev, organization, project); + + stack = context.Stack; + Assert.NotNull(stack); + Assert.Equal(StackStatus.Fixed, stack.Status); + Assert.False(context.IsCancelled); + Assert.False(context.IsDiscarded); } [Theory] From a5bb2bc3f59922ce0b5a38ffa37b578b2481244a Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 4 Mar 2024 07:50:49 -0600 Subject: [PATCH 09/86] Updated deps --- .../ClientApp/package-lock.json | 116 +++++++++--------- src/Exceptionless.Web/ClientApp/package.json | 14 +-- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index ce47e3aff5..75b0d557e2 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -10,16 +10,16 @@ "dependencies": { "@exceptionless/browser": "^3.0.5", "@iconify-json/mdi": "^1.1.64", - "@tanstack/svelte-query": "^5.24.1", - "@tanstack/svelte-query-devtools": "^5.24.1", + "@tanstack/svelte-query": "^5.24.8", + "@tanstack/svelte-query-devtools": "^5.24.8", "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.18.6", + "bits-ui": "^0.19.2", "class-validator": "^0.14.1", "clsx": "^2.1.0", - "cmdk-sv": "^0.0.13", + "cmdk-sv": "^0.0.14", "echarts": "^5.5.0", - "mode-watcher": "^0.2.1", + "mode-watcher": "^0.2.2", "oidc-client-ts": "^3.0.1", "pretty-ms": "^9.0.0", "svelte-echarts": "^0.1.1", @@ -33,13 +33,13 @@ "unplugin-icons": "^0.18.5" }, "devDependencies": { - "@playwright/test": "^1.42.0", + "@playwright/test": "^1.42.1", "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/kit": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^3.0.2", "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", - "autoprefixer": "^10.4.17", + "autoprefixer": "^10.4.18", "cross-env": "^7.0.3", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", @@ -982,9 +982,9 @@ } }, "node_modules/@melt-ui/svelte": { - "version": "0.74.4", - "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.74.4.tgz", - "integrity": "sha512-EeDP3C1grK+bPTezJQXKid2k4RRGZakyHTghD/zg//fM6Gqe4JykVtV0Yih4QJs+yGTgJq/EaNQMQ6JkTnvHxg==", + "version": "0.75.2", + "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.75.2.tgz", + "integrity": "sha512-EZYH5iEzHs/CPsWqRlH6AnJ70sTuPB4llVK3ajafWig6I5q3qyGU8NIz4aozUssL0edf9BKmyDVAy6Vksy1fbA==", "dependencies": { "@floating-ui/core": "^1.3.1", "@floating-ui/dom": "^1.4.5", @@ -1047,12 +1047,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.0.tgz", - "integrity": "sha512-2k1HzC28Fs+HiwbJOQDUwrWMttqSLUVdjCqitBOjdCD0svWOMQUVqrXX6iFD7POps6xXAojsX/dGBpKnjZctLA==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz", + "integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==", "dev": true, "dependencies": { - "playwright": "1.42.0" + "playwright": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -1343,9 +1343,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.24.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.24.1.tgz", - "integrity": "sha512-DZ6Nx9p7BhjkG50ayJ+MKPgff+lMeol7QYXkvuU5jr2ryW/4ok5eanaS9W5eooA4xN0A/GPHdLGOZGzArgf5Cg==", + "version": "5.24.8", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.24.8.tgz", + "integrity": "sha512-yH7KnfXMf10p1U5GffTQzFi2Miiw6WJZImGYGdV7eqa5ZbKO8qVx9lOA9SfhIaJXomrMp1Yz5w/CBhVM3yWeTA==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -1361,11 +1361,11 @@ } }, "node_modules/@tanstack/svelte-query": { - "version": "5.24.1", - "resolved": "https://registry.npmjs.org/@tanstack/svelte-query/-/svelte-query-5.24.1.tgz", - "integrity": "sha512-N1T15f1uwZJ2HADxupj+rDNmA7Ez7q+1D68Koqo7rAyWaRgl2V9gR7Oc/MLQM9LrFv6M768btwogDlE1LfvxLw==", + "version": "5.24.8", + "resolved": "https://registry.npmjs.org/@tanstack/svelte-query/-/svelte-query-5.24.8.tgz", + "integrity": "sha512-8oxwMDG3Ogb0oqcLZAo91gEJtAM5FQYBE66Fg5FxObLqMMxY0E9JEMqV24k/jkeT0/pOG+Pf9kz9zOjlQ3f8RQ==", "dependencies": { - "@tanstack/query-core": "5.24.1" + "@tanstack/query-core": "5.24.8" }, "funding": { "type": "github", @@ -1376,9 +1376,9 @@ } }, "node_modules/@tanstack/svelte-query-devtools": { - "version": "5.24.1", - "resolved": "https://registry.npmjs.org/@tanstack/svelte-query-devtools/-/svelte-query-devtools-5.24.1.tgz", - "integrity": "sha512-X7GbzmYJK/il6xkrYftx/HGdZ9DhV666ocJwPxLtGxTK/9eygHezFhelhsCwCeI0P+Wxs3E9LbC5C6eGQkklZA==", + "version": "5.24.8", + "resolved": "https://registry.npmjs.org/@tanstack/svelte-query-devtools/-/svelte-query-devtools-5.24.8.tgz", + "integrity": "sha512-sIkgiMcptj9hsg0qHTwO1OmUaByJhMwlnSDOBwKiEpvavKOQ2G2WXvtwzYyODqJ3QKOKXqa3Nqu1QQJkYSLtlw==", "dependencies": { "@tanstack/query-devtools": "5.24.0", "esm-env": "^1.0.0" @@ -1388,7 +1388,7 @@ "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "@tanstack/svelte-query": "^5.24.1", + "@tanstack/svelte-query": "^5.24.8", "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0" } }, @@ -2027,9 +2027,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.17", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", - "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", + "version": "10.4.18", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz", + "integrity": "sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==", "dev": true, "funding": [ { @@ -2046,8 +2046,8 @@ } ], "dependencies": { - "browserslist": "^4.22.2", - "caniuse-lite": "^1.0.30001578", + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001591", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -2097,12 +2097,12 @@ } }, "node_modules/bits-ui": { - "version": "0.18.6", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.18.6.tgz", - "integrity": "sha512-UbBFuyG7qEM+VA1rA/7GRy94rXRFCW+B1LfK7uiBd6fZiPZtPmPPW1RjTblGaJjCW2E6e/ruxbuKjxW2oXDP7g==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.19.2.tgz", + "integrity": "sha512-cB5TZPztgd3t93BM4v3M81ve9xWPML9Mb5Db8j8NcSiZaIYEc7At7LB2GX/YCl+AkFI53R8QUa4STbIcBB5isQ==", "dependencies": { "@internationalized/date": "^3.5.1", - "@melt-ui/svelte": "0.74.4", + "@melt-ui/svelte": "0.75.2", "nanoid": "^5.0.5" }, "peerDependencies": { @@ -2147,9 +2147,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -2166,8 +2166,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -2233,9 +2233,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001579", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz", - "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==", + "version": "1.0.30001591", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", + "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", "dev": true, "funding": [ { @@ -2386,9 +2386,9 @@ } }, "node_modules/cmdk-sv": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/cmdk-sv/-/cmdk-sv-0.0.13.tgz", - "integrity": "sha512-WrYn0MMdVyzJx+KuOQy028/7mv+uMwO1cxVBM0uJ4KA+50PX792epsj8Yw3It8WfWR8Rae7siBCg54mIAlKsiw==", + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/cmdk-sv/-/cmdk-sv-0.0.14.tgz", + "integrity": "sha512-6S0dTwOpW8K1v49eoUUwhi99zHaujoJKaJqNfzXzn8+hczS6Skl9tHsketRFymQpdlTWOi8gPbMSl3LUyYpZkw==", "dependencies": { "bits-ui": "^0.9.0", "nanoid": "^5.0.2" @@ -2752,9 +2752,9 @@ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" }, "node_modules/electron-to-chromium": { - "version": "1.4.642", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.642.tgz", - "integrity": "sha512-M4+u22ZJGpk4RY7tne6W+APkZhnnhmAH48FNl8iEFK2lEgob+U5rUQsIqQhvAwCXYpfd3H20pHK/ENsCvwTbsA==", + "version": "1.4.690", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.690.tgz", + "integrity": "sha512-+2OAGjUx68xElQhydpcbqH50hE8Vs2K6TkAeLhICYfndb67CVH0UsZaijmRUE3rHlIxU1u0jxwhgVe6fK3YANA==", "dev": true }, "node_modules/emoji-regex": { @@ -4392,9 +4392,9 @@ } }, "node_modules/mode-watcher": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-0.2.1.tgz", - "integrity": "sha512-HLmJgG5kmJCFR/+rcG2te54HjIxqk7BTAsFnsygZR5hcOYlhLEJQ0V8rh1axv2JQIbOAZs1yPlUBSpVATRFtUw==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-0.2.2.tgz", + "integrity": "sha512-QjkHQL9pXrr7Vb0P3WbOWAF8mv1Q6jEwUZ5GUyCnI9eEoXH234zuaOGChUF7ZQtjxwtmXDzKFSW/36TvLDg1/A==", "peerDependencies": { "svelte": "^4.0.0" } @@ -5122,12 +5122,12 @@ } }, "node_modules/playwright": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0.tgz", - "integrity": "sha512-Ko7YRUgj5xBHbntrgt4EIw/nE//XBHOKVKnBjO1KuZkmkhlbgyggTe5s9hjqQ1LpN+Xg+kHsQyt5Pa0Bw5XpvQ==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", + "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==", "dev": true, "dependencies": { - "playwright-core": "1.42.0" + "playwright-core": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -5140,9 +5140,9 @@ } }, "node_modules/playwright-core": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0.tgz", - "integrity": "sha512-0HD9y8qEVlcbsAjdpBaFjmaTHf+1FeIddy8VJLeiqwhcNqGCBe4Wp2e8knpqiYbzxtxarxiXyNDw2cG8sCaNMQ==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz", + "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==", "dev": true, "bin": { "playwright-core": "cli.js" diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index a692307ee0..3b8b474872 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -21,13 +21,13 @@ "upgrade": "ncu -i" }, "devDependencies": { - "@playwright/test": "^1.42.0", + "@playwright/test": "^1.42.1", "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/kit": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^3.0.2", "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", - "autoprefixer": "^10.4.17", + "autoprefixer": "^10.4.18", "cross-env": "^7.0.3", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", @@ -48,16 +48,16 @@ "dependencies": { "@exceptionless/browser": "^3.0.5", "@iconify-json/mdi": "^1.1.64", - "@tanstack/svelte-query": "^5.24.1", - "@tanstack/svelte-query-devtools": "^5.24.1", + "@tanstack/svelte-query": "^5.24.8", + "@tanstack/svelte-query-devtools": "^5.24.8", "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.18.6", + "bits-ui": "^0.19.2", "class-validator": "^0.14.1", "clsx": "^2.1.0", - "cmdk-sv": "^0.0.13", + "cmdk-sv": "^0.0.14", "echarts": "^5.5.0", - "mode-watcher": "^0.2.1", + "mode-watcher": "^0.2.2", "oidc-client-ts": "^3.0.1", "pretty-ms": "^9.0.0", "svelte-echarts": "^0.1.1", From 123b0218da90b86e3a9200979513816e16ea6563 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 4 Mar 2024 07:51:04 -0600 Subject: [PATCH 10/86] Fixed linting error --- src/Exceptionless.Web/ClientApp/src/lib/api/projectsApi.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/api/projectsApi.ts b/src/Exceptionless.Web/ClientApp/src/lib/api/projectsApi.ts index fa951ea381..42ea1b7ba8 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/api/projectsApi.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/api/projectsApi.ts @@ -35,10 +35,10 @@ export function mutatePromoteTab(id: string) { const client = useQueryClient(); return createMutation, ProblemDetails, { name: string }>({ mutationKey: queryKeys.id(id), - mutationFn: async ({ name }) => { + mutationFn: async (params: { name: string }) => { const { post } = new FetchClient(); const response = await post(`projects/${id}/promotedtabs`, undefined, { - params: { name } + params }); if (response.ok) { From 139f50a1b4617253a43f559303ee2e608cc6bd22 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 4 Mar 2024 07:51:31 -0600 Subject: [PATCH 11/86] WIP - Faceted Filters --- .../data-table-faceted-filter-builder.svelte | 97 ------------------- ...data-table-faceted-filter-container.svelte | 22 ----- .../src/lib/components/data-table/index.ts | 9 -- .../events/facets/StatusFacetedFilter.svelte | 21 ++++ .../events/facets/TypeFacetedFilter.svelte | 21 ++++ .../facets/faceted-filter-builder.svelte | 94 ++++++++++++++++++ .../faceted-filter-dropdown.svelte} | 50 +++++----- .../src/lib/components/facets/index.ts | 10 ++ .../ClientApp/src/routes/(app)/+page.svelte | 62 ++++-------- 9 files changed, 189 insertions(+), 197 deletions(-) delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-container.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/StatusFacetedFilter.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/TypeFacetedFilter.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-builder.svelte rename src/Exceptionless.Web/ClientApp/src/lib/components/{data-table/data-table-faceted-filter.svelte => facets/faceted-filter-dropdown.svelte} (69%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/components/facets/index.ts diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte deleted file mode 100644 index ea88ab684e..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-builder.svelte +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - No results found. - - {#each options as option (option.value)} - -
- -
- - {option.label} - -
- {/each} -
- {#if values.length > 0} - - Clear filters - {/if} -
-
-
-
- -{#each values as type (type)} - -{/each} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-container.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-container.svelte deleted file mode 100644 index 776a384758..0000000000 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter-container.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - - -{#if $showReset} - -{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts index 59f23407c7..c907a941d5 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/index.ts @@ -1,9 +1,6 @@ import Root from './data-table.svelte'; import Body from './data-table-body.svelte'; import Toolbar from './data-table-toolbar.svelte'; -import FacetedFilterBuilder from './data-table-faceted-filter-builder.svelte'; -import FacetedFilterContainer from './data-table-faceted-filter-container.svelte'; -import FacetedFilter from './data-table-faceted-filter.svelte'; import PageSize from './data-table-page-size.svelte'; import Pagination from './data-table-pagination.svelte'; @@ -11,18 +8,12 @@ export { Root, Body, Toolbar, - FacetedFilterBuilder, - FacetedFilterContainer, - FacetedFilter, PageSize, Pagination, // Root as DataTable, Body as DataTableBody, Toolbar as DataTableToolbar, - FacetedFilterBuilder as DataTableFacetedFilterBuilder, - FacetedFilterContainer as DataTableFacetedFilterContainer, - FacetedFilter as DataTableFacetedFilter, PageSize as DataTablePageSize, Pagination as DataTablePagination }; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/StatusFacetedFilter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/StatusFacetedFilter.svelte new file mode 100644 index 0000000000..e4afa1e8a8 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/StatusFacetedFilter.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/TypeFacetedFilter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/TypeFacetedFilter.svelte new file mode 100644 index 0000000000..c2feb79770 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/TypeFacetedFilter.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-builder.svelte new file mode 100644 index 0000000000..32edf839a6 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-builder.svelte @@ -0,0 +1,94 @@ + + + + + + + + + + + No results found. + + {#each facets as facet (facet.type)} + +
+ +
+ + {facet.title} + +
+ {/each} +
+ {#if visible.length > 0} + + Clear filters + {/if} +
+
+
+
+ +{#each facets as facet (facet.type)} + {#if visible.includes(facet.type)} + + {/if} +{/each} + +{#if visible.length > 0} + +{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte similarity index 69% rename from src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte index 7621b08334..d7d0e9b283 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/data-table/data-table-faceted-filter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte @@ -1,38 +1,40 @@ @@ -53,10 +55,12 @@ {values.length} Selected {:else} - {#each values as option (option)} - - {option} - + {#each options as option (option.value)} + {#if values.includes(option.value)} + + {option.label} + + {/if} {/each} {/if} @@ -85,15 +89,11 @@ {/each} - {#if values.length > 0 || onRemoveFilter} - - {/if} + {#if values.length > 0} - Clear filters - {/if} - {#if onRemoveFilter} - Remove filter + Clear filter {/if} + Remove filter diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/index.ts new file mode 100644 index 0000000000..f6662676dd --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/index.ts @@ -0,0 +1,10 @@ +import Root from './faceted-filter-builder.svelte'; +import Dropdown from './faceted-filter-dropdown.svelte'; + +export { + Root, + Dropdown, + // + Root as FacetedFilterBuilder, + Dropdown as FacetedFilterDropdown +}; diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index 89f616c44a..754cfe011a 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -1,7 +1,7 @@ @@ -42,35 +44,7 @@ - - - - {#if type === 'status'} - console.log('onRemoveFilter')} - > - {:else if type === 'type'} - - {/if} - - - + From 3b9f369460efd99f6b66a3a6a8854500239a8537 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 4 Mar 2024 07:51:50 -0600 Subject: [PATCH 12/86] Fixed component typing --- src/Exceptionless.Web/ClientApp/src/routes/routes.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Exceptionless.Web/ClientApp/src/routes/routes.ts b/src/Exceptionless.Web/ClientApp/src/routes/routes.ts index cf22b77c87..170e853a2f 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/routes.ts +++ b/src/Exceptionless.Web/ClientApp/src/routes/routes.ts @@ -1,4 +1,5 @@ import type { User } from '$lib/models/api'; +import type { ComponentType } from 'svelte'; import { routes as appRoutes } from './(app)/routes'; import { routes as authRoutes } from './(auth)/routes'; @@ -11,7 +12,7 @@ export type NavigationItem = { group: string; title: string; href: string; - icon: ConstructorOfATypedSvelteComponent; + icon: ComponentType; show?: (context: NavigationItemContext) => boolean; }; From 23a92cb1ff64501ca63fa6d76de0b08da82a604a Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 5 Mar 2024 07:54:18 -0600 Subject: [PATCH 13/86] Updated deps --- .../ClientApp/package-lock.json | 112 +++++++++--------- src/Exceptionless.Web/ClientApp/package.json | 10 +- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index 75b0d557e2..dfa90da5a1 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -14,10 +14,10 @@ "@tanstack/svelte-query-devtools": "^5.24.8", "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.19.2", + "bits-ui": "^0.19.3", "class-validator": "^0.14.1", "clsx": "^2.1.0", - "cmdk-sv": "^0.0.14", + "cmdk-sv": "^0.0.15", "echarts": "^5.5.0", "mode-watcher": "^0.2.2", "oidc-client-ts": "^3.0.1", @@ -37,8 +37,8 @@ "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/kit": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", "autoprefixer": "^10.4.18", "cross-env": "^7.0.3", "eslint": "^8.57.0", @@ -54,7 +54,7 @@ "swagger-typescript-api": "^13.0.3", "tslib": "^2.6.2", "typescript": "^5.4.0-beta", - "vite": "^5.1.4", + "vite": "^5.1.5", "vitest": "^1.3.1" } }, @@ -1471,16 +1471,16 @@ "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz", - "integrity": "sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", + "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/type-utils": "7.1.0", - "@typescript-eslint/utils": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/type-utils": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1532,15 +1532,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.0.tgz", - "integrity": "sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", + "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4" }, "engines": { @@ -1560,13 +1560,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz", - "integrity": "sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0" + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1577,13 +1577,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz", - "integrity": "sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", + "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.1.0", - "@typescript-eslint/utils": "7.1.0", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/utils": "7.1.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1630,9 +1630,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.0.tgz", - "integrity": "sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1643,13 +1643,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz", - "integrity": "sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/visitor-keys": "7.1.0", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1721,17 +1721,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.0.tgz", - "integrity": "sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.0", - "@typescript-eslint/types": "7.1.0", - "@typescript-eslint/typescript-estree": "7.1.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", "semver": "^7.5.4" }, "engines": { @@ -1746,12 +1746,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz", - "integrity": "sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.0", + "@typescript-eslint/types": "7.1.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2097,9 +2097,9 @@ } }, "node_modules/bits-ui": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.19.2.tgz", - "integrity": "sha512-cB5TZPztgd3t93BM4v3M81ve9xWPML9Mb5Db8j8NcSiZaIYEc7At7LB2GX/YCl+AkFI53R8QUa4STbIcBB5isQ==", + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.19.3.tgz", + "integrity": "sha512-0qqZ1bwE4ZmTnzTdsl4mYEbHY5f0NVgxhddIqscLjJZx4ltkVKDXxBwEusbE2NToqKtXNNrU0wy7sLusdzdhcg==", "dependencies": { "@internationalized/date": "^3.5.1", "@melt-ui/svelte": "0.75.2", @@ -2386,9 +2386,9 @@ } }, "node_modules/cmdk-sv": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/cmdk-sv/-/cmdk-sv-0.0.14.tgz", - "integrity": "sha512-6S0dTwOpW8K1v49eoUUwhi99zHaujoJKaJqNfzXzn8+hczS6Skl9tHsketRFymQpdlTWOi8gPbMSl3LUyYpZkw==", + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/cmdk-sv/-/cmdk-sv-0.0.15.tgz", + "integrity": "sha512-WDEGJwjW30XZnfNXONeh7kQtmPF6e4UTNrDXQCiAWuafDu9odY3qhQpfNrq4pb5mqaZeKQgVtx+4LIojUv7GJw==", "dependencies": { "bits-ui": "^0.9.0", "nanoid": "^5.0.2" @@ -7075,9 +7075,9 @@ } }, "node_modules/vite": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz", - "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.5.tgz", + "integrity": "sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==", "dev": true, "dependencies": { "esbuild": "^0.19.3", diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index 3b8b474872..56075bcda9 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -25,8 +25,8 @@ "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/kit": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", "autoprefixer": "^10.4.18", "cross-env": "^7.0.3", "eslint": "^8.57.0", @@ -42,7 +42,7 @@ "swagger-typescript-api": "^13.0.3", "tslib": "^2.6.2", "typescript": "^5.4.0-beta", - "vite": "^5.1.4", + "vite": "^5.1.5", "vitest": "^1.3.1" }, "dependencies": { @@ -52,10 +52,10 @@ "@tanstack/svelte-query-devtools": "^5.24.8", "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.19.2", + "bits-ui": "^0.19.3", "class-validator": "^0.14.1", "clsx": "^2.1.0", - "cmdk-sv": "^0.0.14", + "cmdk-sv": "^0.0.15", "echarts": "^5.5.0", "mode-watcher": "^0.2.2", "oidc-client-ts": "^3.0.1", From 51df3b4c199640d7e7ac901bfa83eee74094a6a4 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 5 Mar 2024 07:56:22 -0600 Subject: [PATCH 14/86] WIP: Faceted Filters --- .../events/facets/StatusFacetedFilter.svelte | 8 ++-- .../events/facets/TypeFacetedFilter.svelte | 8 ++-- .../facets/faceted-filter-builder.svelte | 33 +++++++------ .../facets/faceted-filter-dropdown.svelte | 1 + .../src/lib/components/filters/filters.ts | 46 +++++++++++++++++-- .../ClientApp/src/lib/stores/events.ts | 6 --- .../ClientApp/src/routes/(app)/+page.svelte | 9 ++-- 7 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/StatusFacetedFilter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/StatusFacetedFilter.svelte index e4afa1e8a8..88e32c6ad3 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/StatusFacetedFilter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/StatusFacetedFilter.svelte @@ -2,14 +2,12 @@ import { stackStatuses } from '$comp/events/options'; import { FacetedFilterDropdown } from '$comp/facets'; import { StatusFilter } from '$comp/filters/filters'; - import type { StackStatus } from '$lib/models/api'; import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); - const filter = new StatusFilter([]); + export let filter: StatusFilter; - function onChanged({ detail }: CustomEvent) { - filter.values = detail; + function onChanged() { dispatch('changed', filter); } @@ -18,4 +16,4 @@ } - + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/TypeFacetedFilter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/TypeFacetedFilter.svelte index c2feb79770..36f7d939a5 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/TypeFacetedFilter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/TypeFacetedFilter.svelte @@ -2,14 +2,12 @@ import { eventTypes } from '$comp/events/options'; import { FacetedFilterDropdown } from '$comp/facets'; import { TypeFilter } from '$comp/filters/filters'; - import type { PersistentEventKnownTypes } from '$lib/models/api'; import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); - const filter = new TypeFilter([]); + export let filter: TypeFilter; - function onChanged({ detail }: CustomEvent) { - filter.values = detail; + function onChanged() { dispatch('changed', filter); } @@ -18,4 +16,4 @@ } - + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-builder.svelte index 32edf839a6..1067b5c0aa 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-builder.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-builder.svelte @@ -11,34 +11,33 @@ import { createEventDispatcher, type ComponentType } from 'svelte'; const dispatch = createEventDispatcher(); - let visible: string[] = []; + let visible: FacetedFilter[] = []; - type FacetedFilter = { title: string; type: string; component: ComponentType; filter?: IFilter }; + type FacetedFilter = { title: string; component: ComponentType; filter: IFilter }; export let facets: FacetedFilter[] = []; let open = false; - function onFacetSelected(type: string) { - if (visible.includes(type)) { - visible = visible.filter((item) => item !== type); + function onFacetSelected(facet: FacetedFilter) { + if (visible.includes(facet)) { + facet.filter.reset(); + visible = visible.filter((f) => f !== facet); } else { - visible = [...visible, type]; + visible = [...visible, facet]; } - console.log('selected', visible); } function onChanged({ detail }: CustomEvent) { - console.log('changed', detail.toFilter()); dispatch('changed', detail); } function onRemove({ detail }: CustomEvent) { - console.log('remove', detail.type); - visible = visible.filter((item) => item !== detail.type); + detail.reset(); + visible = visible.filter((item) => item.filter.type !== detail.type); } function onRemoveAll() { - console.log('remove all'); + facets.forEach((facet) => facet.filter.reset()); visible = []; } @@ -55,12 +54,12 @@ No results found. - {#each facets as facet (facet.type)} - + {#each facets as facet (facet.filter.type)} + onFacetSelected(facet)}>
@@ -80,9 +79,9 @@ -{#each facets as facet (facet.type)} - {#if visible.includes(facet.type)} - +{#each facets as facet (facet.filter.type)} + {#if visible.includes(facet)} + {/if} {/each} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte index d7d0e9b283..ebeab5283c 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte @@ -34,6 +34,7 @@ } function onRemoveFilter(): void { + values = []; dispatch('remove'); } diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts index 411e4a66a4..593531dfca 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/filters.ts @@ -5,8 +5,10 @@ import type { Serializer } from 'svelte-local-storage-store'; export interface IFilter { readonly type: string; toFilter(): string; + reset(): void; } +// TODO: Consider removing. export interface IFacetedFilter extends IFilter { term: string; values: unknown[]; @@ -28,6 +30,10 @@ export class BooleanFilter implements IFilter { return `${this.term}:${this.value}`; } + + public reset(): void { + this.value = undefined; + } } export class DateFilter implements IFilter { @@ -46,6 +52,10 @@ export class DateFilter implements IFilter { const date = this.value instanceof Date ? this.value.toISOString() : this.value; return `${this.term}:${quoteIfSpecialCharacters(date)}`; } + + public reset(): void { + this.value = undefined; + } } export class KeywordFilter implements IFilter { @@ -56,6 +66,10 @@ export class KeywordFilter implements IFilter { public toFilter(): string { return this.keyword; } + + public reset(): void { + this.keyword = ''; + } } export class NumberFilter implements IFilter { @@ -73,6 +87,10 @@ export class NumberFilter implements IFilter { return `${this.term}:${this.value}`; } + + public reset(): void { + this.value = undefined; + } } export class ReferenceFilter implements IFilter { @@ -83,6 +101,10 @@ export class ReferenceFilter implements IFilter { public toFilter(): string { return `reference:${quoteIfSpecialCharacters(this.referenceId)}`; } + + public reset(): void { + this.referenceId = ''; + } } export class SessionFilter implements IFilter { @@ -94,6 +116,10 @@ export class SessionFilter implements IFilter { const session = quoteIfSpecialCharacters(this.sessionId); return `(reference:${session} OR ref.session:${session})`; } + + public reset(): void { + this.sessionId = ''; + } } export class StatusFilter implements IFacetedFilter { @@ -114,6 +140,10 @@ export class StatusFilter implements IFacetedFilter { return `(${this.values.map((val) => `${this.term}:${val}`).join(' OR ')})`; } + + public reset(): void { + this.values = []; + } } export class StringFilter implements IFilter { @@ -131,6 +161,10 @@ export class StringFilter implements IFilter { return `${this.term}:${quoteIfSpecialCharacters(this.value)}`; } + + public reset(): void { + this.value = undefined; + } } export class TypeFilter implements IFacetedFilter { @@ -151,6 +185,10 @@ export class TypeFilter implements IFacetedFilter { return `(${this.values.map((val) => `${this.term}:${val}`).join(' OR ')})`; } + + public reset(): void { + this.values = []; + } } export class VersionFilter implements IFilter { @@ -168,6 +206,10 @@ export class VersionFilter implements IFilter { return `${this.term}:${quoteIfSpecialCharacters(this.value)}`; } + + public reset(): void { + this.value = undefined; + } } export function quoteIfSpecialCharacters(value?: string | null): string | null | undefined { @@ -219,7 +261,6 @@ export function toggleFilter(filters: IFilter[], filter: IFilter): IFilter[] { */ export function upsertOrRemoveFacetFilter(filters: IFilter[], filter: IFacetedFilter): boolean { const index = filters.findIndex((f) => f.type === filter.type && isFaceted(f)); - console.log('upsertOrRemoveFacetFilter', filter, index, filters); // If the filter has no values, remove it. if (!filter.values || filter.values.length == 0) { @@ -289,7 +330,7 @@ export function parseFilter(filters: IFilter[], input: string): IFilter[] { return resolvedFilters; } -export function getFilter(filter: Omit & Record): IFilter | undefined { +export function getFilter(filter: Omit & Record): IFilter | undefined { switch (filter.type) { case 'boolean': return new BooleanFilter(filter.term as string, filter.value as boolean); @@ -327,7 +368,6 @@ export function toFilterTypes(filters: IFilter[]): string[] { } } - console.log(Array.from(types)); return Array.from(types); } diff --git a/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts b/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts index a6a733f350..e2074de7f0 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts @@ -41,10 +41,8 @@ export function updateFilter(filter: IFilter) { export function updateFilterValues(key: string, values: unknown[]) { const filter = getFilter({ type: key, values }) as IFacetedFilter; const currentFilters = get(filters); - console.log('updateFilterValues', filter, currentFilters); if (filter && upsertOrRemoveFacetFilter(currentFilters, filter)) { filters.set(currentFilters); - console.log('updateFilterValues', currentFilters); } } @@ -72,10 +70,6 @@ export function onFacetValuesChanged(facetKey: string, updatedValues: unknown[]) export function onToggleFacetFilterChanged(facetKey: string) { const currentFilters = get(filters); const filter = currentFilters.find((f) => f.type === facetKey); - console.log( - facetKey, - currentFilters.find((f) => f.type === facetKey) - ); if (filter) { toggleFilter(currentFilters, filter); } else { diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index 754cfe011a..e231aff49d 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -15,6 +15,7 @@ import { Button } from '$comp/ui/button'; import StatusFacetedFilter from '$comp/events/facets/StatusFacetedFilter.svelte'; import TypeFacetedFilter from '$comp/events/facets/TypeFacetedFilter.svelte'; + import { StatusFilter, TypeFilter } from '$comp/filters/filters'; let selectedEventId: string | null = null; function onRowClick({ detail }: CustomEvent>) { @@ -24,13 +25,13 @@ const facets = [ { title: 'Status', - type: 'status', - component: StatusFacetedFilter + component: StatusFacetedFilter, + filter: new StatusFilter([]) }, { title: 'Type', - type: 'type', - component: TypeFacetedFilter + component: TypeFacetedFilter, + filter: new TypeFilter([]) } ]; From 2b6edba07f8701906cfd23772a80000b7a2ac809 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 5 Mar 2024 07:58:22 -0600 Subject: [PATCH 15/86] Updated minver --- .github/workflows/build-arm64.yml | 2 +- .github/workflows/build.yaml | 2 +- .github/workflows/elasticsearch-docker-7.yml | 2 +- .github/workflows/elasticsearch-docker-8.yml | 2 +- src/Directory.Build.props | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-arm64.yml b/.github/workflows/build-arm64.yml index 2ff9bcaa82..cc8cc4b8e8 100644 --- a/.github/workflows/build-arm64.yml +++ b/.github/workflows/build-arm64.yml @@ -33,7 +33,7 @@ jobs: run: "echo ref: ${{github.ref}} event: ${{github.event_name}}" - name: Build Version run: | - dotnet tool install --global minver-cli --version 4.3.0 + dotnet tool install --global minver-cli --version 5.0.0 version=$(minver --tag-prefix v) echo "MINVERVERSIONOVERRIDE=$version" >> $GITHUB_ENV echo "VERSION=$version" >> $GITHUB_ENV diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 85863d9568..93c8cc680a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -38,7 +38,7 @@ jobs: - name: Version id: version run: | - dotnet tool install --global minver-cli --version 4.3.0 + dotnet tool install --global minver-cli --version 5.0.0 version=$(minver --tag-prefix v) echo "version=$version" >> $GITHUB_OUTPUT echo "### $version" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/elasticsearch-docker-7.yml b/.github/workflows/elasticsearch-docker-7.yml index 7fe17f147f..fa044a20ef 100644 --- a/.github/workflows/elasticsearch-docker-7.yml +++ b/.github/workflows/elasticsearch-docker-7.yml @@ -26,7 +26,7 @@ jobs: run: "echo ref: ${{github.ref}} event: ${{github.event_name}}" - name: Build Version run: | - dotnet tool install --global minver-cli --version 4.3.0 + dotnet tool install --global minver-cli --version 5.0.0 version=$(minver --tag-prefix v) echo "MINVERVERSIONOVERRIDE=$version" >> $GITHUB_ENV echo "VERSION=$version" >> $GITHUB_ENV diff --git a/.github/workflows/elasticsearch-docker-8.yml b/.github/workflows/elasticsearch-docker-8.yml index 9f22cbd251..7c1d8bbecc 100644 --- a/.github/workflows/elasticsearch-docker-8.yml +++ b/.github/workflows/elasticsearch-docker-8.yml @@ -26,7 +26,7 @@ jobs: run: "echo ref: ${{github.ref}} event: ${{github.event_name}}" - name: Build Version run: | - dotnet tool install --global minver-cli --version 4.3.0 + dotnet tool install --global minver-cli --version 5.0.0 version=$(minver --tag-prefix v) echo "MINVERVERSIONOVERRIDE=$version" >> $GITHUB_ENV echo "VERSION=$version" >> $GITHUB_ENV diff --git a/src/Directory.Build.props b/src/Directory.Build.props index bd755e5e63..df78ac38a5 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -22,6 +22,6 @@ - + From 883d75b47a1bab7009e960a615429223162f5be4 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 5 Mar 2024 08:02:02 -0600 Subject: [PATCH 16/86] Updated dependencies --- src/Exceptionless.Insulation/Exceptionless.Insulation.csproj | 2 +- tests/Exceptionless.Tests/Exceptionless.Tests.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj b/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj index 583b4d56d4..66252c94f1 100644 --- a/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj +++ b/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj @@ -15,7 +15,7 @@ - + diff --git a/tests/Exceptionless.Tests/Exceptionless.Tests.csproj b/tests/Exceptionless.Tests/Exceptionless.Tests.csproj index e6364ae1aa..fed261b191 100644 --- a/tests/Exceptionless.Tests/Exceptionless.Tests.csproj +++ b/tests/Exceptionless.Tests/Exceptionless.Tests.csproj @@ -8,7 +8,7 @@ - + From 8b5ceda51fbea6f54206d806295aeb23db36b603 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Wed, 6 Mar 2024 06:13:36 -0600 Subject: [PATCH 17/86] Updated copy year --- src/Directory.Build.props | 2 +- src/Exceptionless.Web/ClientApp.angular/app/app.tpl.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index df78ac38a5..05dc4b3936 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,7 +5,7 @@ Exceptionless true v - Copyright (c) 2023 Exceptionless. All rights reserved. + Copyright (c) 2024 Exceptionless. All rights reserved. https://github.com/exceptionless/exceptionless Exceptionless $(NoWarn);CS1591 diff --git a/src/Exceptionless.Web/ClientApp.angular/app/app.tpl.html b/src/Exceptionless.Web/ClientApp.angular/app/app.tpl.html index 838ca1d235..49b42df70e 100644 --- a/src/Exceptionless.Web/ClientApp.angular/app/app.tpl.html +++ b/src/Exceptionless.Web/ClientApp.angular/app/app.tpl.html @@ -30,7 +30,7 @@ > - © 2023 Exceptionless + © 2024 Exceptionless Exceptionless + © 2024 Exceptionless News Privacy Policy Terms of Use From afb01473f91298308acac8e37955e419e5f21285 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Wed, 6 Mar 2024 06:54:25 -0600 Subject: [PATCH 18/86] Updated deps --- .../ClientApp/package-lock.json | 42 +++++++++---------- src/Exceptionless.Web/ClientApp/package.json | 6 +-- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index dfa90da5a1..f528c6532e 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -10,11 +10,11 @@ "dependencies": { "@exceptionless/browser": "^3.0.5", "@iconify-json/mdi": "^1.1.64", - "@tanstack/svelte-query": "^5.24.8", - "@tanstack/svelte-query-devtools": "^5.24.8", + "@tanstack/svelte-query": "^5.25.0", + "@tanstack/svelte-query-devtools": "^5.25.0", "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.19.3", + "bits-ui": "^0.19.4", "class-validator": "^0.14.1", "clsx": "^2.1.0", "cmdk-sv": "^0.0.15", @@ -982,9 +982,9 @@ } }, "node_modules/@melt-ui/svelte": { - "version": "0.75.2", - "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.75.2.tgz", - "integrity": "sha512-EZYH5iEzHs/CPsWqRlH6AnJ70sTuPB4llVK3ajafWig6I5q3qyGU8NIz4aozUssL0edf9BKmyDVAy6Vksy1fbA==", + "version": "0.75.3", + "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.75.3.tgz", + "integrity": "sha512-EA2IKn7w9qtzO/M7VEENpphQ9A4az+QDMQbA8SJLuKyu+S8NWliln5y9vvmnx9dZF8GtKtUKuxpwRNyPg5LAOg==", "dependencies": { "@floating-ui/core": "^1.3.1", "@floating-ui/dom": "^1.4.5", @@ -1343,9 +1343,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.24.8", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.24.8.tgz", - "integrity": "sha512-yH7KnfXMf10p1U5GffTQzFi2Miiw6WJZImGYGdV7eqa5ZbKO8qVx9lOA9SfhIaJXomrMp1Yz5w/CBhVM3yWeTA==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.25.0.tgz", + "integrity": "sha512-vlobHP64HTuSE68lWF1mEhwSRC5Q7gaT+a/m9S+ItuN+ruSOxe1rFnR9j0ACWQ314BPhBEVKfBQ6mHL0OWfdbQ==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -1361,11 +1361,11 @@ } }, "node_modules/@tanstack/svelte-query": { - "version": "5.24.8", - "resolved": "https://registry.npmjs.org/@tanstack/svelte-query/-/svelte-query-5.24.8.tgz", - "integrity": "sha512-8oxwMDG3Ogb0oqcLZAo91gEJtAM5FQYBE66Fg5FxObLqMMxY0E9JEMqV24k/jkeT0/pOG+Pf9kz9zOjlQ3f8RQ==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@tanstack/svelte-query/-/svelte-query-5.25.0.tgz", + "integrity": "sha512-R02jzxjGmclRoCnMHvQhSQYHsIZcSlbN4ZlRQ5hJ/W/AeKd/Wb+XfmQ0e2UANGwbJBbh8S9hD2ZPgNrPqUPZ5Q==", "dependencies": { - "@tanstack/query-core": "5.24.8" + "@tanstack/query-core": "5.25.0" }, "funding": { "type": "github", @@ -1376,9 +1376,9 @@ } }, "node_modules/@tanstack/svelte-query-devtools": { - "version": "5.24.8", - "resolved": "https://registry.npmjs.org/@tanstack/svelte-query-devtools/-/svelte-query-devtools-5.24.8.tgz", - "integrity": "sha512-sIkgiMcptj9hsg0qHTwO1OmUaByJhMwlnSDOBwKiEpvavKOQ2G2WXvtwzYyODqJ3QKOKXqa3Nqu1QQJkYSLtlw==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@tanstack/svelte-query-devtools/-/svelte-query-devtools-5.25.0.tgz", + "integrity": "sha512-Z3Pn54ZmuD5OTzVB/BF1o4aYA0AhZs3BcJ0QJR0Sa6sDbmD6IMVXwtaBPRd9H2VMC6CuteO0JIjDNZYx/M73WQ==", "dependencies": { "@tanstack/query-devtools": "5.24.0", "esm-env": "^1.0.0" @@ -1388,7 +1388,7 @@ "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "@tanstack/svelte-query": "^5.24.8", + "@tanstack/svelte-query": "^5.25.0", "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0" } }, @@ -2097,12 +2097,12 @@ } }, "node_modules/bits-ui": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.19.3.tgz", - "integrity": "sha512-0qqZ1bwE4ZmTnzTdsl4mYEbHY5f0NVgxhddIqscLjJZx4ltkVKDXxBwEusbE2NToqKtXNNrU0wy7sLusdzdhcg==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.19.4.tgz", + "integrity": "sha512-xYSNfn/CJUJK2QIdJqStWMgSK4H5/Ij8kD0IDz1pGnLmm1DkKvO0IX0vBZOEO5xiET6YMu0PnDcienTIwt63XA==", "dependencies": { "@internationalized/date": "^3.5.1", - "@melt-ui/svelte": "0.75.2", + "@melt-ui/svelte": "0.75.3", "nanoid": "^5.0.5" }, "peerDependencies": { diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index 56075bcda9..eb88650787 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -48,11 +48,11 @@ "dependencies": { "@exceptionless/browser": "^3.0.5", "@iconify-json/mdi": "^1.1.64", - "@tanstack/svelte-query": "^5.24.8", - "@tanstack/svelte-query-devtools": "^5.24.8", + "@tanstack/svelte-query": "^5.25.0", + "@tanstack/svelte-query-devtools": "^5.25.0", "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.19.3", + "bits-ui": "^0.19.4", "class-validator": "^0.14.1", "clsx": "^2.1.0", "cmdk-sv": "^0.0.15", From 6dba6fe6f255991ef9f1de60f7e211e6117eb1f4 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Wed, 6 Mar 2024 07:01:30 -0600 Subject: [PATCH 19/86] Upgraded shadcn and renamed icons for less diffs. --- .../src/lib/components/ui/checkbox/checkbox.svelte | 8 ++++---- .../src/lib/components/ui/command/command-dialog.svelte | 2 +- .../src/lib/components/ui/command/command-input.svelte | 4 ++-- .../ui/context-menu/context-menu-checkbox-item.svelte | 4 ++-- .../ui/context-menu/context-menu-radio-item.svelte | 4 ++-- .../ui/context-menu/context-menu-sub-trigger.svelte | 4 ++-- .../src/lib/components/ui/dialog/dialog-content.svelte | 4 ++-- .../ui/dropdown-menu/dropdown-menu-checkbox-item.svelte | 4 ++-- .../ui/dropdown-menu/dropdown-menu-radio-item.svelte | 4 ++-- .../ui/dropdown-menu/dropdown-menu-sub-trigger.svelte | 4 ++-- .../ClientApp/src/lib/components/ui/input/index.ts | 2 +- .../ClientApp/src/lib/components/ui/popover/index.ts | 5 ++++- .../lib/components/ui/radio-group/radio-group-item.svelte | 4 ++-- .../src/lib/components/ui/select/select-item.svelte | 8 +++++--- .../src/lib/components/ui/select/select-trigger.svelte | 4 ++-- .../src/lib/components/ui/sheet/sheet-content.svelte | 4 ++-- 16 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/ui/checkbox/checkbox.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/ui/checkbox/checkbox.svelte index 946ab6d80d..a0cdb95efc 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/ui/checkbox/checkbox.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/ui/checkbox/checkbox.svelte @@ -1,7 +1,7 @@ - + import { Command as CommandPrimitive } from 'cmdk-sv'; - import IconSearch from '~icons/mdi/search'; + import MagnifyingGlass from '~icons/mdi/search'; import { cn } from '$lib/utils'; type $$Props = CommandPrimitive.InputProps; @@ -11,7 +11,7 @@
- + import { ContextMenu as ContextMenuPrimitive } from 'bits-ui'; import { cn } from '$lib/utils'; - import IconCheck from '~icons/mdi/check'; + import Check from '~icons/mdi/check'; type $$Props = ContextMenuPrimitive.CheckboxItemProps; type $$Events = ContextMenuPrimitive.CheckboxItemEvents; @@ -28,7 +28,7 @@ > - + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/ui/context-menu/context-menu-radio-item.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/ui/context-menu/context-menu-radio-item.svelte index e230a86816..67bb7b13de 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/ui/context-menu/context-menu-radio-item.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/ui/context-menu/context-menu-radio-item.svelte @@ -1,7 +1,7 @@ @@ -54,12 +76,12 @@ No results found. - {#each facets as facet (facet.filter.type)} + {#each $facets as facet (facet.filter.type)} onFacetSelected(facet)}>
@@ -79,9 +101,9 @@ -{#each facets as facet (facet.filter.type)} - {#if visible.includes(facet)} - +{#each $facets as facet (facet.filter.type)} + {#if visible.includes(facet.filter.type)} + {/if} {/each} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte index ebeab5283c..2bcbd13a27 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/facets/faceted-filter-dropdown.svelte @@ -10,6 +10,7 @@ import Badge from '$comp/ui/badge/badge.svelte'; import { cn } from '$lib/utils'; import { createEventDispatcher } from 'svelte'; + import { derived, writable } from 'svelte/store'; type Option = { value: string; @@ -20,17 +21,30 @@ export let values: string[] = []; export let options: Option[] = []; - let open = false; + const updatedValues = writable(values); + const hasChanged = derived(updatedValues, ($updatedValues) => { + return $updatedValues.length !== values.length || $updatedValues.some((value) => !values.includes(value)); + }); + + const open = writable(false); + open.subscribe(($open) => { + if ($open) { + updatedValues.set(values); + } else if ($hasChanged) { + values = $updatedValues; + dispatch('changed', values); + } + }); const dispatch = createEventDispatcher(); export function onValueSelected(currentValue: string) { - values = values.includes(currentValue) ? values.filter((v) => v !== currentValue) : [...values, currentValue]; - dispatch('changed', values); + updatedValues.update(($updatedValues) => + $updatedValues.includes(currentValue) ? $updatedValues.filter((v) => v !== currentValue) : [...$updatedValues, currentValue] + ); } export function onClearFilter() { - values = []; - dispatch('changed', values); + updatedValues.set([]); } function onRemoveFilter(): void { @@ -39,7 +53,7 @@ } - + + + + 1}> + + + + {#if $hasChanged} + open.set(false)}>Apply filter + + {/if} + {#if $updatedValue?.trim()} + Clear filter + {/if} + Remove filter + + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/index.ts similarity index 56% rename from src/Exceptionless.Web/ClientApp/src/lib/components/facets/index.ts rename to src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/index.ts index f6662676dd..8816305ed4 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/facets/index.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/index.ts @@ -1,10 +1,13 @@ import Root from './faceted-filter-builder.svelte'; import Dropdown from './faceted-filter-dropdown.svelte'; +import Keyword from './faceted-filter-keyword.svelte'; export { Root, Dropdown, + Keyword, // Root as FacetedFilterBuilder, - Dropdown as FacetedFilterDropdown + Dropdown as DropdownFacetedFilter, + Keyword as KeywordFacetedFilter }; diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index 4f133b6c5a..b6326ca0ba 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -1,34 +1,40 @@ -
Events - + - diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte index 09dc3168b5..7f6eaec5e2 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte @@ -1,17 +1,22 @@ - + const time = persisted('events.issues.time', ''); + const defaultFilters = [new KeywordFilter(''), new StatusFilter([]), new TypeFilter([])]; + const filters = persisted('events.issues.filters', defaultFilters, { serializer: new FilterSerializer() }); + $filters.push(...defaultFilters.filter((df) => !$filters.some((f) => f.type === df.type))); + + const filter = derived(filters, ($filters) => toFilter($filters, true)); + const facets = derived(filters, ($filters) => [ + { + title: 'Search', + component: KeywordFacetedFilter, + filter: $filters.find((f) => f.type === 'keyword')! + }, + { + title: 'Status', + component: StatusFacetedFilter, + filter: $filters.find((f) => f.type === 'status')! + }, + { + title: 'Type', + component: TypeFacetedFilter, + filter: $filters.find((f) => f.type === 'type')! + } + ]); + + function onFiltersChanged({ detail }: CustomEvent) { + filters.set(detail); + } +
Issues - + - - + @@ -45,7 +75,9 @@ selectedStackId.set(null)}> - Event Details + Event Details diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte index 800dbd7941..d5a66531b3 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte @@ -1,32 +1,72 @@ - + const defaultFilters = [new KeywordFilter(''), new StatusFilter([]), new TypeFilter([])]; + const filters = persisted('events.stream.filters', defaultFilters, { serializer: new FilterSerializer() }); + $filters.push(...defaultFilters.filter((df) => !$filters.some((f) => f.type === df.type))); + + const filter = derived(filters, ($filters) => toFilter($filters, true)); + const facets = derived(filters, ($filters) => [ + { + title: 'Search', + component: KeywordFacetedFilter, + filter: $filters.find((f) => f.type === 'keyword')! + }, + { + title: 'Status', + component: StatusFacetedFilter, + filter: $filters.find((f) => f.type === 'status')! + }, + { + title: 'Type', + component: TypeFacetedFilter, + filter: $filters.find((f) => f.type === 'type')! + } + ]); + + function onFiltersChanged({ detail }: CustomEvent) { + filters.set(detail); + } + Event Stream - + + + + + (selectedEventId = null)}> - Event Details + Event Details From d2e4f88db39417eee838e413a3328c3826c41ec4 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sun, 10 Mar 2024 14:53:33 -0500 Subject: [PATCH 24/86] Updated deps --- .../ClientApp/package-lock.json | 24 +++++++++---------- src/Exceptionless.Web/ClientApp/package.json | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index f00211badd..26dff9827f 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -14,7 +14,7 @@ "@tanstack/svelte-query-devtools": "^5.25.0", "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.19.5", + "bits-ui": "^0.19.6", "class-validator": "^0.14.1", "clsx": "^2.1.0", "cmdk-sv": "^0.0.15", @@ -35,7 +35,7 @@ "devDependencies": { "@playwright/test": "^1.42.1", "@sveltejs/adapter-static": "^3.0.1", - "@sveltejs/kit": "^2.5.2", + "@sveltejs/kit": "^2.5.3", "@sveltejs/vite-plugin-svelte": "^3.0.2", "@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/parser": "^7.1.1", @@ -982,9 +982,9 @@ } }, "node_modules/@melt-ui/svelte": { - "version": "0.75.3", - "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.75.3.tgz", - "integrity": "sha512-EA2IKn7w9qtzO/M7VEENpphQ9A4az+QDMQbA8SJLuKyu+S8NWliln5y9vvmnx9dZF8GtKtUKuxpwRNyPg5LAOg==", + "version": "0.76.0", + "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.76.0.tgz", + "integrity": "sha512-X1ktxKujjLjOBt8LBvfckHGDMrkHWceRt1jdsUTf0EH76ikNPP1ofSoiV0IhlduDoCBV+2YchJ8kXCDfDXfC9Q==", "dependencies": { "@floating-ui/core": "^1.3.1", "@floating-ui/dom": "^1.4.5", @@ -1264,9 +1264,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.2.tgz", - "integrity": "sha512-1Pm2lsBYURQsjnLyZa+jw75eVD4gYHxGRwPyFe4DAmB3FjTVR8vRNWGeuDLGFcKMh/B1ij6FTUrc9GrerogCng==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.3.tgz", + "integrity": "sha512-s6x7HBn/Fp+UNvyhJohjIA0FcJ+BWHGUDQ4PCg1D0EboUlvbimJQYchINu8G6sspLXYmlcsuNsp8bbcrRk85iw==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -2055,12 +2055,12 @@ } }, "node_modules/bits-ui": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.19.5.tgz", - "integrity": "sha512-jrt0pGZdixtl27VrfzLj5yJxha29CK+6nClZZSoJCL5DlXFT1sluF9NnOSMP48D3kczR5YjpArvCe0BEnGq4jA==", + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.19.6.tgz", + "integrity": "sha512-ZKWHa1Vt8YW7DdooeNleVdtOtk9hxXZIo8El0myqn7r8S8OkJaSPXhQn/jp4/Q6BphYxZ2Tatqb/WLphmrSfUg==", "dependencies": { "@internationalized/date": "^3.5.1", - "@melt-ui/svelte": "0.75.3", + "@melt-ui/svelte": "0.76.0", "nanoid": "^5.0.5" }, "peerDependencies": { diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index f3590a361d..b728838ae7 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -23,7 +23,7 @@ "devDependencies": { "@playwright/test": "^1.42.1", "@sveltejs/adapter-static": "^3.0.1", - "@sveltejs/kit": "^2.5.2", + "@sveltejs/kit": "^2.5.3", "@sveltejs/vite-plugin-svelte": "^3.0.2", "@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/parser": "^7.1.1", @@ -52,7 +52,7 @@ "@tanstack/svelte-query-devtools": "^5.25.0", "@tanstack/svelte-table": "^8.13.2", "@web3-storage/parse-link-header": "^3.1.0", - "bits-ui": "^0.19.5", + "bits-ui": "^0.19.6", "class-validator": "^0.14.1", "clsx": "^2.1.0", "cmdk-sv": "^0.0.15", From 0836010ea677aa02aa9c5741d6a18f9b782cf04a Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sun, 10 Mar 2024 14:56:42 -0500 Subject: [PATCH 25/86] Removed events store --- .../events/table/EventsDataTable.svelte | 7 +- .../table/EventsTailLogDataTable.svelte | 7 +- .../faceted-filter-builder.svelte | 0 .../faceted-filter-dropdown.svelte | 0 .../faceted-filter-keyword.svelte | 0 .../facets => faceted-filter}/index.ts | 0 .../facets/KeywordFacetedFilter.svelte | 2 +- .../facets/StatusFacetedFilter.svelte | 2 +- .../facets/TypeFacetedFilter.svelte | 2 +- .../src/lib/components/filters/filters.ts | 147 +----------------- .../ClientApp/src/lib/stores/events.ts | 78 ---------- .../ClientApp/src/routes/(app)/+page.svelte | 13 +- .../src/routes/(app)/issues/+page.svelte | 13 +- .../src/routes/(app)/stream/+page.svelte | 13 +- 14 files changed, 32 insertions(+), 252 deletions(-) rename src/Exceptionless.Web/ClientApp/src/lib/components/{filters/facets => faceted-filter}/faceted-filter-builder.svelte (100%) rename src/Exceptionless.Web/ClientApp/src/lib/components/{filters/facets => faceted-filter}/faceted-filter-dropdown.svelte (100%) rename src/Exceptionless.Web/ClientApp/src/lib/components/{filters/facets => faceted-filter}/faceted-filter-keyword.svelte (100%) rename src/Exceptionless.Web/ClientApp/src/lib/components/{filters/facets => faceted-filter}/index.ts (100%) rename src/Exceptionless.Web/ClientApp/src/lib/components/{events => filters}/facets/KeywordFacetedFilter.svelte (89%) rename src/Exceptionless.Web/ClientApp/src/lib/components/{events => filters}/facets/StatusFacetedFilter.svelte (90%) rename src/Exceptionless.Web/ClientApp/src/lib/components/{events => filters}/facets/TypeFacetedFilter.svelte (90%) delete mode 100644 src/Exceptionless.Web/ClientApp/src/lib/stores/events.ts diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/events/table/EventsDataTable.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/events/table/EventsDataTable.svelte index 52d9e8c1a9..cac5f2d721 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/events/table/EventsDataTable.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/events/table/EventsDataTable.svelte @@ -10,11 +10,10 @@ import * as DataTable from '$comp/data-table'; import { getOptions } from './options'; import { DEFAULT_LIMIT } from '$lib/helpers/api'; - import SearchInput from '$comp/SearchInput.svelte'; - import { limit, onFilterInputChanged } from '$lib/stores/events'; export let filter: Readable; export let pageFilter: string | undefined = undefined; + export let limit: Readable; export let time: Readable; export let mode: GetEventsMode = 'summary'; @@ -63,9 +62,7 @@ - - - + dispatch('rowclick', event.detail)}> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/events/table/EventsTailLogDataTable.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/events/table/EventsTailLogDataTable.svelte index 30f925bfb4..3df27ca97d 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/events/table/EventsTailLogDataTable.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/events/table/EventsTailLogDataTable.svelte @@ -11,11 +11,10 @@ import CustomEventMessage from '$comp/messaging/CustomEventMessage.svelte'; import Muted from '$comp/typography/Muted.svelte'; import { getOptions } from './options'; - import SearchInput from '$comp/SearchInput.svelte'; - import { limit, onFilterInputChanged } from '$lib/stores/events'; import { DEFAULT_LIMIT } from '$lib/helpers/api'; export let filter: Readable; + export let limit: Readable; const parameters = writable({ mode: 'summary', limit: $limit }); const options = getOptions>(parameters, (options) => ({ @@ -93,9 +92,7 @@ - - - + dispatch('rowclick', event.detail)}> diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-builder.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/faceted-filter-builder.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-builder.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/faceted-filter-dropdown.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-dropdown.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/faceted-filter-dropdown.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-dropdown.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/faceted-filter-keyword.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-keyword.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/faceted-filter-keyword.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-keyword.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/index.ts similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/index.ts rename to src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/index.ts diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/KeywordFacetedFilter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/KeywordFacetedFilter.svelte similarity index 89% rename from src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/KeywordFacetedFilter.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/KeywordFacetedFilter.svelte index eaf50dca30..548f84a3ce 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/events/facets/KeywordFacetedFilter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/filters/facets/KeywordFacetedFilter.svelte @@ -1,5 +1,5 @@ @@ -59,31 +63,26 @@ {title} - {#if values.length > 0} + {#if loading} + + + Loading + + {:else if value} - {values.length} + {displayValue(value)} {/if} - - + + 1}> No results found. @@ -93,7 +92,7 @@
@@ -109,7 +108,7 @@ open.set(false)}>Apply filter {/if} - {#if $updatedValues.length > 0} + {#if $updatedValue?.trim()} Clear filter {/if} Remove filter diff --git a/src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-keyword.svelte b/src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-keyword.svelte index 591bbf6d83..b89b543a5b 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-keyword.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/components/faceted-filter/faceted-filter-keyword.svelte @@ -48,7 +48,7 @@ {#if value} - {value} + {value}