Display recent forum posts on homepage

This commit is contained in:
Thibault Duplessis 2012-05-27 01:30:16 +02:00
parent 1f2073fc48
commit 3ba130bef6
15 changed files with 83 additions and 12 deletions

View file

@ -15,6 +15,7 @@ object Lobby extends LilaController {
def hookRepo = env.lobby.hookRepo
def fisherman = env.lobby.fisherman
def joiner = env.setup.hookJoiner
def forumRecent = env.forum.recent
val home = Open { implicit ctx
renderHome(none).fold(identity, Ok(_))
@ -32,7 +33,7 @@ object Lobby extends LilaController {
myHook = myHook
).unsafePerformIO.bimap(
url Redirect(url),
preload html.lobby.home(toJson(preload), myHook)
preload html.lobby.home(toJson(preload), myHook, forumRecent(ctx.me))
)
def socket = WebSocket.async[JsValue] { implicit req

View file

@ -24,6 +24,7 @@ final class Settings(config: Config) {
val ForumTopicMaxPerPage = getInt("forum.topic.max_per_page")
val ForumPostMaxPerPage = getInt("forum.post.max_per_page")
val ForumRecentTimeout = millis("forum.recent.timeout")
val SetupFriendConfigMemoTtl = millis("setup.friend_config.memo.ttl")

View file

@ -27,5 +27,9 @@ final class ForumEnv(
lazy val postApi = new PostApi(this, ForumPostMaxPerPage)
lazy val recent = new Recent(
env = this,
timeout = ForumRecentTimeout)
lazy val denormalize = topicApi.denormalize flatMap { _ categApi.denormalize }
}

View file

@ -5,7 +5,12 @@ import user.UserHelper
trait ForumHelper { self: UserHelper
def showAuthorName(post: Post) =
def authorName(post: Post) =
post.userId.fold(userIdToUsername, post.showAuthor)
def authorLink(post: Post, cssClass: Option[String] = None) =
post.userId.fold(
userId userIdLink(userId.some, cssClass),
authorName(post)
)
}

View file

@ -42,6 +42,16 @@ final class PostApi(env: ForumEnv, maxPerPage: Int) {
)
} yield (topicOption |@| postOption).tupled
def view(post: Post): IO[Option[PostView]] = for {
topicOption env.topicRepo byId post.topicId
categOption topicOption.fold(
topic env.categRepo bySlug topic.categId,
io(none[Categ])
)
} yield topicOption |@| categOption apply {
case (topic, categ) PostView(post, topic, categ, pageOf)
}
def lastNumberOf(topic: Topic): IO[Int] =
env.postRepo lastByTopics List(topic) map (_.number)

View file

@ -27,6 +27,10 @@ final class PostRepo(
find(DBObject()).toList
}
def recent(nb: Int): IO[List[Post]] = io {
find(DBObject()).sort(sortQuery(-1)).limit(nb).toList.reverse
}
val sortQuery: DBObject = sortQuery(1)
def sortQuery(order: Int): DBObject = DBObject("createdAt" -> order)

10
app/forum/PostView.scala Normal file
View file

@ -0,0 +1,10 @@
package lila
package forum
case class PostView(
post: Post,
topic: Topic,
categ: Categ,
pageOf: Post Int) {
}

27
app/forum/Recent.scala Normal file
View file

@ -0,0 +1,27 @@
package lila
package forum
import memo.Builder
import user.User
import security.{ Permission, Granter }
import scalaz.effects._
final class Recent(env: ForumEnv, timeout: Int) {
val nb = 30
private val cache = Builder.cache[Boolean, List[PostView]](timeout, staff
fetch(staff).unsafePerformIO
)
def apply(user: Option[User]): List[PostView] =
cache get Granter.option(Permission.StaffForum)(user)
private def fetch(staff: Boolean): IO[List[PostView]] = for {
posts env.postRepo.recent(nb)
views (posts map env.postApi.view).sequence
} yield views collect {
case Some(v) if (staff || v.categ.slug != "staff") v
}
}

View file

@ -7,4 +7,7 @@ object Granter {
def apply(permission: Permission)(user: User): Boolean =
Permission(user.roles) exists (_ is permission)
def option(permission: Permission)(user: Option[User]): Boolean =
user.fold(apply(permission), false)
}

View file

@ -28,7 +28,7 @@ title = trans.forum.str()) {
<td class="last_post">
@categ.lastPost.map {
case (topic, post) => {
<a href="@routes.ForumTopic.show(categ.slug, topic.slug, categ pageOf post)#@post.number">@showDate(post.createdAt)</a><br />by @showAuthorName(post)
<a href="@routes.ForumTopic.show(categ.slug, topic.slug, categ pageOf post)#@post.number">@showDate(post.createdAt)</a><br />by @authorName(post)
}
}
</td>

View file

@ -33,7 +33,7 @@ title = categ.name) {
<td class="right">@(topic.nbPosts - 1)</td>
<td class="last_post">
@topic.lastPost.map { post =>
<a href="@routes.ForumTopic.show(categ.slug, topic.slug, topic pageOf post)#@post.number">@showDate(post.createdAt)</a><br />by @showAuthorName(post)
<a href="@routes.ForumTopic.show(categ.slug, topic.slug, topic pageOf post)#@post.number">@showDate(post.createdAt)</a><br />by @authorName(post)
}
</td>
@if(isGranted(Permission.ModerateForum)) {

View file

@ -0,0 +1,10 @@
@(posts: List[lila.forum.PostView])(implicit ctx: Context)
@for(v <- posts) {
@defining(routes.ForumTopic.show(v.categ.slug, v.topic.slug, v pageOf v.post) + "#" + v.post.number) { postUrl =>
<li>
<a class="post_link" href="@postUrl">@v.topic.name</a>
<span>@authorLink(v.post)</span>
@Html(shorten(v.post.text, 80).replace("<br />", ""))
</li>
}
}

View file

@ -18,11 +18,7 @@ title = topic.name) {
@for(post <- posts.currentPageResults) {
<div class="post" id="@post.number">
<div class="metas clearfix">
@post.userId.map { userId =>
<span class="author authenticated">@userIdLink(userId.some)</span>
}.getOrElse {
<span class="author">@showAuthorName(post)</span>
}
@authorLink(post, "author".some)
<span class="createdAt">@showDate(post.createdAt)</span>
<a class="anchor" href="routes.ForumTopic.show(categ.slug, topic.slug, posts.page)">#@post.number</a>
@if(isGranted(Permission.ModerateForum)) {

View file

@ -1,4 +1,4 @@
@(preload: String, myHook: Option[lila.lobby.Hook])(implicit ctx: Context)
@(preload: String, myHook: Option[lila.lobby.Hook], forumRecent: List[lila.forum.PostView])(implicit ctx: Context)
@chat = {
@ctx.me.map { m =>
@ -50,8 +50,7 @@
<span class="title">@trans.forum()</span>
</div>
<div class="undertable_inner">
<ol>
</ol>
<ol>@forum.post.recent(forumRecent)</ol>
</div>
</div>
</div>

View file

@ -44,6 +44,7 @@ game {
forum {
topic.max_per_page = 10
post.max_per_page = 10
recent.timeout = 1 hour
}
setup {
friend_config.memo.ttl = 1 day