Skip to content

Commit

Permalink
Disable size field and show helper text when editing an unbound storage
Browse files Browse the repository at this point in the history
  • Loading branch information
DaoDaoNoCode committed Nov 7, 2024
1 parent 0e4420f commit 40379b9
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 45 deletions.
16 changes: 9 additions & 7 deletions frontend/src/__mocks__/mockPVCK8sResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type MockResourceConfigType = {
storageClassName?: string;
displayName?: string;
uid?: string;
status?: PersistentVolumeClaimKind['status'];
};

export const mockPVCK8sResource = ({
Expand All @@ -17,6 +18,13 @@ export const mockPVCK8sResource = ({
storageClassName = 'gp3',
displayName = 'Test Storage',
uid = genUID('pvc'),
status = {
phase: 'Bound',
accessModes: ['ReadWriteOnce'],
capacity: {
storage,
},
},
}: MockResourceConfigType): PersistentVolumeClaimKind => ({
kind: 'PersistentVolumeClaim',
apiVersion: 'v1',
Expand All @@ -43,11 +51,5 @@ export const mockPVCK8sResource = ({
storageClassName,
volumeMode: 'Filesystem',
},
status: {
phase: 'Bound',
accessModes: ['ReadWriteOnce'],
capacity: {
storage,
},
},
status,
});
10 changes: 7 additions & 3 deletions frontend/src/__tests__/cypress/cypress/pages/clusterStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class ClusterStorageModal extends Modal {

shouldHavePVSizeSelectValue(name: string) {
this.findPVSizeSelectButton().contains(name).should('exist');
return this;
return this.findPVSizeSelectButton();
}

private findPVSizeField() {
Expand All @@ -95,8 +95,12 @@ class ClusterStorageModal extends Modal {
return this.findPVSizeField().findByRole('button', { name: 'Minus' });
}

findPersistentStorageWarning() {
return this.find().findByTestId('persistent-storage-warning');
findPersistentStorageWarningCanNotEdit() {
return this.find().findByTestId('persistent-storage-warning-can-not-edit');
}

findPersistentStorageWarningCanOnlyIncrease() {
return this.find().findByTestId('persistent-storage-warning-can-only-increase');
}

findPVSizeInput() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ const initInterceptors = ({ isEmpty = false, storageClassName }: HandlersProps)
: [
mockPVCK8sResource({ uid: 'test-id', storageClassName }),
mockPVCK8sResource({ displayName: 'Another Cluster Storage', storageClassName }),
mockPVCK8sResource({
displayName: 'Unbound storage',
storageClassName,
status: { phase: 'Pending' },
}),
],
),
);
Expand Down Expand Up @@ -412,7 +417,7 @@ describe('ClusterStorage', () => {
updateClusterStorageModal.findNameInput().should('have.value', 'Test Storage');
updateClusterStorageModal.findPVSizeInput().should('have.value', '5');
updateClusterStorageModal.shouldHavePVSizeSelectValue('GiB');
updateClusterStorageModal.findPersistentStorageWarning().should('exist');
updateClusterStorageModal.findPersistentStorageWarningCanOnlyIncrease().should('exist');
updateClusterStorageModal.findSubmitButton().should('be.enabled');
updateClusterStorageModal.findNameInput().fill('test-updated');

Expand Down Expand Up @@ -446,6 +451,17 @@ describe('ClusterStorage', () => {
});
});

it('should disable size field when editing unbound storage', () => {
initInterceptors({});
clusterStorage.visit('test-project');
const clusterStorageRow = clusterStorage.getClusterStorageRow('Unbound storage');
clusterStorageRow.findKebabAction('Edit storage').click();
updateClusterStorageModal.findNameInput().should('have.value', 'Unbound storage');
updateClusterStorageModal.findPVSizeInput().should('have.value', '5').should('be.disabled');
updateClusterStorageModal.shouldHavePVSizeSelectValue('GiB').should('be.disabled');
updateClusterStorageModal.findPersistentStorageWarningCanNotEdit().should('exist');
});

it('Delete cluster storage', () => {
initInterceptors({});
clusterStorage.visit('test-project');
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/ValueUnitField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type ValueUnitFieldProps = {
value: ValueUnitString;
validated?: 'default' | 'error' | 'warning' | 'success' | ValidatedOptions | undefined;
menuAppendTo?: HTMLElement;
isDisabled?: boolean;
};

const ValueUnitField: React.FC<ValueUnitFieldProps> = ({
Expand All @@ -41,6 +42,7 @@ const ValueUnitField: React.FC<ValueUnitFieldProps> = ({
menuAppendTo,
value: fullValue,
validated,
isDisabled,
}) => {
const [open, setOpen] = React.useState(false);
const [currentValue, currentUnitOption] = splitValueUnit(fullValue, options);
Expand All @@ -64,6 +66,7 @@ const ValueUnitField: React.FC<ValueUnitFieldProps> = ({
onChange={(value) => {
onChange(`${value || minAsNumber}${currentUnitOption.unit}`);
}}
isDisabled={isDisabled}
/>
</SplitItem>
<SplitItem>
Expand All @@ -80,6 +83,7 @@ const ValueUnitField: React.FC<ValueUnitFieldProps> = ({
setOpen(!open);
}}
isExpanded={open}
isDisabled={isDisabled}
>
{currentUnitOption.name}
</MenuToggle>
Expand Down
79 changes: 50 additions & 29 deletions frontend/src/pages/projects/components/PVSizeField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { FormGroup, FormHelperText, HelperText, HelperTextItem } from '@patternf
import { ExclamationTriangleIcon } from '@patternfly/react-icons';
import ValueUnitField from '~/components/ValueUnitField';
import { MEMORY_UNITS_FOR_SELECTION, UnitOption } from '~/utilities/valueUnits';
import { PersistentVolumeClaimKind } from '~/k8sTypes';

type PVSizeFieldProps = {
fieldID: string;
size: string;
menuAppendTo?: HTMLElement;
setSize: (size: string) => void;
currentSize?: string;
currentStatus?: PersistentVolumeClaimKind['status'];
label?: string;
options?: UnitOption[];
};
Expand All @@ -19,35 +20,55 @@ const PVSizeField: React.FC<PVSizeFieldProps> = ({
size,
menuAppendTo,
setSize,
currentSize,
currentStatus,
label = 'Persistent storage size',
options = MEMORY_UNITS_FOR_SELECTION,
}) => (
<FormGroup label={label} fieldId={fieldID} data-testid={fieldID}>
<ValueUnitField
min={currentSize ?? 1}
onBlur={(value) => setSize(value)}
menuAppendTo={menuAppendTo}
onChange={(value) => setSize(value)}
validated={currentSize ? 'warning' : 'default'}
options={options}
value={size}
/>
{currentSize && (
<FormHelperText>
<HelperText>
<HelperTextItem
data-testid="persistent-storage-warning"
variant="warning"
icon={<ExclamationTriangleIcon />}
>
Storage size can only be increased. If you do so, the workbench will restart and be
unavailable for a period of time that is usually proportional to the size change.
</HelperTextItem>
</HelperText>
</FormHelperText>
)}
</FormGroup>
);
}) => {
const currentSize = currentStatus?.capacity?.storage;
const isUnbound = currentStatus && currentStatus.phase !== 'Bound';

return (
<FormGroup label={label} fieldId={fieldID} data-testid={fieldID}>
<ValueUnitField
min={currentSize ?? 1}
onBlur={(value) => setSize(value)}
menuAppendTo={menuAppendTo}
onChange={(value) => setSize(value)}
validated={currentSize ? 'warning' : 'default'}
options={options}
value={size}
isDisabled={isUnbound}
/>

{(currentSize || isUnbound) && (
<FormHelperText>
<HelperText>
{isUnbound && (
<HelperTextItem
data-testid="persistent-storage-warning-can-not-edit"
variant="warning"
icon={<ExclamationTriangleIcon />}
>
To edit the size, you must first attach this cluster storage to a workbench, then
start the workbench. If the workbench is already running, it will restart
automatically.
</HelperTextItem>
)}
{currentSize && (
<HelperTextItem
data-testid="persistent-storage-warning-can-only-increase"
variant="warning"
icon={<ExclamationTriangleIcon />}
>
Storage size can only be increased. If you do so, the workbench will restart and be
unavailable for a period of time that is usually proportional to the size change.
</HelperTextItem>
)}
</HelperText>
</FormHelperText>
)}
</FormGroup>
);
};

export default PVSizeField;
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const BaseStorageModal: React.FC<BaseStorageModalProps> = ({
<CreateNewStorageSection
data={createData}
setData={setCreateData}
currentSize={existingData?.status?.capacity?.storage}
currentStatus={existingData?.status}
autoFocusName
disableStorageClassSelect={!!existingData}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ const ManageStorageModal: React.FC<AddStorageModalProps> = ({ existingData, onCl
<CreateNewStorageSection
data={createData}
setData={setCreateData}
currentSize={existingData?.status?.capacity?.storage}
currentStatus={existingData?.status}
autoFocusName
disableStorageClassSelect={!!existingData}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { CreatingStorageObject, UpdateObjectAtPropAndValue } from '~/pages/proje
import PVSizeField from '~/pages/projects/components/PVSizeField';
import NameDescriptionField from '~/concepts/k8s/NameDescriptionField';
import { SupportedArea, useIsAreaAvailable } from '~/concepts/areas';
import { PersistentVolumeClaimKind } from '~/k8sTypes';
import StorageClassSelect from './StorageClassSelect';

type CreateNewStorageSectionProps<D extends CreatingStorageObject> = {
data: D;
setData: UpdateObjectAtPropAndValue<D>;
currentSize?: string;
currentStatus?: PersistentVolumeClaimKind['status'];
autoFocusName?: boolean;
menuAppendTo?: HTMLElement;
disableStorageClassSelect?: boolean;
Expand All @@ -18,7 +19,7 @@ type CreateNewStorageSectionProps<D extends CreatingStorageObject> = {
const CreateNewStorageSection = <D extends CreatingStorageObject>({
data,
setData,
currentSize,
currentStatus,
menuAppendTo,
autoFocusName,
disableStorageClassSelect,
Expand Down Expand Up @@ -50,7 +51,7 @@ const CreateNewStorageSection = <D extends CreatingStorageObject>({
<PVSizeField
menuAppendTo={menuAppendTo}
fieldID="create-new-storage-size"
currentSize={currentSize}
currentStatus={currentStatus}
size={data.size}
setSize={(size) => setData('size', size)}
/>
Expand Down

0 comments on commit 40379b9

Please sign in to comment.