-
Notifications
You must be signed in to change notification settings - Fork 293
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
Fixes #36295 - Auto activation key selection if there's only one #10518
Conversation
Can one of the admins verify this patch? |
Issues: #36295 |
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 @girijaasoni !
|
||
|
||
useEffect(() => { | ||
if(activationKeys.length==1){ |
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(activationKeys.length==1){ | |
if (activationKeys.length === 1) { |
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.
@girijaasoni npm run lint -- --fix
is your friend
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 @stejskalleos
|
||
useEffect(() => { | ||
if(activationKeys.length==1){ | ||
onChange({ activationKeys: [activationKeys[0]?.name]}) |
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 you could reuse the onSelect
function above instead by passing the value of the activation key?
if(activationKeys.length==1){ | ||
onChange({ activationKeys: [activationKeys[0]?.name]}) | ||
} | ||
}, [activationKeys]); |
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.
we should avoid objects/arrays as dependencies: https://dmitripavlutin.com/react-useeffect-infinite-loop/#21-avoid-objects-as-dependencies
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 @Ron-Lavi
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.
Two nits, otherwise code looks good, but haven't tested it yet.
@@ -38,10 +38,16 @@ const ActivationKeys = ({ | |||
}; | |||
|
|||
// Validate field when hostgroup is changed (host group may have some keys) | |||
useEffect(() => { | |||
useEffect(() => { |
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: Trailing space, check the configuration of VS code, Trim Trailing Whitespace
should be enabled by default if I am not mistaken
handleInvalidField('Activation Keys', akHasValidValue(hostGroupId, pluginValues?.activationKeys, hostGroupActivationKeys)); | ||
}, [handleInvalidField, hostGroupId, hostGroupActivationKeys, pluginValues]); | ||
|
||
useEffect(() => { | ||
if (activationKeys?.length === 1) { | ||
updatePluginValues([activationKeys[0]?.name]); |
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 activationKeys
is not empty, we can safely assume that the key has a name attribute:
updatePluginValues([activationKeys[0].name]);
@@ -88,7 +94,7 @@ ActivationKeys.propTypes = { | |||
}; | |||
|
|||
ActivationKeys.defaultProps = { | |||
activationKeys: undefined, | |||
activationKeys: [], |
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.
activationKeys is set to "[]" in the useEffect of indexJs
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 know, but it was supposed to be []
from the beginning ...
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.
undefined
is for first form load so the field is not marked as invalid
@@ -88,7 +94,7 @@ ActivationKeys.propTypes = { | |||
}; | |||
|
|||
ActivationKeys.defaultProps = { | |||
activationKeys: undefined, | |||
activationKeys: [], |
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.
activationKeys is set to "[]" in the useEffect of indexJs
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.
Nice work @girijaasoni !
-
When there is only one activation key available during host registration, the Activation Key is automatically selected.
-
When multiple activation keys are available during host registration, the Activation Key is not automatically selected.
-
The auto-selection of the Activation Key does not interfere with the ability to manually select or deselect the option.
-
There's a warning alert shown initially when user's have multiple AK (not sure if you are going to address it in this PR):
That is done in the foreman pr which blocks this pr theforeman/foreman#9688 |
return ( | ||
<FormGroup | ||
label={__('Activation Keys')} | ||
fieldId="reg_katello_ak" | ||
helperText={hostGroupActivationKeys && sprintf('From host group: %s', hostGroupActivationKeys)} | ||
helperTextInvalid={activationKeys?.length === 0 ? <a href="/activation_keys/new">{__('Create new activation key')}</a> : __('No Activation Keys selected')} | ||
validated={validateAKField(hostGroupId, pluginValues?.activationKeys, hostGroupActivationKeys)} | ||
helperTextInvalidIcon={<ExclamationCircleIcon />} |
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.
Not sure if we should remove the {activationKeys?.length === 0 ? <a href="/activation_keys/new">{__('Create new activation key')}</a>
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 remove 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.
I don't see the "Create new activation key" link any more. I see no reason to remove it; can you please put it back?
if (activationKeys?.length === 1) { | ||
updatePluginValues([activationKeys[0].name]); | ||
} | ||
}, [activationKeys?.length]); |
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.
not entirely against using optional chaining (?.)
though proptypes should protect us in this case and we can expect it to be an array,
I think we would be ok not using it in this case
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.
Optional chaining is required for the case when activationKeys
is undefined
(on form load)
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 nit about PropTypes
otherwise works fine.
@@ -88,7 +94,7 @@ ActivationKeys.propTypes = { | |||
}; | |||
|
|||
ActivationKeys.defaultProps = { | |||
activationKeys: undefined, | |||
activationKeys: [], |
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.
undefined
is for first form load so the field is not marked as invalid
@@ -73,7 +73,7 @@ export const RegistrationActivationKeys = ({ | |||
isLoading, | |||
}) => { | |||
useEffect(() => { | |||
onChange({ activationKeys: [] }); | |||
onChange({ activationKeys: undefined }); |
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.
PropTypes.oneOfType([PropTypes.undefined, PropTypes.array])
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.
imho it's not a best practice to pass the value as undefined
if we are doing this in order to hide/display proper error on the field, e.g:
hide the error when the user opens the page,
and show it upon interaction with the field,
I propose to add a const [ wasInteracted, setInteraction ] = useState(false)
and then use the wasInteracted
in the right places.
This should give us more control over what we are trying to achieve.
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'm not against it, it makes sense, just didn't know that it's a bad practice.
@jeremylenz @MariaAga How do you handle touched / untouched form fields in React components?
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 used onBlur={() => setWasFocus(true)
here: theforeman/foreman_remote_execution#784
c1f4c4a
to
38409df
Compare
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.
@girijaasoni snapshot test is failing, could you update it?
npm test -- -u
2f87ffd
to
ecc90cb
Compare
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 @girijaasoni, I left a couple code comments below :)
useEffect(() => { | ||
if (activationKeys?.length === 1) { | ||
updatePluginValues([activationKeys[0].name]); | ||
} | ||
if (activationKeys?.length === 0) { | ||
setHasInteraction(true); | ||
} | ||
}, [activationKeys?.length]); |
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.
In general, setting state in effects should be avoided if possible.
Rather, setting state in event handlers is much better. For hasInteraction
, I think we can achieve the same thing by adding an onFocus
to the <FormGroup>
:
<FormGroup
onFocus={() => setHasInteraction(true)}
And for the pluginValues
, I would strongly prefer if that could be updated outside an effect as well, but it seems slot and fill makes that too difficult. So I'm ok with keeping that part.
Either way, this is really good reading: https://react.dev/learn/you-might-not-need-an-effect
useEffect(() => { | ||
if (activationKeys?.length === 1) { | ||
updatePluginValues([activationKeys[0].name]); | ||
} | ||
if (activationKeys?.length === 0) { | ||
setHasInteraction(true); | ||
} | ||
}, [activationKeys?.length]); |
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.
However this effect ends up, the dependency array needs to be correct :)
hostGroupActivationKeys: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.array, | ||
]), | ||
hostGroupId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | ||
pluginValues: PropTypes.objectOf(PropTypes.shape({})), |
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 got this console error; seems like this needs an update:
Warning: Failed prop type: Invalid prop `pluginValues.activationKeys` of type `array` supplied to `ActivationKeys`, expected `object`
@girijaasoni any update here? This is still on our review board. |
Since it was for 6.15, I paused the work on it, back on it now again :D |
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 useEffect code is looking much better and the page is mostly working well! 👍 Just a couple more minor comments below.
@@ -2,7 +2,7 @@ | |||
|
|||
exports[`ActivationKeys renders 1`] = ` | |||
<FormGroup | |||
fieldId="activation_keys_field" | |||
fieldId="reg_katello_ak" |
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 thought QE wanted us to remove "katello" from these? Or did I have that switched around?
} | ||
helperTextInvalidIcon={<ExclamationCircleIcon />} | ||
labelIcon={ | ||
<LabelIcon text={__('Activation key(s) for Subscription Manager.')} /> |
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.
Since subscription-manager is going away at some point, this might be a good time to update the wording here.
<LabelIcon text={__('Activation key(s) for Subscription Manager.')} /> | |
<LabelIcon text={__('Activation key(s) to use during registration.')} /> |
return ( | ||
<FormGroup | ||
label={__('Activation Keys')} | ||
fieldId="reg_katello_ak" | ||
helperText={hostGroupActivationKeys && sprintf('From host group: %s', hostGroupActivationKeys)} | ||
helperTextInvalid={activationKeys?.length === 0 ? <a href="/activation_keys/new">{__('Create new activation key')}</a> : __('No Activation Keys selected')} | ||
validated={validateAKField(hostGroupId, pluginValues?.activationKeys, hostGroupActivationKeys)} | ||
helperTextInvalidIcon={<ExclamationCircleIcon />} |
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 don't see the "Create new activation key" link any more. I see no reason to remove it; can you please put it back?
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.
Tested all three scenarios
✔️ No AKs available
✔️ Only one AK
✔️ Multiple AKs
All works great. Nice work! APJ 👍
[test katello] |
Test failures unrelated |
@girijaasoni If you rebase to current master the test failures should go away now :) |
[test katello] |
1 similar comment
[test katello] |
This PR is blocked by Foreman PR:
theforeman/foreman#9688
This PR has changes t
o auto select an activation key when there's just one and to remove the "No activation key selected error" on User's arrival to the register form. This pr also has better validation formatting like the exclamation icon on the left of carter and underline on the Select dropdown when there's an error! Screenshots of the changes are attached below: