Skip to content
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

CNV-18014: Add Size drop down to Add volume modal #1054

Conversation

hstastna
Copy link

@hstastna hstastna commented Feb 13, 2023

📝 Description

Add missing Size dropdown to Add volume to boot from modal when creating a VM, also to Edit volume parameters (the name is going to be changed to this one in another PR) modal in the Bootable volumes list, to separate workload type and size, and so to set the appropriate InstanceType label to the selected DataSource.

This PR is related to features:
https://issues.redhat.com/browse/CNV-18014
https://issues.redhat.com/browse/CNV-15501

🎥 Demo

Before:
Edit modal in the Bootable volumes list:
bootable_before
No Size drop down in Add volume to boot from modal:
size_before

After:
Edit modal in the Bootable volumes list:
bootable_after
Size drop down in Add volume to boot from modal:
size_after
After the user has chosen Default InstanceType, the first option of possible appropriate sizes is chosen, selected in the Size drop down, because both values have to be set, if ever (then the user can change the size, of course):
type_and_size

@openshift-ci-robot
Copy link
Collaborator

@hstastna: This pull request references CNV-18014 which is a valid jira issue.

In response to this:

📝 Description

Add missing Size dropdown to Add volume to boot from modal when creating a VM, also to Edit modal in the Bootable volumes list, to separate workload type and size, and so to set an appropriate Instancetype label to the selected DataSource.

Fixes:
https://issues.redhat.com/browse/CNV-18014
https://issues.redhat.com/browse/CNV-15501

🎥 Demo

Before:
Edit modal in the Bootable volumes list:
bootable_before
No Size drop down in Add volume to boot from modal:
size_before

After:
Edit modal in the Bootable volumes list:
bootable_after
Size drop down in Add volume to boot from modal:
size_after
After Instancetype selection, user can select an appropriate size:
size2_after

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@hstastna hstastna changed the title CNV-18014: Add Size drop down to Add volume modal [WIP] CNV-18014: Add Size drop down to Add volume modal Feb 13, 2023
@openshift-ci-robot
Copy link
Collaborator

@hstastna: This pull request references CNV-18014 which is a valid jira issue.

In response to this:

📝 Description

Add missing Size dropdown to Add volume to boot from modal when creating a VM, also to Edit modal in the Bootable volumes list, to separate workload type and size, and so to set an appropriate Instancetype label to the selected DataSource.

Fixes:
https://issues.redhat.com/browse/CNV-18014
https://issues.redhat.com/browse/CNV-15501

🎥 Demo

Before:
Edit modal in the Bootable volumes list:
bootable_before
No Size drop down in Add volume to boot from modal:
size_before

After:
Edit modal in the Bootable volumes list:
bootable_after
Size drop down in Add volume to boot from modal:
size_after
After Default Instancetype selection, user can select an appropriate size:
size2_after

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@openshift-ci-robot
Copy link
Collaborator

@hstastna: This pull request references CNV-18014 which is a valid jira issue.

In response to this:

📝 Description

Add missing Size dropdown to Add volume to boot from modal when creating a VM, also to Edit modal in the Bootable volumes list, to separate workload type and size, and so to set an appropriate Instancetype label to the selected DataSource.

This PR is related to features:
https://issues.redhat.com/browse/CNV-18014
https://issues.redhat.com/browse/CNV-15501

🎥 Demo

Before:
Edit modal in the Bootable volumes list:
bootable_before
No Size drop down in Add volume to boot from modal:
size_before

After:
Edit modal in the Bootable volumes list:
bootable_after
Size drop down in Add volume to boot from modal:
size_after
After Default Instancetype selection, user can select an appropriate size:
size2_after

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@hstastna hstastna force-pushed the Add_Size_drop_down_instancetype branch 9 times, most recently from 8cfdc7d to a26edb9 Compare February 16, 2023 19:48
@openshift-ci-robot
Copy link
Collaborator

@hstastna: This pull request references CNV-18014 which is a valid jira issue.

In response to this:

📝 Description

Add missing Size dropdown to Add volume to boot from modal when creating a VM, also to Edit volume parameters (the name is going to be changed to this one in another PR) modal in the Bootable volumes list, to separate workload type and size, and so to set the appropriate InstanceType label to the selected DataSource.

This PR is related to features:
https://issues.redhat.com/browse/CNV-18014
https://issues.redhat.com/browse/CNV-15501

🎥 Demo

Before:
Edit modal in the Bootable volumes list:
bootable_before
No Size drop down in Add volume to boot from modal:
size_before

After:
Edit modal in the Bootable volumes list:
bootable_after
Size drop down in Add volume to boot from modal:
size_after
After Default Instancetype selection, user can select an appropriate size:
size2_after

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@openshift-ci-robot
Copy link
Collaborator

@hstastna: This pull request references CNV-18014 which is a valid jira issue.

In response to this:

📝 Description

Add missing Size dropdown to Add volume to boot from modal when creating a VM, also to Edit volume parameters (the name is going to be changed to this one in another PR) modal in the Bootable volumes list, to separate workload type and size, and so to set the appropriate InstanceType label to the selected DataSource.

This PR is related to features:
https://issues.redhat.com/browse/CNV-18014
https://issues.redhat.com/browse/CNV-15501

🎥 Demo

Before:
Edit modal in the Bootable volumes list:
bootable_before
No Size drop down in Add volume to boot from modal:
size_before

After:
Edit modal in the Bootable volumes list:
bootable_after
Size drop down in Add volume to boot from modal:
size_after

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@openshift-ci-robot
Copy link
Collaborator

@hstastna: This pull request references CNV-18014 which is a valid jira issue.

In response to this:

📝 Description

Add missing Size dropdown to Add volume to boot from modal when creating a VM, also to Edit volume parameters (the name is going to be changed to this one in another PR) modal in the Bootable volumes list, to separate workload type and size, and so to set the appropriate InstanceType label to the selected DataSource.

This PR is related to features:
https://issues.redhat.com/browse/CNV-18014
https://issues.redhat.com/browse/CNV-15501

🎥 Demo

Before:
Edit modal in the Bootable volumes list:
bootable_before
No Size drop down in Add volume to boot from modal:
size_before

After:
Edit modal in the Bootable volumes list:
bootable_after
Size drop down in Add volume to boot from modal:
size_after
After the user has chosen Default InstanceType, the first option of possible appropriate sizes is chosen, selected in the Size drop down, because both values have to be set, if ever (then the user can change the size, of course):
type_and_size

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@hstastna
Copy link
Author

/retest

@hstastna hstastna changed the title [WIP] CNV-18014: Add Size drop down to Add volume modal CNV-18014: Add Size drop down to Add volume modal Feb 16, 2023
@hstastna
Copy link
Author

@metalice @pcbailey @upalatucci @vojtechszocs please review

Copy link
Member

@pcbailey pcbailey left a comment

Choose a reason for hiding this comment

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

It's looking really good! I just had some minor suggestions.

const [preference, setPreference] = useState<string>(initialParams.preference);
const [instanceType, setInstanceType] = useState<string>(initialParams.instanceType);
const [size, setSize] = useState<string>(initialParams.size);
const [sizeOptions, setSizeOptions] = useState<string[]>(
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: Just for organization purposes, I would move this below the description state to keep all of the state coming from the initialParams object together. You could also use useMemo to have it automatically recalculate whenever instanceType changes instead of setting it manually.

Copy link
Author

Choose a reason for hiding this comment

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

Okay, I'll move it below the description state. But I am not sure how to combine useState with useMemo for sizeOptions (and if it ever is a good idea)... Or how did you mean that?

Copy link
Member

Choose a reason for hiding this comment

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

useMemo caches the result of a calculation and returns it on each re-render unless one of its dependencies changes. It's made specifically to watch props and state for changes.

In this case, it would look something like:

const sizeOptions = useMemo(() => instanceTypesToSizeMap[instanceType], [instanceType, instanceTypesToSizeMap]);

You could then remove the call to setSizeOptions as it would no longer be needed.

Copy link
Author

Choose a reason for hiding this comment

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

I understand what you mean, seems good to me, except that I am not sure if the Size drop down will be re-rendered accordingly, when value of instanceType changes...

Copy link
Member

Choose a reason for hiding this comment

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

When instanceType changes, the component will re-render. When it re-renders, useMemo will know that it has changed and recompute sizeOptions, which will then be passed to the dropdown causing it to re-render since its props will have changed.

Copy link
Author

@hstastna hstastna Feb 21, 2023

Choose a reason for hiding this comment

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

When instanceType changes, the component will re-render...

Yep, I understand this. I just wouldn't be so sure with anything. I'd better say "it is expected to work like that". Sometimes it doesn't work as we think. React can be tricky sometimes...
In some of my previous code versions of this, I used to update size totally the same way, according to changes of metadata (used to store everything in one object). And even when the value changed, the drop down wasn't re-rendered. Everything looked fine, useMemo was at its right place, too, it didn't work as expected anyway. I had to find some other way of implementation, and fortunately, it seems to be okay now and it DOES re-render! :)

@hstastna hstastna force-pushed the Add_Size_drop_down_instancetype branch 3 times, most recently from 0ff0e83 to 5cda6a3 Compare February 20, 2023 13:36
@@ -2,3 +2,7 @@ export type BootableVolumeMetadata = {
labels: { [key: string]: string };
annotations: { [key: string]: string };
};

