FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Revert "Revert "live blog block-level permalinks"" · devhttps/frontend@b9064c4 · GitHub

Commit b9064c4

Browse files
committed
Revert "Revert "live blog block-level permalinks""
1 parent 5a0c22c commit b9064c4

11 files changed

Lines changed: 229 additions & 135 deletions

File tree

‎article/app/controllers/ArticleController.scala‎

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package controllers
22

3+
import _root_.liveblog.LiveBlogPageModel
34
import com.gu.contentapi.client.model.ItemResponse
45
import com.gu.contentapi.client.model.v1.{Content => ApiContent}
56
import com.gu.util.liveblogs.{Block, BlockToText}
@@ -8,9 +9,8 @@ import conf.LiveContentApi.getResponse
89
import conf._
910
import conf.switches.Switches
1011
import conf.switches.Switches.LongCacheSwitch
11-
import liveblog.BodyBlocks
1212
import model._
13-
import model.liveblog.KeyEventData
13+
import model.liveblog.{BodyBlock, KeyEventData}
1414
import org.joda.time.DateTime
1515
import performance.MemcachedAction
1616
import play.api.libs.functional.syntax._
@@ -19,6 +19,7 @@ import play.api.mvc._
1919
import views.support._
2020

2121
import scala.concurrent.Future
22+
import scala.util.parsing.combinator.RegexParsers
2223

