improve game filters
This commit is contained in:
parent
6f95b76493
commit
ce18609522
|
@ -7,7 +7,7 @@ import controllers.routes
|
|||
|
||||
trait AssetHelper {
|
||||
|
||||
val assetVersion = 46
|
||||
val assetVersion = 47
|
||||
|
||||
def cssTag(name: String) = css("stylesheets/" + name)
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
10
app/views/base/radio.scala.html
Normal file
10
app/views/base/radio.scala.html
Normal 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>
|
10
app/views/base/radios.scala.html
Normal file
10
app/views/base/radios.scala.html
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
6
app/views/setup/filterRadio.scala.html
Normal file
6
app/views/setup/filterRadio.scala.html
Normal 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>
|
8
app/views/setup/filterRadios.scala.html
Normal file
8
app/views/setup/filterRadios.scala.html
Normal 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))
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
BIN
public/images/radio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
2
todo
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue