applications/app/controllers/GalleryController.scala (99 lines of code) (raw):
package controllers
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.json.JsValue
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,
wsClient: WSClient,
remoteRenderer: renderers.DotcomRenderingService = DotcomRenderingService(),
)(implicit context: ApplicationContext)
extends BaseController
with RendersItemResponse
with GuLogging
with ImplicitControllerExecutionContext {
def renderJson(path: String): Action[AnyContent] = render(path)
def render(path: String): Action[AnyContent] = Action.async { implicit request => renderItem(path) }
override def renderItem(path: String)(implicit request: RequestHeader): Future[Result] = {
val index = request.getIntParameter("index") getOrElse 1
val isTrail = request.getBooleanParameter("trail") getOrElse false
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 request.isJson && request.forceDCR =>
val pageType = PageType(model, request, context)
Future.successful(
common.renderJson(getDCRJson(model, pageType, blocks), model).as("application/json"),
)
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)
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) }
}
}
private def getDCRJson(galleryPage: GalleryPage, pageType: PageType, blocks: Blocks)(implicit
request: RequestHeader,
): JsValue = {
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)
logInfoWithRequestId(s"Fetching gallery: $path for edition $edition")
contentApiClient
.getResponse(
contentApiClient
.item(path, edition)
.showFields("all")
.showBlocks("all"),
)
.map { response =>
val gallery = response.content.map(Content(_))
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.map((_, blocks)), response)
}
.recover { convertApiExceptions }
}
private def renderGallery(model: GalleryPage)(implicit request: RequestHeader) = {
val htmlResponse: (() => Html) = () => GalleryHtmlPage.html(model)
val jsonResponse = () => views.html.fragments.galleryBody(model)
renderFormat(htmlResponse, jsonResponse, model, Switches.all)
}
private def isSupported(c: ApiContent) = c.isGallery
override def canRender(i: ItemResponse): Boolean = i.content.exists(isSupported)
}