puzzle complete UI with voting

This commit is contained in:
Thibault Duplessis 2016-12-08 12:27:08 +01:00
parent 820b4d74c2
commit 9e0f100f94
7 changed files with 110 additions and 42 deletions

View file

@ -143,9 +143,11 @@ object Puzzle extends LilaController {
(round, _) = finished
me2 <- UserRepo byId me.id map (_ | me)
infos <- env userInfos me2
voted <- ctx.me.?? { env.api.vote.value(puzzle.id, _) }
} yield Ok(Json.obj(
"user" -> lila.puzzle.JsonView.infos(false)(infos),
"round" -> lila.puzzle.JsonView.round(round)
"round" -> lila.puzzle.JsonView.round(round),
"voted" -> voted
))
case None =>
lila.mon.puzzle.round.anon()

View file

@ -31,7 +31,7 @@ final class JsonView(gameJson: GameJson) {
"initialPly" -> puzzle.initialPly,
"gameId" -> puzzle.gameId,
"lines" -> lila.puzzle.Line.toJson(puzzle.lines),
"branch" -> makeBranch(puzzle),
"branch" -> (!isMobileApi).option(makeBranch(puzzle)),
"enabled" -> puzzle.enabled,
"vote" -> puzzle.vote.sum
),

View file

@ -39,6 +39,7 @@
line-height: 64px;
text-align: center;
}
#puzzle .feedback.good .icon,
#puzzle .feedback.win .icon {
color: #759900;
}
@ -66,14 +67,65 @@
opacity: 1;
}
#puzzle .after .continue {
#puzzle .feedback.after {
}
#puzzle .feedback.after .half {
flex: 0 0 50%;
}
#puzzle .feedback.after .half.top {
display: flex;
flex-flow: row nowrap;
}
#puzzle .feedback.after .complete {
flex: 1 0;
display: flex;
align-items: center;
justify-content: center;
}
#puzzle .feedback.after .vote {
flex: 0 1;
display: flex;
flex-flow: column;
margin: 0 10px;
align-items: center;
justify-content: center;
}
#puzzle .feedback.after .vote a {
cursor: default;
cursor: pointer;
opacity: 0.7;
}
#puzzle .feedback.after .vote a::before {
font-size: 34px;
}
#puzzle .feedback.after .vote a:hover,
#puzzle .feedback.after .vote a.active {
opacity: 1;
color: #d85000;
}
#puzzle .feedback.after .vote span.count {
font-size: 22px;
line-height: 1;
}
#puzzle .feedback.after .continue {
display: flex;
height: 50%;
width: 100%;
font-size: 1.3em;
background: #3893E8;
color: #fff;
align-items: center;
justify-content: center;
text-transform: uppercase;
}
#puzzle .feedback.after .continue:hover {
background: #5ba6ec;
}
#puzzle .feedback.after .continue i::before {
font-size: 2.5em;
margin-right: 10px;
}
#puzzle move {

View file

