class student real name WIP
This commit is contained in:
parent
104b7d99a0
commit
9fd53a3c9e
|
@ -104,8 +104,8 @@ final class Clas(
|
||||||
err
|
err
|
||||||
)
|
)
|
||||||
).fuccess,
|
).fuccess,
|
||||||
username =>
|
data =>
|
||||||
env.clas.api.student.create(clas, username, t) map {
|
env.clas.api.student.create(clas, data, t) map {
|
||||||
case (user, password) =>
|
case (user, password) =>
|
||||||
Redirect(routes.Clas.studentShow(clas.id.value, user.username))
|
Redirect(routes.Clas.studentShow(clas.id.value, user.username))
|
||||||
.flashing("password" -> password.value)
|
.flashing("password" -> password.value)
|
||||||
|
@ -129,8 +129,8 @@ final class Clas(
|
||||||
env.clas.forms.student.create
|
env.clas.forms.student.create
|
||||||
)
|
)
|
||||||
).fuccess,
|
).fuccess,
|
||||||
username =>
|
data =>
|
||||||
env.user.repo named username flatMap {
|
env.user.repo named data.username flatMap {
|
||||||
_ ?? { user =>
|
_ ?? { user =>
|
||||||
env.clas.api.student.invite(clas, user, t) inject
|
env.clas.api.student.invite(clas, user, t) inject
|
||||||
Redirect(routes.Clas.studentForm(clas.id.value)).flashSuccess
|
Redirect(routes.Clas.studentForm(clas.id.value)).flashSuccess
|
||||||
|
|
|
@ -6,7 +6,7 @@ import lila.api.Context
|
||||||
import lila.app.templating.Environment._
|
import lila.app.templating.Environment._
|
||||||
import lila.app.ui.ScalatagsTemplate._
|
import lila.app.ui.ScalatagsTemplate._
|
||||||
import lila.clas.{ Clas, Student }
|
import lila.clas.{ Clas, Student }
|
||||||
import lila.clas.ClasForm.Data
|
import lila.clas.ClasForm.ClasData
|
||||||
import controllers.routes
|
import controllers.routes
|
||||||
|
|
||||||
object clas {
|
object clas {
|
||||||
|
@ -92,21 +92,21 @@ object clas {
|
||||||
fragList(clas.teachers.toList.map(t => userIdLink(t.value.some)))
|
fragList(clas.teachers.toList.map(t => userIdLink(t.value.some)))
|
||||||
)
|
)
|
||||||
|
|
||||||
def create(form: Form[Data])(implicit ctx: Context) =
|
def create(form: Form[ClasData])(implicit ctx: Context) =
|
||||||
bits.layout("New class", Right("newClass"))(
|
bits.layout("New class", Right("newClass"))(
|
||||||
cls := "box-pad",
|
cls := "box-pad",
|
||||||
h1("New class"),
|
h1("New class"),
|
||||||
innerForm(form, routes.Clas.create)
|
innerForm(form, routes.Clas.create)
|
||||||
)
|
)
|
||||||
|
|
||||||
def edit(c: lila.clas.Clas, form: Form[Data])(implicit ctx: Context) =
|
def edit(c: lila.clas.Clas, form: Form[ClasData])(implicit ctx: Context) =
|
||||||
bits.layout(c.name, Left(c))(
|
bits.layout(c.name, Left(c))(
|
||||||
cls := "box-pad",
|
cls := "box-pad",
|
||||||
h1("Edit ", c.name),
|
h1("Edit ", c.name),
|
||||||
innerForm(form, routes.Clas.update(c.id.value))
|
innerForm(form, routes.Clas.update(c.id.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
private def innerForm(form: Form[Data], url: play.api.mvc.Call)(implicit ctx: Context) =
|
private def innerForm(form: Form[ClasData], url: play.api.mvc.Call)(implicit ctx: Context) =
|
||||||
postForm(cls := "form3", action := url)(
|
postForm(cls := "form3", action := url)(
|
||||||
form3.globalError(form),
|
form3.globalError(form),
|
||||||
form3.group(form("name"), frag("Class name"))(form3.input(_)(autofocus)),
|
form3.group(form("name"), frag("Class name"))(form3.input(_)(autofocus)),
|
||||||
|
|
|
@ -142,7 +142,14 @@ object student {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def form(c: lila.clas.Clas, invite: Form[String], create: Form[String])(implicit ctx: Context) =
|
private def realName(form: Form[_])(implicit ctx: Context) =
|
||||||
|
form3.group(
|
||||||
|
form("realName"),
|
||||||
|
frag("Real name"),
|
||||||
|
help = frag("Private info, never visible on Lichess. Helps you remember who that student is.").some
|
||||||
|
)(form3.input(_))
|
||||||
|
|
||||||
|
def form(c: lila.clas.Clas, invite: Form[_], create: Form[_])(implicit ctx: Context) =
|
||||||
bits.layout("Add student", Left(c))(
|
bits.layout("Add student", Left(c))(
|
||||||
cls := "box-pad student-add",
|
cls := "box-pad student-add",
|
||||||
h1("Add student"),
|
h1("Add student"),
|
||||||
|
@ -166,6 +173,7 @@ object student {
|
||||||
form3.group(invite("invite"), frag("Invite username"))(
|
form3.group(invite("invite"), frag("Invite username"))(
|
||||||
form3.input(_, klass = "user-autocomplete")(autofocus)(dataTag := "span")
|
form3.input(_, klass = "user-autocomplete")(autofocus)(dataTag := "span")
|
||||||
),
|
),
|
||||||
|
realName(invite),
|
||||||
form3.submit("Invite")
|
form3.submit("Invite")
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -186,6 +194,7 @@ object student {
|
||||||
),
|
),
|
||||||
postForm(cls := "form3", action := routes.Clas.studentCreate(c.id.value))(
|
postForm(cls := "form3", action := routes.Clas.studentCreate(c.id.value))(
|
||||||
form3.group(create("username"), frag("Create username"))(form3.input(_)(autofocus)),
|
form3.group(create("username"), frag("Create username"))(form3.input(_)(autofocus)),
|
||||||
|
realName(create),
|
||||||
form3.submit(trans.signUp())
|
form3.submit(trans.signUp())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -50,12 +50,12 @@ final class ClasApi(
|
||||||
.sort($sort desc "viewedAt")
|
.sort($sort desc "viewedAt")
|
||||||
.list[Clas]()
|
.list[Clas]()
|
||||||
|
|
||||||
def create(data: ClasForm.Data, teacher: Teacher): Fu[Clas] = {
|
def create(data: ClasForm.ClasData, teacher: Teacher): Fu[Clas] = {
|
||||||
val clas = Clas.make(teacher, data.name, data.desc)
|
val clas = Clas.make(teacher, data.name, data.desc)
|
||||||
coll.insert.one(clas) inject clas
|
coll.insert.one(clas) inject clas
|
||||||
}
|
}
|
||||||
|
|
||||||
def update(from: Clas, data: ClasForm.Data): Fu[Clas] = {
|
def update(from: Clas, data: ClasForm.ClasData): Fu[Clas] = {
|
||||||
val clas = data update from
|
val clas = data update from
|
||||||
coll.update.one($id(clas.id), clas) inject clas
|
coll.update.one($id(clas.id), clas) inject clas
|
||||||
}
|
}
|
||||||
|
@ -109,23 +109,27 @@ final class ClasApi(
|
||||||
def isIn(clas: Clas, userId: User.ID): Fu[Boolean] =
|
def isIn(clas: Clas, userId: User.ID): Fu[Boolean] =
|
||||||
coll.exists($id(Student.id(userId, clas.id)))
|
coll.exists($id(Student.id(userId, clas.id)))
|
||||||
|
|
||||||
def create(clas: Clas, username: String, teacher: Teacher.WithUser): Fu[(User, ClearPassword)] = {
|
def create(
|
||||||
val email = EmailAddress(s"noreply.class.${clas.id}.$username@lichess.org")
|
clas: Clas,
|
||||||
|
data: ClasForm.NewStudent,
|
||||||
|
teacher: Teacher.WithUser
|
||||||
|
): Fu[(User, ClearPassword)] = {
|
||||||
|
val email = EmailAddress(s"noreply.class.${clas.id}.${data.username}@lichess.org")
|
||||||
val password = Student.password.generate
|
val password = Student.password.generate
|
||||||
lila.mon.clas.studentCreate(teacher.user.id)
|
lila.mon.clas.studentCreate(teacher.user.id)
|
||||||
userRepo
|
userRepo
|
||||||
.create(
|
.create(
|
||||||
username = username,
|
username = data.username,
|
||||||
passwordHash = authenticator.passEnc(password),
|
passwordHash = authenticator.passEnc(password),
|
||||||
email = email,
|
email = email,
|
||||||
blind = false,
|
blind = false,
|
||||||
mobileApiVersion = none,
|
mobileApiVersion = none,
|
||||||
mustConfirmEmail = false
|
mustConfirmEmail = false
|
||||||
)
|
)
|
||||||
.orFail(s"No user could be created for $username")
|
.orFail(s"No user could be created for ${data.username}")
|
||||||
.flatMap { user =>
|
.flatMap { user =>
|
||||||
userRepo.setKid(user, true) >>
|
userRepo.setKid(user, true) >>
|
||||||
coll.insert.one(Student.make(user, clas, teacher.teacher.id, managed = true)) >>
|
coll.insert.one(Student.make(user, clas, teacher.teacher.id, data.realName, managed = true)) >>
|
||||||
sendWelcomeMessage(teacher, user, clas, s"$baseUrl/class/${clas.id}") inject
|
sendWelcomeMessage(teacher, user, clas, s"$baseUrl/class/${clas.id}") inject
|
||||||
(user -> password)
|
(user -> password)
|
||||||
}
|
}
|
||||||
|
@ -139,7 +143,7 @@ final class ClasApi(
|
||||||
}
|
}
|
||||||
|
|
||||||
private[ClasApi] def join(clas: Clas, user: User, teacherId: Teacher.Id): Fu[Student] = {
|
private[ClasApi] def join(clas: Clas, user: User, teacherId: Teacher.Id): Fu[Student] = {
|
||||||
val student = Student.make(user, clas, teacherId, managed = false)
|
val student = Student.make(user, clas, teacherId, "", managed = false)
|
||||||
coll.insert.one(student) inject student
|
coll.insert.one(student) inject student
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,26 +15,32 @@ final class ClasForm(
|
||||||
mapping(
|
mapping(
|
||||||
"name" -> text(minLength = 3, maxLength = 100),
|
"name" -> text(minLength = 3, maxLength = 100),
|
||||||
"desc" -> text(minLength = 0, maxLength = 2000)
|
"desc" -> text(minLength = 0, maxLength = 2000)
|
||||||
)(Data.apply)(Data.unapply)
|
)(ClasData.apply)(ClasData.unapply)
|
||||||
)
|
)
|
||||||
|
|
||||||
def create = form
|
def create = form
|
||||||
|
|
||||||
def edit(c: Clas) = form fill Data(
|
def edit(c: Clas) = form fill ClasData(
|
||||||
name = c.name,
|
name = c.name,
|
||||||
desc = c.desc
|
desc = c.desc
|
||||||
)
|
)
|
||||||
|
|
||||||
object student {
|
object student {
|
||||||
|
|
||||||
def create = securityForms.signup.managed
|
def create = Form(
|
||||||
|
mapping(
|
||||||
|
"username" -> securityForms.signup.username,
|
||||||
|
"realName" -> nonEmptyText
|
||||||
|
)(NewStudent.apply)(NewStudent.unapply)
|
||||||
|
)
|
||||||
|
|
||||||
def invite = Form(
|
def invite = Form(
|
||||||
single(
|
mapping(
|
||||||
"invite" -> lila.user.DataForm.historicalUsernameField.verifying("Unknown username", {
|
"username" -> lila.user.DataForm.historicalUsernameField.verifying("Unknown username", {
|
||||||
blockingFetchUser(_).isDefined
|
blockingFetchUser(_).isDefined
|
||||||
})
|
}),
|
||||||
)
|
"realName" -> nonEmptyText
|
||||||
|
)(NewStudent.apply)(NewStudent.unapply)
|
||||||
)
|
)
|
||||||
|
|
||||||
private def blockingFetchUser(username: String) =
|
private def blockingFetchUser(username: String) =
|
||||||
|
@ -44,7 +50,7 @@ final class ClasForm(
|
||||||
|
|
||||||
object ClasForm {
|
object ClasForm {
|
||||||
|
|
||||||
case class Data(
|
case class ClasData(
|
||||||
name: String,
|
name: String,
|
||||||
desc: String
|
desc: String
|
||||||
) {
|
) {
|
||||||
|
@ -53,4 +59,9 @@ object ClasForm {
|
||||||
desc = desc
|
desc = desc
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class NewStudent(
|
||||||
|
username: String,
|
||||||
|
realName: String
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ case class Student(
|
||||||
_id: Student.Id, // userId:clasId
|
_id: Student.Id, // userId:clasId
|
||||||
userId: User.ID,
|
userId: User.ID,
|
||||||
clasId: Clas.Id,
|
clasId: Clas.Id,
|
||||||
|
realName: String,
|
||||||
|
notes: String,
|
||||||
managed: Boolean, // created for the class by the teacher
|
managed: Boolean, // created for the class by the teacher
|
||||||
created: Clas.Recorded,
|
created: Clas.Recorded,
|
||||||
archived: Option[Clas.Recorded]
|
archived: Option[Clas.Recorded]
|
||||||
|
@ -27,10 +29,12 @@ object Student {
|
||||||
|
|
||||||
def id(userId: User.ID, clasId: Clas.Id) = Id(s"${userId}:${clasId}")
|
def id(userId: User.ID, clasId: Clas.Id) = Id(s"${userId}:${clasId}")
|
||||||
|
|
||||||
def make(user: User, clas: Clas, teacherId: Teacher.Id, managed: Boolean) = Student(
|
def make(user: User, clas: Clas, teacherId: Teacher.Id, realName: String, managed: Boolean) = Student(
|
||||||
_id = id(user.id, clas.id),
|
_id = id(user.id, clas.id),
|
||||||
userId = user.id,
|
userId = user.id,
|
||||||
clasId = clas.id,
|
clasId = clas.id,
|
||||||
|
realName = realName,
|
||||||
|
notes = "",
|
||||||
managed = managed,
|
managed = managed,
|
||||||
created = Clas.Recorded(teacherId, DateTime.now),
|
created = Clas.Recorded(teacherId, DateTime.now),
|
||||||
archived = none
|
archived = none
|
||||||
|
|
|
@ -52,7 +52,7 @@ final class DataForm(
|
||||||
|
|
||||||
object signup {
|
object signup {
|
||||||
|
|
||||||
private val username = trimField(nonEmptyText)
|
val username = trimField(nonEmptyText)
|
||||||
.verifying(
|
.verifying(
|
||||||
Constraints minLength 2,
|
Constraints minLength 2,
|
||||||
Constraints maxLength 20,
|
Constraints maxLength 20,
|
||||||
|
@ -83,7 +83,7 @@ final class DataForm(
|
||||||
|
|
||||||
val website = Form(
|
val website = Form(
|
||||||
mapping(
|
mapping(
|
||||||
"username" -> trimField(username),
|
"username" -> username,
|
||||||
"password" -> text(minLength = 4),
|
"password" -> text(minLength = 4),
|
||||||
"email" -> withAcceptableDns(acceptableUniqueEmail(none)),
|
"email" -> withAcceptableDns(acceptableUniqueEmail(none)),
|
||||||
"agreement" -> agreement,
|
"agreement" -> agreement,
|
||||||
|
@ -94,17 +94,11 @@ final class DataForm(
|
||||||
|
|
||||||
val mobile = Form(
|
val mobile = Form(
|
||||||
mapping(
|
mapping(
|
||||||
"username" -> trimField(username),
|
"username" -> username,
|
||||||
"password" -> text(minLength = 4),
|
"password" -> text(minLength = 4),
|
||||||
"email" -> withAcceptableDns(acceptableUniqueEmail(none))
|
"email" -> withAcceptableDns(acceptableUniqueEmail(none))
|
||||||
)(MobileSignupData.apply)(_ => None)
|
)(MobileSignupData.apply)(_ => None)
|
||||||
)
|
)
|
||||||
|
|
||||||
val managed = Form(
|
|
||||||
single(
|
|
||||||
"username" -> trimField(username)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val passwordReset = Form(
|
val passwordReset = Form(
|
||||||
|
@ -214,7 +208,7 @@ final class DataForm(
|
||||||
|
|
||||||
val reopen = Form(
|
val reopen = Form(
|
||||||
mapping(
|
mapping(
|
||||||
"username" -> nonEmptyText,
|
"username" -> trimField(nonEmptyText),
|
||||||
"email" -> sendableEmail, // allow unacceptable emails for BC
|
"email" -> sendableEmail, // allow unacceptable emails for BC
|
||||||
"gameId" -> text,
|
"gameId" -> text,
|
||||||
"move" -> text
|
"move" -> text
|
||||||
|
|
Loading…
Reference in a new issue