allow users to delete their imported games - closes #416

pull/437/head
Thibault Duplessis 2015-04-22 16:27:10 +02:00
parent 8e5665c59d
commit a2ba8025b0
10 changed files with 66 additions and 17 deletions

View File

@ -33,6 +33,19 @@ object Game extends LilaController with BaseGame {
}
}
def delete(gameId: String) = Auth { implicit ctx =>
me =>
OptionFuResult(GameRepo game gameId) { game =>
if (game.pgnImport.flatMap(_.user) ?? (me.id==)) {
Env.hub.actor.bookmark ! lila.hub.actorApi.bookmark.Remove(game.id)
GameRepo remove game.id inject Redirect(routes.User.show(me.username))
}
else fuccess {
Redirect(routes.Round.watcher(game.id, game.firstColor.name))
}
}
}
def export(user: String) = Auth { implicit ctx =>
_ =>
Env.security.forms.emptyWithCaptcha map {

View File

@ -20,7 +20,8 @@ lichess = lichess || {};
lichess.analyse = {
data: @Html(play.api.libs.json.Json.stringify(data)),
routes: roundRoutes.controllers,
i18n: @round.jsI18n()
i18n: @round.jsI18n(),
userId: @Html(ctx.userId.fold("null")(id => s""""$id""""))
};
}
}

View File

@ -40,6 +40,8 @@
@if(g.variant.exotic) {
@variantLink(g.variant, g.variant.name.toUpperCase, cssClass = "hint--top")
} else {
@g.variant.name.toUpperCase
}
} else {
@g.clock.map(_.show).getOrElse {

View File

@ -113,6 +113,8 @@ POST /$gameId<\w{8}>/note controllers.Round.writeNote(gam
GET /$gameId<\w{8}>/edit controllers.Editor.game(gameId: String)
GET /$gameId<\w{8}>/$color<white|black>/analysis controllers.UserAnalysis.game(gameId: String, color: String)
POST /$gameId<\w{8}>/delete controllers.Game.delete(gameId: String)
GET /round-next/$gameId<\w{8}> controllers.Round.next(gameId: String)
GET /whats-next/$gameId<\w{8}> controllers.Round.whatsNext(gameId: String)

View File

@ -174,7 +174,8 @@ final class JsonView(
)
},
"status" -> statusJson(game.status),
"joinable" -> game.joinable).noNull,
"joinable" -> game.joinable,
"importedBy" -> game.pgnImport.flatMap(_.user)).noNull,
"clock" -> game.clock.map(clockJson),
"correspondence" -> game.correspondenceClock.map(correspondenceJson),
"player" -> Json.obj(

View File

@ -60,7 +60,7 @@ lichess.StrongSocket.defaults = {
($('body').data('ports') + '').split(',').map(function(port) {
return 'socket.' + document.domain + ':' + port;
})),
onFirstConnect: $.noop(),
onFirstConnect: $.noop,
baseUrlKey: 'surl3'
}
};
@ -239,10 +239,10 @@ lichess.StrongSocket.prototype = {
if (this.ws) {
this.debug("Disconnect", true);
this.autoReconnect = false;
this.ws.onerror = $.noop();
this.ws.onclose = $.noop();
this.ws.onopen = $.noop();
this.ws.onmessage = $.noop();
this.ws.onerror = $.noop;
this.ws.onclose = $.noop;
this.ws.onopen = $.noop;
this.ws.onmessage = $.noop;
this.ws.close();
}
},
@ -2061,7 +2061,8 @@ lichess.storage = {
}
};
data.path = location.hash ? location.hash.replace(/#/, '') : '';
analyse = LichessAnalyse(element.querySelector('.analyse'), cfg.data, cfg.routes, cfg.i18n, cfg.onChange);
cfg.element = element.querySelector('.analyse');
analyse = LichessAnalyse(cfg);
cfg.jump = analyse.jump;
$('.underboard_content', element).appendTo($('.underboard .center', element)).show();

View File

@ -140,6 +140,17 @@ div.game_control .jumps {
.lichess_ground .action_menu .button::before {
font-size: 2em;
}
.lichess_ground .action_menu form.delete {
margin-top: 2em;
text-align: right;
}
.lichess_ground .action_menu form.delete .button {
display: inline-block;
padding: 0 8px;
}
.lichess_ground .action_menu form.delete .button::before {
font-size: 1.2em;
}
.lichess_ground .replay .turn > .index {
display: inline-block;
width: 26px;

View File

@ -18,6 +18,21 @@ function speedsOf(data) {
return data.game.moveTimes.length ? allSpeeds : baseSpeeds;
}
function deleteButton(data, userId) {
if (data.game.source === 'import' &&
data.game.importedBy && data.game.importedBy === userId)
return m('form.delete', {
method: 'post',
action: '/' + data.game.id + '/delete',
onsubmit: function() {
return confirm('Delete this imported game?');
}
}, m('button.button.text.thin', {
type: 'submit',
'data-icon': 'q',
}, 'Delete'));
}
module.exports = {
controller: function() {
@ -50,6 +65,7 @@ module.exports = {
onclick: partial(ctrl.togglePlay, speed.delay)
}, 'Auto play ' + speed.name);
}),
deleteButton(ctrl.data, ctrl.userId),
m('div.continue_with.' + ctrl.data.game.id, [
m('a.button', {
href: ctrl.data.userAnalysis ? '/?fen=' + ctrl.vm.situation.fen + '#ai' : ctrl.router.Round.continue(ctrl.data.game.id, 'ai').url + '?fen=' + ctrl.vm.situation.fen,

View File

@ -11,14 +11,16 @@ var control = require('./control');
var promotion = require('./promotion');
var m = require('mithril');
module.exports = function(cfg, router, i18n, onChange) {
module.exports = function(opts) {
this.data = data({}, cfg);
this.data = data({}, opts.data);
this.analyse = new analyse(this.data.game, this.data.analysis);
this.actionMenu = new actionMenu();
this.autoplay = new autoplay(this);
var initialPath = cfg.path ? treePath.read(cfg.path) : treePath.default();
this.userId = opts.userId;
var initialPath = opts.path ? treePath.read(opts.path) : treePath.default();
this.vm = {
path: initialPath,
@ -132,7 +134,7 @@ module.exports = function(cfg, router, i18n, onChange) {
this.chessground = ground.make(this.data, this.vm.situation, userMove);
this.chessground.stop();
this.chessground.set(this.vm.situation);
if (onChange) onChange(this.vm.situation.fen, this.vm.path);
if (opts.onChange) opts.onChange(this.vm.situation.fen, this.vm.path);
}.bind(this);
this.jump = function(path) {
@ -178,10 +180,10 @@ module.exports = function(cfg, router, i18n, onChange) {
if (!promotion.start(this, orig, dest, addMove)) addMove(orig, dest);
}.bind(this);
this.router = router;
this.router = opts.routes;
this.trans = function(key) {
var str = i18n[key] || key;
var str = opts.i18n[key] || key;
Array.prototype.slice.call(arguments, 1).forEach(function(arg) {
str = str.replace('%s', arg);
});

View File

@ -2,11 +2,11 @@ var ctrl = require('./ctrl');
var view = require('./view');
var m = require('mithril');
module.exports = function(element, config, router, i18n, onChange) {
module.exports = function(opts) {
var controller = new ctrl(config, router, i18n, onChange);
var controller = new ctrl(opts);
m.module(element, {
m.module(opts.element, {
controller: function () { return controller; },
view: view
});