diff --git a/src/layouts/EditHomepage/EditHomepage.jsx b/src/layouts/EditHomepage/EditHomepage.jsx
index 2462c2070a..fd81a712c1 100644
--- a/src/layouts/EditHomepage/EditHomepage.jsx
+++ b/src/layouts/EditHomepage/EditHomepage.jsx
@@ -31,6 +31,7 @@ import {
validateSections,
validateHighlights,
validateDropdownElems,
+ validateAnnouncements,
} from "utils/validators"
import { HomepageStartEditingImage } from "assets"
@@ -40,6 +41,8 @@ import { EditableContextProvider } from "../../contexts/EditableContext"
import { useDrag, onCreate, onDelete } from "../../hooks/useDrag"
import { CustomiseSectionsHeader, Editable } from "../components/Editable"
import { AddSectionButton } from "../components/Editable/AddSectionButton"
+import { AnnouncementBody } from "../components/Homepage/AnnouncementBody"
+import { AnnouncementSection } from "../components/Homepage/AnnouncementSection"
import { HeroBody } from "../components/Homepage/HeroBody"
import { HeroDropdownSection } from "../components/Homepage/HeroDropdownSection"
import { HeroHighlightSection } from "../components/Homepage/HeroHighlightSection"
@@ -54,6 +57,8 @@ import {
INFOPIC_SECTION,
KEY_HIGHLIGHT_SECTION,
RESOURCES_SECTION,
+ ANNOUNCEMENT_BLOCK,
+ ANNOUNCEMENT_SECTION,
} from "./constants"
import { HomepagePreview } from "./HomepagePreview"
import { getErrorValues } from "./utils"
@@ -119,6 +124,11 @@ const enumSection = (type, isError) => {
? { infopic: getErrorValues(INFOPIC_SECTION) }
: { infopic: INFOPIC_SECTION }
+ case "announcementBlock":
+ return isError
+ ? { announcementBlock: getErrorValues(ANNOUNCEMENT_BLOCK) }
+ : { announcementBlock: ANNOUNCEMENT_BLOCK }
+
default:
return isError
? { infobar: getErrorValues(INFOBAR_SECTION) }
@@ -139,6 +149,7 @@ const EditHomepage = ({ match }) => {
image: "",
notification: "",
sections: [],
+ announcementBlock: {},
})
const [originalFrontMatter, setOriginalFrontMatter] = useState({
title: "",
@@ -150,12 +161,14 @@ const EditHomepage = ({ match }) => {
})
const [sha, setSha] = useState(null)
const [displaySections, setDisplaySections] = useState([])
+ const [displayAnnouncements, setDisplayAnnouncements] = useState([])
const [displayHighlights, setDisplayHighlights] = useState([])
const [displayDropdownElems, setDisplayDropdownElems] = useState([])
const [errors, setErrors] = useState({
sections: [],
highlights: [],
dropdownElems: [],
+ announcements: [],
})
const [itemPendingForDelete, setItemPendingForDelete] = useState({
id: "",
@@ -172,6 +185,7 @@ const EditHomepage = ({ match }) => {
displayDropdownElems,
displayHighlights,
displaySections,
+ displayAnnouncements,
}
const onDrag = useDrag(homepageState)
const setHomepageState = ({
@@ -216,6 +230,7 @@ const EditHomepage = ({ match }) => {
const sectionsErrors = []
let dropdownElemsErrors = []
let highlightsErrors = []
+ const announcementErrors = []
const scrollRefs = []
frontMatter.sections.forEach((section) => {
scrollRefs.push(createRef())
@@ -267,6 +282,12 @@ const EditHomepage = ({ match }) => {
sectionsErrors.push({ infopic: getErrorValues(INFOPIC_SECTION) })
}
+ if (section.announcementBlock) {
+ sectionsErrors.push({
+ announcementBlock: getErrorValues(ANNOUNCEMENT_BLOCK),
+ })
+ }
+
// Minimize all sections by default
displaySections.push(false)
})
@@ -276,6 +297,7 @@ const EditHomepage = ({ match }) => {
sections: sectionsErrors,
highlights: highlightsErrors,
dropdownElems: dropdownElemsErrors,
+ announcements: announcementErrors,
}
setFrontMatter(frontMatter)
@@ -332,7 +354,7 @@ const EditHomepage = ({ match }) => {
// sectionIndex is the index of the section array in the frontMatter
const sectionIndex = parseInt(idArray[1], RADIX_PARSE_INT)
- const sectionType = idArray[2] // e.g. "hero" or "infobar" or "resources"
+ const sectionType = idArray[2] // e.g. "hero" or "infobar" or "resources" or "announcement"
const field = idArray[3] // e.g. "title" or "subtitle"
const newSections = update(sections, {
@@ -441,6 +463,60 @@ const EditHomepage = ({ match }) => {
scrollTo(scrollRefs[0])
break
}
+ case "announcement": {
+ // The field that changed belongs to a hero highlight
+ const { sections } = frontMatter
+
+ const announcementBlockIndex = sections.findIndex(
+ (value) => Object.keys(value)[0] === "announcementBlock"
+ )
+ // announcementIndex is the index of the announcements array
+ const announcementIndex = parseInt(idArray[1], RADIX_PARSE_INT)
+ const field = idArray[2] // e.g. "title" or "url"
+
+ const newSections = update(sections, {
+ [announcementBlockIndex]: {
+ announcementBlock: {
+ announcements: {
+ [announcementIndex]: {
+ [field]: {
+ $set: value,
+ },
+ },
+ },
+ },
+ },
+ })
+
+ const newErrors = update(errors, {
+ announcements: {
+ [announcementIndex]: {
+ $set: validateAnnouncements(
+ errors.announcements[announcementIndex],
+ field,
+ value
+ ),
+ },
+ },
+ })
+
+ // Additional validation that depends on other fields
+ const isLinkTextFilled = !!frontMatter.sections[
+ announcementBlockIndex
+ ].announcementBlock.announcements[announcementIndex].linkText
+ if (field === "linkUrl" && !value && isLinkTextFilled) {
+ newErrors.announcements[announcementIndex].linkText =
+ "Please specify a URL for your link"
+ }
+
+ setFrontMatter({
+ ...frontMatter,
+ sections: newSections,
+ })
+ setErrors(newErrors)
+ scrollTo(scrollRefs[0])
+ break
+ }
case "dropdownelem": {
// The field that changed is a dropdown element (i.e. dropdownelem)
const { sections } = frontMatter
@@ -582,6 +658,20 @@ const EditHomepage = ({ match }) => {
setDisplayHighlights(displayHighlights)
break
}
+ case "announcement": {
+ const val = ANNOUNCEMENT_SECTION
+ const err = getErrorValues(ANNOUNCEMENT_SECTION)
+ const updatedHomepageState = onCreate(
+ homepageState,
+ elemType,
+ val,
+ err
+ )
+ const newScrollRefs = update(scrollRefs, { $push: [createRef()] })
+ setHomepageState(updatedHomepageState)
+ setScrollRefs(newScrollRefs)
+ break
+ }
default:
}
} catch (err) {
@@ -787,8 +877,21 @@ const EditHomepage = ({ match }) => {
})
setDisplaySections(newDisplaySections)
+ scrollTo(scrollRefs[index])
+ break
+ }
+ case "announcement": {
+ const resetAnnouncementSections = _.fill(
+ Array(displayAnnouncements.length),
+ false
+ )
+ resetAnnouncementSections[index] = !displayAnnouncements[index]
+ const newDisplayAnnouncements = update(displayAnnouncements, {
+ $set: resetAnnouncementSections,
+ })
scrollTo(scrollRefs[index])
+ setDisplayAnnouncements(newDisplayAnnouncements)
break
}
case "highlight": {
@@ -861,7 +964,7 @@ const EditHomepage = ({ match }) => {
}
}
- // NOTE: sectionType is one of `resources`, `infopic` or `infobar`
+ // NOTE: sectionType is one of `announcementBlock, `resources`, `infopic` or `infobar`
const onClick = (sectionType) => {
createHandler({
target: {
@@ -1076,6 +1179,51 @@ const EditHomepage = ({ match }) => {
/>
)}
+
+ {section.announcementBlock && (
+ Announcement
+ }
+ title={
+ section.announcementBlock.title ||
+ "New Announcement"
+ }
+ isInvalid={_.some(
+ errors.sections[sectionIndex]
+ .announcementBlock
+ )}
+ >
+
+
+
+
+ )}
>
)
)}
@@ -1103,6 +1251,19 @@ const EditHomepage = ({ match }) => {
subtitle={INFOBAR_SECTION.subtitle}
onClick={() => onClick(INFOBAR_SECTION.id)}
/>
+ {/* NOTE: Check if the sections contain any `announcement`
+ and if it does, prevent creation of another `resources` section
+ */}
+ {!frontMatter.sections.some(
+ ({ announcementBlock }) => !!announcementBlock
+ ) && (
+ onClick(ANNOUNCEMENT_BLOCK.id)}
+ />
+ )}
+
{/* NOTE: Check if the sections contain any `resources`
and if it does, prevent creation of another `resources` section
*/}