student notes
parent
7b2b0e8f82
commit
0ff2435307
|
@ -27,8 +27,8 @@ final class Clas(
|
|||
.bindFromRequest()(ctx.body)
|
||||
.fold(
|
||||
err => BadRequest(html.clas.clas.create(err)).fuccess,
|
||||
setup =>
|
||||
env.clas.api.clas.create(setup, t.teacher) map { clas =>
|
||||
data =>
|
||||
env.clas.api.clas.create(data, t.teacher) map { clas =>
|
||||
Redirect(routes.Clas.show(clas.id.value))
|
||||
}
|
||||
)
|
||||
|
@ -69,9 +69,9 @@ final class Clas(
|
|||
.bindFromRequest()(ctx.body)
|
||||
.fold(
|
||||
err => BadRequest(html.clas.clas.edit(clas, err)).fuccess,
|
||||
setup =>
|
||||
env.clas.api.clas.update(clas, setup) map { clas =>
|
||||
Redirect(routes.Clas.show(clas.id.value))
|
||||
data =>
|
||||
env.clas.api.clas.update(clas, data) map { clas =>
|
||||
Redirect(routes.Clas.show(clas.id.value)).flashSuccess
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -159,20 +159,39 @@ final class Clas(
|
|||
|
||||
def studentShow(id: String, username: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
env.user.repo named username flatMap {
|
||||
_ ?? { user =>
|
||||
env.clas.api.student.get(clas, user) flatMap {
|
||||
_ ?? { student =>
|
||||
env.activity.read.recent(student.user, 14) map { activity =>
|
||||
views.html.clas.student.show(clas, students, student, activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
WithStudent(clas, username) { s =>
|
||||
env.activity.read.recent(s.user, 14) map { activity =>
|
||||
views.html.clas.student.show(clas, students, s, activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def studentEdit(id: String, username: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
WithStudent(clas, username) { s =>
|
||||
Ok(views.html.clas.student.edit(clas, students, s, env.clas.forms.student edit s.student)).fuccess
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def studentUpdate(id: String, username: String) = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
WithStudent(clas, username) { s =>
|
||||
env.clas.forms.student
|
||||
.edit(s.student)
|
||||
.bindFromRequest()(ctx.body)
|
||||
.fold(
|
||||
err => BadRequest(html.clas.student.edit(clas, students, s, err)).fuccess,
|
||||
data =>
|
||||
env.clas.api.student.update(s.student, data) map { _ =>
|
||||
Redirect(routes.Clas.studentShow(clas.id.value, s.user.username)).flashSuccess
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def studentArchive(id: String, username: String, v: Boolean) = Secure(_.Teacher) { _ => me =>
|
||||
WithClass(me, id) { t => clas =>
|
||||
WithStudent(clas, username) { s =>
|
||||
|
|
|
@ -59,6 +59,7 @@ object clas {
|
|||
)("Add student")
|
||||
)
|
||||
),
|
||||
standardFlash(),
|
||||
clas.desc.nonEmpty option div(cls := "box__pad clas-desc")(clas.desc),
|
||||
teachers(clas),
|
||||
students.partition(_.student.isArchived) match {
|
||||
|
|
|
@ -7,6 +7,7 @@ import lila.api.Context
|
|||
import lila.app.templating.Environment._
|
||||
import lila.app.ui.ScalatagsTemplate._
|
||||
import lila.clas.{ Clas, Student }
|
||||
import lila.common.String.html.richText
|
||||
|
||||
object student {
|
||||
|
||||
|
@ -18,29 +19,7 @@ object student {
|
|||
)(implicit ctx: Context) =
|
||||
bits.layout(s.user.username, Left(clas withStudents students), s.student.some)(
|
||||
cls := "student-show",
|
||||
div(cls := "student-show__top")(
|
||||
h1(dataIcon := "r")(
|
||||
span(
|
||||
strong(s.user.username),
|
||||
em(s.student.realName)
|
||||
)
|
||||
),
|
||||
div(cls := "student-show__top__meta")(
|
||||
p(
|
||||
"Invited to ",
|
||||
a(href := routes.Clas.show(clas.id.value))(clas.name),
|
||||
" by ",
|
||||
userIdLink(s.student.created.by.value.some, withOnline = false),
|
||||
" ",
|
||||
momentFromNowOnce(s.student.created.at)
|
||||
),
|
||||
a(
|
||||
href := routes.User.show(s.user.username),
|
||||
cls := "button button-empty",
|
||||
title := "View full Lichess profile"
|
||||
)("profile")
|
||||
)
|
||||
),
|
||||
top(clas, s),
|
||||
div(cls := "box__pad")(
|
||||
standardFlash(),
|
||||
s.student.archived map { archived =>
|
||||
|
@ -59,6 +38,7 @@ object student {
|
|||
)
|
||||
)
|
||||
},
|
||||
s.student.notes.nonEmpty option div(cls := "student-show__notes")(richText(s.student.notes)),
|
||||
s.student.managed option div(cls := "student-show__managed")(
|
||||
p("This student account is managed"),
|
||||
div(cls := "student-show__managed__actions")(
|
||||
|
@ -91,6 +71,38 @@ object student {
|
|||
)
|
||||
)
|
||||
|
||||
private def top(clas: Clas, s: Student.WithUser) =
|
||||
div(cls := "student-show__top")(
|
||||
h1(dataIcon := "r")(
|
||||
span(
|
||||
strong(s.user.username),
|
||||
em(s.student.realName)
|
||||
)
|
||||
),
|
||||
div(cls := "student-show__top__meta")(
|
||||
p(
|
||||
"Invited to ",
|
||||
a(href := routes.Clas.show(clas.id.value))(clas.name),
|
||||
" by ",
|
||||
userIdLink(s.student.created.by.value.some, withOnline = false),
|
||||
" ",
|
||||
momentFromNowOnce(s.student.created.at)
|
||||
),
|
||||
div(
|
||||
a(
|
||||
href := routes.Clas.studentEdit(clas.id.value, s.user.username),
|
||||
cls := "button button-empty",
|
||||
title := "Edit student"
|
||||
)("Edit"),
|
||||
a(
|
||||
href := routes.User.show(s.user.username),
|
||||
cls := "button button-empty",
|
||||
title := "View full Lichess profile"
|
||||
)("Profile")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
private val sortNumberTh = th(attr("data-sort-method") := "number")
|
||||
private val dataSort = attr("data-sort")
|
||||
|
||||
|
@ -128,7 +140,7 @@ object student {
|
|||
)
|
||||
)
|
||||
|
||||
private def realName(form: Form[_])(implicit ctx: Context) =
|
||||
private def realNameField(form: Form[_])(implicit ctx: Context) =
|
||||
form3.group(
|
||||
form("realName"),
|
||||
frag("Real name"),
|
||||
|
@ -181,7 +193,7 @@ object student {
|
|||
form3.group(invite("username"), frag("Lichess username"))(
|
||||
form3.input(_, klass = "user-autocomplete")(created.isEmpty option autofocus)(dataTag := "span")
|
||||
),
|
||||
realName(invite),
|
||||
realNameField(invite),
|
||||
form3.submit("Invite")
|
||||
)
|
||||
),
|
||||
|
@ -204,9 +216,29 @@ object student {
|
|||
form3.group(create("username"), frag("Lichess username"))(
|
||||
form3.input(_)(created.isDefined option autofocus)
|
||||
),
|
||||
realName(create),
|
||||
realNameField(create),
|
||||
form3.submit(trans.signUp())
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def edit(clas: Clas, students: List[Student], s: Student.WithUser, form: Form[_])(implicit ctx: Context) =
|
||||
bits.layout(s.user.username, Left(clas withStudents students), s.student.some)(
|
||||
cls := "student-show student-edit",
|
||||
top(clas, s),
|
||||
div(cls := "box__pad")(
|
||||
standardFlash(),
|
||||
postForm(cls := "form3", action := routes.Clas.studentUpdate(clas.id.value, s.user.username))(
|
||||
form3.globalError(form),
|
||||
realNameField(form),
|
||||
form3.group(form("notes"), raw("Notes"), help = frag("Only visible to the class teachers").some)(
|
||||
form3.textarea(_)(autofocus, rows := 15)
|
||||
),
|
||||
form3.actions(
|
||||
a(href := routes.Clas.studentShow(clas.id.value, s.user.username))(trans.cancel()),
|
||||
form3.submit(trans.apply())
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -451,6 +451,8 @@ GET /class/$id<\w{8}>/student/:username controllers.Clas.studentShow(id: Strin
|
|||
POST /class/$id<\w{8}>/student/:username/archive controllers.Clas.studentArchive(id: String, username: String, v: Boolean)
|
||||
POST /class/$id<\w{8}>/student/:username/reset-password controllers.Clas.studentResetPassword(id: String, username: String)
|
||||
POST /class/$id<\w{8}>/student/:username/set-kid controllers.Clas.studentSetKid(id: String, username: String, v: Boolean)
|
||||
GET /class/$id<\w{8}>/student/:username/edit controllers.Clas.studentEdit(id: String, username: String)
|
||||
POST /class/$id<\w{8}>/student/:username/edit controllers.Clas.studentUpdate(id: String, username: String)
|
||||
|
||||
# DB image
|
||||
GET /image/:id/:hash/:name controllers.Main.image(id: String, hash: String, name: String)
|
||||
|
|
|
@ -111,6 +111,11 @@ final class ClasApi(
|
|||
// def isIn(clas: Clas, userId: User.ID): Fu[Boolean] =
|
||||
// coll.exists($id(Student.id(userId, clas.id)))
|
||||
|
||||
def update(from: Student, data: ClasForm.StudentData): Fu[Student] = {
|
||||
val student = data update from
|
||||
coll.update.one($id(student.id), student) inject student
|
||||
}
|
||||
|
||||
def create(
|
||||
clas: Clas,
|
||||
data: ClasForm.NewStudent,
|
||||
|
|
|
@ -43,6 +43,14 @@ final class ClasForm(
|
|||
)(NewStudent.apply)(NewStudent.unapply)
|
||||
)
|
||||
|
||||
def edit(s: Student) =
|
||||
Form(
|
||||
mapping(
|
||||
"realName" -> nonEmptyText,
|
||||
"notes" -> text(maxLength = 20000)
|
||||
)(StudentData.apply)(StudentData.unapply)
|
||||
) fill StudentData(s.realName, s.notes)
|
||||
|
||||
private def blockingFetchUser(username: String) =
|
||||
lightUserAsync(lila.user.User normalize username).await(1 second, "clasInviteUser")
|
||||
}
|
||||
|
@ -64,4 +72,14 @@ object ClasForm {
|
|||
username: String,
|
||||
realName: String
|
||||
)
|
||||
|
||||
case class StudentData(
|
||||
realName: String,
|
||||
notes: String
|
||||
) {
|
||||
def update(c: Student) = c.copy(
|
||||
realName = realName,
|
||||
notes = notes
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,18 +7,23 @@ $clas-color: rgb(127, 90, 240);
|
|||
max-width: 15vw;
|
||||
}
|
||||
&.student {
|
||||
font-weight: bold;
|
||||
padding: .4rem 2vw .4rem .8rem;
|
||||
&.active {
|
||||
color: $clas-color;
|
||||
}
|
||||
&::after {
|
||||
background: $clas-color;
|
||||
}
|
||||
em {
|
||||
@extend %roboto;
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
display: none;
|
||||
}
|
||||
@include breakpoint($mq-subnav-side) {
|
||||
font-weight: bold;
|
||||
padding: .4rem 2vw .4rem .8rem;
|
||||
&.active {
|
||||
color: $clas-color;
|
||||
}
|
||||
&::after {
|
||||
background: $clas-color;
|
||||
}
|
||||
em {
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +80,10 @@ $clas-color: rgb(127, 90, 240);
|
|||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.teachers {
|
||||
margin: 1em 0 2em 0;
|
||||
}
|
||||
|
||||
.students {
|
||||
&-archived {
|
||||
margin-top: 2em;
|
||||
|
@ -135,6 +144,10 @@ $clas-color: rgb(127, 90, 240);
|
|||
}
|
||||
}
|
||||
|
||||
&__notes {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
&__managed {
|
||||
@extend %box-radius, %flex-between;
|
||||
background: fade-out($c-primary, .8);
|
||||
|
|
Loading…
Reference in New Issue