fix(striker-ui): add input groups to build add/edit manifest forms

main
Tsu-ba-me 2 years ago
parent f59d273ebb
commit 768ef98f51
  1. 34
      striker-ui/components/ManageManifest/AddAnvilManifestInputGroup.tsx
  2. 172
      striker-ui/components/ManageManifest/AnvilHostInputGroup.tsx
  3. 152
      striker-ui/components/ManageManifest/AnvilIdInputGroup.tsx
  4. 203
      striker-ui/components/ManageManifest/AnvilNetworkConfigInputGroup.tsx
  5. 174
      striker-ui/components/ManageManifest/AnvilNetworkInputGroup.tsx
  6. 88
      striker-ui/components/ManageManifest/ManageManifestPanel.tsx
  7. 94
      striker-ui/types/ManageManifest.d.ts

@ -0,0 +1,34 @@
import { ReactElement } from 'react';
import AnvilIdInputGroup, {
INPUT_ID_ANVIL_ID_DOMAIN,
INPUT_ID_ANVIL_ID_PREFIX,
INPUT_ID_ANVIL_ID_SEQUENCE,
} from './AnvilIdInputGroup';
import AnvilNetworkConfigInputGroup, {
INPUT_ID_ANVIL_NETWORK_CONFIG_DNS,
INPUT_ID_ANVIL_NETWORK_CONFIG_MTU,
INPUT_ID_ANVIL_NETWORK_CONFIG_NTP,
} from './AnvilNetworkConfigInputGroup';
import FlexBox from '../FlexBox';
const AddAnvilManifestInputGroup = <
M extends {
[K in
| typeof INPUT_ID_ANVIL_ID_DOMAIN
| typeof INPUT_ID_ANVIL_ID_PREFIX
| typeof INPUT_ID_ANVIL_ID_SEQUENCE
| typeof INPUT_ID_ANVIL_NETWORK_CONFIG_DNS
| typeof INPUT_ID_ANVIL_NETWORK_CONFIG_MTU
| typeof INPUT_ID_ANVIL_NETWORK_CONFIG_NTP]: string;
},
>({
formUtils,
}: AddAnvilInputGroupProps<M>): ReactElement => (
<FlexBox>
<AnvilIdInputGroup formUtils={formUtils} />
<AnvilNetworkConfigInputGroup formUtils={formUtils} />
</FlexBox>
);
export default AddAnvilManifestInputGroup;

