diff --git a/modules/relay/src/main/RelayTour.scala b/modules/relay/src/main/RelayTour.scala index 794d15ac1bb4..7c216ba59117 100644 --- a/modules/relay/src/main/RelayTour.scala +++ b/modules/relay/src/main/RelayTour.scala @@ -1,6 +1,7 @@ package lila.relay import reactivemongo.api.bson.Macros.Annotations.Key +import io.mola.galimatias.URL import lila.core.i18n.Language import lila.core.id.ImageId @@ -81,11 +82,13 @@ object RelayTour: format: Option[String], tc: Option[String], fideTc: Option[FideTC], - players: Option[String] + location: Option[String], + players: Option[String], + website: Option[URL], + standings: Option[URL] ): - val all = List(format, tc, fideTc, players).flatten - export all.nonEmpty - override def toString = all.mkString(" | ") + def nonEmpty = List(format, tc, fideTc, location, players, website, standings).flatten.nonEmpty + override def toString = List(format, tc, fideTc, location, players).mkString(" | ") lazy val fideTcOrGuess: FideTC = fideTc | tc .map(_.trim.toLowerCase.replace("classical", "standard")) diff --git a/modules/relay/src/main/RelayTourForm.scala b/modules/relay/src/main/RelayTourForm.scala index 6ec90a580670..80afdeea8198 100644 --- a/modules/relay/src/main/RelayTourForm.scala +++ b/modules/relay/src/main/RelayTourForm.scala @@ -3,6 +3,7 @@ package lila.relay import play.api.data.* import play.api.data.Forms.* import play.api.data.format.Formatter +import io.mola.galimatias.URL import lila.common.Form.{ cleanText, cleanNonEmptyText, formatter, into, numberIn, typeIn, url } import lila.core.perm.Granter @@ -21,10 +22,13 @@ final class RelayTourForm(langList: lila.core.i18n.LangList): private val fideTcMapping: Mapping[FideTC] = typeIn[FideTC](FideTC.values.toSet) private val infoMapping = mapping( - "format" -> optional(cleanText(maxLength = 80)), - "tc" -> optional(cleanText(maxLength = 80)), - "fideTc" -> optional(fideTcMapping), - "players" -> optional(cleanText(maxLength = 120)) + "format" -> optional(cleanText(maxLength = 80)), + "tc" -> optional(cleanText(maxLength = 80)), + "fideTc" -> optional(fideTcMapping), + "location" -> optional(cleanText(maxLength = 80)), + "players" -> optional(cleanText(maxLength = 120)), + "website" -> optional(url.field), + "standings" -> optional(url.field) )(RelayTour.Info.apply)(unapply) private val pinnedStreamMapping = mapping( @@ -118,7 +122,7 @@ object RelayTourForm: object Data: - val empty = Data(RelayTour.Name(""), RelayTour.Info(none, none, none, none)) + val empty = Data(RelayTour.Name(""), RelayTour.Info(none, none, none, none, none, none, none)) def make(tg: RelayTour.WithGroupTours) = import tg.* diff --git a/modules/relay/src/main/ui/FormUi.scala b/modules/relay/src/main/ui/FormUi.scala index e37c875cf8e8..8e5df5b4eacb 100644 --- a/modules/relay/src/main/ui/FormUi.scala +++ b/modules/relay/src/main/ui/FormUi.scala @@ -428,9 +428,8 @@ final class FormUi(helpers: Helpers, ui: RelayUi, tourUi: RelayTourUi): half = true )(form3.input(_)), form3.group( - form("info.players"), - "Top players", - help = frag("Mention up to 4 of the best players participating").some, + form("info.location"), + "Tournament Location", half = true )(form3.input(_)) ), @@ -453,6 +452,26 @@ final class FormUi(helpers: Helpers, ui: RelayUi, tourUi: RelayTourUi): tc.toString -> tc.toString.capitalize ) ), + form3.group( + form("info.players"), + "Top players", + help = frag("Mention up to 4 of the best players participating").some, + half = true + )(form3.input(_)), + form3.split( + form3.group( + form("info.website"), + "Official Website", + help = frag("External website URL").some, + half = true + )(form3.input(_)), + form3.group( + form("info.standings"), + "Official Standings", + help = frag("External website URL, e.g. chess-results.com, info64.org").some, + half = true + )(form3.input(_)) + ), form3.group( form("markdown"), trb.fullDescription(), diff --git a/ui/analyse/src/study/relay/interfaces.ts b/ui/analyse/src/study/relay/interfaces.ts index 83e09ee640b1..48115345649c 100644 --- a/ui/analyse/src/study/relay/interfaces.ts +++ b/ui/analyse/src/study/relay/interfaces.ts @@ -37,7 +37,10 @@ export interface RelayTourInfo { format?: string; tc?: string; fideTc?: string; + location?: string; players?: string; + website?: string; + standings?: string; } export type RelayTourDates = [number] | [number, number]; diff --git a/ui/analyse/src/study/relay/relayTourView.ts b/ui/analyse/src/study/relay/relayTourView.ts index ad3252574e9c..8e46a4013751 100644 --- a/ui/analyse/src/study/relay/relayTourView.ts +++ b/ui/analyse/src/study/relay/relayTourView.ts @@ -112,15 +112,22 @@ const showInfo = (i: RelayTourInfo, dates?: RelayTourDates) => { ['dates', dates && showDates(dates), 'objects.spiral-calendar'], ['format', i.format, 'objects.crown'], ['tc', i.tc, 'objects.mantelpiece-clock'], + ['location', i.location, 'travel-places.world-map'], ['players', i.players, 'activity.sparkles'], + ['website', i.website, null, 'Official website'], + ['standings', i.standings, null, 'Standings'], ] .map( - ([key, value, icon]) => + ([key, value, icon, linkName]) => + key && value && - icon && - h('div.relay-tour__info__' + key, [h('img', { attrs: { src: site.asset.flairSrc(icon) } }), value]), + h('div.relay-tour__info__' + key, [ + icon && h('img', { attrs: { src: site.asset.flairSrc(icon) } }), + linkName ? h('a', { attrs: { href: value, target: '_blank' } }, linkName) : value, + ]), ) .filter(defined); + return contents.length ? h('div.relay-tour__info', contents) : undefined; };