user blog WIP
parent
fb8b6de80e
commit
8585905cc3
|
@ -156,6 +156,7 @@ final class LilaComponents(ctx: ApplicationLoader.Context) extends BuiltInCompon
|
|||
lazy val dgt: DgtCtrl = wire[DgtCtrl]
|
||||
lazy val storm: Storm = wire[Storm]
|
||||
lazy val racer: Racer = wire[Racer]
|
||||
lazy val ublog: Ublog = wire[Ublog]
|
||||
lazy val bulkPairing: BulkPairing = wire[BulkPairing]
|
||||
|
||||
// eagerly wire up all controllers
|
||||
|
|
|
@ -84,6 +84,7 @@ final class Env(
|
|||
val swiss: lila.swiss.Env,
|
||||
val storm: lila.storm.Env,
|
||||
val racer: lila.racer.Env,
|
||||
val ublog: lila.ublog.Env,
|
||||
val lilaCookie: lila.common.LilaCookie,
|
||||
val net: NetConfig,
|
||||
val controllerComponents: ControllerComponents
|
||||
|
@ -280,6 +281,7 @@ final class EnvBoot(
|
|||
lazy val swiss: lila.swiss.Env = wire[lila.swiss.Env]
|
||||
lazy val storm: lila.storm.Env = wire[lila.storm.Env]
|
||||
lazy val racer: lila.racer.Env = wire[lila.racer.Env]
|
||||
lazy val ublog: lila.ublog.Env = wire[lila.ublog.Env]
|
||||
lazy val api: lila.api.Env = wire[lila.api.Env]
|
||||
lazy val lilaCookie = wire[lila.common.LilaCookie]
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package controllers
|
||||
|
||||
import views._
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app._
|
||||
import lila.ublog.UblogPost
|
||||
|
||||
final class Ublog(env: Env) extends LilaController(env) {
|
||||
|
||||
def index(username: String, page: Int) = Open { implicit ctx =>
|
||||
OptionFuOk(env.user.repo named username) { user =>
|
||||
env.ublog.api.liveByUser(user, page) map { posts =>
|
||||
html.ublog.index(user, posts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def post(username: String, slug: String, id: String) = Open { implicit ctx =>
|
||||
OptionFuResult(env.user.repo named username) { user =>
|
||||
env.ublog.api.find(UblogPost.Id(id)) map {
|
||||
_ ?? { post =>
|
||||
if (!user.is(post.user) || slug != post.slug) Redirect(html.ublog.post.url(post))
|
||||
else {
|
||||
val markup = scalatags.Text.all.raw(env.ublog.markup(post.markdown))
|
||||
Ok(html.ublog.post(user, post, markup))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package views.html.ublog
|
||||
|
||||
import controllers.routes
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app.templating.Environment._
|
||||
import lila.app.ui.ScalatagsTemplate._
|
||||
import lila.common.paginator.Paginator
|
||||
import lila.ublog.UblogPost
|
||||
import lila.user.User
|
||||
|
||||
object index {
|
||||
|
||||
def apply(user: User, posts: Paginator[UblogPost])(implicit ctx: Context) =
|
||||
views.html.base.layout(
|
||||
moreCss = frag(cssTag("ublog")),
|
||||
title = s"${user.username} blog"
|
||||
) {
|
||||
main(cls := "box box-pad page ublog-index")(
|
||||
h1(s"${user.username} blog"),
|
||||
div(cls := "ublog-index__posts")(
|
||||
div(cls := "infinite-scroll")(
|
||||
posts.currentPageResults map views.html.ublog.post.mini,
|
||||
pagerNext(posts, np => s"${routes.Ublog.index(user.username, np).url}")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package views.html.ublog
|
||||
|
||||
import controllers.routes
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app.templating.Environment._
|
||||
import lila.app.ui.ScalatagsTemplate._
|
||||
import lila.ublog.UblogPost
|
||||
import lila.user.User
|
||||
|
||||
object post {
|
||||
|
||||
def apply(user: User, post: UblogPost, markup: Frag)(implicit ctx: Context) =
|
||||
views.html.base.layout(
|
||||
moreCss = frag(cssTag("ublog")),
|
||||
title = s"${user.username} blog • ${post.title}"
|
||||
) {
|
||||
main(cls := "box box-pad page ublog-post")(
|
||||
h1(cls := "ublog-post__title")(post.title),
|
||||
strong(cls := "ublog-post__intro")(post.intro),
|
||||
div(cls := "ublog-post__markup")(markup)
|
||||
)
|
||||
}
|
||||
|
||||
def mini(post: UblogPost)(implicit ctx: Context) =
|
||||
a(cls := "ublog-post-mini", href := url(post))(
|
||||
h2(cls := "ublog-post-mini__title", post.title),
|
||||
strong(cls := "ublog-post-mini__intro", post.intro)
|
||||
)
|
||||
|
||||
def url(post: UblogPost) = routes.Ublog.post(usernameOrId(post.user), post.slug, post.id.value)
|
||||
}
|
|
@ -57,6 +57,10 @@ GET /insights/:username/:metric/:dimension/*filters controllers.Insight.path(u
|
|||
# User subpages
|
||||
GET /@/:username/tournaments/:path controllers.UserTournament.path(username: String, path: String, page: Int ?= 1)
|
||||
|
||||
# User blog
|
||||
GET /@/:username/blog controllers.Ublog.index(username: String, page: Int ?= 1)
|
||||
GET /@/:username/blog/:slug/:id controllers.Ublog.post(username: String, slug: String, id: String)
|
||||
|
||||
# User
|
||||
GET /api/stream/:username/mod controllers.User.mod(username: String)
|
||||
POST /@/:username/note controllers.User.writeNote(username: String)
|
||||
|
|
|
@ -14,4 +14,6 @@ final class Env(
|
|||
private val postColl = db(CollName("ublog_post"))
|
||||
|
||||
val api = wire[UblogApi]
|
||||
|
||||
val markup = wire[UblogMarkup]
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package lila.ublog
|
||||
|
||||
import lila.db.dsl._
|
||||
import lila.user.User
|
||||
import reactivemongo.api._
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
import lila.common.config.MaxPerPage
|
||||
import lila.common.paginator.Paginator
|
||||
import lila.db.dsl._
|
||||
import lila.db.paginator.Adapter
|
||||
import lila.user.User
|
||||
|
||||
final class UblogApi(coll: Coll)(implicit ec: ExecutionContext) {
|
||||
|
||||
import UblogBsonHandlers._
|
||||
|
@ -12,4 +17,25 @@ final class UblogApi(coll: Coll)(implicit ec: ExecutionContext) {
|
|||
val post = UblogPost.make(user, data.title, data.intro, data.markdown)
|
||||
coll.insert.one(post) inject post
|
||||
}
|
||||
|
||||
def find(id: UblogPost.Id): Fu[Option[UblogPost]] = coll.byId[UblogPost](id.value)
|
||||
|
||||
def liveByUser(user: User, page: Int): Fu[Paginator[UblogPost]] =
|
||||
paginatorByUser(user, true, page)
|
||||
|
||||
def draftByUser(user: User, page: Int): Fu[Paginator[UblogPost]] =
|
||||
paginatorByUser(user, false, page)
|
||||
|
||||
private def paginatorByUser(user: User, live: Boolean, page: Int): Fu[Paginator[UblogPost]] =
|
||||
Paginator(
|
||||
adapter = new Adapter[UblogPost](
|
||||
collection = coll,
|
||||
selector = $doc("user" -> user.id, "live" -> live),
|
||||
projection = none,
|
||||
sort = $doc("liveAt" -> -1, "createdAt" -> -1),
|
||||
readPreference = ReadPreference.secondaryPreferred
|
||||
),
|
||||
currentPage = page,
|
||||
maxPerPage = MaxPerPage(15)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package lila.ublog
|
||||
|
||||
import com.github.blemale.scaffeine.LoadingCache
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
final class UblogMarkup {
|
||||
|
||||
private val renderer =
|
||||
new lila.common.Markdown(
|
||||
autoLink = true,
|
||||
list = true,
|
||||
strikeThrough = true,
|
||||
header = true
|
||||
)
|
||||
|
||||
private val cache: LoadingCache[String, String] = lila.memo.CacheApi.scaffeineNoScheduler
|
||||
.expireAfterAccess(20 minutes)
|
||||
.maximumSize(512)
|
||||
.build(renderer.apply)
|
||||
|
||||
def apply(text: String): String = cache.get(text)
|
||||
}
|
|
@ -10,10 +10,14 @@ case class UblogPost(
|
|||
title: String,
|
||||
intro: String,
|
||||
markdown: String,
|
||||
live: Boolean,
|
||||
createdAt: DateTime,
|
||||
updatedAt: DateTime
|
||||
updatedAt: DateTime,
|
||||
liveAt: Option[DateTime]
|
||||
) {
|
||||
|
||||
def id = _id
|
||||
|
||||
lazy val slug = {
|
||||
val s = lila.common.String slugify title
|
||||
if (s.isEmpty) "-" else s
|
||||
|
@ -29,8 +33,10 @@ object UblogPost {
|
|||
title = title,
|
||||
intro = intro,
|
||||
markdown = markdown,
|
||||
live = false,
|
||||
createdAt = DateTime.now,
|
||||
updatedAt = DateTime.now
|
||||
updatedAt = DateTime.now,
|
||||
liveAt = none
|
||||
)
|
||||
|
||||
case class Id(value: String) extends AnyVal with StringValue
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
@import '../../../common/css/plugin';
|
||||
@import '../ublog/ublog';
|
|
@ -0,0 +1,3 @@
|
|||
.ublog-index {
|
||||
background: red;
|
||||
}
|
Loading…
Reference in New Issue