@ -0,0 +1,172 @@
import { ReactElement, useMemo } from 'react';
import NETWORK_TYPES from '../../lib/consts/NETWORK_TYPES';
import Grid from '../Grid';
import InputWithRef from '../InputWithRef';
import OutlinedInputWithLabel from '../OutlinedInputWithLabel';
import { InnerPanel, InnerPanelBody, InnerPanelHeader } from '../Panels';
import SwitchWithLabel from '../SwitchWithLabel';
import {
buildIPAddressTestBatch,
buildNumberTestBatch,
} from '../../lib/test_input';
import { BodyText } from '../Text';
const INPUT_ID_PREFIX_ANVIL_HOST_CONFIG = 'anvil-host-config-input';
const INPUT_CELL_ID_PREFIX_ANVIL_HOST_CONFIG = `${INPUT_ID_PREFIX_ANVIL_HOST_CONFIG}-cell`;
const AnvilHostInputGroup = <M extends MapToInputTestID>({
formUtils: {
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
msgSetters,
setMsgSetter,
},
hostLabel,
previous: { fences = {}, networks = {}, upses = {} } = {},
}: AnvilHostInputGroupProps<M>): ReactElement => {
const gridLayout = useMemo(() => {
let result: GridLayout = {};
result = Object.entries(networks).reduce<GridLayout>(
(previous, [networkId, { networkIp, networkNumber, networkType }]) => {
const idPostfix = `${networkId}-ip`;
const cellId = `${INPUT_CELL_ID_PREFIX_ANVIL_HOST_CONFIG}-${idPostfix}`;
const inputId = `${INPUT_ID_PREFIX_ANVIL_HOST_CONFIG}-${idPostfix}`;
const inputLabel = `${NETWORK_TYPES[networkType]} ${networkNumber}`;
setMsgSetter(inputId);
previous[cellId] = {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={inputId}
label={inputLabel}
value={networkIp}
/>
}
inputTestBatch={buildIPAddressTestBatch(
inputLabel,
() => {
msgSetters[inputId]();
},
{ onFinishBatch: buildFinishInputTestBatchFunction(inputId) },
(message) => {
msgSetters[inputId]({
children: message,
});
},
)}
onFirstRender={buildInputFirstRenderFunction(inputId)}
required
/>
),
};
return previous;
},
result,
);
result = Object.entries(fences).reduce<GridLayout>(
(previous, [fenceId, { fenceName, fencePort }]) => {
const idPostfix = `${fenceId}-port`;
const cellId = `${INPUT_CELL_ID_PREFIX_ANVIL_HOST_CONFIG}-${idPostfix}`;
const inputId = `${INPUT_ID_PREFIX_ANVIL_HOST_CONFIG}-${idPostfix}`;
const inputLabel = fenceName;
setMsgSetter(inputId);
previous[cellId] = {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={inputId}
label={fenceName}
value={fencePort}
/>
}
inputTestBatch={buildNumberTestBatch(
inputLabel,
() => {
msgSetters[inputId]();
},
{ onFinishBatch: buildFinishInputTestBatchFunction(inputId) },
(message) => {
msgSetters[inputId]({
children: message,
});
},
)}
required
valueType="number"
/>
),
};
return previous;
},
result,
);
result = Object.entries(upses).reduce<GridLayout>(
(previous, [upsId, { isPowerHost, upsName }]) => {
const idPostfix = `${upsId}-power-host`;
const cellId = `${INPUT_CELL_ID_PREFIX_ANVIL_HOST_CONFIG}-${idPostfix}`;
const inputId = `${INPUT_ID_PREFIX_ANVIL_HOST_CONFIG}-${idPostfix}`;
previous[cellId] = {
children: (
<InputWithRef
input={
<SwitchWithLabel
id={inputId}
label={upsName}
checked={isPowerHost}
/>
}
valueType="boolean"
/>
),
};
return previous;
},
result,
);
return result;
}, [
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
setMsgSetter,
fences,
msgSetters,
networks,
upses,
]);
return (
<InnerPanel>
<InnerPanelHeader>
<BodyText>{hostLabel}</BodyText>
</InnerPanelHeader>
<InnerPanelBody>
<Grid layout={gridLayout} spacing="1em" />
</InnerPanelBody>
</InnerPanel>
);
};
export default AnvilHostInputGroup;

