Skip to content

Commit

Permalink
Gallery picker (#26188)
Browse files Browse the repository at this point in the history
* Add DCR flag and picker for Galleries

* formatting

* request blocks from capi

* update test to use ws client plus these db files

* fix imports
  • Loading branch information
alinaboghiu authored Jun 12, 2023
1 parent d6fe041 commit 66c651c
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 28 deletions.
68 changes: 53 additions & 15 deletions applications/app/controllers/GalleryController.scala
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
package controllers

import com.gu.contentapi.client.model.v1.{ItemResponse, Content => ApiContent}
import com.gu.contentapi.client.model.v1.{Blocks, ItemResponse, Content => ApiContent}
import common._
import conf.switches.Switches
import contentapi.ContentApiClient
import model._
import model.dotcomrendering.{DotcomRenderingDataModel, PageType}
import pages.GalleryHtmlPage
import play.api.libs.ws.WSClient
import play.api.mvc._
import play.twirl.api.Html
import renderers.DotcomRenderingService
import services.dotcomrendering.{GalleryPicker, RemoteRender}
import views.support.RenderOtherStatus

import scala.concurrent.Future

class GalleryController(contentApiClient: ContentApiClient, val controllerComponents: ControllerComponents)(implicit
context: ApplicationContext,
) extends BaseController
class GalleryController(
contentApiClient: ContentApiClient,
val controllerComponents: ControllerComponents,
wsClient: WSClient,
remoteRenderer: renderers.DotcomRenderingService = DotcomRenderingService(),
)(implicit context: ApplicationContext)
extends BaseController
with RendersItemResponse
with GuLogging
with ImplicitControllerExecutionContext {
Expand All @@ -26,39 +34,69 @@ class GalleryController(contentApiClient: ContentApiClient, val controllerCompon
val index = request.getIntParameter("index") getOrElse 1
val isTrail = request.getBooleanParameter("trail") getOrElse false

lookup(path, index, isTrail) map {
case Right(model) if model.gallery.content.isExpired =>
RenderOtherStatus(Gone) // TODO - delete this line after switching to new content api
case Right(model) => renderGallery(model)
case Left(other) => RenderOtherStatus(other)
lookup(path, index, isTrail) flatMap {
case Right((model, _)) if model.gallery.content.isExpired =>
Future.successful(RenderOtherStatus(Gone)) // TODO - delete this line after switching to new content api
case Right((model, blocks)) if GalleryPicker.getTier(model) == RemoteRender =>
remoteRender(model, blocks)
case Right((model, _)) => Future.successful(renderGallery(model))
case Left(other) => Future.successful(RenderOtherStatus(other))
}
}

private def remoteRender(model: GalleryPage, blocks: Blocks)(implicit
request: RequestHeader,
) = {
val pageType = PageType(model, request, context)
if (request.isJson) {
Future.successful(
common.renderJson(getDCRJson(model, pageType, blocks), model).as("application/json"),
)
} else {
remoteRenderer.getGallery(
wsClient,
model,
pageType,
blocks,
)
}
}

def lightboxJson(path: String): Action[AnyContent] =
Action.async { implicit request =>
val index = request.getIntParameter("index") getOrElse 1
lookup(path, index, isTrail = false) map {
case Left(other) => RenderOtherStatus(other)
case Right(model) => Cached(model) { JsonComponent.fromWritable(model.gallery.lightbox.javascriptConfig) }
case Left(other) => RenderOtherStatus(other)
case Right((model, _)) => Cached(model) { JsonComponent.fromWritable(model.gallery.lightbox.javascriptConfig) }
}
}

private def lookup(path: String, index: Int, isTrail: Boolean)(implicit request: RequestHeader) = {
private def getDCRJson(galleryPage: GalleryPage, pageType: PageType, blocks: Blocks)(implicit
request: RequestHeader,
): String = {
DotcomRenderingDataModel.toJson(DotcomRenderingDataModel.forGallery(galleryPage, request, pageType, blocks))
}

private def lookup(path: String, index: Int, isTrail: Boolean)(implicit
request: RequestHeader,
): Future[Either[Result, (GalleryPage, Blocks)]] = {
val edition = Edition(request)
log.info(s"Fetching gallery: $path for edition $edition")
contentApiClient
.getResponse(
contentApiClient
.item(path, edition)
.showFields("all"),
.showFields("all")
.showBlocks("all"),
)
.map { response =>
val gallery = response.content.map(Content(_))
val model: Option[GalleryPage] = gallery collect {
val blocks = response.content.flatMap(_.blocks).getOrElse(Blocks())
val model = gallery collect {
case g: Gallery => GalleryPage(g, StoryPackages(g.metadata.id, response), index, isTrail)
}

ModelOrResult(model, response)
ModelOrResult(model.map((_, blocks)), response)

}
.recover { convertApiExceptions }
Expand Down
47 changes: 47 additions & 0 deletions applications/app/services/dotcomrendering/GalleryPicker.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package services.dotcomrendering

import common.GuLogging
import model.Cors.RichRequestHeader
import model.GalleryPage
import play.api.mvc.RequestHeader
import utils.DotcomponentsLogger

object GalleryPicker extends GuLogging {

/**
*
* Add to this function any logic for including/excluding
* a gallery article from being rendered with DCR
*
* Currently defaulting to false until we implement image articles in DCR
*
* */
private def dcrCouldRender(galleryPage: GalleryPage): Boolean = {
false
}

def getTier(
galleryPage: GalleryPage,
)(implicit
request: RequestHeader,
): RenderType = {

val participatingInTest = false // until we create a test for this content type
val dcrCanRender = dcrCouldRender(galleryPage)

val tier = {
if (request.forceDCROff) LocalRender
else if (request.forceDCR) RemoteRender
else if (dcrCanRender && participatingInTest) RemoteRender
else LocalRender
}

if (tier == RemoteRender) {
DotcomponentsLogger.logger.logRequest(s"path executing in dotcomponents", Map.empty, galleryPage.gallery)
} else {
DotcomponentsLogger.logger.logRequest(s"path executing in web", Map.empty, galleryPage.gallery)
}

tier
}
}
2 changes: 1 addition & 1 deletion applications/test/GalleryControllerTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import org.scalatest.{BeforeAndAfterAll, DoNotDiscover}
val galleryUrl = "news/gallery/2012/may/02/picture-desk-live-kabul-burma"

lazy val galleryController =
new GalleryController(testContentApiClient, play.api.test.Helpers.stubControllerComponents())
new GalleryController(testContentApiClient, play.api.test.Helpers.stubControllerComponents(), wsClient)

"Gallery Controller" should "200 when content type is gallery" in {
val result = galleryController.render(galleryUrl)(TestRequest(s"/$galleryUrl"))
Expand Down
26 changes: 26 additions & 0 deletions common/app/model/dotcomrendering/DotcomRenderingDataModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import model.{
ContentFormat,
ContentPage,
GUDateTimeFormatNew,
GalleryPage,
ImageContentPage,
InteractivePage,
LiveBlogPage,
Expand Down Expand Up @@ -283,6 +284,31 @@ object DotcomRenderingDataModel {
)
}

def forGallery(
galleryPage: GalleryPage,
request: RequestHeader,
pageType: PageType,
blocks: APIBlocks,
) = {

val linkedData = LinkedData.forArticle(
article = galleryPage.gallery,
baseURL = Configuration.dotcom.baseUrl,
fallbackLogo = Configuration.images.fallbackLogo,
)

apply(
page = galleryPage,
request = request,
pageType = pageType,
linkedData = linkedData,
mainBlock = blocks.main,
bodyBlocks = blocks.body.getOrElse(Nil).toSeq,
hasStoryPackage = galleryPage.related.hasStoryPackage,
storyPackage = getStoryPackage(galleryPage.related.faciaItems, request),
)
}

def keyEventsFallback(
blocks: APIBlocks,
): Seq[APIBlock] = {
Expand Down
28 changes: 16 additions & 12 deletions common/app/renderers/DotcomRenderingService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import conf.Configuration
import conf.switches.Switches.CircuitBreakerSwitch
import http.{HttpPreconnections, ResultWithPreconnectPreload}
import model.Cached.{RevalidatableResult, WithoutRevalidationResult}
import model.SimplePage
import model.dotcomrendering._
import model.{
CacheTime,
Cached,
GalleryPage,
ImageContentPage,
InteractivePage,
LiveBlogPage,
Expand All @@ -20,24 +21,16 @@ import model.{
PageWithStoryPackage,
PressedPage,
RelatedContentItem,
SimplePage,
Topic,
TopicResult,
}
import model.dotcomrendering.{
DotcomBlocksRenderingDataModel,
DotcomFrontsRenderingDataModel,
DotcomNewslettersPageRenderingDataModel,
DotcomRenderingDataModel,
DotcomTagFrontsRenderingDataModel,
PageType,
Trail,
}
import services.{IndexPage, NewsletterData}
import services.newsletters.model.NewsletterResponse
import play.api.libs.ws.{WSClient, WSResponse}
import play.api.mvc.Results.{InternalServerError, NotFound}
import play.api.mvc.{RequestHeader, Result}
import play.twirl.api.Html
import services.newsletters.model.NewsletterResponse
import services.{IndexPage, NewsletterData}

import java.lang.System.currentTimeMillis
import java.net.ConnectException
Expand Down Expand Up @@ -347,6 +340,17 @@ class DotcomRenderingService extends GuLogging with ResultWithPreconnectPreload
val json = DotcomRenderingDataModel.toJson(dataModel)
post(ws, json, Configuration.rendering.baseURL + "/Article", CacheTime.Facia)
}

def getGallery(
ws: WSClient,
gallery: GalleryPage,
pageType: PageType,
blocks: Blocks,
)(implicit request: RequestHeader): Future[Result] = {
val dataModel = DotcomRenderingDataModel.forGallery(gallery, request, pageType, blocks)
val json = DotcomRenderingDataModel.toJson(dataModel)
post(ws, json, Configuration.rendering.baseURL + "/Article", CacheTime.Facia)
}
}

object DotcomRenderingService {
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 66c651c

Please sign in to comment.