show video tag path

pull/382/head
Thibault Duplessis 2015-03-23 02:34:45 +01:00
parent 62b2b2b524
commit b2405aaafe
7 changed files with 48 additions and 19 deletions

View File

@ -16,7 +16,7 @@ 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.popularAnd(25, reqTags) map { tags =>
env.api.tag.pathsAnd(25, reqTags) map { tags =>
UserControl(
filter = Filter(reqTags),
tags = tags)

View File

@ -4,12 +4,14 @@
<div id="video_side">
<div class="tag_list">
@control.tags.map { t =>
<a class="@if(control.filter.tags contains t.tag) {checked}"
@defining(control.filter.tags contains t.tag) { checked =>
<a class="@if(checked) {checked} @if(checked || t.nb > 0) {full} else {empty}"
href="@routes.Video.index?@control.filter.toggle(t.tag).queryString">
<em>@t.nb</em>
@if(t.nb > 0) {<em>@t.nb</em>}
@t.tag.capitalize
</a>
}
}
</div>
</div>
}

View File

@ -133,21 +133,27 @@ private[video] final class VideoApi(
object tag {
private val cache: Cache[List[TagNb]] = LruCache(timeToLive = 1.day)
private val nbCache: Cache[List[TagNb]] = LruCache(timeToLive = 1.day)
def clearCache = fuccess(cache.clear)
def popularAnd(max: Int, forced: List[Tag]): Fu[List[TagNb]] = popular map { all =>
val tags = all take max
val missing = forced filterNot { t =>
tags exists (_.tag == t)
}
tags.take(max - missing.size) ::: missing.flatMap { t =>
all find (_.tag == t)
}
def clearCache = fuccess {
nbCache.clear
}
def popular: Fu[List[TagNb]] = cache(true) {
def pathsAnd(max: Int, forced: List[Tag]): Fu[List[TagNb]] =
popular zip paths(forced) map {
case (all, paths) =>
val tags = all take max map { t =>
paths find (_._id == t._id) getOrElse TagNb(t._id, 0)
}
val missing = forced filterNot { t =>
tags exists (_.tag == t)
}
tags.take(max - missing.size) ::: missing.flatMap { t =>
all find (_.tag == t)
}
}
def popular: Fu[List[TagNb]] = nbCache("") {
import reactivemongo.core.commands._
val command = Aggregate(videoColl.name, Seq(
Project("tags" -> BSONBoolean(true)),
@ -159,5 +165,22 @@ private[video] final class VideoApi(
_.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])
}
}
}
}

View File

@ -47,7 +47,7 @@ private[video] final class Youtube(
case JsSuccess(entries, _) => fuccess(entries.toList)
}
case res =>
println(res.body)
println(s"key: $apiKey")
fufail(s"[video youtube] fetch ${res.status}")
}
}

View File

@ -29,7 +29,7 @@ body.dark div.chat_menu > a.active {
body.dark .crosstable td {
border-color: #1a1a1a;
}
body.dark #video_side .tag_list a:hover {
body.dark #video_side .tag_list a.full:hover {
background: #222;
border-color: #444;
}

View File

@ -129,20 +129,24 @@
border-left: 2px solid transparent;
transition: 0.13s;
}
#video_side .tag_list a:hover {
#video_side .tag_list a.full:hover {
background: #f8f8f8;
border-color: #ccc;
}
#video_side .tag_list em {
float: right;
font-weight: bold;
opacity: 0.5;
opacity: 0.6;
}
#video_side .tag_list a.checked {
font-weight: bold;
background: #fff;
border-color: #d85000!important;
}
#video_side .tag_list a.empty {
opacity: 0.6;
cursor: default;
}
#video .not_found {
margin-top: 200px;