feat(frontend): App debug mode (#3252)

* feat(frontend): App debug mode

* feat(frontend): App debug mode

* feat(frontend): App debug mode

* feat(frontend): App debug mode

* feat(frontend): App debug mode done

* feat(frontend): App debug mode done
This commit is contained in:
Faton Ramadani
2024-02-20 23:50:29 +01:00
committed by GitHub
parent 65e09a705f
commit 247396d04d
4 changed files with 192 additions and 4 deletions
@@ -23,7 +23,7 @@
import TabContent from '$lib/components/common/tabs/TabContent.svelte'
import Tabs from '$lib/components/common/tabs/Tabs.svelte'
import { userStore, workspaceStore } from '$lib/stores'
import { classNames, encodeState } from '$lib/utils'
import { classNames, encodeState, sendUserToast } from '$lib/utils'
import AppPreview from './AppPreview.svelte'
import ComponentList from './componentsPanel/ComponentList.svelte'
import ContextPanel from './contextPanel/ContextPanel.svelte'
@@ -119,6 +119,7 @@
const worldStore = buildWorld(context)
const previewTheme: Writable<string | undefined> = writable(undefined)
const initialized = writable({ initialized: false, initializedComponents: [] })
$secondaryMenuRightStore.isOpen = false
$secondaryMenuLeftStore.isOpen = false
@@ -127,7 +128,7 @@
worldStore,
app: appStore,
summary: summaryStore,
initialized: writable({ initialized: false, initializedComponents: [] }),
initialized: initialized,
selectedComponent,
mode,
connectingInput,
@@ -470,6 +471,23 @@
onMount(() => {
mounted = true
setTimeout(() => {
if ($initialized?.initialized === false) {
sendUserToast(
'App is not yet initialized, please check the Troubleshoot Panel for more information',
true,
[
{
label: 'Open Troubleshoot Panel',
callback: () => {
appEditorHeader?.openTroubleshootPanel()
}
}
]
)
}
}, 10000)
parseScroll()
})
@@ -92,6 +92,7 @@
createUpdatePostgresInput,
getPrimaryKeys
} from '../components/display/dbtable/utils'
import DebugPanel from './contextPanel/DebugPanel.svelte'
async function hash(message) {
try {
@@ -161,6 +162,7 @@
let saveDrawerOpen = false
let inputsDrawerOpen = fromHub
let historyBrowserDrawerOpen = false
let debugAppDrawerOpen = false
let deploymentMsg: string | undefined = undefined
function closeSaveDrawer() {
@@ -208,7 +210,6 @@
const whereClause = (c.configuration.whereClause as any).value as unknown as
| string
| undefined
console.log(columnDefs)
if (tableValue && resourceValue && columnDefs) {
r.push({
input: createPostgresInput(resourceValue, tableValue, columnDefs, whereClause),
@@ -672,6 +673,14 @@
})
},
disabled: !savedApp
},
// App debug menu
{
displayName: 'Troubleshoot panel',
icon: Bug,
action: () => {
debugAppDrawerOpen = true
}
}
]
@@ -684,6 +693,10 @@
let rightColumnSelect: 'timeline' | 'detail' = 'timeline'
let appReportingDrawerOpen = false
export function openTroubleshootPanel() {
debugAppDrawerOpen = true
}
</script>
<svelte:window on:keydown={onKeyDown} />
@@ -936,6 +949,12 @@
</DrawerContent>
</Drawer>
<Drawer bind:open={debugAppDrawerOpen} size="800px">
<DrawerContent title="Troubleshoot Panel" on:close={() => (debugAppDrawerOpen = false)}>
<DebugPanel />
</DrawerContent>
</Drawer>
<Drawer bind:open={$jobsDrawerOpen} size="900px" --zIndex={1003}>
<DrawerContent
noPadding
@@ -175,7 +175,7 @@
title="Custom Components"
on:close={ccDrawer.closeDrawer}
documentationLink="https://www.windmill.dev/docs/apps/react_components"
>
>
<ComponentsList on:reload={fetchCustomComponents} />
</DrawerContent>
</Drawer>
@@ -0,0 +1,151 @@
<script lang="ts">
import { getContext } from 'svelte'
import { allItems } from '../../utils'
import type { AppViewerContext } from '../../types'
import Section from '$lib/components/Section.svelte'
import Badge from '$lib/components/common/badge/Badge.svelte'
import { findGridItem } from '../appUtils'
import { pluralize } from '$lib/utils'
import Button from '$lib/components/common/button/Button.svelte'
import { Trash } from 'lucide-svelte'
import Alert from '$lib/components/common/alert/Alert.svelte'
const { app, initialized } = getContext<AppViewerContext>('AppViewerContext')
$: unintitializedComponents = allItems($app.grid, $app.subgrids)
.map((x) => x.id)
.filter((x) => !$initialized.initializedComponents?.includes(x))
.sort()
$: subgridsErrors = Object.keys($app.subgrids ?? {})
.map((x) => {
const parentId = x.split('-')[0]
const parent = findGridItem($app, parentId)
if (parent === undefined) {
return {
subGridId: x,
error: 'Parent not found'
}
} else if (parent?.data?.numberOfSubgrids === undefined) {
return {
subGridId: x,
error: 'Parent is not a container'
}
}
})
.filter(Boolean)
</script>
<div class="flex flex-col gap-8" style="all:none;">
{#if unintitializedComponents?.length === 0 && subgridsErrors?.length === 0}
<Alert type="success" title="No issues found">
The app has no subgrid errors or uninitialized components.
</Alert>
{:else}
<Alert type="error" title="Issues found">
The app has {unintitializedComponents.length} uninitialized components and {subgridsErrors.length}
subgrid errors.
<br />
Please contact Windmill support for assistance.
</Alert>
{/if}
{#if unintitializedComponents.length > 0}
<Section label="Uninitialized components">
<div class="max-w-xl">
<div class="text-sm mb-4">
There are {pluralize(unintitializedComponents.length, 'uninitialized component')} in the app.
</div>
<div class="grid grid-cols-3 border rounded-md overflow-hidden">
<!-- Header -->
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
>Component Id</div
>
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
>Type</div
>
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
>Status</div
>
<!-- Iterate over uninitializedComponents to display each component in the grid -->
{#each unintitializedComponents as c}
<!-- Component Id -->
<div class="text-xs flex items-center px-2 py-2">
<Badge>
{c}
</Badge>
</div>
<div class="text-xs flex items-center px-2 py-2">
<Badge color="blue">
{findGridItem($app, c)?.data?.type || 'Unknown'}
</Badge>
</div>
<div class="text-xs flex items-center px-2 py-2">
<Badge color="red">Uninitialized</Badge>
</div>
{/each}
</div>
</div>
</Section>{/if}
{#if subgridsErrors.length > 0}
<Section label="Subgrids errors">
<div class="max-w-xl">
<div class="text-sm mb-4">
There are
{pluralize(subgridsErrors.length, 'subgrid')} with errors in the app.
</div>
<div class="grid grid-cols-3 border rounded-md overflow-hidden">
<!-- Header -->
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
>Subgrid Id</div
>
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
>Error</div
>
<div class="font-semibold bg-gray-100 dark:bg-gray-900 px-2 py-1 text-xs border-b"
>Action</div
>
<!-- Iterate over uninitializedComponents to display each component in the grid -->
{#each subgridsErrors as s}
<!-- Component Id -->
<div class="text-xs flex items-center px-2 py-2">
<Badge>
{s?.subGridId}
</Badge>
</div>
<div class="text-xs flex items-center px-2 py-2">
<Badge color="red">
{s?.error}
</Badge>
</div>
<div class="text-xs flex items-center px-2 py-2">
<Button
color="light"
startIcon={{
icon: Trash
}}
size="xs2"
on:click={() => {
if ($app.subgrids && s) {
delete $app.subgrids[s.subGridId]
$app = { ...$app }
}
}}
>
Remove subgrid
</Button>
</div>
{/each}
</div>
</div>
</Section>
{/if}
</div>