appeal nav tree WIP - for lichess-org/tavern#37

appeal2
Thibault Duplessis 2021-02-26 12:20:21 +01:00
parent d2002257d2
commit 9207c35137
12 changed files with 209 additions and 107 deletions

View File

@ -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 =>

View File

@ -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)
}

View File

@ -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)(

View File

@ -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.")
)
)
}

View File

@ -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")
}

View File

@ -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(),

View File

@ -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(

View File

@ -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)
)
}

View File

@ -12,7 +12,5 @@ final class Env(
private val coll = db(CollName("appeal"))
lazy val forms = wire[AppealForm]
lazy val api: AppealApi = wire[AppealApi]
}

View File

@ -31,7 +31,7 @@
<string name="youCanAlsoReachReportPage">You can also reach that page by clicking the %s report button on a profile page.</string>
<string name="doNotReportInForum">Do not report players in the forum.</string>
<string name="doNotSendReportEmails">Do not send us report emails.</string>
<string name="doNotMessageModerators">Do not send direct messages to moderators.</string>
<string name="doNotMessageModerators">Please do not send direct messages to moderators.</string>
<string name="onlyReports">Only reporting players through the report form is effective.</string>
<string name="wantReportBug">I want to report a bug</string>
<string name="reportBugInForum">In the Lichess Feedback section of the forum</string>

View File

@ -52,4 +52,11 @@
.appeal-presets {
margin-right: 1em;
}
&__moderators {
@extend %box-radius;
margin-top: 3em;
padding: 2em 3em;
background: $c-bg-zebra;
}
}

View File

@ -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) => {