-
Notifications
You must be signed in to change notification settings - Fork 113
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
[KED-2770] - Expose related dataset nodes for focus mode flowchart #530
Conversation
… of node type IDs listed in the state
…ated nested list item error on console
… along with count for listed results
…within node-list-items
src/selectors/nodes.test.js
Outdated
@@ -370,4 +376,17 @@ describe('Selectors', () => { | |||
expect(Object.keys(nodesWithInputParams)).toEqual(parameterNodesID); | |||
}); | |||
}); | |||
|
|||
describe('getInputOutputDataNodes', () => { | |||
it('includes input output ndoes related to a modular pipeline in the returned object', () => { |
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.
typo - nodes
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.
Suggestion: You can use github suggestion to suggest changes for these small issues like this:
it('includes input output ndoes related to a modular pipeline in the returned object', () => { | |
it('includes input output nodes related to a modular pipeline in the returned object', () => { |
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.
Thanks both - great spot! I've updated the typo in my latest commit
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 PR is 🔥 Everything seems very clear to me. Amazing work @studioswong Just a few minor nitpicks.
I will do a bit more testing but the code looks good to me.
src/components/flowchart/draw.js
Outdated
if (changed('edges')) { | ||
enterEdges | ||
.append('path') | ||
if (changed('edges', 'newParamsFlag', 'focusMode', 'inputOutputDataNodes')) { |
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.
qq: do you think we should remove newParamsFlag
from this PR since its removal has already been merged? Or should that be a follow up PR?
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 can remove this in this PR :) thanks for the reminder!
src/components/flowchart/draw.js
Outdated
.attr('marker-end', (edge) => | ||
edge.sourceNode.type === 'parameters' | ||
? `url(#pipeline-arrowhead--accent)` | ||
? focusMode !== null && inputOutputDataEdges[edge.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.
nit: I think giving focusMode !== null && inputOutputDataEdges[edge.id]
a name might help with this block as it's repeated twice in this nested tenary operator. You can also reuse that variable further down as well.
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.
sounds good, I'll extract that out.
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.
Yeah agreed nested ternary ends up being pretty difficult to follow, so it's a probably a good idea to split this one up e.g. some variables / string templates, if that makes sense
src/components/flowchart/draw.js
Outdated
(edge) => edge.sourceNode.type === 'parameters' | ||
(edge) => | ||
edge.sourceNode.type === 'parameters' && | ||
!inputOutputDataEdges[edge.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.
Sorry I don't understand why this condition !inputOutputDataEdges[edge.id]
is needed here. Is it to fix the problem you identified the other day?
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 condition is needed to prevent applying this class to parameter nodes that are also input/output nodes - if this check is not applied this will create potential conflicts with the css class that will be applied to parameter nodes that are part of input/output. ( i.e taking this check out will result in some input/output parameter nodes not adopting the pipeline-edge--parameters--input
class. )
); | ||
}); | ||
|
||
it('applies pipeline-edge--data--input class to input dataset edges under focus mode', () => { |
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.
Nit: shouldn't this modifier be named as pipeline-edge--dataset--input
to be consistent with pipeline-node--dataset-input
(or the other way around)? Same comment about pipeline-edge--parameters--input
and pipeline-node--parameter-input
(although I have a feeling this naming is intentional because pipeline-edge might have more than 1 parameters, right?)
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.
sure, I can rename this as pipeline-edge--dataset--input
to align this with the naming for the input nodes css class
@@ -361,6 +415,9 @@ describe('FlowChart', () => { | |||
visibleSidebar: expect.any(Boolean), | |||
visibleCode: expect.any(Boolean), | |||
visibleMetaSidebar: expect.any(Boolean), | |||
inputOutputDataNodes: expect.any(Object), | |||
inputOutputDataEdges: expect.any(Object), | |||
focusMode: expect.any(Object), |
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 set of tests is awesome. Very clear!!! 🏆
src/selectors/disabled.js
Outdated
return true; | ||
|
||
// Hide nodes that don't have at least one modular pipeline filter enabled | ||
return !isNodeOfActiveModularPipeline( |
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 seems duplicated with the earlier if
check. Should we short circuit by moving it up instead?
if (!isNodeOfActiveModularPipeline(
nodeModularPipelines,
nodeID,
modularPipelineEnabled
) || (nodeType[nodeID] === 'task') {
return false;
}
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.
Thanks for the suggestions - I had a look into this, and while the arrangement of the returned statement would stand as is (i.e we still need to return the result of the check and this cannot be combined with the check for the task node), I had extracted the check for isNodeOfActiveModularPipeline
out to a variable so the check will not be duplicated and allows more readability. I had also added further comments to explain the exceptions that the if
statements filters out before returning the result of this check as the final returned value. Hopefully this will be more clear and the reason behind this arranhement would be more apparent to you.
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.
Hi Susanna, Great work! it work's well for me!
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.
Works really nicely! Great stuff 👏
Still a bit more for me to check out, but for now I've left some suggestions if you're interested, mostly around simplifying a few parts, if it makes sense.
src/components/flowchart/draw.js
Outdated
.attr('marker-end', (edge) => | ||
edge.sourceNode.type === 'parameters' | ||
? `url(#pipeline-arrowhead--accent)` | ||
? focusMode !== null && inputOutputDataEdges[edge.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.
Yeah agreed nested ternary ends up being pretty difficult to follow, so it's a probably a good idea to split this one up e.g. some variables / string templates, if that makes sense
src/components/flowchart/draw.js
Outdated
!inputOutputDataEdges[edge.id] | ||
) | ||
.classed( | ||
'pipeline-edge--parameters--input', |
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.
Just to check since there's two --
in this classname is that to say there are two independent modifiers here? If so maybe consider splitting into two classnames I think to get more flexibility?
src/components/node-list/index.js
Outdated
@@ -69,7 +79,13 @@ const NodeListProvider = ({ | |||
if (isGroupType(item.type) || isModularPipelineType(item.type)) { | |||
onGroupItemChange(item, item.checked); | |||
if (isModularPipelineType(item.type)) { | |||
onToggleFocusMode(item); | |||
if (isModularPipelineType(item.type)) { |
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 like this check might have been duplicated accidentally here?
@@ -84,7 +100,11 @@ const NodeListProvider = ({ | |||
if (isGroupType(item.type) || isModularPipelineType(item.type)) { |
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.
Thinking it might be a good idea at this point to split this into two separate blocks, to help avoid some nesting if possible?
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 had a look at this, and given that both conditions calls onGroupItemChange(item, checked);
, I think it is still better to combine that into a single if statement. The nesting is still readable, and I would rather avoid duplicate code.
@@ -269,14 +274,16 @@ export const getFilteredNodeItems = createSelector( | |||
const disabled = | |||
node.disabled_tag || | |||
node.disabled_type || | |||
node.disabled_modularPipeline; | |||
node.disabled_modularPipeline || | |||
(focusMode !== null && !!inputOutputDataNodes[node.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.
I guess focusMode && inputOutputDataNodes[node.id]
can maybe be ok here (unless 0
is truthy for this)?
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 am glad you raised this question - I am using !!inputOutputDataNodes[node.id]
to force disabled
to return a boolean value under this check. If we use inputOutputDataNodes[node.id]
the check will return an error. ( you can also verify this by trying this out, and you will see what I meant ).
@@ -42,6 +42,10 @@ | |||
height: $row-icon-size; | |||
fill: var(--color-text); | |||
|
|||
&.pipeline-row__toggle-icon--focus-checked{ |
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.
Might just need a space adding near the end here
src/selectors/disabled.js
Outdated
/** | ||
* Calculate whether nodes should be disabled based on their modular pipelines | ||
* Calculate whether nodes should be disabled based on their modular pipelines, | ||
* except related dataset nodes and |
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.
Maybe the comment got a bit cut off at the end here?
nodeID, | ||
modularPipelineEnabled | ||
) && | ||
(nodeType[nodeID] === 'parameters' || nodeType[nodeID] === 'data') |
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 isNodeOfActiveModularPipeline
might get a little expensive, then could be a good idea to move these simpler conditions to be checked first, to help reduce the cost?
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've refactored this check into a separate constant variable - please see my latest commit
@@ -48,10 +66,17 @@ export const getTransitiveEdges = createSelector( | |||
return; | |||
} | |||
const target = edgeTargets[edgeID]; | |||
|
|||
// Further filter out connections between indicative input / output nodes under focus mode | |||
const isNotInputEdge = |
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.
Wondering if it's worth considering flipping this to the positive e.g. isInputEdge
to help simplify the condition (unless it's a performance thing I suppose?)
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.
It is a performance thing as checking isNotInputEdge
is more straight forward and has less cases rather than the positive situation ( this is apparent if you read through the condition - checking for isInputEdge has much more possibility rather than checking for isNotInputEdge
. )
Furthermore, I don't really see the upside of the refactor work for flipping this to positive?
if (focusedModularPipeline !== null) { | ||
visibleEdges.forEach((edge) => { | ||
if ( | ||
!nodeModularPipelines[edge.source]?.includes( |
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.
Might be worth considering breaking out the conditions here into constants?
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 check is only used once in this selector, moreover with it being very straight forward, I believe this is fine for this to stay as is.
Thanks all for the comments! I've gone through all your comments and made the suggested changes. |
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.
/
Description
related ticket: https://jira.quantumblack.com/browse/KED-2770
This is the work to expose the related input and output nodes and display them with a dotted outline and edges. ( see below). Those nodes are displayed for indicative purposes only, where all typical click interations for nodes on the flowchart and sidebar will remain disabled for those input and output nodes.
Development notes
The main changes to enable this feature includes:
getNodeDisabledModularPipeline
selector so that it will check for input and output nodes related to the selected modular pipeline and enable that nodefocusMode
state from a local state to a global state value stored under thevisible
propI have also added in some minor refactor of the focus mode icon.
Please note that, due to the latest decision of removing the newparams flag, I have removed all considerations of styling for when
newparams
flag is off ( i.e old version of parameters).QA notes
Please play around with the focus mode and toggle between filters to test the display of those input / output nodes.
Checklist
RELEASE.md
fileLegal notice
I acknowledge and agree that, by checking this box and clicking "Submit Pull Request":
I submit this contribution under the Apache 2.0 license and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable.
I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorised to submit this contribution on behalf of the original creator(s) or their licensees.
I certify that the use of this contribution as authorised by the Apache 2.0 license does not violate the intellectual property rights of anyone else.