Skip to content

Commit 0866827

Browse files
royendoclaude
andauthored
fix: Workspace UI errors not shown (#9145)
* fix missing error modal and consolidate to one function * prettier * consolidate the waterfall error from mulitple workspaces * Fix TypeScript slot prop typing in WorkspaceError Add \$Slots interface so `let:rootCauseReconcileError` in CanvasWorkspace and ExploreWorkspace passes TypeScript validation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix TypeScript slot prop typing for WorkspaceError - Add `interface \$\$Slots` to declare the `rootCauseReconcileError` slot prop type so svelte-check accepts `let:rootCauseReconcileError` in consumers - Add `varsIgnorePattern: "^\$\$"` to ESLint no-unused-vars so Svelte's reserved `\$\$`-prefixed type declarations (Slots, Props, Events) are not flagged as unused Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix TypeScript errors for rootCauseReconcileError in Canvas and Explore Remove the slot prop pattern from WorkspaceError (which required an unidiomatic \$\$Slots declaration). Canvas and Explore now compute rootCauseReconcileError in their own script for use in their content area; WorkspaceError still owns the single error bar. TanStack Query deduplicates the ListResources request so there is no extra network cost. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * prettier * consolidate --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 51daf49 commit 0866827

7 files changed

Lines changed: 58 additions & 50 deletions

File tree

web-common/src/features/metrics-views/editor/MetricsEditor.svelte

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
export let filePath: string;
2121
export let metricsViewName: string;
2222
export let parseError: V1ParseError | undefined = undefined;
23-
export let rootCauseReconcileError: string | undefined = undefined;
2423
export let fileArtifact: FileArtifact;
2524
export let autoSave: boolean;
2625
@@ -40,9 +39,7 @@
4039
$: if (editor) setLineStatuses(lineStatus ? [lineStatus] : [], editor);
4140
</script>
4241

43-
<WorkspaceEditorContainer
44-
error={parseError?.message ?? rootCauseReconcileError}
45-
>
42+
<WorkspaceEditorContainer>
4643
<Editor
4744
bind:autoSave
4845
bind:editor

web-common/src/features/workspaces/CanvasWorkspace.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import { goto } from "$app/navigation";
33
import CanvasEditor from "@rilldata/web-common/features/canvas/CanvasEditor.svelte";
44
import VisualCanvasEditing from "@rilldata/web-common/features/canvas/inspector/VisualCanvasEditing.svelte";
5-
import { getNameFromFile } from "@rilldata/web-common/features/entity-management/entity-mappers";
65
import { createRootCauseErrorQuery } from "@rilldata/web-common/features/entity-management/error-utils";
6+
import { getNameFromFile } from "@rilldata/web-common/features/entity-management/entity-mappers";
77
import type { FileArtifact } from "@rilldata/web-common/features/entity-management/file-artifact";
88
import {
99
resourceIsLoading,
@@ -57,7 +57,6 @@
5757
$: parseErrorQuery = fileArtifact.getParseError(queryClient);
5858
$: parseError = $parseErrorQuery;
5959
60-
// Reconcile error resolved to root cause for the banner
6160
$: reconcileError = data?.meta?.reconcileError;
6261
$: rootCauseQuery = createRootCauseErrorQuery(
6362
runtimeClient,
@@ -117,8 +116,9 @@
117116

118117
<WorkspaceEditorContainer
119118
slot="body"
120-
error={parseError?.message ?? rootCauseReconcileError}
121-
showError={!!$remoteContent && selectedView === "code"}
119+
resource={data}
120+
{parseError}
121+
remoteContent={$remoteContent}
122122
>
123123
{#if selectedView === "code"}
124124
<CanvasEditor

web-common/src/features/workspaces/ExploreWorkspace.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<script lang="ts">
22
import { goto } from "$app/navigation";
33
import ErrorPage from "@rilldata/web-common/components/ErrorPage.svelte";
4-
import { getNameFromFile } from "@rilldata/web-common/features/entity-management/entity-mappers";
54
import { createRootCauseErrorQuery } from "@rilldata/web-common/features/entity-management/error-utils";
5+
import { getNameFromFile } from "@rilldata/web-common/features/entity-management/entity-mappers";
66
import type { FileArtifact } from "@rilldata/web-common/features/entity-management/file-artifact";
77
import {
88
resourceIsLoading,
@@ -63,7 +63,6 @@
6363
$: parseErrorQuery = fileArtifact.getParseError(queryClient);
6464
$: parseError = $parseErrorQuery;
6565
66-
// Reconcile error resolved to root cause for the banner
6766
$: reconcileError = (exploreResource ?? metricsViewResource)?.meta
6867
?.reconcileError;
6968
$: rootCauseQuery = createRootCauseErrorQuery(
@@ -119,8 +118,9 @@
119118

120119
<WorkspaceEditorContainer
121120
slot="body"
122-
error={parseError?.message ?? rootCauseReconcileError}
123-
showError={!!$remoteContent && selectedView === "code"}
121+
resource={exploreResource ?? metricsViewResource}
122+
{parseError}
123+
remoteContent={$remoteContent}
124124
>
125125
{#if selectedView === "code"}
126126
<ExploreEditor

web-common/src/features/workspaces/MetricsWorkspace.svelte

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<script lang="ts">
22
import { goto } from "$app/navigation";
33
import { getNameFromFile } from "@rilldata/web-common/features/entity-management/entity-mappers";
4-
import { createRootCauseErrorQuery } from "@rilldata/web-common/features/entity-management/error-utils";
54
import type { FileArtifact } from "@rilldata/web-common/features/entity-management/file-artifact";
65
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors";
76
import { handleEntityRename } from "@rilldata/web-common/features/entity-management/ui-actions";
87
import MetricsInspector from "@rilldata/web-common/features/metrics-views/MetricsInspector.svelte";
98
import MetricsEditor from "@rilldata/web-common/features/metrics-views/editor/MetricsEditor.svelte";
109
import WorkspaceContainer from "@rilldata/web-common/layout/workspace/WorkspaceContainer.svelte";
10+
import WorkspaceEditorContainer from "@rilldata/web-common/layout/workspace/WorkspaceEditorContainer.svelte";
1111
import WorkspaceHeader from "@rilldata/web-common/layout/workspace/WorkspaceHeader.svelte";
1212
import { workspaces } from "@rilldata/web-common/layout/workspace/workspace-stores";
1313
import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient";
@@ -65,16 +65,7 @@
6565
$: parseErrorQuery = fileArtifact.getParseError(queryClient);
6666
$: parseError = $parseErrorQuery;
6767
68-
// Reconcile error resolved to root cause for the banner
6968
$: reconcileError = resource?.meta?.reconcileError;
70-
$: rootCauseQuery = createRootCauseErrorQuery(
71-
runtimeClient,
72-
resource,
73-
reconcileError,
74-
);
75-
$: rootCauseReconcileError = reconcileError
76-
? ($rootCauseQuery?.data ?? reconcileError)
77-
: undefined;
7869
7970
async function onChangeCallback(newTitle: string) {
8071
const newRoute = await handleEntityRename(
@@ -113,11 +104,15 @@
113104
</div>
114105
</WorkspaceHeader>
115106

116-
<svelte:fragment slot="body">
107+
<WorkspaceEditorContainer
108+
slot="body"
109+
{resource}
110+
{parseError}
111+
remoteContent={$remoteContent}
112+
>
117113
{#if $selectedView === "code"}
118114
<MetricsEditor
119115
bind:autoSave={$autoSave}
120-
{rootCauseReconcileError}
121116
{fileArtifact}
122117
{filePath}
123118
{parseError}
@@ -126,15 +121,14 @@
126121
{:else}
127122
{#key fileArtifact}
128123
<VisualMetrics
129-
{parseError}
130124
{fileArtifact}
131125
switchView={() => {
132126
$selectedView = "code";
133127
}}
134128
/>
135129
{/key}
136130
{/if}
137-
</svelte:fragment>
131+
</WorkspaceEditorContainer>
138132

139133
<MetricsInspector
140134
{filePath}

web-common/src/features/workspaces/VisualMetrics.svelte

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
<script lang="ts">
2-
import { slide } from "svelte/transition";
32
import Button from "@rilldata/web-common/components/button/Button.svelte";
43
import * as DropdownMenu from "@rilldata/web-common/components/dropdown-menu/";
5-
import type { V1ParseError } from "@rilldata/web-common/runtime-client";
64
import Input from "@rilldata/web-common/components/forms/Input.svelte";
75
import InputLabel from "@rilldata/web-common/components/forms/InputLabel.svelte";
8-
import CancelCircle from "@rilldata/web-common/components/icons/CancelCircle.svelte";
96
import CaretDownIcon from "@rilldata/web-common/components/icons/CaretDownIcon.svelte";
107
import Close from "@rilldata/web-common/components/icons/Close.svelte";
118
import Search from "@rilldata/web-common/components/icons/Search.svelte";
129
import Trash from "@rilldata/web-common/components/icons/Trash.svelte";
13-
import { LIST_SLIDE_DURATION } from "@rilldata/web-common/layout/config";
1410
import { clamp } from "@rilldata/web-common/lib/clamp";
1511
import { TIMESTAMPS } from "@rilldata/web-common/lib/duckdb-data-types";
1612
import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus";
@@ -73,7 +69,6 @@
7369
);
7470
7571
export let fileArtifact: FileArtifact;
76-
export let parseError: V1ParseError | undefined = undefined;
7772
export let switchView: () => void;
7873
export let unsavedChanges = false;
7974
@@ -794,17 +789,6 @@
794789
</div>
795790
{/each}
796791
</div>
797-
798-
{#if parseError}
799-
<div
800-
role="status"
801-
transition:slide={{ duration: LIST_SLIDE_DURATION }}
802-
class="flex items-center gap-x-2 border border-destructive bg-destructive/15 dark:bg-destructive/30 text-fg-primary border-l-4 px-2 py-5 max-h-40 overflow-auto"
803-
>
804-
<CancelCircle className="text-destructive" />
805-
{parseError.message}
806-
</div>
807-
{/if}
808792
</div>
809793

810794
{#if $editingItemData !== null}

web-common/src/layout/workspace/WorkspaceEditorContainer.svelte

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,58 @@
22
import { slide } from "svelte/transition";
33
import CancelCircle from "@rilldata/web-common/components/icons/CancelCircle.svelte";
44
import { LIST_SLIDE_DURATION } from "@rilldata/web-common/layout/config";
5+
import { createRootCauseErrorQuery } from "@rilldata/web-common/features/entity-management/error-utils";
6+
import type {
7+
V1ParseError,
8+
V1Resource,
9+
} from "@rilldata/web-common/runtime-client";
10+
import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2";
511
12+
// Direct error string (existing API, still supported)
613
export let error: string | undefined = undefined;
714
export let showError = true;
15+
16+
// Resource-based error derivation (replaces WorkspaceError wrapper)
17+
export let resource: V1Resource | undefined = undefined;
18+
export let parseError: V1ParseError | undefined = undefined;
19+
export let remoteContent: string | null | undefined = undefined;
20+
21+
const runtimeClient = useRuntimeClient();
22+
23+
$: reconcileError = resource?.meta?.reconcileError;
24+
$: rootCauseQuery = createRootCauseErrorQuery(
25+
runtimeClient,
26+
resource,
27+
reconcileError,
28+
);
29+
$: rootCauseReconcileError = reconcileError
30+
? ($rootCauseQuery?.data ?? reconcileError)
31+
: undefined;
32+
33+
$: derivedError = parseError?.message ?? rootCauseReconcileError;
34+
$: effectiveError = error ?? derivedError;
35+
$: effectiveShowError =
36+
remoteContent !== undefined ? !!remoteContent : showError;
837
</script>
938

1039
<div
1140
class="flex flex-col size-full gap-y-1 bg-surface-subtle rounded-[2px] border overflow-hidden"
1241
>
1342
<div
1443
class="size-full relative overflow-hidden flex flex-col items-center justify-center"
15-
class:!border-red-500={error}
44+
class:!border-red-500={effectiveError}
1645
>
1746
<slot />
1847
</div>
1948

20-
{#if error && showError}
49+
{#if effectiveError && effectiveShowError}
2150
<div
2251
role="status"
2352
transition:slide={{ duration: LIST_SLIDE_DURATION }}
2453
class="border border-destructive bg-destructive/15 dark:bg-destructive/30 text-fg-primary border-l-4 px-2 py-5 max-h-72 overflow-auto"
2554
>
2655
<div class="flex gap-x-2 items-center">
27-
<CancelCircle className="text-destructive" />{error}
56+
<CancelCircle className="text-destructive" />{effectiveError}
2857
</div>
2958
</div>
3059
{/if}

web-local/src/routes/(application)/(workspace)/files/[...file]/+page.svelte

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
inferredResourceKind,
4444
path,
4545
getResource,
46-
getAllErrors,
46+
remoteContent,
4747
} = fileArtifact);
4848
4949
$: resourceKind = <ResourceKind | undefined>$resourceName?.kind;
@@ -59,9 +59,8 @@
5959
? [customYAMLwithJSONandSQL]
6060
: getExtensionsForFile(path);
6161
62-
// Errors for the editor banner (parse + reconcile)
63-
$: allErrorsStore = getAllErrors(queryClient);
64-
$: allErrors = $allErrorsStore;
62+
$: parseErrorStore = fileArtifact.getParseError(queryClient);
63+
$: parseError = $parseErrorStore;
6564
6665
onMount(() => {
6766
expandDirectory(path);
@@ -100,7 +99,12 @@
10099
filePath={path}
101100
hasUnsavedChanges={$hasUnsavedChanges}
102101
/>
103-
<WorkspaceEditorContainer slot="body" error={allErrors[0]?.message}>
102+
<WorkspaceEditorContainer
103+
slot="body"
104+
{resource}
105+
{parseError}
106+
remoteContent={$remoteContent}
107+
>
104108
<Editor
105109
{fileArtifact}
106110
{extensions}

0 commit comments

Comments
 (0)