Local modifications to ClusterLabs/Anvil by Alteeve
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
4.6 KiB

import {
Checkbox,
checkboxClasses,
FormControl,
FormControlLabel,
FormGroup,
InputLabel,
inputLabelClasses,
MenuItem,
OutlinedInput,
outlinedInputClasses,
Select,
selectClasses,
styled,
} from '@mui/material';
import {
Sync as SyncIcon,
SyncDisabled as SyncDisabledIcon,
} from '@mui/icons-material';
import { v4 as uuidv4 } from 'uuid';
import {
BLACK,
BLUE,
BORDER_RADIUS,
GREY,
RED,
TEXT,
UNSELECTED,
} from '../../lib/consts/DEFAULT_THEME';
import { UPLOAD_FILE_TYPES_ARRAY } from '../../lib/consts/UPLOAD_FILE_TYPES';
type FileInfoProps = Pick<FileDetailMetadata, 'fileName' | 'fileLocations'> &
Partial<Pick<FileDetailMetadata, 'fileType'>> & {
isReadonly?: boolean;
onChange?: FileInfoChangeHandler;
};
const FILE_INFO_DEFAULT_PROPS: Partial<FileInfoProps> = {
isReadonly: undefined,
onChange: undefined,
};
const StyledInputLabel = styled(InputLabel)({
color: GREY,
[`&.${inputLabelClasses.focused}`]: {
backgroundColor: GREY,
borderRadius: BORDER_RADIUS,
color: BLACK,
padding: '.1em .6em',
},
});
const StyledOutlinedInput = styled(OutlinedInput)({
color: GREY,
[`& .${outlinedInputClasses.notchedOutline}`]: {
borderColor: UNSELECTED,
},
'&:hover': {
[`& .${outlinedInputClasses.notchedOutline}`]: {
borderColor: GREY,
},
},
[`&.${outlinedInputClasses.focused}`]: {
color: TEXT,
[`& .${outlinedInputClasses.notchedOutline}`]: {
borderColor: GREY,
'& legend': {
paddingRight: '1.2em',
},
},
},
});
const StyledSelect = styled(Select)({
[`& .${selectClasses.icon}`]: {
color: GREY,
},
});
const FileLocationActiveCheckbox = styled(Checkbox)({
color: RED,
[`&.${checkboxClasses.checked}`]: {
color: BLUE,
},
});
const FileInfo = (
{
fileName,
fileType,
fileLocations,
isReadonly,
onChange,
}: FileInfoProps = FILE_INFO_DEFAULT_PROPS as FileInfoProps,
): JSX.Element => {
const idExtension = uuidv4();
const fileNameElementId = `file-name-${idExtension}`;
const fileNameElementLabel = 'File name';
const fileTypeElementId = `file-type-${idExtension}`;
const fileTypeElementLabel = 'File type';
return (
<FormGroup sx={{ '> :not(:first-child)': { marginTop: '1em' } }}>
<FormControl>
<StyledInputLabel htmlFor={fileNameElementId} variant="outlined">
{fileNameElementLabel}
</StyledInputLabel>
<StyledOutlinedInput
defaultValue={fileName}
disabled={isReadonly}
id={fileNameElementId}
label={fileNameElementLabel}
onChange={({ target: { value } }) =>
onChange?.call(null, { fileName: value })
}
/>
</FormControl>
{fileType && (
<FormControl>
<StyledInputLabel htmlFor={fileTypeElementId} variant="outlined">
{fileTypeElementLabel}
</StyledInputLabel>
<StyledSelect
defaultValue={fileType}
disabled={isReadonly}
id={fileTypeElementId}
input={<StyledOutlinedInput label={fileTypeElementLabel} />}
onChange={({ target: { value } }) =>
onChange?.call(null, { fileType: value as FileType })
}
>
{UPLOAD_FILE_TYPES_ARRAY.map(
([fileTypeKey, [, fileTypeDisplayString]]) => {
return (
<MenuItem key={fileTypeKey} value={fileTypeKey}>
{fileTypeDisplayString}
</MenuItem>
);
},
)}
</StyledSelect>
</FormControl>
)}
{fileLocations.map(
(
{ anvilName, anvilDescription, anvilUUID, isFileLocationActive },
fileLocationIndex,
) => (
<FormControlLabel
control={
<FileLocationActiveCheckbox
checkedIcon={<SyncIcon />}
defaultChecked={isFileLocationActive}
disabled={isReadonly}
icon={<SyncDisabledIcon />}
onChange={({ target: { checked } }) =>
onChange?.call(
null,
{ isFileLocationActive: checked },
{ fileLocationIndex },
)
}
/>
}
key={anvilUUID}
label={`${anvilName}: ${anvilDescription}`}
sx={{ color: TEXT }}
value={`${anvilUUID}-sync`}
/>
),
)}
</FormGroup>
);
};
FileInfo.defaultProps = FILE_INFO_DEFAULT_PROPS;
export default FileInfo;