improve game filters

This commit is contained in:
Thibault Duplessis 2013-06-09 02:30:32 +02:00
parent 6f95b76493
commit ce18609522
19 changed files with 122 additions and 69 deletions

View file

@ -7,7 +7,7 @@ import controllers.routes
trait AssetHelper {
val assetVersion = 46
val assetVersion = 47
def cssTag(name: String) = css("stylesheets/" + name)

View file

@ -1,9 +1,9 @@
package lila.app
package templating
import lila.user.Context
import lila.setup._
import chess.{ Mode, Variant, Speed }
import lila.setup._
import lila.user.Context
trait SetupHelper extends scalaz.Booleans { self: I18nHelper
@ -17,7 +17,7 @@ trait SetupHelper extends scalaz.Booleans { self: I18nHelper ⇒
Variant.Chess960.id.toString -> Variant.Chess960.name.capitalize
)
def translatedVariantChoicesWithFen(implicit ctx: Context) =
def translatedVariantChoicesWithFen(implicit ctx: Context) =
translatedVariantChoices(ctx) :+ (Variant.FromPosition.id.toString -> "FEN")
def translatedSpeedChoices(implicit ctx: Context) = Speed.all map { s
@ -25,9 +25,6 @@ trait SetupHelper extends scalaz.Booleans { self: I18nHelper ⇒
}
def eloDiffChoices(elo: Int)(implicit ctx: Context) = FilterConfig.eloDiffs map { diff
diff -> (diff == 0).fold(
trans.eloRange.str(),
"%d - %d (±%d)".format(elo - diff, elo + diff, diff)
)
diff -> "%d - %d (±%d)".format(elo - diff, elo + diff, diff)
}
}

View file

@ -0,0 +1,10 @@
@(field: play.api.data.Field, key: Any, value: String)
<input
type="radio"
id="@(field.id)_@key"
name="@field.name"
value="@value"
@(if(field.value == Some(value)) "checked" else "")
/>
<label class="required" for="@(field.id)_@key">@value</label>

View file

@ -0,0 +1,10 @@
@(field: play.api.data.Field, options: Seq[(Any,String)], default: Option[String] = None)
@default.map { d =>
@base.radio(field, "", d)
}
@options.map {
case (key, value) => {
@base.radio(field, key, value)
}
}

View file

@ -47,10 +47,10 @@ underchat = underchat.some) {
<span class="s16 ddown">@trans.filterGames()</span>
<span class="number">(0)</span>
</a>
<div class="filter"></div>
<div id="hooks"></div>
<div id="hooks_chart"><div class="canvas"></div></div>
<a class="no_hook">@trans.noGameAvailableRightNowCreateOne()</a>
<div id="hook_filter"></div>
</div>
</div>
@lobby.buttons()

View file

@ -2,14 +2,14 @@
@fields = {
<div class="variants buttons">
@setup.radios(form("variant"), translatedVariantChoicesWithFen)
@base.radios(form("variant"), translatedVariantChoicesWithFen)
</div>
@fenInput(form("fen"), true)
@setup.clock(form, lila.setup.AiConfig)
@trans.level()
<div class="level buttons">
<div id="config_level">
@setup.radios(form("level"), lila.setup.AiConfig.levelChoices)
@base.radios(form("level"), lila.setup.AiConfig.levelChoices)
</div>
</div>
}

View file

@ -1,12 +1,28 @@
@(form: Form[_])(implicit ctx: Context)
@helper.form(action = routes.Setup.filter(), 'novalidate -> "novalidate") {
@base.select(form("variant"), translatedVariantChoices, trans.variant.str().some)
@base.select(form("speed"), translatedSpeedChoices, trans.timeControl.str().some)
@ctx.me.map { me =>
@base.select(form("mode"), translatedModeChoices, trans.mode.str().some)
@base.select(form("eloDiff"), eloDiffChoices(me.elo))
}
<table>
<tbody>
<tr>
<td>@trans.variant()</td>
<td>@setup.filterRadios(form, "variant", translatedVariantChoices)</td>
</tr>
<tr>
<td>@trans.timeControl()</td>
<td>@setup.filterRadios(form, "speed", translatedSpeedChoices)</td>
</tr>
@ctx.me.map { me =>
<tr>
<td>@trans.mode()</td>
<td>@setup.filterRadios(form, "mode", translatedModeChoices)</td>
</tr>
<tr>
<td>@trans.eloRange()</td>
<td>@setup.filterRadios(form, "eloDiff", eloDiffChoices(me.elo))</td>
</tr>
}
</tbody>
</table>
<div class="actions">
<button type="submit" class="reset">@trans.reset()</button>
<button type="submit" class="submit">@trans.apply()</button>

View file

@ -0,0 +1,6 @@
@(field: play.api.data.Field, key: Any, value: Option[String], text: Html)
<label>
<input type="radio" name="@field.name" value="@value" @(if(field.value == value) "checked" else "") />
@text
</label>

View file

@ -0,0 +1,8 @@
@(form: Form[_], key: String, options: Seq[(Any,String)])
@setup.filterRadio(form(key), key, none, Html("All"))
@options.map {
case (value, text) => {
@setup.filterRadio(form(key), key, value.toString.some, Html(text))
}
}

View file

@ -7,13 +7,13 @@
@usernameLink(uid.some, cssClass="target".some)
}
<div class="variants buttons">
@setup.radios(form("variant"), translatedVariantChoicesWithFen)
@base.radios(form("variant"), translatedVariantChoicesWithFen)
</div>
@fenInput(form("fen"), false)
@setup.clock(form, lila.setup.FriendConfig)
@if(ctx.isAuth) {
<div class="mode_choice buttons">
@setup.radios(form("mode"), translatedModeChoices)
@base.radios(form("mode"), translatedModeChoices)
</div>
}
}

View file

@ -5,12 +5,12 @@
@fields = {
<div class="variants buttons">
@setup.radios(form("variant"), translatedVariantChoices)
@base.radios(form("variant"), translatedVariantChoices)
</div>
@setup.clock(form, lila.setup.HookConfig)
@if(ctx.isAuth) {
<div class="mode_choice buttons">
@setup.radios(form("mode"), translatedModeChoices)
@base.radios(form("mode"), translatedModeChoices)
</div>
<div class="elo_range_config optional_config">
@trans.eloRange(): <span class="range">? - ?</span>

View file

@ -1,12 +0,0 @@
@(field: play.api.data.Field, options: Seq[(String,String)])
@options.map { v =>
<input
type="radio"
id="@(field.id)_@v._1"
name="@field.name"
value="@v._1"
@(if(field.value == Some(v._1)) "checked" else "")
/>
<label class="required" for="@(field.id)_@v._1">@v._2</label>
}

View file

@ -9,7 +9,7 @@ case class FilterConfig(
variant: Option[Variant],
mode: Option[Mode],
speed: Option[Speed],
eloDiff: Int) {
eloDiff: Option[Int]) {
def withModeCasual = copy(mode = Mode.Casual.some)
@ -17,14 +17,14 @@ case class FilterConfig(
v = ~variant.map(_.id),
m = mode.map(_.id) | -1,
s = ~speed.map(_.id),
e = eloDiff
e = ~eloDiff
)
def >> = (
variant map (_.id),
mode map (_.id),
speed map (_.id),
eloDiff.some
eloDiff
).some
def render = Json.obj(
@ -41,18 +41,18 @@ object FilterConfig {
variant = none,
mode = none,
speed = none,
eloDiff = 0)
eloDiff = none)
val variants = 0 :: Config.variants
val modes = -1 :: Mode.all.map(_.id)
val speeds = 0 :: Config.speeds
val eloDiffs = 0 :: 100 :: 200 :: 300 :: 500 :: Nil
val eloDiffs = 100 :: 200 :: 300 :: 500 :: Nil
def <<(v: Option[Int], m: Option[Int], s: Option[Int], e: Option[Int]) = new FilterConfig(
variant = v flatMap Variant.apply,
mode = m flatMap Mode.apply,
speed = s flatMap Speed.apply,
eloDiff = ~e
eloDiff = e filter (0!=)
)
def fromDB(obj: JsObject): Option[FilterConfig] = for {
@ -87,7 +87,7 @@ private[setup] case class RawFilterConfig(v: Int, m: Int, s: Int, e: Int) {
variant = Variant(v),
mode = Mode(m),
speed = Speed(s),
eloDiff = e
eloDiff = e.some filter (0!=)
).some
}

View file

@ -15,7 +15,7 @@ private[setup] final class FormFactory {
import Mappings._
def filterFilled(implicit ctx: Context): Fu[Form[FilterConfig]] =
filterConfig map filter(ctx).fill
filterConfig map filter(ctx).fill
def filter(ctx: Context) = Form(
mapping(

BIN
public/images/radio.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -1963,24 +1963,25 @@ var lichess_sri = Math.random().toString(36).substring(5); // 8 chars
$wrap.find('a.filter').click(function() {
var $a = $(this);
var $div = $wrap.find('div.filter');
var $div = $wrap.find('#hook_filter');
setTimeout(function() {
$div.click(function(e) {
e.stopPropagation();
});
$('html').one('click', function(e) {
$div.off('click').fadeOut(200);
$div.off('click').fadeOut(500);
$a.removeClass('active');
});
}, 10);
if ($(this).toggleClass('active').hasClass('active')) {
var $filter = $div.fadeIn(200);
if ($filter.is(':empty')) {
$div.fadeIn(500);
if ($div.is(':empty')) {
$.ajax({
url: $(this).attr('href'),
success: function(html) {
$filter.html(html).find('select').change(_.throttle(function() {
var $form = $filter.find('form');
$div.html(html).find('input').change(_.throttle(function() {
var $form = $div.find('form');
console.debug($form.serialize());
$.ajax({
url: $form.attr('action'),
data: $form.serialize(),
@ -1991,10 +1992,10 @@ var lichess_sri = Math.random().toString(36).substring(5); // 8 chars
}
});
}, 500));
$filter.find('button.reset').click(function() {
$filter.find('select').val('').change();
$div.find('button.reset').click(function() {
$div.find('tr label:first-child input').prop('checked', true).trigger('change');
});
$filter.find('button').click(function() {
$div.find('button').click(function() {
$wrap.find('a.filter').click();
return false;
});
@ -2002,10 +2003,10 @@ var lichess_sri = Math.random().toString(36).substring(5); // 8 chars
});
}
} else {
$div.fadeOut(200);
$div.fadeOut(500);
}
return false;
});
}).click();
$bot.on("click", "tr", function() {
location.href = $(this).find('a.watch').attr("href");

View file

@ -1312,29 +1312,43 @@ div.game_config div.color_submits button.random span {
#hooks_wrap a.filter.on span.number {
display: inline;
}
#hooks_wrap div.filter {
#hook_filter {
position: absolute;
z-index: 99;
display: none;
top: 0px;
right: 0px;
min-height: 181px;
width: 244px;
padding: 12px;
border: 1px solid #888;
border-width: 0 0 1px 1px;
background: #fff;
border-radius: 0 0 0 3px;
width: 472px;
height: 472px;
padding: 20px;
background: rgba(255,255,255,0.8);
border-radius: 5px;
}
#hooks_wrap div.filter select {
#hook_filter table {
width: 100%;
margin-bottom: 12px;
padding: 6px;
}
#hooks_wrap div.filter .actions {
#hook_filter td {
padding: 10px 0;
}
#hook_filter td:first-child {
font-size: 1.3em;
}
#hook_filter td > label {
display: block;
padding: 3px 10px;
color: #444;
}
#hook_filter label, #hook_filter input {
cursor: pointer;
}
#hook_filter td > label:hover {
background: #fff;
}
#hook_filter .actions {
text-align: right;
}
#hooks_wrap div.filter .actions button {
#hook_filter .actions button {
padding: 6px;
margin-left: 12px;
}

View file

@ -185,9 +185,14 @@ body.dark .user_link.black {
background-position: 0 -272px;
}
body.dark #hooks_wrap div.filter {
background-color: black;
border-color: #505050;
body.dark #hook_filter {
background: rgba(0,0,0,0.8);
}
body.dark #hook_filter td > label {
color: #c0c0c0;
}
body.dark #hook_filter td > label:hover {
background: #000;
}
body.dark div.undertable tr:nth-child(even) td

2
todo
View file

@ -63,8 +63,6 @@ filter current games for watching http://en.lichess.org/forum/lichess-feedback/v
declined challenge still appears
no time data http://en.lichess.org/x9tls3mh/stats
show rated games to anon
improve game filter UI
games that have no room to show up never appear
second realtime board on homepage (right)
show friend games in homepage board
allow to filter anon