mods list

pull/6119/head
Thibault Duplessis 2020-03-03 13:34:33 -06:00
parent f7a81574c2
commit de6ba687cd
10 changed files with 77 additions and 19 deletions

View File

@ -208,6 +208,10 @@ final class Mod(
modLogApi.recent map { html.mod.log(_) }
}
def table = Secure(_.ModLog) { implicit ctx => _ =>
modApi.allMods map { html.mod.table(_) }
}
private def communications(username: String, priv: Boolean) =
Secure { perms =>
if (priv) perms.ViewPrivateComms else perms.Shadowban

View File

@ -34,6 +34,8 @@ object menu {
"Chat Panic: ",
strong(if (isChatPanicEnabled) "ON" else "OFF")
),
isGranted(_.Admin) option
a(cls := active.active("mods"), href := routes.Mod.table)("Mods"),
isGranted(_.Settings) option
a(cls := active.active("setting"), href := routes.Dev.settings)("Settings"),
isGranted(_.Cli) option

View File

@ -0,0 +1,49 @@
package views.html.mod
import controllers.routes
import lila.api.Context
import lila.app.templating.Environment._
import lila.app.ui.ScalatagsTemplate._
object table {
private val dataSort = attr("data-sort")
def apply(users: List[lila.user.User])(implicit ctx: Context) = {
val title = "All mods"
views.html.base.layout(
title = title,
moreCss = cssTag("mod.misc")
) {
main(cls := "page-menu")(
views.html.mod.menu("mods"),
div(id := "mod_table", cls := "page-menu__content box")(
h1(title),
st.table(cls := "slist slist-pad sortable")(
thead(
tr(
th("Mod"),
th("Permissions"),
th("Last seen at")
)
),
tbody(
users.map { user =>
tr(
td(userLink(user)),
td(a(href := routes.Mod.permissions(user.username))(
lila.security.Permission(user.roles).map(_.name) mkString ", "
)),
td(dataSort := user.seenAt.map(_.getMillis.toString))(user.seenAt.map(momentFromNowOnce)),
)
}
)
)
)
)
}
}
}

View File

@ -378,6 +378,7 @@ POST /mod/:username/rankban/:v controllers.Mod.rankban(username: String,
POST /mod/:username/reportban/:v controllers.Mod.reportban(username: String, v: Boolean)
POST /mod/:username/impersonate controllers.Mod.impersonate(username: String)
GET /mod/log controllers.Mod.log
GET /mod/table controllers.Mod.table
POST /mod/:username/refreshUserAssess controllers.Mod.refreshUserAssess(username: String)
POST /mod/:username/email controllers.Mod.setEmail(username: String)
POST /mod/:username/notify-slack controllers.Mod.notifySlack(username: String)

View File

@ -170,6 +170,12 @@ final class ModApi(
userRepo.setRankban(sus.user.id, v) >>- logApi.rankban(mod, sus, v)
}
def allMods =
userRepo.userIdsWithRoles(Permission.modPermissions.view.map(_.dbKey).toList) flatMap
userRepo.enabledByIds dmap {
_.sortBy(_.timeNoSee)
}
private def withUser[A](username: String)(op: User => Fu[A]): Fu[A] =
userRepo named username orFail s"[mod] missing user $username" flatMap op
}

View File

@ -214,9 +214,13 @@ object Permission {
)
)
lazy val all: List[Permission] = categorized.flatMap {
private lazy val all: Set[Permission] = categorized.flatMap {
case (_, perms) => perms
}
}.toSet
private lazy val nonModPermissions: Set[Permission] = Set(Beta, Prismic, Coach, Teacher, Developer, Verified)
lazy val modPermissions: Set[Permission] = all diff nonModPermissions
lazy val allByDbKey: Map[String, Permission] = all.view map { p =>
(p.dbKey, p)

View File

@ -67,9 +67,7 @@ case class User(
lazy val seenRecently: Boolean = timeNoSee < User.seenRecently
def timeNoSee: Duration = seenAt.fold[Duration](Duration.Inf) { s =>
(nowMillis - s.getMillis).millis
}
def timeNoSee: Duration = (nowMillis - (seenAt | createdAt).getMillis).millis
def everLoggedIn = seenAt.??(createdAt !=)

View File

@ -50,3 +50,7 @@
margin: 0 .5em;
}
}
.slist thead {
white-space: nowrap;
}

View File

@ -83,13 +83,8 @@ $(function() {
};
tablesort.extend('number', function(item) {
return item.match(/^[-+]?[£\x24Û¢´€]?\d+\s*([,\.]\d{0,2})/) || // Prefixed currency
item.match(/^[-+]?\d+\s*([,\.]\d{0,2})?[£\x24Û¢´€]/) || // Suffixed currency
item.match(/^[-+]?(\d)*-?([,\.]){0,1}-?(\d)+([E,e][\-+][\d]+)?%?$/); // Number
return item.match(/^[-+]?(\d)*-?([,\.]){0,1}-?(\d)+([E,e][\-+][\d]+)?%?$/); // Number
}, function(a, b) {
a = cleanNumber(a);
b = cleanNumber(b);
return compareNumber(b, a);
return compareNumber(cleanNumber(b), cleanNumber(a));
});
});

View File

@ -100,14 +100,9 @@ function userMod($zone) {
};
tablesort.extend('number', function(item) {
return item.match(/^-?[£\x24Û¢´€]?\d+\s*([,.]\d{0,2})/) || // Prefixed currency
item.match(/^-?\d+\s*([,.]\d{0,2})?[£\x24Û¢´€]/) || // Suffixed currency
item.match(/^-?(\d)*-?([,.]){0,1}-?(\d)+([E,e][-+][\d]+)?%?$/); // Number
return item.match(/^[-+]?(\d)*-?([,\.]){0,1}-?(\d)+([E,e][\-+][\d]+)?%?$/); // Number
}, function(a, b) {
a = cleanNumber(a);
b = cleanNumber(b);
return compareNumber(b, a);
return compareNumber(cleanNumber(b), cleanNumber(a));
});
}());