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:
parent
d7ce13d260
commit
9859213e19
14 changed files with 72 additions and 49 deletions
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
|
@ -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 />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
28
packages/ui/src/containers/TermsOfUsePromiseModal/index.tsx
Normal file
28
packages/ui/src/containers/TermsOfUsePromiseModal/index.tsx
Normal 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);
|
|
@ -61,7 +61,7 @@ const UsernameSignin = ({ className }: Props) => {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!termsValidation()) {
|
||||
if (!(await termsValidation())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -51,7 +51,7 @@ const useSocial = () => {
|
|||
|
||||
const invokeSocialSignInHandler = useCallback(
|
||||
async (connectorId: string, callback?: () => void) => {
|
||||
if (!termsValidation()) {
|
||||
if (!(await termsValidation())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -56,6 +56,6 @@ describe('<SignIn />', () => {
|
|||
</SettingsProvider>
|
||||
);
|
||||
|
||||
expect(container.querySelectorAll('button')).toHaveLength(3);
|
||||
expect(container.querySelectorAll('button')).toHaveLength(4); // Plus Expand Button
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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'}
|
||||
|
|
Loading…
Reference in a new issue