fix(striker-ui): repopulate network configs in network form

main
Tsu-ba-me 1 year ago
parent 6874218e3c
commit 5f5d521c58
  1. 138
      striker-ui/components/NetworkInitForm.tsx
  2. 51
      striker-ui/components/PrepareNetworkForm.tsx
  3. 2
      striker-ui/lib/consts/NETWORK_TYPES.ts
  4. 19
      striker-ui/types/APIHost.d.ts
  5. 1
      striker-ui/types/NetworkType.d.ts
  6. 1
      striker-ui/types/NumberBoolean.d.ts

@ -577,17 +577,33 @@ NetworkForm.defaultProps = {
const NetworkInitForm = forwardRef<
NetworkInitFormForwardedRefContent,
{
expectHostDetail?: boolean;
hostDetail?: APIHostDetail;
toggleSubmitDisabled?: (testResult: boolean) => void;
}
>(({ hostDetail, toggleSubmitDisabled }, ref) => {
>(({ expectHostDetail = false, hostDetail, toggleSubmitDisabled }, ref) => {
const {
dns: xDns,
gateway: xGateway,
dns: previousDns,
gateway: previousGateway,
hostType,
hostUUID = 'local',
networks: previousNetworks,
}: APIHostDetail = hostDetail ?? ({} as APIHostDetail);
const uninitRequiredNetworks: NetworkInput[] = useMemo(
() =>
hostType === 'node' ? NODE_REQUIRED_NETWORKS : STRIKER_REQUIRED_NETWORKS,
[hostType],
);
const requiredNetworks = useMemo<Partial<Record<NetworkType, number>>>(
() =>
hostType === 'node' ? { bcn: 1, ifn: 1, sn: 1 } : { bcn: 1, ifn: 1 },
[hostType],
);
const [isReadHostDetail, setIsReadHostDetail] = useState<boolean>(false);
const [dragMousePosition, setDragMousePosition] = useState<{
x: number;
y: number;
@ -595,7 +611,7 @@ const NetworkInitForm = forwardRef<
const [networkInterfaceInputMap, setNetworkInterfaceInputMap] =
useState<NetworkInterfaceInputMap>({});
const [networkInputs, setNetworkInputs] = useState<NetworkInput[]>(
hostType === 'node' ? NODE_REQUIRED_NETWORKS : STRIKER_REQUIRED_NETWORKS,
uninitRequiredNetworks,
);
const [networkInterfaceHeld, setNetworkInterfaceHeld] = useState<
NetworkInterfaceOverviewMetadata | undefined
@ -606,12 +622,16 @@ const NetworkInitForm = forwardRef<
const dnsCSVInputRef = useRef<InputForwardedRefContent<'string'>>({});
const messageGroupRef = useRef<MessageGroupForwardedRefContent>({});
const { data: networkInterfaces = [], isLoading } = periodicFetch<
NetworkInterfaceOverviewMetadata[]
>(`${API_BASE_URL}/init/network-interface/${hostUUID}`, {
const {
data: networkInterfaces = [],
isLoading: isLoadingNetworkInterfaces,
} = periodicFetch<NetworkInterfaceOverviewMetadata[]>(
`${API_BASE_URL}/init/network-interface/${hostUUID}`,
{
refreshInterval: 2000,
onSuccess: (data) => {
const map = data.reduce<NetworkInterfaceInputMap>((result, metadata) => {
const map = data.reduce<NetworkInterfaceInputMap>(
(result, metadata) => {
const { networkInterfaceUUID } = metadata;
result[networkInterfaceUUID] = networkInterfaceInputMap[
@ -619,11 +639,14 @@ const NetworkInitForm = forwardRef<
] ?? { metadata };
return result;
}, {});
},
{},
);
setNetworkInterfaceInputMap(map);
},
});
},
);
const isDisableAddNetworkButton: boolean = useMemo(
() =>
@ -634,6 +657,10 @@ const NetworkInitForm = forwardRef<
(hostType === 'node' && networkInterfaces.length <= 6),
[hostType, networkInputs, networkInterfaces, networkInterfaceInputMap],
);
const isLoadingHostDetail: boolean = useMemo(
() => expectHostDetail && !hostDetail,
[expectHostDetail, hostDetail],
);
const setMessage = useCallback(
(key: string, message?: Message) =>
@ -986,20 +1013,31 @@ const NetworkInitForm = forwardRef<
const clearNetworkInterfaceHeld = useCallback(() => {
setNetworkInterfaceHeld(undefined);
}, []);
const createNetwork = useCallback(() => {
const createNetwork = useCallback(
({
inputUUID = uuidv4(),
interfaces = [...INITIAL_IFACES],
ipAddress = '',
name = 'Unknown Network',
subnetMask = '',
type = '',
typeCount = 0,
}: Partial<NetworkInput> = {}) => {
networkInputs.unshift({
inputUUID: uuidv4(),
interfaces: [...INITIAL_IFACES],
ipAddress: '',
name: 'Unknown Network',
subnetMask: '',
type: '',
typeCount: 0,
inputUUID,
interfaces,
ipAddress,
name,
subnetMask,
type,
typeCount,
});
toggleSubmitDisabled?.call(null, false);
setNetworkInputs([...networkInputs]);
}, [networkInputs, toggleSubmitDisabled]);
},
[networkInputs, toggleSubmitDisabled],
);
const removeNetwork = useCallback(
(networkIndex: number) => {
const [{ inputUUID, interfaces }] = networkInputs.splice(networkIndex, 1);
@ -1138,6 +1176,55 @@ const NetworkInitForm = forwardRef<
[clearNetworkInterfaceHeld, networkInterfaceHeld],
);
useEffect(() => {
if (
Object.keys(networkInterfaceInputMap).length > 0 &&
expectHostDetail &&
hostDetail &&
!isReadHostDetail
) {
setNetworkInputs(
Object.values(previousNetworks).reduce<NetworkInput[]>(
(previous, { ip, link1Uuid, link2Uuid = '', subnetMask, type }) => {
const name = NETWORK_TYPES[type];
const typeCount =
getNetworkTypeCount(type, { inputs: previous }) + 1;
const isRequired = requiredNetworks[type] === typeCount;
previous.push({
inputUUID: uuidv4(),
interfaces: [
networkInterfaceInputMap[link1Uuid]?.metadata,
networkInterfaceInputMap[link2Uuid]?.metadata,
],
ipAddress: ip,
isRequired,
name,
subnetMask,
type,
typeCount,
});
return previous;
},
[],
),
);
setIsReadHostDetail(true);
}
}, [
createNetwork,
expectHostDetail,
getNetworkTypeCount,
hostDetail,
isReadHostDetail,
networkInputs,
networkInterfaceInputMap,
previousNetworks,
requiredNetworks,
]);
useEffect(() => {
// Enable network mapping on component mount.
setMapNetwork(1);
@ -1196,7 +1283,7 @@ const NetworkInitForm = forwardRef<
const networkInputMinWidth = '13em';
const networkInputWidth = '25%';
return isLoading ? (
return isLoadingNetworkInterfaces ? (
<Spinner />
) : (
<MUIBox
@ -1288,6 +1375,7 @@ const NetworkInitForm = forwardRef<
},
}}
/>
{!isLoadingHostDetail && (
<FlexBox
row
sx={{
@ -1347,6 +1435,7 @@ const NetworkInitForm = forwardRef<
})}
</MUIBox>
</FlexBox>
)}
<FlexBox
sm="row"
sx={{
@ -1360,7 +1449,9 @@ const NetworkInitForm = forwardRef<
>
<IconButton
disabled={isDisableAddNetworkButton}
onClick={createNetwork}
onClick={() => {
createNetwork();
}}
>
<MUIAddIcon />
</IconButton>
@ -1381,7 +1472,7 @@ const NetworkInitForm = forwardRef<
setGatewayInputMessage();
}}
label="Gateway"
value={xGateway}
value={previousGateway}
/>
}
ref={gatewayInputRef}
@ -1403,7 +1494,7 @@ const NetworkInitForm = forwardRef<
setDnsInputMessage();
}}
label="Domain name server(s)"
value={xDns}
value={previousDns}
/>
}
ref={dnsCSVInputRef}
@ -1420,6 +1511,7 @@ const NetworkInitForm = forwardRef<
});
NetworkInitForm.defaultProps = {
expectHostDetail: false,
hostDetail: undefined,
toggleSubmitDisabled: undefined,
};

@ -13,30 +13,27 @@ import OutlinedInputWithLabel from './OutlinedInputWithLabel';
import { Panel, PanelHeader } from './Panels';
import Spinner from './Spinner';
import { HeaderText } from './Text';
import useProtect from '../hooks/useProtect';
import useProtectedState from '../hooks/useProtectedState';
const PrepareNetworkForm: FC<PrepareNetworkFormProps> = ({
expectUUID: isExpectExternalHostUUID = false,
hostUUID,
}) => {
const { protect } = useProtect();
const {
isReady,
query: { host_uuid: queryHostUUID },
} = useRouter();
const [dataHostDetail, setDataHostDetail] = useProtectedState<
const [hostDetail, setHostDetail] = useProtectedState<
APIHostDetail | undefined
>(undefined, protect);
>(undefined);
const [fatalErrorMessage, setFatalErrorMessage] = useProtectedState<
Message | undefined
>(undefined, protect);
const [isLoading, setIsLoading] = useProtectedState<boolean>(true, protect);
const [previousHostUUID, setPreviousHostUUID] = useProtectedState<
PrepareNetworkFormProps['hostUUID']
>(undefined, protect);
>(undefined);
const [isLoadingHostDetail, setIsLoadingHostDetail] =
useProtectedState<boolean>(true);
const [previousHostUUID, setPreviousHostUUID] =
useProtectedState<PrepareNetworkFormProps['hostUUID']>(undefined);
const isDifferentHostUUID = useMemo(
() => hostUUID !== previousHostUUID,
@ -50,17 +47,15 @@ const PrepareNetworkForm: FC<PrepareNetworkFormProps> = ({
const panelHeaderElement = useMemo(
() => (
<PanelHeader>
<HeaderText>
Prepare network on {dataHostDetail?.shortHostName}
</HeaderText>
<HeaderText>Prepare network on {hostDetail?.shortHostName}</HeaderText>
</PanelHeader>
),
[dataHostDetail],
[hostDetail],
);
const contentElement = useMemo(() => {
let result;
if (isLoading) {
if (isLoadingHostDetail) {
result = <Spinner mt={0} />;
} else if (fatalErrorMessage) {
result = <MessageBox {...fatalErrorMessage} />;
@ -75,12 +70,12 @@ const PrepareNetworkForm: FC<PrepareNetworkFormProps> = ({
formControlProps={{ sx: { maxWidth: '20em' } }}
id="prepare-network-host-name"
label="Host name"
value={dataHostDetail?.hostName}
value={hostDetail?.hostName}
/>
}
required
/>
<NetworkInitForm hostDetail={dataHostDetail} />
<NetworkInitForm expectHostDetail hostDetail={hostDetail} />
<FlexBox row justifyContent="flex-end">
<ContainedButton>Prepare network</ContainedButton>
</FlexBox>
@ -90,18 +85,18 @@ const PrepareNetworkForm: FC<PrepareNetworkFormProps> = ({
}
return result;
}, [dataHostDetail, fatalErrorMessage, isLoading, panelHeaderElement]);
}, [hostDetail, fatalErrorMessage, isLoadingHostDetail, panelHeaderElement]);
const getHostDetail = useCallback(
(uuid: string) => {
setIsLoading(true);
setIsLoadingHostDetail(true);
if (isLoading) {
if (isLoadingHostDetail) {
api
.get<APIHostDetail>(`/host/${uuid}`)
.then(({ data }) => {
setPreviousHostUUID(data.hostUUID);
setDataHostDetail(data);
setHostDetail(data);
})
.catch((error) => {
const { children } = handleAPIError(error);
@ -112,15 +107,15 @@ const PrepareNetworkForm: FC<PrepareNetworkFormProps> = ({
});
})
.finally(() => {
setIsLoading(false);
setIsLoadingHostDetail(false);
});
}
},
[
setIsLoading,
isLoading,
setIsLoadingHostDetail,
isLoadingHostDetail,
setPreviousHostUUID,
setDataHostDetail,
setHostDetail,
setFatalErrorMessage,
],
);
@ -139,7 +134,7 @@ const PrepareNetworkForm: FC<PrepareNetworkFormProps> = ({
type: 'error',
});
setIsLoading(false);
setIsLoadingHostDetail(false);
}
}
}, [
@ -150,8 +145,8 @@ const PrepareNetworkForm: FC<PrepareNetworkFormProps> = ({
isReady,
queryHostUUID,
setFatalErrorMessage,
setDataHostDetail,
setIsLoading,
setHostDetail,
setIsLoadingHostDetail,
isReloadHostDetail,
]);

@ -1,4 +1,4 @@
const NETWORK_TYPES: Record<string, string> = {
const NETWORK_TYPES: Record<NetworkType, string> & Record<string, string> = {
bcn: 'Back-Channel Network',
ifn: 'Internet-Facing Network',
mn: 'Migration Network',

@ -41,8 +41,27 @@ type APIHostOverviewList = {
type APIHostDetail = APIHostOverview & {
dns: string;
domain?: string;
gateway: string;
gatewayInterface: string;
installTarget: APIHostInstallTarget;
networks: {
[networkId: string]: {
createBridge?: NumberBoolean;
ip: string;
link1MacToSet: string;
link1Uuid: string;
link2MacToSet?: string;
link2Uuid?: string;
subnetMask: string;
type: NetworkType;
};
};
organization?: string;
prefix?: string;
sequence?: string;
strikerPassword?: string;
strikerUser?: string;
};
type APIDeleteHostConnectionRequestBody = { [key: 'local' | string]: string[] };

@ -0,0 +1 @@
type NetworkType = 'bcn' | 'ifn' | 'mn' | 'sn';

@ -0,0 +1 @@
type NumberBoolean = '0' | '1';
Loading…
Cancel
Save