From f32a87734abd516d9b63389c7ed0a02ed9db8a88 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 7 Jul 2026 15:19:17 -0500 Subject: [PATCH 01/12] Fix AppHost startup args and expose client setup path --- .codex/environments/environment.toml | 7 ++++++- aspire.config.json | 9 ++++++--- src/Exceptionless.AppHost/Program.cs | 8 +++++++- .../project/[projectId]/api-keys/+page.svelte | 6 ++++++ .../[projectId]/configure/+page.svelte | 19 +++++++++++++++++++ .../project/[projectId]/routes.svelte.ts | 7 +++++++ 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/.codex/environments/environment.toml b/.codex/environments/environment.toml index 0d6d8393fd..f87c077c92 100644 --- a/.codex/environments/environment.toml +++ b/.codex/environments/environment.toml @@ -61,6 +61,7 @@ echo "Removing repo-local temp/test output only..." rm -rf .cache/tmp rm -rf .aspire +rm -rf .aspire-home rm -rf TestResults find . -type d \( -name TestResults -o -name .vite -o -name .svelte-kit \) -exec rm -rf {} + @@ -80,9 +81,13 @@ cd "${CODEX_WORKTREE_PATH:?CODEX_WORKTREE_PATH is required}" export AppMode=Development export DOTNET_ENVIRONMENT=Development export ASPNETCORE_ENVIRONMENT=Development +export ASPIRE_HOME="${CODEX_WORKTREE_PATH}/.aspire-home" +mkdir -p "${ASPIRE_HOME}" +export HOME="${ASPIRE_HOME}" +export DOTNET_CLI_HOME="${ASPIRE_HOME}/.dotnet" if command -v aspire >/dev/null 2>&1; then - aspire run + aspire run --nologo --non-interactive -- --allow-unsecured-transport --skip-trust-developer-certificate else dotnet run --project src/Exceptionless.AppHost/Exceptionless.AppHost.csproj fi diff --git a/aspire.config.json b/aspire.config.json index 8382207087..219b5479a3 100644 --- a/aspire.config.json +++ b/aspire.config.json @@ -1,5 +1,8 @@ { - "appHost": { - "path": "src/Exceptionless.AppHost/Exceptionless.AppHost.csproj" - } + "appHost": { + "path": "src/Exceptionless.AppHost/Exceptionless.AppHost.csproj" + }, + "features": { + "updateNotificationsEnabled": "false" + } } \ No newline at end of file diff --git a/src/Exceptionless.AppHost/Program.cs b/src/Exceptionless.AppHost/Program.cs index f0bb50f674..cf8bd65968 100644 --- a/src/Exceptionless.AppHost/Program.cs +++ b/src/Exceptionless.AppHost/Program.cs @@ -5,7 +5,13 @@ string? scope = WorktreeScope.Resolve(); bool isScoped = !String.IsNullOrWhiteSpace(scope); var worktreePorts = isScoped ? WorktreeScope.AssignFreePorts() : null; -var builder = DistributedApplication.CreateBuilder(args); +var builderOptions = new DistributedApplicationOptions +{ + TrustDeveloperCertificate = !HasArgument("--skip-trust-developer-certificate"), + AllowUnsecuredTransport = HasArgument("--allow-unsecured-transport"), + DisableDashboard = HasArgument("--disable-dashboard") +}; +var builder = DistributedApplication.CreateBuilder(builderOptions); bool servicesOnly = HasArgument("--services-only"); bool ciE2E = HasArgument("--ci-e2e"); bool includeDevTools = !ciE2E; diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte index 0d1e1bcf4a..b2a627fcf8 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte @@ -2,6 +2,7 @@ import type { NewToken, ViewToken } from '$features/tokens/models'; import { page } from '$app/state'; + import { resolve } from '$app/paths'; import DataTableViewOptions from '$comp/data-table/data-table-view-options.svelte'; import { Muted } from '$comp/typography'; import { Button } from '$comp/ui/button'; @@ -11,6 +12,7 @@ import { getTableOptions } from '$features/tokens/components/table/options.svelte'; import TokensDataTable from '$features/tokens/components/table/tokens-data-table.svelte'; import Plus from '@lucide/svelte/icons/plus'; + import Send from '@lucide/svelte/icons/send'; import { createTable } from '@tanstack/svelte-table'; import { queryParamsState } from 'kit-query-params'; import { toast } from 'svelte-sonner'; @@ -85,6 +87,10 @@ {#snippet toolbarChildren()}
+ diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/routes.svelte.ts b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/routes.svelte.ts index c03b7852a3..0ea81ce48c 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/routes.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/routes.svelte.ts @@ -3,6 +3,7 @@ import { page } from '$app/state'; import Usage from '@lucide/svelte/icons/bar-chart'; import ClientConfig from '@lucide/svelte/icons/braces'; import ApiKey from '@lucide/svelte/icons/key'; +import Send from '@lucide/svelte/icons/send'; import Stacks from '@lucide/svelte/icons/layers'; import Integration from '@lucide/svelte/icons/plug-2'; import Settings from '@lucide/svelte/icons/settings'; @@ -21,6 +22,12 @@ export function routes(): NavigationItem[] { icon: Settings, title: 'General' }, + { + group: 'Project Settings', + href: resolve('/(app)/project/[projectId]/configure', { projectId: page.params.projectId }), + icon: Send, + title: 'Client Setup' + }, { group: 'Project Settings', href: resolve('/(app)/project/[projectId]/usage', { projectId: page.params.projectId }), From 5e7481f9ade72a55e6787d3ef57c65794acf2804 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 7 Jul 2026 19:58:14 -0500 Subject: [PATCH 02/12] Preserve Aspire args when using custom builder options --- .codex/environments/environment.toml | 4 ++-- src/Exceptionless.AppHost/Program.cs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.codex/environments/environment.toml b/.codex/environments/environment.toml index f87c077c92..09958c9851 100644 --- a/.codex/environments/environment.toml +++ b/.codex/environments/environment.toml @@ -87,9 +87,9 @@ export HOME="${ASPIRE_HOME}" export DOTNET_CLI_HOME="${ASPIRE_HOME}/.dotnet" if command -v aspire >/dev/null 2>&1; then - aspire run --nologo --non-interactive -- --allow-unsecured-transport --skip-trust-developer-certificate + aspire run --nologo --non-interactive -- --allow-unsecured-transport --skip-trust-developer-certificate "$@" else - dotnet run --project src/Exceptionless.AppHost/Exceptionless.AppHost.csproj + dotnet run --project src/Exceptionless.AppHost/Exceptionless.AppHost.csproj -- "$@" fi ''' diff --git a/src/Exceptionless.AppHost/Program.cs b/src/Exceptionless.AppHost/Program.cs index cf8bd65968..589d520436 100644 --- a/src/Exceptionless.AppHost/Program.cs +++ b/src/Exceptionless.AppHost/Program.cs @@ -7,6 +7,7 @@ var worktreePorts = isScoped ? WorktreeScope.AssignFreePorts() : null; var builderOptions = new DistributedApplicationOptions { + Args = args, TrustDeveloperCertificate = !HasArgument("--skip-trust-developer-certificate"), AllowUnsecuredTransport = HasArgument("--allow-unsecured-transport"), DisableDashboard = HasArgument("--disable-dashboard") From eb98fac32ef4525558df733b0fb89e3b5cb2e788 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Tue, 7 Jul 2026 22:09:25 -0500 Subject: [PATCH 03/12] Remove speculative Aspire startup overrides --- .codex/environments/environment.toml | 9 ++------- aspire.config.json | 9 +++------ src/Exceptionless.AppHost/Program.cs | 9 +-------- .../(app)/project/[projectId]/api-keys/+page.svelte | 4 ++-- .../routes/(app)/project/[projectId]/manage/+page.svelte | 4 ++-- .../routes/(app)/project/[projectId]/routes.svelte.ts | 4 ++-- 6 files changed, 12 insertions(+), 27 deletions(-) diff --git a/.codex/environments/environment.toml b/.codex/environments/environment.toml index 09958c9851..df9fe419ab 100644 --- a/.codex/environments/environment.toml +++ b/.codex/environments/environment.toml @@ -61,7 +61,6 @@ echo "Removing repo-local temp/test output only..." rm -rf .cache/tmp rm -rf .aspire -rm -rf .aspire-home rm -rf TestResults find . -type d \( -name TestResults -o -name .vite -o -name .svelte-kit \) -exec rm -rf {} + @@ -81,15 +80,11 @@ cd "${CODEX_WORKTREE_PATH:?CODEX_WORKTREE_PATH is required}" export AppMode=Development export DOTNET_ENVIRONMENT=Development export ASPNETCORE_ENVIRONMENT=Development -export ASPIRE_HOME="${CODEX_WORKTREE_PATH}/.aspire-home" -mkdir -p "${ASPIRE_HOME}" -export HOME="${ASPIRE_HOME}" -export DOTNET_CLI_HOME="${ASPIRE_HOME}/.dotnet" if command -v aspire >/dev/null 2>&1; then - aspire run --nologo --non-interactive -- --allow-unsecured-transport --skip-trust-developer-certificate "$@" + aspire run --nologo --non-interactive else - dotnet run --project src/Exceptionless.AppHost/Exceptionless.AppHost.csproj -- "$@" + dotnet run --project src/Exceptionless.AppHost/Exceptionless.AppHost.csproj fi ''' diff --git a/aspire.config.json b/aspire.config.json index 219b5479a3..8382207087 100644 --- a/aspire.config.json +++ b/aspire.config.json @@ -1,8 +1,5 @@ { - "appHost": { - "path": "src/Exceptionless.AppHost/Exceptionless.AppHost.csproj" - }, - "features": { - "updateNotificationsEnabled": "false" - } + "appHost": { + "path": "src/Exceptionless.AppHost/Exceptionless.AppHost.csproj" + } } \ No newline at end of file diff --git a/src/Exceptionless.AppHost/Program.cs b/src/Exceptionless.AppHost/Program.cs index 589d520436..f0bb50f674 100644 --- a/src/Exceptionless.AppHost/Program.cs +++ b/src/Exceptionless.AppHost/Program.cs @@ -5,14 +5,7 @@ string? scope = WorktreeScope.Resolve(); bool isScoped = !String.IsNullOrWhiteSpace(scope); var worktreePorts = isScoped ? WorktreeScope.AssignFreePorts() : null; -var builderOptions = new DistributedApplicationOptions -{ - Args = args, - TrustDeveloperCertificate = !HasArgument("--skip-trust-developer-certificate"), - AllowUnsecuredTransport = HasArgument("--allow-unsecured-transport"), - DisableDashboard = HasArgument("--disable-dashboard") -}; -var builder = DistributedApplication.CreateBuilder(builderOptions); +var builder = DistributedApplication.CreateBuilder(args); bool servicesOnly = HasArgument("--services-only"); bool ciE2E = HasArgument("--ci-e2e"); bool includeDevTools = !ciE2E; diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte index b2a627fcf8..1af778c2a6 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte @@ -11,8 +11,8 @@ import { type GetProjectTokensParams, getProjectTokensQuery, postProjectToken } from '$features/tokens/api.svelte'; import { getTableOptions } from '$features/tokens/components/table/options.svelte'; import TokensDataTable from '$features/tokens/components/table/tokens-data-table.svelte'; + import CloudDownload from '@lucide/svelte/icons/cloud-download'; import Plus from '@lucide/svelte/icons/plus'; - import Send from '@lucide/svelte/icons/send'; import { createTable } from '@tanstack/svelte-table'; import { queryParamsState } from 'kit-query-params'; import { toast } from 'svelte-sonner'; @@ -88,7 +88,7 @@
- + + {#snippet toolbarChildren()} +
+ + {/snippet}
From 749ba16980b267bb0d7b9c607af28479cb14b729 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Wed, 8 Jul 2026 08:26:18 -0500 Subject: [PATCH 06/12] Refine API key setup copy --- .../routes/(app)/project/[projectId]/api-keys/+page.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte index b056f88382..8b01eb3012 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte @@ -83,8 +83,8 @@
Create and manage API keys for authenticating clients that send events to Exceptionless. - Need the server URL, install commands, or SDK snippets? - Configure Client. + For SDK install and setup instructions, + set up a client.
From 1611b606bc392764eb4771f5554afbc092c21d1e Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Wed, 8 Jul 2026 17:34:09 -0500 Subject: [PATCH 07/12] Refine client setup flow --- build/update-config-next.sh | 1 + k8s/ex-prod-values.yaml | 1 + k8s/exceptionless/templates/config.yaml | 1 + k8s/exceptionless/values.yaml | 3 +- src/Exceptionless.AppHost/Program.cs | 3 + src/Exceptionless.Web/ClientApp/.env | 7 +- .../ClientApp/.env.development | 1 + src/Exceptionless.Web/ClientApp/.gitignore | 1 + .../e2e/support/exceptionless-journey.ts | 4 +- .../project-configuration-notification.svelte | 20 +- .../setup-first-project-notification.svelte | 10 +- .../table/project-actions-cell.svelte | 10 +- .../[organizationId]/routes.svelte.ts | 12 +- .../project/[projectId]/api-keys/+page.svelte | 6 +- .../[projectId]/configure/+page.svelte | 198 ++++++++---------- .../project/[projectId]/manage/+page.svelte | 42 ++-- .../project/[projectId]/routes.svelte.ts | 19 +- 17 files changed, 157 insertions(+), 182 deletions(-) create mode 100644 src/Exceptionless.Web/ClientApp/.env.development diff --git a/build/update-config-next.sh b/build/update-config-next.sh index 61a2b2750d..030815db40 100644 --- a/build/update-config-next.sh +++ b/build/update-config-next.sh @@ -37,6 +37,7 @@ config=" PUBLIC_ENABLE_ACCOUNT_CREATION: '$EnableAccountCreation', PUBLIC_SYSTEM_NOTIFICATION_MESSAGE: '$EX_NotificationMessage', PUBLIC_EXCEPTIONLESS_API_KEY: '$EX_ExceptionlessApiKey', + PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL: '${PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL:-true}', PUBLIC_EXCEPTIONLESS_SERVER_URL: '$EX_ExceptionlessServerUrl', PUBLIC_STRIPE_PUBLISHABLE_KEY: '$EX_StripePublishableApiKey', PUBLIC_FACEBOOK_APPID: '$FacebookAppId', diff --git a/k8s/ex-prod-values.yaml b/k8s/ex-prod-values.yaml index 7089367dfa..6ef5972533 100644 --- a/k8s/ex-prod-values.yaml +++ b/k8s/ex-prod-values.yaml @@ -28,6 +28,7 @@ jobs: maxReplicaCount: 5 config: + PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL: "false" EX_EnableSnapshotJobs: "true" EX_SmtpFrom: "Exceptionless " EX_TestEmailAddress: "test@exceptionless.io" diff --git a/k8s/exceptionless/templates/config.yaml b/k8s/exceptionless/templates/config.yaml index daeb9d76a3..7b06d17438 100644 --- a/k8s/exceptionless/templates/config.yaml +++ b/k8s/exceptionless/templates/config.yaml @@ -9,6 +9,7 @@ data: {{- end }} EX_BaseUrl: https://{{.Values.app.defaultDomain}} EX_ExceptionlessServerUrl: https://{{.Values.api.defaultDomain}} + PUBLIC_EXCEPTIONLESS_SERVER_URL: https://{{.Values.api.defaultDomain}} EX_DisabledPlugins: GeoPlugin,LocationPlugin EX_EnableSsl: "true" EX_Html5Mode: "true" diff --git a/k8s/exceptionless/values.yaml b/k8s/exceptionless/values.yaml index 9b9febe39b..ced23ad213 100644 --- a/k8s/exceptionless/values.yaml +++ b/k8s/exceptionless/values.yaml @@ -19,7 +19,8 @@ jobs: repository: exceptionless/job pullPolicy: IfNotPresent -config: {} +config: + PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL: "true" # key: value ingress: diff --git a/src/Exceptionless.AppHost/Program.cs b/src/Exceptionless.AppHost/Program.cs index f0bb50f674..727ca45f88 100644 --- a/src/Exceptionless.AppHost/Program.cs +++ b/src/Exceptionless.AppHost/Program.cs @@ -14,6 +14,7 @@ int oldAppLiveReloadPort = worktreePorts?.OldAppLiveReload ?? 35729; string oldAppAspNetCoreUrls = String.Concat("http://localhost:", oldAppHttpPort); int appPort = worktreePorts?.AppHttps ?? 7131; +string publicExceptionlessServerUrl = worktreePorts?.ApiHttpsUrl ?? "https://api-ex.dev.localhost:7111"; const string SharedEmailConnectionString = "smtp://localhost:1025"; var elastic = builder.AddElasticsearch("Elasticsearch", port: 9200) @@ -180,6 +181,8 @@ .WithReference(api) .WithReference(oldApp) .RemoveJavaScriptDebuggingAnnotation() + .WithEnvironment("PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL", "true") + .WithEnvironment("PUBLIC_EXCEPTIONLESS_SERVER_URL", publicExceptionlessServerUrl) .WithEnvironment("PORT", appPort.ToString()) .WithEndpoint("http", e => { diff --git a/src/Exceptionless.Web/ClientApp/.env b/src/Exceptionless.Web/ClientApp/.env index b404d03402..c7364a03d3 100644 --- a/src/Exceptionless.Web/ClientApp/.env +++ b/src/Exceptionless.Web/ClientApp/.env @@ -1,12 +1,13 @@ PUBLIC_BASE_URL= PUBLIC_ENABLE_ACCOUNT_CREATION=true -PUBLIC_SYSTEM_NOTIFICATION_MESSAGE= PUBLIC_EXCEPTIONLESS_API_KEY= +PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL=true PUBLIC_EXCEPTIONLESS_SERVER_URL= -PUBLIC_STRIPE_PUBLISHABLE_KEY= PUBLIC_FACEBOOK_APPID= PUBLIC_GITHUB_APPID= PUBLIC_GOOGLE_APPID= -PUBLIC_MICROSOFT_APPID= PUBLIC_INTERCOM_APPID= +PUBLIC_MICROSOFT_APPID= PUBLIC_SLACK_APPID= +PUBLIC_STRIPE_PUBLISHABLE_KEY= +PUBLIC_SYSTEM_NOTIFICATION_MESSAGE= diff --git a/src/Exceptionless.Web/ClientApp/.env.development b/src/Exceptionless.Web/ClientApp/.env.development new file mode 100644 index 0000000000..09285ce4a3 --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/.env.development @@ -0,0 +1 @@ +PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL=true diff --git a/src/Exceptionless.Web/ClientApp/.gitignore b/src/Exceptionless.Web/ClientApp/.gitignore index 246cecff7e..2400260251 100644 --- a/src/Exceptionless.Web/ClientApp/.gitignore +++ b/src/Exceptionless.Web/ClientApp/.gitignore @@ -15,6 +15,7 @@ Thumbs.db .env .env.* !.env.example +!.env.development !.env.test # Vite diff --git a/src/Exceptionless.Web/ClientApp/e2e/support/exceptionless-journey.ts b/src/Exceptionless.Web/ClientApp/e2e/support/exceptionless-journey.ts index 1a32eb1247..10623ad3cb 100644 --- a/src/Exceptionless.Web/ClientApp/e2e/support/exceptionless-journey.ts +++ b/src/Exceptionless.Web/ClientApp/e2e/support/exceptionless-journey.ts @@ -118,7 +118,7 @@ export class ExceptionlessE2EJourney { this.projectId = getIdFromUrl(this.page, /\/project\/([^/]+)\/configure/); } - await expect(this.page.getByText('Select your project type.')).toBeVisible(); + await expect(this.page.getByText('Choose your project type.')).toBeVisible(); await selectProjectType(this.page, 'Bash Shell'); await expect(this.page.getByText('Execute the following in your shell.')).toBeVisible(); @@ -222,7 +222,7 @@ export class ExceptionlessE2EJourney { await this.page.waitForURL(/\/next\/project\/[^/]+\/configure/, { timeout: 30_000 }); this.projectId = getIdFromUrl(this.page, /\/project\/([^/]+)\/configure/); this.organizationId = await this.getOrganizationIdByName(); - await expect(this.page.getByText('Select your project type.')).toBeVisible(); + await expect(this.page.getByText('Choose your project type.')).toBeVisible(); } async submitRepresentativeEvent(): Promise { diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/organizations/components/notifications/project-configuration-notification.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/organizations/components/notifications/project-configuration-notification.svelte index 743190cc76..39ec9ae668 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/organizations/components/notifications/project-configuration-notification.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/organizations/components/notifications/project-configuration-notification.svelte @@ -24,20 +24,8 @@ - We haven't received any data! - - Please configure your clients for - {#if projects.length === 1} - the - {/if} - {#each projects as project, index (project.id)} - {#if index > 0}, - {/if}{project.name} - {/each} - {#if projects.length === 1} - project - {:else} - projects - {/if} and start becoming exceptionless! - + We haven't received any events yet! + + Open Client setup for this project and start becoming Exceptionless! + diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/organizations/components/notifications/setup-first-project-notification.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/organizations/components/notifications/setup-first-project-notification.svelte index 919dd1e5ea..35489c9526 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/organizations/components/notifications/setup-first-project-notification.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/organizations/components/notifications/setup-first-project-notification.svelte @@ -10,9 +10,9 @@ Setup your first project - - Please - add a new project - and start becoming exceptionless in less than 60 seconds! - + + Please + add a new project + and start becoming Exceptionless in less than 60 seconds! + 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 c6d527c87d..c9455468c1 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 @@ -54,11 +54,11 @@ goto(resolve('/(app)/project/[projectId]/manage', { projectId: project.id }))}> Edit - - goto(resolve('/(app)/project/[projectId]/configure', { projectId: project.id }))}> - - Download & Configure Client - + + goto(resolve('/(app)/project/[projectId]/configure', { projectId: project.id }))}> + + Client Setup + (showRemoveProjectDialog = true)} disabled={removeProject.isPending}> Delete diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/routes.svelte.ts b/src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/routes.svelte.ts index df4dd437d8..5fd6836d04 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/routes.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/organization/[organizationId]/routes.svelte.ts @@ -23,12 +23,6 @@ export function routes(): NavigationItem[] { icon: Settings, title: 'General' }, - { - group: 'Organization Settings', - href: resolve('/(app)/organization/[organizationId]/usage', { organizationId }), - icon: Usage, - title: 'Usage' - }, { group: 'Organization Settings', href: resolve('/(app)/organization/[organizationId]/users', { organizationId }), @@ -47,6 +41,12 @@ export function routes(): NavigationItem[] { icon: Zap, show: (ctx) => !!ctx.user?.roles?.includes('global'), title: 'Features' + }, + { + group: 'Organization Settings', + href: resolve('/(app)/organization/[organizationId]/usage', { organizationId }), + icon: Usage, + title: 'Usage' } ]; } diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte index 8b01eb3012..5149f8a36e 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/api-keys/+page.svelte @@ -81,10 +81,10 @@
- Create and manage API keys for authenticating clients that send events to Exceptionless. + Create and manage API keys for applications and services sending events to Exceptionless. - For SDK install and setup instructions, - set up a client. + To install an SDK and start sending events, open + Client setup.
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte index 7cf62f20d0..762df2047d 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte @@ -3,27 +3,25 @@ import { page } from '$app/state'; import CopyToClipboardButton from '$comp/copy-to-clipboard-button.svelte'; import { Notification, NotificationDescription, NotificationTitle } from '$comp/notification'; - import { A, CodeBlock, Muted, P } from '$comp/typography'; - import { Button } from '$comp/ui/button'; - import * as Select from '$comp/ui/select'; - import { Spinner } from '$comp/ui/spinner'; - import { env } from '$env/dynamic/public'; + import { A, CodeBlock, Muted, P } from '$comp/typography'; + import { Button } from '$comp/ui/button'; + import * as Select from '$comp/ui/select'; + import { env } from '$env/dynamic/public'; import { ProjectFilter } from '$features/events/components/filters'; - import { getIntercom } from '$features/intercom'; - import { openSupportChat } from '$features/intercom/chat'; - import { organization } from '$features/organizations/context.svelte'; - import { useHideOrganizationNotifications } from '$features/organizations/hooks/use-hide-organization-notifications.svelte'; - import { generateSampleData } from '$features/projects/api.svelte'; - import { getProjectDefaultTokenQuery, patchToken } from '$features/tokens/api.svelte'; - import EnableTokenDialog from '$features/tokens/components/dialogs/enable-token-dialog.svelte'; - import { ChangeType, type WebSocketMessageValue } from '$features/websockets/models'; - import ArrowLeft from '@lucide/svelte/icons/arrow-left'; - import Events from '@lucide/svelte/icons/calendar-days'; - import Database from '@lucide/svelte/icons/database'; - import NotificationSettings from '@lucide/svelte/icons/mail'; - import { queryParamsState } from 'kit-query-params'; - import { useEventListener } from 'runed'; - import { toast } from 'svelte-sonner'; + import { getIntercom } from '$features/intercom'; + import { openSupportChat } from '$features/intercom/chat'; + import { organization } from '$features/organizations/context.svelte'; + import { useHideOrganizationNotifications } from '$features/organizations/hooks/use-hide-organization-notifications.svelte'; + import { getProjectDefaultTokenQuery, patchToken } from '$features/tokens/api.svelte'; + import EnableTokenDialog from '$features/tokens/components/dialogs/enable-token-dialog.svelte'; + import { ChangeType, type WebSocketMessageValue } from '$features/websockets/models'; + import ArrowLeft from '@lucide/svelte/icons/arrow-left'; + import Bot from '@lucide/svelte/icons/bot'; + import Events from '@lucide/svelte/icons/calendar-days'; + import NotificationSettings from '@lucide/svelte/icons/mail'; + import { queryParamsState } from 'kit-query-params'; + import { useEventListener } from 'runed'; + import { toast } from 'svelte-sonner'; import { redirectToEventsWithFilter } from '../../../redirect-to-events.svelte'; @@ -38,12 +36,14 @@ return projectId; } } - }); + }); - const apiKey = $derived(defaultTokenQuery.data?.id || 'YOUR_API_KEY'); - const serverUrl = env.PUBLIC_API_URL || window.location.origin; - const isTokenDisabled = $derived(defaultTokenQuery.data?.is_disabled ?? false); - const isTokenSuspended = $derived(defaultTokenQuery.data?.is_suspended ?? false); + const apiKey = $derived(defaultTokenQuery.data?.id || 'YOUR_API_KEY'); + const serverUrl = (env.PUBLIC_EXCEPTIONLESS_SERVER_URL || '').trim(); + const showServerUrl = env.PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL !== 'false'; + const shouldShowServerUrl = showServerUrl && serverUrl.length > 0; + const isTokenDisabled = $derived(defaultTokenQuery.data?.is_disabled ?? false); + const isTokenSuspended = $derived(defaultTokenQuery.data?.is_suspended ?? false); let toastId = $state(); let openEnableTokenDialog = $state(false); @@ -56,16 +56,8 @@ } }); - const generateSampleDataMutation = generateSampleData({ - route: { - get id() { - return projectId; - } - } - }); - - async function enableToken() { - toast.dismiss(toastId); + async function enableToken() { + toast.dismiss(toastId); try { await enableTokenMutation.mutateAsync({ is_disabled: false }); @@ -73,22 +65,10 @@ } catch (error) { toastId = toast.error('Failed to enable API key. Please try again.'); throw error; - } - } + } + } - async function generateProjectSampleData() { - toast.dismiss(toastId); - - try { - await generateSampleDataMutation.mutateAsync(); - toastId = toast.success('Sample data generation has been queued. Events will appear shortly.'); - } catch (error) { - toastId = toast.error('Failed to generate sample data. Please try again.'); - throw error; - } - } - - interface ProjectType { + interface ProjectType { config?: string; id: string; label: string; @@ -111,13 +91,17 @@ installNote?: string; packageName: string; startupCode: string; - } + } - const projectTypes: ProjectType[] = [ - { id: 'bash', label: 'Bash Shell', platform: 'Command Line' }, - { id: 'powershell', label: 'PowerShell', platform: 'Command Line' }, + const projectTypes: ProjectType[] = [ + ...(shouldShowServerUrl + ? [ + { id: 'bash', label: 'Bash Shell', platform: 'Command Line' }, + { id: 'powershell', label: 'PowerShell', platform: 'Command Line' } + ] + : []), - { id: 'dotnet-console', label: 'Console and Service applications', package: 'Exceptionless', platform: '.NET' }, + { id: 'dotnet-console', label: 'Console and Service applications', package: 'Exceptionless', platform: '.NET' }, { id: 'dotnet-aspnetcore', label: 'ASP.NET Core', package: 'Exceptionless.AspNetCore', platform: '.NET' }, { config: 'app.config', id: 'dotnet-wpf', label: 'Windows Presentation Foundation (WPF)', package: 'Exceptionless.Wpf', platform: '.NET' }, { config: 'app.config', id: 'dotnet-winforms', label: 'Windows Forms', package: 'Exceptionless.Windows', platform: '.NET' }, @@ -186,7 +170,18 @@ }); const codeSamples = $derived({ - aspNetCore: `using Exceptionless; + aspNetCore: shouldShowServerUrl + ? `using Exceptionless; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddExceptionless(c => { + c.ApiKey = "${apiKey}"; + c.ServerUrl = "${serverUrl}"; +}); + +var app = builder.Build(); +app.UseExceptionless();` + : `using Exceptionless; var builder = WebApplication.CreateBuilder(args); builder.Services.AddExceptionless("${apiKey}"); @@ -194,31 +189,40 @@ builder.Services.AddExceptionless("${apiKey}"); var app = builder.Build(); app.UseExceptionless();`, - bashShell: `curl "${serverUrl}/api/v2/events" \\ + bashShell: shouldShowServerUrl + ? `curl "${serverUrl}/api/v2/events" \\ --request POST \\ --header "Authorization: Bearer ${apiKey}" \\ --header "Content-Type: application/json" \\ - --data-binary '[{"type":"log","message":"Hello World!"}]'`, + --data-binary '[{"type":"log","message":"Hello World!"}]'` + : '', browserJs: `import { Exceptionless } from "@exceptionless/browser"; await Exceptionless.startup(c => { - c.apiKey = "${apiKey}"; + c.apiKey = "${apiKey}";${shouldShowServerUrl ? `\n c.serverUrl = "${serverUrl}";` : ''} });`, - exceptionless: `using Exceptionless; + exceptionless: shouldShowServerUrl + ? `using Exceptionless; + +ExceptionlessClient.Default.Configuration.ApiKey = "${apiKey}"; +ExceptionlessClient.Default.Configuration.ServerUrl = "${serverUrl}"; +ExceptionlessClient.Default.Startup();` + : `using Exceptionless; ExceptionlessClient.Default.Startup("${apiKey}");`, - legacyAppConfigSectionXml: ``, + legacyAppConfigSectionXml: shouldShowServerUrl ? `` : ``, nodeJs: `import { Exceptionless } from "@exceptionless/node"; await Exceptionless.startup(c => { - c.apiKey = "${apiKey}"; + c.apiKey = "${apiKey}";${shouldShowServerUrl ? `\n c.serverUrl = "${serverUrl}";` : ''} });`, - powerShell: `$body = @{ + powerShell: shouldShowServerUrl + ? `$body = @{ "type"="log" "message"="Hello World!" } | ConvertTo-Json @@ -228,7 +232,8 @@ $header = @{ "Content-Type"="application/json" } -Invoke-RestMethod -Uri "${serverUrl}/api/v2/events" -Method "Post" -Body $body -Headers $header`, +Invoke-RestMethod -Uri "${serverUrl}/api/v2/events" -Method "Post" -Body $body -Headers $header` + : '', reactNativeExpoPlugin: `{ "expo": { @@ -239,15 +244,15 @@ Invoke-RestMethod -Uri "${serverUrl}/api/v2/events" -Method "Post" -Body $body - reactNativeJs: `import { Exceptionless } from "@exceptionless/react-native"; await Exceptionless.startup(c => { - c.apiKey = "${apiKey}"; + c.apiKey = "${apiKey}";${shouldShowServerUrl ? `\n c.serverUrl = "${serverUrl}";` : ''} });`, webApi: `public static void Register(HttpConfiguration config) { config.AddExceptionless("${apiKey}"); }`, - webApiInAspNet: `protected void Application_Start() { - ExceptionlessClient.Default.Configuration.ApiKey = "${apiKey}"; + webApiInAspNet: `protected void Application_Start() { + ExceptionlessClient.Default.Configuration.ApiKey = "${apiKey}";${shouldShowServerUrl ? `\n ExceptionlessClient.Default.Configuration.ServerUrl = "${serverUrl}";` : ''} ExceptionlessClient.Default.Startup(); }`, webApiRegister: `using Exceptionless; @@ -265,7 +270,9 @@ public class Startup { }`, webApiRegisterAspNet: `Exceptionless.ExceptionlessClient.Default.RegisterWebApi(GlobalConfiguration.Configuration)`, - windowsAttributeConfiguration: `[assembly: Exceptionless.Configuration.Exceptionless("${apiKey}")]`, + windowsAttributeConfiguration: shouldShowServerUrl + ? `[assembly: Exceptionless.Configuration.Exceptionless("${apiKey}", ServerUrl = "${serverUrl}")]` + : `[assembly: Exceptionless.Configuration.Exceptionless("${apiKey}")]`, windowsRegister: `using Exceptionless; internal static class Program { @@ -348,24 +355,9 @@ public partial class App : Application {
- The Exceptionless client can be integrated into your project in just a few easy steps -
-

Quick values for your client setup

-
-
- Server URL - {serverUrl} - -
-
- API key - {apiKey} - -
-
-
+ Choose your project type and follow the steps below to connect your application to Exceptionless. - {#if isTokenDisabled} + {#if isTokenDisabled} API Key Disabled @@ -396,12 +388,12 @@ public partial class App : Application { {/if} -
    -
  1. -

    Select your project type.

    - +
  2. +

    Choose your project type.

    + { selectedProjectType = projectTypes.find((P) => P.id === value) || null; queryParams.type = value; @@ -744,20 +736,16 @@ public partial class App : Application { - - - -
+ + + +
{#if isTokenDisabled} 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 89e421caec..ff1d263b7f 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 @@ -15,14 +15,13 @@ import RemoveProjectDialog from '$features/projects/components/dialogs/remove-project-dialog.svelte'; import ResetProjectDataDialog from '$features/projects/components/dialogs/reset-project-data-dialog.svelte'; import { type UpdateProjectFormData, UpdateProjectSchema } from '$features/projects/schemas'; - import { ariaInvalid, getFormErrorMessages, mapFieldErrors, problemDetailsToFormErrors } from '$features/shared/validation'; - import { ProblemDetails } from '@exceptionless/fetchclient'; - import AlertTriangle from '@lucide/svelte/icons/alert-triangle'; - import Bot from '@lucide/svelte/icons/bot'; - import CloudDownload from '@lucide/svelte/icons/cloud-download'; - import Database from '@lucide/svelte/icons/database'; - import Stacks from '@lucide/svelte/icons/layers'; - import NotificationSettings from '@lucide/svelte/icons/mail'; + import { ariaInvalid, getFormErrorMessages, mapFieldErrors, problemDetailsToFormErrors } from '$features/shared/validation'; + import { ProblemDetails } from '@exceptionless/fetchclient'; + import AlertTriangle from '@lucide/svelte/icons/alert-triangle'; + import CloudDownload from '@lucide/svelte/icons/cloud-download'; + import Database from '@lucide/svelte/icons/database'; + import Stacks from '@lucide/svelte/icons/layers'; + import NotificationSettings from '@lucide/svelte/icons/mail'; import X from '@lucide/svelte/icons/x'; import { createForm } from '@tanstack/svelte-form'; import { toast } from 'svelte-sonner'; @@ -170,21 +169,18 @@
- - - - - + + + + + {#snippet toolbarChildren()} +
+ + {/snippet}
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte index f54f535b8d..1b341eb762 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/configure/+page.svelte @@ -3,25 +3,25 @@ import { page } from '$app/state'; import CopyToClipboardButton from '$comp/copy-to-clipboard-button.svelte'; import { Notification, NotificationDescription, NotificationTitle } from '$comp/notification'; - import { A, CodeBlock, Muted, P } from '$comp/typography'; - import { Button } from '$comp/ui/button'; - import * as Select from '$comp/ui/select'; - import { env } from '$env/dynamic/public'; + import { A, CodeBlock, Muted, P } from '$comp/typography'; + import { Button } from '$comp/ui/button'; + import * as Select from '$comp/ui/select'; + import { env } from '$env/dynamic/public'; import { ProjectFilter } from '$features/events/components/filters'; - import { getIntercom } from '$features/intercom'; - import { openSupportChat } from '$features/intercom/chat'; - import { organization } from '$features/organizations/context.svelte'; - import { useHideOrganizationNotifications } from '$features/organizations/hooks/use-hide-organization-notifications.svelte'; - import { getProjectDefaultTokenQuery, patchToken } from '$features/tokens/api.svelte'; - import EnableTokenDialog from '$features/tokens/components/dialogs/enable-token-dialog.svelte'; - import { ChangeType, type WebSocketMessageValue } from '$features/websockets/models'; - import ArrowLeft from '@lucide/svelte/icons/arrow-left'; - import Bot from '@lucide/svelte/icons/bot'; - import Events from '@lucide/svelte/icons/calendar-days'; - import NotificationSettings from '@lucide/svelte/icons/mail'; - import { queryParamsState } from 'kit-query-params'; - import { useEventListener } from 'runed'; - import { toast } from 'svelte-sonner'; + import { getIntercom } from '$features/intercom'; + import { openSupportChat } from '$features/intercom/chat'; + import { organization } from '$features/organizations/context.svelte'; + import { useHideOrganizationNotifications } from '$features/organizations/hooks/use-hide-organization-notifications.svelte'; + import { getProjectDefaultTokenQuery, patchToken } from '$features/tokens/api.svelte'; + import EnableTokenDialog from '$features/tokens/components/dialogs/enable-token-dialog.svelte'; + import { ChangeType, type WebSocketMessageValue } from '$features/websockets/models'; + import ArrowLeft from '@lucide/svelte/icons/arrow-left'; + import Bot from '@lucide/svelte/icons/bot'; + import Events from '@lucide/svelte/icons/calendar-days'; + import NotificationSettings from '@lucide/svelte/icons/mail'; + import { queryParamsState } from 'kit-query-params'; + import { useEventListener } from 'runed'; + import { toast } from 'svelte-sonner'; import { redirectToEventsWithFilter } from '../../../redirect-to-events.svelte'; @@ -36,14 +36,15 @@ return projectId; } } - }); + }); - const apiKey = $derived(defaultTokenQuery.data?.id || 'YOUR_API_KEY'); - const serverUrl = (env.PUBLIC_EXCEPTIONLESS_SERVER_URL || '').trim(); - const showServerUrl = env.PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL !== 'false'; - const shouldShowServerUrl = showServerUrl && serverUrl.length > 0; - const isTokenDisabled = $derived(defaultTokenQuery.data?.is_disabled ?? false); - const isTokenSuspended = $derived(defaultTokenQuery.data?.is_suspended ?? false); + const apiKey = $derived(defaultTokenQuery.data?.id || 'YOUR_API_KEY'); + const serverUrl = (env.PUBLIC_EXCEPTIONLESS_SERVER_URL || '').trim(); + const showServerUrl = env.PUBLIC_EXCEPTIONLESS_CLIENT_SETUP_SHOW_SERVER_URL !== 'false'; + const shouldShowServerUrl = showServerUrl && serverUrl.length > 0; + const eventSubmissionUrl = serverUrl.length > 0 ? `${serverUrl}/api/v2/events` : 'YOUR_EXCEPTIONLESS_SERVER_URL/api/v2/events'; + const isTokenDisabled = $derived(defaultTokenQuery.data?.is_disabled ?? false); + const isTokenSuspended = $derived(defaultTokenQuery.data?.is_suspended ?? false); let toastId = $state(); let openEnableTokenDialog = $state(false); @@ -56,8 +57,8 @@ } }); - async function enableToken() { - toast.dismiss(toastId); + async function enableToken() { + toast.dismiss(toastId); try { await enableTokenMutation.mutateAsync({ is_disabled: false }); @@ -65,10 +66,10 @@ } catch (error) { toastId = toast.error('Failed to enable API key. Please try again.'); throw error; - } - } + } + } - interface ProjectType { + interface ProjectType { config?: string; id: string; label: string; @@ -91,13 +92,13 @@ installNote?: string; packageName: string; startupCode: string; - } + } - const projectTypes: ProjectType[] = [ - { id: 'bash', label: 'Bash Shell', platform: 'Command Line' }, - { id: 'powershell', label: 'PowerShell', platform: 'Command Line' }, + const projectTypes: ProjectType[] = [ + { id: 'bash', label: 'Bash Shell', platform: 'Command Line' }, + { id: 'powershell', label: 'PowerShell', platform: 'Command Line' }, - { id: 'dotnet-console', label: 'Console and Service applications', package: 'Exceptionless', platform: '.NET' }, + { id: 'dotnet-console', label: 'Console and Service applications', package: 'Exceptionless', platform: '.NET' }, { id: 'dotnet-aspnetcore', label: 'ASP.NET Core', package: 'Exceptionless.AspNetCore', platform: '.NET' }, { config: 'app.config', id: 'dotnet-wpf', label: 'Windows Presentation Foundation (WPF)', package: 'Exceptionless.Wpf', platform: '.NET' }, { config: 'app.config', id: 'dotnet-winforms', label: 'Windows Forms', package: 'Exceptionless.Windows', platform: '.NET' }, @@ -166,8 +167,8 @@ }); const codeSamples = $derived({ - aspNetCore: shouldShowServerUrl - ? `using Exceptionless; + aspNetCore: shouldShowServerUrl + ? `using Exceptionless; var builder = WebApplication.CreateBuilder(args); builder.Services.AddExceptionless(c => { @@ -177,7 +178,7 @@ builder.Services.AddExceptionless(c => { var app = builder.Build(); app.UseExceptionless();` - : `using Exceptionless; + : `using Exceptionless; var builder = WebApplication.CreateBuilder(args); builder.Services.AddExceptionless("${apiKey}"); @@ -185,13 +186,7 @@ builder.Services.AddExceptionless("${apiKey}"); var app = builder.Build(); app.UseExceptionless();`, - bashShell: shouldShowServerUrl - ? `curl "${serverUrl}/api/v2/events" \\ - --request POST \\ - --header "Authorization: Bearer ${apiKey}" \\ - --header "Content-Type: application/json" \\ - --data-binary '[{"type":"log","message":"Hello World!"}]'` - : `curl "/api/v2/events" \\ + bashShell: `curl "${eventSubmissionUrl}" \\ --request POST \\ --header "Authorization: Bearer ${apiKey}" \\ --header "Content-Type: application/json" \\ @@ -203,17 +198,19 @@ await Exceptionless.startup(c => { c.apiKey = "${apiKey}";${shouldShowServerUrl ? `\n c.serverUrl = "${serverUrl}";` : ''} });`, - exceptionless: shouldShowServerUrl - ? `using Exceptionless; + exceptionless: shouldShowServerUrl + ? `using Exceptionless; ExceptionlessClient.Default.Configuration.ApiKey = "${apiKey}"; ExceptionlessClient.Default.Configuration.ServerUrl = "${serverUrl}"; ExceptionlessClient.Default.Startup();` - : `using Exceptionless; + : `using Exceptionless; ExceptionlessClient.Default.Startup("${apiKey}");`, - legacyAppConfigSectionXml: shouldShowServerUrl ? `` : ``, + legacyAppConfigSectionXml: shouldShowServerUrl + ? `` + : ``, nodeJs: `import { Exceptionless } from "@exceptionless/node"; @@ -221,19 +218,7 @@ await Exceptionless.startup(c => { c.apiKey = "${apiKey}";${shouldShowServerUrl ? `\n c.serverUrl = "${serverUrl}";` : ''} });`, - powerShell: shouldShowServerUrl - ? `$body = @{ - "type"="log" - "message"="Hello World!" -} | ConvertTo-Json - -$header = @{ - "Authorization"="Bearer ${apiKey}" - "Content-Type"="application/json" -} - -Invoke-RestMethod -Uri "${serverUrl}/api/v2/events" -Method "Post" -Body $body -Headers $header` - : `$body = @{ + powerShell: `$body = @{ "type"="log" "message"="Hello World!" } | ConvertTo-Json @@ -243,7 +228,7 @@ $header = @{ "Content-Type"="application/json" } -Invoke-RestMethod -Uri "/api/v2/events" -Method "Post" -Body $body -Headers $header`, +Invoke-RestMethod -Uri "${eventSubmissionUrl}" -Method "Post" -Body $body -Headers $header`, reactNativeExpoPlugin: `{ "expo": { @@ -261,7 +246,7 @@ await Exceptionless.startup(c => { config.AddExceptionless("${apiKey}"); }`, - webApiInAspNet: `protected void Application_Start() { + webApiInAspNet: `protected void Application_Start() { ExceptionlessClient.Default.Configuration.ApiKey = "${apiKey}";${shouldShowServerUrl ? `\n ExceptionlessClient.Default.Configuration.ServerUrl = "${serverUrl}";` : ''} ExceptionlessClient.Default.Startup(); }`, @@ -280,9 +265,9 @@ public class Startup { }`, webApiRegisterAspNet: `Exceptionless.ExceptionlessClient.Default.RegisterWebApi(GlobalConfiguration.Configuration)`, - windowsAttributeConfiguration: shouldShowServerUrl - ? `[assembly: Exceptionless.Configuration.Exceptionless("${apiKey}", ServerUrl = "${serverUrl}")]` - : `[assembly: Exceptionless.Configuration.Exceptionless("${apiKey}")]`, + windowsAttributeConfiguration: shouldShowServerUrl + ? `[assembly: Exceptionless.Configuration.Exceptionless("${apiKey}", ServerUrl = "${serverUrl}")]` + : `[assembly: Exceptionless.Configuration.Exceptionless("${apiKey}")]`, windowsRegister: `using Exceptionless; internal static class Program { @@ -365,9 +350,9 @@ public partial class App : Application {
- Choose your project type and follow the steps below to connect your application to Exceptionless. + Choose your project type and follow the steps below to connect your application to Exceptionless. - {#if isTokenDisabled} + {#if isTokenDisabled} API Key Disabled @@ -398,12 +383,12 @@ public partial class App : Application { {/if} -
    -
  1. -

    Choose your project type.

    - +
  2. +

    Choose your project type.

    + { selectedProjectType = projectTypes.find((P) => P.id === value) || null; queryParams.type = value; @@ -746,16 +731,16 @@ public partial class App : Application { - - - -
+ + + +
{#if isTokenDisabled} 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 ff1d263b7f..031d35550d 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 @@ -15,13 +15,13 @@ import RemoveProjectDialog from '$features/projects/components/dialogs/remove-project-dialog.svelte'; import ResetProjectDataDialog from '$features/projects/components/dialogs/reset-project-data-dialog.svelte'; import { type UpdateProjectFormData, UpdateProjectSchema } from '$features/projects/schemas'; - import { ariaInvalid, getFormErrorMessages, mapFieldErrors, problemDetailsToFormErrors } from '$features/shared/validation'; - import { ProblemDetails } from '@exceptionless/fetchclient'; - import AlertTriangle from '@lucide/svelte/icons/alert-triangle'; - import CloudDownload from '@lucide/svelte/icons/cloud-download'; - import Database from '@lucide/svelte/icons/database'; - import Stacks from '@lucide/svelte/icons/layers'; - import NotificationSettings from '@lucide/svelte/icons/mail'; + import { ariaInvalid, getFormErrorMessages, mapFieldErrors, problemDetailsToFormErrors } from '$features/shared/validation'; + import { ProblemDetails } from '@exceptionless/fetchclient'; + import AlertTriangle from '@lucide/svelte/icons/alert-triangle'; + import CloudDownload from '@lucide/svelte/icons/cloud-download'; + import Database from '@lucide/svelte/icons/database'; + import Stacks from '@lucide/svelte/icons/layers'; + import NotificationSettings from '@lucide/svelte/icons/mail'; import X from '@lucide/svelte/icons/x'; import { createForm } from '@tanstack/svelte-form'; import { toast } from 'svelte-sonner'; @@ -169,18 +169,18 @@
- - - - + + +