Skip to content

Commit

Permalink
create crosswordpicker and remote rendering for crosswords
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-nowak committed Jan 23, 2024
1 parent 6ddcbf0 commit b642a4f
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 44 deletions.
102 changes: 63 additions & 39 deletions applications/app/controllers/CrosswordsController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import play.api.mvc.{Action, RequestHeader, Result, _}
import services.{IndexPage, IndexPageItem}
import html.HtmlPageHelpers.ContentCSSFile
import model.dotcomrendering.{DotcomRenderingDataModel, PageType}
import play.api.libs.ws.WSClient
import renderers.DotcomRenderingService
import services.dotcomrendering.{CrosswordsPicker, RemoteRender}

import scala.concurrent.Future
import scala.concurrent.duration._
Expand All @@ -31,6 +34,9 @@ trait CrosswordController extends BaseController with GuLogging with ImplicitCon

def contentApiClient: ContentApiClient

val remoteRenderer: DotcomRenderingService = DotcomRenderingService()
val wsClient: WSClient

def noResults()(implicit request: RequestHeader): Result

def getCrossword(crosswordType: String, id: Int)(implicit request: RequestHeader): Future[ItemResponse] = {
Expand All @@ -40,14 +46,14 @@ trait CrosswordController extends BaseController with GuLogging with ImplicitCon
}

