Skip to content

Conversation

christian-byrne
Copy link
Contributor

@christian-byrne christian-byrne commented Sep 28, 2025

Summary

Fixes #5692 by making widget link connection status trigger on change so Vue widgets with connected links could properly switch to the disabled state when they are implicitly converted to inputs.

Changes

  • What: Added node:slot-links:changed event tracking and reactive slot data synchronization for Vue widgets
graph TD
    A[Widget Link Change] --> B[NodeInputSlot.link setter]
    B --> C{Is Widget Input?}
    C -->|Yes| D[Trigger slot-links:changed]
    C -->|No| E[End]
    D --> F[Graph Event Handler]
    F --> G[syncNodeSlotData]
    G --> H[Update Vue Reactive Data]
    H --> I[Widget Re-render]
    
    style A fill:#f9f9f9,stroke:#333,color:#000
    style I fill:#f9f9f9,stroke:#333,color:#000
Loading

Review Focus

Widget reactivity performance with frequent link changes and event handler memory management in graph operations.

┆Issue is synchronized with this Notion page by Unito

@dosubot dosubot bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Sep 28, 2025
Copy link

github-actions bot commented Sep 28, 2025

🎭 Playwright Test Results

Some tests failed

⏰ Completed at: 09/28/2025, 08:47:05 PM UTC

📈 Summary

  • Total Tests: 451
  • Passed: 393 ✅
  • Failed: 27 ❌
  • Flaky: 2 ⚠️
  • Skipped: 29 ⏭️

📊 Test Reports by Browser

  • chromium: View Report • ✅ 385 / ❌ 27 / ⚠️ 2 / ⏭️ 29
  • chromium-2x: View Report • ✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • chromium-0.5x: View Report • ✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • mobile-chrome: View Report • ✅ 5 / ❌ 0 / ⚠️ 0 / ⏭️ 0

🎉 Click on the links above to view detailed test results for each browser configuration.

@christian-byrne christian-byrne requested review from benceruleanlu and DrJKL and removed request for benceruleanlu September 28, 2025 20:38
@DrJKL DrJKL self-assigned this Sep 29, 2025
<NodeWidgets
v-if="nodeData.widgets?.length"
v-memo="[nodeData.widgets?.length]"
v-memo="[nodeData.widgets?.length, nodeData.inputs]"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if we just removed the v-memo and let Vue handle it?

Suggested change
v-memo="[nodeData.widgets?.length, nodeData.inputs]"


export class NodeInputSlot extends NodeSlot implements INodeInputSlot {
link: LinkId | null
private _link: LinkId | null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two points of personal preference for this pattern:
I usually like an Internal suffix, i.e. linkInternal to the underscore prefix. Feels more expressive and helps with IDEs' outlines if you sort fields lexicographically.
I also don't love null over undefined since it does usually entail adding nullish coalescing to pick the specific correct absent value (when otherwise the absent value is undefined in the default case)

Comment on lines +69 to +75
graph.trigger('node:slot-links:changed', {
nodeId: this.node.id,
slotType: NodeSlotType.INPUT,
slotIndex: index,
connected: this._link != null,
linkId: this._link ?? null
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like something that we should be doing in a store, if not now, then soon. I don't like complex decisions being made in components.

nodeId: this.node.id,
slotType: NodeSlotType.INPUT,
slotIndex: index,
connected: this._link != null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
connected: this._link != null,
connected: this.isConnected,

slotType: NodeSlotType.INPUT,
slotIndex: index,
connected: this._link != null,
linkId: this._link ?? null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
linkId: this._link ?? null
linkId: this.link

Comment on lines +66 to +72
const index = this.node.inputs.indexOf(this)
if (index === -1) return

graph.trigger('node:slot-links:changed', {
nodeId: this.node.id,
slotType: NodeSlotType.INPUT,
slotIndex: index,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

option:

Suggested change
const index = this.node.inputs.indexOf(this)
if (index === -1) return
graph.trigger('node:slot-links:changed', {
nodeId: this.node.id,
slotType: NodeSlotType.INPUT,
slotIndex: index,
const slotIndex = this.node.inputs.indexOf(this)
if (slotIndex === -1) return
graph.trigger('node:slot-links:changed', {
nodeId: this.node.id,
slotType: NodeSlotType.INPUT,
slotIndex,


vueNodeData.set(nodeId, {
...currentData,
inputs: node.inputs ? [...node.inputs] : undefined,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR, but what if we defined inputs and outputs as being required, so that a lack of them would just be an empty array? Would that simplify some of the logic?

@DrJKL DrJKL assigned christian-byrne and unassigned DrJKL Sep 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:links area:vue-migration area:widgets size:M This PR changes 30-99 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The widget value is still editable or not hidden when converted to input.
2 participants