-
Notifications
You must be signed in to change notification settings - Fork 27
PlanWizard step 2: Initial Filter & Select VMs #21
Conversation
🚀 Deployed Preview: http://konveyor-virt-ui-pr-21-preview.surge.sh ✨ |
return; | ||
}; | ||
|
||
const onCheck = (event, treeViewItem) => { |
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.
Is this a potential use case for a reusable hook?
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.
Hmm, maybe. We need to address a problem with it though, we shouldn't be mutating state in-place. All state mutations should be done via setItems
or setCheckedItems
or whatever we have for state setters. treeViewItem.checkProps.checked = checked;
does not guarantee a re-render.
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.
Good point - we need to make sure we are operating in a way that is react friendly.
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.
@gildub let's make this onCheck
function a no-op for now, I don't want to leave the imperative mutation here just in case we forget about it.
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.
See comments. Thanks
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.
@gildub, let me know if my feedback about the VMsOptions
/ TreeViewDataItem
objects makes sense. Basically, I don't think we should be storing those in state at all. They're a render implementation detail. The only state we actually change is which items are selected, so let's just keep that in state.
Then, we can create an immutable set of TreeViewDataItems with checked: false
on each item by traversing the API data, and then map over that to create a copy of that data with each of the checked
booleans can be based on the checkedItems
state array.
In order to represent the parent items being checked if the children are all checked, we can use helpers in that map to recursively look at the children when determining each checked
value. See the areAllDescendantsChecked
and areSomeDescendantsChecked
helpers in this JSX example in the docs: https://www.patternfly.org/v4/documentation/react/components/treeview#with-checkboxes
, they use the checkedItems
array to check ids of the whole subtree. See the this.mapTree
method in those docs for an example of how to map over the tree and add the right checked
values.
So we could do something like this, assuming we have datacenters
API data in scope:
const baseOptions: TreeViewDataItem[] = [
{
name: 'All datacenters',
id: 'all',
checkProps: { 'aria-label': 'all-check', checked: false },
children: datacenters.map((datacenter) => ({
// Whatever we need here based on the API data structure
name: datacenter.metadata.name,
id: datacenter.id
checkProps: { 'aria-label': `${datacenter.metadata.name}-check`, checked: false },
children: ... // Another map... probably we'd refactor that into a helper we can use recursively
}),
},
]
And then possibly in the next PR when we add the checkbox state, we can do:
const options = baseOptions.map((option) => ({
...option,
checkProps: { ...option.checkProps, checked: areAllDescendantsChecked(option) },
children: ... // Again, map over the children recursively, so this all should probably be a helper function
});
And in fact, for checkedItems
we could use the useSelectionState
hook I wrote to manage adding and removing items to it instead of useState
directly. https://konveyor.github.io/lib-ui/?path=/docs/hooks-useselectionstate--checkboxes
As you can see I'm coming up with this as I go, I just confused myself a little bit, let me know if you want me to try and hack this together myself as a followup PR. My point is that we should get rid of your onCheck
for now, and we shouldn't keep these options in state. Let's at least make those changes in this PR and then handle the second checked
map call in another PR.
return; | ||
}; | ||
|
||
const onCheck = (event, treeViewItem) => { |
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.
Hmm, maybe. We need to address a problem with it though, we shouldn't be mutating state in-place. All state mutations should be done via setItems
or setCheckedItems
or whatever we have for state setters. treeViewItem.checkProps.checked = checked;
does not guarantee a re-render.
|
||
const FilterVMs: React.FunctionComponent<IFilterVMsProps> = ({ Inventory }: IFilterVMsProps) => { | ||
const [activeItems, setItems] = React.useState(VMsOptions); | ||
const [checkedItems, setCheckedItems] = React.useState([]); |
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, I notice you don't use setCheckedItems
here at all, we should be using it instead of setItems
and creating a const items
array here by mapping over the underlying data and using checkedItems
in that map to determine the checkProps.checked
value.
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.
@gildub Can we add a comment and an issue link for this work? Thx.
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 opened #38 for it, but we may want to add a comment there too.
@@ -0,0 +1,146 @@ | |||
import { IVMs } from '../../../types'; | |||
|
|||
export const VMsOptions = [ |
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.
As mentioned above, instead of putting the tree view item structure in here, let's put mock data in here of datacenters and clusters and folders the way we expect them to be in the API. Here is an example you can look at in Jeff's demo API server: https://inventory-openshift-migration.apps.cluster-jortel.v2v.bos.redhat.com/namespaces/openshift-migration/providers/vsphere/test/tree/vm (requires VPN)
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.
Actually let's talk on Slack about this, Jeff is telling me that might not make sense:
The datacenters/clusters/folders are not the same tree.
it's either datacenter/clusters (by folder)
or
datacenter/folders/vms
Sorry for all the thinking-out-loud, guys. The more I think about this and discuss the data structure with Jeff, the more I think maybe we should leave this PR with the |
+1 I agree - lets open an issue for that & implement in a separate PR. But the rest of the comments should be easy enough to address I think. |
@mturley One thing I show in the mockups that I'd like to include if it's not too much work is the ability to expand all of the VMs table rows with a single click. Possible? What do you think? |
@vconzola Yeah, that's easy with my state abstraction :) it's the same code that drives our checkboxes, so it already has a "select all" function. Where should the button go? |
@mturley Nice! I'd like it to be as shown in the mockups. Caret icon (https://fontawesome.com/icons/caret-square-right?style=regular) in the table toolbar that changes to caret down when it's selected and expands all of the rows. |
Ah, gotcha. Sorry I missed that. |
Ah, dammit, sorry. I was thinking this was another PR.. the tree state is a bit different. Let me take a closer look tomorrow |
Ok @gildub apparently I was very confused yesterday. Vince was in fact referring to the table, so my prior advice stands. You can add As for how to render the expand-all button in the header of the expand-caret column that is generated by Table... hm. Dammit, maybe that needs a PF change as well. @ibolton336 what do you say we handle that as a separate issue as well? |
I am on board with that @mturley |
FYI @gildub now that #32 is merged, when you rebase this you'll need to switch your |
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.
One little thing
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.
LGTM for now, @ibolton336 I think we can address any other nitpicks as we move forward with the followup issues
Opened follow-up issues for things not addressed
Resolves #17