From dae56de82a41997a403b34a95fb7848e5d5c462a Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 19 Jul 2025 15:55:50 -0500 Subject: [PATCH 01/45] Uses HashSet for user organization and roles. Uses HashSet instead of Collection for storing user organization IDs and roles. This change improves performance by leveraging the efficient lookup capabilities of HashSet, ensuring uniqueness and faster access when checking for organization or role membership. --- src/Exceptionless.Core/Models/User.cs | 4 ++-- src/Exceptionless.Web/Models/User/ViewUser.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Exceptionless.Core/Models/User.cs b/src/Exceptionless.Core/Models/User.cs index e62c0e6211..e4376e3852 100644 --- a/src/Exceptionless.Core/Models/User.cs +++ b/src/Exceptionless.Core/Models/User.cs @@ -14,7 +14,7 @@ public record User : IIdentity, IHaveDates, IValidatableObject /// /// The organizations that the user has access to. /// - public ICollection OrganizationIds { get; } = new Collection(); + public ISet OrganizationIds { get; } = new HashSet(); public string? Password { get; set; } public string? Salt { get; set; } @@ -41,7 +41,7 @@ public record User : IIdentity, IHaveDates, IValidatableObject /// public bool IsActive { get; init; } = true; - public ICollection Roles { get; init; } = new Collection(); + public ISet Roles { get; init; } = new HashSet(); public DateTime CreatedUtc { get; set; } public DateTime UpdatedUtc { get; set; } diff --git a/src/Exceptionless.Web/Models/User/ViewUser.cs b/src/Exceptionless.Web/Models/User/ViewUser.cs index 526ee89392..20cb063d9b 100644 --- a/src/Exceptionless.Web/Models/User/ViewUser.cs +++ b/src/Exceptionless.Web/Models/User/ViewUser.cs @@ -5,12 +5,12 @@ namespace Exceptionless.Web.Models; public record ViewUser : IIdentity { public string Id { get; set; } = null!; - public ICollection OrganizationIds { get; init; } = null!; + public ISet OrganizationIds { get; init; } = null!; public string FullName { get; init; } = null!; public string EmailAddress { get; init; } = null!; public bool EmailNotificationsEnabled { get; init; } public bool IsEmailAddressVerified { get; init; } public bool IsActive { get; init; } public bool IsInvite { get; init; } - public ICollection Roles { get; init; } = null!; + public ISet Roles { get; init; } = null!; } From debb3a12f658754f12d7711207068f496c228fdc Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 19 Jul 2025 16:23:11 -0500 Subject: [PATCH 02/45] Adds organization management links to UI Adds links to manage organization settings and billing directly from the user and organization switcher dropdowns. This provides quick access to organization management features, improving the user experience. --- .../sidebar-organization-switcher.svelte | 30 +++++++++++++- .../(components)/layouts/sidebar-user.svelte | 41 +++++++++++++------ 2 files changed, 56 insertions(+), 15 deletions(-) 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 4ebff47792..589d1d74f7 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 @@ -1,6 +1,7 @@ {#if organizations && organizations.length > 1} @@ -57,7 +69,7 @@ {/snippet} - + {#if activeOrganization?.id} + +
+
+ Manage organization + ⇧⌘go +
+ + {/if} +
Add organization + ⇧⌘gn
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte index c5fe4d3495..9c942ef9e9 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte @@ -7,16 +7,19 @@ import * as Sidebar from '$comp/ui/sidebar/index'; import { useSidebar } from '$comp/ui/sidebar/index'; import { Skeleton } from '$comp/ui/skeleton'; + import { organization } from '$features/organizations/context.svelte'; import { User } from '$features/users/models'; import BadgeCheck from '@lucide/svelte/icons/badge-check'; import BookOpen from '@lucide/svelte/icons/book-open'; import Braces from '@lucide/svelte/icons/braces'; - // import Bell from '@lucide/svelte/icons/bell'; + import Bell from '@lucide/svelte/icons/bell'; import ChevronsUpDown from '@lucide/svelte/icons/chevrons-up-down'; import Help from '@lucide/svelte/icons/circle-help'; import GitHub from '@lucide/svelte/icons/github'; - // import CreditCard from '@lucide/svelte/icons/credit-card'; + import CreditCard from '@lucide/svelte/icons/credit-card'; import LogOut from '@lucide/svelte/icons/log-out'; + import Plus from '@lucide/svelte/icons/plus'; + import Settings from '@lucide/svelte/icons/settings'; interface Props { gravatar: Gravatar; @@ -99,17 +102,29 @@ Account ⇧⌘ga - + + + Notifications + ⇧⌘gn + + {#if organization.current} + + + Billing + ⇧⌘gb + + + + Manage organization + ⇧⌘go + + {:else} + + + Add organization + ⇧⌘ga + + {/if} From 5317a9fdacf2aa88d530914c84c0ad2c363c9ec3 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 19 Jul 2025 16:23:39 -0500 Subject: [PATCH 03/45] Includes invites in user count Corrects user pagination by including pending invites in the total user count for accurate "has more" calculations. --- src/Exceptionless.Web/Controllers/UserController.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Exceptionless.Web/Controllers/UserController.cs b/src/Exceptionless.Web/Controllers/UserController.cs index 5d91ea0ca4..afdcd9248c 100644 --- a/src/Exceptionless.Web/Controllers/UserController.cs +++ b/src/Exceptionless.Web/Controllers/UserController.cs @@ -103,8 +103,9 @@ public async Task>> GetByOrganization })); } + long total = results.Total + organization.Invites.Count; var pagedUsers = users.Skip(skip).Take(limit).ToList(); - return OkWithResourceLinks(pagedUsers, users.Count > GetSkip(page + 1, limit), page); + return OkWithResourceLinks(pagedUsers, total > GetSkip(page + 1, limit), page, total); } /// From a5181163652c5feb65dbb9437f8962e1e3338979 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 19 Jul 2025 16:25:26 -0500 Subject: [PATCH 04/45] Updates organization links to use A component Replaces the `goto` function calls with the `A` component from the typography module for navigating to organization management and creation pages. This change enhances the user experience and allows for styling. --- .../sidebar-organization-switcher.svelte | 43 ++++++++----------- .../(components)/layouts/sidebar-user.svelte | 26 ++++++----- 2 files changed, 33 insertions(+), 36 deletions(-) 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 589d1d74f7..5d09e753f0 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 @@ -1,8 +1,8 @@ {#if organizations && organizations.length > 1} @@ -92,24 +82,25 @@ {/if} {#if activeOrganization?.id} - -
-
- Manage organization - ⇧⌘go + + +
+
+ Manage organization + ⇧⌘go +
{/if} - -
-
- Add organization - ⇧⌘gn + + +
+
+ Add organization + ⇧⌘gn +
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte index 9c942ef9e9..547a110ac1 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte @@ -10,13 +10,13 @@ import { organization } from '$features/organizations/context.svelte'; import { User } from '$features/users/models'; import BadgeCheck from '@lucide/svelte/icons/badge-check'; + import Bell from '@lucide/svelte/icons/bell'; import BookOpen from '@lucide/svelte/icons/book-open'; import Braces from '@lucide/svelte/icons/braces'; - import Bell from '@lucide/svelte/icons/bell'; import ChevronsUpDown from '@lucide/svelte/icons/chevrons-up-down'; import Help from '@lucide/svelte/icons/circle-help'; - import GitHub from '@lucide/svelte/icons/github'; import CreditCard from '@lucide/svelte/icons/credit-card'; + import GitHub from '@lucide/svelte/icons/github'; import LogOut from '@lucide/svelte/icons/log-out'; import Plus from '@lucide/svelte/icons/plus'; import Settings from '@lucide/svelte/icons/settings'; @@ -109,20 +109,26 @@
{#if organization.current} - - Billing - ⇧⌘gb + + + Manage organization + ⇧⌘go + - - Manage organization - ⇧⌘go + + + Billing + ⇧⌘gb + {:else} - Add organization - ⇧⌘ga + + Add organization + ⇧⌘gn + {/if} From ba70a1702ee1cabc3e2023a5c1e0b425ca53ae7c Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 21 Jul 2025 17:15:00 -0500 Subject: [PATCH 05/45] WIP - Account notifications --- .../sidebar-organization-switcher.svelte | 4 +- .../(components)/layouts/sidebar-user.svelte | 16 +- .../(app)/account/notifications/+page.svelte | 223 ++++++++++++++++-- .../src/routes/(app)/account/routes.svelte.ts | 1 - 4 files changed, 213 insertions(+), 31 deletions(-) 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 5d09e753f0..01daebb6bc 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 @@ -83,7 +83,7 @@ {#if activeOrganization?.id} - +
@@ -94,7 +94,7 @@ {/if} -
+
diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte index 547a110ac1..69de4db86c 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/(components)/layouts/sidebar-user.svelte @@ -110,14 +110,24 @@ {#if organization.current} -
+ Manage organization ⇧⌘go
- + Billing ⇧⌘gb @@ -125,7 +135,7 @@ {:else} - + Add organization ⇧⌘gn 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 99a0d763a5..58ed71f99a 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 @@ -1,27 +1,154 @@
@@ -31,26 +158,72 @@
-
- - +

Email Notifications

Communication emails

Receive emails about your account activity.
- +
+ {#if updateUser.isPending} + + {/if} +
-
- -
-
+ + + + {:else} +
No Project Selected
+ Please select a project to edit notification settings. + {/if} + diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/routes.svelte.ts b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/routes.svelte.ts index 60da726bef..a06d74d710 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/routes.svelte.ts +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/routes.svelte.ts @@ -25,7 +25,6 @@ export function routes(): NavigationItem[] { group: 'My Account', href: '/next/account/notifications', icon: Notifications, - show: () => false, title: 'Notifications' }, { From 66f9b2915d36b8333a257aa600b7ebb461938ea9 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 21 Jul 2025 17:15:06 -0500 Subject: [PATCH 06/45] updated svelte --- src/Exceptionless.Web/ClientApp/package-lock.json | 8 ++++---- src/Exceptionless.Web/ClientApp/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index e096914fb2..6fa5a6c05c 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -69,7 +69,7 @@ "prettier-plugin-svelte": "^3.4.0", "prettier-plugin-tailwindcss": "^0.6.14", "storybook": "^9.0.17", - "svelte": "^5.36.8", + "svelte": "^5.36.10", "svelte-check": "^4.3.0", "swagger-typescript-api": "^13.2.7", "tslib": "^2.8.1", @@ -7830,9 +7830,9 @@ } }, "node_modules/svelte": { - "version": "5.36.8", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.36.8.tgz", - "integrity": "sha512-8JbZWQu96hMjH/oYQPxXW6taeC6Awl6muGHeZzJTxQx7NGRQ/J9wN1hkzRKLOlSDlbS2igiFg7p5xyTp5uXG3A==", + "version": "5.36.10", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.36.10.tgz", + "integrity": "sha512-hAjYQweQHM8VH5YEEf2+k9hGyMnd+oVHXoSA/eG607vViRk9qQO1g+Dvr29+yMuYQNScpOzHX3qcnC7LrcTGCQ==", "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 45fd3b0569..2bd298dcfa 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -54,7 +54,7 @@ "prettier-plugin-svelte": "^3.4.0", "prettier-plugin-tailwindcss": "^0.6.14", "storybook": "^9.0.17", - "svelte": "^5.36.8", + "svelte": "^5.36.10", "svelte-check": "^4.3.0", "swagger-typescript-api": "^13.2.7", "tslib": "^2.8.1", From e68650c267db8bd033073327e388950387853640 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 21 Jul 2025 21:50:39 -0500 Subject: [PATCH 07/45] Updates dev dependencies Updates Svelte and Typescript-eslint dev dependencies. This ensures the project is using the latest available versions of these packages, which may include bug fixes, performance improvements, and new features. --- .../ClientApp/package-lock.json | 132 +++++++++--------- src/Exceptionless.Web/ClientApp/package.json | 4 +- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/package-lock.json b/src/Exceptionless.Web/ClientApp/package-lock.json index 6fa5a6c05c..e4d9068298 100644 --- a/src/Exceptionless.Web/ClientApp/package-lock.json +++ b/src/Exceptionless.Web/ClientApp/package-lock.json @@ -69,12 +69,12 @@ "prettier-plugin-svelte": "^3.4.0", "prettier-plugin-tailwindcss": "^0.6.14", "storybook": "^9.0.17", - "svelte": "^5.36.10", + "svelte": "^5.36.13", "svelte-check": "^4.3.0", "swagger-typescript-api": "^13.2.7", "tslib": "^2.8.1", "typescript": "^5.8.3", - "typescript-eslint": "^8.37.0", + "typescript-eslint": "^8.38.0", "vite": "^6.3.5", "vitest": "3.2.4" } @@ -2721,17 +2721,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.37.0.tgz", - "integrity": "sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz", + "integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.37.0", - "@typescript-eslint/type-utils": "8.37.0", - "@typescript-eslint/utils": "8.37.0", - "@typescript-eslint/visitor-keys": "8.37.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/type-utils": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2745,7 +2745,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.37.0", + "@typescript-eslint/parser": "^8.38.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -2761,16 +2761,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.37.0.tgz", - "integrity": "sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz", + "integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.37.0", - "@typescript-eslint/types": "8.37.0", - "@typescript-eslint/typescript-estree": "8.37.0", - "@typescript-eslint/visitor-keys": "8.37.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", "debug": "^4.3.4" }, "engines": { @@ -2786,14 +2786,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.37.0.tgz", - "integrity": "sha512-BIUXYsbkl5A1aJDdYJCBAo8rCEbAvdquQ8AnLb6z5Lp1u3x5PNgSSx9A/zqYc++Xnr/0DVpls8iQ2cJs/izTXA==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", + "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.37.0", - "@typescript-eslint/types": "^8.37.0", + "@typescript-eslint/tsconfig-utils": "^8.38.0", + "@typescript-eslint/types": "^8.38.0", "debug": "^4.3.4" }, "engines": { @@ -2808,14 +2808,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.37.0.tgz", - "integrity": "sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz", + "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.37.0", - "@typescript-eslint/visitor-keys": "8.37.0" + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2826,9 +2826,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.37.0.tgz", - "integrity": "sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", + "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", "dev": true, "license": "MIT", "engines": { @@ -2843,15 +2843,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.37.0.tgz", - "integrity": "sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz", + "integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.37.0", - "@typescript-eslint/typescript-estree": "8.37.0", - "@typescript-eslint/utils": "8.37.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -2868,9 +2868,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.37.0.tgz", - "integrity": "sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", + "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", "dev": true, "license": "MIT", "engines": { @@ -2882,16 +2882,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.37.0.tgz", - "integrity": "sha512-zuWDMDuzMRbQOM+bHyU4/slw27bAUEcKSKKs3hcv2aNnc/tvE/h7w60dwVw8vnal2Pub6RT1T7BI8tFZ1fE+yg==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", + "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.37.0", - "@typescript-eslint/tsconfig-utils": "8.37.0", - "@typescript-eslint/types": "8.37.0", - "@typescript-eslint/visitor-keys": "8.37.0", + "@typescript-eslint/project-service": "8.38.0", + "@typescript-eslint/tsconfig-utils": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2937,16 +2937,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.37.0.tgz", - "integrity": "sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz", + "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.37.0", - "@typescript-eslint/types": "8.37.0", - "@typescript-eslint/typescript-estree": "8.37.0" + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2961,13 +2961,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.37.0.tgz", - "integrity": "sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", + "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/types": "8.38.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -7830,9 +7830,9 @@ } }, "node_modules/svelte": { - "version": "5.36.10", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.36.10.tgz", - "integrity": "sha512-hAjYQweQHM8VH5YEEf2+k9hGyMnd+oVHXoSA/eG607vViRk9qQO1g+Dvr29+yMuYQNScpOzHX3qcnC7LrcTGCQ==", + "version": "5.36.13", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.36.13.tgz", + "integrity": "sha512-LnSywHHQM/nJekC65d84T1Yo85IeCYN4AryWYPhTokSvcEAFdYFCfbMhX1mc0zHizT736QQj0nalUk+SXaWrEQ==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -8641,16 +8641,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.37.0.tgz", - "integrity": "sha512-TnbEjzkE9EmcO0Q2zM+GE8NQLItNAJpMmED1BdgoBMYNdqMhzlbqfdSwiRlAzEK2pA9UzVW0gzaaIzXWg2BjfA==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.38.0.tgz", + "integrity": "sha512-FsZlrYK6bPDGoLeZRuvx2v6qrM03I0U0SnfCLPs/XCCPCFD80xU9Pg09H/K+XFa68uJuZo7l/Xhs+eDRg2l3hg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.37.0", - "@typescript-eslint/parser": "8.37.0", - "@typescript-eslint/typescript-estree": "8.37.0", - "@typescript-eslint/utils": "8.37.0" + "@typescript-eslint/eslint-plugin": "8.38.0", + "@typescript-eslint/parser": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/src/Exceptionless.Web/ClientApp/package.json b/src/Exceptionless.Web/ClientApp/package.json index 2bd298dcfa..c839045740 100644 --- a/src/Exceptionless.Web/ClientApp/package.json +++ b/src/Exceptionless.Web/ClientApp/package.json @@ -54,12 +54,12 @@ "prettier-plugin-svelte": "^3.4.0", "prettier-plugin-tailwindcss": "^0.6.14", "storybook": "^9.0.17", - "svelte": "^5.36.10", + "svelte": "^5.36.13", "svelte-check": "^4.3.0", "swagger-typescript-api": "^13.2.7", "tslib": "^2.8.1", "typescript": "^5.8.3", - "typescript-eslint": "^8.37.0", + "typescript-eslint": "^8.38.0", "vite": "^6.3.5", "vitest": "3.2.4" }, From 7cd7e9ffa3ad10bab4fb0101432b1097b5e31488 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Mon, 21 Jul 2025 21:52:15 -0500 Subject: [PATCH 08/45] WIP account notification page updates --- .../(app)/account/notifications/+page.svelte | 121 +++++------------- 1 file changed, 35 insertions(+), 86 deletions(-) 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 58ed71f99a..ddc44ea99a 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 @@ -1,13 +1,12 @@ -{#if $formData} +{#if $formData.send_daily_summary !== undefined}
From d918f4f3446a0b15443f034f9547b31631a984e6 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Thu, 24 Jul 2025 21:39:29 -0500 Subject: [PATCH 12/45] Updates Beast Mode chatmode to v3.1 Refactors the Beast Mode chatmode configuration for improved tool usage and instruction clarity. The update includes a refined set of available tools, clarifies internet research guidelines with more specific instructions on link fetching, and emphasizes the importance of memory management to avoid redundant file reads. Also enforces .env file creation and updates todo list formatting. --- .github/chatmodes/4.1-Beast.chatmode.md | 74 ++++++++++++++++++++----- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/.github/chatmodes/4.1-Beast.chatmode.md b/.github/chatmodes/4.1-Beast.chatmode.md index a00566584b..8a4c8e33af 100644 --- a/.github/chatmodes/4.1-Beast.chatmode.md +++ b/.github/chatmodes/4.1-Beast.chatmode.md @@ -1,9 +1,10 @@ --- -description: 'GPT 4.1 as a top-notch coding agent.' -model: GPT-4.1 -title: '4.1 Beast Mode (VS Code v1.102)' +description: Beast Mode 3.1 +tools: ['changes', 'codebase', 'editFiles', 'extensions', 'fetch', 'findTestFiles', 'githubRepo', 'new', 'problems', 'runInTerminal', 'runNotebooks', 'runTasks', 'runTests', 'search', 'searchResults', 'terminalLastCommand', 'terminalSelection', 'testFailure', 'usages', 'vscodeAPI'] --- +# Beast Mode 3.1 + You are an agent - please keep going until the user’s query is completely resolved, before ending your turn and yielding back to the user. Your thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough. @@ -18,7 +19,7 @@ THE PROBLEM CAN NOT BE SOLVED WITHOUT EXTENSIVE INTERNET RESEARCH. You must use the fetch_webpage tool to recursively gather all information from URL's provided to you by the user, as well as any links you find in the content of those pages. -Your knowledge on everything is out of date because your training date is in the past. +Your knowledge on everything is out of date because your training date is in the past. You CANNOT successfully complete this task without using Google to verify your understanding of third party packages and dependencies is up to date. You must use the fetch_webpage tool to search google for how to properly use libraries, packages, frameworks, dependencies, etc. every single time you install or implement one. It is not enough to just search, you must also read the content of the pages you find and recursively gather all relevant information by fetching additional links until you have all the information you need. @@ -30,12 +31,11 @@ Take your time and think through every step - remember to check your solution ri You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully. -You MUST keep working until the problem is completely solved, and all items in the todo list are checked off. Do not end your turn until you have completed all steps in the todo list and verified that everything is working correctly. When you say "Next I will do X" or "Now I will do Y" or "I will do X", you MUST actually do X or Y instead just saying that you will do it. +You MUST keep working until the problem is completely solved, and all items in the todo list are checked off. Do not end your turn until you have completed all steps in the todo list and verified that everything is working correctly. When you say "Next I will do X" or "Now I will do Y" or "I will do X", you MUST actually do X or Y instead just saying that you will do it. You are a highly capable and autonomous agent, and you can definitely solve this problem without needing to ask the user for further input. # Workflow - 1. Fetch any URL's provided by the user using the `fetch_webpage` tool. 2. Understand the problem deeply. Carefully read the issue and think critically about what is required. Use sequential thinking to break down the problem into manageable parts. Consider the following: - What is the expected behavior? @@ -45,7 +45,7 @@ You are a highly capable and autonomous agent, and you can definitely solve this - What are the dependencies and interactions with other parts of the code? 3. Investigate the codebase. Explore relevant files, search for key functions, and gather context. 4. Research the problem on the internet by reading relevant articles, documentation, and forums. -5. Develop a clear, step-by-step plan. Break down the fix into manageable, incremental steps. Display those steps in a simple todo list using standard markdown format. Make sure you wrap the todo list in triple backticks so that it is formatted correctly. +5. Develop a clear, step-by-step plan. Break down the fix into manageable, incremental steps. Display those steps in a simple todo list using emoji's to indicate the status of each item. 6. Implement the fix incrementally. Make small, testable code changes. 7. Debug as needed. Use debugging techniques to isolate and resolve issues. 8. Test frequently. Run tests after each change to verify correctness. @@ -73,24 +73,26 @@ Carefully read the issue and think hard about a plan to solve it before coding. ## 4. Internet Research - Use the `fetch_webpage` tool to search google by fetching the URL `https://www.google.com/search?q=your+search+query`. - After fetching, review the content returned by the fetch tool. -- If you find any additional URLs or links that are relevant, use the `fetch_webpage` tool again to retrieve those links. -- Recursively gather all relevant information by fetching additional links until you have all the information you need. +- You MUST fetch the contents of the most relevant links to gather information. Do not rely on the summary that you find in the search results. +- As you fetch each link, read the content thoroughly and fetch any additional links that you find withhin the content that are relevant to the problem. +- Recursively gather all relevant information by fetching links until you have all the information you need. -## 5. Develop a Detailed Plan +## 5. Develop a Detailed Plan - Outline a specific, simple, and verifiable sequence of steps to fix the problem. - Create a todo list in markdown format to track your progress. - Each time you complete a step, check it off using `[x]` syntax. - Each time you check off a step, display the updated todo list to the user. -- Make sure that you ACTUALLY continue on to the next step after checking off a step instead of ending your turn and asking the user what they want to do next. +- Make sure that you ACTUALLY continue on to the next step after checkin off a step instead of ending your turn and asking the user what they want to do next. ## 6. Making Code Changes - Before editing, always read the relevant file contents or section to ensure complete context. - Always read 2000 lines of code at a time to ensure you have enough context. - If a patch is not applied correctly, attempt to reapply it. - Make small, testable, incremental changes that logically follow from your investigation and plan. +- Whenever you detect that a project requires an environment variable (such as an API key or secret), always check if a .env file exists in the project root. If it does not exist, automatically create a .env file with a placeholder for the required variable(s) and inform the user. Do this proactively, without waiting for the user to request it. ## 7. Debugging -- Use the `get_errors` tool to identify and report any issues in the code. This tool replaces the previously used `#problems` tool. +- Use the `get_errors` tool to check for any problems in the code - Make code changes only if you have high confidence they can solve the problem - When debugging, try to determine the root cause rather than addressing symptoms - Debug for as long as needed to identify the root cause and identify a fix @@ -106,11 +108,12 @@ Use the following format to create a todo list: - [ ] Step 3: Description of the third step ``` -Do not ever use HTML tags or any other formatting for the todo list, as it will not be rendered correctly. Always use the markdown format shown above. +Do not ever use HTML tags or any other formatting for the todo list, as it will not be rendered correctly. Always use the markdown format shown above. Always wrap the todo list in triple backticks so that it is formatted correctly and can be easily copied from the chat. -# Communication Guidelines -Always communicate clearly and concisely in a casual, friendly yet professional tone. +Always show the completed todo list to the user as the last item in your message, so that they can see that you have addressed all of the steps. +# Communication Guidelines +Always communicate clearly and concisely in a casual, friendly yet professional tone. "Let me fetch the URL you provided to gather more information." "Ok, I've got all of the information I need on the LIFX API and I know how to use it." @@ -119,3 +122,44 @@ Always communicate clearly and concisely in a casual, friendly yet professional "OK! Now let's run the tests to make sure everything is working correctly." "Whelp - I see we have some problems. Let's fix those up." + +- Respond with clear, direct answers. Use bullet points and code blocks for structure. - Avoid unnecessary explanations, repetition, and filler. +- Always write code directly to the correct files. +- Do not display code to the user unless they specifically ask for it. +- Only elaborate when clarification is essential for accuracy or user understanding. + +# Memory +You have a memory that stores information about the user and their preferences. This memory is used to provide a more personalized experience. You can access and update this memory as needed. The memory is stored in a file called `.github/instructions/memory.instruction.md`. If the file is empty, you'll need to create it. + +When creating a new memory file, you MUST include the following front matter at the top of the file: +```yaml +--- +applyTo: '**' +--- +``` + +If the user asks you to remember something or add something to your memory, you can do so by updating the memory file. + +# Reading Files and Folders + +**Always check if you have already read a file, folder, or workspace structure before reading it again.** + +- If you have already read the content and it has not changed, do NOT re-read it. +- Only re-read files or folders if: + - You suspect the content has changed since your last read. + - You have made edits to the file or folder. + - You encounter an error that suggests the context may be stale or incomplete. +- Use your internal memory and previous context to avoid redundant reads. +- This will save time, reduce unnecessary operations, and make your workflow more efficient. + +# Writing Prompts +If you are asked to write a prompt, you should always generate the prompt in markdown format. + +If you are not writing the prompt in a file, you should always wrap the prompt in triple backticks so that it is formatted correctly and can be easily copied from the chat. + +Remember that todo lists must always be written in markdown format and must always be wrapped in triple backticks. + +# Git +If the user tells you to stage and commit, you may do so. + +You are NEVER allowed to stage and commit files automatically. From b6d36c0da44e5f42e7c093eeb2e10e7608312138 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Thu, 24 Jul 2025 21:40:28 -0500 Subject: [PATCH 13/45] Restructures notification settings forms Refactors notification settings forms for users and integrations, improving UI and separating concerns. Introduces a generic `UserNotificationSettingsForm` for user-specific settings and an `IntegrationNotificationSettingsForm` for integration settings, enhancing code organization and reusability. Updates the UI to use a consistent card-based layout with descriptive text for each setting. --- ...gration-notification-settings-form.svelte} | 0 .../user-notification-settings-form.svelte | 126 ++++++++++++++++++ .../(app)/account/notifications/+page.svelte | 7 +- .../[projectId]/integrations/+page.svelte | 4 +- 4 files changed, 133 insertions(+), 4 deletions(-) rename src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/{notification-settings-form.svelte => integration-notification-settings-form.svelte} (100%) create mode 100644 src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/user-notification-settings-form.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/notification-settings-form.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/integration-notification-settings-form.svelte similarity index 100% rename from src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/notification-settings-form.svelte rename to src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/integration-notification-settings-form.svelte diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/user-notification-settings-form.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/user-notification-settings-form.svelte new file mode 100644 index 0000000000..93faa9d31a --- /dev/null +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/user-notification-settings-form.svelte @@ -0,0 +1,126 @@ + + +{#if $formData.send_daily_summary !== undefined} + + +
+ {#if children} + {@render children()} + {/if} +
+
+

Daily Project Summary

+ Receive a daily summary of your project activity. +
+ +
+
+
+

New Errors

+ Notify me on new errors. +
+ +
+
+
+

Critical Errors

+ Notify me on critical errors. +
+ +
+
+
+

Error Regressions

+ Notify me on error regressions. +
+ +
+
+
+

New Events

+ Notify me on new events. +
+ +
+
+
+

Critical Events

+ Notify me on critical events. +
+ +
+
+ +{:else} +
+ {#each { length: 6 } as name, index (`${name}-${index}`)} +
+ + +
+ {/each} +
+{/if} 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 22dfd6f350..2da54d4fa8 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 @@ -7,7 +7,7 @@ import { Skeleton } from '$comp/ui/skeleton'; import { Switch } from '$comp/ui/switch'; import { getProjectsQuery, getProjectUserNotificationSettings, postProjectUserNotificationSettings } from '$features/projects/api.svelte'; - import NotificationSettingsForm from '$features/projects/components/notification-settings-form.svelte'; + import UserNotificationSettingsForm from '$features/projects/components/user-notification-settings-form.svelte'; import { getMeQuery } from '$features/users/api.svelte'; import { patchUser } from '$features/users/api.svelte'; import { queryParamsState } from 'kit-query-params'; @@ -115,6 +115,7 @@ {#if selectedProject} +

Project Notification Settings

Choose how often you want to receive notifications for event occurrences in this project. @@ -133,6 +134,8 @@ - +
+ + {/if} diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/integrations/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/integrations/+page.svelte index 24ae79bdd5..b26995e8a0 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/integrations/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/project/[projectId]/integrations/+page.svelte @@ -17,7 +17,7 @@ putProjectIntegrationNotificationSettings } from '$features/projects/api.svelte'; import RemoveSlackDialog from '$features/projects/components/dialogs/remove-slack-dialog.svelte'; - import NotificationSettingsForm from '$features/projects/components/notification-settings-form.svelte'; + import IntegrationNotificationSettingsForm from '$features/projects/components/integration-notification-settings-form.svelte'; import { DEFAULT_LIMIT } from '$features/shared/api/api.svelte'; import { type GetProjectWebhooksParams, postWebhook } from '$features/webhooks/api.svelte'; import { getProjectWebhooksQuery } from '$features/webhooks/api.svelte'; @@ -192,7 +192,7 @@ > {#if hasSlackIntegration} - + {:else} From 320dcfd5b449f87dc02af11ba457e3edef8b4da3 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Thu, 24 Jul 2025 21:54:33 -0500 Subject: [PATCH 14/45] Improves user notification settings UI Enhances the user interface for the user notification settings form. Replaces the heading component to ensure consistent styling. Improves the loading state of the form by using a more visually appealing skeleton loader, providing a better user experience while data is being fetched. --- .../user-notification-settings-form.svelte | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/user-notification-settings-form.svelte b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/user-notification-settings-form.svelte index 93faa9d31a..e6d1ac8b37 100644 --- a/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/user-notification-settings-form.svelte +++ b/src/Exceptionless.Web/ClientApp/src/lib/features/projects/components/user-notification-settings-form.svelte @@ -2,7 +2,7 @@ import type { Snippet } from "svelte"; import ErrorMessage from '$comp/error-message.svelte'; - import { H3, H4, Muted } from '$comp/typography'; + import { H4, Muted } from '$comp/typography'; import { Skeleton } from '$comp/ui/skeleton'; import { Switch } from '$comp/ui/switch'; import { NotificationSettings } from '$features/projects/models'; @@ -115,11 +115,14 @@ {:else} -
+
{#each { length: 6 } as name, index (`${name}-${index}`)} -
- - +
+
+ + +
+
{/each}
From b808051b120905a63ee0116926cbd4dc5887e9f0 Mon Sep 17 00:00:00 2001 From: Blake Niemyjski Date: Sat, 26 Jul 2025 20:49:56 -0500 Subject: [PATCH 15/45] Improves appearance settings layout Enhances the appearance settings page layout by aligning the theme options (Light, Dark, System) to the center using flexbox. This provides a better user experience by visually centering the theme previews and labels. --- .../src/routes/(app)/account/appearance/+page.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/appearance/+page.svelte b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/appearance/+page.svelte index 42c8f40f41..33e7b0cc04 100644 --- a/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/appearance/+page.svelte +++ b/src/Exceptionless.Web/ClientApp/src/routes/(app)/account/appearance/+page.svelte @@ -26,17 +26,17 @@ onValueChange={onUserThemePreferenceChange} value={userPrefersMode.current} > -