fix(striker-ui): disable submit in StrikerInitForm until sub-forms are valid

main
Tsu-ba-me 2 years ago
parent 9f9f16dc93
commit 56100ee62b
  1. 153
      striker-ui/components/GeneralInitForm.tsx
  2. 34
      striker-ui/components/StrikerInitForm.tsx

@ -23,11 +23,7 @@ import OutlinedInputWithLabel, {
} from './OutlinedInputWithLabel';
import pad from '../lib/pad';
import SuggestButton from './SuggestButton';
import {
createTestInputFunction,
testLength,
testNotBlank,
} from '../lib/test_input';
import { createTestInputFunction, testNotBlank } from '../lib/test_input';
import { InputTestBatches } from '../types/TestInputFunction';
import { BodyText } from './Text';
@ -51,6 +47,15 @@ const MAX_ORGANIZATION_PREFIX_LENGTH = 5;
const MIN_ORGANIZATION_PREFIX_LENGTH = 1;
const MAX_HOST_NUMBER_LENGTH = 2;
const INPUT_COUNT = 7;
const INPUT_TEST_IDS = {
adminPassword: 'adminPassword',
confirmAdminPassword: 'confirmAdminPassword',
domainName: 'domainName',
hostName: 'hostName',
hostNumber: 'hostNumber',
organizationName: 'organizationName',
organizationPrefix: 'organizationPrefix',
};
const MAP_TO_ORGANIZATION_PREFIX_BUILDER: Record<
number,
@ -104,30 +109,28 @@ const MessageChildren: FC<FlexBoxProps> = ({ ...flexBoxProps }) => (
/>
);
const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
(generalInitFormProps, ref) => {
const GeneralInitForm = forwardRef<
GeneralInitFormForwardRefContent,
{ toggleSubmitDisabled?: ToggleSubmitDisabledFunction }
>(({ 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] =
useState<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'>>({});
@ -166,8 +169,9 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
const inputTests: InputTestBatches = useMemo(
() => ({
adminPassword: {
[INPUT_TEST_IDS.adminPassword]: {
defaults: {
getValue: () => adminPasswordInputRef.current.getValue?.call(null),
onSuccess: () => {
setAdminPasswordInputMessage(undefined);
},
@ -191,8 +195,10 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
{ test: testNotBlank },
],
},
confirmAdminPassword: {
[INPUT_TEST_IDS.confirmAdminPassword]: {
defaults: {
getValue: () =>
confirmAdminPasswordInputRef.current.getValue?.call(null),
onSuccess: () => {
setConfirmAdminPasswordInputMessage(undefined);
},
@ -210,8 +216,9 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
{ test: testNotBlank },
],
},
domainName: {
[INPUT_TEST_IDS.domainName]: {
defaults: {
getValue: () => domainNameInputRef.current.getValue?.call(null),
onSuccess: () => {
setDomainNameInputMessage(undefined);
},
@ -222,8 +229,8 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
setDomainNameInputMessage({
children: (
<MessageChildren>
Domain name can only contain lowercase alphanumeric,
hyphen ({ms('-')}), and dot ({ms('.')}) characters.
Domain name can only contain lowercase alphanumeric, hyphen
({ms('-')}), and dot ({ms('.')}) characters.
</MessageChildren>
),
});
@ -233,8 +240,9 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
{ test: testNotBlank },
],
},
hostName: {
[INPUT_TEST_IDS.hostName]: {
defaults: {
getValue: () => hostNameInputRef.current.getValue?.call(null),
onSuccess: () => {
setHostNameInputMessage(undefined);
},
@ -245,8 +253,8 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
setHostNameInputMessage({
children: (
<MessageChildren>
Host name can only contain lowercase alphanumeric, hyphen
({ms('-')}), and dot ({ms('.')}) characters.
Host name can only contain lowercase alphanumeric, hyphen (
{ms('-')}), and dot ({ms('.')}) characters.
</MessageChildren>
),
});
@ -256,8 +264,9 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
{ test: testNotBlank },
],
},
hostNumber: {
[INPUT_TEST_IDS.hostNumber]: {
defaults: {
getValue: () => hostNumberInputRef.current.getValue?.call(null),
onSuccess: () => {
setHostNumberInputMessage(undefined);
},
@ -274,11 +283,18 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
{ test: testNotBlank },
],
},
organizationName: {
[INPUT_TEST_IDS.organizationName]: {
defaults: {
getValue: () => organizationNameInputRef.current.getValue?.call(null),
},
tests: [{ test: testNotBlank }],
},
organizationPrefix: {
[INPUT_TEST_IDS.organizationPrefix]: {
defaults: {
getValue: () =>
organizationPrefixInputRef.current.getValue?.call(null),
max: MAX_ORGANIZATION_PREFIX_LENGTH,
min: MIN_ORGANIZATION_PREFIX_LENGTH,
onSuccess: () => {
setOrganizationPrefixInputMessage(undefined);
},
@ -287,21 +303,12 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
{
onFailure: ({ max, min }) => {
setOrganizationPrefixInputMessage({
children: `Organization prefix must be ${min} to ${max} characters.`,
children: `Organization prefix must be ${min} to ${max} lowercase alphanumeric characters.`,
});
},
test: testLength,
},
{
onFailure: () => {
setOrganizationPrefixInputMessage({
children:
'Organization prefix can only contain lowercase alphanumeric characters.',
});
test: ({ max, min, value }) =>
RegExp(`^[a-z0-9]{${min},${max}}$`).test(value as string),
},
test: ({ value }) => /^[a-z0-9]+$/.test(value as string),
},
{ test: testNotBlank },
],
},
}),
@ -319,11 +326,14 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
() => createTestInputFunction(inputTests),
[inputTests],
);
const testAllInputs = useCallback(
(...excludeTestIds: string[]) =>
testInput({ excludeTestIds, isIgnoreOnCallbacks: true }),
[testInput],
);
const populateOrganizationPrefixInput = useCallback(
({
organizationName = organizationNameInputRef.current.getValue?.call(
null,
),
organizationName = organizationNameInputRef.current.getValue?.call(null),
} = {}) => {
const organizationPrefix = buildOrganizationPrefix(organizationName);
@ -380,9 +390,7 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
const populateOrganizationPrefixInputOnBlur: OutlinedInputWithLabelOnBlur =
useCallback(() => {
if (organizationPrefixInputRef.current.getIsChangedByUser?.call(null)) {
setIsShowOrganizationPrefixSuggest(
isOrganizationPrefixPrereqFilled(),
);
setIsShowOrganizationPrefixSuggest(isOrganizationPrefixPrereqFilled());
} else {
populateOrganizationPrefixInput();
}
@ -437,6 +445,9 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
}}
inputLabelProps={{ isNotifyRequired: true }}
label="Organization name"
onChange={() => {
toggleSubmitDisabled?.call(null, testAllInputs());
}}
onHelp={() => {
setHelpMessage(
buildHelpMessage(
@ -480,13 +491,17 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
onChange={({ target: { value } }) => {
testInput({
inputs: {
organizationPrefix: {
[INPUT_TEST_IDS.organizationPrefix]: {
max: MAX_ORGANIZATION_PREFIX_LENGTH,
min: MIN_ORGANIZATION_PREFIX_LENGTH,
value,
},
},
});
toggleSubmitDisabled?.call(
null,
testAllInputs(INPUT_TEST_IDS.organizationPrefix),
);
setIsShowOrganizationPrefixSuggest(
isOrganizationPrefixPrereqFilled(),
);
@ -518,7 +533,13 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
inputLabelProps={{ isNotifyRequired: true }}
label="Striker #"
onChange={({ target: { value } }) => {
testInput({ inputs: { hostNumber: { value } } });
testInput({
inputs: { [INPUT_TEST_IDS.hostNumber]: { value } },
});
toggleSubmitDisabled?.call(
null,
testAllInputs(INPUT_TEST_IDS.hostNumber),
);
}}
onHelp={() => {
setHelpMessage(
@ -547,7 +568,13 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
inputLabelProps={{ isNotifyRequired: true }}
label="Domain name"
onChange={({ target: { value } }) => {
testInput({ inputs: { domainName: { value } } });
testInput({
inputs: { [INPUT_TEST_IDS.domainName]: { value } },
});
toggleSubmitDisabled?.call(
null,
testAllInputs(INPUT_TEST_IDS.domainName),
);
}}
onHelp={() => {
setHelpMessage(
@ -576,7 +603,13 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
inputLabelProps={{ isNotifyRequired: true }}
label="Host name"
onChange={({ target: { value } }) => {
testInput({ inputs: { hostName: { value } } });
testInput({
inputs: { [INPUT_TEST_IDS.hostName]: { value } },
});
toggleSubmitDisabled?.call(
null,
testAllInputs(INPUT_TEST_IDS.hostName),
);
setIsShowHostNameSuggest(isHostNamePrereqFilled());
}}
onHelp={() => {
@ -621,7 +654,13 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
inputLabelProps={{ isNotifyRequired: true }}
label="Admin password"
onChange={({ target: { value } }) => {
testInput({ inputs: { adminPassword: { value } } });
testInput({
inputs: { [INPUT_TEST_IDS.adminPassword]: { value } },
});
toggleSubmitDisabled?.call(
null,
testAllInputs(INPUT_TEST_IDS.adminPassword),
);
}}
onHelp={() => {
setHelpMessage(
@ -652,8 +691,14 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
label="Confirm password"
onChange={({ target: { value } }) => {
testInput({
inputs: { confirmAdminPassword: { value } },
inputs: {
[INPUT_TEST_IDS.confirmAdminPassword]: { value },
},
});
toggleSubmitDisabled?.call(
null,
testAllInputs(INPUT_TEST_IDS.confirmAdminPassword),
);
}}
/>
}
@ -680,9 +725,9 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
)}
</FlexBox>
);
},
);
});
GeneralInitForm.defaultProps = { toggleSubmitDisabled: undefined };
GeneralInitForm.displayName = 'GeneralInitForm';
export type { GeneralInitFormForwardRefContent };

@ -1,4 +1,4 @@
import { FC, useMemo, useRef, useState } from 'react';
import { FC, useCallback, useMemo, useRef, useState } from 'react';
import ContainedButton from './ContainedButton';
import FlexBox from './FlexBox';
@ -16,6 +16,11 @@ import { HeaderText } from './Text';
const StrikerInitForm: FC = () => {
const [submitMessage, setSubmitMessage] = useState<Message | undefined>();
const [isDisableSubmit, setIsDisableSubmit] = useState<boolean>(true);
const [isGeneralInitFormValid, setIsGeneralInitFormValid] =
useState<boolean>(false);
const [isNetworkInitFormValid, setIsNetworkInitFormValid] =
useState<boolean>(false);
const [isSubmittingForm, setIsSubmittingForm] = useState<boolean>(false);
const generalInitFormRef = useRef<GeneralInitFormForwardRefContent>({});
@ -28,6 +33,7 @@ const StrikerInitForm: FC = () => {
) : (
<FlexBox row sx={{ flexDirection: 'row-reverse' }}>
<ContainedButton
disabled={isDisableSubmit}
onClick={() => {
setIsSubmittingForm(true);
@ -57,17 +63,37 @@ const StrikerInitForm: FC = () => {
</ContainedButton>
</FlexBox>
),
[isSubmittingForm],
[isDisableSubmit, isSubmittingForm],
);
const toggleSubmitDisabled = useCallback((...testResults: boolean[]) => {
setIsDisableSubmit(!testResults.every((testResult) => testResult));
}, []);
return (
<Panel>
<PanelHeader>
<HeaderText text="Initialize striker" />
</PanelHeader>
<FlexBox>
<GeneralInitForm ref={generalInitFormRef} />
<NetworkInitForm ref={networkInitFormRef} />
<GeneralInitForm
ref={generalInitFormRef}
toggleSubmitDisabled={(testResult) => {
if (testResult !== isGeneralInitFormValid) {
setIsGeneralInitFormValid(testResult);
toggleSubmitDisabled(testResult, isNetworkInitFormValid);
}
}}
/>
<NetworkInitForm
ref={networkInitFormRef}
toggleSubmitDisabled={(testResult) => {
if (testResult !== isNetworkInitFormValid) {
setIsNetworkInitFormValid(testResult);
toggleSubmitDisabled(isGeneralInitFormValid, testResult);
}
}}
/>
{submitMessage && (
<MessageBox
{...submitMessage}

Loading…
Cancel
Save