Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Exceptionless.Web/ClientApp/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ node_modules
.vercel
/.svelte-kit
/build
/storybook-static

# OS
.DS_Store
Expand Down
30 changes: 30 additions & 0 deletions src/Exceptionless.Web/ClientApp/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": {
"correctness": "error"
},
"ignorePatterns": [
".agents/**",
".svelte-kit/**",
"build/**",
"dist/**",
"src/lib/features/shared/components/ui/**",
"src/lib/generated/**",
"storybook-static/**"
],
"overrides": [
{
"files": ["**/*.svelte"],
"rules": {
"eslint/no-unassigned-vars": "off",
"no-unused-vars": "off"
}
}
],
"plugins": ["eslint", "typescript", "unicorn", "oxc", "import"],
"rules": {
"unicorn/no-empty-file": "off",
"unicorn/no-useless-fallback-in-spread": "off",
"unicorn/prefer-string-starts-ends-with": "off"
}
}
5 changes: 4 additions & 1 deletion src/Exceptionless.Web/ClientApp/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { includeIgnoreFile } from '@eslint/compat';
import js from '@eslint/js';
import pluginQuery from '@tanstack/eslint-plugin-query';
import prettier from 'eslint-config-prettier';
import oxlint from 'eslint-plugin-oxlint';
import perfectionist from 'eslint-plugin-perfectionist';
import storybook from 'eslint-plugin-storybook';
import svelte from 'eslint-plugin-svelte';
Expand Down Expand Up @@ -59,5 +60,7 @@ export default ts.config(
'perfectionist/sort-svelte-attributes': 'off'
}
},
storybook.configs['flat/recommended']
storybook.configs['flat/recommended'],
// Keep ESLint for framework and plugin coverage while Oxlint owns overlapping rules.
...oxlint.buildFromOxlintConfigFile('./.oxlintrc.json')
);
2,789 changes: 1,683 additions & 1,106 deletions src/Exceptionless.Web/ClientApp/package-lock.json

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions src/Exceptionless.Web/ClientApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "npm run lint:prettier && npm run lint:eslint",
"lint": "npm run lint:prettier && npm run lint:oxlint && npm run lint:eslint",
"lint:eslint": "eslint .",
"lint:oxlint": "svelte-kit sync && oxlint --deny-warnings",
"lint:prettier": "prettier --check .",
"format": "npm run format:prettier && npm run format:eslint",
"format:eslint": "eslint . --fix",
Expand Down Expand Up @@ -44,7 +45,7 @@
"@storybook/sveltekit": "^10.4.6",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.69.2",
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@sveltejs/vite-plugin-svelte": "^7.2.0",
"@tailwindcss/vite": "^4.3.2",
"@tanstack/eslint-plugin-query": "^5.101.2",
"@testing-library/jest-dom": "^6.9.1",
Expand All @@ -55,11 +56,13 @@
"cross-env": "^10.1.0",
"eslint": "^10.6.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-oxlint": "~1.73.0",
"eslint-plugin-perfectionist": "^5.10.0",
"eslint-plugin-storybook": "^10.4.6",
"eslint-plugin-svelte": "^3.20.0",
"globals": "^17.7.0",
"jsdom": "^29.1.1",
"oxlint": "~1.73.0",
"prettier": "^3.9.4",
"prettier-plugin-svelte": "^4.1.1",
"prettier-plugin-tailwindcss": "^0.8.0",
Expand All @@ -70,7 +73,7 @@
"tslib": "^2.8.1",
"typescript": "^6.0.3",
"typescript-eslint": "^8.63.0",
"vite": "^7.3.5",
"vite": "^8.1.5",
"vitest": "4.1.10",
"vitest-websocket-mock": "^0.5.0",
"zod": "^4.4.3"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { describe, expect, it, vi } from 'vitest';
vi.mock('$features/events/components/filters', () => ({ StringTrigger: null }));

import type { PersistentEvent } from '../../models';

import Environment from './environment.svelte';

