more progress on coach

ios-push-2
Thibault Duplessis 2016-09-01 22:21:42 +02:00
parent 19a2cc7db4
commit b35bf929ed
9 changed files with 40 additions and 22 deletions

View File

@ -67,7 +67,7 @@ object Coach extends LilaController {
}
private def WithVisibleCoach(c: CoachModel.WithUser)(f: Fu[Result])(implicit ctx: Context) =
if ((c.coach.isListed || ctx.me.??(c.coach.is)) && ctx.me.??(canViewCoaches)) f
if ((c.coach.isListed || ctx.me.??(c.coach.is) || isGranted(_.Admin)) && ctx.me.??(canViewCoaches)) f
else notFound
def edit = Secure(_.Coach) { implicit ctx =>
@ -99,7 +99,7 @@ object Coach extends LilaController {
def pictureApply = AuthBody(BodyParsers.parse.multipartFormData) { implicit ctx =>
me =>
OptionFuResult(api find me) { c =>
OptionFuResult(api findOrInit me) { c =>
implicit val req = ctx.body
ctx.body.body.file("picture") match {
case Some(pic) => api.uploadPicture(c, pic) recover {

View File

@ -8,6 +8,9 @@
<a href="@routes.Message.inbox(page=1)"><span class="text" data-icon="e">@trans.inbox()</span></a>
}
<a href="@routes.Pref.form("game-display")"@if(playing){ target="_blank"}><span class="text" data-icon="%">@trans.preferences()</span></a>
@if(isGranted(_.Coach)) {
<a href="@routes.Coach.edit"><span class="text" data-icon=":">Coach manager</span></a>
}
<a href="@routes.Auth.logout"><span class="text" data-icon="w">@trans.logOut()</span></a>
<span class="sep"></span>
<a class="status" href="/lag">

View File

@ -41,8 +41,15 @@ moreJs = moreJs) {
</h1>
<p><a href="@routes.Coach.show(c.user.username)" class="text" data-icon="v">Preview coach page</a></p>
@if(!c.user.profileOrDefault.isComplete) {
<p><a href="@routes.Account.profile" target="_blank" class="text" data-icon="m">Complete your public lichess profile.</a></p>
<p>
<a href="@routes.Account.profile" target="_blank" class="text" data-icon="m">
<strong>IMPORTANT!</strong> Complete your public lichess profile.
</a>
</p>
}
<p>
Soon here: Coach page analytics
</p>
</div>
</div>
<form class="content_box_content material form" action="@routes.Coach.edit" method="POST">
@ -57,18 +64,18 @@ moreJs = moreJs) {
<div class="panels">
<div class="panel basics active">
<div>
@base.form.group(form("enabledByUser"), Html("Published in lichess coaches list"), half = true) {
@base.form.select(form("enabledByUser"), booleanChoices)
@base.form.group(form("listed"), Html("Published in lichess coaches list"), help = Html("Set to Yes when your profile is ready").some, half = true) {
@base.form.select(form("listed"), booleanChoices)
}
@base.form.group(form("available"), Html("Currently available for lessons"), half = true) {
@base.form.group(form("available"), Html("Currently available for lessons"), help = Html("Set to Yes to get more students").some, half = true) {
@base.form.select(form("available"), booleanChoices)
}
</div>
@base.form.group(form("profile.headline"), Html("Short and inspiring headline")) {
@base.form.group(form("profile.headline"), Html("Short and inspiring headline"), help = Html("Just one sentence to make students want to choose you").some) {
@base.form.input(form("profile.headline"), maxLength = 170)
}
<div>
@base.form.group(form("profile.languages"), Html("Languages spoken"), half = true) {
@base.form.group(form("profile.languages"), Html("Languages spoken"), help = Html("Which languages can you give lessons in?").some, half = true) {
@base.form.input(form("profile.languages"), maxLength = 140)
}
@base.form.group(form("profile.hourlyRate"), Html("Hourly rate"), help = Html("Indicative, non-contractual").some, half = true) {

View File

@ -18,6 +18,7 @@
<p class="error">@e</p>
}
@helper.form(action = routes.Coach.pictureApply, 'enctype -> "multipart/form-data", 'class -> "upload") {
<p>Max size: @{lila.coach.Photographer.uploadMaxMb}MB.</p>
<input type="file" name="picture">
<button type="submit" class="button">Upload profile picture</button>
}

View File

@ -376,9 +376,9 @@ GET /coach controllers.Coach.allDefault(page: Int ?=
GET /coach/sort/:order controllers.Coach.all(order: String, page: Int ?= 1)
GET /coach/edit controllers.Coach.edit
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
GET /coach/picture/edit controllers.Coach.picture
POST /coach/picture/upload controllers.Coach.pictureApply
POST /coach/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)

View File

@ -28,11 +28,15 @@ final class CoachApi(
def find(username: String): Fu[Option[Coach.WithUser]] =
UserRepo named username flatMap { _ ?? find }
def find(user: User): Fu[Option[Coach.WithUser]] =
def find(user: User): Fu[Option[Coach.WithUser]] = Granter(_.Coach)(user) ?? {
byId(Coach.Id(user.id)) map2 withUser(user)
}
def findOrInit(user: User): Fu[Option[Coach.WithUser]] = find(user) orElse {
fuccess(Coach.WithUser(Coach make user, user).some)
def findOrInit(user: User): Fu[Option[Coach.WithUser]] = Granter(_.Coach)(user) ?? {
find(user) orElse {
val c = Coach.WithUser(Coach make user, user)
coachColl.insert(c.coach) >> cache.clear inject c.some
}
}
def isListedCoach(user: User): Fu[Boolean] =

View File

@ -7,13 +7,13 @@ import lila.db.dsl._
private final class Photographer(coll: Coll) {
private val uploadedMaxMb = 3
private val uploadedMaxBytes = uploadedMaxMb * 1024 * 1024
import Photographer.uploadMaxMb
private val uploadMaxBytes = uploadMaxMb * 1024 * 1024
private def pictureId(id: Coach.Id) = s"coach:${id.value}:picture"
def apply(coachId: Coach.Id, uploaded: Photographer.Uploaded): Fu[DbImage] =
if (uploaded.ref.file.length > uploadedMaxBytes)
fufail(s"File size must not exceed ${uploadedMaxMb}MB.")
if (uploaded.ref.file.length > uploadMaxBytes)
fufail(s"File size must not exceed ${uploadMaxMb}MB.")
else {
process(uploaded.ref.file)
@ -35,7 +35,9 @@ private final class Photographer(coll: Coll) {
}
}
private object Photographer {
object Photographer {
val uploadMaxMb = 3
type Uploaded = play.api.mvc.MultipartFormData.FilePart[play.api.libs.Files.TemporaryFile]
}

View File

@ -20,8 +20,8 @@ $(function() {
submit();
});
var tab = location.hash ? location.hash.slice(1) : 'reviews';
$editor.find('.tabs div[data-tab=' + tab + ']').click();
if ($editor.find('.reviews .review').length)
$editor.find('.tabs div[data-tab=reviews]').click();
$reviews = $editor.find('.reviews');
$reviews.find('.actions a').click(function() {

View File

@ -52,7 +52,7 @@
.material.form .form-help {
margin-top: 0.125rem;
margin-left: 0.125rem;
opacity: 0.6;
opacity: 0.4;
font-size: 0.8rem;
}
.material.form .checkbox .form-help, .form-radio .form-help, .form-group .form-help {
@ -174,6 +174,7 @@ body.dark .material.form .form-group select option {
.material.form .form-group *:focus ~ .control-label,
.material.form .form-group *:focus ~ .form-help {
color: #3893E8;
opacity: 0.6;
}
.material.form .form-group *:focus ~ .bar::before {
width: 100%;