@ -0,0 +1,152 @@
import { ReactElement } from 'react';
import Grid from '../Grid';
import InputWithRef from '../InputWithRef';
import OutlinedInputWithLabel from '../OutlinedInputWithLabel';
import {
buildNumberTestBatch,
buildPeacefulStringTestBatch,
} from '../../lib/test_input';
const INPUT_ID_ANVIL_ID_DOMAIN = 'anvil-id-input-domain';
const INPUT_ID_ANVIL_ID_PREFIX = 'anvil-id-input-prefix';
const INPUT_ID_ANVIL_ID_SEQUENCE = 'anvil-id-input-sequence';
const INPUT_LABEL_ANVIL_ID_DOMAIN = 'Domain name';
const INPUT_LABEL_ANVIL_ID_PREFIX = 'Anvil! prefix';
const INPUT_LABEL_ANVIL_ID_SEQUENCE = 'Anvil! sequence';
const AnvilIdInputGroup = <
M extends {
[K in
| typeof INPUT_ID_ANVIL_ID_DOMAIN
| typeof INPUT_ID_ANVIL_ID_PREFIX
| typeof INPUT_ID_ANVIL_ID_SEQUENCE]: string;
},
>({
formUtils: {
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
msgSetters,
},
previous: {
anvilIdDomain: previousDomain,
anvilIdPrefix: previousPrefix,
anvilIdSequence: previousSequence,
} = {},
}: AnvilIdInputGroupProps<M>): ReactElement => (
<Grid
columns={{ xs: 1, sm: 2, md: 3 }}
layout={{
'anvil-id-input-cell-prefix': {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={INPUT_ID_ANVIL_ID_PREFIX}
label={INPUT_LABEL_ANVIL_ID_PREFIX}
value={previousPrefix}
/>
}
inputTestBatch={buildPeacefulStringTestBatch(
INPUT_LABEL_ANVIL_ID_PREFIX,
() => {
msgSetters[INPUT_ID_ANVIL_ID_PREFIX]();
},
{
onFinishBatch: buildFinishInputTestBatchFunction(
INPUT_ID_ANVIL_ID_PREFIX,
),
},
(message) => {
msgSetters[INPUT_ID_ANVIL_ID_PREFIX]({
children: message,
});
},
)}
onFirstRender={buildInputFirstRenderFunction(
INPUT_ID_ANVIL_ID_PREFIX,
)}
required
/>
),
},
'anvil-id-input-cell-domain': {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={INPUT_ID_ANVIL_ID_DOMAIN}
label={INPUT_LABEL_ANVIL_ID_DOMAIN}
value={previousDomain}
/>
}
inputTestBatch={buildPeacefulStringTestBatch(
INPUT_LABEL_ANVIL_ID_DOMAIN,
() => {
msgSetters[INPUT_ID_ANVIL_ID_DOMAIN]();
},
{
onFinishBatch: buildFinishInputTestBatchFunction(
INPUT_ID_ANVIL_ID_DOMAIN,
),
},
(message) => {
msgSetters[INPUT_ID_ANVIL_ID_DOMAIN]({
children: message,
});
},
)}
onFirstRender={buildInputFirstRenderFunction(
INPUT_ID_ANVIL_ID_DOMAIN,
)}
required
/>
),
},
'anvil-id-input-cell-sequence': {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={INPUT_ID_ANVIL_ID_SEQUENCE}
label={INPUT_LABEL_ANVIL_ID_SEQUENCE}
value={previousSequence}
/>
}
inputTestBatch={buildNumberTestBatch(
INPUT_LABEL_ANVIL_ID_SEQUENCE,
() => {
msgSetters[INPUT_ID_ANVIL_ID_SEQUENCE]();
},
{
onFinishBatch: buildFinishInputTestBatchFunction(
INPUT_ID_ANVIL_ID_SEQUENCE,
),
},
(message) => {
msgSetters[INPUT_ID_ANVIL_ID_SEQUENCE]({
children: message,
});
},
)}
onFirstRender={buildInputFirstRenderFunction(
INPUT_ID_ANVIL_ID_SEQUENCE,
)}
required
valueType="number"
/>
),
},
}}
spacing="1em"
/>
);
export {
INPUT_ID_ANVIL_ID_DOMAIN,
INPUT_ID_ANVIL_ID_PREFIX,
INPUT_ID_ANVIL_ID_SEQUENCE,
};
export default AnvilIdInputGroup;