2324
trait PageWithStoryPackage extends ContentPage {
2425
def article: Article
@@ -35,7 +36,7 @@ object ArticleController extends Controller with RendersItemResponse with Loggin
3536
override def canRender(i: ItemResponse): Boolean = i.content.exists(isSupported)
3637
override def renderItem(path: String)(implicit request: RequestHeader): Future[Result] = mapModel(path, blocks = true)(render(path, _, None))
3738

38-
private def renderLatestFrom(page: PageWithStoryPackage, lastUpdateBlockId: String, isLivePage: Option[Boolean])(implicit request: RequestHeader) = {
39+
private def renderNewerUpdates(page: PageWithStoryPackage, lastUpdateBlockId: String, isLivePage: Option[Boolean])(implicit request: RequestHeader) = {
3940
val newBlocks = page.article.fields.blocks.takeWhile(block => s"block-${block.id}" != lastUpdateBlockId)
4041
val blocksHtml = views.html.liveblog.liveBlogBlocks(newBlocks, page.article, Edition(request).timezone)
4142
val timelineHtml = views.html.liveblog.keyEvents("", KeyEventData(newBlocks, Edition(request).timezone))
@@ -72,19 +73,37 @@ object ArticleController extends Controller with RendersItemResponse with Loggin
7273

7374
}
7475

75-
private def render(path: String, page: PageWithStoryPackage, pageNo: Option[Int])(implicit request: RequestHeader) = page match {
76+
private def renderPageWithBlock(
77+
maybeRequiredBlockId: Option[String],
78+
blog: LiveBlogPage,
79+
modelGen: (Option[(BodyBlock) => Boolean], (BodyBlock) => String) => Option[LiveBlogPageModel[BodyBlock]]
80+
)(implicit request: RequestHeader) =
81+
modelGen(
82+
maybeRequiredBlockId.map(blockId => block => blockId == block.id),
83+
_.id
84+
) match {
85+
case Some(blocks) =>
86+
val htmlResponse = () => views.html.liveBlog (blog, blocks)
87+
val jsonResponse = () => views.html.liveblog.liveBlogBody (blog, blocks)
88+
renderFormat(htmlResponse, jsonResponse, blog, Switches.all)
89+
case None => NotFound
90+
}
91+
92+
private def render(path: String, page: PageWithStoryPackage, pageParam: Option[String])(implicit request: RequestHeader) = page match {
7693
case blog: LiveBlogPage =>
7794
if (request.isAmp) {
7895
NotFound
7996
} else {
8097
val pageSize = if (blog.article.content.tags.tags.map(_.id).contains("sport/sport")) 50 else 10
81-
val blocks = BodyBlocks(pageSize = pageSize, extrasOnFirstPage = 10)(blog.article.content.fields.blocks, pageNo)
82-
blocks match {
83-
case Some(blocks) =>
84-
val htmlResponse = () => views.html.liveBlog (blog, blocks)
85-
val jsonResponse = () => views.html.liveblog.liveBlogBody (blog, blocks)
86-
renderFormat(htmlResponse, jsonResponse, blog, Switches.all)
87-
case None => NotFound
98+
val modelGen = LiveBlogPageModel(
99+
pageSize = pageSize,
100+
extrasOnFirstPage = 10,
101+
blog.article.content.fields.blocks
102+
)_
103+
pageParam.map(new PageParser().blockId) match {
104+
case Some(None) => NotFound
105+
case Some(Some(requiredBlockId)) => renderPageWithBlock(Some(requiredBlockId), blog, modelGen)
106+
case None => renderPageWithBlock(None, blog, modelGen)
88107
}
89108
}
90109

@@ -100,7 +119,7 @@ object ArticleController extends Controller with RendersItemResponse with Loggin
100119
renderFormat(htmlResponse, jsonResponse, article, Switches.all)
101120
}
102121

103-
def renderLiveBlog(path: String, page: Option[Int] = None) =
122+
def renderLiveBlog(path: String, page: Option[String] = None) =
104123
LongCacheAction { implicit request =>
105124
mapModel(path, blocks = true) {// temporarily only ask for blocks too for things we know are new live blogs until until the migration is done and we can always use blocks
106125
render(path, _, page)
@@ -111,7 +130,7 @@ object ArticleController extends Controller with RendersItemResponse with Loggin
111130
LongCacheAction { implicit request =>
112131
mapModel(path, blocks = true) { model =>
113132
(lastUpdate, rendered) match {
114-
case (Some(lastUpdate), _) => renderLatestFrom(model, lastUpdate, isLivePage)
133+
case (Some(lastUpdate), _) => renderNewerUpdates(model, lastUpdate, isLivePage)
115134
case (None, Some(false)) => blockText(model, 6)
116135
case (_, _) => render(path, model, None)
117136
}
@@ -184,3 +203,17 @@ object LongCacheAction {
184203
}
185204
}
186205
}
206+
207+
class PageParser extends RegexParsers {
208+
def blockId(input: String): Option[String] = {
209+
def withParser: Parser[Unit] = "with:" ^^ { _ => () }
210+
def block: Parser[Unit] = "block-" ^^ { _ => () }
211+
def id: Parser[String] = "[a-zA-Z0-9]+".r
212+
def expr: Parser[String] = withParser ~> block ~> id
213+
214+
parse(expr, input) match {
215+
case Success(matched, _) => Some(matched)
216+
case _ => None
217+
}
218+
}
219+
}

‎article/app/liveblog/BodyBlocks.scala‎

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package liveblog
2+
3+
object LiveBlogPageModel {
4+
5+
def apply[B](pageSize: Int, extrasOnFirstPage: Int, blocks: Seq[B])(isRequestedBlock: Option[B => Boolean], id: B => String): Option[LiveBlogPageModel[_ <: B]] = {
6+
val (main, pages) = getPages(pageSize, extrasOnFirstPage, blocks)
7+
val noPage = BlockInfo(Nil/*ignored*/, NoPage)
8+
val endedPages = noPage :: BlockInfo(main, FirstPage) :: (pages.map(page => BlockInfo(page, BlockPage(id(page.head)))) :+ noPage)
9+
10+
def hasRequestedBlock(page: LiveBlogPageModel[_ <: B]): Boolean = {
11+
page.blocks.exists(isRequestedBlock.getOrElse(_ => true))
12+
}
13+
14+
endedPages.sliding(3).toList.map {
15+
case List(later, curr, earlier) =>
16+
LiveBlogPageModel(curr.page, main, later.self, earlier.self, curr.self)
17+
}.find(hasRequestedBlock)
18+
}
19+
20+
// returns the pages, newest at the end, newest at the start
21+
def getPages[B](pageSize: Int, extrasOnFirstPage: Int, blocks: Seq[B]): (Seq[B], List[Seq[B]]) = {
22+
val length = blocks.size
23+
val remainder = extrasOnFirstPage + (length % pageSize)
24+
val (main, rest) = blocks.splitAt(remainder + pageSize)
25+
(main, rest.grouped(pageSize).toList)
26+
}
27+
28+
}
29+
30+
case class BlockInfo[B](page: Seq[B], self: PageReference)
31+
32+
case class LiveBlogPageModel[+B](blocks: Seq[B], main: Seq[B]/*for key events - TODO remove*/, later: PageReference, earlier: PageReference, canonical: PageReference)
33+
34+
sealed trait PageReference {
35+
def suffix: Option[String]
36+
}
37+
case object NoPage extends PageReference { val suffix = None }
38+
case object FirstPage extends PageReference { val suffix = Some("") }
39+
case class BlockPage(blockId: String) extends PageReference { val suffix = Some(s"?page=with:block-$blockId") }

‎article/app/views/liveBlog.scala.html‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
@import _root_.liveblog.BodyBlocks
1+
@import _root_.liveblog.LiveBlogPageModel
22
@import model.liveblog.BodyBlock
3-
@(model: LiveBlogPage, blocks: BodyBlocks[BodyBlock])(implicit request: RequestHeader)
3+
@(model: LiveBlogPage, blocks: LiveBlogPageModel[BodyBlock])(implicit request: RequestHeader)
44

55
@import common.LinkTo
66

77
@main(model){
8-
@blocks.earlier.map { earlierBlock =>
9-
<link rel="next" href="@LinkTo{ /@{model.article.content.metadata.id}?page=@earlierBlock }">
8+
@blocks.earlier.suffix.map { suffix =>
9+
<link rel="next" href="@LinkTo{ /@{model.article.content.metadata.id}@suffix }">
1010
}
1111
@blocks.later.suffix.map { suffix =>
1212
<link rel="prev" href="@LinkTo{ /@{model.article.content.metadata.id}@suffix }">

‎article/app/views/liveblog/liveBlogBlocks.scala.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
@blocks.map { block =>
1111
<div id="block-@block.id" class="block@block.eventClass" itemprop="liveBlogUpdate" itemscope="" itemtype="http://schema.org/BlogPosting">
1212
<p class="block-time published-time">
13-
<a href="#block-@block.id" itemprop="url" class="block-time__link">
13+
<a href="/@article.metadata.id?page=with:block-@block.id#block-@block.id" itemprop="url" class="block-time__link">
1414
@views.html.liveblog.dateBlock(block.publishedCreatedDate(timezone))
1515
</a>
1616
</p>

‎article/app/views/liveblog/liveBlogBody.scala.html‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
@import _root_.liveblog.BodyBlocks
1+
@import _root_.liveblog.LiveBlogPageModel
22
@import model.liveblog.BodyBlock
33
@import model.liveblog.KeyEventData
4-
@(model: LiveBlogPage, blocks: BodyBlocks[BodyBlock])(implicit request: RequestHeader)
4+
@(model: LiveBlogPage, blocks: LiveBlogPageModel[BodyBlock])(implicit request: RequestHeader)
55

66
@import common.LinkTo
77
@import layout.{FaciaCardAndIndex, ItemClasses}
@@ -87,8 +87,8 @@ <h1 itemprop="headline" class="content__headline js-score">@Html(article.trail.h
8787
</div>
8888

8989
<div class="live-navigation">
90-
@blocks.earlier.map { earlierBlock =>
91-
<a href="/@{article.content.metadata.id}?page=@earlierBlock"
90+
@blocks.earlier.suffix.map { suffix =>
91+
<a href="/@{article.content.metadata.id}@suffix"
9292
class="u-button-reset button button--large button--show-more liveblog__show-more"
9393
data-link-name="next page">
9494
Go to older updates

‎article/conf/routes‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ GET /*path.json controllers.ArticleController.renderJson(pat
2525
GET /*path/amp controllers.ArticleController.renderArticle(path)
2626
GET /*path/email controllers.ArticleController.renderArticle(path)
2727
# temp route for live blogs so we can paginate without getting the blocks for all articles
28-
GET /$path<[^/]+/([^/]+/)?live/.*> controllers.ArticleController.renderLiveBlog(path, page: Option[Int])
28+
GET /$path<[^/]+/([^/]+/)?live/.*> controllers.ArticleController.renderLiveBlog(path, page: Option[String])
2929
GET /*path controllers.ArticleController.renderArticle(path)

‎article/test/liveblog/BodyBlocksTest.scala‎

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL