From f6614d2ef39046b0783cf55dcf459b3efed89d70 Mon Sep 17 00:00:00 2001 From: Hsu Zhong Jun <27919917+dcshzj@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:11:19 +0800 Subject: [PATCH] feat(homepage): allow user to override changes when there is a conflict (#1588) --- .../OverwriteChangesModal.tsx | 4 +- .../homepageHooks/useUpdateHomepageHook.ts | 35 +++++++--- src/layouts/EditHomepage/EditHomepage.jsx | 69 +++++++++++++++---- .../components/OverrideWarningModal.tsx | 4 +- 4 files changed, 85 insertions(+), 27 deletions(-) diff --git a/src/components/OverwriteChangesModal/OverwriteChangesModal.tsx b/src/components/OverwriteChangesModal/OverwriteChangesModal.tsx index f084e6783..2704fb151 100644 --- a/src/components/OverwriteChangesModal/OverwriteChangesModal.tsx +++ b/src/components/OverwriteChangesModal/OverwriteChangesModal.tsx @@ -27,8 +27,8 @@ export const OverwriteChangesModal = ({ edits now, their changes will be lost. - We recommend you to make a copy of your changes elsewhere and come - back later. + We recommend you to make a copy of your changes elsewhere, and + come back later to reconcile your changes. diff --git a/src/hooks/homepageHooks/useUpdateHomepageHook.ts b/src/hooks/homepageHooks/useUpdateHomepageHook.ts index 886dbfee6..31b7a2b5e 100644 --- a/src/hooks/homepageHooks/useUpdateHomepageHook.ts +++ b/src/hooks/homepageHooks/useUpdateHomepageHook.ts @@ -1,5 +1,10 @@ import { AxiosError } from "axios" -import { UseMutationResult, useQueryClient, useMutation } from "react-query" +import { + UseMutationResult, + useQueryClient, + useMutation, + UseMutationOptions, +} from "react-query" import { GET_HOMEPAGE_KEY } from "constants/queryKeys" @@ -9,27 +14,41 @@ import { HomepageDto } from "types/homepage" import { useSuccessToast, useErrorToast, DEFAULT_RETRY_MSG } from "utils" export const useUpdateHomepageHook = ( - siteName: string + siteName: string, + mutationOptions?: Omit< + UseMutationOptions, HomepageDto>, + "mutationFn" | "mutationKey" + > ): UseMutationResult, HomepageDto> => { const queryClient = useQueryClient() const successToast = useSuccessToast() const errorToast = useErrorToast() + return useMutation( (homepageData: HomepageDto) => HomepageService.updateHomepage(siteName, homepageData), { - onSuccess: () => { + ...mutationOptions, + onSettled: () => { queryClient.invalidateQueries([GET_HOMEPAGE_KEY, siteName]) + }, + onSuccess: (data, variables, context) => { successToast({ id: "update-homepage-success", description: "Homepage updated successfully", }) + if (mutationOptions?.onSuccess) + mutationOptions.onSuccess(data, variables, context) }, - onError: (err: AxiosError) => { - errorToast({ - id: "update-homepage-error", - description: `Could not update homepage. ${DEFAULT_RETRY_MSG}. Error: ${err.response?.data.error.message}`, - }) + onError: (err, variables, context) => { + if (err.response?.status !== 409) { + errorToast({ + id: "update-homepage-error", + description: `Could not update homepage. ${DEFAULT_RETRY_MSG}. Error: ${err.response?.data?.message}`, + }) + } + if (mutationOptions?.onError) + mutationOptions.onError(err, variables, context) }, } ) diff --git a/src/layouts/EditHomepage/EditHomepage.jsx b/src/layouts/EditHomepage/EditHomepage.jsx index bdd138dbe..42565e7bb 100644 --- a/src/layouts/EditHomepage/EditHomepage.jsx +++ b/src/layouts/EditHomepage/EditHomepage.jsx @@ -20,6 +20,7 @@ import { Footer } from "components/Footer" import { Greyscale } from "components/Greyscale" import Header from "components/Header" import { LoadingButton } from "components/LoadingButton" +import { OverwriteChangesModal } from "components/OverwriteChangesModal" import { WarningModal } from "components/WarningModal" import { FEATURE_FLAGS } from "constants/featureFlags" @@ -207,11 +208,27 @@ const EditHomepage = ({ match }) => { id: "", type: "", }) - const { isOpen, onOpen, onClose } = useDisclosure() + const { + isOpen: isSectionDeleteOpen, + onOpen: onSectionDeleteOpen, + onClose: onSectionDeleteClose, + } = useDisclosure() + const { + isOpen: isOverwriteOpen, + onOpen: onOverwriteOpen, + onClose: onOverwriteClose, + } = useDisclosure() const [savedHeroElems, setSavedHeroElems] = useState("") const [savedHeroErrors, setSavedHeroErrors] = useState("") const { data: homepageData } = useGetHomepageHook(siteName) - const { mutateAsync: updateHomepageHandler } = useUpdateHomepageHook(siteName) + const { mutateAsync: updateHomepageHandler } = useUpdateHomepageHook( + siteName, + { + onError: (err) => { + if (err.response.status === 409) onOverwriteOpen() + }, + } + ) const homepageState = { frontMatter, errors, @@ -237,6 +254,8 @@ const EditHomepage = ({ match }) => { setDisplayAnnouncementItems(displayAnnouncementItems) } const heroSection = frontMatter.sections.filter((section) => !!section.hero) + const hasChanges = + JSON.stringify(originalFrontMatter) !== JSON.stringify(frontMatter) const errorToast = useErrorToast() @@ -244,6 +263,14 @@ const EditHomepage = ({ match }) => { // TODO: Shift this into react query + custom hook useEffect(() => { if (!homepageData) return + if (!!homepageData && hasChanges) { + // We do not want to override changes made by the user but we want the + // user to be able to save using the latest sha if they choose to override + const { sha } = homepageData + setSha(sha) + return + } + const loadPageDetails = async () => { // Set page colors try { @@ -907,7 +934,7 @@ const EditHomepage = ({ match }) => { } const onDeleteClick = (id, name) => { - onOpen() + onSectionDeleteOpen() setItemPendingForDelete({ id, type: name }) } @@ -1163,11 +1190,13 @@ const EditHomepage = ({ match }) => { resetFirstLoad() await updateHomepageHandler(params) } catch (err) { - errorToast({ - id: "update-homepage-error", - description: `There was a problem trying to save your homepage. ${DEFAULT_RETRY_MSG}`, - }) - console.log(err) + if (err.response.status !== 409) { + errorToast({ + id: "update-homepage-error", + description: `There was a problem trying to save your homepage. ${DEFAULT_RETRY_MSG}`, + }) + console.log(err) + } } } @@ -1184,11 +1213,12 @@ const EditHomepage = ({ match }) => { const showNewLayouts = useFeatureIsOn(FEATURE_FLAGS.HOMEPAGE_TEMPLATES) return ( <> + {/* Section deletion warning modal */} { setItemPendingForDelete({ id: null, type: "" }) - onClose() + onSectionDeleteClose() }} displayTitle={`Delete ${itemPendingForDelete.type}`} displayText={ @@ -1202,7 +1232,7 @@ const EditHomepage = ({ match }) => { colorScheme="secondary" onClick={() => { setItemPendingForDelete({ id: null, type: "" }) - onClose() + onSectionDeleteClose() }} > Cancel @@ -1212,18 +1242,27 @@ const EditHomepage = ({ match }) => { onClick={() => { deleteHandler(itemPendingForDelete.id) setItemPendingForDelete({ id: null, type: "" }) - onClose() + onSectionDeleteClose() }} > Yes, delete + + {/* Override changes warning modal */} + { + onOverwriteClose() + savePage() + }} + /> +
- We recommend you to make a copy of your changes elsewhere and come - back later. + We recommend you to make a copy of your changes elsewhere, and + come back later to reconcile your changes.