diff --git a/app/controllers/Appeal.scala b/app/controllers/Appeal.scala
index b196c69699..b6462072d8 100644
--- a/app/controllers/Appeal.scala
+++ b/app/controllers/Appeal.scala
@@ -6,26 +6,32 @@ import views._
import lila.api.Context
import lila.app._
import lila.report.Suspect
+import play.api.data.Form
final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
+ import lila.appeal.Appeal.form
+
def home =
Auth { implicit ctx => me =>
- env.appeal.api.mine(me) map { appeal =>
- Ok(html.appeal.discussion(appeal, env.appeal.forms.text))
- }
+ renderAppealOrTree(me) map { Ok(_) }
}
+ private def renderAppealOrTree(
+ me: lila.user.User,
+ err: Option[Form[String]] = None
+ )(implicit ctx: Context) = env.appeal.api.mine(me) map {
+ case None => html.appeal.tree(me)
+ case Some(a) => html.appeal.discussion(a, err | form)
+ }
+
def post =
AuthBody { implicit ctx => me =>
implicit val req = ctx.body
- env.appeal.forms.text
+ form
.bindFromRequest()
.fold(
- err =>
- env.appeal.api.mine(me) map { appeal =>
- BadRequest(html.appeal.discussion(appeal, err))
- },
+ err => renderAppealOrTree(me, err.some) map { BadRequest(_) },
text => env.appeal.api.post(text, me) inject Redirect(routes.Appeal.home).flashSuccess
)
}
@@ -43,7 +49,7 @@ final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
Secure(_.Appeals) { implicit ctx => me =>
asMod(username) { (appeal, suspect) =>
env.report.api.inquiries.ofSuspectId(suspect.user.id) map { inquiry =>
- Ok(html.appeal.discussion.show(appeal, suspect, inquiry, env.appeal.forms.text, getPresets))
+ Ok(html.appeal.discussion.show(appeal, suspect, inquiry, form, getPresets))
}
}
}
@@ -52,7 +58,7 @@ final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
SecureBody(_.Appeals) { implicit ctx => me =>
asMod(username) { (appeal, suspect) =>
implicit val req = ctx.body
- env.appeal.forms.text
+ form
.bindFromRequest()
.fold(
err =>
diff --git a/app/views/appeal/bits.scala b/app/views/appeal/bits.scala
new file mode 100644
index 0000000000..d17dc5da65
--- /dev/null
+++ b/app/views/appeal/bits.scala
@@ -0,0 +1,19 @@
+package views.html
+package appeal
+
+import lila.api.Context
+import lila.app.templating.Environment._
+import lila.app.ui.ScalatagsTemplate._
+
+object bits {
+
+ def layout(title: String)(body: Frag)(implicit ctx: Context) =
+ views.html.base.layout(
+ title = title,
+ moreCss = frag(
+ cssTag("form3"),
+ cssTag("appeal")
+ ),
+ moreJs = jsModule("appeal")
+ )(body)
+}
diff --git a/app/views/appeal/discussion.scala b/app/views/appeal/discussion.scala
index d4aa143acd..24a2d8d441 100644
--- a/app/views/appeal/discussion.scala
+++ b/app/views/appeal/discussion.scala
@@ -16,35 +16,21 @@ import lila.user.User
object discussion {
- def apply(appeal: Option[Appeal], textForm: Form[_])(implicit ctx: Context) =
- layout("Appeal") {
+ def apply(appeal: Appeal, textForm: Form[String])(implicit ctx: Context) =
+ bits.layout("Appeal") {
main(cls := "page-small box box-pad page appeal")(
- appeal match {
- case Some(a) => renderAppeal(a, textForm, asMod = false, presets = none)
- case None => newAppeal(textForm)
- }
+ renderAppeal(appeal, textForm, asMod = false, presets = none)
)
}
- private def newAppeal(textForm: Form[_])(implicit ctx: Context) =
- frag(
- h1("Appeal a moderation decision"),
- renderHelp,
- div(cls := "body")(
- renderForm(textForm, action = routes.Appeal.post.url, isNew = true, presets = none)
- )
- )
-
def show(
appeal: Appeal,
suspect: Suspect,
inquiry: Option[Inquiry],
- textForm: Form[_],
+ textForm: Form[String],
presets: ModPresets
- )(implicit
- ctx: Context
- ) =
- layout(s"Appeal by ${suspect.user.username}") {
+ )(implicit ctx: Context) =
+ bits.layout(s"Appeal by ${suspect.user.username}") {
main(cls := "page-small box box-pad page appeal")(
renderAppeal(
appeal,
@@ -81,19 +67,9 @@ object discussion {
)
}
- private def layout(title: String)(body: Frag)(implicit ctx: Context) =
- views.html.base.layout(
- title = title,
- moreCss = frag(
- cssTag("form3"),
- cssTag("appeal")
- ),
- moreJs = jsModule("appeal")
- )(body)
-
private def renderAppeal(
appeal: Appeal,
- textForm: Form[_],
+ textForm: Form[String],
asMod: Boolean,
inquiry: Boolean = false,
presets: Option[ModPresets]
@@ -125,19 +101,6 @@ object discussion {
)
)
- private def renderHelp =
- div(cls := "appeal__help")(
- p(
- "If your account has been restricted for violation of ",
- a(href := routes.Page.tos)("the Lichess rules"),
- " you may file an appeal here."
- ),
- p(
- "You can read more about the appeal process ",
- a(href := routes.Page.loneBookmark("appeal"))("here.")
- )
- )
-
private def renderUser(appeal: Appeal, userId: User.ID, asMod: Boolean)(implicit ctx: Context) =
if (appeal isAbout userId) userIdLink(userId.some)
else
@@ -150,7 +113,7 @@ object discussion {
)
)
- private def renderForm(form: Form[_], action: String, isNew: Boolean, presets: Option[ModPresets])(implicit
+ def renderForm(form: Form[String], action: String, isNew: Boolean, presets: Option[ModPresets])(implicit
ctx: Context
) =
postForm(st.action := action)(
diff --git a/app/views/appeal/tree.scala b/app/views/appeal/tree.scala
new file mode 100644
index 0000000000..3ba8bc1be3
--- /dev/null
+++ b/app/views/appeal/tree.scala
@@ -0,0 +1,100 @@
+package views.html
+package appeal
+
+import controllers.routes
+import play.api.data.Form
+
+import lila.api.Context
+import lila.app.templating.Environment._
+import lila.app.ui.ScalatagsTemplate._
+import lila.report.Report.Inquiry
+import lila.user.User
+
+object tree {
+
+ import trans.contact.doNotMessageModerators
+ import views.html.base.navTree._
+
+ private def cleanMenu(implicit ctx: Context): Branch =
+ Branch(
+ "root",
+ "Your account is not marked or restricted. You're all good!",
+ List(
+ Leaf(
+ "clean-other-account",
+ "I want to appeal for another account",
+ frag(
+ p(
+ "Sorry we don't take appeals from other accounts. The appeal should come from nowhere else, but the concerned account."
+ )
+ )
+ ),
+ Leaf(
+ "clean-warning",
+ "I want to discuss a warning I received",
+ frag(
+ p(
+ "Please note that warnings are only warnings, and that your account has not been restricted currently.",
+ br,
+ "If you still want to file an appeal, use the following form:"
+ ),
+ newAppeal
+ )
+ ),
+ Leaf(
+ "clean-other-issue",
+ "I have another issue to discuss",
+ p(
+ "This channel of communication is for appealing moderation related issues.",
+ br,
+ "Please use ",
+ a(href := routes.Main.contact)("the contact page"),
+ " or ",
+ a(href := "https://discordapp.com/invite/pvHanhg")("our discord server"),
+ " to contact us about other issues.",
+ br,
+ "You can also ",
+ a(href := routes.Page.loneBookmark("appeal"))("find here more information about appeals.")
+ )
+ )
+ )
+ )
+
+ def apply(me: User)(implicit ctx: Context) =
+ bits.layout("Appeal a moderation decision") {
+ main(cls := "page page-small box box-pad appeal")(
+ h1("Appeal"),
+ div(cls := "nav-tree")(
+ renderNode(
+ {
+ if (me.marks.clean) cleanMenu
+ else ???
+ },
+ none
+ )
+ ),
+ p(cls := "appeal__moderators text", dataIcon := "")(doNotMessageModerators())
+ )
+ }
+
+ private def newAppeal(implicit ctx: Context) =
+ discussion.renderForm(
+ lila.appeal.Appeal.form,
+ action = routes.Appeal.post.url,
+ isNew = true,
+ presets = none
+ )
+
+ private def renderHelp =
+ div(cls := "appeal__help")(
+ p(
+ "If your account has been restricted for violation of ",
+ a(href := routes.Page.tos)("the Lichess rules"),
+ " you may file an appeal here."
+ ),
+ p(
+ "You can read more about the appeal process ",
+ a(href := routes.Page.loneBookmark("appeal"))("here.")
+ )
+ )
+}
diff --git a/app/views/base/navTree.scala b/app/views/base/navTree.scala
new file mode 100644
index 0000000000..81517fe6ef
--- /dev/null
+++ b/app/views/base/navTree.scala
@@ -0,0 +1,46 @@
+package views.html
+package base
+
+import lila.api.Context
+import lila.app.templating.Environment._
+import lila.app.ui.ScalatagsTemplate._
+
+object navTree {
+
+ sealed trait Node {
+ val id: String
+ val name: Frag
+ }
+ case class Branch(id: String, name: Frag, children: List[Node]) extends Node
+ case class Leaf(id: String, name: Frag, content: Frag) extends Node
+
+ def renderNode(node: Node, parent: Option[Node])(implicit ctx: Context): Frag =
+ node match {
+ case Leaf(_, _, content) =>
+ List(
+ div(makeId(node.id), cls := "node leaf")(
+ h2(parent map goBack, node.name),
+ div(cls := "content")(content)
+ )
+ )
+ case b @ Branch(id, _, children) =>
+ frag(
+ div(makeId(node.id), cls := s"node branch $id")(
+ h2(parent map goBack, node.name),
+ div(cls := "links")(
+ children map { child =>
+ a(makeLink(child.id))(child.name)
+ }
+ )
+ ),
+ children map { renderNode(_, b.some) }
+ )
+ }
+
+ private def makeId(id: String) = st.id := s"help-$id"
+
+ private def makeLink(id: String) = href := s"#help-$id"
+
+ private def goBack(parent: Node): Frag =
+ a(makeLink(parent.id), cls := "back", dataIcon := "I", title := "Go back")
+}
diff --git a/app/views/site/contact.scala b/app/views/site/contact.scala
index cb1fea3aba..f9421e218e 100644
--- a/app/views/site/contact.scala
+++ b/app/views/site/contact.scala
@@ -1,5 +1,5 @@
-package views
-package html.site
+package views.html
+package site
import controllers.routes
import scala.util.chaining._
@@ -11,13 +11,7 @@ import lila.app.ui.ScalatagsTemplate._
object contact {
import trans.contact._
-
- sealed private trait Node {
- val id: String
- val name: Frag
- }
- private case class Branch(id: String, name: Frag, children: List[Node]) extends Node
- private case class Leaf(id: String, name: Frag, content: Frag) extends Node
+ import views.html.base.navTree._
private def reopenLeaf(prefix: String)(implicit ctx: Context) =
Leaf(
@@ -347,35 +341,6 @@ object contact {
)
)
- private def renderNode(node: Node, parent: Option[Node])(implicit ctx: Context): Frag =
- node match {
- case Leaf(_, _, content) =>
- List(
- div(makeId(node.id), cls := "node leaf")(
- h2(parent map goBack, node.name),
- div(cls := "content")(content)
- )
- )
- case b @ Branch(id, _, children) =>
- frag(
- div(makeId(node.id), cls := s"node branch $id")(
- h2(parent map goBack, node.name),
- div(cls := "links")(
- children map { child =>
- a(makeLink(child.id))(child.name)
- }
- )
- ),
- children map { renderNode(_, b.some) }
- )
- }
-
- private def makeId(id: String) = st.id := s"help-$id"
- private def makeLink(id: String) = href := s"#help-$id"
-
- private def goBack(parent: Node): Frag =
- a(makeLink(parent.id), cls := "back", dataIcon := "I", title := "Go back")
-
def apply()(implicit ctx: Context) =
page.layout(
title = trans.contact.contact.txt(),
diff --git a/modules/appeal/src/main/Appeal.scala b/modules/appeal/src/main/Appeal.scala
index c1716dbdbc..4d4805c8f2 100644
--- a/modules/appeal/src/main/Appeal.scala
+++ b/modules/appeal/src/main/Appeal.scala
@@ -59,6 +59,13 @@ object Appeal {
def apply(key: String) = all.find(_.key == key)
}
+ val form = {
+ import play.api.data._
+ import play.api.data.Forms._
+ Form[String](
+ single("text" -> nonEmptyText)
+ )
+ }
}
case class AppealMsg(
diff --git a/modules/appeal/src/main/AppealForm.scala b/modules/appeal/src/main/AppealForm.scala
deleted file mode 100644
index 256e0a14a6..0000000000
--- a/modules/appeal/src/main/AppealForm.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package lila.appeal
-
-import play.api.data._
-import play.api.data.Forms._
-
-final class AppealForm {
-
- val text = Form(
- single("text" -> nonEmptyText)
- )
-}
diff --git a/modules/appeal/src/main/Env.scala b/modules/appeal/src/main/Env.scala
index a3350ed6ad..0d1be19aa3 100644
--- a/modules/appeal/src/main/Env.scala
+++ b/modules/appeal/src/main/Env.scala
@@ -12,7 +12,5 @@ final class Env(
private val coll = db(CollName("appeal"))
- lazy val forms = wire[AppealForm]
-
lazy val api: AppealApi = wire[AppealApi]
}
diff --git a/translation/source/contact.xml b/translation/source/contact.xml
index fc72ea5f94..59db2f8fdd 100644
--- a/translation/source/contact.xml
+++ b/translation/source/contact.xml
@@ -31,7 +31,7 @@
You can also reach that page by clicking the %s report button on a profile page.
Do not report players in the forum.
Do not send us report emails.
- Do not send direct messages to moderators.
+ Please do not send direct messages to moderators.
Only reporting players through the report form is effective.
I want to report a bug
In the Lichess Feedback section of the forum
diff --git a/ui/site/css/_appeal.scss b/ui/site/css/_appeal.scss
index 4fb9b4390a..320b426a20 100644
--- a/ui/site/css/_appeal.scss
+++ b/ui/site/css/_appeal.scss
@@ -52,4 +52,11 @@
.appeal-presets {
margin-right: 1em;
}
+
+ &__moderators {
+ @extend %box-radius;
+ margin-top: 3em;
+ padding: 2em 3em;
+ background: $c-bg-zebra;
+ }
}
diff --git a/ui/site/src/appeal.ts b/ui/site/src/appeal.ts
index e2f717658c..f66ec9bac8 100644
--- a/ui/site/src/appeal.ts
+++ b/ui/site/src/appeal.ts
@@ -1,6 +1,8 @@
import { formToXhr } from 'common/xhr';
lichess.load.then(() => {
+ if ($('.nav-tree').length) location.hash = location.hash || '#help-root';
+
$('select.appeal-presets').on('change', (e: Event) => $('#form3-text').val((e.target as HTMLTextAreaElement).value));
$('form.appeal__actions__slack').on('submit', (e: Event) => {