lila/app/views/event.scala

235 lines
7.6 KiB
Scala

package views.html
import controllers.routes
import play.api.data.Form
import lila.api.Context
import lila.app.templating.Environment._
import lila.app.ui.ScalatagsTemplate._
import lila.event.{ Event, EventForm }
import lila.i18n.LangList
object event {
private val dataSeconds = attr("data-seconds")
def create(form: Form[_])(implicit ctx: Context) =
layout(title = "New event", css = "mod.form") {
div(cls := "crud page-menu__content box box-pad")(
h1("New event"),
postForm(cls := "content_box_content form3", action := routes.Event.create)(inForm(form))
)
}
def edit(event: Event, form: Form[_])(implicit ctx: Context) =
layout(title = event.title, css = "mod.form") {
div(cls := "crud edit page-menu__content box box-pad")(
div(cls := "box__top")(
h1(
a(href := routes.Event.show(event.id))(event.title),
span("Created by ", titleNameOrId(event.createdBy.value), " ", momentFromNow(event.createdAt)),
event.updatedBy map { updatedBy =>
span("Updated by ", titleNameOrId(updatedBy.value), " ", event.updatedAt.map(momentFromNow(_)))
}
),
st.form(cls := "box__top__actions", action := routes.Event.cloneE(event.id), method := "get")(
form3.submit("Clone", "".some)(cls := "button-green button-empty")
)
),
standardFlash(),
postForm(cls := "content_box_content form3", action := routes.Event.update(event.id))(inForm(form))
)
}
def iconOf(e: Event) =
e.icon match {
case None => i(cls := "img", dataIcon := "")
case Some(c) if c == EventForm.icon.broadcast => i(cls := "img", dataIcon := "")
case Some(c) => img(cls := "img", src := assetUrl(s"images/$c"))
}
def show(e: Event)(implicit ctx: Context) =
views.html.base.layout(
title = e.title,
moreCss = cssTag("event"),
moreJs = jsTag("event-countdown.js")
) {
main(cls := "page-small event box box-pad")(
div(cls := "box__top")(
iconOf(e),
div(
h1(e.title),
strong(cls := "headline")(e.headline)
)
),
e.description.map { d =>
div(cls := "desc")(markdown(e, d))
},
if (e.isFinished) p(cls := "desc")("The event is finished.")
else if (e.isNow) a(href := e.url, cls := "button button-fat")(trans.eventInProgress())
else
ul(cls := "countdown", dataSeconds := (~e.secondsToStart + 1))(
List("Days", "Hours", "Minutes", "Seconds") map { t =>
li(span(cls := t.toLowerCase), t)
}
)
)
}
private object markdown {
import scala.concurrent.duration._
private val renderer = new lila.common.Markdown(table = true, list = true)
// hashcode caching is safe for official events
private val cache = lila.memo.CacheApi.scaffeineNoScheduler
.expireAfterAccess(10 minutes)
.maximumSize(64)
.build[Int, String]()
def apply(e: Event, text: String): Frag =
raw(cache.get(text.hashCode, _ => renderer(s"event:${e.id}")(text)))
}
def manager(events: List[Event])(implicit ctx: Context) = {
val title = "Event manager"
layout(title = title) {
div(cls := "crud page-menu__content box")(
div(cls := "box__top")(
h1(title),
div(cls := "box__top__actions")(
a(cls := "button button-green", href := routes.Event.form, dataIcon := "")
)
),
table(cls := "slist slist-pad")(
thead(
tr(
th,
th(utcLink, " start"),
th(utcLink, " end"),
th
)
),
tbody(
events.map { e =>
tr(
td(
a(href := routes.Event.edit(e.id))(
strong(e.title),
em(e.headline)
)
),
td(
showDateTimeUTC(e.startsAt),
momentFromNow(e.startsAt)
),
td(
showDateTimeUTC(e.finishesAt),
momentFromNow(e.finishesAt)
),
td(a(cls := "text", href := routes.Event.show(e.id), dataIcon := ""))
)
}
)
)
)
}
}
private def inForm(form: Form[_])(implicit ctx: Context) =
frag(
form3.split(
form3.group(form("startsAt"), frag("Start date ", strong(utcLink)), half = true)(
form3.flatpickr(_, utc = true)
),
form3.group(form("finishesAt"), frag("End date ", strong(utcLink)), half = true)(
form3.flatpickr(_, utc = true)
)
),
form3.split(
form3.group(
form("title"),
raw("Short title"),
help = raw("Keep it VERY short, so it fits on homepage").some,
half = true
)(form3.input(_)),
form3.group(
form("icon"),
frag("Icon"),
half = true,
help = frag("Displayed on the homepage button").some
)(form3.select(_, EventForm.icon.choices))
),
form3.group(
form("headline"),
raw("Short headline"),
help = raw("Keep it VERY short, so it fits on homepage").some
)(form3.input(_)),
form3
.group(form("description"), raw("Possibly long description"), help = raw("Markdown enabled").some)(
form3.textarea(_)(rows := 15)
),
form3.split(
form3.group(
form("url"),
raw("External URL"),
help = raw("What to redirect to when the event starts").some,
half = true
)(form3.input(_)),
form3.checkbox(
form("countdown"),
frag("Show countdown"),
help = frag(
"Show a countdown on the event page before start. Unselect to redirect to the event URL immediately, even before the event has started."
).some,
half = true
)
),
form3.split(
form3.group(form("lang"), raw("Language"), half = true)(
form3.select(
_,
lila.i18n.LangList.popularNoRegion.map { l =>
l.code -> s"${l.language.toUpperCase} ${LangList name l}"
}
)
),
form3.group(
form("hostedBy"),
raw("Hosted by Lichess user"),
help = raw("Username that must not be featured while the event is ongoing").some,
half = true
) { f =>
div(cls := "complete-parent")(
input(
cls := "form-control user-autocomplete",
name := f.name,
id := form3.id(f),
value := f.value,
dataTag := "span"
)
)
}
),
form3.split(
form3.checkbox(form("enabled"), raw("Enabled"), help = raw("Display the event").some, half = true),
form3.group(
form("homepageHours"),
raw("Hours on homepage before the start (0 to 24)"),
half = true,
help = raw("Go easy on this. The event will also remain on homepage while ongoing.").some
)(form3.input(_, typ = "number")(step := ".01"))
),
form3.action(form3.submit(trans.apply()))
)
private def layout(title: String, css: String = "mod.misc")(body: Frag)(implicit ctx: Context) =
views.html.base.layout(
title = title,
moreCss = cssTag(css),
moreJs = jsModule("flatpickr")
) {
main(cls := "page-menu")(
mod.menu("event"),
body
)
}
}