From 955d1c9a3885d6b7beace6e49c08d719adb4f34b Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 27 Sep 2023 00:32:47 +0800 Subject: [PATCH 1/6] chore: refactor homepage to if/else to preserve existing behaviour --- src/hooks/useDrag.tsx | 880 +++++++++++----------- src/layouts/EditHomepage/EditHomepage.jsx | 8 +- src/types/homepage.ts | 2 +- 3 files changed, 449 insertions(+), 441 deletions(-) diff --git a/src/hooks/useDrag.tsx b/src/hooks/useDrag.tsx index c8fbec395..66728d7e7 100644 --- a/src/hooks/useDrag.tsx +++ b/src/hooks/useDrag.tsx @@ -184,6 +184,31 @@ export const useDrag: OnDragEndResponseWrapper = ( return updateHomepageState(result, homepageState) } +type UpdateHomepageType = + | "editor" + | "dropdownelem" + | "highlight" + | "announcement" + | `textcardcard-${number}` + +const isUpdateHomepageType = (value: any): value is UpdateHomepageType => { + if (typeof value === "string" && value.startsWith("textcardcard-")) { + const valArr = value.split("-") + const number = valArr[1] + return valArr.length === 2 && !Number.isNaN(Number(number)) + } + if (typeof value === "string") { + return ( + value === "editor" || + value === "dropdownelem" || + value === "highlight" || + value === "announcement" + ) + } + + return false +} + // NOTE: We mutate by addr in some places // maybe we just do a deep copy? // and point it to a store next time, @@ -211,211 +236,208 @@ const updateHomepageState = ( destination.index === source.index ) return homepageState - - const typeArray = type.split("-") - switch (typeArray[0]) { - case "editor": { - const draggedElem = frontMatter.sections[source.index] - const newSections = updatePositions( - frontMatter.sections, - source.index, - destination.index, - draggedElem - ) - const draggedError = errors.sections[source.index] - const newSectionErrors = updatePositions( - errors.sections, - source.index, - destination.index, - draggedError - ) - - const draggedTextcardError = errors.textcards[source.index] - const newCardErrors = updatePositions( - errors.textcards, - source.index, - destination.index, - draggedTextcardError - ) - - const displayBool = displaySections[source.index] - const newDisplaySections = updatePositions( - displaySections, - source.index, - destination.index, - displayBool - ) - - return updateEditorSection( - homepageState, - newDisplaySections, - newSections, - newSectionErrors, - newCardErrors - ) - } - // inner dnd for hero - // passed in via droppableId - case "dropdownelem": { - // TODO: type check to avoid casting - const draggedElem = ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroDropdownSection).dropdown.options[source.index] - const newDropdownOptions = updatePositions( - ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroDropdownSection).dropdown.options, - source.index, - destination.index, - draggedElem - ) - - const draggedError = errors.dropdownElems[source.index] - const newDropdownErrors = updatePositions( - errors.dropdownElems, - source.index, - destination.index, - draggedError - ) - const displayBool = displayDropdownElems[source.index] - const newDisplayDropdownElems = updatePositions( - displayDropdownElems, - source.index, - destination.index, - displayBool - ) - - return { - ...homepageState, - displayDropdownElems: newDisplayDropdownElems, - frontMatter: { - ...frontMatter, - sections: _.set( - frontMatter.sections, - ["0", "hero", "dropdown", "options"], - newDropdownOptions - ), - }, - errors: { ...errors, dropdownElems: newDropdownErrors }, - } + if (!isUpdateHomepageType(type)) return homepageState + + if (type === "editor") { + const draggedElem = frontMatter.sections[source.index] + const newSections = updatePositions( + frontMatter.sections, + source.index, + destination.index, + draggedElem + ) + const draggedError = errors.sections[source.index] + const newSectionErrors = updatePositions( + errors.sections, + source.index, + destination.index, + draggedError + ) + + const draggedTextcardError = errors.textcards[source.index] + const newCardErrors = updatePositions( + errors.textcards, + source.index, + destination.index, + draggedTextcardError + ) + + const displayBool = displaySections[source.index] + const newDisplaySections = updatePositions( + displaySections, + source.index, + destination.index, + displayBool + ) + + return updateEditorSection( + homepageState, + newDisplaySections, + newSections, + newSectionErrors, + newCardErrors + ) + } + // inner dnd for hero + // passed in via droppableId + if (type === "dropdownelem") { + // TODO: type check to avoid casting + const draggedElem = ((frontMatter.sections[0] as HeroFrontmatterSection) + .hero as EditorHeroDropdownSection).dropdown.options[source.index] + const newDropdownOptions = updatePositions( + ((frontMatter.sections[0] as HeroFrontmatterSection) + .hero as EditorHeroDropdownSection).dropdown.options, + source.index, + destination.index, + draggedElem + ) + + const draggedError = errors.dropdownElems[source.index] + const newDropdownErrors = updatePositions( + errors.dropdownElems, + source.index, + destination.index, + draggedError + ) + const displayBool = displayDropdownElems[source.index] + const newDisplayDropdownElems = updatePositions( + displayDropdownElems, + source.index, + destination.index, + displayBool + ) + + return { + ...homepageState, + displayDropdownElems: newDisplayDropdownElems, + frontMatter: { + ...frontMatter, + sections: _.set( + frontMatter.sections, + ["0", "hero", "dropdown", "options"], + newDropdownOptions + ), + }, + errors: { ...errors, dropdownElems: newDropdownErrors }, } - case "highlight": { - // TODO: type check to avoid casting - const draggedElem = ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroHighlightsSection).key_highlights[source.index] - const newHighlightOptions = updatePositions( - ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroHighlightsSection).key_highlights, - source.index, - destination.index, - draggedElem - ) - - const draggedError = errors.highlights[source.index] - const newHighlightErrors = updatePositions( - errors.highlights, - source.index, - destination.index, - draggedError - ) - - const displayBool = displayHighlights[source.index] - const newDisplayHighlights = updatePositions( - displayHighlights, - source.index, - destination.index, - displayBool - ) - return updateHighlightsSection( - homepageState, - newDisplayHighlights, - newHighlightOptions, - newHighlightErrors + } + if (type === "highlight") { + // TODO: type check to avoid casting + const draggedElem = ((frontMatter.sections[0] as HeroFrontmatterSection) + .hero as EditorHeroHighlightsSection).key_highlights[source.index] + const newHighlightOptions = updatePositions( + ((frontMatter.sections[0] as HeroFrontmatterSection) + .hero as EditorHeroHighlightsSection).key_highlights, + source.index, + destination.index, + draggedElem + ) + + const draggedError = errors.highlights[source.index] + const newHighlightErrors = updatePositions( + errors.highlights, + source.index, + destination.index, + draggedError + ) + + const displayBool = displayHighlights[source.index] + const newDisplayHighlights = updatePositions( + displayHighlights, + source.index, + destination.index, + displayBool + ) + return updateHighlightsSection( + homepageState, + newDisplayHighlights, + newHighlightOptions, + newHighlightErrors + ) + } + if (type === "announcement") { + const doesAnnouncementKeyExist = !_.isEmpty( + frontMatter.sections.find((section) => + EditorHomepageFrontmatterSection.isAnnouncements(section) ) + ) + if (!doesAnnouncementKeyExist) { + // should not reach here, but defensively return the original state + return homepageState } - case "announcement": { - const doesAnnouncementKeyExist = !_.isEmpty( - frontMatter.sections.find((section) => - EditorHomepageFrontmatterSection.isAnnouncements(section) - ) - ) - if (!doesAnnouncementKeyExist) { - // should not reach here, but defensively return the original state - return homepageState - } - const announcementsIndex = frontMatter.sections.findIndex((section) => - EditorHomepageFrontmatterSection.isAnnouncements(section) - ) - const draggedElem = (frontMatter.sections[ + const announcementsIndex = frontMatter.sections.findIndex((section) => + EditorHomepageFrontmatterSection.isAnnouncements(section) + ) + const draggedElem = (frontMatter.sections[ + announcementsIndex + // safe to assert as check is done above + ] as AnnouncementsFrontmatterSection).announcements.announcement_items[ + source.index + ] + + const newAnnouncementsOptions = updatePositions( + (frontMatter.sections[ announcementsIndex // safe to assert as check is done above - ] as AnnouncementsFrontmatterSection).announcements.announcement_items[ - source.index - ] - - const newAnnouncementsOptions = updatePositions( - (frontMatter.sections[ - announcementsIndex - // safe to assert as check is done above - ] as AnnouncementsFrontmatterSection).announcements.announcement_items, - source.index, - destination.index, - draggedElem - ) - - const draggedError = errors.announcementItems[source.index] - const newAnnouncementErrors = updatePositions( - errors.announcementItems, - source.index, - destination.index, - draggedError - ) - const displayBool = displayAnnouncementItems[source.index] - const newDisplayAnnouncementItems = updatePositions( - displayAnnouncementItems, - source.index, - destination.index, - displayBool - ) - - return updateAnnouncementSection( - homepageState, - newDisplayAnnouncementItems, - newAnnouncementsOptions, - newAnnouncementErrors, - announcementsIndex - ) - } - case "textCardItem": { - const parentId = parseInt(typeArray[1], RADIX_PARSE_INT) - const textCardsItem = (frontMatter.sections[ - parentId - ] as TextcardFrontmatterSection).textcards as EditorTextcardSection - const draggedElem = textCardsItem.cards[source.index] - const newTextcards = updatePositions( - textCardsItem.cards, - source.index, - destination.index, - draggedElem - ) - - const draggedError = errors.textcards[parentId][source.index] - const newTextcardErrors = updatePositions( - errors.textcards[parentId], - source.index, - destination.index, - draggedError - ) - - return updateTextCardsCardSection( - homepageState, - parentId, - newTextcards, - newTextcardErrors - ) - } - default: - return homepageState + ] as AnnouncementsFrontmatterSection).announcements.announcement_items, + source.index, + destination.index, + draggedElem + ) + + const draggedError = errors.announcementItems[source.index] + const newAnnouncementErrors = updatePositions( + errors.announcementItems, + source.index, + destination.index, + draggedError + ) + const displayBool = displayAnnouncementItems[source.index] + const newDisplayAnnouncementItems = updatePositions( + displayAnnouncementItems, + source.index, + destination.index, + displayBool + ) + + return updateAnnouncementSection( + homepageState, + newDisplayAnnouncementItems, + newAnnouncementsOptions, + newAnnouncementErrors, + announcementsIndex + ) } + if (type.startsWith("textcardcard")) { + const parentId = parseInt(type.split("-")[1], RADIX_PARSE_INT) + const textCardsItem = (frontMatter.sections[ + parentId + ] as TextcardFrontmatterSection).textcards as EditorTextcardSection + const draggedElem = textCardsItem.cards[source.index] + const newTextcards = updatePositions( + textCardsItem.cards, + source.index, + destination.index, + draggedElem + ) + + const draggedError = errors.textcards[parentId][source.index] + const newTextcardErrors = updatePositions( + errors.textcards[parentId], + source.index, + destination.index, + draggedError + ) + + return updateTextCardsCardSection( + homepageState, + parentId, + newTextcards, + newTextcardErrors + ) + } + return homepageState } // NOTE: Handles only placement, @@ -424,8 +446,7 @@ export const onCreate = ( homepageState: EditorHomepageState, elemType: EditorHomepageElement, val: PossibleEditorSections, - err: E, - parentId = 0 + err: E ): EditorHomepageState => { const { errors, @@ -436,155 +457,152 @@ export const onCreate = ( displayAnnouncementItems, } = homepageState - switch (elemType) { - case "section": { - const sections = createElement(frontMatter.sections, val) - const newErrorSections = createElement(errors.sections, err) + if (elemType === "section") { + const sections = createElement(frontMatter.sections, val) + const newErrorSections = createElement(errors.sections, err) - const resetDisplaySections = _.fill(Array(displaySections.length), false) - const newDisplaySections = createElement(resetDisplaySections, true) + const resetDisplaySections = _.fill(Array(displaySections.length), false) + const newDisplaySections = createElement(resetDisplaySections, true) - const newTextcardErrors = createElement(errors.textcards, []) + const newTextcardErrors = createElement(errors.textcards, []) - return updateEditorSection( - homepageState, - newDisplaySections, - sections as EditorHomepageState["frontMatter"]["sections"], - newErrorSections, - newTextcardErrors + return updateEditorSection( + homepageState, + newDisplaySections, + sections as EditorHomepageState["frontMatter"]["sections"], + newErrorSections, + newTextcardErrors + ) + } + if (elemType === "dropdownelem") { + const newDropdownOptions = createElement( + ((frontMatter.sections[0] as HeroFrontmatterSection) + .hero as EditorHeroDropdownSection).dropdown.options, + val + ) + const newDropdownErrors = createElement(errors.dropdownElems, err) + const resetDisplayDropdownElems = _.fill( + Array(displayDropdownElems.length), + false + ) + const newDisplayDropdownElems = createElement( + resetDisplayDropdownElems, + true + ) + + return updateDropdownSection( + homepageState, + newDisplayDropdownElems, + newDropdownOptions, + newDropdownErrors + ) + } + if (elemType === "highlight") { + // If key highlights section exists + if ( + !_.isEmpty( + ((frontMatter.sections[0] as HeroFrontmatterSection) + .hero as EditorHeroHighlightsSection).key_highlights ) - } - case "dropdownelem": { - const newDropdownOptions = createElement( + ) { + const newHighlightOptions = createElement( ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroDropdownSection).dropdown.options, + .hero as EditorHeroHighlightsSection).key_highlights, val ) - const newDropdownErrors = createElement(errors.dropdownElems, err) - const resetDisplayDropdownElems = _.fill( - Array(displayDropdownElems.length), + + const newHighlightErrors = createElement(errors.highlights, err) + + const resetDisplayHighlights = _.fill( + Array(displayHighlights.length), false ) - const newDisplayDropdownElems = createElement( - resetDisplayDropdownElems, - true - ) + const newDisplayHighlights = createElement(resetDisplayHighlights, true) - return updateDropdownSection( + return updateHighlightsSection( homepageState, - newDisplayDropdownElems, - newDropdownOptions, - newDropdownErrors + newDisplayHighlights, + newHighlightOptions, + newHighlightErrors ) } - case "highlight": { - // If key highlights section exists - if ( - !_.isEmpty( - ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroHighlightsSection).key_highlights - ) - ) { - const newHighlightOptions = createElement( - ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroHighlightsSection).key_highlights, - val - ) - - const newHighlightErrors = createElement(errors.highlights, err) - - const resetDisplayHighlights = _.fill( - Array(displayHighlights.length), - false - ) - const newDisplayHighlights = createElement(resetDisplayHighlights, true) - - return updateHighlightsSection( - homepageState, - newDisplayHighlights, - newHighlightOptions, - newHighlightErrors - ) - } - - return updateHighlightsSection(homepageState, [true], [val], [err]) - } - case "announcement": { - const announcementKeyExist = !_.isEmpty( - frontMatter.sections.find((section) => - EditorHomepageFrontmatterSection.isAnnouncements(section) - ) - ) - if (!announcementKeyExist) { - // should not reach here, but defensively return the original state - return homepageState - } - const announcementsIndex = frontMatter.sections.findIndex((section) => + return updateHighlightsSection(homepageState, [true], [val], [err]) + } + if (elemType === "announcement") { + const announcementKeyExist = !_.isEmpty( + frontMatter.sections.find((section) => EditorHomepageFrontmatterSection.isAnnouncements(section) ) - const announcementBlockSection: AnnouncementsFrontmatterSection = frontMatter - .sections[announcementsIndex] as AnnouncementsFrontmatterSection - - const announcements = createElementFromTop( - announcementBlockSection.announcements.announcement_items, - val as AnnouncementOption - ) - - const resetDisplaySections = _.fill( - Array(displayAnnouncementItems.length), - false - ) - const newDisplayAnnouncementItems = createElementFromTop( - resetDisplaySections, - true - ) - - const newAnnouncementErrors = createElementFromTop( - errors.announcementItems, - err - ) + ) + if (!announcementKeyExist) { + // should not reach here, but defensively return the original state + return homepageState + } - return updateAnnouncementSection( + const announcementsIndex = frontMatter.sections.findIndex((section) => + EditorHomepageFrontmatterSection.isAnnouncements(section) + ) + const announcementBlockSection: AnnouncementsFrontmatterSection = frontMatter + .sections[announcementsIndex] as AnnouncementsFrontmatterSection + + const announcements = createElementFromTop( + announcementBlockSection.announcements.announcement_items, + val as AnnouncementOption + ) + + const resetDisplaySections = _.fill( + Array(displayAnnouncementItems.length), + false + ) + const newDisplayAnnouncementItems = createElementFromTop( + resetDisplaySections, + true + ) + + const newAnnouncementErrors = createElementFromTop( + errors.announcementItems, + err + ) + + return updateAnnouncementSection( + homepageState, + newDisplayAnnouncementItems, + announcements, + newAnnouncementErrors, + announcementsIndex + ) + } + if (elemType.startsWith("textcardcard")) { + const parentId = parseInt(elemType.split("-")[1], RADIX_PARSE_INT) + const sectionInfo = (frontMatter.sections[ + parentId + ] as TextcardFrontmatterSection).textcards as EditorTextcardCardsSection + if (!_.isEmpty(sectionInfo.cards)) { + const newTextCards = createElement(sectionInfo.cards, val) + const newTextcardErrors = createElement(errors.textcards[parentId], err) + return updateTextCardsCardSection( homepageState, - newDisplayAnnouncementItems, - announcements, - newAnnouncementErrors, - announcementsIndex + parentId, + newTextCards, + newTextcardErrors ) } - case "textCardItem": { - if ( - !_.isEmpty( - ((frontMatter.sections[parentId] as TextcardFrontmatterSection) - .textcards as EditorTextcardCardsSection).cards - ) - ) { - const newTextCards = createElement( - ((frontMatter.sections[parentId] as TextcardFrontmatterSection) - .textcards as EditorTextcardCardsSection).cards, - val - ) - const newTextcardErrors = createElement(errors.textcards[parentId], err) - return updateTextCardsCardSection( - homepageState, - parentId, - newTextCards, - newTextcardErrors - ) - } - return updateTextCardsCardSection(homepageState, parentId, [val], [err]) - } - default: - return homepageState + const newState = updateTextCardsCardSection( + homepageState, + parentId, + [val], + [err] + ) + return newState } + return homepageState } export const onDelete = ( homepageState: EditorHomepageState, elemType: EditorHomepageElement, - indexToDelete: number, - subindexToDelete = 0 + indexToDelete: number ): EditorHomepageState => { const { errors, @@ -595,121 +613,113 @@ export const onDelete = ( displayAnnouncementItems, } = homepageState - switch (elemType) { - case "section": { - const sections = deleteElement(frontMatter.sections, indexToDelete) - const newErrorSections = deleteElement(errors.sections, indexToDelete) - const newDisplaySections = deleteElement(displaySections, indexToDelete) - const newTextcardErrors = deleteElement(errors.textcards, indexToDelete) - - return updateEditorSection( - homepageState, - newDisplaySections, - sections, - newErrorSections, - newTextcardErrors - ) - } - - case "dropdownelem": { - const newDropdownOptions = deleteElement( - ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroDropdownSection).dropdown.options, - indexToDelete - ) - const newDropdownErrors = deleteElement( - errors.dropdownElems, - indexToDelete - ) - const newDisplayDropdownElems = deleteElement( - displayDropdownElems, - indexToDelete - ) - - return updateDropdownSection( - homepageState, - newDisplayDropdownElems, - newDropdownOptions, - newDropdownErrors - ) - } - case "highlight": { - const newHighlightOptions = deleteElement( - ((frontMatter.sections[0] as HeroFrontmatterSection) - .hero as EditorHeroHighlightsSection).key_highlights, - indexToDelete - ) - const newHighlightErrors = deleteElement(errors.highlights, indexToDelete) - - const newDisplayHighlights = deleteElement( - displayHighlights, - indexToDelete - ) - - return updateHighlightsSection( - homepageState, - newDisplayHighlights, - newHighlightOptions, - newHighlightErrors - ) - } - case "announcement": { - const announcementKeyExist = !_.isEmpty( - frontMatter.sections.find((section) => - EditorHomepageFrontmatterSection.isAnnouncements(section) - ) - ) - if (!announcementKeyExist) { - // should not reach here, but defensively return the original state - return homepageState - } + if (elemType === "section") { + const sections = deleteElement(frontMatter.sections, indexToDelete) + const newErrorSections = deleteElement(errors.sections, indexToDelete) + const newDisplaySections = deleteElement(displaySections, indexToDelete) + const newTextcardErrors = deleteElement(errors.textcards, indexToDelete) + + return updateEditorSection( + homepageState, + newDisplaySections, + sections, + newErrorSections, + newTextcardErrors + ) + } - const announcementsIndex = frontMatter.sections.findIndex((section) => + if (elemType === "dropdownelem") { + const newDropdownOptions = deleteElement( + ((frontMatter.sections[0] as HeroFrontmatterSection) + .hero as EditorHeroDropdownSection).dropdown.options, + indexToDelete + ) + const newDropdownErrors = deleteElement(errors.dropdownElems, indexToDelete) + const newDisplayDropdownElems = deleteElement( + displayDropdownElems, + indexToDelete + ) + + return updateDropdownSection( + homepageState, + newDisplayDropdownElems, + newDropdownOptions, + newDropdownErrors + ) + } + if (elemType === "highlight") { + const newHighlightOptions = deleteElement( + ((frontMatter.sections[0] as HeroFrontmatterSection) + .hero as EditorHeroHighlightsSection).key_highlights, + indexToDelete + ) + const newHighlightErrors = deleteElement(errors.highlights, indexToDelete) + + const newDisplayHighlights = deleteElement(displayHighlights, indexToDelete) + + return updateHighlightsSection( + homepageState, + newDisplayHighlights, + newHighlightOptions, + newHighlightErrors + ) + } + if (elemType === "announcement") { + const announcementKeyExist = !_.isEmpty( + frontMatter.sections.find((section) => EditorHomepageFrontmatterSection.isAnnouncements(section) ) - const announcementsSection: AnnouncementsFrontmatterSection = frontMatter - .sections[announcementsIndex] as AnnouncementsFrontmatterSection - - const newAnnouncementOptions = deleteElement( - announcementsSection.announcements.announcement_items, - indexToDelete - ) - const newAnnouncementErrors = deleteElement( - errors.announcementItems, - indexToDelete - ) - - const newDisplayAnnouncements = deleteElement( - displayAnnouncementItems, - indexToDelete - ) - - return updateAnnouncementSection( - homepageState, - newDisplayAnnouncements, - newAnnouncementOptions, - newAnnouncementErrors, - announcementsIndex - ) - } - case "textCardItem": { - const newTextCards = deleteElement( - ((frontMatter.sections[indexToDelete] as TextcardFrontmatterSection) - .textcards as EditorTextcardCardsSection).cards, - subindexToDelete - ) - const newTextcardErrors = deleteElement( - errors.textcards[indexToDelete], - subindexToDelete - ) - return updateTextCardsCardSection( - homepageState, - indexToDelete, - newTextCards, - newTextcardErrors - ) - } - default: + ) + if (!announcementKeyExist) { + // should not reach here, but defensively return the original state return homepageState + } + + const announcementsIndex = frontMatter.sections.findIndex((section) => + EditorHomepageFrontmatterSection.isAnnouncements(section) + ) + const announcementsSection: AnnouncementsFrontmatterSection = frontMatter + .sections[announcementsIndex] as AnnouncementsFrontmatterSection + + const newAnnouncementOptions = deleteElement( + announcementsSection.announcements.announcement_items, + indexToDelete + ) + const newAnnouncementErrors = deleteElement( + errors.announcementItems, + indexToDelete + ) + + const newDisplayAnnouncements = deleteElement( + displayAnnouncementItems, + indexToDelete + ) + + return updateAnnouncementSection( + homepageState, + newDisplayAnnouncements, + newAnnouncementOptions, + newAnnouncementErrors, + announcementsIndex + ) + } + if (elemType.startsWith("textcardcard")) { + const parentId = parseInt(elemType.split("-")[1], RADIX_PARSE_INT) + const newTextCards = deleteElement( + ((frontMatter.sections[parentId] as TextcardFrontmatterSection) + .textcards as EditorTextcardCardsSection).cards, + indexToDelete + ) + const newTextcardErrors = deleteElement( + errors.textcards[parentId], + indexToDelete + ) + return updateTextCardsCardSection( + homepageState, + parentId, + newTextCards, + newTextcardErrors + ) } + return homepageState } diff --git a/src/layouts/EditHomepage/EditHomepage.jsx b/src/layouts/EditHomepage/EditHomepage.jsx index 46a8823ea..5a6802d4c 100644 --- a/src/layouts/EditHomepage/EditHomepage.jsx +++ b/src/layouts/EditHomepage/EditHomepage.jsx @@ -805,10 +805,9 @@ const EditHomepage = ({ match }) => { const err = getErrorValues(TEXTCARDS_ITEM_SECTION) const updatedHomepageState = onCreate( homepageState, - elemType, + `${elemType}-${parentId}`, val, - err, - parentId + err ) setHomepageState(updatedHomepageState) @@ -839,8 +838,7 @@ const EditHomepage = ({ match }) => { const newHomepageState = onDelete( homepageState, - elemType, - index, + `${elemType}-${index}`, childIndex ) setHomepageState(newHomepageState) diff --git a/src/types/homepage.ts b/src/types/homepage.ts index 4d5dac27d..8b0511ca4 100644 --- a/src/types/homepage.ts +++ b/src/types/homepage.ts @@ -120,7 +120,7 @@ export type EditorHomepageElement = | "dropdownelem" | "highlight" | "announcement" - | `textCardItem` + | `textcardcard-${number}` export type PossibleEditorSections = IterableElement< | EditorHomepageState["frontMatter"]["sections"] | EditorHeroDropdownSection["dropdown"]["options"] From 4bd06e9b70fc3943ff05f18d6fde7c78c035ef39 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 27 Sep 2023 17:05:13 +0800 Subject: [PATCH 2/6] fix: rebase errors --- src/hooks/useDrag.tsx | 16 ++++++++-------- src/layouts/EditHomepage/EditHomepage.jsx | 4 ++-- src/types/homepage.ts | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hooks/useDrag.tsx b/src/hooks/useDrag.tsx index 66728d7e7..f1abc92e0 100644 --- a/src/hooks/useDrag.tsx +++ b/src/hooks/useDrag.tsx @@ -9,7 +9,7 @@ import { EditorHeroHighlightsSection, EditorHomepageElement, EditorHomepageState, - EditorTextcardCardsSection, + EditortextCardItemsSection, EditorTextcardSection, HeroFrontmatterSection, PossibleEditorSections, @@ -189,10 +189,10 @@ type UpdateHomepageType = | "dropdownelem" | "highlight" | "announcement" - | `textcardcard-${number}` + | `textCardItem-${number}` const isUpdateHomepageType = (value: any): value is UpdateHomepageType => { - if (typeof value === "string" && value.startsWith("textcardcard-")) { + if (typeof value === "string" && value.startsWith("textCardItem-")) { const valArr = value.split("-") const number = valArr[1] return valArr.length === 2 && !Number.isNaN(Number(number)) @@ -409,7 +409,7 @@ const updateHomepageState = ( announcementsIndex ) } - if (type.startsWith("textcardcard")) { + if (type.startsWith("textCardItem")) { const parentId = parseInt(type.split("-")[1], RADIX_PARSE_INT) const textCardsItem = (frontMatter.sections[ parentId @@ -573,11 +573,11 @@ export const onCreate = ( announcementsIndex ) } - if (elemType.startsWith("textcardcard")) { + if (elemType.startsWith("textCardItem")) { const parentId = parseInt(elemType.split("-")[1], RADIX_PARSE_INT) const sectionInfo = (frontMatter.sections[ parentId - ] as TextcardFrontmatterSection).textcards as EditorTextcardCardsSection + ] as TextcardFrontmatterSection).textcards as EditortextCardItemsSection if (!_.isEmpty(sectionInfo.cards)) { const newTextCards = createElement(sectionInfo.cards, val) const newTextcardErrors = createElement(errors.textcards[parentId], err) @@ -703,11 +703,11 @@ export const onDelete = ( announcementsIndex ) } - if (elemType.startsWith("textcardcard")) { + if (elemType.startsWith("textCardItem")) { const parentId = parseInt(elemType.split("-")[1], RADIX_PARSE_INT) const newTextCards = deleteElement( ((frontMatter.sections[parentId] as TextcardFrontmatterSection) - .textcards as EditorTextcardCardsSection).cards, + .textcards as EditortextCardItemsSection).cards, indexToDelete ) const newTextcardErrors = deleteElement( diff --git a/src/layouts/EditHomepage/EditHomepage.jsx b/src/layouts/EditHomepage/EditHomepage.jsx index 5a6802d4c..6fbb6640d 100644 --- a/src/layouts/EditHomepage/EditHomepage.jsx +++ b/src/layouts/EditHomepage/EditHomepage.jsx @@ -114,7 +114,7 @@ const getHasErrors = (errors) => { const hasHighlightErrors = getHasError(errors.highlights) const hasDropdownElemErrors = getHasError(errors.dropdownElems) const hasAnnouncementErrors = getHasError(errors.announcementItems) - const hasTextcardCardErrors = _.some(errors.textcards, (section) => + const hastextCardItemErrors = _.some(errors.textcards, (section) => getHasError(section) ) @@ -123,7 +123,7 @@ const getHasErrors = (errors) => { hasHighlightErrors || hasDropdownElemErrors || hasAnnouncementErrors || - hasTextcardCardErrors + hastextCardItemErrors ) } diff --git a/src/types/homepage.ts b/src/types/homepage.ts index 8b0511ca4..00db698b3 100644 --- a/src/types/homepage.ts +++ b/src/types/homepage.ts @@ -120,7 +120,7 @@ export type EditorHomepageElement = | "dropdownelem" | "highlight" | "announcement" - | `textcardcard-${number}` + | `textCardItem-${number}` export type PossibleEditorSections = IterableElement< | EditorHomepageState["frontMatter"]["sections"] | EditorHeroDropdownSection["dropdown"]["options"] @@ -151,11 +151,11 @@ export type AnnouncementsFrontmatterSection = { announcements: AnnouncementsBlockSection } -export interface EditorTextcardCardsSection { +export interface EditortextCardItemsSection { cards: [] } -export interface EditorTextcardSection extends EditorTextcardCardsSection { +export interface EditorTextcardSection extends EditortextCardItemsSection { title: string subtitle: string description: string From 4cf4b018a4197a4a9fce80138f35577911cd81d0 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 27 Sep 2023 17:32:33 +0800 Subject: [PATCH 3/6] fix: check for empty string --- src/hooks/useDrag.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hooks/useDrag.tsx b/src/hooks/useDrag.tsx index f1abc92e0..8c4256cca 100644 --- a/src/hooks/useDrag.tsx +++ b/src/hooks/useDrag.tsx @@ -195,7 +195,11 @@ const isUpdateHomepageType = (value: any): value is UpdateHomepageType => { if (typeof value === "string" && value.startsWith("textCardItem-")) { const valArr = value.split("-") const number = valArr[1] - return valArr.length === 2 && !Number.isNaN(Number(number)) + return ( + valArr.length === 2 && + !!possibleCardIndex && + !Number.isNaN(Number(possibleCardIndex)) + ) } if (typeof value === "string") { return ( From e1e69692b2e410b3ef8953faf7a8b2631a30abda Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 27 Sep 2023 17:32:50 +0800 Subject: [PATCH 4/6] fix: rename var --- src/hooks/useDrag.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useDrag.tsx b/src/hooks/useDrag.tsx index 8c4256cca..d2ea0dc6b 100644 --- a/src/hooks/useDrag.tsx +++ b/src/hooks/useDrag.tsx @@ -194,7 +194,7 @@ type UpdateHomepageType = const isUpdateHomepageType = (value: any): value is UpdateHomepageType => { if (typeof value === "string" && value.startsWith("textCardItem-")) { const valArr = value.split("-") - const number = valArr[1] + const possibleCardIndex = valArr[1] return ( valArr.length === 2 && !!possibleCardIndex && From 96d0dddc2f7d06b599739083fad3887ffef41b9c Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 27 Sep 2023 17:33:14 +0800 Subject: [PATCH 5/6] fix: add type guards to create and delete and add comments --- src/hooks/useDrag.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/hooks/useDrag.tsx b/src/hooks/useDrag.tsx index d2ea0dc6b..e1ebd010b 100644 --- a/src/hooks/useDrag.tsx +++ b/src/hooks/useDrag.tsx @@ -191,7 +191,9 @@ type UpdateHomepageType = | "announcement" | `textCardItem-${number}` -const isUpdateHomepageType = (value: any): value is UpdateHomepageType => { +const isUpdateHomepageType = ( + value: any +): value is UpdateHomepageType | EditorHomepageElement => { if (typeof value === "string" && value.startsWith("textCardItem-")) { const valArr = value.split("-") const possibleCardIndex = valArr[1] @@ -206,7 +208,8 @@ const isUpdateHomepageType = (value: any): value is UpdateHomepageType => { value === "editor" || value === "dropdownelem" || value === "highlight" || - value === "announcement" + value === "announcement" || + value === "section" ) } @@ -414,6 +417,7 @@ const updateHomepageState = ( ) } if (type.startsWith("textCardItem")) { + // We've validated that type can only be such that the second item is a number const parentId = parseInt(type.split("-")[1], RADIX_PARSE_INT) const textCardsItem = (frontMatter.sections[ parentId @@ -461,6 +465,8 @@ export const onCreate = ( displayAnnouncementItems, } = homepageState + if (!isUpdateHomepageType(elemType)) return homepageState + if (elemType === "section") { const sections = createElement(frontMatter.sections, val) const newErrorSections = createElement(errors.sections, err) @@ -578,6 +584,7 @@ export const onCreate = ( ) } if (elemType.startsWith("textCardItem")) { + // We've validated that type can only be such that the second item is a number const parentId = parseInt(elemType.split("-")[1], RADIX_PARSE_INT) const sectionInfo = (frontMatter.sections[ parentId @@ -617,6 +624,7 @@ export const onDelete = ( displayAnnouncementItems, } = homepageState + if (!isUpdateHomepageType(elemType)) return homepageState if (elemType === "section") { const sections = deleteElement(frontMatter.sections, indexToDelete) const newErrorSections = deleteElement(errors.sections, indexToDelete) @@ -708,6 +716,7 @@ export const onDelete = ( ) } if (elemType.startsWith("textCardItem")) { + // We've validated that type can only be such that the second item is a number const parentId = parseInt(elemType.split("-")[1], RADIX_PARSE_INT) const newTextCards = deleteElement( ((frontMatter.sections[parentId] as TextcardFrontmatterSection) From 8e0b01728961af0602a429a857a7f8648f961103 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 27 Sep 2023 17:49:15 +0800 Subject: [PATCH 6/6] chore: change to unknown --- src/hooks/useDrag.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useDrag.tsx b/src/hooks/useDrag.tsx index e1ebd010b..6ba4953cb 100644 --- a/src/hooks/useDrag.tsx +++ b/src/hooks/useDrag.tsx @@ -192,7 +192,7 @@ type UpdateHomepageType = | `textCardItem-${number}` const isUpdateHomepageType = ( - value: any + value: unknown ): value is UpdateHomepageType | EditorHomepageElement => { if (typeof value === "string" && value.startsWith("textCardItem-")) { const valArr = value.split("-")