@ -0,0 +1,203 @@
import { ReactElement, useMemo } from 'react';
import NETWORK_TYPES from '../../lib/consts/NETWORK_TYPES';
import AnvilNetworkInputGroup from './AnvilNetworkInputGroup';
import Grid from '../Grid';
import InputWithRef from '../InputWithRef';
import OutlinedInputWithLabel from '../OutlinedInputWithLabel';
import { buildNumberTestBatch } from '../../lib/test_input';
const INPUT_ID_PREFIX_ANVIL_NETWORK_CONFIG = 'anvil-network-config-input';
const INPUT_CELL_ID_PREFIX_ANVIL_NETWORK_CONFIG = `${INPUT_ID_PREFIX_ANVIL_NETWORK_CONFIG}-cell`;
const INPUT_ID_ANVIL_NETWORK_CONFIG_DNS = 'anvil-network-config-input-dns';
const INPUT_ID_ANVIL_NETWORK_CONFIG_MTU = 'anvil-network-config-input-mtu';
const INPUT_ID_ANVIL_NETWORK_CONFIG_NTP = 'anvil-network-config-input-ntp';
const INPUT_LABEL_ANVIL_NETWORK_CONFIG_DNS = 'DNS';
const INPUT_LABEL_ANVIL_NETWORK_CONFIG_MTU = 'MTU';
const INPUT_LABEL_ANVIL_NETWORK_CONFIG_NTP = 'NTP';
const DEFAULT_NETWORKS: { [networkId: string]: AnvilNetworkConfigNetwork } = {
bcn1: {
networkMinIp: '',
networkNumber: 1,
networkSubnetMask: '',
networkType: 'bcn',
},
sn1: {
networkMinIp: '',
networkNumber: 1,
networkSubnetMask: '',
networkType: 'sn',
},
ifn1: {
networkMinIp: '',
networkNumber: 1,
networkSubnetMask: '',
networkType: 'ifn',
},
};
const AnvilNetworkConfigInputGroup = <
M extends MapToInputTestID & {
[K in
| typeof INPUT_ID_ANVIL_NETWORK_CONFIG_DNS
| typeof INPUT_ID_ANVIL_NETWORK_CONFIG_MTU
| typeof INPUT_ID_ANVIL_NETWORK_CONFIG_NTP]: string;
},
>({
formUtils,
previous: {
dnsCsv: previousDnsCsv,
mtu: previousMtu,
networks = DEFAULT_NETWORKS,
ntpCsv: previousNtpCsv,
} = {},
}: AnvilNetworkConfigInputGroupProps<M>): ReactElement => {
const {
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
msgSetters,
} = formUtils;
const networksGridLayout = useMemo<GridLayout>(() => {
let result: GridLayout = {};
result = Object.entries(networks).reduce<GridLayout>(
(
previous,
[
networkId,
{
networkGateway: previousGateway,
networkMinIp: previousMinIp,
networkNumber,
networkSubnetMask: previousSubnetMask,
networkType,
},
],
) => {
const cellId = `${INPUT_CELL_ID_PREFIX_ANVIL_NETWORK_CONFIG}-${networkId}`;
const idPrefix = `anvil-network-${networkId}`;
const inputIdPrefix = `${INPUT_ID_PREFIX_ANVIL_NETWORK_CONFIG}-${networkId}`;
const inputGatewayId = `${inputIdPrefix}-gateway`;
const inputMinIpId = `${inputIdPrefix}-min-ip`;
const inputSubnetMaskId = `${inputIdPrefix}-subnet-mask`;
const networkName = `${NETWORK_TYPES[networkType]} ${networkNumber}`;
const isShowGateway = networkType === 'ifn';
previous[cellId] = {
children: (
<AnvilNetworkInputGroup
formUtils={formUtils}
idPrefix={idPrefix}
inputGatewayId={inputGatewayId}
inputMinIpId={inputMinIpId}
inputSubnetMaskId={inputSubnetMaskId}
networkName={networkName}
previous={{
gateway: previousGateway,
minIp: previousMinIp,
subnetMask: previousSubnetMask,
}}
showGateway={isShowGateway}
/>
),
md: 3,
sm: 2,
};
return previous;
},
result,
);
return result;
}, [formUtils, networks]);
return (
<Grid
columns={{ xs: 1, sm: 2, md: 3 }}
layout={{
...networksGridLayout,
'anvil-network-config-input-cell-dns': {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={INPUT_ID_ANVIL_NETWORK_CONFIG_DNS}
label={INPUT_LABEL_ANVIL_NETWORK_CONFIG_DNS}
value={previousDnsCsv}
/>
}
required
/>
),
},
'anvil-network-config-input-cell-ntp': {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={INPUT_ID_ANVIL_NETWORK_CONFIG_NTP}
label={INPUT_LABEL_ANVIL_NETWORK_CONFIG_NTP}
value={previousNtpCsv}
/>
}
/>
),
},
'anvil-network-config-input-cell-mtu': {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={INPUT_ID_ANVIL_NETWORK_CONFIG_MTU}
inputProps={{ placeholder: '1500' }}
label={INPUT_LABEL_ANVIL_NETWORK_CONFIG_MTU}
value={previousMtu}
/>
}
inputTestBatch={buildNumberTestBatch(
INPUT_LABEL_ANVIL_NETWORK_CONFIG_MTU,
() => {
msgSetters[INPUT_ID_ANVIL_NETWORK_CONFIG_MTU]();
},
{
onFinishBatch: buildFinishInputTestBatchFunction(
INPUT_ID_ANVIL_NETWORK_CONFIG_MTU,
),
},
(message) => {
msgSetters[INPUT_ID_ANVIL_NETWORK_CONFIG_MTU]({
children: message,
});
},
)}
onFirstRender={buildInputFirstRenderFunction(
INPUT_ID_ANVIL_NETWORK_CONFIG_MTU,
)}
valueType="number"
/>
),
},
}}
spacing="1em"
/>
);
};
export {
INPUT_ID_ANVIL_NETWORK_CONFIG_DNS,
INPUT_ID_ANVIL_NETWORK_CONFIG_MTU,
INPUT_ID_ANVIL_NETWORK_CONFIG_NTP,
};
export default AnvilNetworkConfigInputGroup;

@ -0,0 +1,174 @@
import { ReactElement, ReactNode, useEffect, useMemo } from 'react';
import Grid from '../Grid';
import IconButton from '../IconButton';
import InputWithRef from '../InputWithRef';
import OutlinedInputWithLabel from '../OutlinedInputWithLabel';
import { InnerPanel, InnerPanelBody, InnerPanelHeader } from '../Panels';
import { buildIPAddressTestBatch } from '../../lib/test_input';
import { BodyText } from '../Text';
const AnvilNetworkInputGroup = <M extends MapToInputTestID>({
formUtils: {
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
msgSetters,
setMsgSetter,
},
idPrefix,
inputGatewayId,
inputGatewayLabel = 'Gateway',
inputMinIpId,
inputMinIpLabel = 'IP address',
inputSubnetMaskId,
inputSubnetMaskLabel = 'Subnet mask',
networkName,
previous: {
gateway: previousGateway,
minIp: previousIpAddress,
subnetMask: previousSubnetMask,
} = {},
showGateway: isShowGateway,
}: AnvilNetworkInputGroupProps<M>): ReactElement => {
const inputCellGatewayId = useMemo(
() => `${idPrefix}-input-cell-gateway`,
[idPrefix],
);
const inputCellIpId = useMemo(() => `${idPrefix}-input-cell-ip`, [idPrefix]);
const inputCellSubnetMaskId = useMemo(
() => `${idPrefix}-input-cell-subnet-mask`,
[idPrefix],
);
const inputCellGatewayDisplay = useMemo(
() => (isShowGateway ? undefined : 'none'),
[isShowGateway],
);
const inputGatewayElement = useMemo<ReactNode>(() => {
let result: ReactNode;
if (isShowGateway && inputGatewayId) {
setMsgSetter(inputGatewayId);
result = (
<InputWithRef
input={
<OutlinedInputWithLabel
id={inputGatewayId}
label={inputGatewayLabel}
value={previousGateway}
/>
}
inputTestBatch={buildIPAddressTestBatch(
`${networkName} ${inputGatewayLabel}`,
() => {
msgSetters[inputGatewayId]();
},
{
onFinishBatch: buildFinishInputTestBatchFunction(inputGatewayId),
},
(message) => {
msgSetters[inputGatewayId]({
children: message,
});
},
)}
required={isShowGateway}
/>
);
}
return result;
}, [
isShowGateway,
inputGatewayId,
setMsgSetter,
inputGatewayLabel,
previousGateway,
networkName,
buildFinishInputTestBatchFunction,
msgSetters,
]);
useEffect(() => {
setMsgSetter(inputMinIpId);
setMsgSetter(inputSubnetMaskId);
}, [inputMinIpId, inputSubnetMaskId, setMsgSetter]);
return (
<InnerPanel mv={0}>
<InnerPanelHeader>
<BodyText>{networkName}</BodyText>
<IconButton
mapPreset="close"
iconProps={{ fontSize: 'small' }}
sx={{
padding: '.2em',
position: 'absolute',
right: '-.6rem',
top: '-.2rem',
}}
/>
</InnerPanelHeader>
<InnerPanelBody>
<Grid
layout={{
[inputCellIpId]: {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={inputMinIpId}
label={inputMinIpLabel}
value={previousIpAddress}
/>
}
inputTestBatch={buildIPAddressTestBatch(
`${networkName} ${inputMinIpLabel}`,
() => {
msgSetters[inputMinIpId]();
},
{
onFinishBatch:
buildFinishInputTestBatchFunction(inputMinIpId),
},
(message) => {
msgSetters[inputMinIpId]({
children: message,
});
},
)}
onFirstRender={buildInputFirstRenderFunction(inputMinIpId)}
required
/>
),
},
[inputCellSubnetMaskId]: {
children: (
<InputWithRef
input={
<OutlinedInputWithLabel
id={inputSubnetMaskId}
label={inputSubnetMaskLabel}
value={previousSubnetMask}
/>
}
required
/>
),
},
[inputCellGatewayId]: {
children: inputGatewayElement,
display: inputCellGatewayDisplay,
},
}}
spacing="1em"
/>
</InnerPanelBody>
</InnerPanel>
);
};
export default AnvilNetworkInputGroup;

@ -1,15 +1,40 @@
import { PlayCircle } from '@mui/icons-material'; import { PlayCircle } from '@mui/icons-material';
import { FC, useMemo, useState } from 'react'; import { FC, useMemo, useRef, useState } from 'react';
import API_BASE_URL from '../../lib/consts/API_BASE_URL'; import API_BASE_URL from '../../lib/consts/API_BASE_URL';
import periodicFetch from '../../lib/fetchers/periodicFetch';
import AddAnvilManifestInputGroup from './AddAnvilManifestInputGroup';
import {
INPUT_ID_ANVIL_ID_DOMAIN,
INPUT_ID_ANVIL_ID_PREFIX,
INPUT_ID_ANVIL_ID_SEQUENCE,
} from './AnvilIdInputGroup';
import {
INPUT_ID_ANVIL_NETWORK_CONFIG_DNS,
INPUT_ID_ANVIL_NETWORK_CONFIG_MTU,
INPUT_ID_ANVIL_NETWORK_CONFIG_NTP,
} from './AnvilNetworkConfigInputGroup';
import ConfirmDialog from '../ConfirmDialog';
import FlexBox from '../FlexBox'; import FlexBox from '../FlexBox';
import FormDialog from '../FormDialog';
import IconButton from '../IconButton'; import IconButton from '../IconButton';
import List from '../List'; import List from '../List';
import { MessageGroupForwardedRefContent } from '../MessageGroup';
import { Panel, PanelHeader } from '../Panels'; import { Panel, PanelHeader } from '../Panels';
import periodicFetch from '../../lib/fetchers/periodicFetch';
import Spinner from '../Spinner'; import Spinner from '../Spinner';
import { BodyText, HeaderText } from '../Text'; import { BodyText, HeaderText } from '../Text';
import useConfirmDialogProps from '../../hooks/useConfirmDialogProps';
import useFormUtils from '../../hooks/useFormUtils';
const ManageManifestPanel: FC = () => { const ManageManifestPanel: FC = () => {
const confirmDialogRef = useRef<ConfirmDialogForwardedRefContent>({});
const formDialogRef = useRef<ConfirmDialogForwardedRefContent>({});
const messageGroupRef = useRef<MessageGroupForwardedRefContent>({});
const [confirmDialogProps] = useConfirmDialogProps();
const [formDialogProps, setFormDialogProps] = useConfirmDialogProps();
const [isEditManifests, setIsEditManifests] = useState<boolean>(false); const [isEditManifests, setIsEditManifests] = useState<boolean>(false);
const { data: manifestOverviews, isLoading: isLoadingManifestOverviews } = const { data: manifestOverviews, isLoading: isLoadingManifestOverviews } =
@ -17,6 +42,28 @@ const ManageManifestPanel: FC = () => {
refreshInterval: 60000, refreshInterval: 60000,
}); });
const formUtils = useFormUtils(
[
INPUT_ID_ANVIL_ID_DOMAIN,
INPUT_ID_ANVIL_ID_PREFIX,
INPUT_ID_ANVIL_ID_SEQUENCE,
INPUT_ID_ANVIL_NETWORK_CONFIG_DNS,
INPUT_ID_ANVIL_NETWORK_CONFIG_MTU,
INPUT_ID_ANVIL_NETWORK_CONFIG_NTP,
],
messageGroupRef,
);
const { isFormInvalid } = formUtils;
const addAnvilManifestFormDialogProps = useMemo<ConfirmDialogProps>(
() => ({
actionProceedText: 'Add',
content: <AddAnvilManifestInputGroup formUtils={formUtils} />,
titleText: 'Add a Anvil! manifest',
}),
[formUtils],
);
const listElement = useMemo( const listElement = useMemo(
() => ( () => (
<List <List
@ -26,6 +73,10 @@ const ManageManifestPanel: FC = () => {
header header
listEmpty="No manifest(s) registered." listEmpty="No manifest(s) registered."
listItems={manifestOverviews} listItems={manifestOverviews}
onAdd={() => {
setFormDialogProps(addAnvilManifestFormDialogProps);
formDialogRef.current.setOpen?.call(null, true);
}}
onEdit={() => { onEdit={() => {
setIsEditManifests((previous) => !previous); setIsEditManifests((previous) => !previous);
}} }}
@ -39,7 +90,12 @@ const ManageManifestPanel: FC = () => {
)} )}
/> />
), ),
[isEditManifests, manifestOverviews], [
addAnvilManifestFormDialogProps,
isEditManifests,
manifestOverviews,
setFormDialogProps,
],
); );
const panelContent = useMemo( const panelContent = useMemo(
@ -48,12 +104,26 @@ const ManageManifestPanel: FC = () => {
); );
return ( return (
<Panel> <>
<PanelHeader> <Panel>
<HeaderText>Manage manifests</HeaderText> <PanelHeader>
</PanelHeader> <HeaderText>Manage manifests</HeaderText>
{panelContent} </PanelHeader>
</Panel> {panelContent}
</Panel>
<FormDialog
{...formDialogProps}
ref={formDialogRef}
proceedButtonProps={{ disabled: isFormInvalid }}
scrollBoxProps={{
paddingRight: '.4em',
paddingTop: '.6em',
sx: { overflowX: 'hidden' },
}}
scrollContent
/>
<ConfirmDialog {...confirmDialogProps} ref={confirmDialogRef} />
</>
); );
}; };

@ -0,0 +1,94 @@
type AnvilIdInputGroupOptionalProps = {
previous?: {
anvilIdPrefix?: string;
anvilIdDomain?: string;
anvilIdSequence?: number;
};
};
type AnvilIdInputGroupProps<M extends MapToInputTestID> =
AnvilIdInputGroupOptionalProps & {
formUtils: FormUtils<M>;
};
type AnvilNetworkInputGroupOptionalProps = {
inputGatewayId?: string;
inputGatewayLabel?: string;
inputMinIpLabel?: string;
inputSubnetMaskLabel?: string;
previous?: {
gateway?: string;
minIp?: string;
subnetMask?: string;
};
showGateway?: boolean;
};
type AnvilNetworkInputGroupProps<M extends MapToInputTestID> =
AnvilNetworkInputGroupOptionalProps & {
formUtils: FormUtils<M>;
idPrefix: string;
inputMinIpId: string;
inputSubnetMaskId: string;
networkName: string;
};
type AnvilHostInputGroupOptionalProps = {
previous?: {
fences?: {
[fenceId: string]: {
fenceName: string;
fencePort: number;
};
};
networks?: {
[networkId: string]: {
networkIp: string;
networkNumber: number;
networkType: string;
};
};
upses?: {
[upsId: string]: {
isPowerHost: boolean;
upsName: string;
};
};
};
};
type AnvilHostInputGroupProps<M extends MapToInputTestID> =
AnvilHostInputGroupOptionalProps & {
formUtils: FormUtils<M>;
hostLabel: string;
idPrefix: string;
};
type AnvilNetworkConfigNetwork = {
networkGateway?: string;
networkMinIp: string;
networkNumber: number;
networkSubnetMask: string;
networkType: string;
};
type AnvilNetworkConfigInputGroupOptionalProps = {
previous?: {
dnsCsv?: string;
/** Max Transmission Unit (MTU); unit: bytes */
mtu?: number;
networks?: {
[networkId: string]: AnvilNetworkConfigNetwork;
};
ntpCsv?: string;
};
};
type AnvilNetworkConfigInputGroupProps<M extends MapToInputTestID> =
AnvilNetworkConfigInputGroupOptionalProps & {
formUtils: FormUtils<M>;
};
type AddAnvilInputGroupProps<M extends MapToInputTestID> = {
formUtils: FormUtils<M>;
};
Loading…
Cancel
Save