diff --git a/src/Exceptionless.Core/Repositories/Configuration/Indexes/EventIndex.cs b/src/Exceptionless.Core/Repositories/Configuration/Indexes/EventIndex.cs index 268b6ddc6f..b9a2ca22a7 100644 --- a/src/Exceptionless.Core/Repositories/Configuration/Indexes/EventIndex.cs +++ b/src/Exceptionless.Core/Repositories/Configuration/Indexes/EventIndex.cs @@ -134,6 +134,8 @@ protected override void ConfigureQueryParser(ElasticQueryParserConfiguration con config .SetDefaultFields([ "id", + Alias.ReferenceId, + "reference_id", "source", "message", "tags", diff --git a/src/Exceptionless.Core/Utility/RandomEventGenerator.cs b/src/Exceptionless.Core/Utility/RandomEventGenerator.cs index 1fe80991b8..c0e84cb14b 100644 --- a/src/Exceptionless.Core/Utility/RandomEventGenerator.cs +++ b/src/Exceptionless.Core/Utility/RandomEventGenerator.cs @@ -38,6 +38,11 @@ public List Generate(string organizationId, string projectId, i }; PopulateEvent(ev, i < errorLogCount ? "Error" : null); + if (i % 5 == 0) + { + ev.ReferenceId = GenerateReferenceId(); + } + events.Add(ev); } @@ -165,6 +170,11 @@ private void PopulateEvent(Event ev, string? logLevel = null) : LogMessages.Random(); } + private static string GenerateReferenceId() + { + return Guid.NewGuid().ToString("N").Substring(0, 10); + } + private List? _randomErrors; private List? _randomSimpleErrors; diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/api.svelte.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/events/api.svelte.ts index b452b71912..632e676b78 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/api.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/api.svelte.ts @@ -34,6 +34,8 @@ export async function invalidatePersistentEventQueries(queryClient: QueryClient, export const queryKeys = { deleteEvent: (ids: string[] | undefined) => [...queryKeys.type, 'delete', ...(ids ?? [])] as const, + eventsByReference: (referenceId: string | undefined, projectId?: string | undefined, params?: GetEventsByReferenceRequest['params']) => + [...queryKeys.type, 'by-ref', referenceId, projectId, params] as const, id: (id: string | undefined) => [...queryKeys.type, id] as const, organizations: (id: string | undefined) => [...queryKeys.type, 'organizations', id] as const, organizationsCount: (id: string | undefined, params?: GetOrganizationCountRequest['params']) => [...queryKeys.organizations(id), 'count', params] as const, @@ -74,6 +76,21 @@ export interface GetEventRequest { }; } +export interface GetEventsByReferenceRequest { + params?: { + after?: string; + before?: string; + limit?: number; + mode?: 'summary'; + offset?: string; + page?: number; + }; + route: { + projectId?: string | undefined; + referenceId: string | undefined; + }; +} + export type GetEventsMode = 'stack_frequent' | 'stack_new' | 'stack_recent' | 'stack_users' | 'summary' | null; export interface GetEventsParams { @@ -211,6 +228,31 @@ export function getEventQuery(request: GetEventRequest) { })); } +export function getEventsByReferenceQuery(request: GetEventsByReferenceRequest) { + return createQuery[], ProblemDetails>(() => ({ + enabled: () => !!accessToken.current && !!request.route.referenceId, + queryFn: async ({ signal }: { signal: AbortSignal }) => { + const client = useFetchClient(); + const path = request.route.projectId + ? `projects/${request.route.projectId}/events/by-ref/${encodeURIComponent(request.route.referenceId ?? '')}` + : `events/by-ref/${encodeURIComponent(request.route.referenceId ?? '')}`; + const response = await client.getJSON[]>(path, { + params: { + ...(DEFAULT_OFFSET ? { offset: DEFAULT_OFFSET } : {}), + limit: 20, + mode: 'summary', + page: 1, + ...request.params + }, + signal + }); + + return response.data!; + }, + queryKey: queryKeys.eventsByReference(request.route.referenceId, request.route.projectId, request.params) + })); +} + export function getEventWithNavigationQuery(request: GetEventRequest) { const queryClient = useQueryClient(); return createQuery(() => ({ diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/event-detail-sheet.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/event-detail-sheet.svelte index 0acde2bc76..c704542091 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/event-detail-sheet.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/event-detail-sheet.svelte @@ -17,7 +17,7 @@ let { detailsHref, eventId = $bindable(), filterChanged, onClose, onError }: Props = $props(); - const resolvedHref = $derived(detailsHref ?? (eventId ? resolve('/(app)/events/[eventId=objectid]', { eventId }) : '#')); + const resolvedHref = $derived(detailsHref ?? (eventId ? resolve('/(app)/event/[eventId=objectid]', { eventId }) : '#')); function handleError(problem: ProblemDetails) { if (onError) { diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-error-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-error-summary.svelte index e18bf0e979..fb7a16dab8 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-error-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-error-summary.svelte @@ -29,7 +29,7 @@ {/if} - + {source.data.Message} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-feature-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-feature-summary.svelte index 221c84ac63..f8d0750d92 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-feature-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-feature-summary.svelte @@ -17,5 +17,5 @@ {#if showType} Feature:  {/if} - {source.data.Source} + {source.data.Source} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-log-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-log-summary.svelte index fbf1492e01..cce9bece98 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-log-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-log-summary.svelte @@ -34,5 +34,5 @@ {/if} {#if showType || source.data.Source}: {/if} - {source.data.Message} + {source.data.Message} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-not-found-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-not-found-summary.svelte index 585c5fd96b..01a5bd0e73 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-not-found-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-not-found-summary.svelte @@ -17,5 +17,5 @@ {#if showType} 404:  {/if} - {source.data.Source} + {source.data.Source} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-session-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-session-summary.svelte index ccf43bcc60..fb905f605b 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-session-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-session-summary.svelte @@ -26,7 +26,7 @@ :  {/if} - + {#if source.data.Name || source.data.Identity || source.data.SessionId} {source.data.Name || source.data.Identity || source.data.SessionId} {#if source.data.Name && source.data.Identity} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-simple-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-simple-summary.svelte index caf55d5a07..dfa7ac5f87 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-simple-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-simple-summary.svelte @@ -15,7 +15,7 @@ {#if source.data.Path} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-summary.svelte index e35cae8f2e..1259b8db81 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/event-summary.svelte @@ -26,5 +26,5 @@ {#if showType || source.data.Source} :  {/if} - {source.data.Message} + {source.data.Message} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-error-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-error-summary.svelte index 8fd65946b6..702d474fd9 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-error-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-error-summary.svelte @@ -37,7 +37,7 @@ {/if} - + {source.title} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-feature-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-feature-summary.svelte index d33a82790c..6cc903e5c5 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-feature-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-feature-summary.svelte @@ -27,7 +27,7 @@ Feature:  {/if} - + {source.title} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-log-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-log-summary.svelte index d00a8ca8f9..eb0657ec55 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-log-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-log-summary.svelte @@ -27,7 +27,7 @@ Log source:  {/if} - + {#if source.data?.Source} {source.data.SourceShortName} {:else} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-not-found-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-not-found-summary.svelte index 91a8c6ec56..ccd1239fb4 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-not-found-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-not-found-summary.svelte @@ -26,7 +26,7 @@ {#if showType} 404:  {/if} - + {source.title} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-session-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-session-summary.svelte index bee537d038..a95f163cef 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-session-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-session-summary.svelte @@ -27,7 +27,7 @@ Session:  {/if} - + {source.title} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-simple-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-simple-summary.svelte index 9a910e3f26..7b9e209f7d 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-simple-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-simple-summary.svelte @@ -27,7 +27,7 @@ {source.data.Type}: - {source.title} + {source.title} {#if source.data.Path} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-summary.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-summary.svelte index c34d604dee..971e856202 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-summary.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/events/components/summary/stack-summary.svelte @@ -39,7 +39,7 @@ :  {/if} - + {source.title} 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 7c1585213f..a05ca3ee78 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 @@ -1,6 +1,7 @@ diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/projects/api.svelte.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/api.svelte.ts index 0311f42257..189193d7cd 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/projects/api.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/api.svelte.ts @@ -423,8 +423,22 @@ export function postProject() { return response.data!; }, mutationKey: queryKeys.postProject(), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: queryKeys.type }); + onSuccess: async (project: ViewProject) => { + queryClient.setQueryData(queryKeys.id(project.id), project); + + const organizationProjectsQueryKey = [...queryKeys.organization(project.organization_id), { params: undefined }] as const; + queryClient.setQueryData | undefined>(organizationProjectsQueryKey, (response) => { + if (!response || response.data?.some((existingProject) => existingProject.id === project.id)) { + return response; + } + + return { + ...response, + data: [...(response.data ?? []), project] + }; + }); + + await queryClient.invalidateQueries({ queryKey: queryKeys.type }); } })); } diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/table/project-actions-cell.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/table/project-actions-cell.svelte index 64893fa2c6..c6d527c87d 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/table/project-actions-cell.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/table/project-actions-cell.svelte @@ -47,7 +47,7 @@ {/snippet} - goto(resolve('/(app)/stacks'))}> + goto(resolve('/(app)/stack'))}> Stacks diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/slugs.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/slugs.ts index f24cf96455..b8ced969e3 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/slugs.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/saved-views/slugs.ts @@ -41,7 +41,7 @@ export function savedViewHref(savedView: SavedViewLink): string { return `${resolve('/(app)/stream')}?saved=${savedView.id}`; } - const base = savedView.view_type === 'events' ? resolve('/(app)/events') : resolve('/(app)/stacks'); + const base = savedView.view_type === 'events' ? resolve('/(app)/event') : resolve('/(app)/stack'); return `${base}/${savedViewResolvedSlug(savedView)}`; } diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-actions.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-actions.svelte index 616baf08d7..0b8589957e 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-actions.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/shared/components/faceted-filter/faceted-filter-actions.svelte @@ -22,8 +22,8 @@ {#snippet child({ props })} - {/snippet} @@ -34,11 +34,11 @@ {#snippet child({ props })} - {/snippet} @@ -49,8 +49,8 @@ {#snippet child({ props })} - {/snippet} 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 d623410530..e7bce9d401 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 @@ -250,12 +250,26 @@ {#snippet child({ props })} - {/snippet} @@ -266,8 +280,8 @@ {#snippet child({ props })} - {/snippet} diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/stack-detail-sheet.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/stack-detail-sheet.svelte index a185582ce0..e044e9a37a 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/stack-detail-sheet.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/stacks/components/stack-detail-sheet.svelte @@ -16,7 +16,7 @@ let { filterChanged, onClose, onError, stackId = $bindable() }: Props = $props(); - const resolvedHref = $derived(stackId ? resolve('/(app)/stacks/[stackId=objectid]', { stackId }) : '#'); + const resolvedHref = $derived(stackId ? resolve('/(app)/stack/[stackId=objectid]', { stackId }) : '#'); function handleError(problem: ProblemDetails) { if (onError) { diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/users/api.svelte.ts b/src/Exceptionless.Web/ClientApp/src/lib/features/users/api.svelte.ts index f6e3af95ed..c2f87ed063 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/users/api.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/users/api.svelte.ts @@ -1,4 +1,5 @@ import type { WebSocketMessageValue } from '$features/websockets/models'; +import type { WorkInProgressResult } from '$shared/models'; import { setUserIdentity } from '$features/auth/exceptionless-session'; import { accessToken } from '$features/auth/index.svelte'; @@ -22,6 +23,7 @@ export async function invalidateUserQueries(queryClient: QueryClient, message: W } export const queryKeys = { + deleteCurrentUser: () => [...queryKeys.me(), 'delete'] as const, id: (id: string | undefined) => [...queryKeys.type, id] as const, idEmailAddress: (id?: string) => [...queryKeys.id(id), 'email-address'] as const, ids: (ids: string[] | undefined) => [...queryKeys.type, ...(ids ?? [])] as const, @@ -62,6 +64,18 @@ export interface ResendVerificationEmailRequest { }; } +export function deleteCurrentUser() { + return createMutation(() => ({ + enabled: () => !!accessToken.current, + mutationFn: async () => { + const client = useFetchClient(); + const response = await client.deleteJSON('users/me'); + return response.data!; + }, + mutationKey: queryKeys.deleteCurrentUser() + })); +} + export function getMeQuery() { const queryClient = useQueryClient(); diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/users/components/dialogs/delete-current-user-dialog.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/users/components/dialogs/delete-current-user-dialog.svelte new file mode 100644 index 0000000000..eb4a20ed61 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/users/components/dialogs/delete-current-user-dialog.svelte @@ -0,0 +1,31 @@ + + + + + + Delete Account + + Are you sure you want to delete your account? This will queue your account for deletion and sign you out. + + + + Cancel + Delete Account + + + diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/navbar.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/navbar.svelte index 1e8b7aa0ae..c0e5446666 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/navbar.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/navbar.svelte @@ -25,7 +25,7 @@
- + {#if isMediumScreenQuery.current} {:else} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-organization-switcher.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-organization-switcher.svelte index 5f63f21d72..a2b7199f0b 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-organization-switcher.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-organization-switcher.svelte @@ -72,12 +72,12 @@ } async function handleImpersonate(organization: ViewOrganization): Promise { - await goto(resolve('/(app)/stacks')); + await goto(resolve('/(app)/stack')); currentOrganizationId = organization.id; } async function stopImpersonating(): Promise { - await goto(resolve('/(app)/stacks')); + await goto(resolve('/(app)/stack')); currentOrganizationId = organizations[0]?.id; } diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/navigation-command.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/navigation-command.svelte index 0305466cfb..e7c7a6b157 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/navigation-command.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/navigation-command.svelte @@ -175,15 +175,15 @@ } function getEventHref(result: CommandSearchResult): string { - return resolve('/(app)/events/[eventId=objectid]', { eventId: result.id }); + return resolve('/(app)/event/[eventId=objectid]', { eventId: result.id }); } function getStackHref(result: CommandSearchResult): string { - return resolve('/(app)/stacks/[stackId=objectid]', { stackId: result.id }); + return resolve('/(app)/stack/[stackId=objectid]', { stackId: result.id }); } - const eventSearchHref = $derived(buildSearchHref(resolve('/(app)/events'), debouncedSearchText)); - const stackSearchHref = $derived(buildSearchHref(resolve('/(app)/stacks'), debouncedSearchText)); + const eventSearchHref = $derived(buildSearchHref(resolve('/(app)/event'), debouncedSearchText)); + const stackSearchHref = $derived(buildSearchHref(resolve('/(app)/stack'), debouncedSearchText)); const commandRoutes = $derived( routes.flatMap((route) => { diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte index dd60f5caf5..ad0df28cd6 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+layout.svelte @@ -226,13 +226,13 @@ if (isKeyboardShortcut(e, appKeyboardShortcuts.allEvents)) { e.preventDefault(); - void goto(resolve('/(app)/events')); + void goto(resolve('/(app)/event')); return; } if (isKeyboardShortcut(e, appKeyboardShortcuts.stacks)) { e.preventDefault(); - void goto(resolve('/(app)/stacks')); + void goto(resolve('/(app)/stack')); return; } @@ -357,8 +357,8 @@ }); const viewToHref: Record = { - events: resolve('/(app)/events'), - stacks: resolve('/(app)/stacks'), + events: resolve('/(app)/event'), + stacks: resolve('/(app)/stack'), stream: resolve('/(app)/stream') }; diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte index b464334369..db112da03d 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/+page.svelte @@ -3,6 +3,6 @@ import { resolve } from '$app/paths'; $effect(() => { - goto(resolve('/(app)/stacks'), { replaceState: true }); + goto(resolve('/(app)/stack'), { replaceState: true }); }); diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/manage/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/manage/+page.svelte index fe1af1903e..5f89b16943 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/manage/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/manage/+page.svelte @@ -1,24 +1,35 @@
@@ -205,4 +229,18 @@ Email not verified. Resend verification email. {/if} + +
+ +
+ + diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/events/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/+page.svelte similarity index 99% rename from src/Exceptionless.Web/ClientApp/src/routes/(app)/events/+page.svelte rename to src/Exceptionless.Web/ClientApp/src/routes/(app)/event/+page.svelte index b82dd82a8d..913fb0b60c 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/events/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/+page.svelte @@ -60,7 +60,7 @@ } function rowHref(row: EventSummaryModel): string { - return resolve('/(app)/events/[eventId=objectid]', { eventId: row.id }); + return resolve('/(app)/event/[eventId=objectid]', { eventId: row.id }); } const DEFAULT_TIME_RANGE = '[now-7d TO now]'; @@ -117,7 +117,7 @@ let showStats = $state(true); let showChart = $state(true); const savedViewsState = useSavedViews({ - baseHref: resolve('/(app)/events'), + baseHref: resolve('/(app)/event'), defaultColumnVisibility: defaultEventColumnVisibility, filterCacheKey, getColumnOrder: () => table.state.columnOrder, diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/events/[eventId=objectid]/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/[eventId=objectid]/+page.svelte similarity index 88% rename from src/Exceptionless.Web/ClientApp/src/routes/(app)/events/[eventId=objectid]/+page.svelte rename to src/Exceptionless.Web/ClientApp/src/routes/(app)/event/[eventId=objectid]/+page.svelte index 87587751cb..c880522752 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/events/[eventId=objectid]/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/[eventId=objectid]/+page.svelte @@ -17,7 +17,7 @@ watch( () => organization.current, () => { - goto(resolve('/(app)/events')); + goto(resolve('/(app)/event')); }, { lazy: true } ); @@ -32,7 +32,7 @@ } toast.error(`The event "${page.params.eventId}" could not be found.`); - await goto(resolve('/(app)/events')); + await goto(resolve('/(app)/event')); } $effect(() => { @@ -44,5 +44,5 @@ {filterChanged} id={page.params.eventId || ''} {handleError} - onNavigate={(newId) => goto(resolve('/(app)/events/[eventId=objectid]', { eventId: newId }))} + onNavigate={(newId) => goto(resolve('/(app)/event/[eventId=objectid]', { eventId: newId }))} /> diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/events/[slug=savedview]/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/[slug=savedview]/+page.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/routes/(app)/events/[slug=savedview]/+page.svelte rename to src/Exceptionless.Web/ClientApp/src/routes/(app)/event/[slug=savedview]/+page.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/by-ref/[referenceId]/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/by-ref/[referenceId]/+page.svelte new file mode 100644 index 0000000000..abc0659be6 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/by-ref/[referenceId]/+page.svelte @@ -0,0 +1,68 @@ + + +
+
+

Event Reference

+ {referenceId} +
+ + {#if eventsQuery.isPending} +
+ + Loading events... +
+ {:else if eventsQuery.error} +
Unable to load events for this reference.
+ {:else if (eventsQuery.data?.length ?? 0) === 0} +
+ No events were found for this reference. + +
+ {:else if (eventsQuery.data?.length ?? 0) > 1} +
+ Found {eventsQuery.data?.length} events for this reference. + +
+ +
+ {#each eventsQuery.data ?? [] as event (event.id)} +
+ + Open Event +
+ {/each} +
+ {/if} +
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/events/routes.svelte.ts b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/routes.svelte.ts similarity index 82% rename from src/Exceptionless.Web/ClientApp/src/routes/(app)/events/routes.svelte.ts rename to src/Exceptionless.Web/ClientApp/src/routes/(app)/event/routes.svelte.ts index 127fa4c716..407c6a55e6 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/events/routes.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/event/routes.svelte.ts @@ -12,7 +12,7 @@ export function routes(): NavigationItem[] { return [ { group: 'Event', - href: resolve('/(app)/events/[eventId=objectid]', { eventId: page.params.eventId }), + href: resolve('/(app)/event/[eventId=objectid]', { eventId: page.params.eventId }), icon: Events, show: () => false, title: 'Event Details' diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/manage/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/manage/+page.svelte index 617d3654c8..713b971b6b 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/manage/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/manage/+page.svelte @@ -14,6 +14,7 @@ import { type NewOrganizationFormData, NewOrganizationSchema } from '$features/organizations/schemas'; import { ariaInvalid, getFormErrorMessages, mapFieldErrors, problemDetailsToFormErrors } from '$features/shared/validation'; import { ProblemDetails } from '@exceptionless/fetchclient'; + import Projects from '@lucide/svelte/icons/folder-open'; import Stacks from '@lucide/svelte/icons/layers'; import X from '@lucide/svelte/icons/x'; import { createForm } from '@tanstack/svelte-form'; @@ -129,10 +130,15 @@ -
- +
+
+ + +
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/payment/[id]/+page@.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/payment/[id]/+page@.svelte index e3769b3ea8..660ac3da36 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/payment/[id]/+page@.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/payment/[id]/+page@.svelte @@ -26,11 +26,11 @@ $effect(() => { if (!accessToken.current || !organization.current || invoiceQuery.isError) { - goto(resolve('/(app)/stacks')); + goto(resolve('/(app)/stack')); } if (invoiceQuery.isSuccess && invoiceQuery.data?.organization_id !== organization.current) { - goto(resolve('/(app)/stacks')); + goto(resolve('/(app)/stack')); } }); diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/manage/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/manage/+page.svelte index 0bb415386c..b34df949cc 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/manage/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/manage/+page.svelte @@ -169,7 +169,7 @@
-