Skip to content

Commit

Permalink
Merge pull request #27055 from guardian/ab/enhance-timeline
Browse files Browse the repository at this point in the history
Enhance timeline elements with ids
  • Loading branch information
abeddow91 authored Apr 22, 2024
2 parents 4084c88 + 23e2a6f commit b17a7ef
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 20 deletions.
61 changes: 41 additions & 20 deletions common/app/model/dotcomrendering/ElementsEnhancer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,55 @@ package model.dotcomrendering

import play.api.libs.json.{Json, _}

object ElementsEnhancer {
/**
* The `ElementsEnhancer` object provides functions to enhance JSON representations of elements used in Dotcom Rendering.
* It adds unique identifiers to elements, as expected by the DCR schemas. More information on the decision for this can be found in PageElement-Identifiers.md or by searching for "03feb394-a17d-4430-8384-edd1891e0d01"
*
*/

// Note:
// In the file PageElement-Identifiers.md you will find a discussion of identifiers used by PageElements
// Also look for "03feb394-a17d-4430-8384-edd1891e0d01"
object ElementsEnhancer {

def enhanceElement(element: JsValue): JsValue = {
// Add an elementId to the element
val elementWithId = element.as[JsObject] ++ Json.obj("elementId" -> java.util.UUID.randomUUID.toString)
// Extract element type
val elementType = elementWithId.value("_type").as[String]
val elementIsList = elementType == "model.dotcomrendering.pageElements.ListBlockElement"

if (elementIsList) {
val listItems = elementWithId.value("items").as[JsArray]
val listItemsWithIds = listItems.value.map { item =>
val obj = item.as[JsObject]
obj ++ Json.obj("elements" -> enhanceElements(obj.value("elements")))
// If element has further nesting, continue to enhance. otherwise, return the enhanced element
elementType match {
case "model.dotcomrendering.pageElements.ListBlockElement" => enhanceListBlockElement(elementWithId)
case "model.dotcomrendering.pageElements.TimelineBlockElement" => enhanceTimelineBlockElement(elementWithId)
case _ => elementWithId;
}

}
def enhanceListBlockElement(elementWithId: JsObject): JsObject = {
val listItems = elementWithId.value("items").as[JsArray]
val listItemsWithIds = listItems.value.map { item =>
val obj = item.as[JsObject]
obj ++ Json.obj("elements" -> enhanceElements(obj.value("elements")))
}
elementWithId ++ Json.obj("items" -> listItemsWithIds)
}

def enhanceTimelineBlockElement(element: JsObject): JsObject = {
val sectionsList = element.value("sections").as[List[JsObject]]
val sectionsListWithIds = sectionsList.map { section =>
val eventsList = section.value("events").as[List[JsObject]]
val eventsListWithIds = eventsList.map { event =>
val bodyElementsWithIds = enhanceElements(event.value("body").as[JsArray])
event.as[JsObject] ++ Json.obj("body" -> bodyElementsWithIds)
}
elementWithId ++ Json.obj("items" -> listItemsWithIds)
} else {
elementWithId
section.as[JsObject] ++ Json.obj("events" -> eventsListWithIds)
}
element ++ Json.obj("sections" -> sectionsListWithIds)
}

def enhanceElements(elements: JsValue): IndexedSeq[JsValue] = {
elements.as[JsArray].value.map(element => enhanceElement(element))
}.toIndexedSeq

def enhanceObjectWithElementsAtDepth1(obj: JsValue): JsValue = {
def enhanceObjectWithElements(obj: JsValue): JsValue = {
obj.asOpt[JsObject] match {
case Some(o) =>
val elements = o.value("elements")
Expand All @@ -38,21 +59,21 @@ object ElementsEnhancer {
}
}

def enhanceObjectsWithElementsAtDepth1(objs: JsValue): IndexedSeq[JsValue] = {
objs.as[JsArray].value.map(obj => enhanceObjectWithElementsAtDepth1(obj))
def enhanceObjectsWithElements(objs: JsValue): IndexedSeq[JsValue] = {
objs.as[JsArray].value.map(obj => enhanceObjectWithElements(obj))
}.toIndexedSeq

def enhanceBlocks(obj: JsObject): JsObject = {
obj ++
Json.obj("blocks" -> enhanceObjectsWithElementsAtDepth1(obj.value("blocks")))
Json.obj("blocks" -> enhanceObjectsWithElements(obj.value("blocks")))
}

def enhanceDcrObject(obj: JsObject): JsObject = {
obj ++
Json.obj("blocks" -> enhanceObjectsWithElementsAtDepth1(obj.value("blocks"))) ++
Json.obj("blocks" -> enhanceObjectsWithElements(obj.value("blocks"))) ++
Json.obj("mainMediaElements" -> enhanceElements(obj.value("mainMediaElements"))) ++
Json.obj("keyEvents" -> enhanceObjectsWithElementsAtDepth1(obj.value("keyEvents"))) ++
Json.obj("pinnedPost" -> enhanceObjectWithElementsAtDepth1(obj.value("pinnedPost"))) ++
Json.obj("keyEvents" -> enhanceObjectsWithElements(obj.value("keyEvents"))) ++
Json.obj("pinnedPost" -> enhanceObjectWithElements(obj.value("pinnedPost"))) ++
Json.obj("promotedNewsletter" -> obj.value("promotedNewsletter"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,8 @@ object PageElement {
case _: WitnessBlockElement => true
case _: VineBlockElement => true
case _: ListBlockElement => true
case _: TimelineBlockElement => true

// TODO we should quick fail here for these rather than pointlessly go to DCR
case table: TableBlockElement if table.isMandatory.exists(identity) => true

Expand Down

0 comments on commit b17a7ef

Please sign in to comment.