[refactor] Unify small modal dialog styles with showSmallLayoutDialog (#8834)

## Summary
Extract a shared `showSmallLayoutDialog` utility and move
dialog-specific logic into composables, unifying the duplicated `pt`
configurations across small modal dialogs.

## Changes
- **`showSmallLayoutDialog`**: Added to `dialogService.ts` with a single
unified `pt` config for all small modal dialogs (missing nodes, missing
models, import failed, node conflict)
- **Composables**: Extracted 4 dialog functions from `dialogService`
into dedicated composables following the `useSettingsDialog` /
`useModelSelectorDialog` pattern:
  - `useMissingNodesDialog`
  - `useMissingModelsDialog`
  - `useImportFailedNodeDialog`
  - `useNodeConflictDialog`
- Each composable uses direct imports, synchronous `show()`, `hide()`,
and a `DIALOG_KEY` constant
- Updated all call sites (`app.ts`, `useHelpCenter`, `PackEnableToggle`,
`PackInstallButton`, `useImportFailedDetection`)

## Review Focus
- Unified `pt` config removes minor style variations between dialogs —
intentional design unification

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8834-refactor-Unify-small-modal-dialog-styles-with-showSmallLayoutDialog-3056d73d365081b6963beffc0e5943bf)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Jin Yi
2026-02-20 13:58:59 +09:00
committed by GitHub
parent fe78bc6043
commit 44733f010d
15 changed files with 244 additions and 267 deletions

View File

