0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor(ui): refactor terms modal as a promisified function (#897)

refactor terms modal as a promisified function
This commit is contained in:
simeng-li 2022-05-20 09:59:40 +08:00 committed by GitHub
parent d7ce13d260
commit 9859213e19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 72 additions and 49 deletions

View file

@ -54,6 +54,7 @@
"react-dom": "^17.0.2",
"react-i18next": "^11.15.4",
"react-modal": "^3.14.4",
"react-modal-promise": "^1.0.2",
"react-phone-number-input": "^3.1.46",
"react-router-dom": "^6.2.2",
"react-string-replace": "^1.0.0",

View file

@ -58,12 +58,12 @@ const CreateAccount = ({ className }: Props) => {
const { result, run: asyncRegister } = useApi(register, registerErrorHandlers);
const onSubmitHandler = useCallback(() => {
const onSubmitHandler = useCallback(async () => {
if (!validateForm()) {
return;
}
if (!termsValidation()) {
if (!(await termsValidation())) {
return;
}

View file

@ -53,12 +53,12 @@ const EmailPasswordless = ({ type, className }: Props) => {
const sendPasscode = getSendPasscodeApi(type, 'email');
const { result, run: asyncSendPasscode } = useApi(sendPasscode, errorHandlers);
const onSubmitHandler = useCallback(() => {
const onSubmitHandler = useCallback(async () => {
if (!validateForm()) {
return;
}
if (!termsValidation()) {
if (!(await termsValidation())) {
return;
}

View file

@ -63,12 +63,12 @@ const PhonePasswordless = ({ type, className }: Props) => {
[isValidPhoneNumber]
);
const onSubmitHandler = useCallback(() => {
const onSubmitHandler = useCallback(async () => {
if (!validateForm()) {
return;
}
if (!termsValidation()) {
if (!(await termsValidation())) {
return;
}

View file

@ -34,7 +34,7 @@ describe('SecondarySocialSignIn', () => {
</SettingsProvider>
);
expect(container.querySelectorAll('button')).toHaveLength(defaultSize);
expect(container.querySelectorAll('button')).toHaveLength(defaultSize + 1); // Expand button
const expandButton = container.querySelector('svg');
@ -42,6 +42,6 @@ describe('SecondarySocialSignIn', () => {
fireEvent.click(expandButton);
}
expect(container.querySelectorAll('button')).toHaveLength(socialConnectors.length);
expect(container.querySelectorAll('button')).toHaveLength(socialConnectors.length + 1); // Expand button
});
});

View file

@ -61,7 +61,7 @@ describe('SecondarySocialSignIn', () => {
</MemoryRouter>
</SettingsProvider>
);
expect(container.querySelectorAll('button')).toHaveLength(defaultSize - 1);
expect(container.querySelectorAll('button')).toHaveLength(defaultSize); // Plus Expand button
expect(container.querySelector('svg')).not.toBeNull();
});

View file

@ -1,7 +1,7 @@
import React from 'react';
import ModalContainer from 'react-modal-promise';
import PureTermsOfUse from '@/components/TermsOfUse';
import TermsOfUseModal from '@/components/TermsOfUseModal';
import useTerms from '@/hooks/use-terms';
type Props = {
@ -9,8 +9,7 @@ type Props = {
};
const TermsOfUse = ({ className }: Props) => {
const { termsAgreement, setTermsAgreement, termsSettings, showTermsModal, setShowTermsModal } =
useTerms();
const { termsAgreement, setTermsAgreement, termsSettings } = useTerms();
if (!termsSettings?.enabled || !termsSettings.contentUrl) {
return null;
@ -27,17 +26,7 @@ const TermsOfUse = ({ className }: Props) => {
setTermsAgreement(checked);
}}
/>
<TermsOfUseModal
isOpen={showTermsModal}
termsUrl={termsSettings.contentUrl}
onConfirm={() => {
setTermsAgreement(true);
setShowTermsModal(false);
}}
onClose={() => {
setShowTermsModal(false);
}}
/>
<ModalContainer />
</>
);
};

View file

@ -0,0 +1,28 @@
import React, { useContext } from 'react';
import { create, InstanceProps } from 'react-modal-promise';
import TermsOfUseModal from '@/components/TermsOfUseModal';
import { PageContext } from '@/hooks/use-page-context';
const TermsOfUsePromiseModal = ({ isOpen, onResolve, onReject }: InstanceProps<boolean>) => {
const { setTermsAgreement, experienceSettings } = useContext(PageContext);
const { termsOfUse } = experienceSettings ?? {};
return (
<TermsOfUseModal
isOpen={isOpen}
termsUrl={termsOfUse?.contentUrl ?? ''}
onConfirm={() => {
setTermsAgreement(true);
onResolve(true);
}}
onClose={() => {
onReject(false);
}}
/>
);
};
export default TermsOfUsePromiseModal;
export const termsOfUseModalPromise = create(TermsOfUsePromiseModal);

View file

@ -61,7 +61,7 @@ const UsernameSignin = ({ className }: Props) => {
return;
}
if (!termsValidation()) {
if (!(await termsValidation())) {
return;
}

View file

@ -9,14 +9,12 @@ type Context = {
loading: boolean;
platform: Platform;
termsAgreement: boolean;
showTermsModal: boolean;
experienceSettings: SignInExperienceSettings | undefined;
setTheme: (theme: Theme) => void;
setToast: (message: string) => void;
setLoading: (loading: boolean) => void;
setPlatform: (platform: Platform) => void;
setTermsAgreement: (termsAgreement: boolean) => void;
setShowTermsModal: (showTermsModal: boolean) => void;
setExperienceSettings: (settings: SignInExperienceSettings) => void;
};
@ -30,14 +28,12 @@ export const PageContext = createContext<Context>({
loading: false,
platform: isMobile ? 'mobile' : 'web',
termsAgreement: false,
showTermsModal: false,
experienceSettings: undefined,
setTheme: noop,
setToast: noop,
setLoading: noop,
setPlatform: noop,
setTermsAgreement: noop,
setShowTermsModal: noop,
setExperienceSettings: noop,
});
@ -48,7 +44,6 @@ const usePageContext = () => {
const [platform, setPlatform] = useState<Platform>(isMobile ? 'mobile' : 'web');
const [experienceSettings, setExperienceSettings] = useState<SignInExperienceSettings>();
const [termsAgreement, setTermsAgreement] = useState(false);
const [showTermsModal, setShowTermsModal] = useState(false);
const context = useMemo(
() => ({
@ -57,17 +52,15 @@ const usePageContext = () => {
loading,
platform,
termsAgreement,
showTermsModal,
experienceSettings,
setTheme,
setLoading,
setToast,
setPlatform,
setTermsAgreement,
setShowTermsModal,
setExperienceSettings,
}),
[experienceSettings, loading, platform, showTermsModal, termsAgreement, theme, toast]
[experienceSettings, loading, platform, termsAgreement, theme, toast]
);
return {

View file

@ -51,7 +51,7 @@ const useSocial = () => {
const invokeSocialSignInHandler = useCallback(
async (connectorId: string, callback?: () => void) => {
if (!termsValidation()) {
if (!(await termsValidation())) {
return;
}

View file

@ -1,33 +1,33 @@
import { useContext, useCallback } from 'react';
import { termsOfUseModalPromise } from '@/containers/TermsOfUsePromiseModal';
import { PageContext } from './use-page-context';
const useTerms = () => {
const {
termsAgreement,
setTermsAgreement,
showTermsModal,
setShowTermsModal,
experienceSettings,
} = useContext(PageContext);
const { termsAgreement, setTermsAgreement, experienceSettings } = useContext(PageContext);
const termsValidation = useCallback(() => {
if (termsAgreement || !experienceSettings?.termsOfUse.enabled) {
const { termsOfUse } = experienceSettings ?? {};
const termsValidation = useCallback(async () => {
if (termsAgreement || !termsOfUse?.enabled || !termsOfUse.contentUrl) {
return true;
}
setShowTermsModal(true);
try {
await termsOfUseModalPromise();
return false;
}, [experienceSettings, termsAgreement, setShowTermsModal]);
return true;
} catch {
return false;
}
}, [termsAgreement, termsOfUse]);
return {
termsSettings: experienceSettings?.termsOfUse,
termsSettings: termsOfUse,
termsAgreement,
showTermsModal,
termsValidation,
setTermsAgreement,
setShowTermsModal,
};
};

View file

@ -56,6 +56,6 @@ describe('<SignIn />', () => {
</SettingsProvider>
);
expect(container.querySelectorAll('button')).toHaveLength(3);
expect(container.querySelectorAll('button')).toHaveLength(4); // Plus Expand Button
});
});

View file

@ -964,6 +964,7 @@ importers:
react-dom: ^17.0.2
react-i18next: ^11.15.4
react-modal: ^3.14.4
react-modal-promise: ^1.0.2
react-phone-number-input: ^3.1.46
react-router-dom: ^6.2.2
react-string-replace: ^1.0.0
@ -1010,6 +1011,7 @@ importers:
react-dom: 17.0.2_react@17.0.2
react-i18next: 11.15.4_fq32mavcto3l2u7t3zyhvdh4yu
react-modal: 3.14.4_sfoxds7t5ydpegc3knd667wn6m
react-modal-promise: 1.0.2_sfoxds7t5ydpegc3knd667wn6m
react-phone-number-input: 3.1.46_sfoxds7t5ydpegc3knd667wn6m
react-router-dom: 6.2.2_sfoxds7t5ydpegc3knd667wn6m
react-string-replace: 1.0.0
@ -16623,6 +16625,16 @@ packages:
- supports-color
dev: true
/react-modal-promise/1.0.2_sfoxds7t5ydpegc3knd667wn6m:
resolution: {integrity: sha512-dqT618ROhG8qh1+O6EZkia5ELw3zaZWGpMX2YfEH4bgwYENPuFonqKw1W70LFx3K/SCZvVBcD6UYEI12yzYXzg==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
dependencies:
react: 17.0.2
react-dom: 17.0.2_react@17.0.2
dev: true
/react-modal/3.14.4_sfoxds7t5ydpegc3knd667wn6m:
resolution: {integrity: sha512-8surmulejafYCH9wfUmFyj4UfbSJwjcgbS9gf3oOItu4Hwd6ivJyVBETI0yHRhpJKCLZMUtnhzk76wXTsNL6Qg==}
engines: {node: '>=8'}