-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(web): templates store - update the workflow editor position when selecting the blueprint template #3487
Conversation
…selecting the blueprint template
NV-2376 🏪 [Template store] Update Workflow Editor position
Reproduction StepsRight now if you select template and scroll the Workflow Editor and click on any other blueprint template, then the Workflow Editor position is preserved, we want to update it and re-render basically on the tree from the top-centered, like it is initialised in the beginning. Expected BehaviourUpdate the Workflow Editor position when clicking on the blueprint template in the Templates Store modal. |
const [nodes, setNodes, onNodesChange] = useNodesState([]); | ||
const [edges, setEdges, onEdgesChange] = useEdgesState<IEdge>([]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
by default we don't set the initial nodes and edges
reactFlowInstance?.project({ x: middle, y: 10 }); | ||
setViewport({ x: middle, y: 10, zoom: zoomView }); | ||
|
||
reactFlowInstance.setViewport({ x: middle, y: 10, zoom: zoomView }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then we update the viewport to be top-centered
setTimeout(() => { | ||
initializeWorkflowTree(); | ||
}, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After the viewport is updated we render the nodes and edges. This way we are skipping the initial blink that can be noticed here:
Screen.Recording.2023-05-23.at.20.38.33.mov
|
||
if (steps.length) { | ||
for (let i = 0; i < steps.length; i++) { | ||
const step = steps[i]; | ||
const oldNode = nodes[i + 1] || { position: { x: 0, y: 120 } }; | ||
const oldNode = nodes[i + 1]; | ||
const position = oldNode && oldNode.type !== 'addNode' ? oldNode.position : { x: 0, y: 120 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed the nodes positioning issue
setNodes(finalNodes); | ||
setEdges(finalEdges); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set all the nodes and edges at the end
@@ -106,6 +106,7 @@ export const TemplatesStoreModal = ({ general, isOpened, onClose }: ITemplatesSt | |||
<CanvasHolder> | |||
<ReactFlowProvider> | |||
<FlowEditor | |||
key={selectedTemplate._id} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this way we can update the Workflow Editor position when another blueprint template is selected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the react rerender?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the selectedTemplate._id
has changed, the rerender
aka reconciliation
algorithm will unmount FlowEditor
and mount it again because the key
prop has changed.
Basically, when React does rerender the same element in the tree it checks if the type is the same, or the key is the same, if any of these changes it does unmount for the old component, and mounts for the new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good left a couple of comments, on the things I was not sure about.
const newId = (step._id || step.id) as string; | ||
|
||
await onStepInit?.(step); | ||
|
||
const newNode = buildNewNode(newId, oldNode, parentId, step, i); | ||
setNodes((nds) => nds.concat(newNode)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why there was a concat 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because before at the beginning of this function call initializeWorkflowTree
we were resetting the nodes state to [trigger, addNode]. And I guess it only worked because we have the await
in the line 168
, the React setState
is async.
initializeWorkflowTree(); | ||
setTimeout(() => { | ||
initializeWorkflowTree(); | ||
}, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a setTimeout of 0? did you face race or something else while development?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The set timeout is like saying after the viewport is updated
. We have two useEffects
, the first one is adjusting the viewport to top-center, and in the second we are saying with the timeout: "when the viewport is updated, then build all the nodes".
The setTimeout(callback, 0)
Web API puts the callback
in the callback queue
, which is executed right away when the JS callstack
is empty (like when JS/React finishes it's job), so at that time, we are sure that the viewport is updated.
|
||
if (steps.length) { | ||
for (let i = 0; i < steps.length; i++) { | ||
const step = steps[i]; | ||
const oldNode = nodes[i + 1] || { position: { x: 0, y: 120 } }; | ||
const oldNode = nodes[i + 1]; | ||
const position = oldNode && oldNode.type !== 'addNode' ? oldNode.position : { x: 0, y: 120 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You remember where is { x: 0, y: 120 } pointing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from what I do remember it says to put the new node 120px below the old one
@@ -106,6 +106,7 @@ export const TemplatesStoreModal = ({ general, isOpened, onClose }: ITemplatesSt | |||
<CanvasHolder> | |||
<ReactFlowProvider> | |||
<FlowEditor | |||
key={selectedTemplate._id} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the react rerender?
…pdate-workflow-editor-position
What change does this PR introduce?
In this PR:
Why was this change needed?
Templates Store PRD.
Other information (Screenshots)
Wrong-positioned nodes
Fixes
Screen.Recording.2023-05-23.at.20.29.10.mov
Screen.Recording.2023-05-23.at.20.29.42.mov