improve navigation in videos
This commit is contained in:
parent
2c7e6e53aa
commit
436ea7e89b
|
@ -16,26 +16,18 @@ object Video extends LilaController {
|
|||
|
||||
private def WithUserControl[A](f: UserControl => Fu[A])(implicit ctx: Context): Fu[A] = {
|
||||
val reqTags = get("tags") ?? (_.split(',').toList.map(_.trim.toLowerCase))
|
||||
env.api.tag.pathsAnd(30, reqTags) map { tags =>
|
||||
UserControl(
|
||||
filter = Filter(reqTags),
|
||||
tags = tags)
|
||||
env.api.tag.paths(reqTags) map { tags =>
|
||||
UserControl(filter = Filter(reqTags), tags = tags)
|
||||
} flatMap f
|
||||
}
|
||||
|
||||
private def renderIndex(control: UserControl)(implicit ctx: Context) =
|
||||
def index = Open { implicit ctx =>
|
||||
WithUserControl { control =>
|
||||
env.api.video.byTags(control.filter.tags, getInt("page") | 1) zip
|
||||
env.api.video.count.apply map {
|
||||
case (videos, count) =>
|
||||
Ok(html.video.index(videos, count, control))
|
||||
}
|
||||
|
||||
def index = Open { implicit ctx =>
|
||||
WithUserControl { control =>
|
||||
val filter = control.filter.copy(
|
||||
tags = get("tags") ?? (_.split(',').toList.map(_.trim.toLowerCase))
|
||||
)
|
||||
renderIndex(control.copy(filter = filter))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
}
|
||||
}
|
||||
</div>
|
||||
@if(control.filter.tags.nonEmpty) {
|
||||
<div class="under_tags">
|
||||
<a class="button" href="@routes.Video.index">Clear search</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
@ -47,10 +47,6 @@ final class Env(
|
|||
youtube.updateAll logFailure "video youtube"
|
||||
}
|
||||
|
||||
scheduler.once(15 seconds) {
|
||||
sheet.fetchAll >> youtube.updateAll logFailure "video boot"
|
||||
}
|
||||
|
||||
private[video] lazy val videoColl = db(CollectionVideo)
|
||||
private[video] lazy val viewColl = db(CollectionView)
|
||||
private[video] lazy val filterColl = db(CollectionFilter)
|
||||
|
|
|
@ -4,11 +4,11 @@ import org.joda.time.DateTime
|
|||
import reactivemongo.bson._
|
||||
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.memo.AsyncCache
|
||||
import lila.user.{ User, UserRepo }
|
||||
|
||||
private[video] final class VideoApi(
|
||||
|
@ -104,13 +104,14 @@ private[video] final class VideoApi(
|
|||
}
|
||||
|
||||
object count {
|
||||
private val cache: Cache[Int] = LruCache(timeToLive = 1.day)
|
||||
|
||||
def clearCache = fuccess(cache.clear)
|
||||
private val cache = AsyncCache.single(
|
||||
f = videoColl.db command Count(videoColl.name, none),
|
||||
timeToLive = 1.day)
|
||||
|
||||
def apply: Fu[Int] = cache(true) {
|
||||
videoColl.db command Count(videoColl.name, none)
|
||||
}
|
||||
def clearCache = cache.clear
|
||||
|
||||
def apply: Fu[Int] = cache apply true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,28 +134,48 @@ private[video] final class VideoApi(
|
|||
|
||||
object tag {
|
||||
|
||||
private val nbCache: Cache[List[TagNb]] = LruCache(timeToLive = 1.day)
|
||||
def paths(filterTags: List[Tag]): Fu[List[TagNb]] = pathsCache(filterTags.sorted)
|
||||
|
||||
def clearCache = fuccess {
|
||||
nbCache.clear
|
||||
def clearCache = pathsCache.clear >> popularCache.clear
|
||||
|
||||
private val max = 25
|
||||
|
||||
private val pathsCache = AsyncCache[List[Tag], List[TagNb]](
|
||||
f = filterTags => {
|
||||
val allPaths =
|
||||
if (filterTags.isEmpty) popularCache(true)
|
||||
else {
|
||||
val command = Aggregate(videoColl.name, Seq(
|
||||
Match(BSONDocument("tags" -> BSONDocument("$all" -> filterTags))),
|
||||
Project("tags" -> BSONBoolean(true)),
|
||||
Unwind("tags"),
|
||||
GroupField("tags")("nb" -> SumValue(1))
|
||||
))
|
||||
videoColl.db.command(command) map {
|
||||
_.toList.flatMap(_.asOpt[TagNb])
|
||||
}
|
||||
|
||||
def pathsAnd(max: Int, forced: List[Tag]): Fu[List[TagNb]] =
|
||||
popular zip paths(forced) map {
|
||||
}
|
||||
popularCache(true) zip allPaths map {
|
||||
case (all, paths) =>
|
||||
val tags = all take max map { t =>
|
||||
val tags = all map { t =>
|
||||
paths find (_._id == t._id) getOrElse TagNb(t._id, 0)
|
||||
}
|
||||
val missing = forced filterNot { t =>
|
||||
} filterNot (_.empty) take max
|
||||
val missing = filterTags filterNot { t =>
|
||||
tags exists (_.tag == t)
|
||||
}
|
||||
tags.take(max - missing.size) ::: missing.flatMap { t =>
|
||||
val list = tags.take(max - missing.size) ::: missing.flatMap { t =>
|
||||
all find (_.tag == t)
|
||||
}
|
||||
list.sortBy { t =>
|
||||
if (filterTags contains t.tag) Int.MinValue
|
||||
else -t.nb
|
||||
}
|
||||
}
|
||||
},
|
||||
timeToLive = 1.day)
|
||||
|
||||
def popular: Fu[List[TagNb]] = nbCache("") {
|
||||
import reactivemongo.core.commands._
|
||||
private val popularCache = AsyncCache.single[List[TagNb]](
|
||||
f = {
|
||||
val command = Aggregate(videoColl.name, Seq(
|
||||
Project("tags" -> BSONBoolean(true)),
|
||||
Unwind("tags"),
|
||||
|
@ -164,23 +185,7 @@ private[video] final class VideoApi(
|
|||
videoColl.db.command(command) map {
|
||||
_.toList.flatMap(_.asOpt[TagNb])
|
||||
}
|
||||
}
|
||||
|
||||
def paths(tags: List[Tag]): Fu[List[TagNb]] =
|
||||
if (tags.isEmpty) popular
|
||||
else nbCache(tags.sorted.mkString(",")) {
|
||||
import reactivemongo.core.commands._
|
||||
val command = Aggregate(videoColl.name, Seq(
|
||||
Match(BSONDocument("tags" -> BSONDocument("$all" -> tags))),
|
||||
Project("tags" -> BSONBoolean(true)),
|
||||
Unwind("tags"),
|
||||
// Match(BSONDocument("tags" -> BSONDocument("$nin" -> tags))),
|
||||
GroupField("tags")("nb" -> SumValue(1)),
|
||||
Sort(Seq(Descending("nb")))
|
||||
))
|
||||
videoColl.db.command(command) map {
|
||||
_.toList.flatMap(_.asOpt[TagNb])
|
||||
}
|
||||
}
|
||||
},
|
||||
timeToLive = 1.day)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import org.joda.time.DateTime
|
|||
case class TagNb(_id: Tag, nb: Int) {
|
||||
|
||||
def tag = _id
|
||||
|
||||
def empty = nb == 0
|
||||
}
|
||||
|
||||
case class Filter(tags: List[String]) {
|
||||
|
|
|
@ -147,6 +147,10 @@
|
|||
opacity: 0.5;
|
||||
cursor: default;
|
||||
}
|
||||
#video_side .under_tags {
|
||||
margin-top: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#video .not_found {
|
||||
margin-top: 200px;
|
||||
|
|
Loading…
Reference in a new issue