From cc1fdd0822f03f796392d2fd7ce110b68b88d710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rio=20Nunes?= Date: Fri, 12 Jul 2024 20:01:36 +0800 Subject: [PATCH] chore: use react-router new routing approach RouterProvider (#3761) * chore: use react-router new routing approach RouterProvider * fix: confirmation on leaving the page --- .../src/BlockedRoute/BlockedRoute.tsx | 2 +- .../src/Breadcrumbs/BreadcrumbsItem.tsx | 8 +- .../ButtonShowReplies/ButtonShowReplies.tsx | 3 +- .../src/CommentItem/CommentItem.tsx | 2 + .../src/CommentList/CommentList.tsx | 5 +- .../src/ConfirmModal/ConfirmModal.tsx | 8 +- .../ContentStatistics/ContentStatistics.tsx | 3 +- .../src/EditComment/EditComment.tsx | 3 +- .../src/FollowButton/FollowButton.tsx | 1 + .../components/src/ImageCrop/ImageCrop.tsx | 6 +- .../components/src/MapWithPin/MapWithPin.tsx | 1 + .../src/NotificationList/NotificationList.tsx | 3 +- .../ResearchEditorOverview.tsx | 4 +- .../ResearchEditorOverview.test.tsx.snap | 6 + .../UsefulStatsButton/UsefulStatsButton.tsx | 1 + .../src/integration/howto/write.spec.ts | 19 +-- .../src/integration/research/write.spec.ts | 21 +--- .../cypress/src/integration/settings.spec.ts | 15 +-- packages/cypress/src/support/commandsUi.ts | 9 +- src/common/Error/handlers/ChunkLoadError.tsx | 4 +- src/common/Form/FileInput/FileInput.tsx | 1 + src/common/Form/ImageInput/DeleteImage.tsx | 1 + src/common/Form/UnsavedChangesDialog.tsx | 56 +++------ src/common/HideDiscussionContainer.tsx | 1 + src/common/hooks/usePrompt.ts | 48 -------- src/pages/Howto/Content/Common/Howto.form.tsx | 12 +- .../Content/Common/HowtoButtonPublish.tsx | 2 +- .../Howto/Content/Common/HowtoFieldFiles.tsx | 1 + .../Howto/Content/Common/HowtoFieldStep.tsx | 6 +- .../Common/HowtoFieldStepsContainer.tsx | 5 +- .../Howto/Content/Common/SubmitStatus.tsx | 1 + src/pages/Howto/Content/Howto/Howto.tsx | 1 + .../HowtoDescription/HowtoDescription.tsx | 3 +- .../Howto/Content/HowtoList/HowtoList.tsx | 5 +- src/pages/Maps/Content/Controls/Controls.tsx | 5 +- .../Content/Controls/GroupingFilterMobile.tsx | 2 +- .../Question/Content/Common/QuestionForm.tsx | 2 +- src/pages/Question/QuestionListing.tsx | 4 +- src/pages/Question/QuestionPage.tsx | 2 +- .../Research/Content/Common/Research.form.tsx | 71 ++--------- .../Content/Common/ResearchUpdate.form.tsx | 35 +++--- .../Research/Content/Common/SubmitStatus.tsx | 4 +- .../CreateResearch/Form/FilesFields.tsx | 7 +- .../Research/Content/ResearchArticle.tsx | 1 + .../Research/Content/ResearchDescription.tsx | 13 +- src/pages/Research/Content/ResearchList.tsx | 9 +- src/pages/Research/Content/ResearchUpdate.tsx | 5 +- src/pages/SignUp/SignUp.tsx | 2 +- src/pages/SignUp/SignUpMessage.tsx | 9 +- .../User/contact/UserContactNotLoggedIn.tsx | 4 +- src/pages/User/impact/ImpactMissing.tsx | 4 +- .../content/formSections/ChangeEmail.form.tsx | 1 + .../formSections/ChangePassword.form.tsx | 1 + .../formSections/Collection.section.tsx | 1 + .../Fields/OpeningHoursPicker.field.tsx | 48 +++++--- .../formSections/Fields/ProfileLink.field.tsx | 5 +- .../formSections/Impact/Impact.section.tsx | 1 + .../Impact/ImpactYearDisplay.field.tsx | 1 + .../formSections/PatreonIntegration.tsx | 2 + .../formSections/SettingsMapPinSection.tsx | 4 + .../formSections/UserProfile.section.tsx | 11 +- src/pages/common/Drafts/DraftButton.tsx | 1 + src/pages/common/Header/Header.tsx | 1 + .../Header/Menu/Profile/ProfileButtonItem.tsx | 1 + src/pages/common/StickyButton.tsx | 2 + src/pages/index.tsx | 116 +++++++++++------- 66 files changed, 302 insertions(+), 340 deletions(-) delete mode 100644 src/common/hooks/usePrompt.ts diff --git a/packages/components/src/BlockedRoute/BlockedRoute.tsx b/packages/components/src/BlockedRoute/BlockedRoute.tsx index f713c08771..7d842c5f7d 100644 --- a/packages/components/src/BlockedRoute/BlockedRoute.tsx +++ b/packages/components/src/BlockedRoute/BlockedRoute.tsx @@ -20,7 +20,7 @@ export const BlockedRoute = (props: BlockedRouteProps) => { {props.children} - diff --git a/packages/components/src/Breadcrumbs/BreadcrumbsItem.tsx b/packages/components/src/Breadcrumbs/BreadcrumbsItem.tsx index bc51282ac7..d71a221791 100644 --- a/packages/components/src/Breadcrumbs/BreadcrumbsItem.tsx +++ b/packages/components/src/Breadcrumbs/BreadcrumbsItem.tsx @@ -17,10 +17,14 @@ interface BreadcrumbItemProps { const BreadcrumbButton = ({ text, link }: BreadcrumbButtonProps) => { return link ? ( - + ) : ( - + ) } diff --git a/packages/components/src/ButtonShowReplies/ButtonShowReplies.tsx b/packages/components/src/ButtonShowReplies/ButtonShowReplies.tsx index 3fa29b82d4..786b67602e 100644 --- a/packages/components/src/ButtonShowReplies/ButtonShowReplies.tsx +++ b/packages/components/src/ButtonShowReplies/ButtonShowReplies.tsx @@ -20,7 +20,8 @@ export const ButtonShowReplies = (props: Props) => { return ( diff --git a/packages/components/src/MapWithPin/MapWithPin.tsx b/packages/components/src/MapWithPin/MapWithPin.tsx index a781518c6f..f0b4502b15 100644 --- a/packages/components/src/MapWithPin/MapWithPin.tsx +++ b/packages/components/src/MapWithPin/MapWithPin.tsx @@ -89,6 +89,7 @@ export const MapWithPin = (props: Props) => { /> {hasUserLocation && ( + If it doesn't work you might need to try another browser.

Or send us a{' '} diff --git a/src/common/Form/FileInput/FileInput.tsx b/src/common/Form/FileInput/FileInput.tsx index 42386e15b7..cfd4ece443 100644 --- a/src/common/Form/FileInput/FileInput.tsx +++ b/src/common/Form/FileInput/FileInput.tsx @@ -69,6 +69,7 @@ export const FileInput = (props: IProps) => { {showFileList ? ( <> diff --git a/src/pages/Howto/Content/Common/HowtoFieldStepsContainer.tsx b/src/pages/Howto/Content/Common/HowtoFieldStepsContainer.tsx index e90cd66861..5eef1fdf8e 100644 --- a/src/pages/Howto/Content/Common/HowtoFieldStepsContainer.tsx +++ b/src/pages/Howto/Content/Common/HowtoFieldStepsContainer.tsx @@ -78,8 +78,9 @@ export const HowtoFieldStepsContainer = () => { @@ -132,6 +132,7 @@ const HowtoDescription = ({ howto, loggedInUser, ...props }: IProps) => { {loggedInUser && isAllowedToDeleteContent(howto, loggedInUser) && ( diff --git a/src/pages/Maps/Content/Controls/Controls.tsx b/src/pages/Maps/Content/Controls/Controls.tsx index 7b65a7f2b7..8defe174f6 100644 --- a/src/pages/Maps/Content/Controls/Controls.tsx +++ b/src/pages/Maps/Content/Controls/Controls.tsx @@ -114,12 +114,15 @@ export const Controls = ({ // the map underneath also redirects, so prevent it from doing so onClick={(e) => e.stopPropagation()} > - + diff --git a/src/pages/Question/Content/Common/QuestionForm.tsx b/src/pages/Question/Content/Common/QuestionForm.tsx index 075c171c0b..23714219b8 100644 --- a/src/pages/Question/Content/Common/QuestionForm.tsx +++ b/src/pages/Question/Content/Common/QuestionForm.tsx @@ -127,7 +127,7 @@ export const QuestionForm = (props: IProps) => { @@ -140,7 +140,7 @@ export const QuestionListing = () => { justifyContent: 'center', }} > - diff --git a/src/pages/Question/QuestionPage.tsx b/src/pages/Question/QuestionPage.tsx index 324640c6be..68e2a32f26 100644 --- a/src/pages/Question/QuestionPage.tsx +++ b/src/pages/Question/QuestionPage.tsx @@ -114,7 +114,7 @@ export const QuestionPage = () => { /> {store.userCanEditQuestion && ( - diff --git a/src/pages/Research/Content/Common/Research.form.tsx b/src/pages/Research/Content/Common/Research.form.tsx index f09ff09ee2..0fb976109f 100644 --- a/src/pages/Research/Content/Common/Research.form.tsx +++ b/src/pages/Research/Content/Common/Research.form.tsx @@ -13,7 +13,7 @@ import { IModerationStatus } from 'oa-shared' import IconHeaderHowto from 'src/assets/images/header-section/howto-header-icon.svg' import { SelectField } from 'src/common/Form/Select.field' import { TagsSelectField } from 'src/common/Form/TagsSelect.field' -import { usePrompt } from 'src/common/hooks/usePrompt' +import { UnsavedChangesDialog } from 'src/common/Form/UnsavedChangesDialog' import { researchStatusOptions } from 'src/models/research.models' import { ResearchErrors, @@ -45,13 +45,6 @@ import ResearchFieldCategory from './ResearchCategorySelect' import type { MainFormAction } from 'src/common/Form/types' import type { IResearch } from 'src/models/research.models' -const CONFIRM_DIALOG_MSG = - 'You have unsaved changes. Are you sure you want to leave this page?' -interface IState { - formSaved: boolean - dirty: boolean - showSubmitModal?: boolean -} interface IProps { 'data-testid'?: string formValues: any @@ -64,11 +57,6 @@ const ResearchFormLabel = ({ children, ...props }) => ( ) -const beforeUnload = (e) => { - e.preventDefault() - e.returnValue = CONFIRM_DIALOG_MSG -} - const ResearchForm = observer((props: IProps) => { const { formValues, parentType } = props const { create, update } = buttons.draft @@ -85,11 +73,7 @@ const ResearchForm = observer((props: IProps) => { } = overview const store = useResearchStore() - const [state, setState] = React.useState({ - formSaved: false, - dirty: false, - showSubmitModal: false, - }) + const [showSubmitModal, setShowSubmitModal] = React.useState(false) const [submissionHandler, setSubmissionHandler] = React.useState({ draft: formValues.moderation === IModerationStatus.DRAFT, shouldSubmit: false, @@ -104,12 +88,6 @@ const ResearchForm = observer((props: IProps) => { } }, [store.activeUser]) - React.useEffect(() => { - if (store.researchUploadStatus.Complete) { - window.removeEventListener('beforeunload', beforeUnload, false) - } - }, [store.researchUploadStatus.Complete]) - React.useEffect(() => { if (submissionHandler.shouldSubmit) { const form = document.getElementById('researchForm') @@ -117,7 +95,7 @@ const ResearchForm = observer((props: IProps) => { form.dispatchEvent( new Event('submit', { cancelable: true, bubbles: true }), ) - setState((prevState) => ({ ...prevState, showSubmitModal: true })) + setShowSubmitModal(true) } } }, [submissionHandler]) @@ -129,46 +107,23 @@ const ResearchForm = observer((props: IProps) => { await store.uploadResearch(formValues) } - // Display a confirmation dialog when leaving the page outside the React Router - const unloadDecorator = (form) => { - return form.subscribe( - ({ dirty }) => { - if (dirty && !store.researchUploadStatus.Complete) { - window.addEventListener('beforeunload', beforeUnload, false) - return - } - window.removeEventListener('beforeunload', beforeUnload, false) - }, - { dirty: true }, - ) - } - - // Block navigating elsewhere when data has been entered into the input - usePrompt( - CONFIRM_DIALOG_MSG, - !store.updateUploadStatus.Complete && state.dirty, - ) - const draftButtonText = formValues.moderation !== IModerationStatus.DRAFT ? create : update const pageTitle = headings.overview[parentType] return (
- {state.showSubmitModal && ( + {showSubmitModal && ( { - setState((prevState) => ({ ...prevState, showSubmitModal: false })) + setShowSubmitModal(false) store.resetResearchUploadStatus() }} /> )} { - onSubmit(v as IResearch.FormInput) - }} + onSubmit={async (v) => await onSubmit(v as IResearch.FormInput)} initialValues={formValues} mutators={{ setAllowDraftSaveFalse, @@ -176,7 +131,6 @@ const ResearchForm = observer((props: IProps) => { ...arrayMutators, }} validateOnBlur - decorators={[unloadDecorator]} render={({ dirty, errors, @@ -185,13 +139,12 @@ const ResearchForm = observer((props: IProps) => { hasValidationErrors, submitting, submitFailed, + submitSucceeded, }) => { - if (state.dirty !== dirty) { - setState((prev) => ({ ...prev, dirty })) - } - return ( - + + + { {isEdit ? ( diff --git a/src/pages/Research/Content/ResearchArticle.tsx b/src/pages/Research/Content/ResearchArticle.tsx index 284237aa2e..ca396d4ea9 100644 --- a/src/pages/Research/Content/ResearchArticle.tsx +++ b/src/pages/Research/Content/ResearchArticle.tsx @@ -275,6 +275,7 @@ const ResearchArticle = observer(() => { @@ -162,8 +164,9 @@ const ResearchDescription = ({ {isDeletable && ( @@ -147,7 +147,7 @@ const ResearchList = observer(() => { handleShowDrafts={handleShowDrafts} /> - @@ -185,7 +185,10 @@ const ResearchList = observer(() => { justifyContent: 'center', }} > - diff --git a/src/pages/Research/Content/ResearchUpdate.tsx b/src/pages/Research/Content/ResearchUpdate.tsx index e902b4441f..c76d0a0e90 100644 --- a/src/pages/Research/Content/ResearchUpdate.tsx +++ b/src/pages/Research/Content/ResearchUpdate.tsx @@ -138,8 +138,9 @@ const ResearchUpdate = ({ to={'/research/' + slug + '/edit-update/' + update._id} > diff --git a/src/pages/User/contact/UserContactNotLoggedIn.tsx b/src/pages/User/contact/UserContactNotLoggedIn.tsx index fb440c8802..ad76d47ba6 100644 --- a/src/pages/User/contact/UserContactNotLoggedIn.tsx +++ b/src/pages/User/contact/UserContactNotLoggedIn.tsx @@ -27,7 +27,9 @@ export const UserContactNotLoggedIn = ({ displayName }: Props) => { Login - + diff --git a/src/pages/User/impact/ImpactMissing.tsx b/src/pages/User/impact/ImpactMissing.tsx index dfcce0ea5d..2defb1f33a 100644 --- a/src/pages/User/impact/ImpactMissing.tsx +++ b/src/pages/User/impact/ImpactMissing.tsx @@ -55,13 +55,13 @@ export const ImpactMissing = observer((props: Props) => { <> {reportYearLabel} - + )} {isPageOwner && ( - + )} diff --git a/src/pages/UserSettings/content/formSections/ChangeEmail.form.tsx b/src/pages/UserSettings/content/formSections/ChangeEmail.form.tsx index 351dc535c0..ebd8b4e5a1 100644 --- a/src/pages/UserSettings/content/formSections/ChangeEmail.form.tsx +++ b/src/pages/UserSettings/content/formSections/ChangeEmail.form.tsx @@ -126,6 +126,7 @@ export const ChangeEmailForm = () => { )} + {index > 0 && ( + + )} toggleDeleteModal()} isOpen={state.showDeleteModal} @@ -230,8 +236,9 @@ export const OpeningHoursPicker = (props: IProps) => { diff --git a/src/pages/UserSettings/content/formSections/Fields/ProfileLink.field.tsx b/src/pages/UserSettings/content/formSections/Fields/ProfileLink.field.tsx index ec3309acf3..d3dfdfb660 100644 --- a/src/pages/UserSettings/content/formSections/Fields/ProfileLink.field.tsx +++ b/src/pages/UserSettings/content/formSections/Fields/ProfileLink.field.tsx @@ -79,9 +79,10 @@ export const ProfileLinkField = (props: IProps) => { const DeleteButton = (props) => ( {user.patreon && (
} + > + + + + + + } + key="index" + > + {routeElements} + , + ]), + ) + return ( - - - - } - > - - {menuItems.map((page) => ( - - -
- <>{page.component} -
- - } - /> - ))} - {isModuleSupported(MODULE.QUESTION) ? ( - - -
- -
- - } - /> - ) : null} - } /> - } /> -
-
-
- +
) }