more appeal WIP

pull/7068/head
Thibault Duplessis 2020-07-31 13:06:12 +02:00
parent 600d3927b8
commit 5fc41e1281
7 changed files with 108 additions and 48 deletions

View File

@ -1,10 +1,10 @@
package controllers
import play.api.mvc.Result
import lila.app._
import lila.api.Context
import views._
import lila.app._
import lila.report.Suspect
import play.api.mvc.Result
import views._
final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
@ -31,17 +31,19 @@ final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
def queue =
Secure(_.Appeals) { implicit ctx => me =>
env.appeal.api.queue zip reportC.getCounts flatMap {
case (appeals, counts ~ streamers ~ nbAppeals) =>
env.appeal.api.queue zip env.report.api.inquiries.allBySuspect zip reportC.getCounts flatMap {
case ((appeals, inquiries), counts ~ streamers ~ nbAppeals) =>
(env.user.lightUserApi preloadMany appeals.map(_.id)) inject
Ok(html.appeal2.queue(appeals, counts, streamers, nbAppeals))
Ok(html.appeal2.queue(appeals, inquiries, counts, streamers, nbAppeals))
}
}
def show(username: String) =
Secure(_.Appeals) { implicit ctx => me =>
asMod(username) { (appeal, suspect) =>
Ok(html.appeal2.show(appeal, suspect, env.appeal.forms.text)).fuccess
env.report.api.inquiries.ofSuspectId(suspect.user.id) map { inquiry =>
Ok(html.appeal2.show(appeal, suspect, inquiry, env.appeal.forms.text))
}
}
}
@ -52,7 +54,10 @@ final class Appeal(env: Env, reportC: => Report) extends LilaController(env) {
env.appeal.forms.text
.bindFromRequest()
.fold(
err => BadRequest(html.appeal2.show(appeal, suspect, err)).fuccess,
err =>
env.report.api.inquiries.ofSuspectId(suspect.user.id) map { inquiry =>
BadRequest(html.appeal2.show(appeal, suspect, inquiry, err))
},
text =>
for {
_ <- env.appeal.api.reply(text, appeal, me)

View File

@ -1,8 +1,5 @@
package controllers
import play.api.data._
import play.api.data.Forms._
import play.api.mvc._
import scala.annotation.nowarn
import lila.api.{ BodyContext, Context }
@ -14,6 +11,9 @@ import lila.report.{ Suspect, Mod => AsMod }
import lila.security.{ FingerHash, Permission }
import lila.user.{ User => UserModel, Title }
import ornicar.scalalib.Zero
import play.api.data._
import play.api.data.Forms._
import play.api.mvc._
import views._
final class Mod(
@ -290,7 +290,15 @@ final class Mod(
def spontaneousInquiry(username: String) =
Secure(_.SeeReport) { implicit ctx => me =>
OptionFuResult(env.user.repo named username) { user =>
env.report.api.inquiries.spontaneous(AsMod(me), Suspect(user)) inject redirect(user.username, true)
env.appeal.api.exists(user) flatMap { isAppeal =>
val f =
if (isAppeal) env.report.api.inquiries.appeal _
else env.report.api.inquiries.spontaneous _
f(AsMod(me), Suspect(user)) inject {
if (isAppeal) Redirect(routes.Appeal.show(user.username))
else redirect(user.username, true)
}
}
}
}

View File

@ -1,14 +1,15 @@
package views.html
import controllers.routes
import lila.api.Context
import lila.app.templating.Environment._
import lila.app.ui.ScalatagsTemplate._
import lila.common.String.html.richText
import play.api.data.Form
import lila.appeal.Appeal
import controllers.routes
import lila.common.String.html.richText
import lila.report.Report.Inquiry
import lila.report.Suspect
import lila.user.User
import play.api.data.Form
import play.api.i18n.Lang
object appeal2 {
@ -32,35 +33,51 @@ object appeal2 {
)
)
def show(appeal: Appeal, suspect: Suspect, textForm: Form[_])(implicit ctx: Context) =
def show(appeal: Appeal, suspect: Suspect, inquiry: Option[Inquiry], textForm: Form[_])(implicit
ctx: Context
) =
layout(s"Appeal by ${suspect.user.username}") {
main(cls := "page-small box box-pad page appeal")(
renderAppeal(appeal, textForm, asMod = true),
renderAppeal(appeal, textForm, asMod = true, inquiry = inquiry.map(_.mod).exists(ctx.userId.has)),
div(cls := "appeal__actions")(
if (appeal.isOpen)
frag(
postForm(action := routes.Appeal.act(suspect.user.username, "close"))(
submitButton("Close")(cls := "button button-red button-thin")
),
if (appeal.isMuted)
postForm(action := routes.Appeal.act(suspect.user.username, "open"))(
submitButton("Un-mute")(cls := "button button-green button-thin")
)
else
postForm(action := routes.Appeal.act(suspect.user.username, "mute"))(
submitButton("Mute")(cls := "button button-red button-thin")
)
)
else
postForm(action := routes.Appeal.act(suspect.user.username, "open"))(
submitButton("Open")(cls := "button button-green button-thin")
)
inquiry match {
case None =>
postForm(action := routes.Mod.spontaneousInquiry(appeal.id))(
submitButton(cls := "button")("Handle this appeal")
)
case Some(Inquiry(mod, _)) if ctx.userId has mod =>
frag(
postForm(action := routes.Report.inquiry(appeal.id))(
submitButton(cls := "button button-metal button-thin")("Release this appeal")
),
if (appeal.isOpen)
frag(
postForm(action := routes.Appeal.act(suspect.user.username, "close"))(
submitButton("Close")(cls := "button button-red button-thin")
),
if (appeal.isMuted)
postForm(action := routes.Appeal.act(suspect.user.username, "open"))(
submitButton("Un-mute")(cls := "button button-green button-thin")
)
else
postForm(action := routes.Appeal.act(suspect.user.username, "mute"))(
submitButton("Mute")(cls := "button button-red button-thin")
)
)
else
postForm(action := routes.Appeal.act(suspect.user.username, "open"))(
submitButton("Open")(cls := "button button-green button-thin")
)
)
case Some(Inquiry(mod, _)) => frag(userIdLink(mod.some), " is handling this.")
}
)
)
}
def queue(
appeals: List[Appeal],
inquiries: Map[User.ID, Inquiry],
counts: lila.report.Room.Counts,
streamers: Int,
nbAppeals: Int
@ -70,6 +87,7 @@ object appeal2 {
thead(
tr(
th("By"),
th("Last message"),
th
)
),
@ -81,7 +99,13 @@ object appeal2 {
),
td(appeal.msgs.lastOption map { msg =>
msg.text
})
}),
td(
a(href := routes.Appeal.show(appeal.id), cls := "button button-metal")("View"),
inquiries.get(appeal.id) map { i =>
frag(userIdLink(i.mod.some), " is handling this")
}
)
)
}
)
@ -97,7 +121,9 @@ object appeal2 {
title = title
)(body)
private def renderAppeal(appeal: Appeal, textForm: Form[_], asMod: Boolean)(implicit ctx: Context) =
private def renderAppeal(appeal: Appeal, textForm: Form[_], asMod: Boolean, inquiry: Boolean = false)(
implicit ctx: Context
) =
frag(
h1(
if (appeal.isOpen) "Ongoing appeal" else "Closed appeal",
@ -106,7 +132,7 @@ object appeal2 {
standardFlash(),
!asMod option renderHelp,
div(cls := "body")(
renderStatus(appeal),
!asMod option renderStatus(appeal),
appeal.msgs.map { msg =>
div(cls := s"appeal__msg appeal__msg--${if (appeal isByMod msg) "mod" else "suspect"}")(
div(cls := "appeal__msg__header")(
@ -116,7 +142,7 @@ object appeal2 {
div(cls := "appeal__msg__text")(richText(msg.text))
)
},
appeal.isOpen option renderForm(
(asMod == inquiry) && appeal.isOpen option renderForm(
textForm,
action =
if (asMod) routes.Appeal.reply(appeal.id).url

View File

@ -14,6 +14,8 @@ final class AppealApi(
def get(user: User) = coll.byId[Appeal](user.id)
def exists(user: User) = coll.exists($id(user.id))
def post(text: String, me: User) =
mine(me) flatMap {
case None =>

View File

@ -153,6 +153,7 @@ object Report {
}
private[report] val spontaneousText = "Spontaneous inquiry"
private[report] val appealText = "Appeal"
def make(c: Candidate.Scored, existing: Option[Report]) =
c match {

View File

@ -1,14 +1,14 @@
package lila.report
import com.softwaremill.macwire._
import org.joda.time.DateTime
import reactivemongo.api.ReadPreference
import scala.concurrent.duration._
import com.softwaremill.macwire._
import lila.common.Bus
import lila.db.dsl._
import lila.memo.CacheApi._
import lila.common.Bus
import lila.user.{ User, UserRepo }
import org.joda.time.DateTime
import reactivemongo.api.ReadPreference
final class ReportApi(
val coll: Coll,
@ -503,10 +503,20 @@ final class ReportApi(
name = "report.inquiries"
)
// def all: Fu[List[Report]] = coll.list[Report]($doc("inquiry.mod" $exists true))
def allBySuspect: Fu[Map[User.ID, Report.Inquiry]] =
coll.list[Report]($doc("inquiry.mod" $exists true)) map {
_.view.flatMap { r =>
r.inquiry map { i =>
r.user -> i
}
}.toMap
}
def ofModId(modId: User.ID): Fu[Option[Report]] = coll.one[Report]($doc("inquiry.mod" -> modId))
def ofSuspectId(suspectId: User.ID): Fu[Option[Report.Inquiry]] =
coll.primitiveOne[Report.Inquiry]($doc("inquiry.mod" $exists true, "user" -> suspectId), "inquiry")
/*
* If the mod has no current inquiry, just start this one.
* If they had another inquiry, cancel it and start this one instead.
@ -519,7 +529,9 @@ final class ReportApi(
private def doToggle(mod: Mod, id: Report.ID): Fu[Option[Report]] =
for {
report <- coll.byId[Report](id) orFail s"No report $id found"
report <- coll.byId[Report](id) orElse coll.one[Report](
$doc("user" -> id, "inquiry.mod" $exists true)
) orFail s"No report $id found"
current <- ofModId(mod.user.id)
_ <- current ?? cancel(mod)
_ <-
@ -553,6 +565,12 @@ final class ReportApi(
.void
def spontaneous(mod: Mod, sus: Suspect): Fu[Report] =
openOther(mod, sus, Report.spontaneousText)
def appeal(mod: Mod, sus: Suspect): Fu[Report] =
openOther(mod, sus, Report.appealText)
private def openOther(mod: Mod, sus: Suspect, name: String): Fu[Report] =
ofModId(mod.user.id) flatMap { current =>
current.??(cancel(mod)) >> {
val report = Report
@ -561,7 +579,7 @@ final class ReportApi(
Reporter(mod.user),
sus,
Reason.Other,
Report.spontaneousText
name
) scored Report.Score(0),
none
)

View File

@ -83,10 +83,10 @@ object BuildSettings {
// "-Wnumeric-widen",
"-Wunused:imports",
"-Wunused:locals",
"-Wunused:patvars"
"-Wunused:patvars",
// "-Wunused:privates", // unfortunately doesn't work with macros
// "-Wunused:implicits",
// "-Wunused:params",
"-Wunused:params"
// "-Wvalue-discard",
)