@@ -16,22 +16,9 @@ import type {
ShowDialogOptions
} from '@/stores/dialogStore'
import type { ConflictDetectionResult } from '@/workbench/extensions/manager/types/conflictDetectionTypes'
import type { ComponentAttrs } from 'vue-component-type-helpers'
// Type-only imports for ComponentAttrs inference (no runtime cost)
import type MissingNodesContent from '@/components/dialog/content/MissingNodesContent.vue'
import type MissingModelsWarning from '@/components/dialog/content/MissingModelsWarning.vue'
// Lazy loaders for dialogs - components are loaded on first use
const lazyMissingNodesContent = () =>
import('@/components/dialog/content/MissingNodesContent.vue')
const lazyMissingNodesHeader = () =>
import('@/components/dialog/content/MissingNodesHeader.vue')
const lazyMissingNodesFooter = () =>
import('@/components/dialog/content/MissingNodesFooter.vue')
const lazyMissingModelsWarning = () =>
import('@/components/dialog/content/MissingModelsWarning.vue')
const lazyApiNodesSignInContent = () =>
import('@/components/dialog/content/ApiNodesSignInContent.vue')
const lazySignInContent = () =>
@@ -40,18 +27,6 @@ const lazyUpdatePasswordContent = () =>
import('@/components/dialog/content/UpdatePasswordContent.vue')
const lazyComfyOrgHeader = () =>
import('@/components/dialog/header/ComfyOrgHeader.vue')
const lazyImportFailedNodeContent = () =>
import('@/workbench/extensions/manager/components/manager/ImportFailedNodeContent.vue')
const lazyImportFailedNodeHeader = () =>
import('@/workbench/extensions/manager/components/manager/ImportFailedNodeHeader.vue')
const lazyImportFailedNodeFooter = () =>
import('@/workbench/extensions/manager/components/manager/ImportFailedNodeFooter.vue')
const lazyNodeConflictDialogContent = () =>
import('@/workbench/extensions/manager/components/manager/NodeConflictDialogContent.vue')
const lazyNodeConflictHeader = () =>
import('@/workbench/extensions/manager/components/manager/NodeConflictHeader.vue')
const lazyNodeConflictFooter = () =>
import('@/workbench/extensions/manager/components/manager/NodeConflictFooter.vue')
export type ConfirmationDialogType =
| 'default'
@@ -77,56 +52,6 @@ export interface ExecutionErrorDialogInput {
export const useDialogService = () => {
const dialogStore = useDialogStore()
async function showLoadWorkflowWarning(
props: ComponentAttrs<typeof MissingNodesContent>
) {
const [
{ default: MissingNodesContent },
{ default: MissingNodesHeader },
{ default: MissingNodesFooter }
] = await Promise.all([
lazyMissingNodesContent(),
lazyMissingNodesHeader(),
lazyMissingNodesFooter()
])
dialogStore.showDialog({
key: 'global-missing-nodes',
headerComponent: MissingNodesHeader,
footerComponent: MissingNodesFooter,
component: MissingNodesContent,
dialogComponentProps: {
closable: true,
pt: {
root: { class: 'bg-base-background border-border-default' },
header: { class: '!p-0 !m-0' },
content: { class: '!p-0 overflow-y-hidden' },
footer: { class: '!p-0' },
pcCloseButton: {
root: {
class: '!w-7 !h-7 !border-none !outline-none !p-2 !m-1.5'
}
}
}
},
props,
footerProps: {
missingNodeTypes: props.missingNodeTypes
}
})
}
async function showMissingModelsWarning(
props: ComponentAttrs<typeof MissingModelsWarning>
) {
const { default: MissingModelsWarning } = await lazyMissingModelsWarning()
dialogStore.showDialog({
key: 'global-missing-models-warning',
component: MissingModelsWarning,
props
})
}
function showExecutionErrorDialog(executionError: ExecutionErrorDialogInput) {
const props: ComponentAttrs<typeof ErrorDialogContent> = {
error: {
@@ -440,29 +365,15 @@ export const useDialogService = () => {
})
}
async function showImportFailedNodeDialog(
options: {
conflictedPackages?: ConflictDetectionResult[]
dialogComponentProps?: DialogComponentProps
} = {}
function showSmallLayoutDialog(
options: Omit<ShowDialogOptions, 'dialogComponentProps'> & {
dialogComponentProps?: Omit<DialogComponentProps, 'pt'>
}
) {
const [
{ default: ImportFailedNodeHeader },
{ default: ImportFailedNodeFooter },
{ default: ImportFailedNodeContent }
] = await Promise.all([
lazyImportFailedNodeHeader(),
lazyImportFailedNodeFooter(),
lazyImportFailedNodeContent()
])
const { dialogComponentProps, conflictedPackages } = options
const { dialogComponentProps: callerProps, ...rest } = options
return dialogStore.showDialog({
key: 'global-import-failed',
headerComponent: ImportFailedNodeHeader,
footerComponent: ImportFailedNodeFooter,
component: ImportFailedNodeContent,
...rest,
dialogComponentProps: {
closable: true,
pt: {
@@ -476,71 +387,7 @@ export const useDialogService = () => {
}
}
},
...dialogComponentProps
},
props: {
conflictedPackages: conflictedPackages ?? []
},
footerProps: {
conflictedPackages: conflictedPackages ?? []
}
})
}
async function showNodeConflictDialog(
options: {
showAfterWhatsNew?: boolean
conflictedPackages?: ConflictDetectionResult[]
dialogComponentProps?: DialogComponentProps
buttonText?: string
onButtonClick?: () => void
} = {}
) {
const [
{ default: NodeConflictHeader },
{ default: NodeConflictFooter },
{ default: NodeConflictDialogContent }
] = await Promise.all([
lazyNodeConflictHeader(),
lazyNodeConflictFooter(),
lazyNodeConflictDialogContent()
])
const {
dialogComponentProps,
buttonText,
onButtonClick,
showAfterWhatsNew,
conflictedPackages
} = options
return dialogStore.showDialog({
key: 'global-node-conflict',
headerComponent: NodeConflictHeader,
footerComponent: NodeConflictFooter,
component: NodeConflictDialogContent,
dialogComponentProps: {
closable: true,
pt: {
header: { class: '!p-0 !m-0' },
content: { class: '!p-0 overflow-y-hidden' },
footer: { class: '!p-0' },
pcCloseButton: {
root: {
class:
'!w-7 !h-7 !border-none !outline-none !p-2 !m-1.5 bg-dialog-surface text-white'
}
}
},
...dialogComponentProps
},
props: {
showAfterWhatsNew,
conflictedPackages
},
footerProps: {
buttonText,
onButtonClick
...callerProps
}
})
}
@@ -715,8 +562,6 @@ export const useDialogService = () => {
}
return {
showLoadWorkflowWarning,
showMissingModelsWarning,
showExecutionErrorDialog,
showApiNodesSignInDialog,
showSignInDialog,
@@ -728,8 +573,7 @@ export const useDialogService = () => {
showErrorDialog,
confirm,
showLayoutDialog,
showImportFailedNodeDialog,
showNodeConflictDialog,
showSmallLayoutDialog,
showDeleteWorkspaceDialog,
showCreateWorkspaceDialog,
showLeaveWorkspaceDialog,