diff --git a/app/controllers/Setup.scala b/app/controllers/Setup.scala
index c284550649..421cb24f2e 100644
--- a/app/controllers/Setup.scala
+++ b/app/controllers/Setup.scala
@@ -1,12 +1,11 @@
package controllers
-import play.api.data.Form
-import play.api.mvc.{ Result, Call }
-
import lila.app._
import lila.game.GameRepo
import lila.user.UserRepo
import lila.user.{ Context, BodyContext }
+import play.api.data.Form
+import play.api.mvc.{ Result, Call }
import views._
object Setup extends LilaController with TheftPrevention {
@@ -69,7 +68,9 @@ object Setup extends LilaController with TheftPrevention {
}
def filterForm = Open { implicit ctx ⇒
- env.forms.filterFilled map { html.setup.filter(_) }
+ env.forms.filterFilled map {
+ case (form, filter) ⇒ html.setup.filter(form, filter)
+ }
}
def filter = OpenBody { implicit ctx ⇒
diff --git a/app/templating/SetupHelper.scala b/app/templating/SetupHelper.scala
index 78e2fbb3a7..e9a17f7e03 100644
--- a/app/templating/SetupHelper.scala
+++ b/app/templating/SetupHelper.scala
@@ -29,8 +29,4 @@ trait SetupHelper extends scalaz.Booleans { self: I18nHelper ⇒
}
}
}
-
- def eloDiffChoices(elo: Int)(implicit ctx: Context) = FilterConfig.eloDiffs map { diff ⇒
- diff -> "%d - %d (±%d)".format(elo - diff, elo + diff, diff)
- }
}
diff --git a/app/views/setup/filter.scala.html b/app/views/setup/filter.scala.html
index 43e344e078..4cc3fac74b 100644
--- a/app/views/setup/filter.scala.html
+++ b/app/views/setup/filter.scala.html
@@ -1,24 +1,24 @@
-@(form: Form[_])(implicit ctx: Context)
+@(form: Form[_], filter: lila.setup.FilterConfig)(implicit ctx: Context)
@helper.form(action = routes.Setup.filter(), 'novalidate -> "novalidate") {
@trans.variant() |
- @setup.filterRadios(form, "variant", translatedVariantChoices) |
+ @setup.filterCheckboxes(form, "variant", filter.variant.map(_.id.toString), translatedVariantChoices) |
@trans.timeControl() |
- @setup.filterRadios(form, "speed", translatedSpeedChoices) |
+ @setup.filterCheckboxes(form, "speed", filter.speed.map(_.id.toString), translatedSpeedChoices) |
@trans.mode() |
- @setup.filterRadios(form, "mode", translatedModeChoices) |
+ @setup.filterCheckboxes(form, "mode", filter.mode.map(_.id.toString), translatedModeChoices) |
@ctx.me.map { me =>
@trans.eloRange() |
- @setup.filterRadios(form, "eloDiff", eloDiffChoices(me.elo)) |
+ @helper.inputText(form("eloRange")) |
}
diff --git a/app/views/setup/filterCheckbox.scala.html b/app/views/setup/filterCheckbox.scala.html
new file mode 100644
index 0000000000..29a36f648c
--- /dev/null
+++ b/app/views/setup/filterCheckbox.scala.html
@@ -0,0 +1,10 @@
+@(form: Form[_], key: String, index: Int, value: String, checks: List[String], text: Html)
+
+
diff --git a/app/views/setup/filterCheckboxes.scala.html b/app/views/setup/filterCheckboxes.scala.html
new file mode 100644
index 0000000000..ba6b6ea9f5
--- /dev/null
+++ b/app/views/setup/filterCheckboxes.scala.html
@@ -0,0 +1,7 @@
+@(form: Form[_], key: String, checks: List[String], options: Seq[(Any,String)])(implicit ctx: Context)
+
+@options.zipWithIndex.map {
+case ((value, text), index) => {
+@setup.filterCheckbox(form, key, index, value.toString, checks, Html(text))
+}
+}
diff --git a/modules/common/src/main/PimpedJson.scala b/modules/common/src/main/PimpedJson.scala
index 30262ab450..9b1d6278b7 100644
--- a/modules/common/src/main/PimpedJson.scala
+++ b/modules/common/src/main/PimpedJson.scala
@@ -26,6 +26,11 @@ trait PimpedJson {
def arr(key: String): Option[JsArray] =
(js \ key).asOpt[JsArray]
+ def ints(key: String): Option[List[Int]] =
+ (js \ key).asOpt[JsArray] map { arr ⇒
+ arr.value.toList map { v ⇒ v.asOpt[Int] } flatten
+ }
+
def get[A: Reads](key: String): Option[A] =
(js \ key).asOpt[A]
}
diff --git a/modules/setup/src/main/FilterConfig.scala b/modules/setup/src/main/FilterConfig.scala
index 260ed01c05..161f0c9985 100644
--- a/modules/setup/src/main/FilterConfig.scala
+++ b/modules/setup/src/main/FilterConfig.scala
@@ -4,62 +4,62 @@ import play.api.libs.json._
import chess.{ Variant, Mode, Speed }
import lila.common.PimpedJson._
+import lila.common.EloRange
case class FilterConfig(
- variant: Option[Variant],
- mode: Option[Mode],
- speed: Option[Speed],
- eloDiff: Option[Int]) {
+ variant: List[Variant],
+ mode: List[Mode],
+ speed: List[Speed],
+ eloRange: EloRange) {
def encode = RawFilterConfig(
- v = ~variant.map(_.id),
- m = mode.map(_.id) | -1,
- s = ~speed.map(_.id),
- e = ~eloDiff
+ v = variant.map(_.id),
+ m = mode.map(_.id),
+ s = speed.map(_.id),
+ e = eloRange.toString
)
def >> = (
variant map (_.id),
mode map (_.id),
speed map (_.id),
- eloDiff
+ eloRange.toString
).some
def render = Json.obj(
"variant" -> variant.map(_.toString),
"mode" -> mode.map(_.toString),
"speed" -> speed.map(_.id),
- "eloDiff" -> eloDiff
+ "eloRange" -> eloRange.toString
)
}
object FilterConfig {
+ val variants = List(Variant.Standard, Variant.Chess960)
+ val modes = Mode.all
+ val speeds = Speed.all
+
val default = FilterConfig(
- variant = none,
- mode = none,
- speed = none,
- eloDiff = none)
+ variant = variants,
+ mode = modes,
+ speed = speeds,
+ eloRange = EloRange.default)
- val variants = 0 :: Config.variants
- val modes = -1 :: Mode.all.map(_.id)
- val speeds = 0 :: Config.speeds
- 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 filter (0!=)
+ def <<(v: List[Int], m: List[Int], s: List[Int], e: String) = new FilterConfig(
+ variant = v map Variant.apply flatten,
+ mode = m map Mode.apply flatten,
+ speed = s map Speed.apply flatten,
+ eloRange = EloRange orDefault e
)
def fromDB(obj: JsObject): Option[FilterConfig] = for {
filter ← obj obj "filter"
- variant ← filter int "v"
- mode ← filter int "m"
- speed ← filter int "s"
- eloDiff ← filter int "e"
- config ← RawFilterConfig(variant, mode, speed, eloDiff).decode
+ variant ← filter ints "v"
+ mode ← filter ints "m"
+ speed ← filter ints "s"
+ eloRange ← filter str "e"
+ config ← RawFilterConfig(variant, mode, speed, eloRange).decode
} yield config
import lila.db.Tube
@@ -79,13 +79,13 @@ object FilterConfig {
)
}
-private[setup] case class RawFilterConfig(v: Int, m: Int, s: Int, e: Int) {
+private[setup] case class RawFilterConfig(v: List[Int], m: List[Int], s: List[Int], e: String) {
def decode = FilterConfig(
- variant = Variant(v),
- mode = Mode(m),
- speed = Speed(s),
- eloDiff = e.some filter (0!=)
+ variant = v map Variant.apply flatten,
+ mode = m map Mode.apply flatten,
+ speed = s map Speed.apply flatten,
+ eloRange = EloRange orDefault e
).some
}
diff --git a/modules/setup/src/main/FormFactory.scala b/modules/setup/src/main/FormFactory.scala
index 11ff59262f..65c4dabbce 100644
--- a/modules/setup/src/main/FormFactory.scala
+++ b/modules/setup/src/main/FormFactory.scala
@@ -1,28 +1,27 @@
package lila.setup
-import play.api.data._
-import play.api.data.Forms._
-
import chess.Variant
import lila.common.EloRange
import lila.db.api._
import lila.lobby.Color
import lila.user.Context
+import play.api.data._
+import play.api.data.Forms._
import tube.{ userConfigTube, anonConfigTube }
private[setup] final class FormFactory {
import Mappings._
- def filterFilled(implicit ctx: Context): Fu[Form[FilterConfig]] =
- filterConfig map filter(ctx).fill
+ def filterFilled(implicit ctx: Context): Fu[(Form[FilterConfig], FilterConfig)] =
+ filterConfig map { f ⇒ filter(ctx).fill(f) -> f }
def filter(ctx: Context) = Form(
mapping(
- "variant" -> optional(variant),
- "mode" -> mode(true),
- "speed" -> optional(speed),
- "eloDiff" -> optional(eloDiff)
+ "variant" -> list(variant),
+ "mode" -> list(rawMode(true)),
+ "speed" -> list(speed),
+ "eloRange" -> nonEmptyText
)(FilterConfig.<<)(_.>>)
)
@@ -30,7 +29,7 @@ private[setup] final class FormFactory {
def aiFilled(fen: Option[String])(implicit ctx: Context): Fu[Form[AiConfig]] =
aiConfig map { config ⇒
- ai(ctx) fill fen.fold(config) { f ⇒
+ ai(ctx) fill fen.fold(config) { f ⇒
config.copy(fen = f.some, variant = Variant.FromPosition)
}
}
@@ -51,7 +50,7 @@ private[setup] final class FormFactory {
def friendFilled(fen: Option[String])(implicit ctx: Context): Fu[Form[FriendConfig]] =
friendConfig map { config ⇒
- friend(ctx) fill fen.fold(config) { f ⇒
+ friend(ctx) fill fen.fold(config) { f ⇒
config.copy(fen = f.some, variant = Variant.FromPosition)
}
}
@@ -90,6 +89,6 @@ private[setup] final class FormFactory {
def hookConfig(implicit ctx: Context): Fu[HookConfig] = savedConfig map (_.hook)
- def savedConfig(implicit ctx: Context): Fu[UserConfig] =
+ def savedConfig(implicit ctx: Context): Fu[UserConfig] =
ctx.me.fold(AnonConfigRepo config ctx.req)(UserConfigRepo.config)
}
diff --git a/modules/setup/src/main/Mappings.scala b/modules/setup/src/main/Mappings.scala
index 1b90c4b0c8..e3129b9dae 100644
--- a/modules/setup/src/main/Mappings.scala
+++ b/modules/setup/src/main/Mappings.scala
@@ -13,14 +13,14 @@ object Mappings {
val variantWithFen = number.verifying(Config.variantsWithFen contains _)
val time = number.verifying(HookConfig.times contains _)
val increment = number.verifying(HookConfig.increments contains _)
- def mode(isAuth: Boolean) = optional(number
+ def mode(isAuth: Boolean) = optional(rawMode(isAuth))
+ def rawMode(isAuth: Boolean) = number
.verifying(HookConfig.modes contains _)
- .verifying(m ⇒ m == Mode.Casual.id || isAuth))
+ .verifying(m ⇒ m == Mode.Casual.id || isAuth)
val eloRange = optional(nonEmptyText.verifying(EloRange valid _))
val color = nonEmptyText.verifying(Color.names contains _)
val level = number.verifying(AiConfig.levels contains _)
val speed = number.verifying(Config.speeds contains _)
- val eloDiff = number.verifying(FilterConfig.eloDiffs contains _)
def fen(strict: Boolean) = optional {
nonEmptyText verifying { source ⇒ ~(Forsyth <<< source).map(_.situation playable strict) }
diff --git a/public/javascripts/big.js b/public/javascripts/big.js
index c2fc4e3aae..dbf0865851 100644
--- a/public/javascripts/big.js
+++ b/public/javascripts/big.js
@@ -2033,7 +2033,7 @@ var storage = {
$div.fadeOut(500);
}
return false;
- });
+ }).click();
$bot.on("click", "tr", function() {
location.href = $(this).find('a.watch').attr("href");
diff --git a/todo b/todo
index 927b4913b3..c8a584d180 100644
--- a/todo
+++ b/todo
@@ -57,4 +57,8 @@ customize sound notifications http://imgur.com/70WVyb5
opera issue http://en.lichess.org/forum/lichess-feedback/new-game-wont-show-on-games-list-opera#1
embedded games links http://2ls.ru/chessonline/
filter ranges http://en.lichess.org/forum/lichess-feedback/my-proposed-changes-with-filter-window#1
-takeback en passant http://fr.lichess.org/forum/general-chess-discussion/bug-with-take-back-and-en-passant#2
+
+deploy
+------
+db.config.update({filter:{$exists:1}},{$unset:{filter:1}},{multi:1})
+db.config_anon.update({filter:{$exists:1}},{$unset:{filter:1}},{multi:1})