def withCrossword(crosswordType: String, id: Int)(
f: (Crossword, ApiContent) => Result,
f: (Crossword, ApiContent) => Future[Result],
)(implicit request: RequestHeader): Future[Result] = {
getCrossword(crosswordType, id).map { response =>
getCrossword(crosswordType, id).flatMap { response =>
val maybeCrossword = for {
content <- response.content
crossword <- content.crossword
} yield f(crossword, content)
maybeCrossword getOrElse noResults()
maybeCrossword getOrElse Future.successful(noResults())
} recover {
case t: Throwable =>
log.error(s"Error retrieving $crosswordType crossword id $id from API", t)
Expand All @@ -60,22 +66,31 @@ trait CrosswordController extends BaseController with GuLogging with ImplicitCon
context: ApplicationContext,
): Future[Result] = {
withCrossword(crosswordType, id) { (crossword, content) =>
Cached(60.seconds)(
RevalidatableResult.Ok(
CrosswordHtmlPage.html(
CrosswordPageWithSvg(
CrosswordContent.make(CrosswordData.fromCrossword(crossword, content), content),
CrosswordSvg(crossword, None, None, false),
val page = CrosswordPageWithSvg(
CrosswordContent.make(CrosswordData.fromCrossword(crossword, content), content),
CrosswordSvg(crossword, None, None, false),
)

if (CrosswordsPicker.getTier(page) == RemoteRender)
remoteRenderer.getCrossword(wsClient, page, PageType(page, request, context))
else
Future.successful(
Cached(60.seconds)(
RevalidatableResult.Ok(
CrosswordHtmlPage.html(page),
),
),
),
)
)
}
}
}

class CrosswordPageController(val contentApiClient: ContentApiClient, val controllerComponents: ControllerComponents)(
implicit context: ApplicationContext,
class CrosswordPageController(
val contentApiClient: ContentApiClient,
val controllerComponents: ControllerComponents,
val wsClient: WSClient,
)(implicit
context: ApplicationContext,
) extends CrosswordController {

def noResults()(implicit request: RequestHeader): Result =
Expand All @@ -93,30 +108,34 @@ class CrosswordPageController(val contentApiClient: ContentApiClient, val contro
val crosswordPage = new CrosswordPageWithContent(crosswordContent)

val pageType = PageType(crosswordPage, request, context)
common.renderJson(getDCRJson(crosswordPage, pageType), crosswordPage).as("application/json")
Future.successful(
common.renderJson(getDCRJson(crosswordPage, pageType), crosswordPage).as("application/json"),
)
}
}
}
private def getDCRJson(crosswordPage: CrosswordPageWithContent, pageType: PageType)(implicit
request: RequestHeader,
): String =
DotcomRenderingDataModel.toJson(
DotcomRenderingDataModel.forCrossword(crosswordPage, request, pageType, crosswordPage.crossword),
DotcomRenderingDataModel.forCrossword(crosswordPage, request, pageType),
)

def accessibleCrossword(crosswordType: String, id: Int): Action[AnyContent] =
Action.async { implicit request =>
withCrossword(crosswordType, id) { (crossword, content) =>
Cached(60.seconds)(
RevalidatableResult.Ok(
CrosswordHtmlPage.html(
AccessibleCrosswordPage(
CrosswordContent.make(
CrosswordData
.fromCrossword(crossword.copy(name = s"Accessible version of ${crossword.name}"), content),
content,
Future.successful(
Cached(60.seconds)(
RevalidatableResult.Ok(
CrosswordHtmlPage.html(
AccessibleCrosswordPage(
CrosswordContent.make(
CrosswordData
.fromCrossword(crossword.copy(name = s"Accessible version of ${crossword.name}"), content),
content,
),
AccessibleCrosswordRows(crossword),
),
AccessibleCrosswordRows(crossword),
),
),
),
Expand All @@ -127,12 +146,14 @@ class CrosswordPageController(val contentApiClient: ContentApiClient, val contro
def printableCrossword(crosswordType: String, id: Int): Action[AnyContent] =
Action.async { implicit request =>
withCrossword(crosswordType, id) { (crossword, content) =>
Cached(60.seconds)(
RevalidatableResult.Ok(
PrintableCrosswordHtmlPage.html(
CrosswordPageWithSvg(
CrosswordContent.make(CrosswordData.fromCrossword(crossword, content), content),
CrosswordSvg(crossword, None, None, false),
Future.successful(
Cached(60.seconds)(
RevalidatableResult.Ok(
PrintableCrosswordHtmlPage.html(
CrosswordPageWithSvg(
CrosswordContent.make(CrosswordData.fromCrossword(crossword, content), content),
CrosswordSvg(crossword, None, None, false),
),
),
),
),
Expand All @@ -147,22 +168,25 @@ class CrosswordPageController(val contentApiClient: ContentApiClient, val contro

val globalStylesheet = Static(s"stylesheets/$ContentCSSFile.css")

Cached(60.seconds) {
val body = s"""$xml"""
RevalidatableResult(
Cors {
Ok(body).as("image/svg+xml")
},
body,
)
}
Future.successful(
Cached(60.seconds) {
val body = s"""$xml"""
RevalidatableResult(
Cors {
Ok(body).as("image/svg+xml")
},
body,
)
},
)
}
}
}

class CrosswordSearchController(
val contentApiClient: ContentApiClient,
val controllerComponents: ControllerComponents,
val wsClient: WSClient,
)(implicit context: ApplicationContext)
extends CrosswordController {
val searchForm = Form(
Expand Down
51 changes: 51 additions & 0 deletions applications/app/services/dotcomrendering/CrosswordsPicker.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package services.dotcomrendering

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

object CrosswordsPicker extends GuLogging {

/**
*
* Add to this function any logic for including/excluding
* a crossword page from being rendered with DCR
*
* Currently defaulting to false until we implement crosswords in DCR
*
* */
private def dcrCouldRender(crosswordPageWithContent: CrosswordPageWithContent): Boolean = {
false
}

def getTier(
crosswordPageWithContent: CrosswordPageWithContent,
)(implicit
request: RequestHeader,
): RenderType = {

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

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,
crosswordPageWithContent.item,
)
} else {
DotcomponentsLogger.logger.logRequest(s"path executing in web", Map.empty, crosswordPageWithContent.item)
}

tier
}
}
2 changes: 1 addition & 1 deletion applications/test/CrosswordDataTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import org.scalatest.time.{Millis, Span}
"CrosswordData" - {

lazy val crosswordPageController =
new CrosswordPageController(testContentApiClient, play.api.test.Helpers.stubControllerComponents())
new CrosswordPageController(testContentApiClient, play.api.test.Helpers.stubControllerComponents(), wsClient)

"fromCrossword should normalize separators for grouped entries" in {

Expand Down
2 changes: 1 addition & 1 deletion applications/test/CrosswordPageMetaDataTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import org.scalatest.{BeforeAndAfterAll, DoNotDiscover}

val crosswordUrl = "crosswords/cryptic/26697"
lazy val crosswordPageController =
new CrosswordPageController(testContentApiClient, play.api.test.Helpers.stubControllerComponents())
new CrosswordPageController(testContentApiClient, play.api.test.Helpers.stubControllerComponents(), wsClient)

it should "not include the ios deep link" in {
val result = crosswordPageController.crossword("cryptic", 26697)(TestRequest(crosswordUrl))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import common.Maps.RichMap
import common.commercial.EditionCommercialProperties
import common.{CanonicalLink, Chronos, Edition, Localisation, RichRequestHeader}
import conf.Configuration
import crosswords.CrosswordPageWithContent
import experiments.ActiveExperiments
import model.dotcomrendering.DotcomRenderingUtils._
import model.dotcomrendering.pageElements.{PageElement, TextCleaner}
Expand Down Expand Up @@ -342,10 +343,9 @@ object DotcomRenderingDataModel {
}

def forCrossword(
crosswordPage: ContentPage,
crosswordPage: CrosswordPageWithContent,
request: RequestHeader,
pageType: PageType,
crossword: CrosswordData, // TODO or move CrosswordPageWithContent to common so usable here
): DotcomRenderingDataModel = {
val linkedData = LinkedData.forArticle(
article = crosswordPage.item,
Expand All @@ -360,7 +360,7 @@ object DotcomRenderingDataModel {
linkedData = linkedData,
mainBlock = None,
bodyBlocks = Seq.empty,
crossword = Some(crossword),
crossword = Some(crosswordPage.crossword),
)
}

Expand Down
11 changes: 11 additions & 0 deletions common/app/renderers/DotcomRenderingService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import common.{DCRMetrics, GuLogging}
import concurrent.CircuitBreakerRegistry
import conf.Configuration
import conf.switches.Switches.CircuitBreakerSwitch
import crosswords.CrosswordPageWithContent
import http.{HttpPreconnections, ResultWithPreconnectPreload}
import model.Cached.{RevalidatableResult, WithoutRevalidationResult}
import model.dotcomrendering._
Expand Down Expand Up @@ -392,6 +393,16 @@ class DotcomRenderingService extends GuLogging with ResultWithPreconnectPreload
val json = DotcomRenderingDataModel.toJson(dataModel)
post(ws, json, Configuration.rendering.articleBaseURL + "/Article", CacheTime.Facia)
}

def getCrossword(
ws: WSClient,
crosswordPage: CrosswordPageWithContent,
pageType: PageType,
)(implicit request: RequestHeader): Future[Result] = {
val dataModel = DotcomRenderingDataModel.forCrossword(crosswordPage, request, pageType)
val json = DotcomRenderingDataModel.toJson(dataModel)
post(ws, json, Configuration.rendering.articleBaseURL + "/Article", CacheTime.Facia)
}
}

object DotcomRenderingService {
Expand Down

0 comments on commit b642a4f

Please sign in to comment.