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

Bug 1828993: Affinity Modal needs refinement #5249

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
.affinity-modal__add-btn {
padding: var(--pf-global--spacer--xl);
}

.affinity-modal__desc-container {
display: flex;
flex-direction: column;
margin-bottom: var(--pf-global--spacer--md);

.affinity-modal__desc {
color: var(--pf-global--Color--200);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@ import {
HandlePromiseProps,
FirehoseResult,
} from '@console/internal/components/utils';
import { Button, ButtonVariant, Split, SplitItem } from '@patternfly/react-core';
import {
Button,
ButtonVariant,
Split,
SplitItem,
Text,
TextVariants,
EmptyState,
EmptyStateVariant,
Title,
EmptyStateBody,
} from '@patternfly/react-core';
import { ModalTitle, ModalBody, ModalComponentProps } from '@console/internal/components/factory';
import { NodeModel } from '@console/internal/models';
import { K8sResourceKind, k8sPatch } from '@console/internal/module/k8s';
Expand Down Expand Up @@ -132,9 +143,9 @@ export const AffinityModal = withHandlePromise<AffinityModalProps>(
</SplitItem>
<SplitItem isFilled />
<SplitItem className="affinity-modal__add-btn">
{!isEditing && (
{!isEditing && affinities.length > 0 && (
<Button onClick={() => onAffinityClickAdd()} variant="secondary">
Add Affinity
Add Affinity rule
</Button>
)}
</SplitItem>
Expand All @@ -149,17 +160,68 @@ export const AffinityModal = withHandlePromise<AffinityModalProps>(
) : (
<>
<ModalBody>
<AffinityTable
columnClasses={columnClasses}
data={affinities}
customData={{
isDisabled: false,
vmLikeFinal,
onEdit: onAffinityClickEdit,
onDelete: onAffinityDelete,
}}
row={AffinityRow}
/>
{affinities.length > 0 && (
<div className="affinity-modal__desc-container">
<Text className="affinity-modal__desc" component={TextVariants.small}>
{
'Set scheduling requirements and affect the ranking of the nodes candidate for scheduling.'
}
</Text>
<Text className="affinity-modal__desc" component={TextVariants.small}>
{
"Rules with 'Preferred' condition will stack with an 'AND' relation between them."
}
</Text>

<Text className="affinity-modal__desc" component={TextVariants.small}>
{
"Rules with 'Required' condition will stack with an 'OR' relation between them."
}
</Text>
</div>
)}
{affinities.length > 0 ? (
<AffinityTable
columnClasses={columnClasses}
data={affinities}
customData={{
isDisabled: false,
vmLikeFinal,
onEdit: onAffinityClickEdit,
onDelete: onAffinityDelete,
}}
row={AffinityRow}
/>
) : (
<EmptyState variant={EmptyStateVariant.full}>
<Title headingLevel="h5" size="lg">
No Affinity rules found
</Title>
<EmptyStateBody>
<div className="affinity-modal__desc-container">
<Text className="affinity-modal__desc" component={TextVariants.small}>
{
'Set scheduling requirements and affect the ranking of the nodes candidate for scheduling.'
}
</Text>
<Text className="affinity-modal__desc" component={TextVariants.small}>
{
"Rules with 'Preferred' condition will stack with an 'AND' relation between them."
}
</Text>

<Text className="affinity-modal__desc" component={TextVariants.small}>
{
"Rules with 'Required' condition will stack with an 'OR' relation between them."
}
</Text>
</div>
</EmptyStateBody>
<Button variant="secondary" onClick={() => onAffinityClickAdd()}>
Add Affinity rule
</Button>
</EmptyState>
)}
</ModalBody>
<ModalFooter
id="affinity"
Expand All @@ -169,7 +231,7 @@ export const AffinityModal = withHandlePromise<AffinityModalProps>(
isSimpleError={!!loadError}
onSubmit={submit}
onCancel={onCancel}
submitButtonText={'Apply'}
submitButtonText={'Save'}
infoTitle={showCollisionAlert && 'Affinity has been updated outside this flow.'}
infoMessage={
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import * as React from 'react';
import { Form, FormSelect, FormSelectOption, TextInput, Divider } from '@patternfly/react-core';
import {
Form,
FormSelect,
FormSelectOption,
TextInput,
Divider,
Text,
TextVariants,
} from '@patternfly/react-core';
import { FirehoseResult } from '@console/internal/components/utils';
import { K8sResourceKind } from '@console/internal/module/k8s';
import { ModalBody } from '@console/internal/components/factory';
Expand Down Expand Up @@ -75,17 +83,20 @@ export const AffinityEdit: React.FC<AffinityEditProps> = ({
return (
<>
<ModalBody>
<div className="affinity-modal__desc-container">
<Text className="affinity-modal__desc" component={TextVariants.small}>
{
'Define an affinity rule. This rule will be added to the list of affinity rules applied to this workload.'
}
</Text>
</div>
<Form>
<FormRow title="Type" fieldId={'affinity-type'} isRequired>
<FormSelect
onChange={(value) =>
setFocusedAffinity({
...focusedAffinity,
type: value as AffinityRowData['type'],
condition:
value === 'nodeAffinity'
? AFFINITY_CONDITIONS.preferred
: focusedAffinity.condition,
})
}
value={focusedAffinity.type}
Expand Down Expand Up @@ -124,7 +135,6 @@ export const AffinityEdit: React.FC<AffinityEditProps> = ({
key={AFFINITY_CONDITIONS.required}
value={AFFINITY_CONDITIONS.required}
label={AFFINITY_CONDITION_LABELS[AFFINITY_CONDITIONS.required]}
isDisabled={isDisabled}
/>
</FormSelect>
</FormRow>
Expand Down Expand Up @@ -167,13 +177,40 @@ export const AffinityEdit: React.FC<AffinityEditProps> = ({
/>
</FormRow>
)}
<Divider />
<Divider component="div" />
<FormRow
title={isNodeAffinity ? 'Node Labels' : 'Workload Labels'}
fieldId={'expressions'}
validationType={isExpressionsInvalid && ValidationErrorType.Error}
validationMessage={isExpressionsInvalid && 'Missing fields'}
validationMessage={
isExpressionsInvalid && isNodeAffinity
? 'Missing fields in node labels'
: 'Missing fields in workload labels'
}
>
<div className="affinity-modal__desc-container">
{isNodeAffinity ? (
<>
<Text className="affinity-modal__desc" component={TextVariants.small}>
{'Select nodes that must have all the following expressions.'}
</Text>
<Text className="affinity-modal__desc" component={TextVariants.small}>
{
'Note that for Node field expressions, entering a full path is required in the Key field (e.g. `metadata.name: value`)'
}
</Text>
<Text className="affinity-modal__desc" component={TextVariants.small}>
{'A list of matching nodes will be provided on label input below.'}
</Text>
</>
) : (
<>
<Text className="affinity-modal__desc" component={TextVariants.small}>
{'Select workloads that must have all the following expressions.'}
</Text>
</>
)}
</div>
<AffinityExpressionList
expressions={affinityExpressions}
addRowText="Add Expression"
Expand All @@ -184,12 +221,11 @@ export const AffinityEdit: React.FC<AffinityEditProps> = ({
</FormRow>
{isNodeAffinity && (
<>
<Divider />
<FormRow
title="Node Fields"
fieldId={'fields'}
validationType={isFieldsInvalid && ValidationErrorType.Error}
validationMessage={isFieldsInvalid && 'Missing fields'}
validationMessage={isFieldsInvalid && 'Missing fields in node fields'}
>
<AffinityExpressionList
expressions={affinityFields}
Expand All @@ -216,7 +252,7 @@ export const AffinityEdit: React.FC<AffinityEditProps> = ({
})
}
onCancel={onCancel}
submitButtonText="Save Affinity"
submitButtonText="Save Affinity rule"
isDisabled={isAffinityInvalid}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export const AFFINITY_CREATE = 'New Affinity';
export const AFFINITY_EDITING = 'Edit Affinity';

export const AFFINITY_CONDITION_LABELS = {
preferredDuringSchedulingIgnoredDuringExecution: 'Preferred',
requiredDuringSchedulingIgnoredDuringExecution: 'Required',
preferredDuringSchedulingIgnoredDuringExecution: 'Preferred during scheduling',
requiredDuringSchedulingIgnoredDuringExecution: 'Required during scheduling',
};

export const AFFINITY_CONDITIONS = {
Expand Down