activity UI WIP
parent
92c7a5a001
commit
0a1e8c7637
|
@ -12,8 +12,8 @@ import lila.common.paginator.Paginator
|
|||
import lila.common.{ IpAddress, HTTPRequest }
|
||||
import lila.game.{ GameRepo, Game => GameModel }
|
||||
import lila.rating.PerfType
|
||||
import lila.user.{ User => UserModel, UserRepo }
|
||||
import lila.socket.UserLagCache
|
||||
import lila.user.{ User => UserModel, UserRepo }
|
||||
import views._
|
||||
|
||||
object User extends LilaController {
|
||||
|
@ -322,4 +322,12 @@ object User extends LilaController {
|
|||
def myself = Auth { ctx => me =>
|
||||
fuccess(Redirect(routes.User.show(me.username)))
|
||||
}
|
||||
|
||||
def activity(username: String) = Open { implicit ctx =>
|
||||
OptionFuResult(UserRepo named username) { user =>
|
||||
Env.activity.read.recent(user.id, 3) map { as =>
|
||||
Ok(html.activity.list(user, as))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package views.html.activity
|
||||
|
||||
import play.twirl.api.Html
|
||||
|
||||
import lila.activity.activities._
|
||||
import lila.activity.model._
|
||||
import lila.api.Context
|
||||
import lila.i18n.{ I18nKey, I18nKeys => trans }
|
||||
|
||||
object ActivityHtml extends lila.Steroids {
|
||||
|
||||
def scoreHtml(s: Score)(implicit ctx: Context) = Html {
|
||||
s"""<score>${scorePart("win", s.win, trans.nbWins)}${scorePart("draw", s.draw, trans.nbDraws)}${scorePart("loss", s.loss, trans.nbLosses)}</score>"""
|
||||
}
|
||||
|
||||
private def scorePart(tag: String, p: Int, name: I18nKey)(implicit ctx: Context) =
|
||||
if (p == 0) ""
|
||||
else s"""<$tag>${wrapNumber(name.pluralSameTxt(p))}</$tag>"""
|
||||
|
||||
private val wrapNumberRegex = """(\d+)""".r
|
||||
private def wrapNumber(str: String) =
|
||||
wrapNumberRegex.replaceAllIn(str, "<strong>$1</strong>")
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
@(u: User, as: List[lila.activity.ActivityView.AsTo])(implicit ctx: Context)
|
||||
|
||||
@import ActivityHtml._
|
||||
|
||||
@moreCss = {
|
||||
@cssTag("activity.css")
|
||||
}
|
||||
|
||||
@user.layout(
|
||||
title = s"${u.username} activity",
|
||||
evenMoreCss = moreCss) {
|
||||
<div class="content_box no_padding activity">
|
||||
<div class="content_box_top">
|
||||
<h1 class="lichess_title">
|
||||
<a href="@routes.User.show(u.username)">
|
||||
@u.username activity
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="timeline">
|
||||
@as.map {
|
||||
case lila.activity.ActivityView.AsTo(date, a) => {
|
||||
<section>
|
||||
<h2>@semanticDate(date)</h2>
|
||||
@defining(a.puzzles) { p =>
|
||||
<div class="entry puzzles">
|
||||
<strong>Played @p.score.size tactical puzzles</strong>
|
||||
@scoreHtml(p.score)
|
||||
</div>
|
||||
}
|
||||
@a.games.value.map {
|
||||
case (pt, score) => {
|
||||
<div class="entry games">
|
||||
<strong>Played @score.size @pt.name games</strong>
|
||||
@scoreHtml(score)
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</section>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="content_box_content">right here.</div>
|
||||
</div>
|
||||
}
|
|
@ -55,6 +55,7 @@ GET /@/:username/mod controllers.User.mod(username: String)
|
|||
POST /@/:username/note controllers.User.writeNote(username: String)
|
||||
GET /@/:username/mini controllers.User.showMini(username: String)
|
||||
GET /@/:username/tv controllers.User.tv(username: String)
|
||||
GET /@/:username/activity controllers.User.activity(username: String)
|
||||
GET /@/:username/studyTv controllers.User.studyTv(username: String)
|
||||
GET /@/:username/perf/:perfKey controllers.User.perfStat(username: String, perfKey: String)
|
||||
GET /@/:username/:filterName controllers.User.showFilter(username: String, filterName: String, page: Int ?= 1)
|
||||
|
|
|
@ -18,8 +18,7 @@ case class Activity(
|
|||
corres: Corres
|
||||
) {
|
||||
|
||||
def userId = id.userId
|
||||
def day = id.day
|
||||
def date = Activity.Day.genesis plusDays id.day.value
|
||||
}
|
||||
|
||||
object Activity {
|
||||
|
@ -36,6 +35,9 @@ object Activity {
|
|||
object Day {
|
||||
val genesis = new DateTime(2010, 1, 1, 0, 0).withTimeAtStartOfDay
|
||||
def today = Day(Days.daysBetween(genesis, DateTime.now.withTimeAtStartOfDay).getDays)
|
||||
def recent(nb: Int): List[Day] = (0 to (nb - 1)).toList.map { delta =>
|
||||
Day(Days.daysBetween(genesis, DateTime.now.minusDays(delta).withTimeAtStartOfDay).getDays)
|
||||
}
|
||||
}
|
||||
|
||||
def make(userId: User.ID) = Activity(
|
||||
|
|
|
@ -12,5 +12,16 @@ final class ActivityReadApi(coll: Coll) {
|
|||
import BSONHandlers._
|
||||
import activities._
|
||||
|
||||
def get(userId: User.ID) = coll.byId[Activity, Id](Id today userId)
|
||||
def recent(userId: User.ID, days: Int): Fu[List[ActivityView.AsTo]] =
|
||||
coll.find($inIds(makeIds(userId, days))).list[Activity]() map { as =>
|
||||
as.map { a =>
|
||||
ActivityView.AsTo(
|
||||
a.pp.date,
|
||||
ActivityView(a.games, a.puzzles)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private def makeIds(userId: User.ID, days: Int): List[Id] =
|
||||
Day.recent(days).map { Id(userId, _) }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package lila.activity
|
||||
|
||||
import org.joda.time.DateTime
|
||||
|
||||
import lila.user.User
|
||||
|
||||
import activities._
|
||||
|
||||
case class ActivityView(
|
||||
games: Games,
|
||||
puzzles: Puzzles
|
||||
) {
|
||||
}
|
||||
|
||||
object ActivityView {
|
||||
|
||||
case class AsTo(day: DateTime, activity: ActivityView)
|
||||
}
|
|
@ -25,4 +25,4 @@ object Insight {
|
|||
case class Stacked(points: List[(Metric.MetricValueName, Point)]) extends Insight
|
||||
}
|
||||
|
||||
case class Point(y: Double)
|
||||
case class Point(y: Double) extends AnyVal
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
.activity section::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 15px;
|
||||
z-index: -1;
|
||||
display: block;
|
||||
width: 2px;
|
||||
content: "";
|
||||
background-color: #e6ebf1;
|
||||
}
|
||||
.activity section h2 {
|
||||
font-weight: bold;
|
||||
}
|
||||
.activity .entry {
|
||||
padding: 20px;
|
||||
}
|
||||
.activity .entry strong {
|
||||
font-weight: normal;
|
||||
}
|
||||
.activity .score {
|
||||
float: right;
|
||||
}
|
||||
.activity .score strong {
|
||||
}
|
Loading…
Reference in New Issue