common/app/model/trails.scala (102 lines of code) (raw):
package model
import com.gu.contentapi.client.model.{v1 => contentapi}
import implicits.Dates._
import org.joda.time.DateTime
import com.github.nscala_time.time.Implicits._
import play.api.libs.json.{JodaWrites, JsBoolean, JsString, JsValue, Json}
import play.api.mvc.RequestHeader
import views.support.{ImgSrc, Naked}
/** additional information needed to display something on a facia page from CAPI
*/
object Trail {
private val trailPicMinDesiredSize = 460
// if you change these rules make sure you update IMAGES.md (in this project)
private def findTrailImages(elements: Elements): Option[ImageMedia] = {
// Try to pick a thumbnail element which contains an image with at least 460 width.
val trailImageMedia = elements.thumbnail
.find(_.images.imageCrops.exists(_.width >= trailPicMinDesiredSize))
.map(_.images)
.orElse(elements.mainPicture.map(_.images))
.orElse(elements.videos.headOption.map(_.images))
.orElse(elements.thumbnail.map(_.images))
// Try to take the master image (5:4 or 5:3). At render-time, the image resizing service will size the image according to card width.
// Filtering the list images here means that facia-press does not need to slim down the Trail object.
trailImageMedia.flatMap { imageMedia =>
val filteredTrailImages = imageMedia.allImages.filter { image =>
IsRatio(5, 4, image.width, image.height) || IsRatio(5, 3, image.width, image.height)
}
val masterTrailImage = filteredTrailImages.find(_.isMaster).map { master =>
ImageMedia.make(List(master))
}
// If there isn't a 5:4 or 5:3 image, no ImageMedia object will be created.
lazy val largestTrailImage = filteredTrailImages.sortBy(-_.width).headOption.map { bestImage =>
ImageMedia.make(List(bestImage))
}
// Choose the master image (5:4 or 5:3), or the largest image (5:4 or 5:3).
masterTrailImage.orElse(largestTrailImage)
}
}
def make(
tags: Tags,
fields: Fields,
commercial: Commercial,
elements: Elements,
metadata: MetaData,
apiContent: contentapi.Content,
): Trail = {
Trail(
webPublicationDate = apiContent.webPublicationDate.map(_.toJoda).getOrElse(DateTime.now),
headline = apiContent.fields.flatMap(_.headline).getOrElse(""),
sectionName = apiContent.sectionName.getOrElse(""),
thumbnailPath = apiContent.fields.flatMap(_.thumbnail).map(ImgSrc(_, Naked)),
isCommentable = apiContent.fields.flatMap(_.commentable).exists(b => b),
isClosedForComments = !apiContent.fields.flatMap(_.commentCloseDate).map(_.toJoda).exists(_.isAfterNow),
byline = apiContent.fields.flatMap(_.byline).map(stripHtml),
trailPicture = findTrailImages(elements),
tags = tags,
commercial = commercial,
fields = fields,
metadata = metadata,
elements = elements,
)
}
}
final case class Trail(
tags: Tags,
commercial: Commercial,
fields: Fields,
metadata: MetaData,
elements: Elements,
webPublicationDate: DateTime,
headline: String,
byline: Option[String],
sectionName: String,
trailPicture: Option[ImageMedia],
thumbnailPath: Option[String] = None,
discussionId: Option[String] = None,
isCommentable: Boolean = false,
isClosedForComments: Boolean = false,
) {
/** TODO - this should be set in the Facia tool */
lazy val showByline: Boolean = tags.isComment
def shouldHidePublicationDate(implicit request: RequestHeader): Boolean = {
val isPaidContent = metadata.commercial.exists(_.isPaidContent)
isPaidContent && webPublicationDate.isOlderThan(2.weeks)
}
def faciaUrl: Option[String] =
this match {
case t: Trail => Option(t.metadata.url)
}
lazy val trailType: Option[String] = {
if (tags.tags.exists(_.id == "tone/comment")) {
Option("comment")
} else if (tags.tags.exists(_.id == "tone/features")) {
Option("feature")
} else {
Option("news")
}
}
implicit val dateToTimestampWrites: JodaWrites.JodaDateTimeNumberWrites.type =
play.api.libs.json.JodaWrites.JodaDateTimeNumberWrites
def javascriptConfig: Map[String, JsValue] =
Map(
("sectionName", JsString(sectionName)),
("thumbnail", thumbnailPath.map(JsString.apply).getOrElse(JsBoolean(false))),
("isLive", JsBoolean(fields.isLive)),
("webPublicationDate", Json.toJson(webPublicationDate)),
("headline", JsString(headline)),
("commentable", JsBoolean(isCommentable)),
("byline", JsString(byline.getOrElse(""))),
)
}