paginate videos

pull/382/head
Thibault Duplessis 2015-03-22 19:15:35 +01:00
parent 60d3191e74
commit 0bb0db7784
8 changed files with 72 additions and 36 deletions

View File

@ -24,7 +24,7 @@ object Video extends LilaController {
}
private def renderIndex(control: UserControl)(implicit ctx: Context) =
env.api.video.byTags(control.filter.tags, 15) map { videos =>
env.api.video.byTags(control.filter.tags, getInt("page") | 1) map { videos =>
Ok(html.video.index(videos, control))
}
@ -50,7 +50,7 @@ object Video extends LilaController {
def author(author: String) = Open { implicit ctx =>
WithUserControl { control =>
env.api.video byAuthor author map { videos =>
env.api.video.byAuthor(author, getInt("page") | 1) map { videos =>
Ok(html.video.author(author, videos, control))
}
}

View File

@ -1,4 +1,4 @@
@(author: String, videos: List[lila.video.Video], control: lila.video.UserControl)(implicit ctx: Context)
@(author: String, videos: Paginator[lila.video.Video], control: lila.video.UserControl)(implicit ctx: Context)
@layout(
title = s"$author • Free Chess Videos",
@ -7,12 +7,17 @@ control = control) {
<div class="content_box_top">
<a class="is4 text lichess_title" data-icon="i" href="@routes.Video.index?@control.filter.queryString"></a>
<h1 class="lichess_title">
@author • @pluralize("video", videos.size) found
@author • @pluralize("video", videos.nbResults) found
</h1>
</div>
<div class="list">
@videos.map { video =>
<div class="list infinitescroll">
@videos.currentPageResults.map { video =>
@card(video, control)
}
@videos.nextPage.map { next =>
<div class="pager none">
<a href="@routes.Video.author(author)?@control.filter.queryString&page=@next">Next</a>
</div>
}
</div>
}

View File

@ -1,6 +1,6 @@
@(video: lila.video.Video, control: lila.video.UserControl)(implicit ctx: Context)
<a class="card" href="@routes.Video.show(video.id)?@control.filter.queryString">
<a class="card paginated_element" href="@routes.Video.show(video.id)?@control.filter.queryString">
<span class="img" style="background-image: url(@video.thumbnail)"></span>
<span class="info">
<span class="title">@video.title</span>

View File

@ -1,4 +1,4 @@
@(videos: List[lila.video.Video], control: lila.video.UserControl)(implicit ctx: Context)
@(videos: Paginator[lila.video.Video], control: lila.video.UserControl)(implicit ctx: Context)
@layout(
title = "Free Chess Videos",
@ -7,19 +7,24 @@ control = control) {
<div class="content_box_top">
<h1 data-icon="@openingBrace" class="is4 text lichess_title">
@if(control.filter.tags.nonEmpty) {
@pluralize("video", videos.size) found
@pluralize("video", videos.nbResults) found
} else {
Video library
}
</h1>
</div>
<div class="list">
@videos.map { video =>
@if(control.filter.tags.isEmpty) {
<p class="explain">
All videos are free for everyone. Click one or many tags on the left to filter.
</p>
}
<div class="list infinitescroll">
@videos.currentPageResults.map { video =>
@card(video, control)
}
@if(videos.size < 4) {
<div class="not_much nb_@videos.size">
@if(videos.isEmpty) {
@if(videos.currentPageResults.size < 4) {
<div class="not_much nb_@videos.nbResults">
@if(videos.currentPageResults.isEmpty) {
No videos for these tags!
} else {
That's all we got for these tags!
@ -29,5 +34,10 @@ control = control) {
<a href="@routes.Video.index" class="button">Clear search</a>
</div>
}
@videos.nextPage.map { next =>
<div class="pager none">
<a href="@routes.Video.index?@control.filter.queryString&page=@next">Next</a>
</div>
}
</div>
}

View File

@ -15,7 +15,7 @@
}
@evenMoreJs = {
@jsTag("video.js")
@jsTag("vendor/jquery.infinitescroll.min.js")
}
@base.layout(

View File

@ -6,6 +6,8 @@ import reactivemongo.core.commands._
import scala.concurrent.duration._
import spray.caching.{ LruCache, Cache }
import lila.common.paginator._
import lila.db.paginator.BSONAdapter
import lila.db.Types.Coll
import lila.user.{ User, UserRepo }
@ -26,6 +28,8 @@ private[video] final class VideoApi(
object video {
private val maxPerPage = 15
def find(id: Video.ID): Fu[Option[Video]] =
videoColl.find(BSONDocument("_id" -> id)).one[Video]
@ -55,28 +59,39 @@ private[video] final class VideoApi(
doc flatMap (_.getAs[String]("_id"))
}
def popular(max: Int): Fu[List[Video]] =
videoColl.find(BSONDocument())
.sort(BSONDocument("metadata.likes" -> -1))
.cursor[Video]
.collect[List](max)
def popular(page: Int): Fu[Paginator[Video]] = Paginator(
adapter = new BSONAdapter[Video](
collection = videoColl,
selector = BSONDocument(),
sort = BSONDocument("metadata.likes" -> -1)
),
currentPage = page,
maxPerPage = maxPerPage)
def byTags(tags: List[Tag], max: Int): Fu[List[Video]] =
if (tags.isEmpty) popular(max)
else videoColl.find(BSONDocument(
"tags" -> BSONDocument("$all" -> tags)
)).sort(BSONDocument(
"metadata.likes" -> -1
)).cursor[Video]
.collect[List]()
def byTags(tags: List[Tag], page: Int): Fu[Paginator[Video]] =
if (tags.isEmpty) popular(page)
else Paginator(
adapter = new BSONAdapter[Video](
collection = videoColl,
selector = BSONDocument(
"tags" -> BSONDocument("$all" -> tags)
),
sort = BSONDocument("metadata.likes" -> -1)
),
currentPage = page,
maxPerPage = maxPerPage)
def byAuthor(author: String): Fu[List[Video]] =
videoColl.find(BSONDocument(
"author" -> author
)).sort(BSONDocument(
"metadata.likes" -> -1
)).cursor[Video]
.collect[List]()
def byAuthor(author: String, page: Int): Fu[Paginator[Video]] =
Paginator(
adapter = new BSONAdapter[Video](
collection = videoColl,
selector = BSONDocument(
"author" -> author
),
sort = BSONDocument("metadata.likes" -> -1)
),
currentPage = page,
maxPerPage = maxPerPage)
def similar(video: Video, max: Int): Fu[List[Video]] =
videoColl.find(BSONDocument(
@ -112,7 +127,9 @@ private[video] final class VideoApi(
def popularAnd(max: Int, forced: List[Tag]): Fu[List[TagNb]] = popular map { all =>
val tags = all take max
val missing = forced filterNot tags.contains
val missing = forced filterNot { t =>
tags exists (_.tag == t)
}
tags.take(max - missing.size) ::: missing.flatMap { t =>
all find (_.tag == t)
}

View File

@ -143,3 +143,7 @@
#video .not_much.nb_0 {
margin-top: 200px;
}
#video .explain {
text-align: center;
margin: 50px 0 35px 0;
}