multiple autocomplete for kicking team members

pull/9556/head
andresrcom 2021-08-11 01:35:37 +03:00
parent bafe8a99b7
commit 7d84de4095
6 changed files with 50 additions and 33 deletions

View File

@ -144,11 +144,9 @@ final class Team(
}
def kickForm(id: String) =
Auth { implicit ctx => me =>
Auth { implicit ctx => _ =>
WithOwnedTeamEnabled(id) { team =>
env.team.memberRepo userIdsByTeam team.id map { userIds =>
html.team.admin.kick(team, userIds.filter(me.id !=))
}
Ok(html.team.admin.kick(team, forms.members)).fuccess
}
}
@ -156,8 +154,8 @@ final class Team(
AuthBody { implicit ctx => me =>
WithOwnedTeamEnabled(id) { team =>
implicit val req = ctx.body
forms.selectMember.bindFromRequest().value ?? { api.kick(team, _, me) } inject Redirect(
routes.Team.kickForm(team.id)
forms.members.bindFromRequest().value ?? { api.kickMembers(team, _, me).sequenceFu } inject Redirect(
routes.Team.show(team.id)
).flashSuccess
}
}

View File

@ -16,7 +16,10 @@ object admin {
views.html.base.layout(
title = title,
moreCss = frag(cssTag("team"), cssTag("tagify")),
moreJs = jsModule("team.admin")
moreJs = frag(
jsModule("team.admin"),
embedJsUnsafeLoadThen("""teamAdmin.initTagify('form3-leaders')""")
)
) {
main(cls := "page-menu page-small")(
bits.menu(none),
@ -39,24 +42,30 @@ object admin {
}
}
def kick(t: lila.team.Team, userIds: Iterable[lila.user.User.ID])(implicit ctx: Context) = {
def kick(t: lila.team.Team, form: Form[_])(implicit ctx: Context) = {
val title = s"${t.name}${kickSomeone.txt()}"
bits.layout(title = title) {
views.html.base.layout(
title = title,
moreCss = frag(cssTag("team"), cssTag("tagify")),
moreJs = frag(
jsModule("team.admin"),
embedJsUnsafeLoadThen("""teamAdmin.initTagify('form3-members')""")
)
) {
main(cls := "page-menu page-small")(
bits.menu(none),
div(cls := "page-menu__content box box-pad")(
h1(title),
p(whoToKick()),
br,
br,
postForm(cls := "kick", action := routes.Team.kick(t.id))(
userIds.toList.sorted.map { userId =>
button(name := "userId", cls := "button button-empty button-no-upper confirm", value := userId)(
usernameOrId(userId)
)
}
postForm(action := routes.Team.kick(t.id))(
form3.group(form("members"), frag(whoToKick()))(
form3.textarea(_)(rows := 2)
),
form3.actions(
a(href := routes.Team.show(t.id))(trans.cancel()),
form3.submit(trans.save())
)
)
)
)

View File

@ -232,22 +232,27 @@ final class TeamApi(
} >>-
Bus.publish(KickFromTeam(teamId = team.id, userId = userId), "teamKick")
def kickMembers(team: Team, json: String, me: User) =
parseTagifyInput(json) map (kick(team, _, me))
private case class TagifyUser(value: String)
implicit private val TagifyUserReads = Json.reads[TagifyUser]
def setLeaders(team: Team, json: String, by: User, byMod: Boolean): Funit = {
val leaders: Set[User.ID] = Try {
json.trim.nonEmpty ?? {
Json.parse(json).validate[List[TagifyUser]] match {
case JsSuccess(users, _) =>
users
.map(_.value.toLowerCase.trim)
.filter(User.lichessId !=)
.toSet take 30
case _ => Set.empty[User.ID]
}
private def parseTagifyInput(json: String) = Try {
json.trim.nonEmpty ?? {
Json.parse(json).validate[List[TagifyUser]] match {
case JsSuccess(users, _) =>
users
.map(_.value.toLowerCase.trim)
.filter(User.lichessId !=)
.toSet
case _ => Set.empty[User.ID]
}
} getOrElse Set.empty
}
} getOrElse Set.empty
def setLeaders(team: Team, json: String, by: User, byMod: Boolean): Funit = {
val leaders: Set[User.ID] = parseTagifyInput(json) take 30
for {
ids <- memberRepo.filterUserIdsInTeam(team.id, leaders)
previousValidLeaders <- memberRepo.filterUserIdsInTeam(team.id, team.leaders)

View File

@ -117,6 +117,10 @@ final private[team] class TeamForm(
.map(_.name)
.mkString(", ")
def members = Form(
single("members" -> nonEmptyText)
)
private def teamExists(setup: TeamSetup) =
teamRepo.coll.exists($id(Team nameToId setup.trim.name))
}

View File

@ -198,6 +198,7 @@ export default rollupProject({
teamAdmin: {
input: 'src/teamAdmin.ts',
output: 'team.admin',
name: 'teamAdmin',
},
appeal: {
input: 'src/appeal.ts',

View File

@ -2,8 +2,8 @@ import Tagify from '@yaireo/tagify';
import debounce from 'debounce-promise';
import * as xhr from 'common/xhr';
lichess.load.then(() => {
const input = document.getElementById('form3-leaders') as HTMLInputElement;
export function initTagify(id: string) {
const input = document.getElementById(id) as HTMLInputElement;
const tagify = new Tagify(input, {
pattern: /.{3,}/,
@ -26,4 +26,4 @@ lichess.load.then(() => {
tagify.loading(false).dropdown.show.call(tagify, term); // render the suggestions dropdown
});
});
});
}