From a590e9174a959925d9e4fd5f848cf430d3d1319f Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sun, 1 Dec 2024 16:18:04 -0600 Subject: [PATCH 01/52] WIP - Next Stack Actions --- .../events/components/EventsDrawer.svelte | 3 + .../stacks/components/StackCard.svelte | 73 +++++++++++++++++++ .../components/StackStatusDropdown.svelte | 38 ++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdown.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte index c2a008c6b..f93ee47f4 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte @@ -14,6 +14,7 @@ import { getExtendedDataItems, hasErrorOrSimpleError } from '$features/events/persistent-event'; import { getProjectByIdQuery } from '$features/projects/api.svelte'; import { getStackByIdQuery } from '$features/stacks/api.svelte'; + import StackCard from '$features/stacks/components/StackCard.svelte'; import type { PersistentEvent } from '../models/index'; @@ -111,6 +112,8 @@ {#if eventResponse.isLoading}

Loading...

{:else if eventResponse.isSuccess} + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte new file mode 100644 index 000000000..6d90997e0 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte @@ -0,0 +1,73 @@ + + +{#if stackResponse.isLoading} +

Loading...

+{:else if stackResponse.isSuccess} +
+
+ + + Status + + + +
+

+ {#if stack.date_fixed} + Fixed {#if stack.fixed_in_version}in {stack.fixed_in_version} {/if} on + {/if} + {#if stack.snooze_until_utc} + Snoozed until + {/if} + + + + + Users + + + +

+2350
+

+180.1% from last month

+
+
+ + + Events / All time + + + +
+{stack.total_occurrences} (First / Last)
+

+201 since last hour

+
+
+
+
+{:else} + +{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdown.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdown.svelte new file mode 100644 index 000000000..42364a090 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdown.svelte @@ -0,0 +1,38 @@ + + + + + {selected.label} + + + {#each items as item (item.label)} + {item.label} + {/each} + + From c59b16ea0e970b415c8ba0a83468916625eeb823 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 2 Dec 2024 08:19:36 -0600 Subject: [PATCH 02/52] Fixed linting --- .../features/stacks/components/StackCard.svelte | 10 ++++++---- .../stacks/components/StackStatusDropdown.svelte | 14 +++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte index 6d90997e0..144a64bea 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte @@ -1,6 +1,6 @@ - Loading + Loading diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder.svelte index 0b51da796..2829cc064 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-builder.svelte @@ -67,7 +67,7 @@ {#snippet children()} {/snippet} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/DropDownFacetedFilter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/DropDownFacetedFilter.svelte index b9c83161a..8fc968270 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/DropDownFacetedFilter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/DropDownFacetedFilter.svelte @@ -91,21 +91,21 @@ {/if} + {noOptionsText} {#if loading} -
Loading...
+
Loading...
{/if} - {noOptionsText} {#if options.length > 0} {#each options as option (option.value)} onValueSelected(option.value)} value={option.value}>
- +
{option.label} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/MultiselectFacetedFilter.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/MultiselectFacetedFilter.svelte index f628ec078..9381e223a 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/MultiselectFacetedFilter.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/filters/facets/base/MultiselectFacetedFilter.svelte @@ -94,10 +94,10 @@ {/if} + {noOptionsText} {#if loading}
Loading...
{/if} - {noOptionsText} {#if options.length > 0} {#each options as option (option.value)} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/appearance/(components)/ThemePreview.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/appearance/(components)/ThemePreview.svelte index e6408eec6..c1a6803bf 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/appearance/(components)/ThemePreview.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/appearance/(components)/ThemePreview.svelte @@ -21,11 +21,11 @@
-
+
-
+
@@ -41,11 +41,11 @@
-
+
-
+
From dbbc3e240caa5c0de68eaa05a984fb6f9e1cf5fc Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sun, 8 Dec 2024 21:08:14 -0600 Subject: [PATCH 06/52] WIP - Stack Card --- .../events/components/EventsDrawer.svelte | 1 - .../stacks/components/StackCard.svelte | 250 ++++++++++++++---- .../components/StackStatusDropdownMenu.svelte | 122 +++++++++ 3 files changed, 318 insertions(+), 55 deletions(-) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte index 328dcd74a..1327f9b37 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte @@ -4,7 +4,6 @@ import ErrorMessage from '$comp/ErrorMessage.svelte'; import ClickableProjectFilter from '$comp/filters/ClickableProjectFilter.svelte'; - import ClickableStringFilter from '$comp/filters/ClickableStringFilter.svelte'; import DateTime from '$comp/formatters/DateTime.svelte'; import TimeAgo from '$comp/formatters/TimeAgo.svelte'; import { P } from '$comp/typography'; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte index 144a64bea..f9a34d097 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte @@ -1,20 +1,36 @@ -{#if stackResponse.isLoading} -

Loading...

-{:else if stackResponse.isSuccess} -
-
- - - Status - - - -
-

- {#if stack.date_fixed} - Fixed {#if stack.fixed_in_version}in {stack.fixed_in_version} - {/if} on - {/if} - {#if stack.snooze_until_utc} - Snoozed until - {/if} -

-
- - - Users - - - -
+2350
-

+180.1% from last month

-
-
- - - Events / All time - - - -
+{stack.total_occurrences} (First / Last)
-

+201 since last hour

-
-
-
-
-{:else} - +{#if stack} + + + + +
+ + {stack.title} +
+
+
+ + + + + + + + Stack Options + + updateCritical()} + title="All future occurrences will be marked as critical" + > + Future Occurrences Are Critical + + + promoteToExternal()} title="Used to promote stacks to external systems"> + + Promote To External + + addReferenceLink()} title="Add a reference link to an external resource"> + + Add Reference Link + + + remove()} class="text-destructive" title="Delete this stack"> + + Delete + + + + +
+
+
+ +
+ + + + + Total Events + + + All Time + + + + + + + Users Affected + + Users Affected + + + + + + First + + + First Occurred On + + + + + + + Last + + + Last Occurred On + + +
+ +
+ {#if (stack.status === 'fixed' || stack.status === 'regressed') && stack.date_fixed} +
+ + + Fixed {stack.fixed_in_version && `in ${stack.fixed_in_version}`} on + +
+ {/if} + + {#if stack.status === 'snoozed' && stack.snooze_until_utc} +
+ + Snoozed until +
+ {/if} +
+ + + + {#if stack.tags && stack.tags.length > 0} +
+ {#each stack.tags as tag (tag)} + {tag} + {/each} +
+ {/if} + + {#if stack.references && stack.references.length > 0} +
+ {#each stack.references as ref} + + + + + + + +

{ref}

+
+
+ {/each} +
+ {/if} +
+
{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte new file mode 100644 index 000000000..f8c41cf70 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte @@ -0,0 +1,122 @@ + + + + + + + + + Update Status + + updateOpen()}>Open + updateFixed()}>Fixed + + updateSnooze()} + >Snoozed + + updateSnooze('6hours')}>6 Hours + updateSnooze('day')}>1 Day + updateSnooze('week')}>1 Week + updateSnooze('month')}>1 Month + + + updateIgnore()}>Ignored + updateDiscard()} + >Discarded + + + From c22a472004ef212c4faf57e70ef6f047f4d975b4 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 9 Dec 2024 08:12:05 -0600 Subject: [PATCH 07/52] WIP - Stack Status --- .../src/lib/features/stacks/api.svelte.ts | 72 ++++++++++- .../components/StackStatusDropdownMenu.svelte | 112 +++++++++++------- 2 files changed, 140 insertions(+), 44 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/api.svelte.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/api.svelte.ts index 90717052e..58a6f7eae 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/api.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/api.svelte.ts @@ -2,9 +2,9 @@ import type { WebSocketMessageValue } from '$features/websockets/models'; import { accessToken } from '$features/auth/index.svelte'; import { type ProblemDetails, useFetchClient } from '@exceptionless/fetchclient'; -import { createQuery, QueryClient, useQueryClient } from '@tanstack/svelte-query'; +import { createMutation, createQuery, QueryClient, useQueryClient } from '@tanstack/svelte-query'; -import type { Stack } from './models'; +import type { Stack, StackStatus } from './models'; // export async function invalidateStackQueries(queryClient: QueryClient, message: WebSocketMessageValue<'StackChanged'>) { @@ -25,6 +25,18 @@ export interface GetStackByIdProps { id: string | undefined; } +export interface UpdateStackFixedStatusProps { + id: string | undefined; +} + +export interface UpdateStackSnoozedStatusProps { + id: string | undefined; +} + +export interface UpdateStackStatusProps { + id: string | undefined; +} + export function getStackByIdQuery(props: GetStackByIdProps) { return createQuery(() => ({ enabled: () => !!accessToken.value && !!props.id, @@ -40,6 +52,62 @@ export function getStackByIdQuery(props: GetStackByIdProps) { })); } +export function mutateStackFixedStatus(props: UpdateStackFixedStatusProps) { + const queryClient = useQueryClient(); + return createMutation(() => ({ + enabled: () => !!accessToken.value && !!props.id, + mutationFn: async (version?: string) => { + const client = useFetchClient(); + const response = await client.postJSON(`stacks/${props.id}/mark-fixed`, { version }); + return response.data!; + }, + mutationKey: queryKeys.id(props.id), + onError: () => { + queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); + }, + onSuccess: (data) => { + queryClient.setQueryData(queryKeys.id(props.id), data); + } + })); +} +export function mutateStackSnoozedStatus(props: UpdateStackSnoozedStatusProps) { + const queryClient = useQueryClient(); + return createMutation(() => ({ + enabled: () => !!accessToken.value && !!props.id, + mutationFn: async (snoozeUntilUtc: Date) => { + const client = useFetchClient(); + const response = await client.postJSON(`stacks/${props.id}/mark-snoozed`, { snoozeUntilUtc }); + return response.data!; + }, + mutationKey: queryKeys.id(props.id), + onError: () => { + queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); + }, + onSuccess: (data) => { + queryClient.setQueryData(queryKeys.id(props.id), data); + } + })); +} + +export function mutateStackStatus(props: UpdateStackStatusProps) { + const queryClient = useQueryClient(); + return createMutation(() => ({ + enabled: () => !!accessToken.value && !!props.id, + mutationFn: async (status: StackStatus) => { + const client = useFetchClient(); + const response = await client.postJSON(`stacks/${props.id}/change-status`, { status }); + return response.data!; + }, + mutationKey: queryKeys.id(props.id), + onError: () => { + queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); + }, + onSuccess: (data) => { + queryClient.setQueryData(queryKeys.id(props.id), data); + } + })); +} + export async function prefetchStack(props: GetStackByIdProps) { if (!accessToken.value) { return; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte index f8c41cf70..a600b8aee 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte @@ -3,14 +3,14 @@ import * as DropdownMenu from '$comp/ui/dropdown-menu'; import ChevronDown from '~icons/mdi/chevron-down'; - import { StackStatus } from '../models'; + import { mutateStackFixedStatus, mutateStackSnoozedStatus, mutateStackStatus } from '../api.svelte'; + import { Stack, StackStatus } from '../models'; interface Props { - id: string; - status: StackStatus; + stack: Stack; } - let { id, status }: Props = $props(); + let { stack }: Props = $props(); type Item = { label: string; value: StackStatus }; const items: Item[] = [ @@ -22,59 +22,86 @@ { label: 'Discarded', value: StackStatus.Discarded } ]; - let selected = $derived((items.find((item) => item.value === status) || items[items.length - 1]) as Item); + let selected = $derived((items.find((item) => item.value === stack?.status) || items[items.length - 1]) as Item); - function updateOpen() { - //stackService.changeStatus(id, "open") + const updateStackFixedStatus = mutateStackFixedStatus({ + get id() { + return stack?.id; + } + }); + + const updateStackSnoozedStatus = mutateStackSnoozedStatus({ + get id() { + return stack?.id; + } + }); + + const updateStackStatus = mutateStackStatus({ + get id() { + return stack?.id; + } + }); + + async function updateOpen() { + if (stack.status === StackStatus.Open) { + return; + } + + await updateStackStatus.mutateAsync(StackStatus.Open); } - function updateFixed() { - // if (vm.stack.status === "fixed") { - // return updateOpen(); - // } - // tackDialogService + async function updateFixed() { + if (stack.status === StackStatus.Fixed) { + return; + } + // .markFixed() // .then(function (version) { // return stackService // .markFixed(vm._stackId, version) // .then(onSuccess, onFailure) // .catch(function (e) {}); + const version = undefined; + await updateStackFixedStatus.mutateAsync(version); } - function updateSnooze(timePeriod?: '6hours' | 'day' | 'month' | 'week') { - console.log(timePeriod, id); - // if (!timePeriod && vm.stack.status === "snoozed") { - // return updateOpen(); - // } - // - // var snoozeUntilUtc = moment(); - // switch (timePeriod) { - // case "6hours": - // snoozeUntilUtc = snoozeUntilUtc.add(6, "hours"); - // break; - // case "day": - // snoozeUntilUtc = snoozeUntilUtc.add(1, "days"); - // break; - // case "week": - // snoozeUntilUtc = snoozeUntilUtc.add(1, "weeks"); - // break; - // case "month": - // default: - // snoozeUntilUtc = snoozeUntilUtc.add(1, "months"); - // break; - // } - // - // return stackService - // .markSnoozed(vm._stackId, snoozeUntilUtc.format("YYYY-MM-DDTHH:mm:ssz")) + async function updateSnooze(timePeriod?: '6hours' | 'day' | 'month' | 'week') { + if (stack.status === StackStatus.Snoozed) { + return; + } + + let snoozeUntilUtc = new Date(); + switch (timePeriod) { + case '6hours': + snoozeUntilUtc.setHours(snoozeUntilUtc.getHours() + 6); + break; + case 'day': + snoozeUntilUtc.setDate(snoozeUntilUtc.getDate() + 1); + break; + case 'week': + snoozeUntilUtc.setDate(snoozeUntilUtc.getDate() + 7); + break; + case 'month': + default: + snoozeUntilUtc.setMonth(snoozeUntilUtc.getMonth() + 1); + break; + } + + await updateStackSnoozedStatus.mutateAsync(snoozeUntilUtc); } - function updateIgnore() { - // var ignored = vm.stack.status === "ignored"; - // return stackService - // .changeStatus(vm._stackId, ignored ? "open" : "ignored") + async function updateIgnore() { + if (stack.status === StackStatus.Ignored) { + return; + } + + await updateStackStatus.mutateAsync(StackStatus.Ignored); } - function updateDiscard() { + async function updateDiscard() { + if (stack.status === StackStatus.Discarded) { + return; + } // if (vm.stack.status === "discarded") { // return updateOpen(); // } @@ -86,6 +113,7 @@ // "All future occurrences will be discarded and will not count against your event limit." // ); //changeStatus(vm._stackId, "discarded") + await updateStackStatus.mutateAsync(StackStatus.Discarded); } From f70bd09888e4e61c9f5e0ff5abebf4c35726c819 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 9 Dec 2024 19:57:10 -0600 Subject: [PATCH 08/52] Added Alert Dialog --- .../alert-dialog/alert-dialog-action.svelte | 13 ++++++ .../alert-dialog/alert-dialog-cancel.svelte | 17 ++++++++ .../alert-dialog/alert-dialog-content.svelte | 26 ++++++++++++ .../alert-dialog-description.svelte | 16 ++++++++ .../alert-dialog/alert-dialog-footer.svelte | 20 ++++++++++ .../alert-dialog/alert-dialog-header.svelte | 20 ++++++++++ .../alert-dialog/alert-dialog-overlay.svelte | 19 +++++++++ .../ui/alert-dialog/alert-dialog-title.svelte | 18 +++++++++ .../components/ui/alert-dialog/index.ts | 40 +++++++++++++++++++ 9 files changed, 189 insertions(+) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-action.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-cancel.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-content.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-description.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-footer.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-header.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-overlay.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-title.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/index.ts diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-action.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-action.svelte new file mode 100644 index 000000000..204e59e6d --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-action.svelte @@ -0,0 +1,13 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-cancel.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-cancel.svelte new file mode 100644 index 000000000..a2277f764 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-cancel.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-content.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-content.svelte new file mode 100644 index 000000000..858b8bc1b --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-content.svelte @@ -0,0 +1,26 @@ + + + + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-description.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-description.svelte new file mode 100644 index 000000000..600ef8c53 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-description.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-footer.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-footer.svelte new file mode 100644 index 000000000..91ecaba64 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-footer.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-header.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-header.svelte new file mode 100644 index 000000000..44a7b082e --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-overlay.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-overlay.svelte new file mode 100644 index 000000000..62acab8a4 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-overlay.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-title.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-title.svelte new file mode 100644 index 000000000..ef197dce7 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/alert-dialog-title.svelte @@ -0,0 +1,18 @@ + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/index.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/index.ts new file mode 100644 index 000000000..dd20f99cf --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/ui/alert-dialog/index.ts @@ -0,0 +1,40 @@ +import { AlertDialog as AlertDialogPrimitive } from "bits-ui"; + +import Title from "./alert-dialog-title.svelte"; +import Action from "./alert-dialog-action.svelte"; +import Cancel from "./alert-dialog-cancel.svelte"; +import Footer from "./alert-dialog-footer.svelte"; +import Header from "./alert-dialog-header.svelte"; +import Overlay from "./alert-dialog-overlay.svelte"; +import Content from "./alert-dialog-content.svelte"; +import Description from "./alert-dialog-description.svelte"; + +const Root = AlertDialogPrimitive.Root; +const Trigger = AlertDialogPrimitive.Trigger; +const Portal = AlertDialogPrimitive.Portal; + +export { + Root, + Title, + Action, + Cancel, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + // + Root as AlertDialog, + Title as AlertDialogTitle, + Action as AlertDialogAction, + Cancel as AlertDialogCancel, + Portal as AlertDialogPortal, + Footer as AlertDialogFooter, + Header as AlertDialogHeader, + Trigger as AlertDialogTrigger, + Overlay as AlertDialogOverlay, + Content as AlertDialogContent, + Description as AlertDialogDescription, +}; From c4c08d64845845e186263775d1392ce0b24ad87a Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 9 Dec 2024 19:57:44 -0600 Subject: [PATCH 09/52] Updated Stack Card --- .../src/lib/features/stacks/api.svelte.ts | 27 +++++++++---------- .../stacks/components/StackCard.svelte | 10 +++---- .../components/StackStatusDropdownMenu.svelte | 22 +++++++-------- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/api.svelte.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/api.svelte.ts index 58a6f7eae..add91be47 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/api.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/api.svelte.ts @@ -54,56 +54,53 @@ export function getStackByIdQuery(props: GetStackByIdProps) { export function mutateStackFixedStatus(props: UpdateStackFixedStatusProps) { const queryClient = useQueryClient(); - return createMutation(() => ({ + return createMutation(() => ({ enabled: () => !!accessToken.value && !!props.id, mutationFn: async (version?: string) => { const client = useFetchClient(); - const response = await client.postJSON(`stacks/${props.id}/mark-fixed`, { version }); - return response.data!; + await client.post(`stacks/${props.id}/mark-fixed`, undefined, { params: { version } }); }, mutationKey: queryKeys.id(props.id), onError: () => { queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); }, - onSuccess: (data) => { - queryClient.setQueryData(queryKeys.id(props.id), data); + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); } })); } export function mutateStackSnoozedStatus(props: UpdateStackSnoozedStatusProps) { const queryClient = useQueryClient(); - return createMutation(() => ({ + return createMutation(() => ({ enabled: () => !!accessToken.value && !!props.id, mutationFn: async (snoozeUntilUtc: Date) => { const client = useFetchClient(); - const response = await client.postJSON(`stacks/${props.id}/mark-snoozed`, { snoozeUntilUtc }); - return response.data!; + await client.post(`stacks/${props.id}/mark-snoozed`, undefined, { params: { snoozeUntilUtc: snoozeUntilUtc.toISOString() } }); }, mutationKey: queryKeys.id(props.id), onError: () => { queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); }, - onSuccess: (data) => { - queryClient.setQueryData(queryKeys.id(props.id), data); + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); } })); } export function mutateStackStatus(props: UpdateStackStatusProps) { const queryClient = useQueryClient(); - return createMutation(() => ({ + return createMutation(() => ({ enabled: () => !!accessToken.value && !!props.id, mutationFn: async (status: StackStatus) => { const client = useFetchClient(); - const response = await client.postJSON(`stacks/${props.id}/change-status`, { status }); - return response.data!; + await client.post(`stacks/${props.id}/change-status`, undefined, { params: { status } }); }, mutationKey: queryKeys.id(props.id), onError: () => { queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); }, - onSuccess: (data) => { - queryClient.setQueryData(queryKeys.id(props.id), data); + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: queryKeys.id(props.id) }); } })); } diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte index f9a34d097..e8151e13a 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte @@ -78,7 +78,7 @@
- + + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/RemoveStackDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/RemoveStackDialog.svelte new file mode 100644 index 000000000..7223efaba --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/RemoveStackDialog.svelte @@ -0,0 +1,29 @@ + + + + + + Delete Stack + Are you sure you want to delete this stack (includes all stack events)? + + + Cancel + DELETE STACK + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte index e8151e13a..f92df0a30 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte @@ -9,7 +9,6 @@ import { Badge } from '$comp/ui/badge'; import { Button } from '$comp/ui/button'; import * as Card from '$comp/ui/card'; - import * as DropdownMenu from '$comp/ui/dropdown-menu'; import * as Tooltip from '$comp/ui/tooltip'; import { getStackByIdQuery } from '$features/stacks/api.svelte'; import IconFirstOccurrence from '~icons/mdi/arrow-left-circle'; @@ -17,12 +16,11 @@ import IconCalendar from '~icons/mdi/calendar'; import IconClock from '~icons/mdi/clock'; import IconFilter from '~icons/mdi/filter'; - import IconSettings from '~icons/mdi/gear'; import IconReference from '~icons/mdi/link'; - import IconDelete from '~icons/mdi/trash-can'; - import IconPromoteToExternal from '~icons/mdi/trending-up'; + import IconOpenInNew from '~icons/mdi/open-in-new'; import IconUsers from '~icons/mdi/users'; + import StackOptionsDropdownMenu from './StackOptionsDropdownMenu.svelte'; import StackStatusDropdownMenu from './StackStatusDropdownMenu.svelte'; interface Props { @@ -39,32 +37,6 @@ }); const stack = $derived(stackResponse.data!); - - function promoteToExternal() { - throw new Error('Function not implemented.'); - } - - function updateCritical() { - // if (vm.stack.occurrences_are_critical) { - // return stackService.markNotCritical(vm._stackId).then(onSuccess, onFailure); - // } - // - // return stackService.markCritical(vm._stackId).catch(onSuccess, onFailure); - } - - function addReferenceLink() { - // - // if (vm.stack.references.indexOf(url) < 0) - // return stackService.addLink(vm._stackId, url).then(onSuccess, onFailure); - } - - function remove() { - // Are you sure you want to delete this stack (includes all stack events)? - // close - // remove(vm._stackId) - // - // translateService.T("Successfully queued the stack for deletion.") - } {#if stack} @@ -78,41 +50,8 @@
- - - - - - - - Stack Options - - updateCritical()} - title="All future occurrences will be marked as critical" - > - Future Occurrences Are Critical - - - promoteToExternal()} title="Used to promote stacks to external systems"> - - Promote To External - - addReferenceLink()} title="Add a reference link to an external resource"> - - Add Reference Link - - - remove()} class="text-destructive" title="Delete this stack"> - - Delete - - - - + +
@@ -158,9 +97,11 @@ + +
{#if (stack.status === 'fixed' || stack.status === 'regressed') && stack.date_fixed} -
+
Fixed {stack.fixed_in_version && `in ${stack.fixed_in_version}`} on @@ -169,21 +110,13 @@ {/if} {#if stack.status === 'snoozed' && stack.snooze_until_utc} -
+
Snoozed until
{/if}
- - {#if stack.tags && stack.tags.length > 0}
{#each stack.tags as tag (tag)} @@ -196,19 +129,14 @@
{/if} + {#if stack.references && stack.references.length > 0} -
- {#each stack.references as ref} - - - - - - - -

{ref}

-
-
+
+ + {#each stack.references as referenceUrl} + {/each}
{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte new file mode 100644 index 000000000..4fb0787ad --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte @@ -0,0 +1,134 @@ + + + + + + + + + Stack Options + + updateCritical()} + title="All future occurrences will be marked as critical" + > + Future Occurrences Are Critical + + + promoteToExternal()} title="Used to promote stacks to external systems"> + + Promote To External + + (openAddStackReferenceDialog = true)} title="Add a reference link to an external resource"> + + Add Reference Link + + + (openRemoveStackDialog = true)} class="text-destructive" title="Delete this stack"> + + Delete + + + + + + + From 678739082613ceee49c87f3e61ce3e8ed5654744 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 10 Dec 2024 08:24:04 -0600 Subject: [PATCH 11/52] Added form validation to add reference link --- .../components/AddStackReferenceDialog.svelte | 62 +++++++++++++------ .../src/lib/features/stacks/models.ts | 6 ++ 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte index 3ad9cabcf..7e128156c 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte @@ -1,38 +1,60 @@ - - Add Reference Link - Add a reference link to an external resource. - -
-
- - +
+ + Add Reference Link + Add a reference link to an external resource. + + +
+ + + {#snippet children({ props })} + Reference Link + + {/snippet} + + + +
-
- - - + + + Save Reference Link + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/models.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/models.ts index 18737b19b..283c07d06 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/models.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/models.ts @@ -1 +1,7 @@ export { Stack, StackStatus } from '$generated/api'; +import { IsUrl } from 'class-validator'; + +export class ReferenceLinkForm { + @IsUrl({ require_tld: false }) + url!: string; +} From 98e60287423084f3f1ea1692f65d29b9cbb9b5c0 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 10 Dec 2024 08:29:42 -0600 Subject: [PATCH 12/52] Reset form on dialog show --- .../features/stacks/components/AddStackReferenceDialog.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte index 7e128156c..61baa8700 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte @@ -31,7 +31,7 @@ const { enhance, form: formData } = form; - + form.reset()}>
From 0197e28d196536a0afb70754a3298e81bd0a6238 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 10 Dec 2024 19:50:51 -0600 Subject: [PATCH 13/52] Added Mark Fixed dialog --- .../StackOptionsDropdownMenu.svelte | 8 +- .../components/StackStatusDropdownMenu.svelte | 19 ++-- .../AddStackReferenceDialog.svelte | 32 +++--- .../MarkStackFixedInVersionDialog.svelte | 100 ++++++++++++++++++ .../{ => dialogs}/RemoveStackDialog.svelte | 0 .../src/lib/features/stacks/models.ts | 8 +- 6 files changed, 134 insertions(+), 33 deletions(-) rename src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/{ => dialogs}/AddStackReferenceDialog.svelte (63%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackFixedInVersionDialog.svelte rename src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/{ => dialogs}/RemoveStackDialog.svelte (100%) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte index 4fb0787ad..51ad5caca 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte @@ -10,16 +10,16 @@ import { mutateAddStackReference, mutateMarkStackAsCritical, mutateMarkStackAsNotCritical, promoteStackToExternal, removeStack } from '../api.svelte'; import { Stack } from '../models'; - import AddStackReferenceDialog from './AddStackReferenceDialog.svelte'; - import RemoveStackDialog from './RemoveStackDialog.svelte'; + import AddStackReferenceDialog from './dialogs/AddStackReferenceDialog.svelte'; + import RemoveStackDialog from './dialogs/RemoveStackDialog.svelte'; interface Props { stack: Stack; } let { stack }: Props = $props(); - let openRemoveStackDialog = $state(false); let openAddStackReferenceDialog = $state(false); + let openRemoveStackDialog = $state(false); const addStackReference = mutateAddStackReference({ get id() { @@ -130,5 +130,5 @@ - + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte index ba5a9f9ae..0d002a556 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte @@ -5,6 +5,7 @@ import { mutateStackFixedStatus, mutateStackSnoozedStatus, mutateStackStatus } from '../api.svelte'; import { Stack, StackStatus } from '../models'; + import MarkStackFixedInVersionDialog from './dialogs/MarkStackFixedInVersionDialog.svelte'; interface Props { stack: Stack; @@ -22,6 +23,7 @@ { label: 'Discarded', value: StackStatus.Discarded } ]; + let openMarkStackFixedInVersionDialog = $state(false); let selected = $derived((items.find((item) => item.value === stack?.status) || items[items.length - 1]) as Item); const updateStackFixedStatus = mutateStackFixedStatus({ @@ -50,18 +52,7 @@ await updateStackStatus.mutateAsync(StackStatus.Open); } - async function updateFixed() { - if (stack.status === StackStatus.Fixed) { - return; - } - - // .markFixed() - // .then(function (version) { - // return stackService - // .markFixed(vm._stackId, version) - // .then(onSuccess, onFailure) - // .catch(function (e) {}); - const version = undefined; + async function updateFixed(version?: string) { await updateStackFixedStatus.mutateAsync(version); } @@ -125,7 +116,7 @@ Update Status updateOpen()}>Open - updateFixed()}>Fixed + (openMarkStackFixedInVersionDialog = true)}>Fixed updateSnooze()} >Snoozed + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/AddStackReferenceDialog.svelte similarity index 63% rename from src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/AddStackReferenceDialog.svelte index 61baa8700..95c9b6ec5 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/AddStackReferenceDialog.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/AddStackReferenceDialog.svelte @@ -1,11 +1,12 @@ - form.reset()}> - + form.reset()}> + - - Add Reference Link - Add a reference link to an external resource. - + + Add Reference Link + Add a reference link to an external resource. + -
+

{#snippet children({ props })} @@ -50,11 +51,12 @@ -

+

- - Save Reference Link - + + Cancel + Save Reference Link + -
-
+ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackFixedInVersionDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackFixedInVersionDialog.svelte new file mode 100644 index 000000000..6d5ec276d --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackFixedInVersionDialog.svelte @@ -0,0 +1,100 @@ + + + form.reset()}> + +
+ + Mark Fixed + Marks the stack as fixed. This will also prevent error occurrences from being displayed in the dashboard. + + +

+ Optional: Please enter the version in which the stack has been fixed. Any submitted occurrences with a lower version will not + cause a regression. + +

+ + + + {#snippet children({ props })} + Version + + {/snippet} + + + + + + + Cancel + Mark Fixed + +
+
+
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/RemoveStackDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackDialog.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/RemoveStackDialog.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackDialog.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/models.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/models.ts index 283c07d06..ce0194a36 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/models.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/models.ts @@ -1,5 +1,11 @@ export { Stack, StackStatus } from '$generated/api'; -import { IsUrl } from 'class-validator'; +import { IsOptional, IsSemVer, IsUrl } from 'class-validator'; + +export class FixedInVersionForm { + @IsOptional() + @IsSemVer() + version?: string; +} export class ReferenceLinkForm { @IsUrl({ require_tld: false }) From 85f5eec2b93f718272157b58812eec466cd67295 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 10 Dec 2024 20:11:00 -0600 Subject: [PATCH 14/52] Updated deps --- .../ClientApp/package-lock.json | 188 ++++++++---------- src/Exceptionless.Web/ClientApp/package.json | 8 +- 2 files changed, 87 insertions(+), 109 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index f4b76d032..4432574bf 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -35,9 +35,9 @@ }, "devDependencies": { "@iconify-json/lucide": "^1.2.18", - "@playwright/test": "^1.49.0", + "@playwright/test": "^1.49.1", "@sveltejs/adapter-static": "^3.0.6", - "@sveltejs/kit": "^2.9.0", + "@sveltejs/kit": "^2.10.1", "@sveltejs/vite-plugin-svelte": "^5.0.1", "@types/eslint": "^9.6.1", "@types/node": "^22.10.1", @@ -53,12 +53,12 @@ "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.2", "prettier-plugin-tailwindcss": "^0.6.9", - "svelte": "^5.9.0", + "svelte": "^5.10.1", "svelte-check": "^4.1.1", "swagger-typescript-api": "^13.0.23", "tslib": "^2.8.1", "typescript": "^5.7.2", - "typescript-eslint": "^8.17.0", + "typescript-eslint": "^8.18.0", "vite": "^6.0.3", "vitest": "2.1.6" } @@ -1020,13 +1020,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0.tgz", - "integrity": "sha512-DMulbwQURa8rNIQrf94+jPJQ4FmOVdpE5ZppRNvWVjvhC+6sOeo28r8MgIpQRYouXRtt/FCCXU7zn20jnHR4Qw==", + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz", + "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.0" + "playwright": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -1327,9 +1327,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.9.0.tgz", - "integrity": "sha512-W3E7ed3ChB6kPqRs2H7tcHp+Z7oiTFC6m+lLyAQQuyXeqw6LdNuuwEUla+5VM0OGgqQD+cYD6+7Xq80vVm17Vg==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.10.1.tgz", + "integrity": "sha512-2aormKTn94aU8Lfxj4gcbRGh1Dyw0hCFlNo51+njdRDn9P2ERuWC4bOtTuoy5HJpPYR3AH8oaaEjKDWUHbi1OA==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -1583,17 +1583,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz", - "integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz", + "integrity": "sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/type-utils": "8.17.0", - "@typescript-eslint/utils": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/type-utils": "8.18.0", + "@typescript-eslint/utils": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1608,25 +1608,21 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz", - "integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.0.tgz", + "integrity": "sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==", "dev": true, - "license": "BSD-2-Clause", + "license": "MITClause", "dependencies": { - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/typescript-estree": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", "debug": "^4.3.4" }, "engines": { @@ -1637,23 +1633,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz", - "integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz", + "integrity": "sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0" + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1664,14 +1656,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz", - "integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz", + "integrity": "sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.17.0", - "@typescript-eslint/utils": "8.17.0", + "@typescript-eslint/typescript-estree": "8.18.0", + "@typescript-eslint/utils": "8.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1683,18 +1675,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz", - "integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.0.tgz", + "integrity": "sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==", "dev": true, "license": "MIT", "engines": { @@ -1706,14 +1694,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz", - "integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz", + "integrity": "sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1728,10 +1716,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -1761,16 +1747,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz", - "integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.0.tgz", + "integrity": "sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/typescript-estree": "8.17.0" + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1780,22 +1766,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz", - "integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz", + "integrity": "sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.17.0", + "@typescript-eslint/types": "8.18.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -5614,13 +5596,13 @@ } }, "node_modules/playwright": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0.tgz", - "integrity": "sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A==", + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", + "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -5633,9 +5615,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0.tgz", - "integrity": "sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA==", + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", + "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -6889,9 +6871,9 @@ } }, "node_modules/svelte": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.9.0.tgz", - "integrity": "sha512-ZcC3BtjIDa4yfhAyAr94MxDQLD97zbpXmaUldFv2F5AkdZwYgQYB3BZVNRU5zEVaeeHoAns8ADiRMnre3QmpxQ==", + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.10.1.tgz", + "integrity": "sha512-JOBw4VStdoP/Iw93vrzGAOUWdV4Gk8hCuprvTwjbdMZG3GyYxbLogR56XqrO2M7E6PifoPkwDphXu0s49R2wvw==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -7736,15 +7718,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.17.0.tgz", - "integrity": "sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.18.0.tgz", + "integrity": "sha512-Xq2rRjn6tzVpAyHr3+nmSg1/9k9aIHnJ2iZeOH7cfGOWqTkXTm3kwpQglEuLGdNrYvPF+2gtAs+/KF5rjVo+WQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.17.0", - "@typescript-eslint/parser": "8.17.0", - "@typescript-eslint/utils": "8.17.0" + "@typescript-eslint/eslint-plugin": "8.18.0", + "@typescript-eslint/parser": "8.18.0", + "@typescript-eslint/utils": "8.18.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7754,12 +7736,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/ufo": { diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index a0f0ab510..bfc287ef8 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -24,9 +24,9 @@ }, "devDependencies": { "@iconify-json/lucide": "^1.2.18", - "@playwright/test": "^1.49.0", + "@playwright/test": "^1.49.1", "@sveltejs/adapter-static": "^3.0.6", - "@sveltejs/kit": "^2.9.0", + "@sveltejs/kit": "^2.10.1", "@sveltejs/vite-plugin-svelte": "^5.0.1", "@types/eslint": "^9.6.1", "@types/node": "^22.10.1", @@ -42,12 +42,12 @@ "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.2", "prettier-plugin-tailwindcss": "^0.6.9", - "svelte": "^5.9.0", + "svelte": "^5.10.1", "svelte-check": "^4.1.1", "swagger-typescript-api": "^13.0.23", "tslib": "^2.8.1", "typescript": "^5.7.2", - "typescript-eslint": "^8.17.0", + "typescript-eslint": "^8.18.0", "vite": "^6.0.3", "vitest": "2.1.6" }, From ba8a118905d94e3df7d02762944e9395fd28f9b3 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 10 Dec 2024 20:11:22 -0600 Subject: [PATCH 15/52] WIP Stack actions --- .../StackOptionsDropdownMenu.svelte | 12 +++++-- .../components/StackStatusDropdownMenu.svelte | 20 +++++------- .../dialogs/MarkStackDiscardedDialog.svelte | 31 +++++++++++++++++++ .../dialogs/RemoveStackDialog.svelte | 6 ++-- .../RequiresPromotedWebHookDialog.svelte | 29 +++++++++++++++++ 5 files changed, 79 insertions(+), 19 deletions(-) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackDiscardedDialog.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RequiresPromotedWebHookDialog.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte index 51ad5caca..a4094acd0 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackOptionsDropdownMenu.svelte @@ -12,6 +12,7 @@ import { Stack } from '../models'; import AddStackReferenceDialog from './dialogs/AddStackReferenceDialog.svelte'; import RemoveStackDialog from './dialogs/RemoveStackDialog.svelte'; + import RequiresPromotedWebHookDialog from './dialogs/RequiresPromotedWebHookDialog.svelte'; interface Props { stack: Stack; @@ -20,6 +21,7 @@ let { stack }: Props = $props(); let openAddStackReferenceDialog = $state(false); let openRemoveStackDialog = $state(false); + let openRequiresPromotedWebHookDialog = $state(false); const addStackReference = mutateAddStackReference({ get id() { @@ -68,13 +70,16 @@ } if (response.status === 501) { - toast.error('No promoted web hooks are configured for this project. Please add a promoted web hook to use this feature.'); - // confirm dialog .confirm(response.data.message, translateService.T("Manage Integrations")) - await goto(`/next/account/manage/notifications?project=${stack.project_id}`); + openRequiresPromotedWebHookDialog = true; return; } } + async function navigateToProjectIntegrations() { + // TODO: Verify this works once page is added. + await goto(`/next/project/${stack.project_id}/manage/integrations`); + } + async function updateCritical() { if (stack.occurrences_are_critical) { await markStackAsNotCritical.mutateAsync(); @@ -132,3 +137,4 @@ + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte index 0d002a556..142562bd0 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackStatusDropdownMenu.svelte @@ -5,6 +5,7 @@ import { mutateStackFixedStatus, mutateStackSnoozedStatus, mutateStackStatus } from '../api.svelte'; import { Stack, StackStatus } from '../models'; + import MarkStackDiscardedDialog from './dialogs/MarkStackDiscardedDialog.svelte'; import MarkStackFixedInVersionDialog from './dialogs/MarkStackFixedInVersionDialog.svelte'; interface Props { @@ -23,6 +24,7 @@ { label: 'Discarded', value: StackStatus.Discarded } ]; + let openMarkStackDiscardedDialog = $state(false); let openMarkStackFixedInVersionDialog = $state(false); let selected = $derived((items.find((item) => item.value === stack?.status) || items[items.length - 1]) as Item); @@ -89,17 +91,7 @@ if (stack.status === StackStatus.Discarded) { return; } - // if (vm.stack.status === "discarded") { - // return updateOpen(); - // } - // translateService.T( - // "Are you sure you want to all current stack events and discard any future stack events?" - // ) + - // " " + - // translateService.T( - // "All future occurrences will be discarded and will not count against your event limit." - // ); - //changeStatus(vm._stackId, "discarded") + await updateStackStatus.mutateAsync(StackStatus.Discarded); } @@ -129,11 +121,13 @@
updateIgnore()}>Ignored - updateDiscard()} - >Discarded (openMarkStackDiscardedDialog = true)}>Discarded + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackDiscardedDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackDiscardedDialog.svelte new file mode 100644 index 000000000..a22817eb3 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackDiscardedDialog.svelte @@ -0,0 +1,31 @@ + + + + + + Discard Stack + Are you sure you want to all current stack events and discard any future stack events? + + All future occurrences will be discarded and will not count against your event limit. + + Cancel + Discard Stack + + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackDialog.svelte index 7223efaba..71dc9495e 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackDialog.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackDialog.svelte @@ -7,10 +7,10 @@ remove: () => Promise; } - let { open = $bindable(), remove: removeStack }: Props = $props(); + let { open = $bindable(), remove }: Props = $props(); async function onSubmit() { - await removeStack(); + await remove(); open = false; } @@ -23,7 +23,7 @@ Cancel - DELETE STACK + Delete Stack diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RequiresPromotedWebHookDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RequiresPromotedWebHookDialog.svelte new file mode 100644 index 000000000..70af0ffe6 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RequiresPromotedWebHookDialog.svelte @@ -0,0 +1,29 @@ + + + + + + Manage Integrations + No promoted web hooks are configured for this project. Please add a promoted web hook to use this feature. + + + Cancel + Manage Integrations + + + From 4aafe0a00df47233efd53f4b163d1216cd4db45e Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 10 Dec 2024 20:12:43 -0600 Subject: [PATCH 16/52] Fixed lint message --- .../stacks/components/dialogs/MarkStackDiscardedDialog.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackDiscardedDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackDiscardedDialog.svelte index a22817eb3..6c330a1ac 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackDiscardedDialog.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/MarkStackDiscardedDialog.svelte @@ -1,5 +1,4 @@ From 4f3c451fc4d685fe867bcf84b54832f3cf95a384 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Fri, 13 Dec 2024 21:01:46 -0600 Subject: [PATCH 20/52] Added closing of the event drawer and fixed stack traces and code block formatting --- .../features/events/components/EventsDrawer.svelte | 9 +++++++-- .../events/components/ExtendedDataItem.svelte | 12 +++++++----- .../events/components/SimpleStackTrace.svelte | 9 ++++----- .../lib/features/events/components/StackTrace.svelte | 6 +++--- .../events/components/StackTraceHeader.svelte | 2 +- .../features/events/components/views/Error.svelte | 2 +- .../features/events/components/views/Overview.svelte | 4 ++-- .../ClientApp/src/routes/(app)/+page.svelte | 2 +- .../ClientApp/src/routes/(app)/issues/+page.svelte | 2 +- .../ClientApp/src/routes/(app)/stream/+page.svelte | 2 +- 10 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte index b37e01042..c52499008 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/EventsDrawer.svelte @@ -26,10 +26,11 @@ interface Props { changed: (filter: IFilter) => void; + close: () => void; id: string; } - let { changed, id }: Props = $props(); + let { changed, close, id }: Props = $props(); function getTabs(event?: null | PersistentEvent, project?: ViewProject): TabType[] { if (!event) { @@ -100,7 +101,11 @@ activeTab = 'Extended Data'; } - // TODO: Navigate on event deletion. + $effect(() => { + if (eventResponse.isError) { + close(); + } + }); {#if eventResponse.isLoading} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/ExtendedDataItem.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/ExtendedDataItem.svelte index 04ee27573..d4c9e7bfe 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/ExtendedDataItem.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/ExtendedDataItem.svelte @@ -81,9 +81,11 @@
- {#if showRaw} -
{json}
- {:else} - - {/if} +
+ {#if showRaw} +
{json}
+ {:else} + + {/if} +
{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/SimpleStackTrace.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/SimpleStackTrace.svelte index 237b28233..05045860c 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/SimpleStackTrace.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/SimpleStackTrace.svelte @@ -19,9 +19,8 @@ const errors = getErrors(error); -
{#each errors.reverse() as error, index}{#if error.stack_trace}
{cleanStackTrace( - error.stack_trace - )}
{#if index < errors.length - 1}
--- End of inner error stack trace ---
{/if}{/if}{/each}
{#each errors.reverse() as error, index}{#if error.stack_trace}
{cleanStackTrace(error.stack_trace)}
{#if index < errors.length - 1}
--- End of inner error stack trace ---
{/if}{/if}{/each}
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/StackTrace.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/StackTrace.svelte index f915b593d..51b3b12b3 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/StackTrace.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/StackTrace.svelte @@ -15,8 +15,8 @@ const errors = getErrors(error); -
{#each errors.reverse() as error, index}{#if error.stack_trace}
{#each error.stack_trace as frame}{getStackFrame(frame)}
{/each}{#if index < errors.length - 1}
--- End of inner exception stack trace ---
{/if}
{/if}{/each}
{#each error.stack_trace as frame}{getStackFrame(frame)}
{/each}{#if index < errors.length - 1}
--- End of inner exception stack trace ---
{/if}
{/if}{/each} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/StackTraceHeader.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/StackTraceHeader.svelte index bcc87b98e..e4ed30a9f 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/StackTraceHeader.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/StackTraceHeader.svelte @@ -8,7 +8,7 @@ let { errors }: Props = $props(); -{#each errors as error, index}
+{#each errors as error, index}
{#if index > 0}---> {/if}{#if error.type}{error.type}:{/if}{#if error.message}{error.message}{/if}
diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte index f3a3f5a20..c88c7d671 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Error.svelte @@ -70,7 +70,7 @@
-
+
{#if event.data?.['@error']} {:else if event.data?.['@simple_error']} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte index ddcda637e..de43c1c5a 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/views/Overview.svelte @@ -271,13 +271,13 @@ {/if} {#if hasError} -
+

Stack Trace

-
+
{#if event.data?.['@error']} {:else if event.data?.['@simple_error']} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index a0c7663af..c71d99635 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -127,6 +127,6 @@ > - + (selectedEventId = null)}> 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 85a1922a8..62b7f8d2e 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte @@ -121,6 +121,6 @@ >Event Details - + (selectedStackId = undefined)}> 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 8cbe32a66..edc4a4efa 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte @@ -155,6 +155,6 @@ > - + (selectedEventId = null)}> From b00037534101df2e25d7ea46a58d6a35f89eb931 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 14 Dec 2024 15:47:00 -0600 Subject: [PATCH 21/52] Adding Loading indicator to data grids --- .../components/table/EventsDataTable.svelte | 5 +++-- .../components/data-table/data-table-body.svelte | 15 ++++++++++++++- .../ClientApp/src/routes/(app)/+page.svelte | 4 ++-- .../src/routes/(app)/issues/+page.svelte | 4 ++-- .../src/routes/(app)/stream/+page.svelte | 2 +- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte index cf2ef272f..f1a035fc3 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte @@ -8,12 +8,13 @@ interface Props { limit: number; + loading: boolean; rowclick?: (row: EventSummaryModel) => void; table: Table>; toolbarChildren?: Snippet; } - let { limit = $bindable(), rowclick, table, toolbarChildren }: Props = $props(); + let { limit = $bindable(), loading, rowclick, table, toolbarChildren }: Props = $props(); @@ -22,7 +23,7 @@ {@render toolbarChildren()} {/if} - + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/data-table/data-table-body.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/data-table/data-table-body.svelte index 24f0db9a2..38efc4860 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/data-table/data-table-body.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/data-table/data-table-body.svelte @@ -3,17 +3,19 @@
@@ -58,6 +62,15 @@ + {#if isLoading} + + +
+ Loading... +
+
+
+ {/if} {#each table.getRowModel().rows as row (row.id)} {#each row.getVisibleCells() as cell (cell.id)} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index c71d99635..cff8ca203 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -50,7 +50,7 @@ const table = createTable(context.options); const client = useFetchClient(); - let response: FetchClientResponse[]>; + let response = $state[]>>(); async function loadData() { if (client.loading) { @@ -110,7 +110,7 @@ Events - + {#snippet toolbarChildren()} {/snippet} 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 62b7f8d2e..8f6b4d9c3 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/issues/+page.svelte @@ -65,7 +65,7 @@ const table = createTable(context.options); const client = useFetchClient(); - let response: FetchClientResponse[]>; + let response = $state[]>>(); async function loadData() { if (client.loading) { @@ -105,7 +105,7 @@ Issues - + {#snippet toolbarChildren()} {/snippet} 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 edc4a4efa..de03e52b9 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/stream/+page.svelte @@ -136,7 +136,7 @@ - +
From 1992540147012943aa3e74a93617a2e1e6536e70 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sun, 15 Dec 2024 09:33:36 -0600 Subject: [PATCH 22/52] Updated deps --- .../ClientApp/package-lock.json | 63 ++++++++++++------- src/Exceptionless.Web/ClientApp/package.json | 8 +-- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index e0668036d..092b526e4 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -9,7 +9,7 @@ "version": "8.0.0", "dependencies": { "@exceptionless/browser": "^3.1.0", - "@exceptionless/fetchclient": "^0.29.0", + "@exceptionless/fetchclient": "^0.31.0", "@iconify-json/mdi": "^1.2.1", "@tanstack/svelte-query": "https://pkg.pr.new/@tanstack/svelte-query@28f98f9", "@tanstack/svelte-query-devtools": "https://pkg.pr.new/@tanstack/svelte-query-devtools@28f98f9", @@ -18,7 +18,7 @@ "bits-ui": "^1.0.0-next.67", "class-validator": "^0.14.1", "clsx": "^2.1.1", - "formsnap": "^2.0.0-next.1", + "formsnap": "^2.0.0", "mode-watcher": "^0.5.0", "oidc-client-ts": "^3.1.0", "pretty-ms": "^9.2.0", @@ -44,7 +44,7 @@ "@types/throttle-debounce": "^5.0.2", "autoprefixer": "^10.4.20", "cross-env": "^7.0.3", - "eslint": "^9.16.0", + "eslint": "^9.17.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-perfectionist": "^4.3.0", "eslint-plugin-svelte": "^2.46.1", @@ -53,7 +53,7 @@ "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.2", "prettier-plugin-tailwindcss": "^0.6.9", - "svelte": "^5.12.0", + "svelte": "^5.14.0", "svelte-check": "^4.1.1", "swagger-typescript-api": "^13.0.23", "tslib": "^2.8.1", @@ -654,9 +654,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", - "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", + "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", "dev": true, "license": "MIT", "engines": { @@ -703,9 +703,9 @@ "license": "Apache-2.0" }, "node_modules/@exceptionless/fetchclient": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/@exceptionless/fetchclient/-/fetchclient-0.29.0.tgz", - "integrity": "sha512-ZwfPIgWda22rwhzk06Am67UWh8h/8oIw0/36LDs0MmxwVrLK+kprUVuZ2TFOvGWPRm+vs8AzBS4X9VzzKSwLLg==", + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@exceptionless/fetchclient/-/fetchclient-0.31.0.tgz", + "integrity": "sha512-1FFrxqiSIpjM7LNBaT/j4aw/Z78l8mwnFEE9Yw49sxZXnOgJal/wp3SEumyicnPw6fHIl+GpH583Ro0s464ypA==", "license": "Apache-2.0" }, "node_modules/@exodus/schemasafe": { @@ -3161,9 +3161,9 @@ } }, "node_modules/eslint": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", - "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", + "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", "dev": true, "license": "MIT", "dependencies": { @@ -3172,7 +3172,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.9.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.16.0", + "@eslint/js": "9.17.0", "@eslint/plugin-kit": "^0.2.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -3181,7 +3181,7 @@ "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.5", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -3623,12 +3623,12 @@ } }, "node_modules/formsnap": { - "version": "2.0.0-next.1", - "resolved": "https://registry.npmjs.org/formsnap/-/formsnap-2.0.0-next.1.tgz", - "integrity": "sha512-ha8r9eMmsGEGMY+ljV3FEyTtB72E7dt95y9HHUbCcaDnjbz3Q6n00BHLz7dfBZ9rqyaMeIO200EmP1IcYMExeg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/formsnap/-/formsnap-2.0.0.tgz", + "integrity": "sha512-W61elddvdzeBEs10nNvwxQnx/FctJFHBXPk9uluNQAckHo1nuSUvSQGIjtLjTKIbQdQnwEOoxqWrk9tuv0U7hA==", "license": "MIT", "dependencies": { - "svelte-toolbelt": "^0.4.4" + "svelte-toolbelt": "^0.5.0" }, "engines": { "node": ">=18", @@ -3639,6 +3639,25 @@ "sveltekit-superforms": "^2.19.0" } }, + "node_modules/formsnap/node_modules/svelte-toolbelt": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.5.0.tgz", + "integrity": "sha512-t3tenZcnfQoIeRuQf/jBU7bvTeT3TGkcEE+1EUr5orp0lR7NEpprflpuie3x9Dn0W9nOKqs3HwKGJeeN5Ok1sQ==", + "funding": [ + "https://github.com/sponsors/huntabyte" + ], + "dependencies": { + "clsx": "^2.1.1", + "style-to-object": "^1.0.8" + }, + "engines": { + "node": ">=18", + "pnpm": ">=8.7.0" + }, + "peerDependencies": { + "svelte": "^5.0.0-next.126" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -6871,9 +6890,9 @@ } }, "node_modules/svelte": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.12.0.tgz", - "integrity": "sha512-nOd7uj0D/4A3IrHnltaFYndVPGViYSs0s+Zi3N4uQg3owJt9RoiUdwxYx8qjorj5CtaGsx8dNYsFVbH6czrGNg==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.14.0.tgz", + "integrity": "sha512-xHrS9dd2Ci9GJd2sReNFqJztoe515wB4OzsPw4A8L2M6lddLFkREkWDJnM5DAND30Zyvjwc1icQVzH0F+Sdx5A==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index 28dcd8f0a..ff3d38373 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -33,7 +33,7 @@ "@types/throttle-debounce": "^5.0.2", "autoprefixer": "^10.4.20", "cross-env": "^7.0.3", - "eslint": "^9.16.0", + "eslint": "^9.17.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-perfectionist": "^4.3.0", "eslint-plugin-svelte": "^2.46.1", @@ -42,7 +42,7 @@ "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.2", "prettier-plugin-tailwindcss": "^0.6.9", - "svelte": "^5.12.0", + "svelte": "^5.14.0", "svelte-check": "^4.1.1", "swagger-typescript-api": "^13.0.23", "tslib": "^2.8.1", @@ -53,7 +53,7 @@ }, "dependencies": { "@exceptionless/browser": "^3.1.0", - "@exceptionless/fetchclient": "^0.29.0", + "@exceptionless/fetchclient": "^0.31.0", "@iconify-json/mdi": "^1.2.1", "@tanstack/svelte-query": "https://pkg.pr.new/@tanstack/svelte-query@28f98f9", "@tanstack/svelte-query-devtools": "https://pkg.pr.new/@tanstack/svelte-query-devtools@28f98f9", @@ -62,7 +62,7 @@ "bits-ui": "^1.0.0-next.67", "class-validator": "^0.14.1", "clsx": "^2.1.1", - "formsnap": "^2.0.0-next.1", + "formsnap": "^2.0.0", "mode-watcher": "^0.5.0", "oidc-client-ts": "^3.1.0", "pretty-ms": "^9.2.0", From 9afea7c8156cba6c97c4eef08905215710cf318b Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sun, 15 Dec 2024 09:34:00 -0600 Subject: [PATCH 23/52] Fixed loading indicators --- .../events/components/table/EventsDataTable.svelte | 6 +++--- .../shared/components/data-table/data-table-body.svelte | 8 ++++---- .../ClientApp/src/routes/(app)/+page.svelte | 7 +++++-- .../src/routes/(app)/account/notifications/+page.svelte | 7 +++++-- .../src/routes/(app)/account/security/+page.svelte | 7 +++++-- .../ClientApp/src/routes/(app)/issues/+page.svelte | 7 +++++-- .../ClientApp/src/routes/(app)/stream/+page.svelte | 7 +++++-- .../ClientApp/src/routes/(auth)/logout/+page.svelte | 7 +++++-- 8 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte index f1a035fc3..c6616b6d6 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/table/EventsDataTable.svelte @@ -7,14 +7,14 @@ import type { EventSummaryModel, SummaryTemplateKeys } from '../summary/index'; interface Props { + isLoading: boolean; limit: number; - loading: boolean; rowclick?: (row: EventSummaryModel) => void; table: Table>; toolbarChildren?: Snippet; } - let { limit = $bindable(), loading, rowclick, table, toolbarChildren }: Props = $props(); + let { isLoading, limit = $bindable(), rowclick, table, toolbarChildren }: Props = $props(); @@ -23,7 +23,7 @@ {@render toolbarChildren()} {/if} - + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/data-table/data-table-body.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/data-table/data-table-body.svelte index 38efc4860..2dff17df1 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/data-table/data-table-body.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/data-table/data-table-body.svelte @@ -10,12 +10,12 @@ import DataTableColumnHeader from './data-table-column-header.svelte'; interface Props { - loading: boolean; + isLoading: boolean; rowclick?: (row: TData) => void; table: SvelteTable; } - let { loading, rowclick, table }: Props = $props(); + let { isLoading, rowclick, table }: Props = $props(); function getHeaderColumnClass(header: Header) { const classes = [(header.column.columnDef.meta as { class?: string })?.class || '']; @@ -40,7 +40,7 @@ } } - const isLoading = $derived(loading && table.getRowModel().rows.length === 0); + const showLoading = $derived(isLoading && table.getRowModel().rows.length === 0);
@@ -62,7 +62,7 @@ - {#if isLoading} + {#if showLoading}
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index cff8ca203..20d93b0b6 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -50,10 +50,13 @@ const table = createTable(context.options); const client = useFetchClient(); + let isLoading = $state(false); + client.loading.on((loading) => (isLoading = loading!)); + let response = $state[]>>(); async function loadData() { - if (client.loading) { + if (isLoading) { return; } @@ -110,7 +113,7 @@ Events - + {#snippet toolbarChildren()} {/snippet} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/notifications/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/notifications/+page.svelte index 0d5fb9c42..3c098e25a 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/notifications/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/notifications/+page.svelte @@ -12,10 +12,13 @@ data.email_notifications_enabled = true; const client = useFetchClient(); + let isLoading = $state(false); + client.loading.on((loading) => (isLoading = loading!)); + let problem = $state(new ProblemDetails()); async function onSave() { - if (client.loading) { + if (isLoading) { return; } } @@ -42,7 +45,7 @@
Promote to Tab {:else} Demote Tab {/if} {/if} From 601e45f488236a29da2bd56a46312f835cde707a Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Thu, 26 Dec 2024 14:51:04 -0600 Subject: [PATCH 52/52] Added ability to display and remove stack reference links --- .../stacks/components/StackCard.svelte | 16 +----- .../stacks/components/StackReferences.svelte | 55 +++++++++++++++++++ .../dialogs/RemoveStackReferenceDialog.svelte | 32 +++++++++++ 3 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackReferences.svelte create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackReferenceDialog.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte index cb70f4aa4..2a981581b 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackCard.svelte @@ -8,7 +8,6 @@ import TimeAgo from '$comp/formatters/TimeAgo.svelte'; import Muted from '$comp/typography/Muted.svelte'; import { Badge } from '$comp/ui/badge'; - import { Button } from '$comp/ui/button'; import * as Card from '$comp/ui/card'; import * as Tooltip from '$comp/ui/tooltip'; import { getProjectCountQuery, getStackCountQuery } from '$features/events/api.svelte'; @@ -20,11 +19,10 @@ import IconCalendar from '~icons/mdi/calendar'; import IconClock from '~icons/mdi/clock'; import IconFilter from '~icons/mdi/filter'; - import IconReference from '~icons/mdi/link'; - import IconOpenInNew from '~icons/mdi/open-in-new'; import IconUsers from '~icons/mdi/users'; import StackOptionsDropdownMenu from './StackOptionsDropdownMenu.svelte'; + import StackReferences from './StackReferences.svelte'; import StackStatusDropdownMenu from './StackStatusDropdownMenu.svelte'; interface Props { @@ -164,17 +162,7 @@
{/if} - - {#if stack.references && stack.references.length > 0} -
- - {#each stack.references as referenceUrl} - - {/each} -
- {/if} +
{/if} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackReferences.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackReferences.svelte new file mode 100644 index 000000000..103c85a23 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/StackReferences.svelte @@ -0,0 +1,55 @@ + + +{#if stack.references?.length > 0} + +{/if} + + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackReferenceDialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackReferenceDialog.svelte new file mode 100644 index 000000000..e5fb193af --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/dialogs/RemoveStackReferenceDialog.svelte @@ -0,0 +1,32 @@ + + + + + + Delete Reference + Are you sure you want to delete this reference link? + + {reference} + + Cancel + Delete Reference Link + + +