Skip to content
This repository has been archived by the owner on Jan 12, 2023. It is now read-only.

PlanWizard step 2: Initial Filter & Select VMs #21

Merged
merged 12 commits into from
Sep 11, 2020
Merged

PlanWizard step 2: Initial Filter & Select VMs #21

merged 12 commits into from
Sep 11, 2020

Conversation

gildub
Copy link
Contributor

@gildub gildub commented Sep 1, 2020

Resolves #17

@konveyor-preview-bot
Copy link

🚀 Deployed Preview: http://konveyor-virt-ui-pr-21-preview.surge.sh

package.json Outdated Show resolved Hide resolved
@gildub gildub marked this pull request as ready for review September 3, 2020 21:19
@gildub gildub requested a review from a team September 3, 2020 21:19
@gildub gildub changed the title Wizard step2 PlanWizard step 2: Initial Filter & Select VMs Sep 4, 2020
return;
};

const onCheck = (event, treeViewItem) => {
Copy link
Contributor

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?

Copy link
Collaborator

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.

Copy link
Contributor

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.

Copy link
Collaborator

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.

Copy link
Contributor

@ibolton336 ibolton336 left a comment

Choose a reason for hiding this comment

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

See comments. Thanks

Copy link
Collaborator

@mturley mturley left a 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.

src/app/Plans/components/Wizard/FilterVMs.tsx Outdated Show resolved Hide resolved
return;
};

const onCheck = (event, treeViewItem) => {
Copy link
Collaborator

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([]);
Copy link
Collaborator

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.

Copy link
Contributor

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.

Copy link
Collaborator

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 = [
Copy link
Collaborator

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)

Copy link
Collaborator

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

src/app/Plans/types.ts Outdated Show resolved Hide resolved
@mturley
Copy link
Collaborator

mturley commented Sep 8, 2020

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 VMsOptions mock data in place in that TreeViewDataItem structure, and save the creation of it based on API data for another PR. @ibolton336 thoughts?

@ibolton336
Copy link
Contributor

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 VMsOptions mock data in place in that TreeViewDataItem structure, and save the creation of it based on API data for another PR. @ibolton336 thoughts?

+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.

@vconzola
Copy link

vconzola commented Sep 8, 2020

@gildub Link to latest mockups for this step. Slides 29-31. Let me know if you have any questions.

@vconzola
Copy link

vconzola commented Sep 8, 2020

@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?

@mturley
Copy link
Collaborator

mturley commented Sep 8, 2020

@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?

@vconzola
Copy link

vconzola commented Sep 9, 2020

@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.

@mturley
Copy link
Collaborator

mturley commented Sep 9, 2020

Ah, gotcha. Sorry I missed that.
@gildub, if you add a button for that, you can add selectAll to your destructured object from useSelectionState and call it with a boolean for whether to expand all or collapse all.

@mturley
Copy link
Collaborator

mturley commented Sep 9, 2020

Ah, dammit, sorry. I was thinking this was another PR.. the tree state is a bit different. Let me take a closer look tomorrow

@mturley
Copy link
Collaborator

mturley commented Sep 9, 2020

Ok @gildub apparently I was very confused yesterday. Vince was in fact referring to the table, so my prior advice stands. You can add selectAll to your destructuring here: https://github.com/konveyor/virt-ui/pull/21/files#diff-b61187f9e8bf2d5d8a64f3f8f6dd97fbR38 and then call it in your expand/collapse-all button. You'll also want to change the icon between <AngleRightIcon /> and <AngleDownIcon /> based on areAllSelected, so add that to the destructure too (or don't destructure it like we discussed on slack).

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?

@ibolton336
Copy link
Contributor

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

@mturley
Copy link
Collaborator

mturley commented Sep 9, 2020

Ok. I opened #35, #36 and #38 to follow up on later.

@mturley
Copy link
Collaborator

mturley commented Sep 9, 2020

Since the search state is also not connected, I think we can address that as a separate issue too so we don't hold this up any longer. Opened #39 for that. We probably want to address #38 and #39 at the same time since they will involve the same traversal of the generated tree items.

@mturley
Copy link
Collaborator

mturley commented Sep 9, 2020

FYI @gildub now that #32 is merged, when you rebase this you'll need to switch your useSelectionState imports to use the lib-ui version, and in the process change the params you pass to it into an object. We should also use the new isEqual and isItemSelected parts of it as described here: https://github.com/konveyor/virt-ui/pull/32/files#r485879159

Copy link
Collaborator

@mturley mturley left a comment

Choose a reason for hiding this comment

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

One little thing

src/app/Plans/components/Wizard/FilterVMsForm.tsx Outdated Show resolved Hide resolved
Copy link
Collaborator

@mturley mturley left a 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

@mturley mturley dismissed ibolton336’s stale review September 11, 2020 16:53

Opened follow-up issues for things not addressed

@mturley mturley merged commit 89623f6 into kubev2v:master Sep 11, 2020
@gildub gildub deleted the wizard-step2 branch September 14, 2020 12:34
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Wizard VM selection step scaffolding
5 participants