common/app/layout/Front.scala (130 lines of code) (raw):
package layout
import common.{Edition, LinkTo}
import model.PressedPage
import model.facia.PressedCollection
import model.meta.{ItemList, ListItem}
import model.pressed.PressedContent
import play.api.mvc.RequestHeader
import slices._
import scala.annotation.tailrec
case class Front(
containers: Seq[FaciaContainer],
)
object Front {
type TrailUrl = String
def itemsVisible(containerDefinition: ContainerDefinition): Int =
itemsVisible(containerDefinition.slices)
def itemsVisible(slices: Seq[Slice]): Int =
slices.flatMap(_.layout.columns.map(_.numItems)).sum
// Never de-duplicate snaps.
def participatesInDeduplication(faciaContent: PressedContent): Boolean = faciaContent.properties.embedType.isEmpty
def fromConfigsAndContainers(
configs: Seq[((ContainerDisplayConfig, CollectionEssentials), Container)],
initialContext: ContainerLayoutContext = ContainerLayoutContext.empty,
): Front = {
@tailrec
def faciaContainers(
allConfigs: Seq[((ContainerDisplayConfig, CollectionEssentials), Container)],
context: ContainerLayoutContext,
index: Int = 0,
accumulation: Vector[FaciaContainer] = Vector.empty,
): Seq[FaciaContainer] = {
allConfigs.toList match {
case Nil => accumulation
case ((config, collection), container) :: remainingConfigs =>
val newItems = collection.items.distinctBy(_.header.url)
val layoutMaybe = ContainerLayout.fromContainer(container, context, config, newItems, hasMore = false)
val newContext = layoutMaybe.map(_._2).getOrElse(context)
val faciaContainer = FaciaContainer.fromConfigAndAdSpecs(
index,
container,
config.collectionConfigWithId,
collection.copy(items = newItems),
layoutMaybe.map(_._1),
None,
)
faciaContainers(remainingConfigs, newContext, index + 1, accumulation :+ faciaContainer)
}
}
Front(
faciaContainers(configs, initialContext).filterNot(_.items.isEmpty),
)
}
def fromPressedPageWithDeduped(
pressedPage: PressedPage,
edition: Edition,
initialContext: ContainerLayoutContext = ContainerLayoutContext.empty,
adFree: Boolean,
): Seq[FaciaContainer] = {
@tailrec
def faciaContainers(
collections: List[PressedCollection],
context: ContainerLayoutContext,
index: Int = 0,
accumulation: Seq[FaciaContainer] = Vector.empty[FaciaContainer],
): Seq[FaciaContainer] = {
collections match {
case Nil => accumulation
case pressedCollection :: remainingPressedCollections =>
val omitMPU: Boolean = pressedPage.metadata.omitMPUsFromContainers(edition)
val container: Container = Container.fromPressedCollection(pressedCollection, omitMPU, adFree)
val newItems = pressedCollection.distinct
val collectionEssentials = CollectionEssentials.fromPressedCollection(pressedCollection)
val containerDisplayConfig = ContainerDisplayConfig.withDefaults(pressedCollection.collectionConfigWithId)
val containerLayoutMaybe: Option[(ContainerLayout, ContainerLayoutContext)] = ContainerLayout.fromContainer(
container,
context,
containerDisplayConfig,
newItems,
pressedCollection.hasMore,
)
val newContext: ContainerLayoutContext = containerLayoutMaybe.map(_._2).getOrElse(context)
val faciaContainer = FaciaContainer.fromConfigAndAdSpecs(
index,
container,
pressedCollection.collectionConfigWithId,
collectionEssentials.copy(items = newItems),
containerLayoutMaybe.map(_._1),
None,
omitMPU = if (containerLayoutMaybe.isDefined) false else omitMPU,
adFree = adFree,
targetedTerritory = pressedCollection.targetedTerritory,
)
faciaContainers(
remainingPressedCollections,
newContext,
index + 1,
accumulation :+ faciaContainer,
)
}
}
faciaContainers(
pressedPage.collections.filterNot(_.curatedPlusBackfillDeduplicated.isEmpty),
initialContext,
)
}
def fromPressedPage(
pressedPage: PressedPage,
edition: Edition,
initialContext: ContainerLayoutContext = ContainerLayoutContext.empty,
adFree: Boolean,
): Front =
Front(fromPressedPageWithDeduped(pressedPage, edition, initialContext, adFree))
def makeLinkedData(url: String, collections: Seq[FaciaContainer])(implicit request: RequestHeader): ItemList = {
ItemList(
url = LinkTo(url),
itemListElement = collections.zipWithIndex.map { case (collection, index) =>
ListItem(
position = index,
item = Some(
ItemList(
url = LinkTo(url), // don't have a uri for each container
itemListElement = collection.items.zipWithIndex.map { case (item, i) =>
ListItem(position = i, url = Some(LinkTo(item.header.url)))
},
),
),
)
},
)
}
}