more work on coach and reviews
parent
e0efc0b26b
commit
6e7f396dc8
|
@ -46,14 +46,20 @@ object Coach extends LilaController {
|
|||
}
|
||||
}
|
||||
|
||||
def approveReview(id: String) = SecureBody(_.Coach) { implicit ctx =>
|
||||
???
|
||||
}
|
||||
|
||||
private def WithVisibleCoach(c: CoachModel.WithUser)(f: Fu[Result])(implicit ctx: Context) =
|
||||
if (c.coach.isFullyEnabled || ctx.me.??(c.coach.is) || isGranted(_.PreviewCoach)) f
|
||||
else notFound
|
||||
|
||||
def edit = Secure(_.Coach) { implicit ctx =>
|
||||
me =>
|
||||
OptionResult(api findOrInit me) { c =>
|
||||
NoCache(Ok(html.coach.edit(c, CoachProfileForm edit c.coach)))
|
||||
OptionFuResult(api findOrInit me) { c =>
|
||||
api.reviews.pendingByCoach(c.coach) map { reviews =>
|
||||
NoCache(Ok(html.coach.edit(c, CoachProfileForm edit c.coach, reviews)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +68,7 @@ object Coach extends LilaController {
|
|||
OptionFuResult(api findOrInit me) { c =>
|
||||
implicit val req = ctx.body
|
||||
CoachProfileForm.edit(c.coach).bindFromRequest.fold(
|
||||
form => fuccess(BadRequest(html.coach.edit(c, form))),
|
||||
form => fuccess(BadRequest),
|
||||
data => api.update(c, data) inject Ok
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@(c: lila.coach.Coach.WithUser, form: Form[_])(implicit ctx: Context)
|
||||
@(c: lila.coach.Coach.WithUser, form: Form[_], reviews: lila.coach.CoachReview.Reviews)(implicit ctx: Context)
|
||||
|
||||
@import play.api.data.Field
|
||||
|
||||
|
@ -49,6 +49,9 @@ moreJs = moreJs) {
|
|||
<div data-tab="basics" class="active">Basics</div>
|
||||
<div data-tab="texts">Texts</div>
|
||||
<div data-tab="contents">Contents</div>
|
||||
<div data-tab="reviews" data-count="@reviews.list.size" class="data-count">
|
||||
Pending reviews
|
||||
</div>
|
||||
</div>
|
||||
<div class="panels">
|
||||
<div class="panel basics active">
|
||||
|
@ -87,6 +90,12 @@ moreJs = moreJs) {
|
|||
}
|
||||
@textarea(form("profile.publicStudies"), Html("Featured public lichess studies"), help = Html("Up to 6 lichess study URLs, one per line").some)
|
||||
</div>
|
||||
<div class="panel reviews">
|
||||
@reviews.list.map { r =>
|
||||
<form class="review" action="@routes.Coach.approveReview(r.review.id)" method="POST">
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="status text" data-icon="E">Your changes have been saved.</div>
|
||||
</form>
|
||||
|
|
|
@ -378,6 +378,7 @@ POST /coach/edit controllers.Coach.editApply
|
|||
GET /coach/edit/picture controllers.Coach.picture
|
||||
POST /coach/edit/picture controllers.Coach.pictureApply
|
||||
POST /coach/edit/picture/delete controllers.Coach.pictureDelete
|
||||
POST /coach/approve-review/:id controllers.Coach.approveReview(id: String)
|
||||
GET /coach/:username controllers.Coach.show(username: String)
|
||||
POST /coach/:username/review controllers.Coach.review(username: String)
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ final class CoachApi(
|
|||
def approvedByCoach(c: Coach): Fu[CoachReview.Reviews] =
|
||||
findRecent($doc("coachId" -> c.id.value, "approved" -> true))
|
||||
|
||||
def notApprovedByCoach(c: Coach): Fu[CoachReview.Reviews] =
|
||||
def pendingByCoach(c: Coach): Fu[CoachReview.Reviews] =
|
||||
findRecent($doc("coachId" -> c.id.value, "approved" -> false))
|
||||
|
||||
def allByCoach(c: Coach): Fu[CoachReview.Reviews] =
|
||||
|
@ -113,6 +113,12 @@ final class CoachApi(
|
|||
private def findRecent(selector: Bdoc): Fu[CoachReview.Reviews] =
|
||||
reviewColl.find(selector)
|
||||
.sort($sort desc "createdAt")
|
||||
.list[CoachReview](100) map CoachReview.Reviews.apply
|
||||
.list[CoachReview](100) flatMap { reviews =>
|
||||
UserRepo byIds reviews.map(_.userId) map { users =>
|
||||
reviews.flatMap { review =>
|
||||
users.find(_.id == review.userId) map { CoachReview.WithUser(review, _) }
|
||||
}
|
||||
}
|
||||
} map CoachReview.Reviews
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,18 +16,20 @@ case class CoachReview(
|
|||
|
||||
object CoachReview {
|
||||
|
||||
case class WithUser(review: CoachReview, user: User)
|
||||
|
||||
def makeId(user: User, coach: Coach) = s"${user.id}:${coach.id.value}"
|
||||
|
||||
case class Score(value: Double) extends AnyVal {
|
||||
|
||||
}
|
||||
|
||||
case class Reviews(list: List[CoachReview]) {
|
||||
case class Reviews(list: List[CoachReview.WithUser]) {
|
||||
|
||||
def approved = list.filter(_.approved)
|
||||
def approved = list.filter(_.review.approved)
|
||||
|
||||
lazy val averageScore: Option[Score] = approved.nonEmpty option {
|
||||
Score(approved.map(_.score).sum.toDouble / list.size)
|
||||
Score(approved.map(_.review.score).sum.toDouble / list.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,7 @@ $(function() {
|
|||
$editor.find('div.status').removeClass('saved');
|
||||
submit();
|
||||
});
|
||||
|
||||
var tab = location.hash ? location.hash.slice(1) : 'reviews';
|
||||
$editor.find('.tabs div[data-tab=' + tab + ']').click();
|
||||
});
|
||||
|
|
|
@ -62,6 +62,14 @@
|
|||
flex: 1 1 100%;
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
.coach_edit .tabs > div.data-count::after {
|
||||
padding: 2px 6px;
|
||||
font-size: 1.2em;
|
||||
height: auto;
|
||||
line-height: 1.2em;
|
||||
top: 6px;
|
||||
}
|
||||
.coach_edit .tabs > div:hover {
|
||||
color: #3893E8;
|
||||
|
|
Loading…
Reference in New Issue