let tournament owners disable the chat - closes #6436

chatRefactor
Thibault Duplessis 2020-04-22 10:39:30 -06:00
parent 2f8ddc6531
commit b13f73ffcd
9 changed files with 71 additions and 47 deletions

View File

@ -68,7 +68,7 @@ final class Tournament(
}
private[controllers] def canHaveChat(tour: Tour, json: Option[JsObject])(implicit ctx: Context): Boolean =
!ctx.kid && // no public chats for kids
tour.hasChat && !ctx.kid && // no public chats for kids
ctx.me.fold(!tour.isPrivate) { u => // anon can see public chats, except for private tournaments
(!tour.isPrivate || json.fold(true)(jsonHasMe) || isGranted(_.ChatTimeout)) && // private tournament that I joined or has ChatTimeout
env.chat.panic.allowed(u, tighter = tour.variant == chess.variant.Antichess)

View File

@ -118,7 +118,7 @@ object crud {
)
),
h2("Entry requirements"),
tournament.form.condition(form, auto = false, Nil),
tournament.form.condition(form, new TourFields(form), auto = false, Nil),
form3.action(form3.submit(trans.apply()))
)

View File

@ -39,8 +39,7 @@ object form {
fieldset(cls := "conditions")(
fields.advancedSettings,
div(cls := "form")(
fields.password,
condition(form, auto = true, teams = myTeams),
condition(form, fields, auto = true, teams = myTeams),
fields.startDate
)
),
@ -85,8 +84,7 @@ object form {
fieldset(cls := "conditions")(
fields.advancedSettings,
div(cls := "form")(
fields.password,
condition(form, auto = true, teams = myTeams)
condition(form, fields, auto = true, teams = myTeams)
)
),
form3.actions(
@ -107,60 +105,74 @@ object form {
if (auto) form3.hidden(field) else visible(field)
)
def condition(form: Form[_], auto: Boolean, teams: List[lila.hub.LightTeam])(implicit ctx: Context) = frag(
def condition(form: Form[_], fields: TourFields, auto: Boolean, teams: List[lila.hub.LightTeam])(
implicit ctx: Context
) = frag(
form3.split(
form3.group(form("conditions.nbRatedGame.nb"), raw("Minimum rated games"), half = true)(
fields.password,
(auto && teams.size > 0) option {
val baseField = form("conditions.teamMember.teamId")
val field = ctx.req.queryString get "team" flatMap (_.headOption) match {
case None => baseField
case Some(team) => baseField.copy(value = team.some)
}
form3.group(field, frag("Only members of team"), half = true)(
form3.select(_, List(("", "No Restriction")) ::: teams.map(_.pair))
)
}
),
form3.split(
form3.group(form("conditions.nbRatedGame.nb"), frag("Minimum rated games"), half = true)(
form3.select(_, Condition.DataForm.nbRatedGameChoices)
),
autoField(auto, form("conditions.nbRatedGame.perf")) { field =>
form3.group(field, raw("In variant"), half = true)(
form3.group(field, frag("In variant"), half = true)(
form3.select(_, ("", "Any") :: Condition.DataForm.perfChoices)
)
}
),
form3.split(
form3.group(form("conditions.minRating.rating"), raw("Minimum rating"), half = true)(
form3.group(form("conditions.minRating.rating"), frag("Minimum rating"), half = true)(
form3.select(_, Condition.DataForm.minRatingChoices)
),
autoField(auto, form("conditions.minRating.perf")) { field =>
form3.group(field, raw("In variant"), half = true)(form3.select(_, Condition.DataForm.perfChoices))
form3.group(field, frag("In variant"), half = true)(form3.select(_, Condition.DataForm.perfChoices))
}
),
form3.split(
form3.group(form("conditions.maxRating.rating"), raw("Maximum weekly rating"), half = true)(
form3.group(form("conditions.maxRating.rating"), frag("Maximum weekly rating"), half = true)(
form3.select(_, Condition.DataForm.maxRatingChoices)
),
autoField(auto, form("conditions.maxRating.perf")) { field =>
form3.group(field, raw("In variant"), half = true)(form3.select(_, Condition.DataForm.perfChoices))
form3.group(field, frag("In variant"), half = true)(form3.select(_, Condition.DataForm.perfChoices))
}
),
form3.split(
(ctx.me.exists(_.hasTitle) || isGranted(_.ManageTournament)) ?? {
form3.checkbox(
form("conditions.titled"),
raw("Only titled players"),
help = raw("Require an official title to join the tournament").some,
frag("Only titled players"),
help = frag("Require an official title to join the tournament").some,
half = true
)
},
form3.checkbox(
form("berserkable"),
raw("Allow Berserk"),
help = raw("Let players halve their clock time to gain an extra point").some,
frag("Allow Berserk"),
help = frag("Let players halve their clock time to gain an extra point").some,
half = true
),
input(tpe := "hidden", st.name := form("berserkable").name, value := "false") // hack allow disabling berserk
input(tpe := "hidden", st.name := form("berserkable").name, value := "false") // hack to allow disabling berserk
),
(auto && teams.size > 0) option {
val baseField = form("conditions.teamMember.teamId")
val field = ctx.req.queryString get "team" flatMap (_.headOption) match {
case None => baseField
case Some(team) => baseField.copy(value = team.some)
}
form3.group(field, raw("Only members of team"), half = false)(
form3.select(_, List(("", "No Restriction")) ::: teams.map(_.pair))
)
}
form3.split(
form3.checkbox(
form("hasChat"),
trans.chatRoom(),
help = frag("Let players discuss in a chat room").some,
half = true
),
input(tpe := "hidden", st.name := form("hasChat").name, value := "false") // hack to allow disabling chat
)
)
def startingPosition(field: Field) =
@ -240,7 +252,7 @@ final private class TourFields(form: Form[_])(implicit ctx: Context) {
def description =
form3.group(
form("description"),
raw("Tournament description"),
frag("Tournament description"),
help = frag("Anything special you want to tell the participants? Try to keep it short.").some
)(form3.textarea(_)(rows := 2))
def password =
@ -248,13 +260,14 @@ final private class TourFields(form: Form[_])(implicit ctx: Context) {
form3.group(
form("password"),
trans.password(),
help = trans.makePrivateTournament().some
help = trans.makePrivateTournament().some,
half = true
)(form3.input(_))
def startDate =
form3.group(
form("startDate"),
raw("Custom start date"),
help = raw("""This overrides the "Time before tournament starts" setting""").some
frag("Custom start date"),
help = frag("""This overrides the "Time before tournament starts" setting""").some
)(form3.flatpickr(_))
def advancedSettings = frag(
legend(trans.advancedSettings()),

View File

@ -86,7 +86,8 @@ object BSONHandlers {
winnerId = r strO "winner",
featuredId = r strO "featured",
spotlight = r.getO[Spotlight]("spotlight"),
description = r strO "description"
description = r strO "description",
hasChat = r boolO "chat" getOrElse true
)
}
def writes(w: BSON.Writer, o: Tournament) = $doc(
@ -115,7 +116,8 @@ object BSONHandlers {
"winner" -> o.winnerId,
"featured" -> o.featuredId,
"spotlight" -> o.spotlight,
"description" -> o.description
"description" -> o.description,
"chat" -> (!o.hasChat).option(false)
)
}

View File

@ -31,7 +31,8 @@ final class DataForm {
conditions = Condition.DataForm.AllSetup.default,
teamBattleByTeam = teamBattleId,
berserkable = true.some,
description = none
description = none,
hasChat = true.some
)
def edit(user: User, tour: Tournament) = form(user) fill TournamentSetup(
@ -49,7 +50,8 @@ final class DataForm {
conditions = Condition.DataForm.AllSetup(tour.conditions),
teamBattleByTeam = none,
berserkable = tour.berserkable.some,
description = tour.description
description = tour.description,
hasChat = tour.hasChat.some
)
private val nameType = text.verifying(
@ -85,7 +87,8 @@ final class DataForm {
"conditions" -> Condition.DataForm.all,
"teamBattleByTeam" -> optional(nonEmptyText),
"berserkable" -> optional(boolean),
"description" -> optional(nonEmptyText)
"description" -> optional(nonEmptyText),
"hasChat" -> optional(boolean)
)(TournamentSetup.apply)(TournamentSetup.unapply)
.verifying("Invalid clock", _.validClock)
.verifying("15s variant games cannot be rated", _.validRatedUltraBulletVariant)
@ -152,7 +155,8 @@ private[tournament] case class TournamentSetup(
conditions: Condition.DataForm.AllSetup,
teamBattleByTeam: Option[String],
berserkable: Option[Boolean],
description: Option[String]
description: Option[String],
hasChat: Option[Boolean]
) {
def validClock = (clockTime + clockIncrement) > 0

View File

@ -32,7 +32,8 @@ case class Tournament(
winnerId: Option[User.ID] = None,
featuredId: Option[String] = None,
spotlight: Option[Spotlight] = None,
description: Option[String] = None
description: Option[String] = None,
hasChat: Boolean = true
) {
def isCreated = status == Status.Created
@ -151,7 +152,8 @@ object Tournament {
startDate: Option[DateTime],
berserkable: Boolean,
teamBattle: Option[TeamBattle],
description: Option[String]
description: Option[String],
hasChat: Boolean
) = Tournament(
id = makeId,
name = name | {
@ -176,7 +178,8 @@ object Tournament {
case Some(startDate) => startDate plusSeconds scala.util.Random.nextInt(60)
case None => DateTime.now plusMinutes waitMinutes
},
description = description
description = description,
hasChat = hasChat
)
def scheduleAs(sched: Schedule, minutes: Int) = Tournament(

View File

@ -74,7 +74,8 @@ final class TournamentApi(
DataForm.startingPosition(setup.position | chess.StartingPosition.initial.fen, setup.realVariant),
berserkable = setup.berserkable | true,
teamBattle = setup.teamBattleByTeam map TeamBattle.init,
description = setup.description
description = setup.description,
hasChat = setup.hasChat | true
) |> { tour =>
tour.perfType.fold(tour) { perfType =>
tour.copy(conditions = setup.conditions.convert(perfType, myTeams.view.map(_.pair).toMap))
@ -97,7 +98,8 @@ final class TournamentApi(
position = DataForm.startingPosition(position | chess.StartingPosition.initial.fen, realVariant),
noBerserk = !(~berserkable),
teamBattle = old.teamBattle,
description = description
description = description,
hasChat = data.hasChat | true
) |> { tour =>
tour.perfType.fold(tour) { perfType =>
tour.copy(conditions = conditions.convert(perfType, myTeams.view.map(_.pair).toMap))

View File

@ -27,9 +27,8 @@ final class TournamentRepo(val coll: Coll, playerCollName: CollName)(
private def variantSelect(variant: Variant) =
if (variant.standard) $doc("variant" $exists false)
else $doc("variant" -> variant.id)
private val nonEmptySelect = $doc("nbPlayers" $ne 0)
private def hasPlayersSelect(nb: Int) = $doc("nbPlayers" $gte nb)
private[tournament] val selectUnique = $doc("schedule.freq" -> "unique")
private val nonEmptySelect = $doc("nbPlayers" $ne 0)
private[tournament] val selectUnique = $doc("schedule.freq" -> "unique")
def byId(id: Tournament.ID): Fu[Option[Tournament]] = coll.byId[Tournament](id)

View File

@ -71,7 +71,8 @@ final class CrudApi(tournamentRepo: TournamentRepo) {
startDate = none,
berserkable = true,
teamBattle = none,
description = none
description = none,
hasChat = true
)
private def updateTour(tour: Tournament, data: CrudForm.Data) = {