From eb1900e4b8a4b2b5c2607a1f012bc63560fa1b8c Mon Sep 17 00:00:00 2001 From: DanielCliftonGuardian <110032454+DanielCliftonGuardian@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:15:45 +0000 Subject: [PATCH 01/17] WIP --- .../controllers/CrosswordsController.scala | 46 ++++++++++++++----- applications/conf/routes | 1 + .../EditionsCrosswordRenderingDataModel.scala | 40 ++++++++++++++++ 3 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala diff --git a/applications/app/controllers/CrosswordsController.scala b/applications/app/controllers/CrosswordsController.scala index 41e2757662d..fe995c681f9 100644 --- a/applications/app/controllers/CrosswordsController.scala +++ b/applications/app/controllers/CrosswordsController.scala @@ -1,19 +1,13 @@ package controllers +import com.gu.contentapi.client.model.v1.Content.unsafeEmpty.crossword +import com.gu.contentapi.client.model.v1.CrosswordType.{Cryptic, Quick} import com.gu.contentapi.client.model.v1.{Crossword, ItemResponse, Content => ApiContent, Section => ApiSection} import common.{Edition, GuLogging, ImplicitControllerExecutionContext} import conf.Static import contentapi.ContentApiClient import pages.{CrosswordHtmlPage, IndexHtmlPage, PrintableCrosswordHtmlPage} -import crosswords.{ - AccessibleCrosswordPage, - AccessibleCrosswordRows, - CrosswordPageWithContent, - CrosswordPageWithSvg, - CrosswordSearchPageNoResult, - CrosswordSearchPageWithResults, - CrosswordSvg, -} +import crosswords.{AccessibleCrosswordPage, AccessibleCrosswordRows, CrosswordPageWithContent, CrosswordPageWithSvg, CrosswordSearchPageNoResult, CrosswordSearchPageWithResults, CrosswordSvg} import model.Cached.{RevalidatableResult, WithoutRevalidationResult} import model._ import org.joda.time.{DateTime, LocalDate} @@ -22,6 +16,8 @@ import play.api.data._ import play.api.mvc.{Action, RequestHeader, Result, _} import services.{IndexPage, IndexPageItem} import html.HtmlPageHelpers.ContentCSSFile +import model.dotcomrendering.pageElements.EditionsCrosswordRenderingDataModel +import model.dotcomrendering.pageElements.EditionsCrosswordRenderingDataModel.toJson import model.dotcomrendering.{DotcomRenderingDataModel, PageType} import play.api.libs.ws.WSClient import renderers.DotcomRenderingService @@ -290,11 +286,12 @@ class CrosswordSearchController( case class CrosswordLookup(crosswordType: String, id: Int) } -class CrosswordEditionsController(val controllerComponents: ControllerComponents) - extends BaseController +class CrosswordEditionsController( + val contentApiClient: ContentApiClient, + val controllerComponents: ControllerComponents, +) extends BaseController with GuLogging with ImplicitControllerExecutionContext { - def digitalEdition: Action[AnyContent] = Action.async { implicit request => Future.successful( @@ -303,4 +300,29 @@ class CrosswordEditionsController(val controllerComponents: ControllerComponents ), ) } + + def getCrosswords: Action[AnyContent] = Action.async { implicit request => + contentApiClient + .getResponse( + contentApiClient.item(s"crosswords"), + ) + .flatMap { response => + val crosswords = for { + results <- response.results + quick <- results.find(_.crossword.exists(_.`type` == Quick)).flatMap(_.crossword) + cryptic <- results.find(_.crossword.exists(_.`type` == Cryptic)).flatMap(_.crossword) + } yield (quick, cryptic) + + crosswords match { + case Some((quick, cryptic)) => + val crosswordPage = EditionsCrosswordRenderingDataModel(quick, cryptic) + Future.successful( + Cached(CacheTime.Default)( + RevalidatableResult.Ok(toJson(crosswordPage)), + ).as("application/json"), + ) + case None => Future.successful(NotFound) + } + } + } } diff --git a/applications/conf/routes b/applications/conf/routes index e17e9272bd6..5de2e9ee519 100644 --- a/applications/conf/routes +++ b/applications/conf/routes @@ -29,6 +29,7 @@ GET /crosswords/lookup # Crosswords digital edition GET /crosswords/digital-edition controllers.CrosswordEditionsController.digitalEdition +GET /crosswordtest controllers.CrosswordEditionsController.getCrosswords # Email paths GET /email/form/$emailType/$listId<[0-9]+> controllers.EmailSignupController.renderForm(emailType: String, listId: Int) diff --git a/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala b/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala new file mode 100644 index 00000000000..4a568b7edf7 --- /dev/null +++ b/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala @@ -0,0 +1,40 @@ +package model.dotcomrendering.pageElements + +import com.gu.contentapi.client.model.v1.Crossword +import model.dotcomrendering.DotcomRenderingDataModel +import model.dotcomrendering.DotcomRenderingUtils.withoutNull +import org.apache.thrift.protocol.TSimpleJSONProtocol +import org.apache.thrift.transport.TIOStreamTransport +import play.api.libs.json.{JsValue, Json, OWrites, Writes} + +case class EditionsCrosswordRenderingDataModel( + quick: Crossword, + cryptic: Crossword, +) + +object EditionsCrosswordRenderingDataModel { + // we Json.parse this into a JsValue to ensure we get the raw JSON + // from the Content API rather than a Json.stringified version + private def contentApiToJsonValue(crossword: Crossword): JsValue = { + val protocolFactory = new TSimpleJSONProtocol.Factory + + val buffer = new java.io.ByteArrayOutputStream + val protocol = protocolFactory.getProtocol(new TIOStreamTransport(buffer)) + + Crossword.encode(crossword, protocol) + Json.parse(new String(buffer.toByteArray, "UTF-8")) + } + implicit val writes: Writes[EditionsCrosswordRenderingDataModel] = + new Writes[EditionsCrosswordRenderingDataModel] { + def writes(model: EditionsCrosswordRenderingDataModel) = { + Json.obj( + "quick" -> contentApiToJsonValue(model.quick), + "cryptic" -> contentApiToJsonValue(model.cryptic), + ) + } + } + def toJson(model: EditionsCrosswordRenderingDataModel): String = { + val jsValue = Json.toJson(model) + Json.stringify(withoutNull(jsValue)) + } +} From d6001625b0dfd7ee1aebcb8685f6030906f0b235 Mon Sep 17 00:00:00 2001 From: DanielCliftonGuardian <110032454+DanielCliftonGuardian@users.noreply.github.com> Date: Fri, 15 Nov 2024 13:12:08 +0000 Subject: [PATCH 02/17] Add to DCR service --- .../app/controllers/CrosswordsController.scala | 13 ++++++++++++- applications/conf/routes | 3 +-- build.sbt | 1 + .../EditionsCrosswordRenderingDataModel.scala | 15 ++++----------- common/app/renderers/DotcomRenderingService.scala | 13 ++++++++++++- project/Dependencies.scala | 1 + 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/applications/app/controllers/CrosswordsController.scala b/applications/app/controllers/CrosswordsController.scala index fe995c681f9..9d170e53d2b 100644 --- a/applications/app/controllers/CrosswordsController.scala +++ b/applications/app/controllers/CrosswordsController.scala @@ -7,7 +7,15 @@ import common.{Edition, GuLogging, ImplicitControllerExecutionContext} import conf.Static import contentapi.ContentApiClient import pages.{CrosswordHtmlPage, IndexHtmlPage, PrintableCrosswordHtmlPage} -import crosswords.{AccessibleCrosswordPage, AccessibleCrosswordRows, CrosswordPageWithContent, CrosswordPageWithSvg, CrosswordSearchPageNoResult, CrosswordSearchPageWithResults, CrosswordSvg} +import crosswords.{ + AccessibleCrosswordPage, + AccessibleCrosswordRows, + CrosswordPageWithContent, + CrosswordPageWithSvg, + CrosswordSearchPageNoResult, + CrosswordSearchPageWithResults, + CrosswordSvg, +} import model.Cached.{RevalidatableResult, WithoutRevalidationResult} import model._ import org.joda.time.{DateTime, LocalDate} @@ -289,6 +297,8 @@ class CrosswordSearchController( class CrosswordEditionsController( val contentApiClient: ContentApiClient, val controllerComponents: ControllerComponents, + val remoteRenderer: DotcomRenderingService = DotcomRenderingService(), + val wsClient: WSClient, ) extends BaseController with GuLogging with ImplicitControllerExecutionContext { @@ -316,6 +326,7 @@ class CrosswordEditionsController( crosswords match { case Some((quick, cryptic)) => val crosswordPage = EditionsCrosswordRenderingDataModel(quick, cryptic) + remoteRenderer.getEditionsCrossword(wsClient, quick, cryptic) Future.successful( Cached(CacheTime.Default)( RevalidatableResult.Ok(toJson(crosswordPage)), diff --git a/applications/conf/routes b/applications/conf/routes index 5de2e9ee519..2c0e804f64b 100644 --- a/applications/conf/routes +++ b/applications/conf/routes @@ -29,8 +29,7 @@ GET /crosswords/lookup # Crosswords digital edition GET /crosswords/digital-edition controllers.CrosswordEditionsController.digitalEdition -GET /crosswordtest controllers.CrosswordEditionsController.getCrosswords - +GET /crosswordtest controllers.CrosswordEditionsController.getCrosswords # Email paths GET /email/form/$emailType/$listId<[0-9]+> controllers.EmailSignupController.renderForm(emailType: String, listId: Int) GET /email/form/$emailType/:listName controllers.EmailSignupController.renderFormFromName(emailType: String, listName: String) diff --git a/build.sbt b/build.sbt index 611392947a1..afc1bac4d01 100644 --- a/build.sbt +++ b/build.sbt @@ -31,6 +31,7 @@ val common = library("common") eTagCachingS3, nettyCodecHttp2, contentApiClient, + contentApiModelsJson, enumeratumPlayJson, filters, commonsLang, diff --git a/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala b/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala index 4a568b7edf7..11e938a0235 100644 --- a/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala +++ b/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala @@ -1,11 +1,10 @@ package model.dotcomrendering.pageElements import com.gu.contentapi.client.model.v1.Crossword -import model.dotcomrendering.DotcomRenderingDataModel import model.dotcomrendering.DotcomRenderingUtils.withoutNull -import org.apache.thrift.protocol.TSimpleJSONProtocol -import org.apache.thrift.transport.TIOStreamTransport -import play.api.libs.json.{JsValue, Json, OWrites, Writes} +import play.api.libs.json.{JsValue, Json, Writes} +import com.gu.contentapi.json.CirceEncoders._ +import io.circe.syntax._ case class EditionsCrosswordRenderingDataModel( quick: Crossword, @@ -16,13 +15,7 @@ object EditionsCrosswordRenderingDataModel { // we Json.parse this into a JsValue to ensure we get the raw JSON // from the Content API rather than a Json.stringified version private def contentApiToJsonValue(crossword: Crossword): JsValue = { - val protocolFactory = new TSimpleJSONProtocol.Factory - - val buffer = new java.io.ByteArrayOutputStream - val protocol = protocolFactory.getProtocol(new TIOStreamTransport(buffer)) - - Crossword.encode(crossword, protocol) - Json.parse(new String(buffer.toByteArray, "UTF-8")) + Json.parse(crossword.asJson.toString()) } implicit val writes: Writes[EditionsCrosswordRenderingDataModel] = new Writes[EditionsCrosswordRenderingDataModel] { diff --git a/common/app/renderers/DotcomRenderingService.scala b/common/app/renderers/DotcomRenderingService.scala index d9cf9b59e0a..5b8ce3b78bd 100644 --- a/common/app/renderers/DotcomRenderingService.scala +++ b/common/app/renderers/DotcomRenderingService.scala @@ -1,7 +1,7 @@ package renderers import org.apache.pekko.actor.{ActorSystem => PekkoActorSystem} -import com.gu.contentapi.client.model.v1.{Block, Blocks, Content} +import com.gu.contentapi.client.model.v1.{Block, Blocks, Content, Crossword} import common.{DCRMetrics, GuLogging} import concurrent.CircuitBreakerRegistry import conf.Configuration @@ -10,6 +10,7 @@ import crosswords.CrosswordPageWithContent import http.{HttpPreconnections, ResultWithPreconnectPreload} import model.Cached.{RevalidatableResult, WithoutRevalidationResult} import model.dotcomrendering._ +import model.dotcomrendering.pageElements.EditionsCrosswordRenderingDataModel import model.{ CacheTime, Cached, @@ -417,6 +418,16 @@ class DotcomRenderingService extends GuLogging with ResultWithPreconnectPreload val json = DotcomRenderingDataModel.toJson(dataModel) post(ws, json, Configuration.rendering.articleBaseURL + "/Article", CacheTime.Facia) } + + def getEditionsCrossword( + ws: WSClient, + quickCrossword: Crossword, + crypticCrossword: Crossword, + )(implicit request: RequestHeader): Future[Result] = { + val dataModel = EditionsCrosswordRenderingDataModel(quickCrossword, crypticCrossword) + val json = EditionsCrosswordRenderingDataModel.toJson(dataModel) + post(ws, json, Configuration.rendering.articleBaseURL + "/EditionsCrossword", CacheTime.Facia) + } } object DotcomRenderingService { diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 29751049d28..e9ea26293b8 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -32,6 +32,7 @@ object Dependencies { val commonsIo = "commons-io" % "commons-io" % "2.16.1" val cssParser = "net.sourceforge.cssparser" % "cssparser" % "0.9.30" val contentApiClient = "com.gu" %% "content-api-client" % capiVersion + val contentApiModelsJson = "com.gu" %% "content-api-models-json" % "25.1.0" val dfpAxis = "com.google.api-ads" % "dfp-axis" % "5.6.0" val faciaFapiScalaClient = "com.gu" %% "fapi-client-play30" % faciaVersion val identityCookie = "com.gu.identity" %% "identity-cookie" % identityLibVersion From 115f994fbee5e0c4f2f0802e0e15c7ddd6ecb32e Mon Sep 17 00:00:00 2001 From: DanielCliftonGuardian <110032454+DanielCliftonGuardian@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:59:29 +0000 Subject: [PATCH 03/17] Send to dcr --- .../controllers/CrosswordsController.scala | 49 +++++++------------ applications/conf/routes | 2 +- .../EditionsCrosswordRenderingDataModel.scala | 23 ++------- .../renderers/DotcomRenderingService.scala | 6 +-- 4 files changed, 26 insertions(+), 54 deletions(-) diff --git a/applications/app/controllers/CrosswordsController.scala b/applications/app/controllers/CrosswordsController.scala index 9d170e53d2b..3b52eadc9e5 100644 --- a/applications/app/controllers/CrosswordsController.scala +++ b/applications/app/controllers/CrosswordsController.scala @@ -302,38 +302,25 @@ class CrosswordEditionsController( ) extends BaseController with GuLogging with ImplicitControllerExecutionContext { - def digitalEdition: Action[AnyContent] = - Action.async { implicit request => - Future.successful( - Cached(CacheTime.Default)( - RevalidatableResult.Ok("Digital Edition Crossword Entry Point"), - ), - ) - } - def getCrosswords: Action[AnyContent] = Action.async { implicit request => - contentApiClient - .getResponse( - contentApiClient.item(s"crosswords"), - ) - .flatMap { response => - val crosswords = for { - results <- response.results - quick <- results.find(_.crossword.exists(_.`type` == Quick)).flatMap(_.crossword) - cryptic <- results.find(_.crossword.exists(_.`type` == Cryptic)).flatMap(_.crossword) - } yield (quick, cryptic) - - crosswords match { - case Some((quick, cryptic)) => - val crosswordPage = EditionsCrosswordRenderingDataModel(quick, cryptic) - remoteRenderer.getEditionsCrossword(wsClient, quick, cryptic) - Future.successful( - Cached(CacheTime.Default)( - RevalidatableResult.Ok(toJson(crosswordPage)), - ).as("application/json"), - ) - case None => Future.successful(NotFound) - } + def digitalEdition: Action[AnyContent] = Action.async { implicit request => + getCrosswords + .map(parseCrosswords) + .flatMap { + case Some(crosswordPage) => + remoteRenderer.getEditionsCrossword(wsClient, crosswordPage) + case None => Future.successful(NotFound) } } + + private lazy val crosswordsQuery = contentApiClient.item("crosswords") + + private def getCrosswords: Future[ItemResponse] = contentApiClient.getResponse(crosswordsQuery) + + private def parseCrosswords(response: ItemResponse): Option[EditionsCrosswordRenderingDataModel] = + for { + results <- response.results + quick <- results.find(_.crossword.exists(_.`type` == Quick)).flatMap(_.crossword) + cryptic <- results.find(_.crossword.exists(_.`type` == Cryptic)).flatMap(_.crossword) + } yield EditionsCrosswordRenderingDataModel(quick, cryptic) } diff --git a/applications/conf/routes b/applications/conf/routes index 2c0e804f64b..e17e9272bd6 100644 --- a/applications/conf/routes +++ b/applications/conf/routes @@ -29,7 +29,7 @@ GET /crosswords/lookup # Crosswords digital edition GET /crosswords/digital-edition controllers.CrosswordEditionsController.digitalEdition -GET /crosswordtest controllers.CrosswordEditionsController.getCrosswords + # Email paths GET /email/form/$emailType/$listId<[0-9]+> controllers.EmailSignupController.renderForm(emailType: String, listId: Int) GET /email/form/$emailType/:listName controllers.EmailSignupController.renderFormFromName(emailType: String, listName: String) diff --git a/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala b/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala index 11e938a0235..92cfff9ec8a 100644 --- a/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala +++ b/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala @@ -1,9 +1,8 @@ package model.dotcomrendering.pageElements import com.gu.contentapi.client.model.v1.Crossword -import model.dotcomrendering.DotcomRenderingUtils.withoutNull -import play.api.libs.json.{JsValue, Json, Writes} import com.gu.contentapi.json.CirceEncoders._ +import io.circe.JsonObject import io.circe.syntax._ case class EditionsCrosswordRenderingDataModel( @@ -12,22 +11,10 @@ case class EditionsCrosswordRenderingDataModel( ) object EditionsCrosswordRenderingDataModel { - // we Json.parse this into a JsValue to ensure we get the raw JSON - // from the Content API rather than a Json.stringified version - private def contentApiToJsonValue(crossword: Crossword): JsValue = { - Json.parse(crossword.asJson.toString()) - } - implicit val writes: Writes[EditionsCrosswordRenderingDataModel] = - new Writes[EditionsCrosswordRenderingDataModel] { - def writes(model: EditionsCrosswordRenderingDataModel) = { - Json.obj( - "quick" -> contentApiToJsonValue(model.quick), - "cryptic" -> contentApiToJsonValue(model.cryptic), - ) - } - } def toJson(model: EditionsCrosswordRenderingDataModel): String = { - val jsValue = Json.toJson(model) - Json.stringify(withoutNull(jsValue)) + JsonObject( + "quick" -> model.quick.asJson.dropNullValues, + "cryptic" -> model.cryptic.asJson.dropNullValues, + ).asJson.dropNullValues.noSpaces } } diff --git a/common/app/renderers/DotcomRenderingService.scala b/common/app/renderers/DotcomRenderingService.scala index 5b8ce3b78bd..36aabed2010 100644 --- a/common/app/renderers/DotcomRenderingService.scala +++ b/common/app/renderers/DotcomRenderingService.scala @@ -421,11 +421,9 @@ class DotcomRenderingService extends GuLogging with ResultWithPreconnectPreload def getEditionsCrossword( ws: WSClient, - quickCrossword: Crossword, - crypticCrossword: Crossword, + crosswords: EditionsCrosswordRenderingDataModel, )(implicit request: RequestHeader): Future[Result] = { - val dataModel = EditionsCrosswordRenderingDataModel(quickCrossword, crypticCrossword) - val json = EditionsCrosswordRenderingDataModel.toJson(dataModel) + val json = EditionsCrosswordRenderingDataModel.toJson(crosswords) post(ws, json, Configuration.rendering.articleBaseURL + "/EditionsCrossword", CacheTime.Facia) } } From 4b10e9d457204e83ff99b42fc5a60fa195367b4f Mon Sep 17 00:00:00 2001 From: Emmanuel Ferdman Date: Tue, 19 Nov 2024 02:40:27 -0800 Subject: [PATCH 04/17] update `000-structure-for-initial-milestone.md` reference Signed-off-by: Emmanuel Ferdman --- docs/01-start-here/05-development-tips.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/01-start-here/05-development-tips.md b/docs/01-start-here/05-development-tips.md index 64413a92c3d..c1a92532fe4 100644 --- a/docs/01-start-here/05-development-tips.md +++ b/docs/01-start-here/05-development-tips.md @@ -26,7 +26,7 @@ make validate ``` These will fix the linting issues to make sure you won't have any issue trying to push or with the simple parts of the build. -If you have already committed you can use `make fix-commits` to verify & fix your commited code. It's +If you have already committed you can use `make fix-commits` to verify & fix your committed code. It's faster than `make fix` but you will need to amend your previous commits to get a clean history. If you are wondering what other options make has, you can simply type `make` at the comment line. @@ -68,4 +68,4 @@ without having to configure the debugger yourself: ### Viewing AMP Pages -[Use DCR](https://github.com/guardian/dotcom-rendering/blob/main/docs/architecture/amp/000-structure-for-initial-milestone.md) +[Use DCR](https://github.com/guardian/dotcom-rendering/blob/main/dotcom-rendering/docs/architecture/amp/000-structure-for-initial-milestone.md) From 6b85086180493608758592c43e582652378b2858 Mon Sep 17 00:00:00 2001 From: Georges Lebreton <102960844+Georges-GNM@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:46:32 +0000 Subject: [PATCH 05/17] Add aspect ratio to frontend collection config --- common/app/model/CollectionConfig.scala | 4 ++++ project/Dependencies.scala | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/common/app/model/CollectionConfig.scala b/common/app/model/CollectionConfig.scala index d12150f9a9b..9cbe6101fa5 100644 --- a/common/app/model/CollectionConfig.scala +++ b/common/app/model/CollectionConfig.scala @@ -23,6 +23,7 @@ final case class CollectionConfig( hideShowMore: Boolean, displayHints: Option[DisplayHints], platform: Option[CollectionPlatform] = None, + aspectRatio: String, ) object CollectionConfig { @@ -53,6 +54,8 @@ object CollectionConfig { None } + val aspectRatio: String = fapi.CollectionConfig.AspectRatio.getAspectRatio(config.collectionType).label + CollectionConfig( displayName = config.displayName, backfill = config.backfill, @@ -73,6 +76,7 @@ object CollectionConfig { hideShowMore = config.hideShowMore, displayHints = config.displayHints.map(DisplayHints.make), platform = Some(config.platform), + aspectRatio = aspectRatio, ) } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 8974c0df116..7fdb3078ce5 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -33,7 +33,7 @@ object Dependencies { val cssParser = "net.sourceforge.cssparser" % "cssparser" % "0.9.30" val contentApiClient = "com.gu" %% "content-api-client" % capiVersion val dfpAxis = "com.google.api-ads" % "dfp-axis" % "5.6.0" - val faciaFapiScalaClient = "com.gu" %% "fapi-client-play30" % faciaVersion + val faciaFapiScalaClient = "com.gu" %% "fapi-client-play30" % "12.2.0-PREVIEW.glaspect-ratio.2024-11-19T1531.f7f1aaba" val identityCookie = "com.gu.identity" %% "identity-cookie" % identityLibVersion /** There can only be one version of `scala-xml`. We will evict all v1.x From a4fdc368652fc8a096c941ac5d1a2ccee530f6bb Mon Sep 17 00:00:00 2001 From: Georges Lebreton <102960844+Georges-GNM@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:34:02 +0000 Subject: [PATCH 06/17] update pressedcollectionbuilder test --- common/test/common/facia/PressedCollectionBuilder.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/common/test/common/facia/PressedCollectionBuilder.scala b/common/test/common/facia/PressedCollectionBuilder.scala index 4a9dc049156..63e3d7ea2cb 100644 --- a/common/test/common/facia/PressedCollectionBuilder.scala +++ b/common/test/common/facia/PressedCollectionBuilder.scala @@ -36,6 +36,7 @@ object PressedCollectionBuilder { showTimestamps = false, hideShowMore, displayHints = None, + aspectRatio = "5:3", ) PressedCollection( From b52515af85d88857a2973a47cd34c1c35572ea68 Mon Sep 17 00:00:00 2001 From: Georges Lebreton <102960844+Georges-GNM@users.noreply.github.com> Date: Wed, 20 Nov 2024 11:02:09 +0000 Subject: [PATCH 07/17] set facia version to preview release --- project/Dependencies.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 7fdb3078ce5..94d1b219a19 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -7,7 +7,7 @@ object Dependencies { val awsVersion = "1.12.758" val awsSdk2Version = "2.26.27" val capiVersion = "32.0.0" - val faciaVersion = "13.0.0" + val faciaVersion = "12.2.0-PREVIEW.glaspect-ratio.2024-11-19T1531.f7f1aaba" val dispatchVersion = "0.13.1" val romeVersion = "1.0" val jerseyVersion = "1.19.4" @@ -33,7 +33,7 @@ object Dependencies { val cssParser = "net.sourceforge.cssparser" % "cssparser" % "0.9.30" val contentApiClient = "com.gu" %% "content-api-client" % capiVersion val dfpAxis = "com.google.api-ads" % "dfp-axis" % "5.6.0" - val faciaFapiScalaClient = "com.gu" %% "fapi-client-play30" % "12.2.0-PREVIEW.glaspect-ratio.2024-11-19T1531.f7f1aaba" + val faciaFapiScalaClient = "com.gu" %% "fapi-client-play30" % faciaVersion val identityCookie = "com.gu.identity" %% "identity-cookie" % identityLibVersion /** There can only be one version of `scala-xml`. We will evict all v1.x From f6b8b9a1b76b56cd2446013377dd00ca3d162258 Mon Sep 17 00:00:00 2001 From: DanielCliftonGuardian <110032454+DanielCliftonGuardian@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:35:28 +0000 Subject: [PATCH 08/17] Update CrosswordsController.scala --- .../app/controllers/CrosswordsController.scala | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/applications/app/controllers/CrosswordsController.scala b/applications/app/controllers/CrosswordsController.scala index 3b52eadc9e5..48c16256bec 100644 --- a/applications/app/controllers/CrosswordsController.scala +++ b/applications/app/controllers/CrosswordsController.scala @@ -1,12 +1,10 @@ package controllers -import com.gu.contentapi.client.model.v1.Content.unsafeEmpty.crossword import com.gu.contentapi.client.model.v1.CrosswordType.{Cryptic, Quick} import com.gu.contentapi.client.model.v1.{Crossword, ItemResponse, Content => ApiContent, Section => ApiSection} import common.{Edition, GuLogging, ImplicitControllerExecutionContext} import conf.Static import contentapi.ContentApiClient -import pages.{CrosswordHtmlPage, IndexHtmlPage, PrintableCrosswordHtmlPage} import crosswords.{ AccessibleCrosswordPage, AccessibleCrosswordRows, @@ -16,20 +14,20 @@ import crosswords.{ CrosswordSearchPageWithResults, CrosswordSvg, } +import html.HtmlPageHelpers.ContentCSSFile import model.Cached.{RevalidatableResult, WithoutRevalidationResult} import model._ +import model.dotcomrendering.pageElements.EditionsCrosswordRenderingDataModel +import model.dotcomrendering.{DotcomRenderingDataModel, PageType} import org.joda.time.{DateTime, LocalDate} +import pages.{CrosswordHtmlPage, IndexHtmlPage, PrintableCrosswordHtmlPage} import play.api.data.Forms._ import play.api.data._ -import play.api.mvc.{Action, RequestHeader, Result, _} -import services.{IndexPage, IndexPageItem} -import html.HtmlPageHelpers.ContentCSSFile -import model.dotcomrendering.pageElements.EditionsCrosswordRenderingDataModel -import model.dotcomrendering.pageElements.EditionsCrosswordRenderingDataModel.toJson -import model.dotcomrendering.{DotcomRenderingDataModel, PageType} import play.api.libs.ws.WSClient +import play.api.mvc._ import renderers.DotcomRenderingService import services.dotcomrendering.{CrosswordsPicker, RemoteRender} +import services.{IndexPage, IndexPageItem} import scala.concurrent.Future import scala.concurrent.duration._ From 5349994491d24fa704a7deaba0bcdca87a9dcfc4 Mon Sep 17 00:00:00 2001 From: Jake Date: Wed, 20 Nov 2024 13:23:06 +0000 Subject: [PATCH 09/17] bump (#27627) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index baf711b3f15..db796d56dee 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@emotion/react": "11.11.1", "@emotion/styled": "^10.0.27", "@guardian/ab-core": "8.0.0", - "@guardian/commercial": "23.7.0", + "@guardian/commercial": "23.7.1", "@guardian/core-web-vitals": "6.0.0", "@guardian/eslint-config-typescript": "9.0.1", "@guardian/identity-auth": "3.0.0", diff --git a/yarn.lock b/yarn.lock index 5c17a2afecf..1ef4ebac67a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3607,9 +3607,9 @@ __metadata: languageName: node linkType: hard -"@guardian/commercial@npm:23.7.0": - version: 23.7.0 - resolution: "@guardian/commercial@npm:23.7.0" +"@guardian/commercial@npm:23.7.1": + version: 23.7.1 + resolution: "@guardian/commercial@npm:23.7.1" dependencies: "@guardian/prebid.js": "npm:8.52.0-8" "@octokit/core": "npm:^6.1.2" @@ -3626,7 +3626,7 @@ __metadata: "@guardian/libs": ^19.1.0 "@guardian/source": ^8.0.0 typescript: ~5.5.3 - checksum: 10c0/0cdff54bd95d094329fe9210a44c6717b36fd8fe364f4ebbd1a8d48eea929d883895b837e6257befa413d3da8ddec85519746bbd2bbcbce33d58d33d17203884 + checksum: 10c0/a065f7201a0c77831191b654c002b4c075b7626840bfcf45993bcaeab052c55f50abc424aca78eeefe4f89a4c2107786ddbdc5d4c41b29dacc6722da233ab537 languageName: node linkType: hard @@ -3699,7 +3699,7 @@ __metadata: "@emotion/react": "npm:11.11.1" "@emotion/styled": "npm:^10.0.27" "@guardian/ab-core": "npm:8.0.0" - "@guardian/commercial": "npm:23.7.0" + "@guardian/commercial": "npm:23.7.1" "@guardian/core-web-vitals": "npm:6.0.0" "@guardian/eslint-config-typescript": "npm:9.0.1" "@guardian/identity-auth": "npm:3.0.0" From cc8dd30194319ffd2a08e6c30f40909b98f9a567 Mon Sep 17 00:00:00 2001 From: DanielCliftonGuardian <110032454+DanielCliftonGuardian@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:51:50 +0000 Subject: [PATCH 10/17] Use CacheTime.Default --- common/app/renderers/DotcomRenderingService.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/app/renderers/DotcomRenderingService.scala b/common/app/renderers/DotcomRenderingService.scala index 36aabed2010..32d7e067a59 100644 --- a/common/app/renderers/DotcomRenderingService.scala +++ b/common/app/renderers/DotcomRenderingService.scala @@ -424,7 +424,7 @@ class DotcomRenderingService extends GuLogging with ResultWithPreconnectPreload crosswords: EditionsCrosswordRenderingDataModel, )(implicit request: RequestHeader): Future[Result] = { val json = EditionsCrosswordRenderingDataModel.toJson(crosswords) - post(ws, json, Configuration.rendering.articleBaseURL + "/EditionsCrossword", CacheTime.Facia) + post(ws, json, Configuration.rendering.articleBaseURL + "/EditionsCrossword", CacheTime.Default) } } From e40345294ea31ee0ad4b2a9c111e641596e414ff Mon Sep 17 00:00:00 2001 From: Demetrios Skamiotis Date: Wed, 20 Nov 2024 16:41:08 +0000 Subject: [PATCH 11/17] bump comercial version for gpid in prebid --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index db796d56dee..121e1ec389a 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@emotion/react": "11.11.1", "@emotion/styled": "^10.0.27", "@guardian/ab-core": "8.0.0", - "@guardian/commercial": "23.7.1", + "@guardian/commercial": "23.7.2", "@guardian/core-web-vitals": "6.0.0", "@guardian/eslint-config-typescript": "9.0.1", "@guardian/identity-auth": "3.0.0", diff --git a/yarn.lock b/yarn.lock index 1ef4ebac67a..51ba4918e91 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3607,9 +3607,9 @@ __metadata: languageName: node linkType: hard -"@guardian/commercial@npm:23.7.1": - version: 23.7.1 - resolution: "@guardian/commercial@npm:23.7.1" +"@guardian/commercial@npm:23.7.2": + version: 23.7.2 + resolution: "@guardian/commercial@npm:23.7.2" dependencies: "@guardian/prebid.js": "npm:8.52.0-8" "@octokit/core": "npm:^6.1.2" @@ -3626,7 +3626,7 @@ __metadata: "@guardian/libs": ^19.1.0 "@guardian/source": ^8.0.0 typescript: ~5.5.3 - checksum: 10c0/a065f7201a0c77831191b654c002b4c075b7626840bfcf45993bcaeab052c55f50abc424aca78eeefe4f89a4c2107786ddbdc5d4c41b29dacc6722da233ab537 + checksum: 10c0/bdf9180e0f21be2571e406c307ba4d8d5af343eccbc07ad1c81fd1124f670f87cf7ac1233f9695ee87af36ed09b747acd08fe78ff5b61a3c31cb74d1a907e5f9 languageName: node linkType: hard @@ -3699,7 +3699,7 @@ __metadata: "@emotion/react": "npm:11.11.1" "@emotion/styled": "npm:^10.0.27" "@guardian/ab-core": "npm:8.0.0" - "@guardian/commercial": "npm:23.7.1" + "@guardian/commercial": "npm:23.7.2" "@guardian/core-web-vitals": "npm:6.0.0" "@guardian/eslint-config-typescript": "npm:9.0.1" "@guardian/identity-auth": "npm:3.0.0" From 8202c3b860c64882578ae5fef084354581dd51f0 Mon Sep 17 00:00:00 2001 From: Dominik Lander Date: Thu, 21 Nov 2024 09:43:47 +0000 Subject: [PATCH 12/17] Add onwards content article test --- common/app/conf/switches/ABTestSwitches.scala | 13 +++++++++- .../tests/onwards-content-article.js | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 static/src/javascripts/projects/common/modules/experiments/tests/onwards-content-article.js diff --git a/common/app/conf/switches/ABTestSwitches.scala b/common/app/conf/switches/ABTestSwitches.scala index 4242553405b..3a1af373203 100644 --- a/common/app/conf/switches/ABTestSwitches.scala +++ b/common/app/conf/switches/ABTestSwitches.scala @@ -55,7 +55,18 @@ trait ABTestSwitches { "Test the impact of showing the user a component that highlights the Guardians journalism", owners = Seq(Owner.withEmail("dotcom.platform@guardian.co.uk")), safeState = Off, - sellByDate = Some(LocalDate.of(2024, 12, 18)), + sellByDate = Some(LocalDate.of(2025, 1, 29)), + exposeClientSide = true, + highImpact = false, + ) + + Switch( + ABTests, + "ab-onwards-content-article", + "Test the impact of showing the galleries onwards content component on article pages", + owners = Seq(Owner.withEmail("dotcom.platform@guardian.co.uk")), + safeState = Off, + sellByDate = Some(LocalDate.of(2025, 1, 29)), exposeClientSide = true, highImpact = false, ) diff --git a/static/src/javascripts/projects/common/modules/experiments/tests/onwards-content-article.js b/static/src/javascripts/projects/common/modules/experiments/tests/onwards-content-article.js new file mode 100644 index 00000000000..3cdf4fc812f --- /dev/null +++ b/static/src/javascripts/projects/common/modules/experiments/tests/onwards-content-article.js @@ -0,0 +1,24 @@ +export const onwardsContentArticle = { + id: 'onwardsContentArticle', + start: '2024-11-25', + expiry: '2025-01-29', + author: 'dotcom.platform@guardian.co.uk', + description: + 'Test the impact of showing the galleries onwards content component on article pages.', + audience: 0 / 100, + audienceOffset: 0 / 100, + audienceCriteria: 'Article pages', + successMeasure: + 'Users are more likely to click a link in the onward content component.', + canRun: () => true, + variants: [ + { + id: 'control', + test: () => {}, + }, + { + id: 'variant', + test: () => {}, + }, + ], +}; From 58b684a97fa88131799dd29250f7e478e5ad5379 Mon Sep 17 00:00:00 2001 From: Georges Lebreton <102960844+Georges-GNM@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:09:23 +0000 Subject: [PATCH 13/17] Use latest preview release --- common/app/model/CollectionConfig.scala | 2 +- project/Dependencies.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/app/model/CollectionConfig.scala b/common/app/model/CollectionConfig.scala index 9cbe6101fa5..a82d3bda3cd 100644 --- a/common/app/model/CollectionConfig.scala +++ b/common/app/model/CollectionConfig.scala @@ -54,7 +54,7 @@ object CollectionConfig { None } - val aspectRatio: String = fapi.CollectionConfig.AspectRatio.getAspectRatio(config.collectionType).label + val aspectRatio: String = fapi.CollectionConfig.getAspectRatio(config).label CollectionConfig( displayName = config.displayName, diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 94d1b219a19..1c6fb83a55d 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -7,7 +7,7 @@ object Dependencies { val awsVersion = "1.12.758" val awsSdk2Version = "2.26.27" val capiVersion = "32.0.0" - val faciaVersion = "12.2.0-PREVIEW.glaspect-ratio.2024-11-19T1531.f7f1aaba" + val faciaVersion = "13.1.0-PREVIEW.glaspect-ratio.2024-11-21T0922.ecaf8409" val dispatchVersion = "0.13.1" val romeVersion = "1.0" val jerseyVersion = "1.19.4" From 9ffd428bd833779636a0b435bf1c8193014b366a Mon Sep 17 00:00:00 2001 From: Georges Lebreton <102960844+Georges-GNM@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:27:51 +0000 Subject: [PATCH 14/17] Set aspect ratio as an option --- common/app/model/CollectionConfig.scala | 4 ++-- common/test/common/facia/PressedCollectionBuilder.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/app/model/CollectionConfig.scala b/common/app/model/CollectionConfig.scala index a82d3bda3cd..b00209afa24 100644 --- a/common/app/model/CollectionConfig.scala +++ b/common/app/model/CollectionConfig.scala @@ -23,7 +23,7 @@ final case class CollectionConfig( hideShowMore: Boolean, displayHints: Option[DisplayHints], platform: Option[CollectionPlatform] = None, - aspectRatio: String, + aspectRatio: Option[String], ) object CollectionConfig { @@ -76,7 +76,7 @@ object CollectionConfig { hideShowMore = config.hideShowMore, displayHints = config.displayHints.map(DisplayHints.make), platform = Some(config.platform), - aspectRatio = aspectRatio, + aspectRatio = Some(aspectRatio), ) } diff --git a/common/test/common/facia/PressedCollectionBuilder.scala b/common/test/common/facia/PressedCollectionBuilder.scala index 63e3d7ea2cb..8b4aa0d5a3e 100644 --- a/common/test/common/facia/PressedCollectionBuilder.scala +++ b/common/test/common/facia/PressedCollectionBuilder.scala @@ -36,7 +36,7 @@ object PressedCollectionBuilder { showTimestamps = false, hideShowMore, displayHints = None, - aspectRatio = "5:3", + aspectRatio = Some(""), ) PressedCollection( From ecfcb422b1f42b6ef223f2246a231c940a7d82c6 Mon Sep 17 00:00:00 2001 From: Emma Imber Date: Thu, 21 Nov 2024 16:54:44 +0000 Subject: [PATCH 15/17] Bump to 23.7.3 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 121e1ec389a..5a3fd001e17 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@emotion/react": "11.11.1", "@emotion/styled": "^10.0.27", "@guardian/ab-core": "8.0.0", - "@guardian/commercial": "23.7.2", + "@guardian/commercial": "23.7.3", "@guardian/core-web-vitals": "6.0.0", "@guardian/eslint-config-typescript": "9.0.1", "@guardian/identity-auth": "3.0.0", diff --git a/yarn.lock b/yarn.lock index 51ba4918e91..3ef977c3589 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3607,9 +3607,9 @@ __metadata: languageName: node linkType: hard -"@guardian/commercial@npm:23.7.2": - version: 23.7.2 - resolution: "@guardian/commercial@npm:23.7.2" +"@guardian/commercial@npm:23.7.3": + version: 23.7.3 + resolution: "@guardian/commercial@npm:23.7.3" dependencies: "@guardian/prebid.js": "npm:8.52.0-8" "@octokit/core": "npm:^6.1.2" @@ -3626,7 +3626,7 @@ __metadata: "@guardian/libs": ^19.1.0 "@guardian/source": ^8.0.0 typescript: ~5.5.3 - checksum: 10c0/bdf9180e0f21be2571e406c307ba4d8d5af343eccbc07ad1c81fd1124f670f87cf7ac1233f9695ee87af36ed09b747acd08fe78ff5b61a3c31cb74d1a907e5f9 + checksum: 10c0/96d76b6ebb1479a48d574ebd22f062875d00832252e21ba6aa1edc5f4f7df458dfe220898907dc73c4a4839dfdce2c73b0d83860239ebd5086d43880fe0b204f languageName: node linkType: hard @@ -3699,7 +3699,7 @@ __metadata: "@emotion/react": "npm:11.11.1" "@emotion/styled": "npm:^10.0.27" "@guardian/ab-core": "npm:8.0.0" - "@guardian/commercial": "npm:23.7.2" + "@guardian/commercial": "npm:23.7.3" "@guardian/core-web-vitals": "npm:6.0.0" "@guardian/eslint-config-typescript": "npm:9.0.1" "@guardian/identity-auth": "npm:3.0.0" From d8732929652b8328a54d800b12b39d49162706dc Mon Sep 17 00:00:00 2001 From: Ravi <7014230+arelra@users.noreply.github.com> Date: Sat, 23 Nov 2024 23:33:24 +0000 Subject: [PATCH 16/17] Update to @guardian/commercial@23.7.4 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 5a3fd001e17..fd9b5b8df55 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@emotion/react": "11.11.1", "@emotion/styled": "^10.0.27", "@guardian/ab-core": "8.0.0", - "@guardian/commercial": "23.7.3", + "@guardian/commercial": "23.7.4", "@guardian/core-web-vitals": "6.0.0", "@guardian/eslint-config-typescript": "9.0.1", "@guardian/identity-auth": "3.0.0", diff --git a/yarn.lock b/yarn.lock index 3ef977c3589..1e9a106e39b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3607,9 +3607,9 @@ __metadata: languageName: node linkType: hard -"@guardian/commercial@npm:23.7.3": - version: 23.7.3 - resolution: "@guardian/commercial@npm:23.7.3" +"@guardian/commercial@npm:23.7.4": + version: 23.7.4 + resolution: "@guardian/commercial@npm:23.7.4" dependencies: "@guardian/prebid.js": "npm:8.52.0-8" "@octokit/core": "npm:^6.1.2" @@ -3626,7 +3626,7 @@ __metadata: "@guardian/libs": ^19.1.0 "@guardian/source": ^8.0.0 typescript: ~5.5.3 - checksum: 10c0/96d76b6ebb1479a48d574ebd22f062875d00832252e21ba6aa1edc5f4f7df458dfe220898907dc73c4a4839dfdce2c73b0d83860239ebd5086d43880fe0b204f + checksum: 10c0/09fa6f6f237ff0a2bd81d4e9bf4203f4fe37bff33c963401217f5f5e513da505ccc9fab1284e8d732f8d77cff0927141fb7a67dfd60986f5fa91d27b47d5fd0a languageName: node linkType: hard @@ -3699,7 +3699,7 @@ __metadata: "@emotion/react": "npm:11.11.1" "@emotion/styled": "npm:^10.0.27" "@guardian/ab-core": "npm:8.0.0" - "@guardian/commercial": "npm:23.7.3" + "@guardian/commercial": "npm:23.7.4" "@guardian/core-web-vitals": "npm:6.0.0" "@guardian/eslint-config-typescript": "npm:9.0.1" "@guardian/identity-auth": "npm:3.0.0" From cb7d220481f663896ff414da9949fa42e9232592 Mon Sep 17 00:00:00 2001 From: Georges Lebreton <102960844+Georges-GNM@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:09:41 +0000 Subject: [PATCH 17/17] Use latest facia scala client release --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 1c6fb83a55d..5c3134f2b11 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -7,7 +7,7 @@ object Dependencies { val awsVersion = "1.12.758" val awsSdk2Version = "2.26.27" val capiVersion = "32.0.0" - val faciaVersion = "13.1.0-PREVIEW.glaspect-ratio.2024-11-21T0922.ecaf8409" + val faciaVersion = "13.1.0" val dispatchVersion = "0.13.1" val romeVersion = "1.0" val jerseyVersion = "1.19.4"