|
|
|
import { Checkbox as MUICheckbox, Grid as MUIGrid } from '@mui/material';
|
|
|
|
import {
|
|
|
|
forwardRef,
|
|
|
|
ReactNode,
|
|
|
|
useCallback,
|
|
|
|
useEffect,
|
|
|
|
useImperativeHandle,
|
|
|
|
useMemo,
|
|
|
|
useRef,
|
|
|
|
useState,
|
|
|
|
} from 'react';
|
|
|
|
|
|
|
|
import INPUT_TYPES from '../lib/consts/INPUT_TYPES';
|
|
|
|
import { REP_DOMAIN } from '../lib/consts/REG_EXP_PATTERNS';
|
|
|
|
|
|
|
|
import FlexBox from './FlexBox';
|
|
|
|
import InputWithRef, { InputForwardedRefContent } from './InputWithRef';
|
|
|
|
import MessageBox, { Message } from './MessageBox';
|
|
|
|
import MessageGroup, { MessageGroupForwardedRefContent } from './MessageGroup';
|
|
|
|
import OutlinedInputWithLabel, {
|
|
|
|
OutlinedInputWithLabelProps,
|
|
|
|
} from './OutlinedInputWithLabel';
|
|
|
|
import pad from '../lib/pad';
|
|
|
|
import SuggestButton from './SuggestButton';
|
|
|
|
import { createTestInputFunction, testNotBlank } from '../lib/test_input';
|
|
|
|
import { BodyText, InlineMonoText } from './Text';
|
|
|
|
|
|
|
|
type GeneralInitFormValues = {
|
|
|
|
adminPassword?: string;
|
|
|
|
domainName?: string;
|
|
|
|
hostName?: string;
|
|
|
|
hostNumber?: number;
|
|
|
|
organizationName?: string;
|
|
|
|
organizationPrefix?: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
type GeneralInitFormForwardedRefContent = {
|
|
|
|
get?: () => GeneralInitFormValues;
|
|
|
|
};
|
|
|
|
|
|
|
|
type OutlinedInputWithLabelOnBlur = Exclude<
|
|
|
|
OutlinedInputWithLabelProps['inputProps'],
|
|
|
|
undefined
|
|
|
|
>['onBlur'];
|
|
|
|
|
|
|
|
const MAX_ORGANIZATION_PREFIX_LENGTH = 5;
|
|
|
|
const MIN_ORGANIZATION_PREFIX_LENGTH = 1;
|
|
|
|
const MAX_HOST_NUMBER_LENGTH = 2;
|
|
|
|
const IT_IDS = {
|
|
|
|
adminPassword: 'adminPassword',
|
|
|
|
confirmAdminPassword: 'confirmAdminPassword',
|
|
|
|
domainName: 'domainName',
|
|
|
|
hostName: 'hostName',
|
|
|
|
hostNumber: 'hostNumber',
|
|
|
|
organizationName: 'organizationName',
|
|
|
|
organizationPrefix: 'organizationPrefix',
|
|
|
|
};
|
|
|
|
|
|
|
|
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(''),
|
|
|
|
};
|
|
|
|
|
|
|
|
const buildOrganizationPrefix = (organizationName = '') => {
|
|
|
|
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,
|
|
|
|
hostNumber,
|
|
|
|
domainName,
|
|
|
|
}: {
|
|
|
|
organizationPrefix?: string;
|
|
|
|
hostNumber?: number;
|
|
|
|
domainName?: string;
|
|
|
|
}) =>
|
|
|
|
[organizationPrefix, hostNumber, domainName].every((value) => Boolean(value))
|
|
|
|
? `${organizationPrefix}-striker${pad(hostNumber)}.${domainName}`
|
|
|
|
: '';
|
|
|
|
|
|
|
|
const GeneralInitForm = forwardRef<
|
|
|
|
GeneralInitFormForwardedRefContent,
|
|
|
|
{
|
|
|
|
expectHostDetail?: boolean;
|
|
|
|
hostDetail?: APIHostDetail;
|
|
|
|
onHostNumberBlurAppend?: OutlinedInputWithLabelProps['onBlur'];
|
|
|
|
toggleSubmitDisabled?: ToggleSubmitDisabledFunction;
|
|
|
|
}
|
|
|
|
>(
|
|
|
|
(
|
|
|
|
{
|
|
|
|
expectHostDetail = false,
|
|
|
|
hostDetail,
|
|
|
|
onHostNumberBlurAppend,
|
|
|
|
toggleSubmitDisabled,
|
|
|
|
},
|
|
|
|
ref,
|
|
|
|
) => {
|
|
|
|
const [helpMessage, setHelpMessage] = useState<ReactNode | undefined>();
|
|
|
|
const [
|
|
|
|
isShowOrganizationPrefixSuggest,
|
|
|
|
setIsShowOrganizationPrefixSuggest,
|
|
|
|
] = useState<boolean>(false);
|
|
|
|
const [isShowHostNameSuggest, setIsShowHostNameSuggest] =
|
|
|
|
useState<boolean>(false);
|
|
|
|
const [isConfirmAdminPassword, setIsConfirmAdminPassword] =
|
|
|
|
useState<boolean>(true);
|
|
|
|
const [isValidateDomain, setIsValidateDomain] = useState<boolean>(true);
|
|
|
|
|
|
|
|
const readHostDetailRef = useRef<boolean>(true);
|
|
|
|
|
|
|
|
const adminPasswordInputRef = useRef<InputForwardedRefContent<'string'>>(
|
|
|
|
{},
|
|
|
|
);
|
|
|
|
const confirmAdminPasswordInputRef = useRef<
|
|
|
|
InputForwardedRefContent<'string'>
|
|
|
|
>({});
|
|
|
|
const organizationNameInputRef = useRef<InputForwardedRefContent<'string'>>(
|
|
|
|
{},
|
|
|
|
);
|
|
|
|
const organizationPrefixInputRef = useRef<
|
|
|
|
InputForwardedRefContent<'string'>
|
|
|
|
>({});
|
|
|
|
const domainNameInputRef = useRef<InputForwardedRefContent<'string'>>({});
|
|
|
|
const hostNumberInputRef = useRef<InputForwardedRefContent<'number'>>({});
|
|
|
|
const hostNameInputRef = useRef<InputForwardedRefContent<'string'>>({});
|
|
|
|
const messageGroupRef = useRef<MessageGroupForwardedRefContent>({});
|
|
|
|
|
|
|
|
const setOrganizationPrefixInputMessage = useCallback(
|
|
|
|
(message?: Message) =>
|
|
|
|
messageGroupRef.current.setMessage?.call(
|
|
|
|
null,
|
|
|
|
IT_IDS.organizationPrefix,
|
|
|
|
message,
|
|
|
|
),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
const setHostNumberInputMessage = useCallback(
|
|
|
|
(message?: Message) =>
|
|
|
|
messageGroupRef.current.setMessage?.call(
|
|
|
|
null,
|
|
|
|
IT_IDS.hostNumber,
|
|
|
|
message,
|
|
|
|
),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
const setDomainNameInputMessage = useCallback(
|
|
|
|
(message?: Message) =>
|
|
|
|
messageGroupRef.current.setMessage?.call(
|
|
|
|
null,
|
|
|
|
IT_IDS.domainName,
|
|
|
|
message,
|
|
|
|
),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
const setHostNameInputMessage = useCallback(
|
|
|
|
(message?: Message) =>
|
|
|
|
messageGroupRef.current.setMessage?.call(
|
|
|
|
null,
|
|
|
|
IT_IDS.hostName,
|
|
|
|
message,
|
|
|
|
),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
const setAdminPasswordInputMessage = useCallback(
|
|
|
|
(message?: Message) =>
|
|
|
|
messageGroupRef.current.setMessage?.call(
|
|
|
|
null,
|
|
|
|
IT_IDS.adminPassword,
|
|
|
|
message,
|
|
|
|
),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
const setConfirmAdminPasswordInputMessage = useCallback(
|
|
|
|
(message?: Message) =>
|
|
|
|
messageGroupRef.current.setMessage?.call(
|
|
|
|
null,
|
|
|
|
IT_IDS.confirmAdminPassword,
|
|
|
|
message,
|
|
|
|
),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
|
|
|
|
const inputTests: InputTestBatches = useMemo(
|
|
|
|
() => ({
|
|
|
|
[IT_IDS.adminPassword]: {
|
|
|
|
defaults: {
|
|
|
|
getValue: () => adminPasswordInputRef.current.getValue?.call(null),
|
|
|
|
onSuccess: () => {
|
|
|
|
setAdminPasswordInputMessage(undefined);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tests: [
|
|
|
|
{
|
|
|
|
onFailure: () => {
|
|
|
|
setAdminPasswordInputMessage({
|
|
|
|
children: (
|
|
|
|
<>
|
|
|
|
Admin password cannot contain single-quote (
|
|
|
|
<InlineMonoText text="'" />
|
|
|
|
), double-quote (<InlineMonoText text='"' />
|
|
|
|
), slash (<InlineMonoText text="/" />
|
|
|
|
), backslash (<InlineMonoText text="\" />
|
|
|
|
), angle brackets (<InlineMonoText text="<>" />
|
|
|
|
), curly brackets (<InlineMonoText text="{}" />
|
|
|
|
).
|
|
|
|
</>
|
|
|
|
),
|
|
|
|
});
|
|
|
|
},
|
|
|
|
test: ({ value }) => !/['"/\\><}{]/g.test(value as string),
|
|
|
|
},
|
|
|
|
{ test: testNotBlank },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
[IT_IDS.confirmAdminPassword]: {
|
|
|
|
defaults: {
|
|
|
|
getValue: () =>
|
|
|
|
confirmAdminPasswordInputRef.current?.getValue?.call(null),
|
|
|
|
onSuccess: () => {
|
|
|
|
setConfirmAdminPasswordInputMessage(undefined);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tests: [
|
|
|
|
{
|
|
|
|
onFailure: () => {
|
|
|
|
setConfirmAdminPasswordInputMessage({
|
|
|
|
children: "Confirmation doesn't match admin password.",
|
|
|
|
});
|
|
|
|
},
|
|
|
|
test: ({ value }) =>
|
|
|
|
value === adminPasswordInputRef.current.getValue?.call(null),
|
|
|
|
},
|
|
|
|
{ test: testNotBlank },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
[IT_IDS.domainName]: {
|
|
|
|
defaults: {
|
|
|
|
compare: [!isValidateDomain],
|
|
|
|
getValue: () => domainNameInputRef.current.getValue?.call(null),
|
|
|
|
onSuccess: () => {
|
|
|
|
setDomainNameInputMessage(undefined);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tests: [
|
|
|
|
{
|
|
|
|
onFailure: () => {
|
|
|
|
setDomainNameInputMessage({
|
|
|
|
children: (
|
|
|
|
<>
|
|
|
|
Domain name can only contain lowercase alphanumeric,
|
|
|
|
hyphen (<InlineMonoText text="-" />
|
|
|
|
), and dot (<InlineMonoText text="." />) characters.
|
|
|
|
</>
|
|
|
|
),
|
|
|
|
});
|
|
|
|
},
|
|
|
|
test: ({ compare, value }) =>
|
|
|
|
(compare[0] as boolean) || REP_DOMAIN.test(value as string),
|
|
|
|
},
|
|
|
|
{ test: testNotBlank },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
[IT_IDS.hostName]: {
|
|
|
|
defaults: {
|
|
|
|
compare: [!isValidateDomain],
|
|
|
|
getValue: () => hostNameInputRef.current.getValue?.call(null),
|
|
|
|
onSuccess: () => {
|
|
|
|
setHostNameInputMessage(undefined);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tests: [
|
|
|
|
{
|
|
|
|
onFailure: () => {
|
|
|
|
setHostNameInputMessage({
|
|
|
|
children: (
|
|
|
|
<>
|
|
|
|
Host name can only contain lowercase alphanumeric, hyphen
|
|
|
|
(
|
|
|
|
<InlineMonoText text="-" />
|
|
|
|
), and dot (<InlineMonoText text="." />) characters.
|
|
|
|
</>
|
|
|
|
),
|
|
|
|
});
|
|
|
|
},
|
|
|
|
test: ({ compare, value }) =>
|
|
|
|
(compare[0] as boolean) || REP_DOMAIN.test(value as string),
|
|
|
|
},
|
|
|
|
{ test: testNotBlank },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
[IT_IDS.hostNumber]: {
|
|
|
|
defaults: {
|
|
|
|
getValue: () => hostNumberInputRef.current.getValue?.call(null),
|
|
|
|
onSuccess: () => {
|
|
|
|
setHostNumberInputMessage(undefined);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tests: [
|
|
|
|
{
|
|
|
|
onFailure: () => {
|
|
|
|
setHostNumberInputMessage({
|
|
|
|
children: 'Striker number can only contain digits.',
|
|
|
|
});
|
|
|
|
},
|
|
|
|
test: ({ value }) => /^\d+$/.test(value as string),
|
|
|
|
},
|
|
|
|
{ test: testNotBlank },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
[IT_IDS.organizationName]: {
|
|
|
|
defaults: {
|
|
|
|
getValue: () =>
|
|
|
|
organizationNameInputRef.current.getValue?.call(null),
|
|
|
|
},
|
|
|
|
tests: [{ test: testNotBlank }],
|
|
|
|
},
|
|
|
|
[IT_IDS.organizationPrefix]: {
|
|
|
|
defaults: {
|
|
|
|
getValue: () =>
|
|
|
|
organizationPrefixInputRef.current.getValue?.call(null),
|
|
|
|
max: MAX_ORGANIZATION_PREFIX_LENGTH,
|
|
|
|
min: MIN_ORGANIZATION_PREFIX_LENGTH,
|
|
|
|
onSuccess: () => {
|
|
|
|
setOrganizationPrefixInputMessage(undefined);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tests: [
|
|
|
|
{
|
|
|
|
onFailure: ({ max, min }) => {
|
|
|
|
setOrganizationPrefixInputMessage({
|
|
|
|
children: `Organization prefix must be ${min} to ${max} lowercase alphanumeric characters.`,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
test: ({ max, min, value }) =>
|
|
|
|
RegExp(`^[a-z0-9]{${min},${max}}$`).test(value as string),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
[
|
|
|
|
isValidateDomain,
|
|
|
|
setAdminPasswordInputMessage,
|
|
|
|
setConfirmAdminPasswordInputMessage,
|
|
|
|
setDomainNameInputMessage,
|
|
|
|
setHostNameInputMessage,
|
|
|
|
setHostNumberInputMessage,
|
|
|
|
setOrganizationPrefixInputMessage,
|
|
|
|
],
|
|
|
|
);
|
|
|
|
const testInput = useMemo(
|
|
|
|
() => createTestInputFunction(inputTests),
|
|
|
|
[inputTests],
|
|
|
|
);
|
|
|
|
|
|
|
|
const testInputToToggleSubmitDisabled = useCallback(
|
|
|
|
({
|
|
|
|
excludeTestIds = [],
|
|
|
|
inputs,
|
|
|
|
isContinueOnFailure,
|
|
|
|
isExcludeConfirmAdminPassword = !isConfirmAdminPassword,
|
|
|
|
}: Pick<
|
|
|
|
TestInputFunctionOptions,
|
|
|
|
'inputs' | 'excludeTestIds' | 'isContinueOnFailure'
|
|
|
|
> & {
|
|
|
|
isExcludeConfirmAdminPassword?: boolean;
|
|
|
|
} = {}) => {
|
|
|
|
if (isExcludeConfirmAdminPassword) {
|
|
|
|
excludeTestIds.push(IT_IDS.confirmAdminPassword);
|
|
|
|
}
|
|
|
|
|
|
|
|
toggleSubmitDisabled?.call(
|
|
|
|
null,
|
|
|
|
testInput({
|
|
|
|
excludeTestIds,
|
|
|
|
inputs,
|
|
|
|
isContinueOnFailure,
|
|
|
|
isIgnoreOnCallbacks: true,
|
|
|
|
isTestAll: true,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
[isConfirmAdminPassword, testInput, toggleSubmitDisabled],
|
|
|
|
);
|
|
|
|
const populateOrganizationPrefixInput = useCallback(
|
|
|
|
({
|
|
|
|
organizationName = organizationNameInputRef.current.getValue?.call(
|
|
|
|
null,
|
|
|
|
),
|
|
|
|
} = {}) => {
|
|
|
|
const organizationPrefix = buildOrganizationPrefix(organizationName);
|
|
|
|
|
|
|
|
organizationPrefixInputRef.current.setValue?.call(
|
|
|
|
null,
|
|
|
|
organizationPrefix,
|
|
|
|
);
|
|
|
|
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: {
|
|
|
|
[IT_IDS.organizationPrefix]: {
|
|
|
|
isIgnoreOnCallbacks: false,
|
|
|
|
value: organizationPrefix,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
isContinueOnFailure: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
return organizationPrefix;
|
|
|
|
},
|
|
|
|
[testInputToToggleSubmitDisabled],
|
|
|
|
);
|
|
|
|
const populateHostNameInput = useCallback(
|
|
|
|
({
|
|
|
|
organizationPrefix = organizationPrefixInputRef.current.getValue?.call(
|
|
|
|
null,
|
|
|
|
),
|
|
|
|
hostNumber = hostNumberInputRef.current.getValue?.call(null),
|
|
|
|
domainName = domainNameInputRef.current.getValue?.call(null),
|
|
|
|
} = {}) => {
|
|
|
|
const hostName = buildHostName({
|
|
|
|
organizationPrefix,
|
|
|
|
hostNumber,
|
|
|
|
domainName,
|
|
|
|
});
|
|
|
|
|
|
|
|
hostNameInputRef.current.setValue?.call(null, hostName);
|
|
|
|
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: {
|
|
|
|
[IT_IDS.hostName]: { isIgnoreOnCallbacks: false, value: hostName },
|
|
|
|
},
|
|
|
|
isContinueOnFailure: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
return hostName;
|
|
|
|
},
|
|
|
|
[testInputToToggleSubmitDisabled],
|
|
|
|
);
|
|
|
|
const isOrganizationPrefixPrereqFilled = useCallback(
|
|
|
|
() => Boolean(organizationNameInputRef.current.getValue?.call(null)),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
const isHostNamePrereqFilled = useCallback(
|
|
|
|
() =>
|
|
|
|
[
|
|
|
|
organizationPrefixInputRef.current.getValue?.call(null),
|
|
|
|
hostNumberInputRef.current.getValue?.call(null),
|
|
|
|
domainNameInputRef.current.getValue?.call(null),
|
|
|
|
].every((value) => Boolean(value)),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
const populateOrganizationPrefixInputOnBlur: OutlinedInputWithLabelOnBlur =
|
|
|
|
useCallback(() => {
|
|
|
|
if (organizationPrefixInputRef.current.getIsChangedByUser?.call(null)) {
|
|
|
|
setIsShowOrganizationPrefixSuggest(
|
|
|
|
isOrganizationPrefixPrereqFilled(),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
populateOrganizationPrefixInput();
|
|
|
|
}
|
|
|
|
}, [isOrganizationPrefixPrereqFilled, populateOrganizationPrefixInput]);
|
|
|
|
const populateHostNameInputOnBlur: OutlinedInputWithLabelOnBlur =
|
|
|
|
useCallback(() => {
|
|
|
|
if (hostNameInputRef.current.getIsChangedByUser?.call(null)) {
|
|
|
|
setIsShowHostNameSuggest(isHostNamePrereqFilled());
|
|
|
|
} else {
|
|
|
|
populateHostNameInput();
|
|
|
|
}
|
|
|
|
}, [isHostNamePrereqFilled, populateHostNameInput]);
|
|
|
|
const handleOrganizationPrefixSuggest = useCallback(() => {
|
|
|
|
const organizationPrefix = populateOrganizationPrefixInput();
|
|
|
|
|
|
|
|
if (!hostNameInputRef.current.getIsChangedByUser?.call(null)) {
|
|
|
|
populateHostNameInput({ organizationPrefix });
|
|
|
|
}
|
|
|
|
}, [populateHostNameInput, populateOrganizationPrefixInput]);
|
|
|
|
const handlerHostNameSuggest = useCallback(() => {
|
|
|
|
populateHostNameInput();
|
|
|
|
}, [populateHostNameInput]);
|
|
|
|
const buildHelpMessage = useCallback(
|
|
|
|
(text: string) => (previous?: string) =>
|
|
|
|
previous === text ? undefined : text,
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
|
|
|
|
const validateDomainCheckbox = useMemo(
|
|
|
|
() => (
|
|
|
|
<MUICheckbox
|
|
|
|
checked={isValidateDomain}
|
|
|
|
onChange={(event, checked) => {
|
|
|
|
setIsValidateDomain(checked);
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: {
|
|
|
|
[IT_IDS.domainName]: {
|
|
|
|
compare: [!checked],
|
|
|
|
isIgnoreOnCallbacks: false,
|
|
|
|
},
|
|
|
|
[IT_IDS.hostName]: {
|
|
|
|
compare: [!checked],
|
|
|
|
isIgnoreOnCallbacks: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
isContinueOnFailure: true,
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
sx={{ padding: '.2em' }}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
[isValidateDomain, testInputToToggleSubmitDisabled],
|
|
|
|
);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (
|
|
|
|
[
|
|
|
|
expectHostDetail,
|
|
|
|
hostDetail,
|
|
|
|
readHostDetailRef.current,
|
|
|
|
domainNameInputRef.current,
|
|
|
|
hostNameInputRef.current,
|
|
|
|
hostNumberInputRef.current,
|
|
|
|
organizationNameInputRef.current,
|
|
|
|
organizationPrefixInputRef.current,
|
|
|
|
].every((condition) => Boolean(condition))
|
|
|
|
) {
|
|
|
|
readHostDetailRef.current = false;
|
|
|
|
|
|
|
|
const {
|
|
|
|
domain: pDomain,
|
|
|
|
hostName: pHostName,
|
|
|
|
organization: pOrganization,
|
|
|
|
prefix: pPrefix,
|
|
|
|
sequence: pSequence,
|
|
|
|
} = hostDetail as APIHostDetail;
|
|
|
|
|
|
|
|
domainNameInputRef.current.setValue?.call(null, pDomain);
|
|
|
|
hostNameInputRef.current.setValue?.call(null, pHostName);
|
|
|
|
hostNumberInputRef.current.setValue?.call(null, pSequence);
|
|
|
|
organizationNameInputRef.current.setValue?.call(null, pOrganization);
|
|
|
|
organizationPrefixInputRef.current.setValue?.call(null, pPrefix);
|
|
|
|
|
|
|
|
testInputToToggleSubmitDisabled();
|
|
|
|
}
|
|
|
|
}, [expectHostDetail, hostDetail, testInputToToggleSubmitDisabled]);
|
|
|
|
|
|
|
|
useImperativeHandle(ref, () => ({
|
|
|
|
get: () => ({
|
|
|
|
adminPassword: adminPasswordInputRef.current.getValue?.call(null),
|
|
|
|
organizationName: organizationNameInputRef.current.getValue?.call(null),
|
|
|
|
organizationPrefix:
|
|
|
|
organizationPrefixInputRef.current.getValue?.call(null),
|
|
|
|
domainName: domainNameInputRef.current.getValue?.call(null),
|
|
|
|
hostNumber: hostNumberInputRef.current.getValue?.call(null),
|
|
|
|
hostName: hostNameInputRef.current.getValue?.call(null),
|
|
|
|
}),
|
|
|
|
}));
|
|
|
|
|
|
|
|
return (
|
|
|
|
<FlexBox>
|
|
|
|
<MUIGrid columns={{ xs: 1, sm: 2, md: 3 }} container spacing="1em">
|
|
|
|
<MUIGrid item xs={1}>
|
|
|
|
<FlexBox>
|
|
|
|
<InputWithRef
|
|
|
|
input={
|
|
|
|
<OutlinedInputWithLabel
|
|
|
|
id="striker-init-general-organization-name"
|
|
|
|
inputProps={{
|
|
|
|
onBlur: populateOrganizationPrefixInputOnBlur,
|
|
|
|
}}
|
|
|
|
inputLabelProps={{ isNotifyRequired: true }}
|
|
|
|
label="Organization name"
|
|
|
|
onChange={() => {
|
|
|
|
testInputToToggleSubmitDisabled();
|
|
|
|
}}
|
|
|
|
onHelp={() => {
|
|
|
|
setHelpMessage(
|
|
|
|
buildHelpMessage(
|
|
|
|
'Name of the organization that maintains this Anvil! system. You can enter anything that makes sense to you.',
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
ref={organizationNameInputRef}
|
|
|
|
/>
|
|
|
|
<FlexBox
|
|
|
|
row
|
|
|
|
sx={{
|
|
|
|
'& > :first-child': {
|
|
|
|
flexGrow: 1,
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<InputWithRef
|
|
|
|
input={
|
|
|
|
<OutlinedInputWithLabel
|
|
|
|
id="striker-init-general-organization-prefix"
|
|
|
|
inputProps={{
|
|
|
|
endAdornment: (
|
|
|
|
<SuggestButton
|
|
|
|
show={isShowOrganizationPrefixSuggest}
|
|
|
|
onClick={handleOrganizationPrefixSuggest}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
inputProps: {
|
|
|
|
maxLength: MAX_ORGANIZATION_PREFIX_LENGTH,
|
|
|
|
sx: {
|
|
|
|
minWidth: '2.5em',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
onBlur: (event, ...resetArgs) => {
|
|
|
|
const {
|
|
|
|
target: { value },
|
|
|
|
} = event;
|
|
|
|
|
|
|
|
testInput({
|
|
|
|
inputs: { [IT_IDS.organizationPrefix]: { value } },
|
|
|
|
});
|
|
|
|
populateHostNameInputOnBlur(event, ...resetArgs);
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
inputLabelProps={{ isNotifyRequired: true }}
|
|
|
|
label="Prefix"
|
|
|
|
onChange={({ target: { value } }) => {
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: { [IT_IDS.organizationPrefix]: { value } },
|
|
|
|
});
|
|
|
|
setOrganizationPrefixInputMessage();
|
|
|
|
setIsShowOrganizationPrefixSuggest(
|
|
|
|
isOrganizationPrefixPrereqFilled(),
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
onHelp={() => {
|
|
|
|
setHelpMessage(
|
|
|
|
buildHelpMessage(
|
|
|
|
"Alphanumberic short-form of the organization name. It's used as the prefix for host names.",
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
ref={organizationPrefixInputRef}
|
|
|
|
/>
|
|
|
|
<InputWithRef
|
|
|
|
input={
|
|
|
|
<OutlinedInputWithLabel
|
|
|
|
id="striker-init-general-host-number"
|
|
|
|
inputProps={{
|
|
|
|
inputProps: {
|
|
|
|
maxLength: MAX_HOST_NUMBER_LENGTH,
|
|
|
|
sx: {
|
|
|
|
minWidth: '2em',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
onBlur: (...args) => {
|
|
|
|
const [event] = args;
|
|
|
|
const {
|
|
|
|
target: { value },
|
|
|
|
} = event;
|
|
|
|
|
|
|
|
testInput({
|
|
|
|
inputs: { [IT_IDS.hostNumber]: { value } },
|
|
|
|
});
|
|
|
|
populateHostNameInputOnBlur(...args);
|
|
|
|
|
|
|
|
onHostNumberBlurAppend?.call(null, ...args);
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
inputLabelProps={{ isNotifyRequired: true }}
|
|
|
|
label="Striker #"
|
|
|
|
onChange={({ target: { value } }) => {
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: { [IT_IDS.hostNumber]: { value } },
|
|
|
|
});
|
|
|
|
setHostNumberInputMessage();
|
|
|
|
}}
|
|
|
|
onHelp={() => {
|
|
|
|
setHelpMessage(
|
|
|
|
buildHelpMessage(
|
|
|
|
"Number or count of this striker; this should be '1' for the first striker, '2' for the second striker, and such.",
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
ref={hostNumberInputRef}
|
|
|
|
valueType="number"
|
|
|
|
/>
|
|
|
|
</FlexBox>
|
|
|
|
</FlexBox>
|
|
|
|
</MUIGrid>
|
|
|
|
<MUIGrid item xs={1}>
|
|
|
|
<FlexBox>
|
|
|
|
<InputWithRef
|
|
|
|
input={
|
|
|
|
<OutlinedInputWithLabel
|
|
|
|
id="striker-init-general-domain-name"
|
|
|
|
inputProps={{
|
|
|
|
onBlur: (event, ...restArgs) => {
|
|
|
|
const {
|
|
|
|
target: { value },
|
|
|
|
} = event;
|
|
|
|
|
|
|
|
testInput({
|
|
|
|
inputs: { [IT_IDS.domainName]: { value } },
|
|
|
|
});
|
|
|
|
populateHostNameInputOnBlur(event, ...restArgs);
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
inputLabelProps={{ isNotifyRequired: true }}
|
|
|
|
label="Domain name"
|
|
|
|
onChange={({ target: { value } }) => {
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: { [IT_IDS.domainName]: { value } },
|
|
|
|
});
|
|
|
|
setDomainNameInputMessage();
|
|
|
|
}}
|
|
|
|
onHelp={() => {
|
|
|
|
setHelpMessage(
|
|
|
|
buildHelpMessage(
|
|
|
|
"Domain name for this striker. It's also the default domain used when creating new install manifests.",
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
ref={domainNameInputRef}
|
|
|
|
/>
|
|
|
|
|
|
|
|
<InputWithRef
|
|
|
|
input={
|
|
|
|
<OutlinedInputWithLabel
|
|
|
|
id="striker-init-general-host-name"
|
|
|
|
inputProps={{
|
|
|
|
endAdornment: (
|
|
|
|
<SuggestButton
|
|
|
|
show={isShowHostNameSuggest}
|
|
|
|
onClick={handlerHostNameSuggest}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
onBlur: ({ target: { value } }) => {
|
|
|
|
testInput({ inputs: { [IT_IDS.hostName]: { value } } });
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
inputLabelProps={{ isNotifyRequired: true }}
|
|
|
|
label="Host name"
|
|
|
|
onChange={({ target: { value } }) => {
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: { [IT_IDS.hostName]: { value } },
|
|
|
|
});
|
|
|
|
setHostNameInputMessage();
|
|
|
|
setIsShowHostNameSuggest(isHostNamePrereqFilled());
|
|
|
|
}}
|
|
|
|
onHelp={() => {
|
|
|
|
setHelpMessage(
|
|
|
|
buildHelpMessage(
|
|
|
|
"Host name for this striker. It's usually a good idea to use the auto-generated value.",
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
ref={hostNameInputRef}
|
|
|
|
/>
|
|
|
|
</FlexBox>
|
|
|
|
</MUIGrid>
|
|
|
|
<MUIGrid item xs={1} sm={2} md={1}>
|
|
|
|
<MUIGrid
|
|
|
|
columns={{ xs: 1, sm: 2, md: 1 }}
|
|
|
|
container
|
|
|
|
spacing="1em"
|
|
|
|
sx={{
|
|
|
|
'& > * > *': {
|
|
|
|
width: '100%',
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<MUIGrid item xs={1}>
|
|
|
|
<InputWithRef
|
|
|
|
input={
|
|
|
|
<OutlinedInputWithLabel
|
|
|
|
id="striker-init-general-admin-password"
|
|
|
|
inputProps={{
|
|
|
|
inputProps: {
|
|
|
|
type: INPUT_TYPES.password,
|
|
|
|
},
|
|
|
|
onBlur: ({ target: { value } }) => {
|
|
|
|
testInput({
|
|
|
|
inputs: { [IT_IDS.adminPassword]: { value } },
|
|
|
|
});
|
|
|
|
},
|
|
|
|
onPasswordVisibilityAppend: (inputType) => {
|
|
|
|
const localIsConfirmAdminPassword =
|
|
|
|
inputType === INPUT_TYPES.password;
|
|
|
|
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
isExcludeConfirmAdminPassword:
|
|
|
|
!localIsConfirmAdminPassword,
|
|
|
|
});
|
|
|
|
setIsConfirmAdminPassword(
|
|
|
|
localIsConfirmAdminPassword,
|
|
|
|
);
|
|
|
|
setConfirmAdminPasswordInputMessage();
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
inputLabelProps={{ isNotifyRequired: true }}
|
|
|
|
label="Admin password"
|
|
|
|
onChange={({ target: { value } }) => {
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: { [IT_IDS.adminPassword]: { value } },
|
|
|
|
});
|
|
|
|
setAdminPasswordInputMessage();
|
|
|
|
}}
|
|
|
|
onHelp={() => {
|
|
|
|
setHelpMessage(
|
|
|
|
buildHelpMessage(
|
|
|
|
"Password use to login to this Striker and connect to its database. Don't provide an used password here because it'll be stored as plaintext.",
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
ref={adminPasswordInputRef}
|
|
|
|
/>
|
|
|
|
</MUIGrid>
|
|
|
|
{isConfirmAdminPassword && (
|
|
|
|
<MUIGrid item xs={1}>
|
|
|
|
<InputWithRef
|
|
|
|
input={
|
|
|
|
<OutlinedInputWithLabel
|
|
|
|
id="striker-init-general-confirm-admin-password"
|
|
|
|
inputProps={{
|
|
|
|
inputProps: {
|
|
|
|
type: INPUT_TYPES.password,
|
|
|
|
},
|
|
|
|
onBlur: ({ target: { value } }) => {
|
|
|
|
testInput({
|
|
|
|
inputs: {
|
|
|
|
[IT_IDS.confirmAdminPassword]: { value },
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
inputLabelProps={{
|
|
|
|
isNotifyRequired: isConfirmAdminPassword,
|
|
|
|
}}
|
|
|
|
label="Confirm password"
|
|
|
|
onChange={({ target: { value } }) => {
|
|
|
|
testInputToToggleSubmitDisabled({
|
|
|
|
inputs: {
|
|
|
|
[IT_IDS.confirmAdminPassword]: { value },
|
|
|
|
},
|
|
|
|
});
|
|
|
|
setConfirmAdminPasswordInputMessage();
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
ref={confirmAdminPasswordInputRef}
|
|
|
|
/>
|
|
|
|
</MUIGrid>
|
|
|
|
)}
|
|
|
|
</MUIGrid>
|
|
|
|
</MUIGrid>
|
|
|
|
</MUIGrid>
|
|
|
|
<MessageGroup
|
|
|
|
count={1}
|
|
|
|
defaultMessageType="warning"
|
|
|
|
ref={messageGroupRef}
|
|
|
|
/>
|
|
|
|
<MessageBox>
|
|
|
|
<FlexBox row sx={{ '& > :last-child': { flexGrow: 1 } }}>
|
|
|
|
{validateDomainCheckbox}
|
|
|
|
<BodyText inverted>
|
|
|
|
{isValidateDomain
|
|
|
|
? 'Uncheck to skip domain and host name pattern validation.'
|
|
|
|
: 'Check to re-enable domain and host name pattern validation.'}
|
|
|
|
</BodyText>
|
|
|
|
</FlexBox>
|
|
|
|
</MessageBox>
|
|
|
|
{helpMessage && (
|
|
|
|
<MessageBox
|
|
|
|
onClose={() => {
|
|
|
|
setHelpMessage(undefined);
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{helpMessage}
|
|
|
|
</MessageBox>
|
|
|
|
)}
|
|
|
|
</FlexBox>
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
GeneralInitForm.defaultProps = {
|
|
|
|
expectHostDetail: false,
|
|
|
|
hostDetail: undefined,
|
|
|
|
onHostNumberBlurAppend: undefined,
|
|
|
|
toggleSubmitDisabled: undefined,
|
|
|
|
};
|
|
|
|
|
|
|
|
GeneralInitForm.displayName = 'GeneralInitForm';
|
|
|
|
|
|
|
|
export type { GeneralInitFormForwardedRefContent, GeneralInitFormValues };
|
|
|
|
|
|
|
|
export default GeneralInitForm;
|