-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Format
to the Scala CAPI client
#312
Add Format
to the Scala CAPI client
#312
Conversation
Rendering platforms have moved to use the `Format` type to describe the format that rendered data should take. This includes three specific fields: - `Display` - `Design` - `Theme (Pillar/Special)` Currently the platforms handle the decision logic around how to construct this object on platform but ideally this will be done upstream in order to standardise across platforms and to simplify the parsing of data. In this commit I upstream the `Format` type to the CAPI Scala client. Changes: - Introduce the `Display`, `Theme` and `Design` traits and their associated `case object`s. - Refactor `CAPIModelEnrichment` to move code shared by `RichContent` and `Format` to the upper scope. - Reproduce the decision logic used by platforms to construct the `Format` object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like one of those nice clean input > output pieces of work where it might be useful to have some tests laid out at an earlier stage so that you work to make the tests pass.
I'm not normally a strict TDD evangelist but this does feel like a great place to take advantage of that pattern
client/src/main/scala/com.gu.contentapi.client/utils/CapiModelEnrichment.scala
Show resolved
Hide resolved
client/src/main/scala/com.gu.contentapi.client/utils/CapiModelEnrichment.scala
Outdated
Show resolved
Hide resolved
client/src/main/scala/com.gu.contentapi.client/utils/CapiModelEnrichment.scala
Outdated
Show resolved
Hide resolved
- Replicate the code used in Frontend and apps-rendering to determine the `ShowcaseDisplay` `Display`. - Tidy up code to make it easier to parse.
Looks good +1 |
This textbook rejection of a PR like this is "putting domain logic like this in a language specific API client is bad". But this PR has been extensively reviewed by the submitting teams and their motive is deduplication of code which is already in CAPI consumers. CAPI should approve this and we can roll forward to get it into the ideal place. |
Furthermore.... This will be a versioned release so if the teams submitting this PR can consume it immediately they will be doing the regression testing. Other consumers can stay on or revert back last good release if this causes issues. |
|
||
def isComment: ContentFilter = c => tagExistsWithId("tone/comment")(c) || tagExistsWithId("tone/letters")(c) | ||
val isDeadBlog: ContentFilter = content => !isLiveBloggingNow(content) && tagExistsWithId("tone/minutebyminute")(content) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll need guardian/types#83 to match up with Types
isReview -> ReviewDesign, | ||
tagExistsWithId("tone/analysis") -> AnalysisDesign, | ||
isCommentDesign -> CommentDesign, | ||
tagExistsWithId("tone/features") -> FeatureDesign, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are missing Letter
Design? https://github.com/guardian/types/blob/main/src/format.ts#L24
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good question. We don't currently have Letter
as a Design
in our decideDesign.ts
function.
@oliverlloyd do you know if whether @guardian/types
is correct or if DCR is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@guardian/types
trumps DCR. We haven't yet updated the version of the /types package we're using but when we do we will add support for Letter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Letter is a recent addition: guardian/types#69
tagExistsWithId("tone/matchreports") -> MatchReportDesign, | ||
tagExistsWithId("tone/interview") -> InterviewDesign, | ||
tagExistsWithId("tone/editorials") -> EditorialDesign, | ||
tagExistsWithId("tone/quizzes") -> QuizDesign, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we also missing Interactive
design? https://github.com/guardian/types/blob/main/src/format.ts#L32
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we technically support an Interactive
design on DCR? It's not in our decideDesign
function at least. If it does need supporting, I can add it in here and that way we'll just need to add it to the decideDesign
function to translate it from the Scala JSON output to whatever Typescript needs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the be an Interactive
Design
type? I'm not sure what it represents? @JamieB-gu is there a need for this in Apps or could we remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's in the apps-rendering decision functions, so I'll add it in. If it's in here and then removed, it's not a difficult thing to rip out (which is part of the motivation for this work in the first place).
I think that the work here should be done with a focus on targeting a specific version of @guardian/types
, and at this point this is ever so slightly ahead of the current version by having different Design
s for dead and live blogs, as well as removing the Column
display type. But after this initial step of aligning the two, the goal should be to update the two in parallel, with references to the appropriate version of each within the changelog
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Design.Interactive
is at the moment derived from ContentType.INTERACTIVE
. I believe it's there so that we can build the empty placeholder articles for full-page interactives (ng-interactive
/type/interactive
- example here). Note that we explicitly render these without any styles because the interactive code takes over.
I'm curious as to how DCR models these kinds of articles if it doesn't use the Design
🤔?
isImmersive -> ImmersiveDisplay, | ||
isShowcase -> ShowcaseDisplay, | ||
isNumberedList -> NumberedListDisplay |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A note here that we need to update https://github.com/guardian/types/blob/main/src/format.ts#L37-L43 to remove Column
Display.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with the commentary where we acknowledge that this isn't the ideal resting place for this functionality, and I have no objections to using it as a temporary measure prior to relocating into tools and CAPI. It looks like a well enough isolated change and test coverage looks good too. I can't comment on the intricacies of relationships between types / DCR / dotcom etc, so I'll approve on the basis that you're all happy that everything is covered before you merge 👍
Does this mean moving it into the Thrift definitions? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice! Very pleased that this is starting to make its way upstream 😀
|
||
val isImmersive: ContentFilter = c => c.fields.flatMap(_.displayHint).contains("immersive") | ||
val isMedia: ContentFilter = content => tagExistsWithId("type/audio")(content) || tagExistsWithId("type/video")(content) || tagExistsWithId("type/gallery")(content) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AR also has type/picture
in this category, see guardian/apps-rendering#1146.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this. I'll add it to a card for changes to make on a future version
|
||
val defaultDesign: Design = ArticleDesign | ||
|
||
val isPhotoEssay: ContentFilter = content => content.fields.flatMap(_.displayHint).contains("photoessay") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you want to reuse your displayHintExistsWithName
function here?
val isPhotoEssay: ContentFilter = content => displayHintExistsWithName("photoessay")(content)
tagExistsWithId("tone/editorials") -> EditorialDesign, | ||
tagExistsWithId("tone/quizzes") -> QuizDesign, | ||
isInteractive -> InteractiveDesign, | ||
isPhotoEssay -> PhotoEssayDesign, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@oliverlloyd are we keeping Photo Essays as a separate Design
, or is this temporary until we subsume MultiImage into a normal body element?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is still at least one design aspects of Photo Essays that is unique: coloured captions. So unless we lose that it's here to stay
|
||
def isPillar(pillar: String): ContentFilter = content => content.pillarName.contains(pillar) | ||
|
||
val isSpecialReport: ContentFilter = content => content.tags.exists(t => specialReportTags(t.id)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens for special reports assigned in the targeting tool?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I did this off the back of different decision functions I found across the different codebases. If there's one missing, then we'll need to implement it in a future version. I imagine the process of integrating this all into the platforms will highlight missing areas and then we can update this to reflect that .
It should do, yes. I guess we (platforms) all need to have a discussion as to how we do this, then standardise on it and move forwards |
What does this change?
Rendering platforms have moved to use the
Format
type to describe theformat that rendered data should take. This includes three specific
fields:
Display
Design
Theme (Pillar/Special)
Currently the platforms handle the decision logic around how to
construct this object on platform but ideally this will be done upstream
in order to standardise across platforms and to simplify the parsing of
data.
Here I upstream the
Format
type to the CAPI Scala client.Changes:
Display
,Theme
andDesign
traits and theirassociated
case object
s.CAPIModelEnrichment
to move code shared byRichContent
and
Format
to the upper scope.Format
object.How to test
I've added unit tests for this and they can be run using whatever testing process you prefer e.g.
sbt test
How can we measure success?
Improved DevX for anyone working with the
Format
type, and ideally tidy refactors of the platform code to use this instead of multiple checks and flags.Have we considered potential risks?
I don't think there are any risks. This doesn't affect the raw data and shouldn't remove backwards compatibility.