@ -35,6 +35,7 @@ module.exports = function(opts, i18n) {
vm.mode = 'play'; // play | try | view
vm.loading = false;
vm.round = null;
vm.voted = null;
vm.justPlayed = null;
vm.resultSent = false;
vm.lastFeedback = 'init';
@ -51,8 +52,8 @@ module.exports = function(opts, i18n) {
setTimeout(function() {
vm.canViewSolution = true;
m.redraw();
}, 5000);
// }, 50);
// }, 5000);
}, 50);
socket.setDestsCache(data.game.destsCache);
moveTest = moveTestBuild(vm, data.puzzle);
@ -187,11 +188,11 @@ module.exports = function(opts, i18n) {
vm.lastFeedback = 'retry';
revertUserMove();
} else if (progress === 'win') {
if (vm.mode === 'play') {
if (vm.mode !== 'view') {
vm.lastFeedback = 'win';
vm.mode = 'view';
showGround(); // to disable premoves
sendResult(true);
if (vm.mode === 'play') sendResult(true);
}
} else if (progress && progress.orig) {
vm.lastFeedback = 'good';
@ -208,6 +209,7 @@ module.exports = function(opts, i18n) {
xhr.round(data.puzzle.id, win).then(function(res) {
data.user = res.user;
vm.round = res.round;
vm.voted = res.voted;
vm.loading = false;
m.redraw();
});
@ -320,6 +322,17 @@ module.exports = function(opts, i18n) {
}, '') : '';
};
var hasEverVoted = lichess.storage.make('puzzle-ever-voted');
var vote = function(v) {
hasEverVoted.set(1);
vm.voted = v;
xhr.vote(data.puzzle.id, v).then(function(res) {
data.puzzle.vote = res[1];
m.redraw();
});
};
initiate(opts.data);
keyboard.bind({
@ -340,6 +353,8 @@ module.exports = function(opts, i18n) {
viewSolution: viewSolution,
nextPuzzle: nextPuzzle,
recentHash: recentHash,
hasEverVoted: hasEverVoted,
vote: vote,
trans: lichess.trans(opts.i18n),
socketReceive: socket.receive
};

View file

@ -1,32 +1,30 @@
var m = require('mithril');
// function voteFunction(ctrl, v) {
// return function() {
// ctrl.hasEverVoted.set(1);
// xhr.vote(ctrl, v);
// };
// }
// function renderVote(ctrl) {
// return m('div.upvote' + (ctrl.data.round ? '.enabled' : ''), [
// m('a[data-icon=S]', {
// title: ctrl.trans('thisPuzzleIsCorrect'),
// class: ctrl.data.voted === true ? ' active' : '',
// onclick: voteFunction(ctrl, 1)
// }),
// m('span.count.hint--bottom[data-hint=Popularity]', ctrl.data.puzzle.vote),
// m('a[data-icon=R]', {
// title: ctrl.trans('thisPuzzleIsWrong'),
// class: ctrl.data.voted === false ? ' active' : '',
// onclick: voteFunction(ctrl, 0)
// })
// ]);
// }
function renderVote(ctrl) {
var data = ctrl.getData();
return m('div.vote', [
m('a[data-icon=S]', {
title: ctrl.trans.noarg('thisPuzzleIsCorrect'),
class: ctrl.vm.voted === true ? ' active' : '',
onclick: function() {
ctrl.vote(true);
}
}),
m('span.count.hint--bottom[data-hint=Popularity]', data.puzzle.vote),
m('a[data-icon=R]', {
title: ctrl.trans.noarg('thisPuzzleIsWrong'),
class: ctrl.vm.voted === false ? ' active' : '',
onclick: function() {
ctrl.vote(false);
}
})
]);
}
module.exports = function(ctrl) {
var data = ctrl.getData();
return m('div.feedback.after', [
// (!ctrl.hasEverVoted.get() && ctrl.data.puzzle.enabled && ctrl.data.voted === null) ? m('div.please_vote', [
// (!ctrl.hasEverVoted.get() && data.puzzle.enabled && data.voted === null) ? m('div.please_vote', [
// m('p.first', [
// m('strong', ctrl.trans('wasThisPuzzleAnyGood')),
// m('br'),
@ -36,8 +34,12 @@ module.exports = function(ctrl) {
// m('strong', ctrl.trans('thankYou'))
// )
// ]) : null,
// (ctrl.data.puzzle.enabled && ctrl.data.user) ? renderVote(ctrl) : null,
m('a.continue', {
// (data.puzzle.enabled && data.user) ? renderVote(ctrl) : null,
m('div.half.top', [
m('div.complete', 'Puzzle complete!'),
data.user ? renderVote(ctrl) : null
]),
m('a.half.continue', {
onclick: ctrl.nextPuzzle
}, [
m('i[data-icon=G]'),

View file

@ -63,7 +63,7 @@ function userBox(ctrl) {
klass = '';
if (diff >= 0) {
diff = '+' + diff;
klass = 'up';
if (diff > 0) klass = 'up';
} else if (diff === 0) diff = '+0';
else klass = 'down';
ratingHtml += ' <span class="rp ' + klass + '">' + diff + '</span>';

View file

@ -20,18 +20,15 @@ function round(puzzleId, win) {
});
}
function vote(ctrl, v) {
m.request({
function vote(puzzleId, v) {
return m.request({
method: 'POST',
url: '/training/' + ctrl.data.puzzle.id + '/vote',
url: '/training/' + puzzleId + '/vote',
data: {
vote: v
vote: v ? 1 : 0
},
config: xhrConfig,
background: true
}).then(function(res) {
ctrl.data.voted = res[0];
ctrl.data.puzzle.vote = res[1];
});
}