src: Resolve circular dependency FileSystemTable <-> FileSystemConfiguration

Nothing got added, nothing got removed. Stuff just got moved around and imports are updated.
This commit is contained in:
regexowl 2024-10-11 10:17:51 +02:00 committed by Sanne Raymaekers
parent 076fb3fc9d
commit ba9282b61c
8 changed files with 276 additions and 281 deletions

View file

@ -1,49 +1,26 @@
import React, { useState } from 'react';
import React from 'react';
import {
Alert,
Button,
Text,
TextContent,
TextInput,
TextVariants,
} from '@patternfly/react-core';
import { Select, SelectOption } from '@patternfly/react-core/deprecated';
import { MinusCircleIcon, PlusCircleIcon } from '@patternfly/react-icons';
import { PlusCircleIcon } from '@patternfly/react-icons';
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
import { Td, Tr } from '@patternfly/react-table';
import { v4 as uuidv4 } from 'uuid';
import FileSystemTable from './FileSystemTable';
import {
FILE_SYSTEM_CUSTOMIZATION_URL,
UNIT_GIB,
UNIT_KIB,
UNIT_MIB,
} from '../../../../constants';
import { FILE_SYSTEM_CUSTOMIZATION_URL } from '../../../../constants';
import { useAppDispatch, useAppSelector } from '../../../../store/hooks';
import {
addPartition,
changePartitionMinSize,
changePartitionMountpoint,
selectImageTypes,
removePartition,
selectPartitions,
changePartitionUnit,
} from '../../../../store/wizardSlice';
import UsrSubDirectoriesDisabled from '../../UsrSubDirectoriesDisabled';
import { useFilesystemValidation } from '../../utilities/useValidation';
import { HookValidatedInput } from '../../ValidatedTextInput';
import { FileSystemContext } from './index';
export type Partition = {
id: string;
mountpoint: string;
min_size: string;
unit: Units;
};
const FileSystemConfiguration = () => {
const partitions = useAppSelector(selectPartitions);
@ -118,247 +95,4 @@ const FileSystemConfiguration = () => {
);
};
type RowPropTypes = {
partition: Partition;
onDrop?: (event: React.DragEvent<HTMLTableRowElement>) => void;
onDragEnd?: (event: React.DragEvent<HTMLTableRowElement>) => void;
onDragStart?: (event: React.DragEvent<HTMLTableRowElement>) => void;
};
const normalizeSuffix = (rawSuffix: string) => {
const suffix = rawSuffix.replace(/^\/+/g, '');
return suffix.length > 0 ? '/' + suffix : '';
};
const getPrefix = (mountpoint: string) => {
return mountpoint.split('/')[1] ? '/' + mountpoint.split('/')[1] : '/';
};
const getSuffix = (mountpoint: string) => {
const prefix = getPrefix(mountpoint);
return normalizeSuffix(mountpoint.substring(prefix.length));
};
export const Row = ({
partition,
onDragEnd,
onDragStart,
onDrop,
}: RowPropTypes) => {
const dispatch = useAppDispatch();
const handleRemovePartition = (id: string) => {
dispatch(removePartition(id));
};
const stepValidation = useFilesystemValidation();
const isPristine = React.useContext(FileSystemContext);
return (
<Tr
draggable
id={partition.id}
onDrop={onDrop}
onDragStart={onDragStart}
onDragEnd={onDragEnd}
>
<Td
draggableRow={{
id: `draggable-row-${partition.id}`,
}}
/>
<Td className="pf-m-width-20">
<MountpointPrefix partition={partition} />
{!isPristine && stepValidation.errors[`mountpoint-${partition.id}`] && (
<Alert
variant="danger"
isInline
isPlain
title={stepValidation.errors[`mountpoint-${partition.id}`]}
/>
)}
</Td>
{partition.mountpoint !== '/' &&
!partition.mountpoint.startsWith('/boot') &&
!partition.mountpoint.startsWith('/usr') ? (
<Td width={20}>
<MountpointSuffix partition={partition} />
</Td>
) : (
<Td width={20} />
)}
<Td width={20}>xfs</Td>
<Td width={20}>
<MinimumSize partition={partition} />
</Td>
<Td width={10}>
<SizeUnit partition={partition} />
</Td>
<Td width={10}>
<Button
variant="link"
icon={<MinusCircleIcon />}
onClick={() => handleRemovePartition(partition.id)}
ouiaId="remove-mount-point"
isDisabled={partition.mountpoint === '/'}
/>
</Td>
</Tr>
);
};
export const mountpointPrefixes = [
'/app',
'/boot',
'/data',
'/home',
'/opt',
'/srv',
'/tmp',
'/usr',
'/var',
];
type MountpointPrefixPropTypes = {
partition: Partition;
};
const MountpointPrefix = ({ partition }: MountpointPrefixPropTypes) => {
const dispatch = useAppDispatch();
const [isOpen, setIsOpen] = useState(false);
const prefix = getPrefix(partition.mountpoint);
const suffix = getSuffix(partition.mountpoint);
const onToggle = (isOpen: boolean) => {
setIsOpen(isOpen);
};
const onSelect = (event: React.MouseEvent, selection: string) => {
setIsOpen(false);
const mountpoint = selection + (suffix.length > 0 ? '/' + suffix : '');
dispatch(
changePartitionMountpoint({ id: partition.id, mountpoint: mountpoint })
);
};
return (
<Select
ouiaId="mount-point"
isOpen={isOpen}
onToggle={(_event, isOpen) => onToggle(isOpen)}
onSelect={onSelect}
selections={prefix}
isDisabled={prefix === '/'}
>
{mountpointPrefixes.map((prefix, index) => {
return <SelectOption key={index} value={prefix} />;
})}
</Select>
);
};
type MountpointSuffixPropTypes = {
partition: Partition;
};
const MountpointSuffix = ({ partition }: MountpointSuffixPropTypes) => {
const dispatch = useAppDispatch();
const prefix = getPrefix(partition.mountpoint);
const suffix = getSuffix(partition.mountpoint);
return (
<TextInput
value={suffix}
type="text"
onChange={(event: React.FormEvent, newValue) => {
const mountpoint = prefix + normalizeSuffix(newValue);
dispatch(
changePartitionMountpoint({
id: partition.id,
mountpoint: mountpoint,
})
);
}}
aria-label="mountpoint suffix"
ouiaId="mount-suffix"
/>
);
};
type MinimumSizePropTypes = {
partition: Partition;
};
export type Units = 'KiB' | 'MiB' | 'GiB';
export const getConversionFactor = (units: Units) => {
switch (units) {
case 'KiB':
return UNIT_KIB;
case 'MiB':
return UNIT_MIB;
case 'GiB':
return UNIT_GIB;
}
};
const MinimumSize = ({ partition }: MinimumSizePropTypes) => {
const dispatch = useAppDispatch();
const stepValidation = useFilesystemValidation();
return (
<HookValidatedInput
ariaLabel="minimum partition size"
value={partition.min_size}
type="text"
ouiaId="size"
stepValidation={stepValidation}
fieldName={`min-size-${partition.id}`}
onChange={(event, minSize) => {
if (minSize === '' || /^\d+$/.test(minSize)) {
dispatch(
changePartitionMinSize({
id: partition.id,
min_size: minSize,
})
);
dispatch(
changePartitionUnit({ id: partition.id, unit: partition.unit })
);
}
}}
/>
);
};
type SizeUnitPropTypes = {
partition: Partition;
};
const SizeUnit = ({ partition }: SizeUnitPropTypes) => {
const dispatch = useAppDispatch();
const [isOpen, setIsOpen] = useState(false);
const onToggle = (isOpen: boolean) => {
setIsOpen(isOpen);
};
const onSelect = (event: React.MouseEvent, selection: Units) => {
dispatch(changePartitionUnit({ id: partition.id, unit: selection }));
setIsOpen(false);
};
return (
<Select
ouiaId="unit"
isOpen={isOpen}
onToggle={(_event, isOpen) => onToggle(isOpen)}
onSelect={onSelect}
selections={partition.unit}
>
<SelectOption value={'KiB'} />
<SelectOption value={'MiB'} />
<SelectOption value={'GiB'} />
</Select>
);
};
export default FileSystemConfiguration;

