diff --git a/app/controllers/Appeal.scala b/app/controllers/Appeal.scala index e0eeba1795..4abf8d5cea 100644 --- a/app/controllers/Appeal.scala +++ b/app/controllers/Appeal.scala @@ -54,12 +54,10 @@ final class Appeal(env: Env, reportC: => Report, prismicC: => Prismic, userC: => def queue = Secure(_.Appeals) { implicit ctx => me => - env.appeal.api.queueOf( - me.user - ) zip env.report.api.inquiries.allBySuspect zip reportC.getScores flatMap { + env.appeal.api.queueOf(me.user) zip env.report.api.inquiries.allBySuspect zip reportC.getScores map { case ((appeals, inquiries), ((scores, streamers), nbAppeals)) => - (env.user.lightUserApi preloadMany appeals.map(_.id)) inject - Ok(html.appeal.queue(appeals, inquiries, scores, streamers, nbAppeals)) + env.user.lightUserApi preloadUsers appeals.map(_.user) + Ok(html.appeal.queue(appeals, inquiries, scores, streamers, nbAppeals)) } } diff --git a/app/views/appeal/queue.scala b/app/views/appeal/queue.scala index 593f50c1a6..cb7e7bb3ca 100644 --- a/app/views/appeal/queue.scala +++ b/app/views/appeal/queue.scala @@ -13,7 +13,7 @@ import lila.user.User object queue { def apply( - appeals: List[Appeal], + appeals: List[Appeal.WithUser], inquiries: Map[User.ID, Inquiry], scores: lila.report.Room.Scores, streamers: Int, @@ -29,10 +29,12 @@ object queue { ) ), tbody( - appeals.map { appeal => + appeals.map { case Appeal.WithUser(appeal, user) => tr(cls := List("new" -> appeal.isUnread))( td( - userIdLink(appeal.id.some) + userIdLink(appeal.id.some), + br, + views.html.user.mod.userMarks(user, None) ), td(appeal.msgs.lastOption map { msg => frag( diff --git a/modules/appeal/src/main/Appeal.scala b/modules/appeal/src/main/Appeal.scala index 71de9ba3a4..1521dc7331 100644 --- a/modules/appeal/src/main/Appeal.scala +++ b/modules/appeal/src/main/Appeal.scala @@ -69,6 +69,8 @@ object Appeal { def apply(key: String) = all.find(_.key == key) } + case class WithUser(appeal: Appeal, user: User) + val maxLength = 1000 import play.api.data._ diff --git a/modules/appeal/src/main/AppealApi.scala b/modules/appeal/src/main/AppealApi.scala index 6d2ce8caca..b79e44f2eb 100644 --- a/modules/appeal/src/main/AppealApi.scala +++ b/modules/appeal/src/main/AppealApi.scala @@ -4,6 +4,7 @@ import org.joda.time.DateTime import lila.db.dsl._ import lila.user.{ Holder, NoteApi, User, UserRepo } +import reactivemongo.api.ReadPreference final class AppealApi( coll: Coll, @@ -61,25 +62,52 @@ final class AppealApi( def countUnread = coll.countSel($doc("status" -> Appeal.Status.Unread.key)) - def queueOf(mod: User) = queue(snoozer snoozedKeysOf mod.id map (_.appealId)) + def queueOf(mod: User) = bothQueues(snoozer snoozedKeysOf mod.id map (_.appealId)) - private def queue(exceptIds: Iterable[User.ID]): Fu[List[Appeal]] = - coll - .find($doc("status" -> Appeal.Status.Unread.key) ++ { + private def bothQueues(exceptIds: Iterable[User.ID]): Fu[List[Appeal.WithUser]] = + fetchQueue( + selector = $doc("status" -> Appeal.Status.Unread.key) ++ { exceptIds.nonEmpty ?? $doc("_id" $nin exceptIds) - }) - .sort($doc("firstUnrepliedAt" -> 1)) - .cursor[Appeal]() - .list(30) flatMap { unreads => - coll - .find($doc("status" $ne Appeal.Status.Unread.key)) - .sort($doc("firstUnrepliedAt" -> -1)) - .cursor[Appeal]() - .list(40 - unreads.size) map { - unreads ::: _ - } + }, + ascending = true, + nb = 30 + ) flatMap { unreads => + fetchQueue( + selector = $doc("status" $ne Appeal.Status.Unread.key), + ascending = false, + nb = 40 - unreads.size + ) map { unreads ::: _ } } + private def fetchQueue(selector: Bdoc, ascending: Boolean, nb: Int): Fu[List[Appeal.WithUser]] = + coll + .aggregateList( + maxDocs = nb, + ReadPreference.secondaryPreferred + ) { framework => + import framework._ + Match(selector) -> List( + Sort((if (ascending) Ascending.apply _ else Descending.apply _)("firstUnrepliedAt")), + Limit(nb), + PipelineOperator( + $lookup.simple( + from = userRepo.coll, + as = "user", + local = "_id", + foreign = "_id" + ) + ), + UnwindField("user") + ) + } + .map { docs => + for { + doc <- docs + appeal <- doc.asOpt[Appeal] + user <- doc.getAsOpt[User]("user") + } yield Appeal.WithUser(appeal, user) + } + def setRead(appeal: Appeal) = coll.update.one($id(appeal.id), appeal.read).void