describe('Environment', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<Button
aria-hidden={showFirst ? undefined : true}
aria-label="Go to first page"
class={showFirst ? undefined : 'invisible pointer-events-none'}
class={showFirst ? undefined : 'pointer-events-none invisible'}
disabled={!showFirst}
onclick={goToFirstPage}
title="First page"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@
<button
{...props}
type="button"
class="inline-flex max-w-full items-center gap-1 truncate rounded-sm text-left text-sm font-medium underline decoration-dotted underline-offset-4 hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
class="hover:text-primary focus-visible:ring-ring inline-flex max-w-full items-center gap-1 truncate rounded-sm text-left text-sm font-medium underline decoration-dotted underline-offset-4 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
>
<span class="truncate">{formatResourceSummary()}</span>
<span class="shrink-0 text-muted-foreground">· {scopeCount} {scopeCount === 1 ? 'scope' : 'scopes'}</span>
<span class="text-muted-foreground shrink-0">· {scopeCount} {scopeCount === 1 ? 'scope' : 'scopes'}</span>
</button>
{/snippet}
</Tooltip.Trigger>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<div class="min-w-0 space-y-1 whitespace-normal">
<div class="truncate font-medium" title={grant.application_name}>{grant.application_name}</div>
<div class="text-xs text-muted-foreground">Updated <TimeAgo value={grant.updated_utc} /></div>
<div class="text-muted-foreground text-xs">Updated <TimeAgo value={grant.updated_utc} /></div>
{#if grant.is_application_disabled}
<Badge variant="outline">Disabled</Badge>
{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<button
{...props}
type="button"
class="flex max-w-full items-center gap-1 rounded-sm text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
class="focus-visible:ring-ring flex max-w-full items-center gap-1 rounded-sm text-left focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
>
<Badge class="max-w-40 truncate" variant="outline">{organizations[0]?.name}</Badge>
{#if organizations.length > 1}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@
</div>

{#if eventsQuery.isPending}
<div class="flex items-center gap-2 text-muted-foreground">
<div class="text-muted-foreground flex items-center gap-2">
<Spinner class="size-4" />
<span>Loading events...</span>
</div>
{:else if eventsQuery.error}
<div class="rounded-md border border-destructive/40 bg-destructive/5 p-4 text-sm text-destructive">Unable to load events for this reference.</div>
<div class="border-destructive/40 bg-destructive/5 text-destructive rounded-md border p-4 text-sm">Unable to load events for this reference.</div>
{:else if (eventsQuery.data?.length ?? 0) === 0}
<div class="space-y-3">
<Muted>No events were found for this reference.</Muted>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@
{:else}
{#each sourceMapsQuery.data as sourceMap (sourceMap.id)}
<Table.Row>
<Table.Cell class="max-w-xl break-all font-mono text-xs">{sourceMap.generated_file_url}</Table.Cell>
<Table.Cell class="max-w-xl font-mono text-xs break-all">{sourceMap.generated_file_url}</Table.Cell>
<Table.Cell>
<Badge variant={sourceMap.is_auto_downloaded ? 'secondary' : 'outline'}>
{sourceMap.is_auto_downloaded ? 'Automatic' : 'Uploaded'}
Expand Down Expand Up @@ -251,7 +251,7 @@
<AlertDialog.Header>
<AlertDialog.Title>Delete Source Map</AlertDialog.Title>
<AlertDialog.Description>
Delete the source map for <span class="break-all font-mono text-xs">{sourceMapToDelete?.generated_file_url}</span>? Future events will use
Delete the source map for <span class="font-mono text-xs break-all">{sourceMapToDelete?.generated_file_url}</span>? Future events will use
automatic discovery or retain their generated stack frames.
</AlertDialog.Description>
</AlertDialog.Header>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
{:else if eventsAllTimeChartData.length === 0}
<p class="text-muted-foreground py-8 text-center text-sm">No event history available.</p>
{:else}
<Chart.Container config={eventsAllTimeChartConfig} class="h-48 w-full overflow-visible pl-16 pr-3">
<Chart.Container config={eventsAllTimeChartConfig} class="h-48 w-full overflow-visible pr-3 pl-16">
<AreaChart
data={eventsAllTimeChartData}
x="date"
Expand Down Expand Up @@ -235,7 +235,7 @@
{:else if organizationGrowthChartData.length === 0}
<p class="text-muted-foreground py-8 text-center text-sm">No growth data available.</p>
{:else}
<Chart.Container config={organizationGrowthChartConfig} class="h-48 w-full overflow-visible pl-16 pr-3">
<Chart.Container config={organizationGrowthChartConfig} class="h-48 w-full overflow-visible pr-3 pl-16">
<AreaChart
data={organizationGrowthChartData}
x="month"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
<CopyToClipboardButton value={predefinedJson} variant="outline" />
</div>

<Textarea bind:value={predefinedJson} class="font-mono text-xs max-h-[60vh] min-h-96 overflow-auto" rows={24} spellcheck={false} />
<Textarea bind:value={predefinedJson} class="max-h-[60vh] min-h-96 overflow-auto font-mono text-xs" rows={24} spellcheck={false} />

<div class="flex flex-col justify-end gap-2 sm:flex-row">
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
<P class="px-3">OR</P>
<hr class="w-full" />
</div>
<div class="auto-cols-2 grid grid-flow-col grid-rows-2 gap-4">
<div class="grid auto-cols-2 grid-flow-col grid-rows-2 gap-4">
{#if microsoftClientId}
<Button aria-label="Login with Microsoft" tabindex={4} onclick={() => liveLogin(redirectUrl)}>
<MicrosoftIcon class="size-4" /> Microsoft
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@
<p class="text-destructive">Unable to load account details.</p>
{:else}
<p class="truncate font-medium" title={accountDisplayName}>{accountDisplayName}</p>
<p class="truncate font-mono text-xs text-muted-foreground" title={meQuery.data?.email_address}>{meQuery.data?.email_address}</p>
<p class="text-muted-foreground truncate font-mono text-xs" title={meQuery.data?.email_address}>{meQuery.data?.email_address}</p>
{/if}
</div>
<div class="space-y-2">
Expand All @@ -349,7 +349,7 @@
{:else if organizations.length > 0}
<div class="max-h-32 space-y-1 overflow-y-auto rounded-md border p-1">
{#each organizations as organization (organization.id)}
<label class="flex min-h-8 items-center gap-2 rounded-sm px-2 text-sm hover:bg-muted/50">
<label class="hover:bg-muted/50 flex min-h-8 items-center gap-2 rounded-sm px-2 text-sm">
<Checkbox
checked={selectedOrganizationIds.has(organization.id)}
onCheckedChange={(checked) => toggleOrganization(organization.id, checked)}
Expand All @@ -372,7 +372,7 @@
{:else}
<p class="truncate font-medium" title={applicationDisplayName}>{applicationDisplayName}</p>
{#if consentDetails?.client_name && applicationClientId !== applicationDisplayName}
<p class="truncate font-mono text-xs text-muted-foreground" title={applicationClientId}>{applicationClientId}</p>
<p class="text-muted-foreground truncate font-mono text-xs" title={applicationClientId}>{applicationClientId}</p>
{/if}
{/if}
</div>
Expand All @@ -391,22 +391,22 @@
{#if requestedScopes.length > 0}
<div class="grid gap-2 sm:grid-cols-2">
{#each requestedRequiredScopes as scope (scope)}
<div class="flex min-h-12 items-center gap-2 rounded-sm border bg-muted/30 px-2 py-1.5 text-sm">
<div class="bg-muted/30 flex min-h-12 items-center gap-2 rounded-sm border px-2 py-1.5 text-sm">
<span class="min-w-0 flex-1">
<span class="flex min-w-0 flex-wrap items-center gap-1.5">
<span class="truncate font-medium">{formatScope(scope)}</span>
<Badge variant="outline">Required</Badge>
</span>
<span class="block truncate font-mono text-xs text-muted-foreground">{scope}</span>
<span class="text-muted-foreground block truncate font-mono text-xs">{scope}</span>
</span>
</div>
{/each}
{#each requestedOptionalScopes as scope (scope)}
<label class="flex min-h-12 items-center gap-2 rounded-sm border px-2 py-1.5 text-sm hover:bg-muted/50">
<label class="hover:bg-muted/50 flex min-h-12 items-center gap-2 rounded-sm border px-2 py-1.5 text-sm">
<Checkbox checked={selectedScopes.has(scope)} onCheckedChange={(checked) => toggleScope(scope, checked)} />
<span class="min-w-0 flex-1">
<span class="block truncate font-medium">{formatScope(scope)}</span>
<span class="block truncate font-mono text-xs text-muted-foreground">{scope}</span>
<span class="text-muted-foreground block truncate font-mono text-xs">{scope}</span>
</span>
</label>
{/each}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
<div>
{#if enableOAuthLogin}
<P class="text-center">Sign up with</P>
<div class="auto-cols-2 grid grid-flow-col grid-rows-2 gap-4">
<div class="grid auto-cols-2 grid-flow-col grid-rows-2 gap-4">
{#if microsoftClientId}
<Button aria-label="Sign up with Microsoft" onclick={() => liveLogin(redirectUrl)}>
<MicrosoftIcon class="size-4" /> Microsoft
Expand Down
Loading
Loading