From c15bc8a7bfb3bef2634e6093088967137cd06239 Mon Sep 17 00:00:00 2001 From: Faton Ramadani Date: Thu, 23 Mar 2023 20:54:02 +0100 Subject: [PATCH] fix(frontend): Fix AppTable error display + clear errors when removing a component + properly detect that latest component run had an error (#1322) --- .../components/display/table/AppTable.svelte | 14 ++--- .../helpers/RunnableComponent.svelte | 13 +++++ .../apps/editor/AppEditorHeader.svelte | 4 -- .../apps/editor/ComponentHeader.svelte | 13 ++--- .../lib/components/apps/editor/appUtils.ts | 53 +++++++++++++++++++ .../settingsPanel/ComponentPanel.svelte | 21 ++++++-- .../editor/settingsPanel/TableActions.svelte | 13 ++++- 7 files changed, 109 insertions(+), 22 deletions(-) diff --git a/frontend/src/lib/components/apps/components/display/table/AppTable.svelte b/frontend/src/lib/components/apps/components/display/table/AppTable.svelte index 93c8745930..bd0a9f0073 100644 --- a/frontend/src/lib/components/apps/components/display/table/AppTable.svelte +++ b/frontend/src/lib/components/apps/components/display/table/AppTable.svelte @@ -355,11 +355,13 @@ /> {:else if result != undefined} - - The result should be an array of objects. Received: -
-				{JSON.stringify(result)}
-			
-
+
+ + The result should be an array of objects. Received: +
+				{JSON.stringify(result, null, 4)}
+				
+
+
{/if} diff --git a/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte b/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte index 1a70f531f5..0551487774 100644 --- a/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte +++ b/frontend/src/lib/components/apps/components/helpers/RunnableComponent.svelte @@ -244,6 +244,8 @@ } async function setResult(res: any) { + const hasRes = res !== undefined && res !== null + if (transformer) { $worldStore.newOutput(id, 'raw', res) res = await eval_like( @@ -255,7 +257,18 @@ $componentControl, $worldStore ) + + if (hasRes && res === undefined) { + res = { + error: { + name: 'TransformerError', + message: 'An error occured in the transformer', + stack: 'Transformer returned undefined' + } + } + } } + outputs.result?.set(res) result = res diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte index 56b4826f5b..c0bfe301c8 100644 --- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte @@ -18,7 +18,6 @@ import DisplayResult from '$lib/components/DisplayResult.svelte' import Dropdown from '$lib/components/Dropdown.svelte' import FlowProgressBar from '$lib/components/flows/FlowProgressBar.svelte' - import { idMutex } from '$lib/components/flows/flowStateUtils' import FlowStatusViewer from '$lib/components/FlowStatusViewer.svelte' import JobArgs from '$lib/components/JobArgs.svelte' import LogViewer from '$lib/components/LogViewer.svelte' @@ -43,12 +42,9 @@ Eye, Laptop2, Loader2, - MoreVertical, Pencil, - Redo, SlidersHorizontal, Smartphone, - Undo, X } from 'lucide-svelte' import { getContext } from 'svelte' diff --git a/frontend/src/lib/components/apps/editor/ComponentHeader.svelte b/frontend/src/lib/components/apps/editor/ComponentHeader.svelte index 6dec1d4a1d..57b42a26d8 100644 --- a/frontend/src/lib/components/apps/editor/ComponentHeader.svelte +++ b/frontend/src/lib/components/apps/editor/ComponentHeader.svelte @@ -7,6 +7,7 @@ import { Alert, Button } from '$lib/components/common' import type { AppComponent } from './component' import { twMerge } from 'tailwind-merge' + import { getErrorFromLatestResult } from './appUtils' export let component: AppComponent export let selected: boolean @@ -15,9 +16,9 @@ const dispatch = createEventDispatcher() - const { errorByComponent, openDebugRun } = getContext('AppViewerContext') + const { errorByComponent, openDebugRun, jobs } = getContext('AppViewerContext') - $: error = Object.values($errorByComponent).find((e) => e.componentId === component.id) + $: error = getErrorFromLatestResult(component.id, $errorByComponent, $jobs) function openDebugRuns() { if ($openDebugRun) { @@ -84,7 +85,7 @@ {/if} {#if error} - {@const json = JSON.parse(JSON.stringify(error.error))} + {@const json = JSON.parse(JSON.stringify(error))}
-
{json?.stack ?? ''}
-									
+
+									{json?.stack ?? ''}	
+								
diff --git a/frontend/src/lib/components/apps/editor/appUtils.ts b/frontend/src/lib/components/apps/editor/appUtils.ts index a6d72f9ef8..cc0b33d6c2 100644 --- a/frontend/src/lib/components/apps/editor/appUtils.ts +++ b/frontend/src/lib/components/apps/editor/appUtils.ts @@ -568,3 +568,56 @@ export function recursivelyFilterKeyInJSON( }) return filteredJSON } + +export function clearErrorByComponentId( + id: string, + errorByComponent: Record< + string, + { + error: string + componentId: string + } + > +) { + return Object.entries(errorByComponent).reduce((acc, [key, value]) => { + if (value.componentId !== id) { + acc[key] = value + } + return acc + }, {}) +} + +export function clearJobsByComponentId( + id: string, + jobs: { + job: string + component: string + }[] +) { + return jobs.filter((job) => job.component !== id) +} + +// Returns the error message for the latest job for a component if an error occurred, otherwise undefined +export function getErrorFromLatestResult( + id: string, + errorByComponent: Record< + string, // job id + { + error: string + componentId: string + } + >, + jobs: { + job: string + component: string + }[] +) { + // find last jobId for component id + const lastJob = jobs.find((job) => job.component === id) + + if (lastJob?.job && errorByComponent[lastJob.job]) { + return errorByComponent[lastJob.job].error + } else { + return undefined + } +} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte index 1b050626f7..cf8c46ee55 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte @@ -17,10 +17,10 @@ import AlignmentEditor from './AlignmentEditor.svelte' import RunnableInputEditor from './inputEditor/RunnableInputEditor.svelte' import TemplateEditor from '$lib/components/TemplateEditor.svelte' - import { ccomponents, components, type AppComponent } from '../component' + import { ccomponents, type AppComponent } from '../component' import CssProperty from '../componentsPanel/CssProperty.svelte' import GridTab from './GridTab.svelte' - import { deleteGridItem } from '../appUtils' + import { clearErrorByComponentId, clearJobsByComponentId, deleteGridItem } from '../appUtils' import GridPane from './GridPane.svelte' import { slide } from 'svelte/transition' import { push } from '$lib/history' @@ -35,8 +35,17 @@ let editor: TemplateEditor | undefined = undefined - const { app, runnableComponents, selectedComponent, worldStore, focusedGrid, stateId, state } = - getContext('AppViewerContext') + const { + app, + runnableComponents, + selectedComponent, + worldStore, + focusedGrid, + stateId, + state, + errorByComponent, + jobs + } = getContext('AppViewerContext') const { history, ontextfocus } = getContext('AppEditorContext') @@ -44,6 +53,10 @@ function removeGridElement() { push(history, $app) + + $errorByComponent = clearErrorByComponentId(component.id, $errorByComponent) + $jobs = clearJobsByComponentId(component.id, $jobs) + $selectedComponent = undefined $focusedGrid = undefined if (componentSettings?.item && !noGrid) { diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/TableActions.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/TableActions.svelte index bdcd8d6b5e..2ab3621006 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/TableActions.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/TableActions.svelte @@ -7,7 +7,11 @@ import { getContext } from 'svelte' import { Icon } from 'svelte-awesome' import type { AppViewerContext, BaseAppComponent } from '../../types' - import { appComponentFromType } from '../appUtils' + import { + appComponentFromType, + clearErrorByComponentId, + clearJobsByComponentId + } from '../appUtils' import type { ButtonComponent } from '../component' import PanelSection from './common/PanelSection.svelte' import TableActionLabel from './TableActionLabel.svelte' @@ -15,7 +19,8 @@ export let components: (BaseAppComponent & ButtonComponent)[] export let id: string - const { selectedComponent, app } = getContext('AppViewerContext') + const { selectedComponent, app, errorByComponent, jobs } = + getContext('AppViewerContext') function addComponent() { const actionId = getNextId(components.map((x) => x.id.split('_')[1])) @@ -30,6 +35,10 @@ function deleteComponent(cid: string) { components = components.filter((x) => x.id !== cid) + + $errorByComponent = clearErrorByComponentId(cid, $errorByComponent) + $jobs = clearJobsByComponentId(cid, $jobs) + $selectedComponent = id $app = $app }