rewrite tournament forms

fishnetErrorReporting
Thibault Duplessis 2018-11-29 16:43:52 +07:00
parent 5de518f705
commit f102560484
21 changed files with 140 additions and 259 deletions

View File

@ -45,7 +45,7 @@ trait FormHelper { self: I18nHelper =>
def id(field: Field) = s"$idPrefix-${field.id}"
def split(html: Html) = Html {
s"""<div class="form-group form-split">$html</div>"""
s"""<div class="form-split">$html</div>"""
}
def group(

View File

@ -11,7 +11,7 @@
@form3.group(form("lang"), Html("Language"))(form3.select(_, lila.i18n.LangList.choices))
@form3.split {
@form3.checkbox(form("enabled"), Html("Enabled"), help = Html("Display the event").some, half = true)
@form3.group(form("homepageHours"), Html("Hours on homepage (0 to 24)"), half = true, help = Html("Ask on slack first!").some)(form3.input(_))
@form3.group(form("homepageHours"), Html("Hours on homepage (0 to 24)"), half = true, help = Html("Ask on slack first!").some)(form3.input(_, typ = "number", required = true))
}
@form3.action(form3.submit(trans.apply()))

View File

@ -3,51 +3,31 @@
@import lila.tournament.Condition
@autoField(fieldName: String)(visible: Field => Html) = {
@if(auto) { @base.form.hidden(form(fieldName)) } else { @visible(form(fieldName)) }
@if(auto) { @form3.hidden(form(fieldName)) } else { @visible(form(fieldName)) }
}
<div>
@base.form.group(form("conditions.nbRatedGame.nb"), Html("Minimum rated games"), half = !auto) { field =>
@base.form.select(field, Condition.DataForm.nbRatedGameChoices)
}
@autoField("conditions.nbRatedGame.perf") { field =>
@base.form.group(field, Html("In variant"), half = true) { field =>
@base.form.select(field, ("", "Any") :: Condition.DataForm.perfChoices)
}
}
</div>
<div>
@base.form.group(form("conditions.minRating.rating"), Html("Minimum rating"), half = !auto) { field =>
@base.form.select(field, Condition.DataForm.minRatingChoices)
}
@autoField("conditions.minRating.perf") { field =>
@base.form.group(field, Html("In variant"), half = true) { field =>
@base.form.select(field, Condition.DataForm.perfChoices)
}
}
</div>
<div>
@base.form.group(form("conditions.maxRating.rating"), Html("Maximum weekly rating"), half = !auto) { field =>
@base.form.select(field, Condition.DataForm.maxRatingChoices)
}
@autoField("conditions.maxRating.perf") { field =>
@base.form.group(field, Html("In variant"), half = true) { field =>
@base.form.select(field, Condition.DataForm.perfChoices)
}
}
</div>
<div>
@base.form.group(form("conditions.titled"), Html("Only titled players"), half = true) { field =>
@base.form.select(field, booleanChoices)
@form3.split {
@form3.group(form("conditions.nbRatedGame.nb"), Html("Minimum rated games"), half = true)(form3.select(_, Condition.DataForm.nbRatedGameChoices))
@autoField("conditions.nbRatedGame.perf") { field =>
@form3.group(field, Html("In variant"), half = true)(form3.select(_, ("", "Any") :: Condition.DataForm.perfChoices))
}
@base.form.group(form("berserkable"), Html("Allow Berserk"), half = true) { field =>
@base.form.select(field, booleanChoices)
}
</div>
@form3.split {
@form3.group(form("conditions.minRating.rating"), Html("Minimum rating"), half = true)(form3.select(_, Condition.DataForm.minRatingChoices))
@autoField("conditions.minRating.perf") { field =>
@form3.group(field, Html("In variant"), half = true)(form3.select(_, Condition.DataForm.perfChoices))
}
}
@form3.split {
@form3.group(form("conditions.maxRating.rating"), Html("Maximum weekly rating"), half = true)(form3.select(_, Condition.DataForm.maxRatingChoices))
@autoField("conditions.maxRating.perf") { field =>
@form3.group(field, Html("In variant"), half = true)(form3.select(_, Condition.DataForm.perfChoices))
}
}
@form3.split {
@form3.checkbox(form("conditions.titled"), Html("Only titled players"), help = Html("Require an official title to join the tournament").some, half = true)
@form3.checkbox(form("berserkable"), Html("Allow Berserk"), help = Html("Let players halve their clock time to gain an extra point").some, half = true)
}
@if(auto && teams.size > 0) {
<div>
@base.form.group(form("conditions.teamMember.teamId"), Html("Only members of team"), half = false) { field =>
@base.form.select(field, List(("", "No Restriction")) ::: teams)
}
</div>
@form3.group(form("conditions.teamMember.teamId"), Html("Only members of team"), half = false)(form3.select(_, List(("", "No Restriction")) ::: teams))
}

View File

@ -3,7 +3,7 @@
@layout(title = "New tournament") {
<div class="tour_crud content_box small_box no_padding">
<h1 class="lichess_title">New tournament</h1>
<form class="content_box_content material form" action="@routes.TournamentCrud.create" method="POST">
<form class="content_box_content form3" action="@routes.TournamentCrud.create" method="POST">
@inForm(form)
</form>
</div>

View File

@ -6,7 +6,7 @@
<a href="@routes.Tournament.show(tour.id)">@tour.fullName</a>
<span>Created by @usernameOrId(tour.createdBy) on @showDate(tour.createdAt)</span>
</h1>
<form class="content_box_content material form" action="@routes.TournamentCrud.update(tour.id)" method="POST">
<form class="content_box_content form3" action="@routes.TournamentCrud.update(tour.id)" method="POST">
@inForm(form)
</form>
</div>

View File

@ -4,47 +4,30 @@
@import lila.tournament.crud.CrudForm._
@import lila.rating.PerfType
<div>
@base.form.group(form("date"), Html("Start date <strong>UTC</strong>"), half = true) { field =>
@base.form.flatpickr(field)
}
@base.form.group(form("name"), Html("Name"), half = true) { field =>
@base.form.input(field)
}
</div>
<div>
@base.form.group(form("homepageHours"), Html(s"Hours on homepage (0 to $maxHomepageHours)"), half = true) { field =>
@base.form.input(field, "Ask first!".some)
}
@base.form.group(form("image"), Html("Custom icon"), half = true) { field =>
@base.form.select(field, imageChoices)
}
</div>
@base.form.group(form("headline"), Html("Homepage headline")) { field =>
@base.form.input(field)
@form3.split {
@form3.group(form("date"), Html("Start date <strong>UTC</strong>"), half = true)(form3.flatpickr(_))
@form3.group(form("name"), Html("Name"), half = true)(form3.input(_))
}
@base.form.group(form("description"), Html("Full description | Link: [text](url)")) { field =>
<textarea name="@field.name" id="@field.id">@field.value</textarea>
@form3.split {
@form3.group(form("homepageHours"), Html(s"Hours on homepage (0 to $maxHomepageHours)"), half = true, help = Html("Ask on slack first!").some)(form3.input(_, typ = "number", required = true))
@form3.group(form("image"), Html("Custom icon"), half = true)(form3.select(_, imageChoices))
}
<div>
@base.form.group(form("variant"), Html("Variant"), half = true) { field =>
@base.form.select(field, translatedVariantChoicesWithVariants.map(x => x._1 -> x._2))
}
@base.form.group(form("minutes"), Html("Duration in minutes"), half = true) { field =>
@base.form.input(field)
}
</div>
<div>
@base.form.group(form("clockTime"), Html("Clock time"), half = true) { field =>
@base.form.select(field, clockTimePrivateChoices)
}
@base.form.group(form("clockIncrement"), Html("Clock increment"), half = true) { field =>
@base.form.select(field, clockIncrementPrivateChoices)
}
</div>
@base.form.group(form("position"), trans.startPosition()) { field =>
@tournament.startingPosition(field)
@form3.group(form("headline"), Html("Homepage headline"))(form3.input(_, required = true))
@form3.group(form("description"), Html("Full description | Link: [text](url)"))(form3.textarea(_, rows = 6.some))
@form3.split {
@form3.group(form("variant"), Html("Variant"), half = true) { f =>
@form3.select(f, translatedVariantChoicesWithVariants.map(x => x._1 -> x._2))
}
@form3.group(form("minutes"), Html("Duration in minutes"), half = true)(form3.input(_, typ = "number", required = true))
}
@form3.split {
@form3.group(form("clockTime"), Html("Clock time"), half = true)(form3.select(_, clockTimeChoices))
@form3.group(form("clockIncrement"), Html("Clock increment"), half = true)(form3.select(_, clockIncrementChoices))
}
@form3.group(form("position"), trans.startPosition())(tournament.startingPosition(_))
<hr>
<h2>Conditions of entry</h2>
@tournament.conditionForm(form, auto = false, Nil)
@base.form.submit()
@form3.action(form3.submit(trans.apply()))

View File

@ -1,11 +1,5 @@
@(title: String, evenMoreJs: Html = emptyHtml)(body: Html)(implicit ctx: Context)
@moreCss = {
@cssTag("flatpickr.css")
@cssTag("material.form.css")
@cssTag("tournament.crud.css")
}
@moreJs = {
@flatpickrTag
@embedJs {
@ -17,5 +11,5 @@ $(function() { $(".flatpickr").flatpickr(); })
@mod.layout(
title = title,
active = "tour",
moreCss = moreCss,
moreCss = cssTags("flatpickr.css", "form3.css", "tournament.crud.css"),
moreJs = moreJs)(body)

View File

@ -7,76 +7,42 @@
@flatpickrTag
@jsTag("tournamentForm.js")
}
@moreCss = {
@cssTag("flatpickr.css")
@cssTag("material.form.css")
@cssTag("tournament.form.css")
}
@tournament.layout(
title = trans.newTournament.txt(),
moreCss = moreCss,
moreCss = cssTags("flatpickr.css", "form3.css", "tournament.form.css"),
moreJs = moreJs) {
<div id="tournament">
<div class="content_box small_box tournament_box">
<h1>@trans.createANewTournament()</h1>
<form class="plain create content_box_content" action="@routes.Tournament.create" method="POST">
<input type="hidden" name="@form("system").id" value="1" />
@globalError(form)
<table>
<tbody>
<tr>
<th><label for="isprivate">@trans.isPrivate()</label></th>
<td><input type="checkbox" name="private" id="isprivate" @if(form("private").value.exists(lila.common.Form.trueish)) { checked } /></td>
</tr>
<tr class="password">
<th><label for="@form("password").id">@trans.password()</label></th>
<td>@base.form.input(form("password"))</td>
</tr>
@if(lila.tournament.DataForm.canPickName(me)) {
<tr class="name">
<th><label for="@form("name").id">@trans.name()</label></th>
<td>
<style>.tournament_box form.create input[name=name] { width: 15em!important; }</style>
@base.form.input(form("name")) Arena<br />
@errMsg(form("name"))
<strong>@trans.safeTournamentName()<br />
@trans.inappropriateNameWarning()</strong><br />
@trans.emptyTournamentName()
</td>
</tr>
}
<tr class="variant">
<th><label for="@form("variant").id">@trans.variant()</label></th>
<td>@base.form.select(form("variant"), translatedVariantChoicesWithVariants.map(x => x._1 -> x._2))</td>
</tr>
<tr class="position">
<th><label for="@form("position").id">@trans.startPosition()</label></th>
<td>
@tournament.startingPosition(form("position"))
</td>
</tr>
<tr>
<th><label for="@form("mode").id">@trans.mode()</label></th>
<td>
@base.form.select(form("mode"), translatedModeChoicesTournament.map(x => x._1 -> x._2))
</td>
</tr>
<tr class="time">
<th><label>@trans.timeControl()</label></th>
<td class="inline"></td>
</tr>
<tr class="minutes">
<th><label for="@form("minutes").id">@trans.duration()</label></th>
<td></td>
</tr>
<tr>
<th><label for="@form("waitMinutes").id">@trans.timeBeforeTournamentStarts()</label></th>
<td>@base.form.select(form("waitMinutes"), waitMinuteChoices)</td>
</tr>
</tbody>
</table>
<form class="form3 create content_box_content" action="@routes.Tournament.create" method="POST">
@if(lila.tournament.DataForm.canPickName(me)) {
@form3.group(form("name"), trans.name()) { f =>
<div>
@form3.input(f) Arena<br />
<small class="form-help">
@trans.safeTournamentName()<br />
@trans.inappropriateNameWarning()<br>
@trans.emptyTournamentName()
</small>
</div>
}
}
@form3.split {
@form3.checkbox(form("rated"), trans.rated(), help = Html("Games are rated<br>and impact players ratings").some)
@form3.group(form("variant"), trans.variant(), half = true)(form3.select(_, translatedVariantChoicesWithVariants.map(x => x._1 -> x._2)))
}
@form3.group(form("position"), trans.startPosition(), klass = "position")(tournament.startingPosition(_))
@form3.split {
@form3.group(form("clockTime"), Html("Clock initial time"), half = true)(form3.select(_, clockTimeChoices))
@form3.group(form("clockIncrement"), Html("Clock increment"), half = true)(form3.select(_, clockIncrementChoices))
}
@form3.split {
@form3.group(form("minutes"), trans.duration(), half = true)(form3.select(_, minuteChoices))
@form3.group(form("waitMinutes"), trans.timeBeforeTournamentStarts(), half = true)(form3.select(_, waitMinuteChoices))
}
@form3.globalError(form)
<fieldset class="conditions">
<legend>&nbsp;@trans.advancedSettings()&nbsp;</legend>
@errMsg(form("conditions"))
@ -85,35 +51,18 @@ moreJs = moreJs) {
@trans.fewerPlayers()
<a class="show blue">@trans.showAdvancedSettings()</a>
</p>
<div class="material form">
<div class="form">
@form3.group(form("password"), trans.password(), help = Html("Make the tournament private, and restrict access with a password").some)(form3.input(_))
@tournament.conditionForm(form, auto = true, teams = teams)
@base.form.group(form("startDate"), Html("Custom start date"), help = Html("""This overrides the "Time before tournament starts" setting""").some) { field =>
@base.form.flatpickr(field)
}
<input type="hidden" name="@form("berserkable").name" value="false"> @* hack allow disabling berserk *@
@form3.group(form("startDate"), Html("Custom start date"), help = Html("""This overrides the "Time before tournament starts" setting""").some)(form3.flatpickr(_))
</div>
</fieldset>
<button type="submit" class="submit button" data-icon="g">
@trans.createANewTournament()
</button>
<br /><br />
@form3.actions {
<a href="@routes.Tournament.home()">@trans.cancel()</a>
@form3.submit(trans.createANewTournament(), icon = "g".some)
}
</form>
<div class="none private_time">
@base.form.select(form("clockTime"), clockTimePrivateChoices)
+
@base.form.select(form("clockIncrement"), clockIncrementPrivateChoices)
</div>
<div class="none public_time">
@base.form.select(form("clockTime"), clockTimeChoices)
+
@base.form.select(form("clockIncrement"), clockIncrementChoices)
</div>
<div class="none private_minutes">
@base.form.select(form("minutes"), minutePrivateChoices)
</div>
<div class="none public_minutes">
@base.form.select(form("minutes"), minuteChoices)
</div>
</div>
<div class="content_box small_box faq_box tournament_box">
<div class="content_box_content">@tournament.faq()</div>

View File

@ -55,7 +55,7 @@ s"${usernameOrId(winnerId)} takes the prize home!"
</div>
@if(tour.isCreated) {
<div id="tournament_faq" class="none">
@faq(tour.mode.rated.some, tour.system.some, tour.`private`.option(tour.id))
@faq(tour.mode.rated.some, tour.system.some, tour.isPrivate.option(tour.id))
</div>
}
}

View File

@ -1,5 +1,6 @@
@(field: play.api.data.Field)(implicit ctx: Context)
<select name="@field.name">
<select id="@form3.id(field)" name="@field.name" class="form-control">
@defining(chess.StartingPosition.initial) { v =>
<option value="@v.fen" @(if(field.value == Some(v.fen)) "selected" else "")>@v.name</option>
}

View File

@ -64,7 +64,6 @@ object BSONHandlers {
variant = variant,
position = position,
mode = r.intO("mode") flatMap Mode.apply getOrElse Mode.Rated,
`private` = r boolD "private",
password = r.strO("password"),
conditions = conditions,
noBerserk = r boolD "noBerserk",
@ -92,7 +91,6 @@ object BSONHandlers {
"variant" -> o.variant.some.filterNot(_.standard).map(_.id),
"fen" -> o.position.some.filterNot(_.initial).map(_.fen),
"mode" -> o.mode.some.filterNot(_.rated).map(_.id),
"private" -> w.boolO(o.`private`),
"password" -> o.password,
"conditions" -> o.conditions.ifNonEmpty,
"noBerserk" -> w.boolO(o.noBerserk),

View File

@ -24,9 +24,9 @@ final class DataForm {
startDate = none,
variant = chess.variant.Standard.key.some,
position = StartingPosition.initial.fen.some,
`private` = false,
password = None,
mode = Mode.Rated.id.some,
mode = none,
rated = true.some,
conditionsOption = Condition.DataForm.AllSetup.default.some,
berserkable = true.some
)
@ -42,24 +42,22 @@ final class DataForm {
private lazy val create = Form(mapping(
"name" -> optional(nameType),
"clockTime" -> numberInDouble(clockTimePrivateChoices),
"clockIncrement" -> numberIn(clockIncrementPrivateChoices),
"minutes" -> numberIn(minutePrivateChoices),
"clockTime" -> numberInDouble(clockTimeChoices),
"clockIncrement" -> numberIn(clockIncrementChoices),
"minutes" -> numberIn(minuteChoices),
"waitMinutes" -> optional(numberIn(waitMinuteChoices)),
"startDate" -> optional(inTheFuture(ISODateOrTimestamp.isoDateOrTimestamp)),
"variant" -> optional(nonEmptyText.verifying(v => guessVariant(v).isDefined)),
"position" -> optional(nonEmptyText),
"mode" -> optional(number.verifying(Mode.all map (_.id) contains _)),
"private" -> tolerantBoolean,
"mode" -> optional(number.verifying(Mode.all map (_.id) contains _)), // deprecated, use rated
"rated" -> optional(boolean),
"password" -> optional(nonEmptyText),
"conditions" -> optional(Condition.DataForm.all),
"berserkable" -> optional(boolean)
)(TournamentSetup.apply)(TournamentSetup.unapply)
.verifying("Invalid clock", _.validClock)
.verifying("15s variant games cannot be rated", _.validRatedUltraBulletVariant)
.verifying("Increase tournament duration, or decrease game clock", _.validTiming)
.verifying("These settings will only work for private tournaments", _.validPublic) // very rare, do not translate
)
.verifying("Increase tournament duration, or decrease game clock", _.validTiming))
}
object DataForm {
@ -70,27 +68,21 @@ object DataForm {
import chess.variant._
val clockTimes: Seq[Double] = Seq(0d, 1 / 4d, 1 / 2d, 3 / 4d, 1d, 3 / 2d) ++ (2d to 7d by 1d)
val clockTimesPrivate: Seq[Double] = clockTimes ++ (10d to 30d by 5d) ++ (40d to 60d by 10d)
val clockTimes: Seq[Double] = Seq(0d, 1 / 4d, 1 / 2d, 3 / 4d, 1d, 3 / 2d) ++ (2d to 7d by 1d) ++ (10d to 30d by 5d) ++ (40d to 60d by 10d)
val clockTimeDefault = 2d
private def formatLimit(l: Double) =
chess.Clock.Config(l * 60 toInt, 0).limitString + {
if (l <= 1) " minute" else " minutes"
}
val clockTimeChoices = optionsDouble(clockTimes, formatLimit)
val clockTimePrivateChoices = optionsDouble(clockTimesPrivate, formatLimit)
val clockIncrements = 0 to 2 by 1
val clockIncrementsPrivate = clockIncrements ++ (3 to 7) ++ (10 to 30 by 5) ++ (40 to 60 by 10)
val clockIncrements = (0 to 2 by 1) ++ (3 to 7) ++ (10 to 30 by 5) ++ (40 to 60 by 10)
val clockIncrementDefault = 0
val clockIncrementChoices = options(clockIncrements, "%d second{s}")
val clockIncrementPrivateChoices = options(clockIncrementsPrivate, "%d second{s}")
val minutes = (20 to 60 by 5) ++ (70 to 120 by 10)
val minutesPrivate = minutes ++ (150 to 360 by 30)
val minutes = (20 to 60 by 5) ++ (70 to 120 by 10) ++ (150 to 360 by 30)
val minuteDefault = 45
val minuteChoices = options(minutes, "%d minute{s}")
val minutePrivateChoices = options(minutesPrivate, "%d minute{s}")
val waitMinutes = Seq(1, 2, 3, 5, 10, 15, 20, 30, 45, 60)
val waitMinuteChoices = options(waitMinutes, "%d minute{s}")
@ -121,8 +113,8 @@ private[tournament] case class TournamentSetup(
startDate: Option[DateTime],
variant: Option[String],
position: Option[String],
mode: Option[Int],
`private`: Boolean,
mode: Option[Int], // deprecated, use rated
rated: Option[Boolean],
password: Option[String],
conditionsOption: Option[Condition.DataForm.AllSetup],
berserkable: Option[Boolean]
@ -134,13 +126,7 @@ private[tournament] case class TournamentSetup(
def validTiming = (minutes * 60) >= (3 * estimatedGameDuration)
def validPublic = `private` || {
DataForm.clockTimes.contains(clockTime) &&
DataForm.clockIncrements.contains(clockIncrement) &&
DataForm.minutes.contains(minutes)
}
def realMode = mode.fold(Mode.default)(Mode.orDefault)
def realMode = Mode(rated.orElse(mode.map(Mode.Rated.id ==)) | true)
def realVariant = variant.flatMap(DataForm.guessVariant) | chess.variant.Standard

View File

@ -84,7 +84,7 @@ final class JsonView(
Json.obj("name" -> tour.name, "url" -> url)
}).add("position" -> tour.position.some.filterNot(_.initial).map(positionJson))
.add("schedule" -> tour.schedule.map(scheduleJson))
.add("private" -> tour.`private`)
.add("private" -> tour.isPrivate)
.add("isRecentlyFinished" -> tour.isRecentlyFinished)
.add("secondsToFinish" -> tour.isStarted.option(tour.secondsToFinish))
.add("secondsToStart" -> tour.isCreated.option(tour.secondsToStart))

View File

@ -50,7 +50,7 @@ final class ScheduleJsonView(lightUser: LightUser.Getter) {
"status" -> tour.status.id,
"perf" -> tour.perfType.map(perfJson)
).add("hasMaxRating", tour.conditions.maxRating.isDefined)
.add("private", tour.`private`)
.add("private", tour.isPrivate)
.add("position", tour.position.some.filterNot(_.initial) map positionJson)
.add("schedule", tour.schedule map scheduleJson)

View File

@ -19,7 +19,6 @@ case class Tournament(
variant: chess.variant.Variant,
position: StartingPosition,
mode: Mode,
`private`: Boolean,
password: Option[String] = None,
conditions: Condition.All,
noBerserk: Boolean = false,
@ -37,7 +36,7 @@ case class Tournament(
def isStarted = status == Status.Started
def isFinished = status == Status.Finished
def isPrivate = `private`
def isPrivate = password.isDefined
def fullName = schedule.map(_.freq).fold(s"$name $system") {
case Schedule.Freq.ExperimentalMarathon | Schedule.Freq.Marathon | Schedule.Freq.Unique => name
@ -140,7 +139,6 @@ object Tournament {
variant: chess.variant.Variant,
position: StartingPosition,
mode: Mode,
`private`: Boolean,
password: Option[String],
waitMinutes: Int,
startDate: Option[DateTime],
@ -161,7 +159,6 @@ object Tournament {
variant = variant,
position = position,
mode = mode,
`private` = `private`,
password = password,
conditions = Condition.All.empty,
noBerserk = !berserkable,
@ -184,7 +181,6 @@ object Tournament {
variant = sched.variant,
position = sched.position,
mode = Mode.Rated,
`private` = false,
conditions = sched.conditions,
schedule = Some(sched),
startsAt = sched.at

View File

@ -55,12 +55,11 @@ final class TournamentApi(
waitMinutes = setup.waitMinutes | DataForm.waitMinuteDefault,
startDate = setup.startDate,
mode = setup.realMode,
`private` = setup.`private`,
password = setup.password ifTrue setup.`private`,
password = setup.password,
system = System.Arena,
variant = setup.realVariant,
position = DataForm.startingPosition(setup.position | chess.StartingPosition.initial.fen, setup.realVariant),
berserkable = setup.berserkable | true
berserkable = setup.berserkable.pp("berserkable") | true
) |> { tour =>
tour.perfType.fold(tour) { perfType =>
tour.copy(conditions = setup.conditions.convert(perfType, myTeams toMap))

View File

@ -56,7 +56,6 @@ final class CrudApi {
variant = chess.variant.Standard,
position = chess.StartingPosition.initial,
mode = chess.Mode.Rated,
`private` = false,
password = None,
waitMinutes = 0,
startDate = none,

View File

@ -20,8 +20,8 @@ object CrudForm {
lazy val apply = Form(mapping(
"name" -> nonEmptyText(minLength = 3, maxLength = 40),
"homepageHours" -> number(min = 0, max = maxHomepageHours),
"clockTime" -> numberInDouble(clockTimePrivateChoices),
"clockIncrement" -> numberIn(clockIncrementPrivateChoices),
"clockTime" -> numberInDouble(clockTimeChoices),
"clockIncrement" -> numberIn(clockIncrementChoices),
"minutes" -> number(min = 20, max = 1440),
"variant" -> number.verifying(Variant exists _),
"position" -> nonEmptyText.verifying(DataForm.positions contains _),

View File

@ -1,45 +1,19 @@
$(function() {
var $check = $('#tournament #isprivate');
var $time = $('#tournament tr.time td');
var $minutes = $('#tournament tr.minutes td');
function replace($el, $paste) {
var prvVal = $el.children().first().val();
$el.html($paste.html());
if (prvVal) {
$el.children().first().val(prvVal);
}
}
function showPrivate() {
var v = $check.prop('checked');
$('#tournament form').toggleClass('private', v);
if (v) {
$('#tournament form input[name=password]').focus();
replace($time, $('#tournament .private_time'));
replace($minutes, $('#tournament .private_minutes'));
} else {
replace($time, $('#tournament .public_time'));
replace($minutes, $('#tournament .public_minutes'));
}
};
$check.on('change', showPrivate);
showPrivate();
var $variant = $('#tournament tr.variant select');
var $position = $('#tournament tr.position');
var $variant = $('#form3-variant');
var $position = $('.form3 .position');
function showPosition() {
$position.toggleNone($variant.val() == 1);
};
$variant.on('change', showPosition);
showPosition();
$('.conditions a.show').on('click', function() {
$('form.create .conditions a.show').on('click', function() {
$(this).remove();
$('.conditions .form').show();
$('form.create .conditions').addClass('visible');
});
$(".flatpickr").flatpickr({
$("form.create .flatpickr").flatpickr({
minDate: 'today',
maxDate: new Date(Date.now() + 1000 * 3600 * 24 * 31),
dateFormat: 'Z',

View File

@ -52,6 +52,16 @@ body.dark .form3 .form-control {
color: #dc3545;
}
.form3 .form-help {
font-size: 0.8em;
margin-top: .25rem;
color: #6c757d;
line-height: 1em;
}
body.dark .form3 .form-help {
color: #8a9299;
}
.form3 .form-check {
position: relative;
display: block;

View File

@ -1,14 +1,26 @@
#tournament form fieldset {
#form3-name {
width: 48%!important;
display: inline-block;
}
#tournament form.create .conditions {
margin: 1.5em 0;
border-color: rgba(128,128,128,0.3);
}
#tournament form fieldset legend {
#tournament form.create .conditions legend {
text-align: center;
}
#tournament form fieldset p {
#tournament form.create .conditions p {
margin: 20px;
}
#tournament form fieldset .material {
#tournament form.create .conditions .form {
display: none;
margin: 40px 20px -20px 20px;
}
#tournament form.create .conditions.visible {
margin: 0;
padding: 0;
border-left: none;
border-right: none;
}
#tournament form.create .conditions.visible .form {
display: block;
}