mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 23:50:08 +00:00
Move widget configuration out of sidebar
This commit is contained in:
@@ -22,7 +22,8 @@
|
||||
<ColorPickerButton v-if="showColorPicker" />
|
||||
<FrameNodes v-if="showFrameNodes" />
|
||||
<ConvertToSubgraphButton v-if="showConvertToSubgraph" />
|
||||
<PublishSubgraphButton v-if="showPublishSubgraph" />
|
||||
<ConfigureSubgraph v-if="showSubgraphButtons" />
|
||||
<PublishSubgraphButton v-if="showSubgraphButtons" />
|
||||
<MaskEditorButton v-if="showMaskEditor" />
|
||||
<VerticalDivider
|
||||
v-if="showAnyPrimaryActions && showAnyControlActions"
|
||||
@@ -50,6 +51,7 @@ import { computed, ref } from 'vue'
|
||||
|
||||
import BypassButton from '@/components/graph/selectionToolbox/BypassButton.vue'
|
||||
import ColorPickerButton from '@/components/graph/selectionToolbox/ColorPickerButton.vue'
|
||||
import ConfigureSubgraph from '@/components/graph/selectionToolbox/ConfigureSubgraph.vue'
|
||||
import ConvertToSubgraphButton from '@/components/graph/selectionToolbox/ConvertToSubgraphButton.vue'
|
||||
import DeleteButton from '@/components/graph/selectionToolbox/DeleteButton.vue'
|
||||
import ExecuteButton from '@/components/graph/selectionToolbox/ExecuteButton.vue'
|
||||
@@ -112,7 +114,7 @@ const showInfoButton = computed(() => !!nodeDef.value)
|
||||
const showColorPicker = computed(() => hasAnySelection.value)
|
||||
const showConvertToSubgraph = computed(() => hasAnySelection.value)
|
||||
const showFrameNodes = computed(() => hasMultipleSelection.value)
|
||||
const showPublishSubgraph = computed(() => isSingleSubgraph.value)
|
||||
const showSubgraphButtons = computed(() => isSingleSubgraph.value)
|
||||
|
||||
const showBypass = computed(
|
||||
() =>
|
||||
@@ -130,7 +132,7 @@ const showAnyPrimaryActions = computed(
|
||||
showColorPicker.value ||
|
||||
showConvertToSubgraph.value ||
|
||||
showFrameNodes.value ||
|
||||
showPublishSubgraph.value
|
||||
showSubgraphButtons.value
|
||||
)
|
||||
|
||||
const showAnyControlActions = computed(() => showBypass.value)
|
||||
|
||||
24
src/components/graph/selectionToolbox/ConfigureSubgraph.vue
Normal file
24
src/components/graph/selectionToolbox/ConfigureSubgraph.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<Button
|
||||
v-tooltip.top="{
|
||||
value: t('Edit Subgraph Widgets'),
|
||||
showDelay: 1000
|
||||
}"
|
||||
severity="secondary"
|
||||
text
|
||||
@click="showSubgraphNodeDialog"
|
||||
>
|
||||
<template #icon>
|
||||
<i-lucide:settings2 />
|
||||
</template>
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Button from 'primevue/button'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { showSubgraphNodeDialog } from '@/core/graph/subgraph/useSubgraphNodeDialog'
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
@@ -5,7 +5,6 @@ import draggable from 'vuedraggable'
|
||||
|
||||
import SearchBox from '@/components/common/SearchBox.vue'
|
||||
import SubgraphNodeWidget from '@/components/selectionbar/SubgraphNodeWidget.vue'
|
||||
import SidebarTabTemplate from '@/components/sidebar/tabs/SidebarTabTemplate.vue'
|
||||
import {
|
||||
type ProxyWidgetsProperty,
|
||||
parseProxyWidgets
|
||||
@@ -14,6 +13,7 @@ import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import { SubgraphNode } from '@/lib/litegraph/src/subgraph/SubgraphNode'
|
||||
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
|
||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { useDialogStore } from '@/stores/dialogStore'
|
||||
|
||||
type WidgetItem = [LGraphNode, IBaseWidget]
|
||||
|
||||
@@ -32,6 +32,7 @@ function toKey(item: WidgetItem) {
|
||||
const activeNode = computed(() => {
|
||||
const node = canvasStore.selectedItems[0]
|
||||
if (node instanceof SubgraphNode) return node
|
||||
useDialogStore().closeDialog()
|
||||
return undefined
|
||||
})
|
||||
|
||||
@@ -184,85 +185,76 @@ const filteredActive = computed<WidgetItem[]>(() => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<SidebarTabTemplate
|
||||
:title="'Parameters'"
|
||||
class="workflows-sidebar-tab bg-[var(--p-tree-background)]"
|
||||
>
|
||||
<template #header>
|
||||
<SearchBox
|
||||
v-model:model-value="searchQuery"
|
||||
class="model-lib-search-box p-2 2xl:p-4"
|
||||
:placeholder="$t('g.search') + '...'"
|
||||
<SearchBox
|
||||
v-model:model-value="searchQuery"
|
||||
class="model-lib-search-box p-2 2xl:p-4"
|
||||
:placeholder="$t('g.search') + '...'"
|
||||
/>
|
||||
<div v-if="filteredActive.length" class="widgets-section">
|
||||
<div class="widgets-section-header">
|
||||
<div>{{ t('subgraphStore.shown') }}</div>
|
||||
<a @click.stop="hideAll"> {{ t('subgraphStore.hideAll') }}</a>
|
||||
</div>
|
||||
<div v-if="searchQuery" class="w-full">
|
||||
<div
|
||||
v-for="element in filteredActive"
|
||||
:key="toKey(element)"
|
||||
class="w-full"
|
||||
>
|
||||
<SubgraphNodeWidget
|
||||
:node-id="`${element[0].id}`"
|
||||
:node-title="element[0].title"
|
||||
:widget-name="element[1].name"
|
||||
:toggle-visibility="toggleVisibility"
|
||||
:is-shown="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<draggable
|
||||
v-else
|
||||
v-model="activeWidgets"
|
||||
group="enabledWidgets"
|
||||
class="w-full cursor-grab"
|
||||
chosen-class="cursor-grabbing"
|
||||
drag-class="cursor-grabbing"
|
||||
:animation="100"
|
||||
item-key="id"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<SubgraphNodeWidget
|
||||
:node-id="`${element[0].id}`"
|
||||
:node-title="element[0].title"
|
||||
:widget-name="element[1].name"
|
||||
:is-shown="true"
|
||||
:toggle-visibility="toggleVisibility"
|
||||
:is-draggable="true"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
<div v-if="filteredCandidates.length" class="widgets-section">
|
||||
<div class="widgets-section-header">
|
||||
<div>{{ t('subgraphStore.hidden') }}</div>
|
||||
<a @click.stop="showAll"> {{ t('subgraphStore.showAll') }}</a>
|
||||
</div>
|
||||
<div
|
||||
v-for="element in filteredCandidates"
|
||||
:key="toKey(element)"
|
||||
class="w-full"
|
||||
>
|
||||
<SubgraphNodeWidget
|
||||
:node-id="`${element[0].id}`"
|
||||
:node-title="element[0].title"
|
||||
:widget-name="element[1].name"
|
||||
:toggle-visibility="toggleVisibility"
|
||||
/>
|
||||
</template>
|
||||
<template #body>
|
||||
<div v-if="filteredActive.length" class="widgets-section">
|
||||
<div class="widgets-section-header">
|
||||
<div>{{ t('subgraphStore.shown') }}</div>
|
||||
<a @click.stop="hideAll"> {{ t('subgraphStore.hideAll') }}</a>
|
||||
</div>
|
||||
<div v-if="searchQuery" class="w-full">
|
||||
<div
|
||||
v-for="element in filteredActive"
|
||||
:key="toKey(element)"
|
||||
class="w-full"
|
||||
>
|
||||
<SubgraphNodeWidget
|
||||
:node-id="`${element[0].id}`"
|
||||
:node-title="element[0].title"
|
||||
:widget-name="element[1].name"
|
||||
:toggle-visibility="toggleVisibility"
|
||||
:is-shown="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<draggable
|
||||
v-else
|
||||
v-model="activeWidgets"
|
||||
group="enabledWidgets"
|
||||
class="w-full cursor-grab"
|
||||
chosen-class="cursor-grabbing"
|
||||
drag-class="cursor-grabbing"
|
||||
:animation="100"
|
||||
item-key="id"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<SubgraphNodeWidget
|
||||
:node-id="`${element[0].id}`"
|
||||
:node-title="element[0].title"
|
||||
:widget-name="element[1].name"
|
||||
:is-shown="true"
|
||||
:toggle-visibility="toggleVisibility"
|
||||
:is-draggable="true"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
<div v-if="filteredCandidates.length" class="widgets-section">
|
||||
<div class="widgets-section-header">
|
||||
<div>{{ t('subgraphStore.hidden') }}</div>
|
||||
<a @click.stop="showAll"> {{ t('subgraphStore.showAll') }}</a>
|
||||
</div>
|
||||
<div
|
||||
v-for="element in filteredCandidates"
|
||||
:key="toKey(element)"
|
||||
class="w-full"
|
||||
>
|
||||
<SubgraphNodeWidget
|
||||
:node-id="`${element[0].id}`"
|
||||
:node-title="element[0].title"
|
||||
:widget-name="element[1].name"
|
||||
:toggle-visibility="toggleVisibility"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="recommendedWidgets.length" class="justify-center flex py-4">
|
||||
<Button size="small" @click.stop="showRecommended">
|
||||
{{ t('subgraphStore.showRecommended') }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
</SidebarTabTemplate>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="recommendedWidgets.length" class="justify-center flex py-4">
|
||||
<Button size="small" @click.stop="showRecommended">
|
||||
{{ t('subgraphStore.showRecommended') }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.widgets-section-header {
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { markRaw } from 'vue'
|
||||
|
||||
import SubgraphNode from '@/components/selectionbar/SubgraphNode.vue'
|
||||
import type { SidebarTabExtension } from '@/types/extensionTypes'
|
||||
|
||||
export const useSubgraphNodeTab = (): SidebarTabExtension => {
|
||||
return {
|
||||
id: 'sgn',
|
||||
icon: 'pi pi-chart-bar',
|
||||
iconBadge: () => {
|
||||
return null
|
||||
},
|
||||
title: 'subgraph widgets',
|
||||
tooltip: 'Change displayed subgraph widgets',
|
||||
label: 'subgraph widgets',
|
||||
component: markRaw(SubgraphNode),
|
||||
type: 'vue'
|
||||
}
|
||||
}
|
||||
21
src/core/graph/subgraph/useSubgraphNodeDialog.ts
Normal file
21
src/core/graph/subgraph/useSubgraphNodeDialog.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import SubgraphNode from '@/components/selectionbar/SubgraphNode.vue'
|
||||
import { type DialogComponentProps, useDialogStore } from '@/stores/dialogStore'
|
||||
|
||||
const key = 'global-subgraph-node-config'
|
||||
|
||||
export function showSubgraphNodeDialog() {
|
||||
const dialogStore = useDialogStore()
|
||||
const dialogComponentProps: DialogComponentProps = {
|
||||
headless: true,
|
||||
modal: false,
|
||||
closable: false,
|
||||
position: 'right'
|
||||
}
|
||||
|
||||
dialogStore.showDialog({
|
||||
title: 'Parameters',
|
||||
key,
|
||||
component: SubgraphNode,
|
||||
dialogComponentProps
|
||||
})
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { useNodeAnimatedImage } from '@/composables/node/useNodeAnimatedImage'
|
||||
import { useNodeCanvasImagePreview } from '@/composables/node/useNodeCanvasImagePreview'
|
||||
import { useNodeImage, useNodeVideo } from '@/composables/node/useNodeImage'
|
||||
import { addWidgetPromotionOptions } from '@/core/graph/subgraph/proxyWidgetUtils'
|
||||
import { showSubgraphNodeDialog } from '@/core/graph/subgraph/useSubgraphNodeDialog'
|
||||
import { st, t } from '@/i18n'
|
||||
import {
|
||||
type IContextMenuValue,
|
||||
@@ -825,13 +826,21 @@ export const useLitegraphService = () => {
|
||||
}
|
||||
}
|
||||
if (this instanceof SubgraphNode) {
|
||||
options.unshift({
|
||||
content: 'Unpack Subgraph',
|
||||
callback: () => {
|
||||
useNodeOutputStore().revokeSubgraphPreviews(this)
|
||||
this.graph.unpackSubgraph(this)
|
||||
options.unshift(
|
||||
{
|
||||
content: 'Edit Subgraph Widgets',
|
||||
callback: () => {
|
||||
showSubgraphNodeDialog()
|
||||
}
|
||||
},
|
||||
{
|
||||
content: 'Unpack Subgraph',
|
||||
callback: () => {
|
||||
useNodeOutputStore().revokeSubgraphPreviews(this)
|
||||
this.graph.unpackSubgraph(this)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
if (this.graph && !this.graph.isRootGraph) {
|
||||
const [x, y] = canvas.canvas_mouse
|
||||
|
||||
@@ -4,7 +4,6 @@ import { computed, ref } from 'vue'
|
||||
import { useModelLibrarySidebarTab } from '@/composables/sidebarTabs/useModelLibrarySidebarTab'
|
||||
import { useNodeLibrarySidebarTab } from '@/composables/sidebarTabs/useNodeLibrarySidebarTab'
|
||||
import { useQueueSidebarTab } from '@/composables/sidebarTabs/useQueueSidebarTab'
|
||||
import { useSubgraphNodeTab } from '@/composables/sidebarTabs/useSubgraphNodeTab'
|
||||
import { t, te } from '@/i18n'
|
||||
import { useWorkflowsSidebarTab } from '@/platform/workflow/management/composables/useWorkflowsSidebarTab'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
@@ -93,7 +92,6 @@ export const useSidebarTabStore = defineStore('sidebarTab', () => {
|
||||
registerSidebarTab(useNodeLibrarySidebarTab())
|
||||
registerSidebarTab(useModelLibrarySidebarTab())
|
||||
registerSidebarTab(useWorkflowsSidebarTab())
|
||||
registerSidebarTab(useSubgraphNodeTab())
|
||||
|
||||
const menuStore = useMenuItemStore()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user