Merge pull request #402 from ylei-tsubame/issues/399-populate-network-config

Web UI: auto-suggest partial or whole IP and subnet mask for host networks during config
main
Digimer 1 year ago committed by GitHub
commit bbb6c96ece
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 75
      striker-ui/components/GeneralInitForm.tsx
  2. 280
      striker-ui/components/NetworkInitForm.tsx
  3. 5
      striker-ui/components/StrikerInitForm.tsx
  4. 2
      striker-ui/out/_next/static/8B2qFvgX8u8D8ZWgE33V8/_buildManifest.js
  5. 0
      striker-ui/out/_next/static/8B2qFvgX8u8D8ZWgE33V8/_middlewareManifest.js
  6. 0
      striker-ui/out/_next/static/8B2qFvgX8u8D8ZWgE33V8/_ssgManifest.js
  7. 1
      striker-ui/out/_next/static/chunks/692-59a4ae2829590f4c.js
  8. 1
      striker-ui/out/_next/static/chunks/692-64941f28ab144919.js
  9. 1
      striker-ui/out/_next/static/chunks/pages/init-7428606d331bc1dd.js
  10. 1
      striker-ui/out/_next/static/chunks/pages/init-ae1befa8975f7914.js
  11. 2
      striker-ui/out/anvil.html
  12. 2
      striker-ui/out/config.html
  13. 2
      striker-ui/out/file-manager.html
  14. 2
      striker-ui/out/index.html
  15. 2
      striker-ui/out/init.html
  16. 2
      striker-ui/out/login.html
  17. 2
      striker-ui/out/manage-element.html
  18. 2
      striker-ui/out/server.html

@ -96,12 +96,24 @@ const GeneralInitForm = forwardRef<
{ {
expectHostDetail?: boolean; expectHostDetail?: boolean;
hostDetail?: APIHostDetail; hostDetail?: APIHostDetail;
onHostNumberBlurAppend?: OutlinedInputWithLabelProps['onBlur'];
toggleSubmitDisabled?: ToggleSubmitDisabledFunction; toggleSubmitDisabled?: ToggleSubmitDisabledFunction;
} }
>(({ expectHostDetail = false, hostDetail, toggleSubmitDisabled }, ref) => { >(
(
{
expectHostDetail = false,
hostDetail,
onHostNumberBlurAppend,
toggleSubmitDisabled,
},
ref,
) => {
const [helpMessage, setHelpMessage] = useState<ReactNode | undefined>(); const [helpMessage, setHelpMessage] = useState<ReactNode | undefined>();
const [isShowOrganizationPrefixSuggest, setIsShowOrganizationPrefixSuggest] = const [
useState<boolean>(false); isShowOrganizationPrefixSuggest,
setIsShowOrganizationPrefixSuggest,
] = useState<boolean>(false);
const [isShowHostNameSuggest, setIsShowHostNameSuggest] = const [isShowHostNameSuggest, setIsShowHostNameSuggest] =
useState<boolean>(false); useState<boolean>(false);
const [isConfirmAdminPassword, setIsConfirmAdminPassword] = const [isConfirmAdminPassword, setIsConfirmAdminPassword] =
@ -110,16 +122,18 @@ const GeneralInitForm = forwardRef<
const readHostDetailRef = useRef<boolean>(true); const readHostDetailRef = useRef<boolean>(true);
const adminPasswordInputRef = useRef<InputForwardedRefContent<'string'>>({}); const adminPasswordInputRef = useRef<InputForwardedRefContent<'string'>>(
{},
);
const confirmAdminPasswordInputRef = useRef< const confirmAdminPasswordInputRef = useRef<
InputForwardedRefContent<'string'> InputForwardedRefContent<'string'>
>({}); >({});
const organizationNameInputRef = useRef<InputForwardedRefContent<'string'>>( const organizationNameInputRef = useRef<InputForwardedRefContent<'string'>>(
{}, {},
); );
const organizationPrefixInputRef = useRef<InputForwardedRefContent<'string'>>( const organizationPrefixInputRef = useRef<
{}, InputForwardedRefContent<'string'>
); >({});
const domainNameInputRef = useRef<InputForwardedRefContent<'string'>>({}); const domainNameInputRef = useRef<InputForwardedRefContent<'string'>>({});
const hostNumberInputRef = useRef<InputForwardedRefContent<'number'>>({}); const hostNumberInputRef = useRef<InputForwardedRefContent<'number'>>({});
const hostNameInputRef = useRef<InputForwardedRefContent<'string'>>({}); const hostNameInputRef = useRef<InputForwardedRefContent<'string'>>({});
@ -154,7 +168,11 @@ const GeneralInitForm = forwardRef<
); );
const setHostNameInputMessage = useCallback( const setHostNameInputMessage = useCallback(
(message?: Message) => (message?: Message) =>
messageGroupRef.current.setMessage?.call(null, IT_IDS.hostName, message), messageGroupRef.current.setMessage?.call(
null,
IT_IDS.hostName,
message,
),
[], [],
); );
const setAdminPasswordInputMessage = useCallback( const setAdminPasswordInputMessage = useCallback(
@ -243,8 +261,8 @@ const GeneralInitForm = forwardRef<
setDomainNameInputMessage({ setDomainNameInputMessage({
children: ( children: (
<> <>
Domain name can only contain lowercase alphanumeric, hyphen Domain name can only contain lowercase alphanumeric,
(<InlineMonoText text="-" /> hyphen (<InlineMonoText text="-" />
), and dot (<InlineMonoText text="." />) characters. ), and dot (<InlineMonoText text="." />) characters.
</> </>
), ),
@ -270,7 +288,8 @@ const GeneralInitForm = forwardRef<
setHostNameInputMessage({ setHostNameInputMessage({
children: ( children: (
<> <>
Host name can only contain lowercase alphanumeric, hyphen ( Host name can only contain lowercase alphanumeric, hyphen
(
<InlineMonoText text="-" /> <InlineMonoText text="-" />
), and dot (<InlineMonoText text="." />) characters. ), and dot (<InlineMonoText text="." />) characters.
</> </>
@ -304,7 +323,8 @@ const GeneralInitForm = forwardRef<
}, },
[IT_IDS.organizationName]: { [IT_IDS.organizationName]: {
defaults: { defaults: {
getValue: () => organizationNameInputRef.current.getValue?.call(null), getValue: () =>
organizationNameInputRef.current.getValue?.call(null),
}, },
tests: [{ test: testNotBlank }], tests: [{ test: testNotBlank }],
}, },
@ -377,7 +397,9 @@ const GeneralInitForm = forwardRef<
); );
const populateOrganizationPrefixInput = useCallback( const populateOrganizationPrefixInput = useCallback(
({ ({
organizationName = organizationNameInputRef.current.getValue?.call(null), organizationName = organizationNameInputRef.current.getValue?.call(
null,
),
} = {}) => { } = {}) => {
const organizationPrefix = buildOrganizationPrefix(organizationName); const organizationPrefix = buildOrganizationPrefix(organizationName);
@ -443,7 +465,9 @@ const GeneralInitForm = forwardRef<
const populateOrganizationPrefixInputOnBlur: OutlinedInputWithLabelOnBlur = const populateOrganizationPrefixInputOnBlur: OutlinedInputWithLabelOnBlur =
useCallback(() => { useCallback(() => {
if (organizationPrefixInputRef.current.getIsChangedByUser?.call(null)) { if (organizationPrefixInputRef.current.getIsChangedByUser?.call(null)) {
setIsShowOrganizationPrefixSuggest(isOrganizationPrefixPrereqFilled()); setIsShowOrganizationPrefixSuggest(
isOrganizationPrefixPrereqFilled(),
);
} else { } else {
populateOrganizationPrefixInput(); populateOrganizationPrefixInput();
} }
@ -640,7 +664,8 @@ const GeneralInitForm = forwardRef<
minWidth: '2em', minWidth: '2em',
}, },
}, },
onBlur: (event, ...restArgs) => { onBlur: (...args) => {
const [event] = args;
const { const {
target: { value }, target: { value },
} = event; } = event;
@ -648,7 +673,9 @@ const GeneralInitForm = forwardRef<
testInput({ testInput({
inputs: { [IT_IDS.hostNumber]: { value } }, inputs: { [IT_IDS.hostNumber]: { value } },
}); });
populateHostNameInputOnBlur(event, ...restArgs); populateHostNameInputOnBlur(...args);
onHostNumberBlurAppend?.call(null, ...args);
}, },
}} }}
inputLabelProps={{ isNotifyRequired: true }} inputLabelProps={{ isNotifyRequired: true }}
@ -686,7 +713,9 @@ const GeneralInitForm = forwardRef<
target: { value }, target: { value },
} = event; } = event;
testInput({ inputs: { [IT_IDS.domainName]: { value } } }); testInput({
inputs: { [IT_IDS.domainName]: { value } },
});
populateHostNameInputOnBlur(event, ...restArgs); populateHostNameInputOnBlur(event, ...restArgs);
}, },
}} }}
@ -780,7 +809,9 @@ const GeneralInitForm = forwardRef<
isExcludeConfirmAdminPassword: isExcludeConfirmAdminPassword:
!localIsConfirmAdminPassword, !localIsConfirmAdminPassword,
}); });
setIsConfirmAdminPassword(localIsConfirmAdminPassword); setIsConfirmAdminPassword(
localIsConfirmAdminPassword,
);
setConfirmAdminPasswordInputMessage(); setConfirmAdminPasswordInputMessage();
}, },
}} }}
@ -828,7 +859,9 @@ const GeneralInitForm = forwardRef<
label="Confirm password" label="Confirm password"
onChange={({ target: { value } }) => { onChange={({ target: { value } }) => {
testInputToToggleSubmitDisabled({ testInputToToggleSubmitDisabled({
inputs: { [IT_IDS.confirmAdminPassword]: { value } }, inputs: {
[IT_IDS.confirmAdminPassword]: { value },
},
}); });
setConfirmAdminPasswordInputMessage(); setConfirmAdminPasswordInputMessage();
}} }}
@ -867,11 +900,13 @@ const GeneralInitForm = forwardRef<
)} )}
</FlexBox> </FlexBox>
); );
}); },
);
GeneralInitForm.defaultProps = { GeneralInitForm.defaultProps = {
expectHostDetail: false, expectHostDetail: false,
hostDetail: undefined, hostDetail: undefined,
onHostNumberBlurAppend: undefined,
toggleSubmitDisabled: undefined, toggleSubmitDisabled: undefined,
}; };

@ -110,42 +110,6 @@ const CLASSES = {
const INITIAL_IFACES = [undefined, undefined]; const INITIAL_IFACES = [undefined, undefined];
const MSG_ID_API = 'api'; const MSG_ID_API = 'api';
const STRIKER_REQUIRED_NETWORKS: NetworkInput[] = [
{
inputUUID: '30dd2ac5-8024-4a7e-83a1-6a3df7218972',
interfaces: [...INITIAL_IFACES],
ipAddress: '10.200.1.1',
isRequired: true,
name: `${NETWORK_TYPES.bcn} 1`,
subnetMask: '255.255.0.0',
type: 'bcn',
typeCount: 1,
},
{
inputUUID: 'e7ef3af5-5602-440c-87f8-69c242e3d7f3',
interfaces: [...INITIAL_IFACES],
ipAddress: '10.201.1.1',
isRequired: true,
name: `${NETWORK_TYPES.ifn} 1`,
subnetMask: '255.255.0.0',
type: 'ifn',
typeCount: 1,
},
];
const NODE_REQUIRED_NETWORKS: NetworkInput[] = [
...STRIKER_REQUIRED_NETWORKS,
{
inputUUID: '525e4847-f929-44a7-83b2-28eb289ffb57',
interfaces: [...INITIAL_IFACES],
ipAddress: '10.202.1.1',
isRequired: true,
name: `${NETWORK_TYPES.sn} 1`,
subnetMask: '255.255.0.0',
type: 'sn',
typeCount: 1,
},
];
const MAX_INTERFACES_PER_NETWORK = 2; const MAX_INTERFACES_PER_NETWORK = 2;
const IT_IDS = { const IT_IDS = {
dnsCSV: 'dns', dnsCSV: 'dns',
@ -161,9 +125,56 @@ const NETWORK_INTERFACE_TEMPLATE = Array.from(
{ length: MAX_INTERFACES_PER_NETWORK }, { length: MAX_INTERFACES_PER_NETWORK },
(unused, index) => index + 1, (unused, index) => index + 1,
); );
const MAP_TO_NETWORK_TYPE_DEFAULTS: Record<
string,
{ ip: (sequence: number | string, postfix?: string) => string; mask: string }
> = {
bcn: {
ip: (sequence, postfix = '') => `10.20${sequence}.${postfix}`,
mask: '255.255.0.0',
},
ifn: { ip: () => '', mask: '' },
mn: { ip: () => '10.199.', mask: '255.255.0.0' },
sn: {
ip: (sequence, postfix = '') => `10.10${sequence}.${postfix}`,
mask: '255.255.0.0',
},
};
const createInputTestPrefix = (uuid: string) => `network${uuid}`; const createInputTestPrefix = (uuid: string) => `network${uuid}`;
const createNetworkInput = ({
inputUUID = uuidv4(),
interfaces = [...INITIAL_IFACES],
ipAddress = '',
name: initName,
subnetMask = '',
type = '',
typeCount = 0,
...rest
}: Partial<NetworkInput> = {}): NetworkInput => {
let name = initName;
if (!initName) {
if (NETWORK_TYPES[type] && typeCount > 0) {
name = `${NETWORK_TYPES[type]} ${typeCount}`;
} else {
name = 'Unknown Network';
}
}
return {
inputUUID,
interfaces,
ipAddress,
name,
subnetMask,
type,
typeCount,
...rest,
};
};
const createNetworkInterfaceTableColumns = ( const createNetworkInterfaceTableColumns = (
handleDragMouseDown: ( handleDragMouseDown: (
row: NetworkInterfaceOverviewMetadata, row: NetworkInterfaceOverviewMetadata,
@ -265,12 +276,13 @@ const createNetworkInterfaceTableColumns = (
]; ];
const NetworkForm: FC<{ const NetworkForm: FC<{
allowMigrationNetwork?: boolean;
createDropMouseUpHandler?: ( createDropMouseUpHandler?: (
interfaces: (NetworkInterfaceOverviewMetadata | undefined)[], interfaces: (NetworkInterfaceOverviewMetadata | undefined)[],
interfaceIndex: number, interfaceIndex: number,
) => MUIBoxProps['onMouseUp']; ) => MUIBoxProps['onMouseUp'];
getNetworkTypeCount: GetNetworkTypeCountFunction; getNetworkTypeCount: GetNetworkTypeCountFunction;
hostDetail?: APIHostDetail; hostDetail?: Partial<Pick<APIHostDetail, 'hostType' | 'sequence'>>;
networkIndex: number; networkIndex: number;
networkInput: NetworkInput; networkInput: NetworkInput;
networkInterfaceCount: number; networkInterfaceCount: number;
@ -284,9 +296,10 @@ const NetworkForm: FC<{
testInput: (options?: TestInputFunctionOptions) => boolean; testInput: (options?: TestInputFunctionOptions) => boolean;
testInputToToggleSubmitDisabled: TestInputToToggleSubmitDisabled; testInputToToggleSubmitDisabled: TestInputToToggleSubmitDisabled;
}> = ({ }> = ({
allowMigrationNetwork,
createDropMouseUpHandler, createDropMouseUpHandler,
getNetworkTypeCount, getNetworkTypeCount,
hostDetail: { hostType } = {}, hostDetail: { hostType, sequence } = {},
networkIndex, networkIndex,
networkInput, networkInput,
networkInterfaceCount, networkInterfaceCount,
@ -345,10 +358,48 @@ const NetworkForm: FC<{
const netTypeList = useMemo(() => { const netTypeList = useMemo(() => {
const { bcn, ifn, mn, sn } = NETWORK_TYPES; const { bcn, ifn, mn, sn } = NETWORK_TYPES;
return isNode && networkInterfaceCount >= 8 return isNode &&
networkInterfaceCount >= 8 &&
(allowMigrationNetwork || type === 'mn')
? { bcn, ifn, mn, sn } ? { bcn, ifn, mn, sn }
: { bcn, ifn, sn }; : { bcn, ifn, sn };
}, [isNode, networkInterfaceCount]); }, [allowMigrationNetwork, isNode, networkInterfaceCount, type]);
const setIpAndMask = useCallback(
(nInput: NetworkInput, ip: string, mask: string) => {
const {
current: { getIsChangedByUser: getIpModded, setValue: setIp },
} = ipAddressInputRef;
const {
current: { getIsChangedByUser: getMaskModded, setValue: setMask },
} = subnetMaskInputRef;
if (!getIpModded?.call(null)) {
nInput.ipAddress = ip;
setIp?.call(null, ip);
}
if (!getMaskModded?.call(null)) {
nInput.subnetMask = mask;
setMask?.call(null, mask);
}
},
[],
);
useEffect((): void => {
if (hostType !== 'striker' || type === 'ifn') return;
const changedByUser =
ipAddressInputRef.current.getIsChangedByUser?.call(null);
if (changedByUser || !Number(sequence)) return;
ipAddressInputRef.current.setValue?.call(
null,
ipAddress.replace(/^((?:\d+\.){3})\d*$/, `$1${sequence}`),
);
}, [hostType, ipAddress, sequence, type]);
useEffect(() => { useEffect(() => {
const { ipAddressInputRef: ipRef, subnetMaskInputRef: maskRef } = const { ipAddressInputRef: ipRef, subnetMaskInputRef: maskRef } =
@ -398,6 +449,21 @@ const NetworkForm: FC<{
networkInput.typeCount = networkTypeCount; networkInput.typeCount = networkTypeCount;
networkInput.name = `${NETWORK_TYPES[networkType]} ${networkTypeCount}`; networkInput.name = `${NETWORK_TYPES[networkType]} ${networkTypeCount}`;
const networkTypeDefaults =
MAP_TO_NETWORK_TYPE_DEFAULTS[networkType];
if (networkTypeDefaults) {
const { ip, mask } = networkTypeDefaults;
let postfix: string | undefined;
if (hostType === 'striker' && networkType === 'bcn') {
postfix = '4.';
}
setIpAndMask(networkInput, ip(networkTypeCount, postfix), mask);
}
setNetworkInputs((previous) => [...previous]); setNetworkInputs((previous) => [...previous]);
}, },
renderValue: breakpointLarge renderValue: breakpointLarge
@ -570,6 +636,7 @@ const NetworkForm: FC<{
}; };
NetworkForm.defaultProps = { NetworkForm.defaultProps = {
allowMigrationNetwork: true,
createDropMouseUpHandler: undefined, createDropMouseUpHandler: undefined,
hostDetail: undefined, hostDetail: undefined,
}; };
@ -579,18 +646,78 @@ const NetworkInitForm = forwardRef<
{ {
expectHostDetail?: boolean; expectHostDetail?: boolean;
hostDetail?: APIHostDetail; hostDetail?: APIHostDetail;
hostSequence?: string;
toggleSubmitDisabled?: (testResult: boolean) => void; toggleSubmitDisabled?: (testResult: boolean) => void;
} }
>(({ expectHostDetail = false, hostDetail, toggleSubmitDisabled }, ref) => { >(
const { hostType, hostUUID = 'local' }: APIHostDetail = (
hostDetail ?? ({} as APIHostDetail); {
expectHostDetail = false,
hostDetail,
hostSequence,
toggleSubmitDisabled,
},
ref,
) => {
let hostType: string | undefined;
let hostUUID = 'local';
let sequence = hostSequence;
if (!expectHostDetail) {
hostType = 'striker';
} else if (hostDetail) {
({ hostType, hostUUID, sequence } = hostDetail);
}
const uninitRequiredNetworks: NetworkInput[] = useMemo( const initRequiredNetworks: NetworkInput[] = useMemo(() => {
() => const result: NetworkInput[] = [];
hostType === 'node' ? NODE_REQUIRED_NETWORKS : STRIKER_REQUIRED_NETWORKS,
[hostType], if (hostType === 'striker') {
const ipAddress = sequence ? `10.201.4.${sequence}` : '10.201.4.';
result.push(
createNetworkInput({
ipAddress,
isRequired: true,
subnetMask: '255.255.0.0',
type: 'bcn',
typeCount: 1,
}),
createNetworkInput({
isRequired: true,
type: 'ifn',
typeCount: 1,
}),
); );
return result;
}
result.push(
createNetworkInput({
ipAddress: '10.201.',
isRequired: true,
subnetMask: '255.255.0.0',
type: 'bcn',
typeCount: 1,
}),
createNetworkInput({
isRequired: true,
type: 'ifn',
typeCount: 1,
}),
createNetworkInput({
ipAddress: '10.101.',
isRequired: true,
subnetMask: '255.255.0.0',
type: 'sn',
typeCount: 1,
}),
);
return result;
}, [hostType, sequence]);
const requiredNetworks = useMemo<Partial<Record<NetworkType, number>>>( const requiredNetworks = useMemo<Partial<Record<NetworkType, number>>>(
() => () =>
hostType === 'node' ? { bcn: 1, ifn: 1, sn: 1 } : { bcn: 1, ifn: 1 }, hostType === 'node' ? { bcn: 1, ifn: 1, sn: 1 } : { bcn: 1, ifn: 1 },
@ -603,9 +730,8 @@ const NetworkInitForm = forwardRef<
}>({ x: 0, y: 0 }); }>({ x: 0, y: 0 });
const [networkInterfaceInputMap, setNetworkInterfaceInputMap] = const [networkInterfaceInputMap, setNetworkInterfaceInputMap] =
useState<NetworkInterfaceInputMap>({}); useState<NetworkInterfaceInputMap>({});
const [networkInputs, setNetworkInputs] = useState<NetworkInput[]>( const [networkInputs, setNetworkInputs] =
uninitRequiredNetworks, useState<NetworkInput[]>(initRequiredNetworks);
);
const [networkInterfaceHeld, setNetworkInterfaceHeld] = useState< const [networkInterfaceHeld, setNetworkInterfaceHeld] = useState<
NetworkInterfaceOverviewMetadata | undefined NetworkInterfaceOverviewMetadata | undefined
>(); >();
@ -657,6 +783,13 @@ const NetworkInitForm = forwardRef<
() => expectHostDetail && !hostDetail, () => expectHostDetail && !hostDetail,
[expectHostDetail, hostDetail], [expectHostDetail, hostDetail],
); );
/**
* Allow user to add migration network only if none exists.
*/
const allowMigrationNetwork: boolean = useMemo(
() => networkInputs.every(({ type }) => type !== 'mn'),
[networkInputs],
);
const setMessage = useCallback( const setMessage = useCallback(
(key: string, message?: Message) => (key: string, message?: Message) =>
@ -845,7 +978,8 @@ const NetworkInitForm = forwardRef<
const inputTestPrefix = createInputTestPrefix(inputUUID); const inputTestPrefix = createInputTestPrefix(inputUUID);
const inputTestIDIfaces = IT_IDS.networkInterfaces(inputTestPrefix); const inputTestIDIfaces = IT_IDS.networkInterfaces(inputTestPrefix);
const inputTestIDIPAddress = IT_IDS.networkIPAddress(inputTestPrefix); const inputTestIDIPAddress = IT_IDS.networkIPAddress(inputTestPrefix);
const inputTestIDSubnetMask = IT_IDS.networkSubnetMask(inputTestPrefix); const inputTestIDSubnetMask =
IT_IDS.networkSubnetMask(inputTestPrefix);
const setNetworkIfacesInputMessage = (message?: Message) => const setNetworkIfacesInputMessage = (message?: Message) =>
setMessage(inputTestIDIfaces, message); setMessage(inputTestIDIfaces, message);
@ -1010,24 +1144,8 @@ const NetworkInitForm = forwardRef<
setNetworkInterfaceHeld(undefined); setNetworkInterfaceHeld(undefined);
}, []); }, []);
const createNetwork = useCallback( const createNetwork = useCallback(
({ (args: Partial<NetworkInput> = {}) => {
inputUUID = uuidv4(), networkInputs.unshift(createNetworkInput(args));
interfaces = [...INITIAL_IFACES],
ipAddress = '',
name = 'Unknown Network',
subnetMask = '',
type = '',
typeCount = 0,
}: Partial<NetworkInput> = {}) => {
networkInputs.unshift({
inputUUID,
interfaces,
ipAddress,
name,
subnetMask,
type,
typeCount,
});
toggleSubmitDisabled?.call(null, false); toggleSubmitDisabled?.call(null, false);
setNetworkInputs([...networkInputs]); setNetworkInputs([...networkInputs]);
@ -1036,7 +1154,10 @@ const NetworkInitForm = forwardRef<
); );
const removeNetwork = useCallback( const removeNetwork = useCallback(
(networkIndex: number) => { (networkIndex: number) => {
const [{ inputUUID, interfaces }] = networkInputs.splice(networkIndex, 1); const [{ inputUUID, interfaces }] = networkInputs.splice(
networkIndex,
1,
);
interfaces.forEach((iface) => { interfaces.forEach((iface) => {
if (iface === undefined) { if (iface === undefined) {
@ -1056,7 +1177,11 @@ const NetworkInitForm = forwardRef<
...previous, ...previous,
})); }));
}, },
[networkInputs, networkInterfaceInputMap, testInputToToggleSubmitDisabled], [
networkInputs,
networkInterfaceInputMap,
testInputToToggleSubmitDisabled,
],
); );
const getNetworkTypeCount: GetNetworkTypeCountFunction = useCallback( const getNetworkTypeCount: GetNetworkTypeCountFunction = useCallback(
( (
@ -1198,7 +1323,8 @@ const NetworkInitForm = forwardRef<
const applied: string[] = []; const applied: string[] = [];
const inputs = Object.values(pNetworks).reduce<NetworkInput[]>( const inputs = Object.values(pNetworks).reduce<NetworkInput[]>(
(previous, { ip, link1Uuid, link2Uuid = '', subnetMask, type }) => { (previous, { ip, link1Uuid, link2Uuid = '', subnetMask, type }) => {
const typeCount = getNetworkTypeCount(type, { inputs: previous }) + 1; const typeCount =
getNetworkTypeCount(type, { inputs: previous }) + 1;
const isRequired = requiredNetworks[type] === typeCount; const isRequired = requiredNetworks[type] === typeCount;
const name = `${NETWORK_TYPES[type]} ${typeCount}`; const name = `${NETWORK_TYPES[type]} ${typeCount}`;
@ -1299,7 +1425,8 @@ const NetworkInitForm = forwardRef<
interfaces, interfaces,
ipAddress: ipAddressInputRef?.current.getValue?.call(null) ?? '', ipAddress: ipAddressInputRef?.current.getValue?.call(null) ?? '',
name, name,
subnetMask: subnetMaskInputRef?.current.getValue?.call(null) ?? '', subnetMask:
subnetMaskInputRef?.current.getValue?.call(null) ?? '',
type, type,
typeCount, typeCount,
}), }),
@ -1445,9 +1572,10 @@ const NetworkInitForm = forwardRef<
<NetworkForm <NetworkForm
key={`network-${inputUUID}`} key={`network-${inputUUID}`}
{...{ {...{
allowMigrationNetwork,
createDropMouseUpHandler, createDropMouseUpHandler,
getNetworkTypeCount, getNetworkTypeCount,
hostDetail, hostDetail: { hostType, sequence },
networkIndex, networkIndex,
networkInput, networkInput,
networkInterfaceCount: networkInterfaces.length, networkInterfaceCount: networkInterfaces.length,
@ -1535,11 +1663,13 @@ const NetworkInitForm = forwardRef<
</MUIBox> </MUIBox>
</MUIBox> </MUIBox>
); );
}); },
);
NetworkInitForm.defaultProps = { NetworkInitForm.defaultProps = {
expectHostDetail: false, expectHostDetail: false,
hostDetail: undefined, hostDetail: undefined,
hostSequence: undefined,
toggleSubmitDisabled: undefined, toggleSubmitDisabled: undefined,
}; };
NetworkInitForm.displayName = 'NetworkInitForm'; NetworkInitForm.displayName = 'NetworkInitForm';

@ -48,6 +48,7 @@ const StrikerInitForm: FC = () => {
const [isNetworkInitFormValid, setIsNetworkInitFormValid] = const [isNetworkInitFormValid, setIsNetworkInitFormValid] =
useState<boolean>(false); useState<boolean>(false);
const [isSubmittingForm, setIsSubmittingForm] = useState<boolean>(false); const [isSubmittingForm, setIsSubmittingForm] = useState<boolean>(false);
const [hostNumber, setHostNumber] = useState<string | undefined>();
const [hostDetail, setHostDetail] = useProtectedState< const [hostDetail, setHostDetail] = useProtectedState<
APIHostDetail | undefined APIHostDetail | undefined
@ -147,6 +148,9 @@ const StrikerInitForm: FC = () => {
<GeneralInitForm <GeneralInitForm
expectHostDetail={reconfig} expectHostDetail={reconfig}
hostDetail={hostDetail} hostDetail={hostDetail}
onHostNumberBlurAppend={({ target: { value } }) => {
setHostNumber(value);
}}
ref={generalInitFormRef} ref={generalInitFormRef}
toggleSubmitDisabled={(testResult) => { toggleSubmitDisabled={(testResult) => {
if (testResult !== isGeneralInitFormValid) { if (testResult !== isGeneralInitFormValid) {
@ -158,6 +162,7 @@ const StrikerInitForm: FC = () => {
<NetworkInitForm <NetworkInitForm
expectHostDetail={reconfig} expectHostDetail={reconfig}
hostDetail={hostDetail} hostDetail={hostDetail}
hostSequence={hostNumber}
ref={networkInitFormRef} ref={networkInitFormRef}
toggleSubmitDisabled={(testResult) => { toggleSubmitDisabled={(testResult) => {
if (testResult !== isNetworkInitFormValid) { if (testResult !== isNetworkInitFormValid) {

@ -1 +1 @@
self.__BUILD_MANIFEST=function(s,c,a,e,t,n,i,f,d,u,b,k,h,j,r,g){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,a,e,i,f,k,"static/chunks/717-8bd60b96d67fd464.js",c,t,n,d,h,j,"static/chunks/pages/index-1f8f0ad3b3894dbc.js"],"/_error":["static/chunks/pages/_error-2280fa386d040b66.js"],"/anvil":[s,a,e,i,f,k,c,t,n,d,h,"static/chunks/pages/anvil-c1177b17efcafc34.js"],"/config":[s,a,e,u,c,t,n,b,"static/chunks/pages/config-0ecdb2b2b3f8c089.js"],"/file-manager":[s,a,e,i,"static/chunks/768-9ee3dcb62beecb53.js",c,t,"static/chunks/pages/file-manager-1a707639a4834587.js"],"/init":[s,a,i,f,u,r,c,t,n,d,g,"static/chunks/pages/init-ae1befa8975f7914.js"],"/login":[s,a,e,c,t,n,b,"static/chunks/pages/login-b5de0cd2f49998d6.js"],"/manage-element":[s,a,e,i,f,u,r,"static/chunks/195-d5fd184cc249f755.js",c,t,n,d,b,g,"static/chunks/pages/manage-element-2b1d8792c2a5bf47.js"],"/server":[s,e,"static/chunks/227-a3756585a7ef09ae.js",c,j,"static/chunks/pages/server-db52258419acacf3.js"],sortedPages:["/","/_app","/_error","/anvil","/config","/file-manager","/init","/login","/manage-element","/server"]}}("static/chunks/382-f51344f6f9208507.js","static/chunks/62-532ed713980da8db.js","static/chunks/483-f8013e38dca1620d.js","static/chunks/894-e57948de523bcf96.js","static/chunks/780-e8b3396d257460a4.js","static/chunks/899-83e9de2a35c6bcf0.js","static/chunks/182-08683bbe95fbb010.js","static/chunks/614-0ce04fd295045ffe.js","static/chunks/140-ec935fb15330b98a.js","static/chunks/644-c7c6e21c71345aed.js","static/chunks/903-dc2a40be612a10c3.js","static/chunks/485-77798bccc4308d0e.js","static/chunks/825-d34974d169ea09cc.js","static/chunks/94-db0af749b6e45543.js","static/chunks/676-6159ce853338cc1f.js","static/chunks/692-59a4ae2829590f4c.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); self.__BUILD_MANIFEST=function(s,c,a,e,t,n,i,f,d,b,u,k,h,j,r,g){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,a,e,i,f,k,"static/chunks/717-8bd60b96d67fd464.js",c,t,n,d,h,j,"static/chunks/pages/index-1f8f0ad3b3894dbc.js"],"/_error":["static/chunks/pages/_error-2280fa386d040b66.js"],"/anvil":[s,a,e,i,f,k,c,t,n,d,h,"static/chunks/pages/anvil-c1177b17efcafc34.js"],"/config":[s,a,e,b,c,t,n,u,"static/chunks/pages/config-0ecdb2b2b3f8c089.js"],"/file-manager":[s,a,e,i,"static/chunks/768-9ee3dcb62beecb53.js",c,t,"static/chunks/pages/file-manager-1a707639a4834587.js"],"/init":[s,a,i,f,b,r,c,t,n,d,g,"static/chunks/pages/init-7428606d331bc1dd.js"],"/login":[s,a,e,c,t,n,u,"static/chunks/pages/login-b5de0cd2f49998d6.js"],"/manage-element":[s,a,e,i,f,b,r,"static/chunks/195-d5fd184cc249f755.js",c,t,n,d,u,g,"static/chunks/pages/manage-element-2b1d8792c2a5bf47.js"],"/server":[s,e,"static/chunks/227-a3756585a7ef09ae.js",c,j,"static/chunks/pages/server-db52258419acacf3.js"],sortedPages:["/","/_app","/_error","/anvil","/config","/file-manager","/init","/login","/manage-element","/server"]}}("static/chunks/382-f51344f6f9208507.js","static/chunks/62-532ed713980da8db.js","static/chunks/483-f8013e38dca1620d.js","static/chunks/894-e57948de523bcf96.js","static/chunks/780-e8b3396d257460a4.js","static/chunks/899-83e9de2a35c6bcf0.js","static/chunks/182-08683bbe95fbb010.js","static/chunks/614-0ce04fd295045ffe.js","static/chunks/140-ec935fb15330b98a.js","static/chunks/644-c7c6e21c71345aed.js","static/chunks/903-dc2a40be612a10c3.js","static/chunks/485-77798bccc4308d0e.js","static/chunks/825-d34974d169ea09cc.js","static/chunks/94-db0af749b6e45543.js","static/chunks/676-6159ce853338cc1f.js","static/chunks/692-64941f28ab144919.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save