Team Declined requests page

Create a page to view all the declined requests and allow a declined request to be accepted
pull/9743/head
Ragul Balaji Ravichandran 2021-09-06 20:41:22 +05:30
parent 01f2d00218
commit 8950f3608d
12 changed files with 133 additions and 4 deletions

View File

@ -398,6 +398,28 @@ final class Team(
}
}
def declinedRequests(id: String, page: Int) =
Auth { implicit ctx => _ =>
WithOwnedTeamEnabled(id) { team =>
paginator.declinedRequests(team, page) map { requests =>
Ok(html.team.declinedRequest.all(team, requests))
}
}
}
def processDeclinedRequest(requestId: String) =
Auth { implicit ctx => me =>
import cats.implicits._
OptionFuResult(for {
requestOption <- api declinedRequest requestId
teamOption <- requestOption.??(req => env.team.teamRepo.byLeader(req.team, me.id))
} yield (teamOption, requestOption).mapN((_, _))) { case (team, request) =>
api.processDeclinedRequest(team, request) inject Redirect(
routes.Team.show(team._id)
).flashSuccess
}
}
def quit(id: String) =
AuthOrScoped(_.Team.Write)(
auth = implicit ctx =>

View File

@ -0,0 +1,55 @@
package views.html.team
import controllers.routes
import play.api.data.Form
import lila.api.Context
import lila.app.templating.Environment._
import lila.app.ui.ScalatagsTemplate._
import lila.common.String.html.richText
import lila.common.paginator.Paginator
object declinedRequest {
def all(team: lila.team.Team, requests: Paginator[lila.team.RequestWithUser])(implicit ctx: Context) = {
val title = s"${team.name}${trans.team.declinedRequests.txt()}"
views.html.base.layout(
title = title,
moreCss = frag(cssTag("team"))
) {
val pager = views.html.base.bits
.paginationByQuery(routes.Team.declinedRequests(team.id, 1), requests, showPost = true)
main(cls := "page-menu page-small")(
bits.menu(none),
div(cls := "page-menu__content box box-pad")(
h1(title),
pager,
table(cls := "slist")(
tbody(
requests.currentPageResults.map { request =>
tr(
td(userLink(request.user)),
td(richText(request.message)),
td(momentFromNow(request.date)),
td(cls := "process")(
postForm(
cls := "process-request",
action := routes.Team.processDeclinedRequest(request.id)
)(
button(name := "process", cls := "button button-green", value := "accept")(
trans.accept()
)
)
)
)
}
)
),
pager
)
)
}
}
}

View File

@ -48,7 +48,8 @@ object form {
t.enabled option postForm(cls := "form3", action := routes.Team.update(t.id))(
div(cls := "form-group")(
a(cls := "button button-empty", href := routes.Team.leaders(t.id))(teamLeaders()),
a(cls := "button button-empty", href := routes.Team.kick(t.id))(kickSomeone())
a(cls := "button button-empty", href := routes.Team.kick(t.id))(kickSomeone()),
a(cls := "button button-empty", href := routes.Team.declinedRequests(t.id))(declinedRequests())
),
entryFields(form, t.some),
textFields(form),

View File

@ -357,6 +357,8 @@ POST /team/:id/quit controllers.Team.quit(id: String)
GET /team/:id/request/new controllers.Team.requestForm(id: String)
POST /team/:id/request/new controllers.Team.requestCreate(id: String)
POST /team/:id/request/process controllers.Team.requestProcess(id: String)
GET /team/:id/declined-requests controllers.Team.declinedRequests(id: String, page: Int ?=1)
POST /team/:id/declined-request/process controllers.Team.processDeclinedRequest(id: String)
GET /team/:id/edit controllers.Team.edit(id: String)
POST /team/:id/edit controllers.Team.update(id: String)
GET /team/:id/kick controllers.Team.kickForm(id: String)

View File

@ -1674,6 +1674,7 @@ val `incorrectEntryCode` = new I18nKey("team:incorrectEntryCode")
val `teamAlreadyExists` = new I18nKey("team:teamAlreadyExists")
val `upcomingTourns` = new I18nKey("team:upcomingTourns")
val `completedTourns` = new I18nKey("team:completedTourns")
val `declinedRequests` = new I18nKey("team:declinedRequests")
val `nbMembers` = new I18nKey("team:nbMembers")
val `teamLeaders` = new I18nKey("team:teamLeaders")
val `xJoinRequests` = new I18nKey("team:xJoinRequests")

View File

@ -1,5 +1,7 @@
package lila.team
import com.softwaremill.tagging._
import lila.common.config.MaxPerPage
import lila.common.paginator._
import lila.common.LightUser
@ -9,10 +11,13 @@ import lila.db.paginator._
final private[team] class PaginatorBuilder(
teamRepo: TeamRepo,
memberRepo: MemberRepo,
declinedRequestRepo: RequestRepo @@ DeclinedRequest,
userRepo: lila.user.UserRepo,
lightUserApi: lila.user.LightUserApi
)(implicit ec: scala.concurrent.ExecutionContext) {
private val maxPerPage = MaxPerPage(15)
private val maxUserPerPage = MaxPerPage(30)
private val maxPerPage = MaxPerPage(15)
private val maxUserPerPage = MaxPerPage(30)
private val maxRequestsPerPage = MaxPerPage(10)
import BSONHandlers._
@ -54,4 +59,29 @@ final private[team] class PaginatorBuilder(
private def selector = memberRepo teamQuery team.id
private def sorting = $sort desc "date"
}
def declinedRequests(team: Team, page: Int): Fu[Paginator[RequestWithUser]] =
Paginator(
adapter = new DeclinedRequestAdapter(team),
page,
maxRequestsPerPage
)
final private class DeclinedRequestAdapter(team: Team) extends AdapterLike[RequestWithUser] {
val nbResults = declinedRequestRepo countByTeam team.id
private def selector = declinedRequestRepo teamQuery team.id
private def sorting = $sort desc "date"
def slice(offset: Int, length: Int): Fu[Seq[RequestWithUser]] = {
for {
requests <- declinedRequestRepo.coll
.find(selector)
.sort(sorting)
.skip(offset)
.cursor[Request]()
.list(length)
users <- userRepo usersFromSecondary requests.map(_.user)
} yield requests zip users map { case (request, user) => RequestWithUser(request, user) }
}
}
}

View File

@ -17,6 +17,7 @@ case class Request(
object Request {
type ID = String
def makeId(team: Team.ID, user: User.ID) = s"$user@$team"
def make(team: Team.ID, user: User.ID, message: String): Request =

View File

@ -18,6 +18,7 @@ import lila.hub.LeaderTeam
import lila.memo.CacheApi._
import lila.mod.ModlogApi
import lila.user.{ User, UserRepo }
final class TeamApi(
teamRepo: TeamRepo,
memberRepo: MemberRepo,
@ -42,7 +43,9 @@ final class TeamApi(
def lightsByLeader = teamRepo.lightsByLeader _
def request(id: Team.ID) = requestRepo.coll.byId[Request](id)
def request(id: Request.ID) = requestRepo.coll.byId[Request](id)
def declinedRequest(id: Request.ID) = declinedRequestRepo.coll.byId[Request](id)
def create(setup: TeamSetup, me: User): Fu[Team] = {
val bestId = Team.nameToId(setup.name)
@ -174,6 +177,14 @@ final class TeamApi(
_ <- !accept ?? declinedRequestRepo.coll.insert.one(request.copy(date = DateTime.now())).void
} yield ()
def processDeclinedRequest(team: Team, request: Request): Funit =
for {
_ <- declinedRequestRepo.coll.delete.one(request)
userOption <- userRepo byId request.user
_ <-
userOption.??(user => doJoin(team, user) >> notifier.acceptRequest(team, request))
} yield ()
def deleteRequestsByUserId(userId: User.ID) =
requestRepo.getByUserId(userId) flatMap {
_.map { request =>

View File

@ -53,4 +53,5 @@ Players who don't like receiving your messages might leave the team.</string>
<string name="teamAlreadyExists">This team already exists.</string>
<string name="upcomingTourns">Upcoming tournaments</string>
<string name="completedTourns">Completed tournaments</string>
<string name="declinedRequests">Declined Requests</string>
</resources>

View File

@ -1,4 +1,5 @@
@import '../../../common/css/plugin';
@import '../../../common/css/component/pagination';
@import '../../../common/css/component/slist';
@import '../../../common/css/form/form3';
@import '../../../common/css/form/captcha';

View File

@ -0,0 +1,3 @@
.pagination {
padding: 1em;
}

View File

@ -1,3 +1,4 @@
@import 'list';
@import 'show';
@import 'tournaments';
@import 'declined-request';