-
Notifications
You must be signed in to change notification settings - Fork 30
EDM-5152: Improve fleet and device Updates step UX and copy #767
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| import * as React from 'react'; | ||
| import { Alert, FormSection } from '@patternfly/react-core'; | ||
| import { FormGroup, FormSection, Stack, StackItem } from '@patternfly/react-core'; | ||
| import { type FormikErrors, useFormikContext } from 'formik'; | ||
|
|
||
| import { useTranslation } from '../../../../hooks/useTranslation'; | ||
|
|
@@ -11,6 +11,7 @@ import UpdateStepRolloutPolicy from './UpdateStepRolloutPolicy'; | |
| import UpdateStepDisruptionBudget from './UpdateStepDisruptionBudget'; | ||
| import UpdateStepUpdatePolicy from './UpdateStepUpdatePolicy'; | ||
| import CheckboxField from '../../../form/CheckboxField'; | ||
| import RadioField from '../../../form/RadioField'; | ||
|
|
||
| import './UpdatePolicyStep.css'; | ||
|
|
||
|
|
@@ -23,60 +24,81 @@ const UpdatePolicyStep = ({ isReadOnly }: { isReadOnly: boolean }) => { | |
| const { t } = useTranslation(); | ||
|
|
||
| const { | ||
| values: { useBasicUpdateConfig, rolloutPolicy, disruptionBudget, updatePolicy }, | ||
| values: { customizeUpdates, rolloutPolicy, disruptionBudget, updatePolicy }, | ||
| } = useFormikContext<FleetFormValues>(); | ||
|
|
||
| return ( | ||
| <FlightCtlForm> | ||
| <CheckboxField name="useBasicUpdateConfig" label={t('Use basic configurations')} isDisabled={isReadOnly} /> | ||
| {!useBasicUpdateConfig ? ( | ||
| <FormSection title={t('Advanced configurations')} titleElement="h1" className="fctl-update-policy--advanced"> | ||
| {/* Rollout policies */} | ||
| <CheckboxField | ||
| name="rolloutPolicy.isAdvanced" | ||
| label={ | ||
| <LabelWithHelperText | ||
| label={t('Set rollout policies')} | ||
| content={t('Rollout policies allow you to control the order of updates for the fleet devices.')} | ||
| <Stack hasGutter> | ||
| <StackItem> | ||
| <FormGroup label={t('Update behavior')} role="radiogroup"> | ||
| <Stack hasGutter> | ||
| <RadioField | ||
| id="fleet-update-immediate" | ||
| name="customizeUpdates" | ||
| label={t('Immediate updates')} | ||
| description={t('Devices receive updates as soon as they are available.')} | ||
| checkedValue={false} | ||
| isDisabled={isReadOnly} | ||
| /> | ||
| <RadioField | ||
| id="fleet-update-customize" | ||
| name="customizeUpdates" | ||
| label={t('Customize rollout and scheduling')} | ||
| description={t('Set rollout order, disruption budget, or maintenance windows.')} | ||
| checkedValue={true} | ||
| isDisabled={isReadOnly} | ||
| /> | ||
| </Stack> | ||
| </FormGroup> | ||
| </StackItem> | ||
| {customizeUpdates && ( | ||
| <StackItem> | ||
| <FormSection title={t('Customize updates')} titleElement="h1" className="fctl-update-policy--advanced"> | ||
| {/* Rollout order */} | ||
| <CheckboxField | ||
| name="rolloutPolicy.isAdvanced" | ||
| label={ | ||
| <LabelWithHelperText | ||
| label={t('Set rollout order')} | ||
| content={t('Rollout order controls which fleet devices are updated and in what sequence.')} | ||
| /> | ||
| } | ||
| isDisabled={isReadOnly} | ||
| body={rolloutPolicy.isAdvanced && <UpdateStepRolloutPolicy isReadOnly={isReadOnly} />} | ||
| /> | ||
| } | ||
| isDisabled={isReadOnly} | ||
| body={rolloutPolicy.isAdvanced && <UpdateStepRolloutPolicy isReadOnly={isReadOnly} />} | ||
| /> | ||
|
|
||
| {/* Disruption budget */} | ||
| <CheckboxField | ||
| name="disruptionBudget.isAdvanced" | ||
| label={ | ||
| <LabelWithHelperText | ||
| label={t('Set disruption budget')} | ||
| content={t( | ||
| 'Disruption budget allows you to limit the number of similar devices that may be updating simultaneously.', | ||
| )} | ||
| {/* Disruption budget */} | ||
| <CheckboxField | ||
| name="disruptionBudget.isAdvanced" | ||
| label={ | ||
| <LabelWithHelperText | ||
| label={t('Set disruption budget')} | ||
| content={t( | ||
| 'Disruption budget allows you to limit the number of similar devices that may be updating simultaneously.', | ||
| )} | ||
| /> | ||
| } | ||
| isDisabled={isReadOnly} | ||
| body={disruptionBudget.isAdvanced && <UpdateStepDisruptionBudget isReadOnly={isReadOnly} />} | ||
| /> | ||
| } | ||
| isDisabled={isReadOnly} | ||
| body={disruptionBudget.isAdvanced && <UpdateStepDisruptionBudget isReadOnly={isReadOnly} />} | ||
| /> | ||
|
|
||
| {/* Update (and download) policies */} | ||
| <CheckboxField | ||
| name="updatePolicy.isAdvanced" | ||
| label={ | ||
| <LabelWithHelperText | ||
| label={t('Set update policies')} | ||
| content={t('Update policies allow you to control when updates should be downloaded and applied.')} | ||
| {/* Maintenance windows */} | ||
| <CheckboxField | ||
| name="updatePolicy.isAdvanced" | ||
| label={ | ||
| <LabelWithHelperText | ||
| label={t('Set maintenance windows')} | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something for UX to consider. "Maintenance windows" is not a concept that users would find in our documentation etc, For a UI user looking to expand the information on some of these concepts, using different wording could be confusing. I'll raise this as a separate team discussion. |
||
| content={t('Maintenance windows control when devices may download and install updates.')} | ||
| /> | ||
| } | ||
| isDisabled={isReadOnly} | ||
| body={updatePolicy.isAdvanced && <UpdateStepUpdatePolicy isReadOnly={isReadOnly} />} | ||
| /> | ||
| } | ||
| isDisabled={isReadOnly} | ||
| body={updatePolicy.isAdvanced && <UpdateStepUpdatePolicy isReadOnly={isReadOnly} />} | ||
| /> | ||
| </FormSection> | ||
| ) : ( | ||
| <Alert isInline variant="info" title={t('Default update policy')}> | ||
| {t('All the devices that are part of this fleet will receive updates as soon as they are available.')} | ||
| </Alert> | ||
| )} | ||
| </FormSection> | ||
| </StackItem> | ||
| )} | ||
| </Stack> | ||
| </FlightCtlForm> | ||
| ); | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,12 +7,14 @@ export interface RadioFieldProps extends Omit<RadioProps, 'onChange' | 'ref' | ' | |
| checkedValue?: unknown; | ||
| name: string; | ||
| helperText?: React.ReactNode; | ||
| description?: React.ReactNode; | ||
| onChangeCustom?: (checkedValue: unknown) => void; | ||
| noDefaultOnChange?: boolean; | ||
| } | ||
|
|
||
| const RadioField = ({ | ||
| helperText, | ||
| description, | ||
| checkedValue, | ||
| name, | ||
| onChangeCustom, | ||
|
|
@@ -31,7 +33,7 @@ const RadioField = ({ | |
| if (noDefaultOnChange) { | ||
| return; | ||
| } | ||
| await setValue(checkedValue || true, true); | ||
| await setValue(checkedValue !== undefined ? checkedValue : true, true); | ||
| await setTouched(true); | ||
| } | ||
| }; | ||
|
|
@@ -44,11 +46,12 @@ const RadioField = ({ | |
| {...field} | ||
| {...props} | ||
| id={fieldId} | ||
| description={description} | ||
| onChange={onChange} | ||
| isChecked={checkedValue ? field.value === checkedValue : !!field.value} | ||
| isChecked={checkedValue !== undefined ? field.value === checkedValue : !!field.value} | ||
| /> | ||
|
|
||
| <DefaultHelperText helperText={helperText} /> | ||
| <DefaultHelperText helperText={description ? undefined : helperText} /> | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Currently, none of the "RadioField" usages in the UI use the The I can do this as a follow-up in any case. |
||
| <ErrorHelperText meta={meta} /> | ||
| </FormGroup> | ||
| ); | ||
|
|
||
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 proposed wording is not accurate.
Eventually all the devices in the fleet will receive the updates.
Through the batches, users can control the order in which devices update. Any device that doesn't match any defined "batch", is bundled together as a last "default batch" and those devices receive the updates last.
(See the note with title "Batch sequencing":)