fix(striker-ui): auto-populate org prefix and host name

main
Tsu-ba-me 2 years ago
parent 22eba52b11
commit 322686598c
  1. 239
      striker-ui/components/StrikerInitForm.tsx

@ -1,42 +1,229 @@
import { FC, useState } from 'react'; import { Dispatch, FC, SetStateAction, useState } from 'react';
import { Box as MUIBox } from '@mui/material'; import { Box as MUIBox } from '@mui/material';
import NetworkInitForm from './NetworkInitForm'; import NetworkInitForm from './NetworkInitForm';
import { OutlinedInputProps } from './OutlinedInput';
import OutlinedInputWithLabel from './OutlinedInputWithLabel'; import OutlinedInputWithLabel from './OutlinedInputWithLabel';
import { Panel, PanelHeader } from './Panels'; import { Panel, PanelHeader } from './Panels';
import { HeaderText } from './Text'; import { HeaderText } from './Text';
import pad from '../lib/pad';
const StrikerInitForm: FC = () => { const MAX_ORGANIZATION_PREFIX_LENGTH = 5;
const MIN_ORGANIZATION_PREFIX_LENGTH = 2;
const MAP_TO_ORGANIZATION_PREFIX_BUILDER: Record<
number,
(words: string[]) => string
> = {
0: () => '',
1: ([word]) =>
word.substring(0, MIN_ORGANIZATION_PREFIX_LENGTH).toLocaleLowerCase(),
2: (words) =>
words.map((word) => word.substring(0, 1).toLocaleLowerCase()).join(''),
};
export type MapToType = {
number: number;
string: string;
};
export type MapToStateSetter = {
[TypeName in keyof MapToType]: Dispatch<SetStateAction<MapToType[TypeName]>>;
};
export type MapToValueConverter = {
[TypeName in keyof MapToType]: (value: unknown) => MapToType[TypeName];
};
export type InputOnChangeParameters = Parameters<
Exclude<OutlinedInputProps['onChange'], undefined>
>;
const MAP_TO_VALUE_CONVERTER: MapToValueConverter = {
number: (value) => parseInt(String(value), 10) || 0,
string: (value) => String(value),
};
const createInputOnChangeHandler =
<TypeName extends keyof MapToType>({
postSet,
preSet,
set,
setType = 'string',
}: {
postSet?: (...args: InputOnChangeParameters) => void;
preSet?: (...args: InputOnChangeParameters) => void;
set?: MapToStateSetter[TypeName];
setType?: TypeName | 'string';
}): OutlinedInputProps['onChange'] =>
(event) => {
const {
target: { value },
} = event;
const postConvertValue = MAP_TO_VALUE_CONVERTER[setType](
value,
) as MapToType[TypeName];
preSet?.call(null, event);
set?.call(null, postConvertValue);
postSet?.call(null, event);
};
const buildOrganizationPrefix = (organizationName: string) => {
const words: string[] = organizationName
.split(/\s/)
.filter((word) => !/and|of/.test(word))
.slice(0, MAX_ORGANIZATION_PREFIX_LENGTH);
const builderKey: number = words.length > 1 ? 2 : words.length;
return MAP_TO_ORGANIZATION_PREFIX_BUILDER[builderKey](words);
};
const buildHostName = (
organizationPrefix: string,
hostNumber: number,
domainName: string,
existingHostName = '',
) =>
organizationPrefix.length > 0 && hostNumber > 0 && domainName.length > 0
? `${organizationPrefix}-striker${pad(hostNumber)}.${domainName}`
: existingHostName;
const StrikerInitGeneralForm: FC = () => {
const [organizationNameInput, setOrganizationNameInput] = const [organizationNameInput, setOrganizationNameInput] =
useState<string>(''); useState<string>('');
const [organizationPrefixInput, setOrganizationPrefixInput] =
useState<string>('');
const [domainNameInput, setDomainNameInput] = useState<string>('');
const [hostNumberInput, setHostNumberInput] = useState<number>(0);
const [hostNameInput, setHostNameInput] = useState<string>('');
const handleOrganizationNameInputOnChange = createInputOnChangeHandler({
set: setOrganizationNameInput,
});
const handleOrganizationPrefixInputOnChange = createInputOnChangeHandler({
set: setOrganizationPrefixInput,
});
const handleDomainNameInputOnChange = createInputOnChangeHandler({
set: setDomainNameInput,
});
const handleHostNumberInputOnChange = createInputOnChangeHandler({
set: setHostNumberInput,
setType: 'number',
});
const handleHostNameInputOnChange = createInputOnChangeHandler({
set: setHostNameInput,
});
return ( return (
<Panel> <MUIBox
<PanelHeader> sx={{
<HeaderText text="Initialize striker" /> display: 'flex',
</PanelHeader> flexDirection: 'column',
<MUIBox
sx={{ '& > :not(:first-child)': {
display: 'flex', marginTop: '1em',
flexDirection: 'column', },
}}
'& > :not(:first-child)': { marginTop: '1em' }, >
<OutlinedInputWithLabel
inputProps={{
onBlur: ({ target: { value } }) => {
const newOrganizationName = String(value);
setOrganizationPrefixInput(
buildOrganizationPrefix(newOrganizationName),
);
},
}} }}
> label="Organization name"
<OutlinedInputWithLabel onChange={handleOrganizationNameInputOnChange}
label="Organization name" value={organizationNameInput}
onChange={({ target: { value } }) => { />
setOrganizationNameInput(String(value)); <OutlinedInputWithLabel
}} inputProps={{
value={organizationNameInput} onBlur: ({ target: { value } }) => {
/> const newOrganizationPrefix = String(value);
<OutlinedInputWithLabel label="Organization prefix" />
<OutlinedInputWithLabel label="Domain name" /> setHostNameInput(
<OutlinedInputWithLabel label="Striker number" /> buildHostName(
<NetworkInitForm /> newOrganizationPrefix,
</MUIBox> hostNumberInput,
</Panel> domainNameInput,
hostNameInput,
),
);
},
}}
label="Organization prefix"
onChange={handleOrganizationPrefixInputOnChange}
value={organizationPrefixInput}
/>
<OutlinedInputWithLabel
label="Domain name"
inputProps={{
onBlur: ({ target: { value } }) => {
const newDomainName = String(value);
setHostNameInput(
buildHostName(
organizationPrefixInput,
hostNumberInput,
newDomainName,
hostNameInput,
),
);
},
}}
onChange={handleDomainNameInputOnChange}
value={domainNameInput}
/>
<OutlinedInputWithLabel
inputProps={{
onBlur: ({ target: { value } }) => {
const newHostNumber = parseInt(value, 10);
setHostNameInput(
buildHostName(
organizationPrefixInput,
newHostNumber,
domainNameInput,
hostNameInput,
),
);
},
}}
label="Host number"
onChange={handleHostNumberInputOnChange}
value={hostNumberInput}
/>
<OutlinedInputWithLabel
label="Host name"
onChange={handleHostNameInputOnChange}
value={hostNameInput}
/>
</MUIBox>
); );
}; };
const StrikerInitForm: FC = () => (
<Panel>
<PanelHeader>
<HeaderText text="Initialize striker" />
</PanelHeader>
<MUIBox
sx={{
display: 'flex',
flexDirection: 'column',
'& > :not(:first-child)': { marginTop: '1em' },
}}
>
<StrikerInitGeneralForm />
<NetworkInitForm />
</MUIBox>
</Panel>
);
export default StrikerInitForm; export default StrikerInitForm;

Loading…
Cancel
Save