View file

@ -1,7 +1,15 @@
import React, { useRef, useState } from 'react';
import { Popover, TextContent, Text, Button } from '@patternfly/react-core';
import { HelpIcon } from '@patternfly/react-icons';
import {
Popover,
TextContent,
Text,
Button,
Alert,
TextInput,
} from '@patternfly/react-core';
import { Select, SelectOption } from '@patternfly/react-core/deprecated';
import { HelpIcon, MinusCircleIcon } from '@patternfly/react-icons';
import styles from '@patternfly/react-styles/css/components/Table/table';
import {
Table,
@ -11,15 +19,23 @@ import {
Tr,
TrProps,
TbodyProps,
Td,
} from '@patternfly/react-table';
import { Row } from './FileSystemConfiguration';
import { UNIT_GIB, UNIT_KIB, UNIT_MIB } from '../../../../constants';
import { useAppDispatch, useAppSelector } from '../../../../store/hooks';
import {
changePartitionMinSize,
changePartitionMountpoint,
changePartitionOrder,
changePartitionUnit,
removePartition,
selectPartitions,
} from '../../../../store/wizardSlice';
import { useFilesystemValidation } from '../../utilities/useValidation';
import { HookValidatedInput } from '../../ValidatedTextInput';
import { FileSystemContext } from '.';
export const MinimumSizePopover = () => {
return (
@ -46,6 +62,251 @@ export const MinimumSizePopover = () => {
);
};
export type Partition = {
id: string;
mountpoint: string;
min_size: string;
unit: Units;
};
type RowPropTypes = {
partition: Partition;
onDrop?: (event: React.DragEvent<HTMLTableRowElement>) => void;
onDragEnd?: (event: React.DragEvent<HTMLTableRowElement>) => void;
onDragStart?: (event: React.DragEvent<HTMLTableRowElement>) => void;
};
const normalizeSuffix = (rawSuffix: string) => {
const suffix = rawSuffix.replace(/^\/+/g, '');
return suffix.length > 0 ? '/' + suffix : '';
};
const getPrefix = (mountpoint: string) => {
return mountpoint.split('/')[1] ? '/' + mountpoint.split('/')[1] : '/';
};
const getSuffix = (mountpoint: string) => {
const prefix = getPrefix(mountpoint);
return normalizeSuffix(mountpoint.substring(prefix.length));
};
const Row = ({ partition, onDragEnd, onDragStart, onDrop }: RowPropTypes) => {
const dispatch = useAppDispatch();
const handleRemovePartition = (id: string) => {
dispatch(removePartition(id));
};
const stepValidation = useFilesystemValidation();
const isPristine = React.useContext(FileSystemContext);
return (
<Tr
draggable
id={partition.id}
onDrop={onDrop}
onDragStart={onDragStart}
onDragEnd={onDragEnd}
>
<Td
draggableRow={{
id: `draggable-row-${partition.id}`,
}}
/>
<Td className="pf-m-width-20">
<MountpointPrefix partition={partition} />
{!isPristine && stepValidation.errors[`mountpoint-${partition.id}`] && (
<Alert
variant="danger"
isInline
isPlain
title={stepValidation.errors[`mountpoint-${partition.id}`]}
/>
)}
</Td>
{partition.mountpoint !== '/' &&
!partition.mountpoint.startsWith('/boot') &&
!partition.mountpoint.startsWith('/usr') ? (
<Td width={20}>
<MountpointSuffix partition={partition} />
</Td>
) : (
<Td width={20} />
)}
<Td width={20}>xfs</Td>
<Td width={20}>
<MinimumSize partition={partition} />
</Td>
<Td width={10}>
<SizeUnit partition={partition} />
</Td>
<Td width={10}>
<Button
variant="link"
icon={<MinusCircleIcon />}
onClick={() => handleRemovePartition(partition.id)}
ouiaId="remove-mount-point"
isDisabled={partition.mountpoint === '/'}
/>
</Td>
</Tr>
);
};
export const mountpointPrefixes = [
'/app',
'/boot',
'/data',
'/home',
'/opt',
'/srv',
'/tmp',
'/usr',
'/var',
];
type MountpointPrefixPropTypes = {
partition: Partition;
};
const MountpointPrefix = ({ partition }: MountpointPrefixPropTypes) => {
const dispatch = useAppDispatch();
const [isOpen, setIsOpen] = useState(false);
const prefix = getPrefix(partition.mountpoint);
const suffix = getSuffix(partition.mountpoint);
const onToggle = (isOpen: boolean) => {
setIsOpen(isOpen);
};
const onSelect = (event: React.MouseEvent, selection: string) => {
setIsOpen(false);
const mountpoint = selection + (suffix.length > 0 ? '/' + suffix : '');
dispatch(
changePartitionMountpoint({ id: partition.id, mountpoint: mountpoint })
);
};
return (
<Select
ouiaId="mount-point"
isOpen={isOpen}
onToggle={(_event, isOpen) => onToggle(isOpen)}
onSelect={onSelect}
selections={prefix}
isDisabled={prefix === '/'}
>
{mountpointPrefixes.map((prefix, index) => {
return <SelectOption key={index} value={prefix} />;
})}
</Select>
);
};
type MountpointSuffixPropTypes = {
partition: Partition;
};
const MountpointSuffix = ({ partition }: MountpointSuffixPropTypes) => {
const dispatch = useAppDispatch();
const prefix = getPrefix(partition.mountpoint);
const suffix = getSuffix(partition.mountpoint);
return (
<TextInput
value={suffix}
type="text"
onChange={(event: React.FormEvent, newValue) => {
const mountpoint = prefix + normalizeSuffix(newValue);
dispatch(
changePartitionMountpoint({
id: partition.id,
mountpoint: mountpoint,
})
);
}}
aria-label="mountpoint suffix"
ouiaId="mount-suffix"
/>
);
};
type MinimumSizePropTypes = {
partition: Partition;
};
export type Units = 'KiB' | 'MiB' | 'GiB';
export const getConversionFactor = (units: Units) => {
switch (units) {
case 'KiB':
return UNIT_KIB;
case 'MiB':
return UNIT_MIB;
case 'GiB':
return UNIT_GIB;
}
};
const MinimumSize = ({ partition }: MinimumSizePropTypes) => {
const dispatch = useAppDispatch();
const stepValidation = useFilesystemValidation();
return (
<HookValidatedInput
ariaLabel="minimum partition size"
value={partition.min_size}
type="text"
ouiaId="size"
stepValidation={stepValidation}
fieldName={`min-size-${partition.id}`}
onChange={(event, minSize) => {
if (minSize === '' || /^\d+$/.test(minSize)) {
dispatch(
changePartitionMinSize({
id: partition.id,
min_size: minSize,
})
);
dispatch(
changePartitionUnit({ id: partition.id, unit: partition.unit })
);
}
}}
/>
);
};
type SizeUnitPropTypes = {
partition: Partition;
};
const SizeUnit = ({ partition }: SizeUnitPropTypes) => {
const dispatch = useAppDispatch();
const [isOpen, setIsOpen] = useState(false);
const onToggle = (isOpen: boolean) => {
setIsOpen(isOpen);
};
const onSelect = (event: React.MouseEvent, selection: Units) => {
dispatch(changePartitionUnit({ id: partition.id, unit: selection }));
setIsOpen(false);
};
return (
<Select
ouiaId="unit"
isOpen={isOpen}
onToggle={(_event, isOpen) => onToggle(isOpen)}
onSelect={onSelect}
selections={partition.unit}
>
<SelectOption value={'KiB'} />
<SelectOption value={'MiB'} />
<SelectOption value={'GiB'} />
</Select>
);
};
const FileSystemTable = () => {
const [draggedItemId, setDraggedItemId] = useState<string | null>(null);
const [draggingToItemIndex, setDraggingToItemIndex] = useState<number | null>(

View file

@ -49,7 +49,7 @@ import {
} from '../../../../store/wizardSlice';
import { useHasSpecificTargetOnly } from '../../utilities/hasSpecificTargetOnly';
import { parseSizeUnit } from '../../utilities/parseSizeUnit';
import { Partition, Units } from '../FileSystem/FileSystemConfiguration';
import { Partition, Units } from '../FileSystem/FileSystemTable';
const OpenSCAPFGLabel = () => {
return (

View file

@ -66,10 +66,10 @@ import {
} from '../../../../store/wizardSlice';
import { toMonthAndYear, yyyyMMddFormat } from '../../../../Utilities/time';
import {
Partition,
getConversionFactor,
} from '../FileSystem/FileSystemConfiguration';
import { MinimumSizePopover } from '../FileSystem/FileSystemTable';
MinimumSizePopover,
Partition,
} from '../FileSystem/FileSystemTable';
import { MajorReleasesLifecyclesChart } from '../ImageOutput/ReleaseLifecycle';
import OscapProfileInformation from '../Oscap/OscapProfileInformation';
import { PopoverActivation } from '../Registration/ActivationKeysList';

View file

@ -1,5 +1,5 @@
import { UNIT_GIB, UNIT_KIB, UNIT_MIB } from '../../../constants';
import { Units } from '../steps/FileSystem/FileSystemConfiguration';
import { Units } from '../steps/FileSystem/FileSystemTable';
export const parseSizeUnit = (bytesize: string) => {
let size;

View file

@ -78,7 +78,7 @@ import {
getConversionFactor,
Partition,
Units,
} from '../steps/FileSystem/FileSystemConfiguration';
} from '../steps/FileSystem/FileSystemTable';
import { PackageRepository } from '../steps/Packages/Packages';
import {
convertSchemaToIBCustomRepo,

View file

@ -1,4 +1,4 @@
import type { Partition } from './steps/FileSystem/FileSystemConfiguration';
import type { Partition } from './steps/FileSystem/FileSystemTable';
export const isAwsAccountIdValid = (awsAccountId: string | undefined) => {
return (

View file

@ -15,7 +15,7 @@ import type { FileSystemConfigurationType } from '../Components/CreateImageWizar
import type {
Partition,
Units,
} from '../Components/CreateImageWizard/steps/FileSystem/FileSystemConfiguration';
} from '../Components/CreateImageWizard/steps/FileSystem/FileSystemTable';
import type {
GroupWithRepositoryInfo,
IBPackageWithRepositoryInfo,