more progress on coach
parent
19a2cc7db4
commit
b35bf929ed
|
@ -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 {
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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] =
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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%;
|
||||
|
|
Loading…
Reference in New Issue