feat: Show empty workflow dialog when entering app builder with no nodes (#9379)

## Summary

Prompts users to load a template or return to graph when entering
builder mode on an empty workflow

## Screenshots (if applicable)

<img width="627" height="275" alt="image"
src="https://github.com/user-attachments/assets/c1a35dc3-4e8f-4abd-95b9-2f92524e8ebf"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9379-feat-Show-empty-workflow-dialog-when-entering-app-builder-with-no-nodes-3196d73d36508123b643ec893cd86cac)
by [Unito](https://www.unito.io)
This commit is contained in:
pythongosssss
2026-03-04 20:15:56 +00:00
committed by GitHub
parent f084a60708
commit 31276ff2a6
9 changed files with 221 additions and 48 deletions

View File

@@ -107,6 +107,32 @@ describe('useWorkflowTemplateSelectorDialog', () => {
)
})
it('invokes afterClose callback when dialog is closed', () => {
mockNewUserService.isNewUser.mockReturnValue(false)
const afterClose = vi.fn()
const dialog = useWorkflowTemplateSelectorDialog()
dialog.show('command', { afterClose })
const onClose =
mockDialogService.showLayoutDialog.mock.calls[0][0].props.onClose
onClose()
expect(mockDialogStore.closeDialog).toHaveBeenCalled()
expect(afterClose).toHaveBeenCalled()
})
it('does not fail when afterClose is not provided', () => {
mockNewUserService.isNewUser.mockReturnValue(false)
const dialog = useWorkflowTemplateSelectorDialog()
dialog.show('command')
const onClose =
mockDialogService.showLayoutDialog.mock.calls[0][0].props.onClose
expect(() => onClose()).not.toThrow()
})
it('tracks telemetry with source', () => {
mockNewUserService.isNewUser.mockReturnValue(false)

View File

@@ -1,5 +1,6 @@
import WorkflowTemplateSelectorDialog from '@/components/custom/widget/WorkflowTemplateSelectorDialog.vue'
import { useTelemetry } from '@/platform/telemetry'
import type { TemplateLibraryMetadata } from '@/platform/telemetry/types'
import { useDialogService } from '@/services/dialogService'
import { useNewUserService } from '@/services/useNewUserService'
import { useDialogStore } from '@/stores/dialogStore'
@@ -17,8 +18,8 @@ export const useWorkflowTemplateSelectorDialog = () => {
}
function show(
source: 'sidebar' | 'menu' | 'command' = 'command',
options?: { initialCategory?: string }
source: TemplateLibraryMetadata['source'] = 'command',
options?: { initialCategory?: string; afterClose?: () => void }
) {
useTelemetry()?.trackTemplateLibraryOpened({ source })
@@ -30,7 +31,10 @@ export const useWorkflowTemplateSelectorDialog = () => {
key: DIALOG_KEY,
component: WorkflowTemplateSelectorDialog,
props: {
onClose: hide,
onClose: () => {
hide()
options?.afterClose?.()
},
initialCategory
}
})