mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-22 23:39:45 +00:00
Decouple node help between sidebar and right panel (#8110)
## Summary When the node library is open and you click on the node toolbar info button, this causes the node library info panel & right panel node info to show the same details. ## Changes - Extract useNodeHelpContent composable so NodeHelpContent fetches its own content, allowing multiple panels to show help independently - Remove sync behavior from NodeHelpPage that caused left sidebar to change when selecting different graph nodes since we want to prioritise right panel for this behavior - Add telemetry tracking for node library help button to identify how frequently this is used ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8110-Decouple-node-help-between-sidebar-and-right-panel-2ea6d73d365081a9b3afd25aa51b34bd) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -1,100 +0,0 @@
|
||||
import { flushPromises, mount } from '@vue/test-utils'
|
||||
import { computed, ref } from 'vue'
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest'
|
||||
|
||||
import NodeHelpPage from '@/components/sidebar/tabs/nodeLibrary/NodeHelpPage.vue'
|
||||
import { useSelectionState } from '@/composables/graph/useSelectionState'
|
||||
import { useNodeHelpStore } from '@/stores/workspace/nodeHelpStore'
|
||||
|
||||
vi.mock('@/composables/graph/useSelectionState')
|
||||
vi.mock('@/stores/workspace/nodeHelpStore')
|
||||
|
||||
const baseNode = {
|
||||
nodePath: 'NodeA',
|
||||
display_name: 'Node A',
|
||||
description: '',
|
||||
inputs: {},
|
||||
outputs: []
|
||||
}
|
||||
|
||||
describe('NodeHelpPage', () => {
|
||||
const selection = ref<any | null>(null)
|
||||
let openHelp: ReturnType<typeof vi.fn>
|
||||
|
||||
const mountPage = () =>
|
||||
mount(NodeHelpPage, {
|
||||
props: { node: baseNode as any },
|
||||
global: {
|
||||
mocks: {
|
||||
$t: (key: string) => key
|
||||
},
|
||||
stubs: {
|
||||
ProgressSpinner: true,
|
||||
Button: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks()
|
||||
selection.value = null
|
||||
openHelp = vi.fn()
|
||||
|
||||
vi.mocked(useSelectionState).mockReturnValue({
|
||||
nodeDef: computed(() => selection.value)
|
||||
} as any)
|
||||
|
||||
vi.mocked(useNodeHelpStore).mockReturnValue({
|
||||
renderedHelpHtml: ref('<p>help</p>'),
|
||||
isLoading: ref(false),
|
||||
error: ref(null),
|
||||
isHelpOpen: true,
|
||||
currentHelpNode: { nodePath: 'NodeA' },
|
||||
openHelp,
|
||||
closeHelp: vi.fn()
|
||||
} as any)
|
||||
})
|
||||
|
||||
test('opens help for a newly selected node while help is open', async () => {
|
||||
const wrapper = mountPage()
|
||||
|
||||
selection.value = { nodePath: 'NodeB' }
|
||||
await flushPromises()
|
||||
|
||||
expect(openHelp).toHaveBeenCalledWith({ nodePath: 'NodeB' })
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
test('does not reopen help when the same node stays selected', async () => {
|
||||
const wrapper = mountPage()
|
||||
|
||||
selection.value = { nodePath: 'NodeA' }
|
||||
await flushPromises()
|
||||
|
||||
expect(openHelp).not.toHaveBeenCalled()
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
test('does not react to selection when help is closed', async () => {
|
||||
vi.mocked(useNodeHelpStore).mockReturnValueOnce({
|
||||
renderedHelpHtml: ref('<p>help</p>'),
|
||||
isLoading: ref(false),
|
||||
error: ref(null),
|
||||
isHelpOpen: false,
|
||||
currentHelpNode: null,
|
||||
openHelp,
|
||||
closeHelp: vi.fn()
|
||||
} as any)
|
||||
|
||||
const wrapper = mountPage()
|
||||
|
||||
selection.value = { nodePath: 'NodeB' }
|
||||
await flushPromises()
|
||||
|
||||
expect(openHelp).not.toHaveBeenCalled()
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
@@ -21,32 +21,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { whenever } from '@vueuse/core'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import NodeHelpContent from '@/components/node/NodeHelpContent.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useSelectionState } from '@/composables/graph/useSelectionState'
|
||||
import type { ComfyNodeDefImpl } from '@/stores/nodeDefStore'
|
||||
import { useNodeHelpStore } from '@/stores/workspace/nodeHelpStore'
|
||||
|
||||
const { node } = defineProps<{ node: ComfyNodeDefImpl }>()
|
||||
|
||||
defineEmits<{
|
||||
(e: 'close'): void
|
||||
}>()
|
||||
|
||||
const nodeHelpStore = useNodeHelpStore()
|
||||
const { nodeDef } = useSelectionState()
|
||||
|
||||
const activeHelpDef = computed(() =>
|
||||
nodeHelpStore.isHelpOpen ? nodeDef.value : null
|
||||
)
|
||||
|
||||
// Keep the open help page synced with the current selection while help is open.
|
||||
whenever(activeHelpDef, (def) => {
|
||||
const currentHelpNode = nodeHelpStore.currentHelpNode
|
||||
if (currentHelpNode?.nodePath === def.nodePath) return
|
||||
nodeHelpStore.openHelp(def)
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
variant="muted-textonly"
|
||||
size="icon-sm"
|
||||
:aria-label="$t('g.learnMore')"
|
||||
@click.stop="props.openNodeHelp(nodeDef)"
|
||||
@click.stop="onHelpClick"
|
||||
>
|
||||
<i class="pi pi-question size-3.5" />
|
||||
</Button>
|
||||
@@ -85,6 +85,7 @@ import TreeExplorerTreeNode from '@/components/common/TreeExplorerTreeNode.vue'
|
||||
import NodePreview from '@/components/node/NodePreview.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { useNodeBookmarkStore } from '@/stores/nodeBookmarkStore'
|
||||
import type { ComfyNodeDefImpl } from '@/stores/nodeDefStore'
|
||||
import { useSubgraphStore } from '@/stores/subgraphStore'
|
||||
@@ -112,6 +113,13 @@ const sidebarLocation = computed<'left' | 'right'>(() =>
|
||||
const toggleBookmark = async () => {
|
||||
await nodeBookmarkStore.toggleBookmark(nodeDef.value)
|
||||
}
|
||||
|
||||
const onHelpClick = () => {
|
||||
useTelemetry()?.trackUiButtonClicked({
|
||||
button_id: 'node_library_help_button'
|
||||
})
|
||||
props.openNodeHelp(nodeDef.value)
|
||||
}
|
||||
const editBlueprint = async () => {
|
||||
if (!props.node.data)
|
||||
throw new Error(
|
||||
|
||||
Reference in New Issue
Block a user