coach WIP

coach
Thibault Duplessis 2016-08-21 09:16:41 +02:00
parent efd1013257
commit a8c0b57368
11 changed files with 136 additions and 6 deletions

View File

@ -0,0 +1,25 @@
package controllers
import play.api.mvc._, Results._
import lila.app._
import lila.coach.{ Coach => CoachModel }
import lila.user.{ User => UserModel, UserRepo }
import views._
object Coach extends LilaController {
private val api = Env.coach.api
def index = Open { implicit ctx =>
api.enabledWithUserList map { coaches =>
Ok(html.coach.index(coaches))
}
}
def show(username: String) = Open { implicit ctx =>
OptionOk(api find username) { coach =>
html.coach.show(coach)
}
}
}

View File

@ -0,0 +1,21 @@
@(coaches: List[lila.coach.Coach.WithUser])(implicit ctx: Context)
@layout(title = "Lichess coaches", active = "all") {
<div class="content_box no_padding coach">
<div class="top">
<h1>Chess coaches</h1>
</div>
<div class="list">
@coaches.map {
case lila.coach.Coach.WithUser(c, u) => {
<a class="coach" href="@routes.Coach.show(u.username)">
<h2>@userSpan(u)</h2>
@u.seenAt.map { seen =>
<p class="thin">@trans.lastSeenActive(momentFromNow(seen))</p>
}
</a>
}
}
</div>
</div>
}

View File

@ -0,0 +1,14 @@
@(title: String, active: String)(body: Html)(implicit ctx: Context)
@moreCss = {
@cssTag("coach.css")
}
@menu = {
<a class="@active.active("all")" href="@routes.Coach.index">All coaches</a>
}
@base.layout(
title = title,
side = menu.some,
moreCss = moreCss)(body)

View File

@ -0,0 +1,9 @@
@(c: lila.coach.Coach.WithUser)(implicit ctx: Context)
@layout(title = c.user.titleUsername, active = "coach") {
<div class="content_box no_padding coach">
<div class="top">
<h1>@userLink(c.user)</h1>
</div>
</div>
}

View File

@ -493,6 +493,9 @@ message {
thread.max_per_page = 30
collection.thread = m_thread
}
coach {
collection.coach = coach
}
memo {
collection {
cache = cache

View File

@ -368,6 +368,10 @@ GET /inbox/$id<\w{8}> controllers.Message.thread(id: String)
POST /inbox/$id<\w{8}> controllers.Message.answer(id: String)
POST /inbox/$id<\w{8}>/delete controllers.Message.delete(id: String)
# Coach
GET /coach controllers.Coach.index
GET /coach/:username controllers.Coach.show(username: String)
# Paste
GET /paste controllers.Importer.importGame
POST /import controllers.Importer.sendGame

View File

@ -6,6 +6,10 @@ import reactivemongo.bson._
private[coach] object BsonHandlers {
implicit val CoachIdBSONHandler = stringAnyValHandler[Coach.Id](_.value, Coach.Id.apply)
implicit val CoachEnabledBSONHandler = booleanAnyValHandler[Coach.Enabled](_.value, Coach.Enabled.apply)
implicit val CoachAvailableBSONHandler = booleanAnyValHandler[Coach.Available](_.value, Coach.Available.apply)
implicit val CoachCentsBSONHandler = intAnyValHandler[Coach.Cents](_.value, Coach.Cents.apply)
implicit val CoachMarkdownBSONHandler = stringAnyValHandler[Coach.Markdown](_.value, Coach.Markdown.apply)
implicit val CoachBSONHandler = Macros.handler[Coach]
}

View File

@ -2,12 +2,30 @@ package lila.coach
import org.joda.time.DateTime
import lila.user.User
case class Coach(
_id: Coach.Id, // user ID
createdAt: DateTime,
updatedAt: DateTime)
_id: Coach.Id, // user ID
enabledByUser: Coach.Enabled,
enabledByMod: Coach.Enabled,
available: Coach.Available,
hourlyWage: Coach.Cents,
description: Coach.Markdown,
createdAt: DateTime,
updatedAt: DateTime) {
def id = _id
def is(user: User) = id.value == user.id
}
object Coach {
case class WithUser(coach: Coach, user: User)
case class Id(value: String) extends AnyVal with StringValue
case class Enabled(value: Boolean) extends AnyVal
case class Available(value: Boolean) extends AnyVal
case class Cents(value: Int) extends AnyVal
case class Markdown(value: String) extends AnyVal with StringValue
}

View File

@ -5,4 +5,23 @@ import lila.user.{ User, UserRepo }
final class CoachApi(coll: Coll) {
import BsonHandlers._
def find(username: String): Fu[Option[Coach.WithUser]] =
UserRepo named username flatMap { _ ?? find }
def find(user: User): Fu[Option[Coach.WithUser]] =
coll.byId[Coach](user.id) map2 withUser(user)
def enabledWithUserList: Fu[List[Coach.WithUser]] =
coll.list[Coach]($doc("enabled" -> true)) flatMap { coaches =>
UserRepo.byIds(coaches.map(_.id.value)) map { users =>
coaches.flatMap { coach =>
users find coach.is map { Coach.WithUser(coach, _) }
}
}
}
private def withUser(user: User)(coach: Coach): Coach.WithUser =
Coach.WithUser(coach, user)
}

View File

@ -32,7 +32,9 @@ object ByteArray {
def write(ba: ByteArray) = BSONBinary(ba.value, subtype)
}
def parseByte(s: String): Byte = {
def parseBytes(s: List[String]) = ByteArray(s map parseByte toArray)
private def parseByte(s: String): Byte = {
var i = s.length - 1
var sum = 0
var mult = 1
@ -48,8 +50,6 @@ object ByteArray {
sum.toByte
}
def parseBytes(s: List[String]) = ByteArray(s map parseByte toArray)
def subtype = Subtype.GenericBinarySubtype
private val binarySubType = Converters hex2Str Array(subtype.value)

View File

@ -0,0 +1,13 @@
package lila.db
import org.joda.time.DateTime
case class DbImage(
_id: String,
data: ByteArray,
name: String,
createdAt: DateTime)
object DbImage {
}