persistent challenges WIP

pull/1558/head
Thibault Duplessis 2016-01-28 14:01:55 +07:00
parent 31b7123a5a
commit f87da2f442
10 changed files with 102 additions and 21 deletions

View File

@ -106,7 +106,9 @@ withLangAnnotations: Boolean = true)(body: Html)(implicit ctx: Context)
<span data-icon="U"></span>
</span>
</a>
<div id="challenge_notifications" class="links dropdown"></div>
<div id="challenge_notifications" class="links dropdown">
<div class="square-wrap"><div class="square-spin"></div></div>
</div>
</div>
}.getOrElse {
<a href="@routes.Auth.login" class="signin button fright text">@trans.signIn()</a>

View File

@ -46,8 +46,14 @@ private object BSONHandlers {
def read(b: BSONBoolean) = Mode(b.value)
def write(m: Mode) = BSONBoolean(m.rated)
}
implicit val RatingBSONHandler = new BSON[Rating] {
def reads(r: Reader) = Rating(r.int("i"), r.boolD("p"))
def writes(w: Writer, r: Rating) = BSONDocument(
"i" -> r.int,
"b" -> w.boolO(r.provisional))
}
implicit val EitherChallengerBSONHandler = new BSON[EitherChallenger] {
def reads(r: Reader) = (r.strO("id") |@| r.intO("rating")) {
def reads(r: Reader) = (r.strO("id") |@| r.getO[Rating]("rating")) {
case (id, rating) => Right(Registered(id, rating))
} orElse r.strO("secret").map { secret =>
Left(Anonymous(secret))

View File

@ -25,7 +25,12 @@ case class Challenge(
object Challenge {
case class Registered(id: String, rating: Int)
case class Rating(int: Int, provisional: Boolean)
object Rating {
def apply(p: lila.rating.Perf): Rating = Rating(p.intRating, p.provisional)
}
case class Registered(id: String, rating: Rating)
case class Anonymous(secret: String)
sealed trait TimeControl
@ -78,7 +83,7 @@ object Challenge {
case _ => ColorChoice.Random
},
challenger = challenger.fold[EitherChallenger](Left(Anonymous(randomId))) { u =>
Right(Registered(u.id, u.perfs(perfType(variant, timeControl)).intRating))
Right(Registered(u.id, Rating(u.perfs(perfType(variant, timeControl)))))
},
destUserId = destUserId,
createdAt = DateTime.now,

View File

@ -2,6 +2,8 @@ package lila.challenge
import play.api.libs.json._
import lila.common.PimpedJson._
final class JsonView(getLightUser: String => Option[lila.common.LightUser]) {
import Challenge._
@ -18,8 +20,9 @@ final class JsonView(getLightUser: String => Option[lila.common.LightUser]) {
"id" -> u.id,
"name" -> light.fold(u.id)(_.name),
"title" -> light.map(_.title),
"rating" -> u.rating
)
"rating" -> u.rating.int,
"provisional" -> u.rating.provisional
).noNull
},
"destUserId" -> c.destUserId,
"variant" -> Json.obj(
@ -28,12 +31,13 @@ final class JsonView(getLightUser: String => Option[lila.common.LightUser]) {
"name" -> c.variant.name),
"rated" -> c.mode.rated,
"timeControl" -> (c.timeControl match {
case TimeControl.Clock(l, i) => Json.obj(
case c@TimeControl.Clock(l, i) => Json.obj(
"type" -> "clock",
"limit" -> l,
"increment" -> i)
"increment" -> i,
"show" -> c.show)
case TimeControl.Correspondence(d) => Json.obj(
"type" -> "clock",
"type" -> "correspondence",
"daysPerTurn" -> d)
case TimeControl.Unlimited => Json.obj("type" -> "unlimited")
}),

View File

@ -346,10 +346,9 @@ lichess.challengeBox = (function() {
var baseUrl = $('body').data('asset-url');
var isDev = $('body').data('dev');
$('head').append($('<link rel="stylesheet" type="text/css" />')
.attr('href', baseUrl + '/assets/stylesheet/challenge.css'));
$.getScript(baseUrl + "/assets/compiled/challenge" + (isDev ? '.min' : '') + '.js').done(function() {
instance = LichessChallenge({
element: document.getElementById('#challenge_notifications'),
.attr('href', baseUrl + '/assets/stylesheet/challengeBox.css'));
$.getScript(baseUrl + "/assets/compiled/lichess.challenge" + (isDev ? '' : '.min') + '.js').done(function() {
instance = LichessChallenge(document.getElementById('challenge_notifications'), {
setCount: function(nb) {
$('#challenge_notifications_tag').attr('data-count', nb).toggleClass('none', !nb);
}
@ -1114,9 +1113,9 @@ lichess.unique = function(xs) {
}
});
});
$('#challenge_notifications').one('mouseover', function() {
$('#challenge_notifications_tag').one('mouseover click', function() {
lichess.challengeBox.load();
});
}).trigger('click');
$('#translation_call .close').click(function() {
$.post($(this).data("href"));

View File

@ -6,12 +6,20 @@ module.exports = function(env) {
this.data = env.data;
this.userId = env.userId;
this.socket = new socket(env.socketSend, this);
this.vm = {
initiating: true,
reloading: false
};
this.update = function(data) {
this.data = data;
this.vm.initiating = false;
this.vm.reloading = false;
}.bind(this);
xhr.load();
this.trans = lichess.trans(env.i18n);
};

View File

@ -1,12 +1,13 @@
var m = require('mithril');
var ctrl = require('./ctrl');
module.exports = function(element, opts) {
var controller = new ctrl(opts);
m.module(element, {
controller: function() {
return {
data: opts.data
};
return controller;
},
view: require('./view')
});

View File

@ -1,6 +1,55 @@
var m = require('mithril');
function user(u) {
var rating = u.rating + (u.provisional ? '?' : '');
var fullName = (u.title ? u.title + ' ' : '') + u.name;
return {
tag: 'a',
attrs: {
class: 'ulpt user_link',
'data-href': '/@/' + u.name
},
children: [
fullName,
m('span.progress', [rating, ratingDiff])
]
};
}
function timeControl(c) {
switch (c.type) {
case 'unlimited':
return 'Unlimited';
case 'correspondence':
return c.daysPerTurn + ' days';
case 'clock':
return c.show;
}
}
function challenge(c) {
return m('div.challenge', [
m('i', {
'data-icon': c.perf.icon
}),
m('div.content', [
m('span.title', user(c.challenger)),
m('span.desc', [
c.rated ? 'Rated' : 'Casual',
timeControl(c.timeControl),
c.variant.name
].join(' '))
])
]);
}
module.exports = function(ctrl) {
if (ctrl.vm.initiating) return m('div.square-wrap', m('div.square-spin'));
var d = ctrl.data;
return m('div.challenges', 'hehe');
return m('div', {
class: 'challenges ' + (ctrl.vm.reloading ? ' reloading' : '')
}, [
d.in.map(challenge),
d.out.map(challenge),
])
};

View File

@ -10,4 +10,11 @@ function uncache(url) {
}
module.exports = {
load: function() {
return m.request({
method: 'GET',
url: uncache('/challenge'),
config: xhrConfig,
}).then(ctrl.update);
}
};