export type InstanceTypesAndSizesMapType = {
Copy link
Member

Choose a reason for hiding this comment

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

This name is better, but it's still not as clear as it could be. I did a search for map naming conventions and saw several recommendations for <value type>By<key type>, which I think is very clear since it explains what you're getting and what you're passing to get it. It's also more compact.

So, the type here would be SizesByInstanceType and the map/object name would be sizesByInstanceType, which I think works nicely. What do you think? I'm fine with either that or InstanceTypesToSizes/InstanceTypesToSizesMap.

Copy link
Author

@hstastna hstastna Feb 20, 2023

Choose a reason for hiding this comment

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

I would not use "To" substring in the naming because IMO it is misleading, from the other point of view: we don't convert/change anything to size, size is part of the string/whole information we are dealing with. We just divide the whole label's string in here, and then deal with that some way we need later, but still with the whole information, not with just part of it.

Another note from me is that I don't think it's always good to follow some conventions/general recommendations. IMO readability of the code for a programmer has a higher priority to me (can save a lot of time later etc), and in this case the suggested naming is less clear or self explaining than the original one, when looking at other names and objects in the project.

Anyway, let me reconsider the naming, then I'll update the PR accordingly.

Copy link
Member

Choose a reason for hiding this comment

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

From what I can tell here, you're taking InstanceType codes such as c4.xlarge and breaking them down into the InstanceType name shorthand (c4) and the size (xlarge). You're then creating a mapping, like below. Correct me if I'm wrong. Perhaps I'm simply misunderstanding what the code is doing here.

const map = {
  c4: [xlarge,...],
  ...
}

If the above example is correct, "To" is a much more accurate term than "and" for this use case. A map connects the values to the keys by mapping the key TO the value. Using "and" implies a group of InstanceTypes and sizes together in one group/array, which is incorrect. Once you access the map using an InstanceType shorthand name, you only get the sizes for that InstanceType category, not a list of sizes AND InstanceType names.

I completely agree that readability is paramount. Conventions typically exist to improve readability not hinder it. I don't see how "XWithY" is clearer than "XtoYMap"/"XToY" or "YByX". I have no idea what "with" is supposed to mean in this instance.

In any case, "Type" shouldn't be used in the name.

Copy link
Author

Choose a reason for hiding this comment

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

In any case, "Type" shouldn't be used in the name.

I mostly agree, but not 100%. IMO, it depends on a situation...

Anyway, we don't have much time, so can you please check the actual version of the code? I think you are still looking at some old version of the code. It was updated :)

Copy link
Member

Choose a reason for hiding this comment

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

Weird. I refreshed last night before commenting.

// eslint-disable-next-line prefer-const
let instanceTypesAndSizes: InstanceTypesAndSizesObject = {};

instanceTypesNames.forEach((instanceType) => {
Copy link
Member

Choose a reason for hiding this comment

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

I'm a huge advocate for readability and I can't see an impact to readability here unless the programmer doesn't understand what reduce does, which would be odd for a JavaScript programmer.

In this case, the logic in the body wouldn't really change at all, but it would prevent the requirement for creating an object externally and using side effects from the loop to populate it.

const sizesByInstanceType: SizesByInstanceType = instanceTypeNames.reduce((instanceTypesToSizesMap, instanceType) => {
  const [instanceTypeName, size] = instanceType.split('.');

  instanceTypesToSizesMap[instanceTypeName] !== undefined
    ? instanceTypesToSizesMap[instanceTypeName].push(size)
    : (instanceTypesToSizesMap[instanceTypeName] = [size]);
  });
  
  return instanceTypesToSizesMap;
}, {});

@hstastna hstastna force-pushed the Add_Size_drop_down_instancetype branch from 5cda6a3 to 394239c Compare February 20, 2023 16:45
Add missing Size dropdown to 'Add volume to boot from' modal
when creating a VM, also to 'Edit volume parameters' modal
in the Bootable volumes list, to separate workload type and size,
and so to set the appropriate Instancetype label to the selected
DataSource.

Fixes https://issues.redhat.com/browse/CNV-18014,
https://issues.redhat.com/browse/CNV-15501
@hstastna hstastna force-pushed the Add_Size_drop_down_instancetype branch from 394239c to 4efcbd3 Compare February 20, 2023 17:49
@hstastna hstastna requested review from pcbailey and removed request for yaacov February 21, 2023 14:29
@pcbailey
Copy link
Member

/lgtm

@openshift-ci openshift-ci bot added the lgtm Passed code review, ready for merge label Feb 21, 2023
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 21, 2023

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: hstastna, pcbailey

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved This issue is something we want to fix label Feb 21, 2023
@openshift-merge-robot openshift-merge-robot merged commit e97e7f0 into kubevirt-ui:main Feb 21, 2023
instanceTypesNames.reduce((instanceTypesAndSizes, instanceType) => {
const [instanceTypePart, sizePart] = instanceType.split('.');

instanceTypesAndSizes[instanceTypePart] !== undefined
Copy link
Contributor

Choose a reason for hiding this comment

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

This code could be simplified like so:

instanceTypesAndSizes[instanceTypePart] ??= [];
instanceTypesAndSizes[instanceTypePart].push(sizePart);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_assignment

setSize(instanceTypesToSizesMap[instanceTypeName][0]);
};

const onChangeVolumeParams = () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a note, any functions passed to React components as props (e.g. callbacks) should be referentially stable across re-renders. Otherwise, you're creating a new function instance on every render here, passing it to other React components and causing re-render of these components.

This can be done via React.useCallback hook https://reactjs.org/docs/hooks-reference.html#usecallback

On the other hand, the extra re-renders aren't normally a big issue, so developers may opt into not doing this.

Copy link
Author

Choose a reason for hiding this comment

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

React.useCallback was added in some of the followup PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved This issue is something we want to fix lgtm Passed code review, ready for merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants