fix(striker-ui): auto-suggest last octet of not IFN on striker based on host sequence

main
Tsu-ba-me 1 year ago
parent 6b1c2491d0
commit 86ecd3537c
  1. 75
      striker-ui/components/GeneralInitForm.tsx
  2. 211
      striker-ui/components/NetworkInitForm.tsx
  3. 5
      striker-ui/components/StrikerInitForm.tsx

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

@ -110,42 +110,6 @@ const CLASSES = {
const INITIAL_IFACES = [undefined, undefined];
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 IT_IDS = {
dnsCSV: 'dns',
@ -164,6 +128,38 @@ const NETWORK_INTERFACE_TEMPLATE = Array.from(
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 = (
handleDragMouseDown: (
row: NetworkInterfaceOverviewMetadata,
@ -270,7 +266,7 @@ const NetworkForm: FC<{
interfaceIndex: number,
) => MUIBoxProps['onMouseUp'];
getNetworkTypeCount: GetNetworkTypeCountFunction;
hostDetail?: APIHostDetail;
hostDetail?: Partial<Pick<APIHostDetail, 'hostType' | 'sequence'>>;
networkIndex: number;
networkInput: NetworkInput;
networkInterfaceCount: number;
@ -286,7 +282,7 @@ const NetworkForm: FC<{
}> = ({
createDropMouseUpHandler,
getNetworkTypeCount,
hostDetail: { hostType } = {},
hostDetail: { hostType, sequence } = {},
networkIndex,
networkInput,
networkInterfaceCount,
@ -350,6 +346,20 @@ const NetworkForm: FC<{
: { bcn, ifn, sn };
}, [isNode, networkInterfaceCount]);
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(() => {
const { ipAddressInputRef: ipRef, subnetMaskInputRef: maskRef } =
networkInput;
@ -579,18 +589,78 @@ const NetworkInitForm = forwardRef<
{
expectHostDetail?: boolean;
hostDetail?: APIHostDetail;
hostSequence?: string;
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(
() =>
hostType === 'node' ? NODE_REQUIRED_NETWORKS : STRIKER_REQUIRED_NETWORKS,
[hostType],
const initRequiredNetworks: NetworkInput[] = useMemo(() => {
const result: NetworkInput[] = [];
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>>>(
() =>
hostType === 'node' ? { bcn: 1, ifn: 1, sn: 1 } : { bcn: 1, ifn: 1 },
@ -603,9 +673,8 @@ const NetworkInitForm = forwardRef<
}>({ x: 0, y: 0 });
const [networkInterfaceInputMap, setNetworkInterfaceInputMap] =
useState<NetworkInterfaceInputMap>({});
const [networkInputs, setNetworkInputs] = useState<NetworkInput[]>(
uninitRequiredNetworks,
);
const [networkInputs, setNetworkInputs] =
useState<NetworkInput[]>(initRequiredNetworks);
const [networkInterfaceHeld, setNetworkInterfaceHeld] = useState<
NetworkInterfaceOverviewMetadata | undefined
>();
@ -845,7 +914,8 @@ const NetworkInitForm = forwardRef<
const inputTestPrefix = createInputTestPrefix(inputUUID);
const inputTestIDIfaces = IT_IDS.networkInterfaces(inputTestPrefix);
const inputTestIDIPAddress = IT_IDS.networkIPAddress(inputTestPrefix);
const inputTestIDSubnetMask = IT_IDS.networkSubnetMask(inputTestPrefix);
const inputTestIDSubnetMask =
IT_IDS.networkSubnetMask(inputTestPrefix);
const setNetworkIfacesInputMessage = (message?: Message) =>
setMessage(inputTestIDIfaces, message);
@ -1010,24 +1080,8 @@ const NetworkInitForm = forwardRef<
setNetworkInterfaceHeld(undefined);
}, []);
const createNetwork = useCallback(
({
inputUUID = uuidv4(),
interfaces = [...INITIAL_IFACES],
ipAddress = '',
name = 'Unknown Network',
subnetMask = '',
type = '',
typeCount = 0,
}: Partial<NetworkInput> = {}) => {
networkInputs.unshift({
inputUUID,
interfaces,
ipAddress,
name,
subnetMask,
type,
typeCount,
});
(args: Partial<NetworkInput> = {}) => {
networkInputs.unshift(createNetworkInput(args));
toggleSubmitDisabled?.call(null, false);
setNetworkInputs([...networkInputs]);
@ -1036,7 +1090,10 @@ const NetworkInitForm = forwardRef<
);
const removeNetwork = useCallback(
(networkIndex: number) => {
const [{ inputUUID, interfaces }] = networkInputs.splice(networkIndex, 1);
const [{ inputUUID, interfaces }] = networkInputs.splice(
networkIndex,
1,
);
interfaces.forEach((iface) => {
if (iface === undefined) {
@ -1056,7 +1113,11 @@ const NetworkInitForm = forwardRef<
...previous,
}));
},
[networkInputs, networkInterfaceInputMap, testInputToToggleSubmitDisabled],
[
networkInputs,
networkInterfaceInputMap,
testInputToToggleSubmitDisabled,
],
);
const getNetworkTypeCount: GetNetworkTypeCountFunction = useCallback(
(
@ -1198,7 +1259,8 @@ const NetworkInitForm = forwardRef<
const applied: string[] = [];
const inputs = Object.values(pNetworks).reduce<NetworkInput[]>(
(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 name = `${NETWORK_TYPES[type]} ${typeCount}`;
@ -1299,7 +1361,8 @@ const NetworkInitForm = forwardRef<
interfaces,
ipAddress: ipAddressInputRef?.current.getValue?.call(null) ?? '',
name,
subnetMask: subnetMaskInputRef?.current.getValue?.call(null) ?? '',
subnetMask:
subnetMaskInputRef?.current.getValue?.call(null) ?? '',
type,
typeCount,
}),
@ -1447,7 +1510,7 @@ const NetworkInitForm = forwardRef<
{...{
createDropMouseUpHandler,
getNetworkTypeCount,
hostDetail,
hostDetail: { hostType, sequence },
networkIndex,
networkInput,
networkInterfaceCount: networkInterfaces.length,
@ -1535,11 +1598,13 @@ const NetworkInitForm = forwardRef<
</MUIBox>
</MUIBox>
);
});
},
);
NetworkInitForm.defaultProps = {
expectHostDetail: false,
hostDetail: undefined,
hostSequence: undefined,
toggleSubmitDisabled: undefined,
};
NetworkInitForm.displayName = 'NetworkInitForm';

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

Loading…
Cancel
Save