lobby filter UI

This commit is contained in:
Thibault Duplessis 2012-12-29 16:53:34 +01:00
parent 7063449860
commit 9e80c71585
15 changed files with 134 additions and 64 deletions

View file

@ -41,7 +41,7 @@ object Lobby extends LilaController with Results {
filter = env.setup.filter
).map(_.fold(Redirect(_), {
case (preload, posts, tours, featured) status(html.lobby.home(
toJson(preload).pp,
toJson(preload),
myHook,
posts,
tours,

View file

@ -52,12 +52,20 @@ object Setup extends LilaController with TheftPrevention with RoundEventPerforme
}
}
val filterForm = Open { implicit ctx
IOk(forms.filterFilled map { html.setup.filter(_) })
val filterForm = Auth { implicit ctx
me
IOk(forms.filterFilled map { html.setup.filter(_) })
}
val filter = process(forms.filter) { config
implicit ctx processor filter config inject routes.Lobby.home()
val filter = AuthBody { implicit ctx
me
implicit val req = ctx.body
IOResult {
forms.filter(ctx).bindFromRequest.fold(
f putStrLn(f.errors.toString) inject BadRequest(),
config processor filter config inject JsonOk(config.render)
)
}
}
def join(id: String) = Open { implicit ctx
@ -108,7 +116,7 @@ object Setup extends LilaController with TheftPrevention with RoundEventPerforme
OpenBody { ctx
implicit val req = ctx.body
IORedirect(form(ctx).bindFromRequest.fold(
f putStrLn(f.errors.toString) map { _ routes.Lobby.home },
f putStrLn(f.errors.toString) inject routes.Lobby.home,
config op(config)(ctx)
))
}

View file

@ -11,7 +11,7 @@ import scalaz.effects._
import org.joda.time.DateTime
import org.scala_tools.time.Imports._
class HookRepo(collection: MongoCollection)
final class HookRepo(collection: MongoCollection)
extends SalatDAO[Hook, String](collection) {
def hook(hookId: String): IO[Option[Hook]] = io {

View file

@ -6,7 +6,7 @@ import com.mongodb.casbah.MongoCollection
import com.mongodb.casbah.query.Imports._
import scalaz.effects._
final class MessageRepo(collection: MongoCollection, max: Int)
private[lobby] final class MessageRepo(collection: MongoCollection, max: Int)
extends CappedRepo[Message](collection, max) {
val all = io {

View file

@ -17,7 +17,7 @@ import akka.util.duration._
import akka.util.Timeout
import scalaz.effects._
final class Preload(
private[lobby] final class Preload(
fisherman: Fisherman,
history: History,
hookRepo: HookRepo,
@ -54,10 +54,10 @@ final class Preload(
ioToFuture(filter) map {
case ((((((hooks, messages), entries), posts), tours), feat), filter) (Right((Map(
"version" -> history.version,
"pool" -> renderHooks(hooks, myHook),
"pool" -> renderHooks(hooks, myHook).pp,
"chat" -> (messages.reverse map (_.render)),
"timeline" -> (entries.reverse map (_.render)),
"filter" -> filter.toMap
"filter" -> filter.render
), posts, tours, feat))): Response
}
)

View file

@ -12,7 +12,7 @@ case class FilterConfig(variant: Option[Variant]) {
def >> = Some((variant map (_.id)))
def toMap = Map("variant" -> variant.map(_.id))
def render = Map("variant" -> variant.map(_.toString))
}
object FilterConfig {

View file

@ -24,7 +24,8 @@ private[setup] final class UserConfigRepo(collection: MongoCollection)
def filter(user: User): IO[FilterConfig] = io {
for {
obj collection.findOneByID(user.id, DBObject("filter" -> true))
variant obj.getAs[Int]("v")
filter obj.getAs[DBObject]("filter")
variant filter.getAs[Int]("v")
config RawFilterConfig(variant).decode
} yield config
} map (_ | FilterConfig.default)

View file

@ -7,7 +7,7 @@ import play.api.templates.Html
trait AssetHelper {
val assetVersion = 23
val assetVersion = 24
def cssTag(name: String) = css("stylesheets/" + name)

View file

@ -33,13 +33,5 @@ final class LobbyMenu(i18nKeys: I18nKeys) {
i18nKeys.playWithTheMachine,
i18nKeys.challengeTheArtificialIntelligence)
val filter = new Elem(
"filter",
routes.Setup.filterForm,
i18nKeys.filterGames,
i18nKeys.filterGames)
val allAnon = List(hook, friend, ai)
val allUser = allAnon :+ filter
val all = List(hook, friend, ai)
}

View file

@ -2,7 +2,7 @@
<div class="lichess_ground">
<div class="lichess_table lichess_table_not_started" id="start_buttons">
@ctx.isAuth.fold(lobbyMenu.allUser, lobbyMenu.allAnon).map { b =>
@lobbyMenu.all.map { b =>
<a class="lichess_button button config_@b.code" href="@b.route" title="@b.title()">@b.name()</a>
}
</div>

View file

@ -51,6 +51,10 @@ underchat = underchat.some) {
@board.white()
@widget.connection()
<div class="hooks_wrap">
@if(ctx.isAuth) {
<a class="filter" href="@routes.Setup.filterForm()"><span class="s16">@trans.filterGames()</span></a>
<div class="filter"></div>
}
<div class="hooks"
data-my-hook="@myHook.map(_.ownerId)"
data-cancel-url="@routes.Lobby.cancel("000000000000")"

View file

@ -1,13 +1,11 @@
@(form: Form[_])(implicit ctx: Context)
<div class="lichess_overboard auto_center game_config game_config_filter">
<h2>@trans.filterGames()</h2>
<div class="game_config_form">
@helper.form(action = routes.Setup.filter, 'novalidate -> "novalidate") {
<div class="variants">
@base.select(form("variant"), translatedVariantChoices, "Any variant".some)
</div>
<button type="submit" class="submit">Save filter</button>
}
</div>
@helper.form(action = routes.Setup.filter(), 'novalidate -> "novalidate") {
<div class="variants">
@base.select(form("variant"), translatedVariantChoices, "Any variant".some)
</div>
<div class="actions">
<a class="reset">Reset</a>
<button type="submit" class="submit">Done</button>
</div>
}

View file

@ -1520,6 +1520,36 @@ $(function() {
var myElo = isRegistered ? parseInt($userTag.data('elo')) : null;
var hookOwnerId = $hooks.data('my-hook');
$wrap.find('a.filter').click(function() {
$(this).toggleClass('active');
if($(this).hasClass('active')) {
var $filter = $wrap.find('div.filter').fadeIn(200);
$.ajax({
url: $(this).attr('href'),
success: function(html) {
$filter.html(html).find('select').change(_.throttle(function() {
var $form = $filter.find('form');
$.ajax({
url: $form.attr('action'),
data: $form.serialize(),
type: 'post',
success: function(filter) {
lichess_preload.filter = filter;
updateHookTable();
}
});
}, 500));
$filter.find('a.reset').click(function() {
$filter.find('select').val('').change();
});
}
});
} else {
var $filter = $wrap.find('div.filter').fadeOut(200);
}
return false;
}).click();
if (chatExists) {
var $form = $chat.find('form');
$chat.find('.lichess_messages').scrollable();
@ -1645,8 +1675,7 @@ $(function() {
}
function addHooks(hooks) {
var html = "";
for (i in hooks) html += renderHook(hooks[i]);
$hooksTable.append(html);
for (i in hooks) html += $hooksTable.append(renderHook(hooks[i]));
updateHookTable();
}
function addHook(hook) {
@ -1654,6 +1683,14 @@ $(function() {
updateHookTable();
}
function updateHookTable() {
var filter = lichess_preload.filter;
$hooksTable.find('tr.hook').each(function() {
var hook = $(this).data('hook');
var hide = (filter.variant != null && filter.variant != hook.variant);
hide = hide && (hook.action != 'cancel');
if (hide) $(this).hide(); else $(this).show();
});
if (0 == $hooksTable.find('tr.hook').length) {
$hooksTable.addClass('empty_table').html('<tr class="create_game"><td colspan="5">'+$.trans("No game available right now, create one!")+'</td></tr>');
} else {
@ -1708,8 +1745,10 @@ $(function() {
var cancelParam = hookOwnerId ? "?cancel=" + hookOwnerId : ""
html += '<a href="'+actionUrls.join.replace(/\/0{8}/, '/'+hook.id)+cancelParam+'" class="join"></a>';
}
html += '</td>';
}
return html;
html += '</tr>';
return $(html).data('hook', hook);
}
function resizeLobby() {

File diff suppressed because one or more lines are too long

View file

@ -77,7 +77,7 @@ div.hooks_wrap {
top: 51px;
left: 52px;
padding: 12px;
border-radius: 3px;
border-radius: 3px 0 3px 3px;
box-shadow: 0 0 20px #444;
background: rgba(245,245,245,0.8);
background: -moz-linear-gradient(top, rgba(212,212,212,0.9) 0%, rgba(240,240,240,0.5) 100%);
@ -85,6 +85,7 @@ div.hooks_wrap {
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(212,212,212,0.9)), to(rgba(240,240,240,0.5)));
background: -ms-linear-gradient(top, rgba(212,212,212,0.9) 0%,rgba(240,240,240,0.5) 100%);
background: -o-linear-gradient(top, rgba(212,212,212,0.9) 0%,rgba(240,240,240,0.5) 100%);
background: linear-gradient(top, rgba(212,212,212,0.9) 0%,rgba(240,240,240,0.5) 100%);
}
div.hooks_wrap.large {
height: 512px;
@ -94,6 +95,57 @@ div.hooks_wrap.large {
div.hooks_wrap.hidden {
display: none;
}
div.hooks_wrap a.filter {
position: absolute;
top: -21px;
right: -1px;
height: 20px;
line-height: 20px;
padding: 0 2px 0 10px;
background: rgba(212,212,212,0.9);
background: -moz-linear-gradient(top,rgba(212,212,212,1) 0%, rgba(212,212,212,0.9) 100%);
border: 1px solid #444;
border-bottom: 0;
display: block;
border-radius: 3px 3px 0 0;
color: #333;
text-decoration: none;
}
div.hooks_wrap a.filter:hover,
div.hooks_wrap a.filter.active {
background: #fff;
}
div.hooks_wrap a.filter span {
background-position: right -192px;
padding-left: 0;
padding-right: 20px;
}
div.hooks_wrap div.filter {
position: absolute;
display: none;
top: 0px;
right: 0px;
min-height: 181px;
width: 244px;
padding: 12px;
border: 1px solid #444;
border-width: 0 0 1px 1px;
background: #fff;
}
div.hooks_wrap div.filter select {
width: 100%;
margin-bottom: 12px;
text-transform: capitalize;
padding: 6px;
}
div.hooks_wrap div.filter .actions {
text-align: right;
}
div.hooks_wrap div.filter .actions button {
padding: 6px;
margin-left: 12px;
}
div.hooks {
border: 1px solid #bababa;
border-top: 0