remove class teacher class and collection
parent
a5cda93e42
commit
0b28c69ea1
|
@ -16,10 +16,8 @@ final class Clas(
|
|||
case _ if getBool("home") => renderHome
|
||||
case None => renderHome
|
||||
case Some(me) if isGranted(_.Teacher) =>
|
||||
WithTeacher(me) { t =>
|
||||
env.clas.api.clas.of(t.teacher) map { classes =>
|
||||
Ok(views.html.clas.clas.teacherIndex(classes))
|
||||
}
|
||||
env.clas.api.clas.of(me) map { classes =>
|
||||
Ok(views.html.clas.clas.teacherIndex(classes))
|
||||
}
|
||||
case Some(me) =>
|
||||
env.clas.api.student.isStudent(me.id) flatMap {
|
||||
|
@ -44,17 +42,15 @@ final class Clas(
|
|||
}
|
||||
|
||||
def create = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
WithTeacher(me) { t =>
|
||||
env.clas.forms.clas.create
|
||||
.bindFromRequest()(ctx.body)
|
||||
.fold(
|
||||
err => BadRequest(html.clas.clas.create(err)).fuccess,
|
||||
data =>
|
||||
env.clas.api.clas.create(data, t.teacher) map { clas =>
|
||||
Redirect(routes.Clas.show(clas.id.value))
|
||||
}
|
||||
)
|
||||
}
|
||||
env.clas.forms.clas.create
|
||||
.bindFromRequest()(ctx.body)
|
||||
.fold(
|
||||
err => BadRequest(html.clas.clas.create(err)).fuccess,
|
||||
data =>
|
||||
env.clas.api.clas.create(data, me) map { clas =>
|
||||
Redirect(routes.Clas.show(clas.id.value))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private def preloadStudentUsers(students: List[lila.clas.Student.WithUser]): Unit =
|
||||
|
@ -62,14 +58,14 @@ final class Clas(
|
|||
|
||||
def show(id: String) = Auth { implicit ctx => me =>
|
||||
WithClassAny(id, me)(
|
||||
forTeacher = WithClass(me, id) { _ => clas =>
|
||||
forTeacher = WithClass(me, id) { clas =>
|
||||
env.clas.api.student.activeWithUsers(clas) map { students =>
|
||||
preloadStudentUsers(students)
|
||||
views.html.clas.teacherDashboard.overview(clas, students)
|
||||
}
|
||||
},
|
||||
forStudent = (clas, students) =>
|
||||
env.clas.api.teacher.of(clas) map { teachers =>
|
||||
env.clas.api.clas.teachers(clas) map { teachers =>
|
||||
preloadStudentUsers(students)
|
||||
val wall = scalatags.Text.all.raw(env.clas.markup(clas.wall))
|
||||
Ok(views.html.clas.studentDashboard(clas, wall, teachers, students))
|
||||
|
@ -95,7 +91,7 @@ final class Clas(
|
|||
|
||||
def wall(id: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAny(id, me)(
|
||||
forTeacher = WithClass(me, id) { _ => clas =>
|
||||
forTeacher = WithClass(me, id) { clas =>
|
||||
env.clas.api.student.allWithUsers(clas) map { students =>
|
||||
val wall = scalatags.Text.all.raw(env.clas.markup(clas.wall))
|
||||
views.html.clas.wall.show(clas, wall, students)
|
||||
|
@ -106,7 +102,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def wallEdit(id: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.api.student.activeWithUsers(clas) map { students =>
|
||||
Ok(html.clas.wall.edit(clas, students, env.clas.forms.clas.wall fill clas.wall))
|
||||
}
|
||||
|
@ -114,7 +110,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def wallUpdate(id: String) = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.forms.clas.wall
|
||||
.bindFromRequest()(ctx.body)
|
||||
.fold(
|
||||
|
@ -130,7 +126,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def notifyStudents(id: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.api.student.activeWithUsers(clas) map { students =>
|
||||
Ok(html.clas.clas.notify(clas, students, env.clas.forms.clas.notifyText))
|
||||
}
|
||||
|
@ -138,7 +134,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def notifyPost(id: String) = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.forms.clas.notifyText
|
||||
.bindFromRequest()(ctx.body)
|
||||
.fold(
|
||||
|
@ -158,7 +154,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def archived(id: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.api.student.allWithUsers(clas) map { students =>
|
||||
views.html.clas.teacherDashboard.archived(clas, students)
|
||||
}
|
||||
|
@ -167,7 +163,7 @@ final class Clas(
|
|||
|
||||
def progress(id: String, key: String, days: Int) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
lila.rating.PerfType(key) ?? { perfType =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.api.student.activeWithUsers(clas) flatMap { students =>
|
||||
env.clas.progressApi(perfType, days, students) map { progress =>
|
||||
views.html.clas.teacherDashboard.progress(clas, students, progress)
|
||||
|
@ -178,7 +174,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def edit(id: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.api.student.activeWithUsers(clas) map { students =>
|
||||
Ok(html.clas.clas.edit(clas, students, env.clas.forms.clas.edit(clas)))
|
||||
}
|
||||
|
@ -186,7 +182,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def update(id: String) = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.forms.clas
|
||||
.edit(clas)
|
||||
.bindFromRequest()(ctx.body)
|
||||
|
@ -204,8 +200,8 @@ final class Clas(
|
|||
}
|
||||
|
||||
def archive(id: String, v: Boolean) = SecureBody(_.Teacher) { _ => me =>
|
||||
WithClass(me, id) { t => clas =>
|
||||
env.clas.api.clas.archive(clas, t.teacher, v) inject
|
||||
WithClass(me, id) { clas =>
|
||||
env.clas.api.clas.archive(clas, me, v) inject
|
||||
Redirect(routes.Clas.show(clas.id.value)).flashSuccess
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +210,7 @@ final class Clas(
|
|||
if (getBool("gen")) env.clas.nameGenerator() map {
|
||||
Ok(_)
|
||||
} else
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
WithClassAndStudents(me, id) { (clas, students) =>
|
||||
ctx.req.flash.get("created").map(_ split ' ').?? {
|
||||
case Array(userId, password) =>
|
||||
env.clas.api.student
|
||||
|
@ -240,7 +236,7 @@ final class Clas(
|
|||
def studentCreate(id: String) = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
NoTor {
|
||||
Firewall {
|
||||
WithClassAndStudents(me, id) { t => (clas, students) =>
|
||||
WithClassAndStudents(me, id) { (clas, students) =>
|
||||
env.clas.forms.student.create
|
||||
.bindFromRequest()(ctx.body)
|
||||
.fold(
|
||||
|
@ -254,7 +250,7 @@ final class Clas(
|
|||
)
|
||||
).fuccess,
|
||||
data =>
|
||||
env.clas.api.student.create(clas, data, t) map {
|
||||
env.clas.api.student.create(clas, data, me) map {
|
||||
case (user, password) =>
|
||||
Redirect(routes.Clas.studentForm(clas.id.value))
|
||||
.flashing("created" -> s"${user.id} ${password.value}")
|
||||
|
@ -266,7 +262,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def studentInvite(id: String) = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { t => (clas, students) =>
|
||||
WithClassAndStudents(me, id) { (clas, students) =>
|
||||
env.clas.forms.student
|
||||
.invite(clas)
|
||||
.bindFromRequest()(ctx.body)
|
||||
|
@ -283,7 +279,7 @@ final class Clas(
|
|||
data =>
|
||||
env.user.repo named data.username flatMap {
|
||||
_ ?? { user =>
|
||||
env.clas.api.student.invite(clas, user, data.realName, t) map { so =>
|
||||
env.clas.api.student.invite(clas, user, data.realName, me) map { so =>
|
||||
Redirect(routes.Clas.studentForm(clas.id.value)).flashing {
|
||||
so.fold("warning" -> s"${user.username} is already in the class") { s =>
|
||||
"success" -> s"${user.username} (${s.realName}) has been invited"
|
||||
|
@ -297,7 +293,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def studentShow(id: String, username: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
WithClassAndStudents(me, id) { (clas, students) =>
|
||||
WithStudent(clas, username) { s =>
|
||||
env.activity.read.recent(s.user, 14) map { activity =>
|
||||
views.html.clas.student.show(clas, students, s, activity)
|
||||
|
@ -307,7 +303,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def studentEdit(id: String, username: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
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
|
||||
}
|
||||
|
@ -315,7 +311,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def studentUpdate(id: String, username: String) = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
WithClassAndStudents(me, id) { (clas, students) =>
|
||||
WithStudent(clas, username) { s =>
|
||||
env.clas.forms.student
|
||||
.edit(s.student)
|
||||
|
@ -332,16 +328,16 @@ final class Clas(
|
|||
}
|
||||
|
||||
def studentArchive(id: String, username: String, v: Boolean) = Secure(_.Teacher) { _ => me =>
|
||||
WithClass(me, id) { t => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
WithStudent(clas, username) { s =>
|
||||
env.clas.api.student.archive(s.student, t.teacher, v) inject
|
||||
env.clas.api.student.archive(s.student, me, v) inject
|
||||
Redirect(routes.Clas.studentShow(clas.id.value, username)).flashSuccess
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def studentSetKid(id: String, username: String, v: Boolean) = Secure(_.Teacher) { _ => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
WithStudent(clas, username) { s =>
|
||||
(s.student.managed ?? env.user.repo.setKid(s.user, v)) inject
|
||||
Redirect(routes.Clas.studentShow(clas.id.value, username)).flashSuccess
|
||||
|
@ -350,7 +346,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def studentResetPassword(id: String, username: String) = Secure(_.Teacher) { _ => me =>
|
||||
WithClass(me, id) { _ => clas =>
|
||||
WithClass(me, id) { clas =>
|
||||
WithStudent(clas, username) { s =>
|
||||
env.security.store.closeAllSessionsOf(s.user.id) >>
|
||||
env.clas.api.student.resetPassword(s.student) map { password =>
|
||||
|
@ -362,7 +358,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def studentRelease(id: String, username: String) = Secure(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
WithClassAndStudents(me, id) { (clas, students) =>
|
||||
WithStudent(clas, username) { s =>
|
||||
if (s.student.managed)
|
||||
Ok(views.html.clas.student.release(clas, students, s, env.clas.forms.student.release)).fuccess
|
||||
|
@ -373,7 +369,7 @@ final class Clas(
|
|||
}
|
||||
|
||||
def studentReleasePost(id: String, username: String) = SecureBody(_.Teacher) { implicit ctx => me =>
|
||||
WithClassAndStudents(me, id) { _ => (clas, students) =>
|
||||
WithClassAndStudents(me, id) { (clas, students) =>
|
||||
WithStudent(clas, username) { s =>
|
||||
if (s.student.managed)
|
||||
env.security.forms.preloadEmailDns(ctx.body) >> env.clas.forms.student.release
|
||||
|
@ -403,27 +399,16 @@ final class Clas(
|
|||
Redirect("https://forms.gle/b19pDZZuotncxtbRA")
|
||||
}
|
||||
|
||||
private def WithTeacher(me: lila.user.User)(
|
||||
f: lila.clas.Teacher.WithUser => Fu[Result]
|
||||
): Fu[Result] =
|
||||
env.clas.api.teacher withOrCreate me flatMap f
|
||||
|
||||
private def WithClass(me: lila.user.User, clasId: String)(
|
||||
f: lila.clas.Teacher.WithUser => lila.clas.Clas => Fu[Result]
|
||||
f: lila.clas.Clas => Fu[Result]
|
||||
): Fu[Result] =
|
||||
WithTeacher(me) { t =>
|
||||
env.clas.api.clas.getAndView(lila.clas.Clas.Id(clasId), t.teacher) flatMap {
|
||||
_ ?? f(t)
|
||||
}
|
||||
}
|
||||
env.clas.api.clas.getAndView(lila.clas.Clas.Id(clasId), me) flatMap { _ ?? f }
|
||||
|
||||
private def WithClassAndStudents(me: lila.user.User, clasId: String)(
|
||||
f: lila.clas.Teacher.WithUser => (lila.clas.Clas, List[lila.clas.Student]) => Fu[Result]
|
||||
f: (lila.clas.Clas, List[lila.clas.Student]) => Fu[Result]
|
||||
): Fu[Result] =
|
||||
WithClass(me, clasId) { t => c =>
|
||||
env.clas.api.student.activeOf(c) flatMap { students =>
|
||||
f(t)(c, students)
|
||||
}
|
||||
WithClass(me, clasId) { c =>
|
||||
env.clas.api.student.activeOf(c) flatMap { f(c, _) }
|
||||
}
|
||||
|
||||
private def WithStudent(clas: lila.clas.Clas, username: String)(
|
||||
|
@ -431,9 +416,7 @@ final class Clas(
|
|||
): Fu[Result] =
|
||||
env.user.repo named username flatMap {
|
||||
_ ?? { user =>
|
||||
env.clas.api.student.get(clas, user) flatMap {
|
||||
_ ?? f
|
||||
}
|
||||
env.clas.api.student.get(clas, user) flatMap { _ ?? f }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ private object bits {
|
|||
|
||||
def showArchived(archived: Clas.Recorded)(implicit ctx: Context) =
|
||||
div(
|
||||
trans.clas.closedByX(userIdLink(archived.by.value.some)),
|
||||
trans.clas.closedByX(userIdLink(archived.by.some)),
|
||||
" ",
|
||||
momentFromNowOnce(archived.at)
|
||||
)
|
||||
|
|
|
@ -84,7 +84,7 @@ object clas {
|
|||
def teachers(clas: Clas)(implicit lang: Lang) =
|
||||
div(cls := "clas-teachers")(
|
||||
trans.clas.teachersX(
|
||||
fragList(clas.teachers.toList.map(t => userIdLink(t.value.some)))
|
||||
fragList(clas.teachers.toList.map(t => userIdLink(t.some)))
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ object student {
|
|||
p(
|
||||
trans.clas.invitedToXByY(
|
||||
a(href := routes.Clas.show(clas.id.value))(clas.name),
|
||||
userIdLink(s.student.created.by.value.some, withOnline = false)
|
||||
userIdLink(s.student.created.by.some, withOnline = false)
|
||||
),
|
||||
" ",
|
||||
momentFromNowOnce(s.student.created.at)
|
||||
|
|
|
@ -4,8 +4,9 @@ import controllers.routes
|
|||
import lila.api.Context
|
||||
import lila.app.templating.Environment._
|
||||
import lila.app.ui.ScalatagsTemplate._
|
||||
import lila.clas.{ Clas, Student, Teacher }
|
||||
import lila.clas.{ Clas, Student }
|
||||
import lila.common.String.html.richText
|
||||
import lila.user.User
|
||||
|
||||
object studentDashboard {
|
||||
|
||||
|
@ -14,7 +15,7 @@ object studentDashboard {
|
|||
def apply(
|
||||
c: Clas,
|
||||
wall: Frag,
|
||||
teachers: List[Teacher.WithUser],
|
||||
teachers: List[User],
|
||||
students: List[Student.WithUser]
|
||||
)(implicit ctx: Context) =
|
||||
bits.layout(c.name, Left(c withStudents Nil))(
|
||||
|
@ -37,26 +38,25 @@ object studentDashboard {
|
|||
)
|
||||
),
|
||||
tbody(
|
||||
teachers.map {
|
||||
case Teacher.WithUser(_, user) =>
|
||||
tr(
|
||||
td(
|
||||
userLink(
|
||||
user,
|
||||
name = span(
|
||||
strong(user.username),
|
||||
user.profile.flatMap(_.nonEmptyRealName) map { em(_) }
|
||||
).some,
|
||||
withTitle = false
|
||||
)
|
||||
),
|
||||
td(
|
||||
user.seenAt.map { seen =>
|
||||
trans.lastSeenActive(momentFromNow(seen))
|
||||
}
|
||||
),
|
||||
challengeTd(user)
|
||||
)
|
||||
teachers.map { user =>
|
||||
tr(
|
||||
td(
|
||||
userLink(
|
||||
user,
|
||||
name = span(
|
||||
strong(user.username),
|
||||
user.profile.flatMap(_.nonEmptyRealName) map { em(_) }
|
||||
).some,
|
||||
withTitle = false
|
||||
)
|
||||
),
|
||||
td(
|
||||
user.seenAt.map { seen =>
|
||||
trans.lastSeenActive(momentFromNow(seen))
|
||||
}
|
||||
),
|
||||
challengeTd(user)
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
|
|
|
@ -5,9 +5,6 @@ import reactivemongo.api.bson._
|
|||
|
||||
private[clas] object BsonHandlers {
|
||||
|
||||
implicit val teacherIdBSONHandler = stringAnyValHandler[Teacher.Id](_.value, Teacher.Id.apply)
|
||||
implicit val teacherBSONHandler = Macros.handler[Teacher]
|
||||
|
||||
import Clas.Recorded
|
||||
implicit val recordedBSONHandler = Macros.handler[Recorded]
|
||||
|
||||
|
|
|
@ -3,12 +3,14 @@ package lila.clas
|
|||
import scalaz.NonEmptyList
|
||||
import org.joda.time.DateTime
|
||||
|
||||
import lila.user.User
|
||||
|
||||
case class Clas(
|
||||
_id: Clas.Id,
|
||||
name: String,
|
||||
desc: String,
|
||||
wall: String = "",
|
||||
teachers: NonEmptyList[Teacher.Id], // first is owner
|
||||
teachers: NonEmptyList[User.ID], // first is owner
|
||||
created: Clas.Recorded,
|
||||
viewedAt: DateTime,
|
||||
archived: Option[Clas.Recorded]
|
||||
|
@ -24,7 +26,7 @@ case class Clas(
|
|||
|
||||
object Clas {
|
||||
|
||||
def make(teacher: Teacher, name: String, desc: String) = Clas(
|
||||
def make(teacher: User, name: String, desc: String) = Clas(
|
||||
_id = Id(scala.util.Random.alphanumeric take 8 mkString),
|
||||
name = name,
|
||||
desc = desc,
|
||||
|
@ -38,15 +40,7 @@ object Clas {
|
|||
|
||||
case class Id(value: String) extends AnyVal with StringValue
|
||||
|
||||
case class Recorded(by: Teacher.Id, at: DateTime)
|
||||
case class Recorded(by: User.ID, at: DateTime)
|
||||
|
||||
case class WithStudents(clas: Clas, students: List[Student])
|
||||
|
||||
// case class WithAll(
|
||||
// clas: Clas,
|
||||
// teachers: List[Teacher],
|
||||
// students: List[Student]
|
||||
// ) {
|
||||
// def userIds = teachers.map(_.userId) ::: students.map(_.userId)
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -23,39 +23,13 @@ final class ClasApi(
|
|||
|
||||
import BsonHandlers._
|
||||
|
||||
object teacher {
|
||||
|
||||
val coll = colls.teacher
|
||||
|
||||
def withOrCreate(user: User): Fu[Teacher.WithUser] =
|
||||
coll.byId[Teacher](user.id) flatMap {
|
||||
case Some(teacher) => fuccess(Teacher.WithUser(teacher, user))
|
||||
case None =>
|
||||
val teacher = Teacher make user
|
||||
coll.insert.one(teacher) inject Teacher.WithUser(teacher, user)
|
||||
}
|
||||
|
||||
def of(clas: Clas): Fu[List[Teacher.WithUser]] =
|
||||
coll.ext.byOrderedIds[Teacher, Teacher.Id](clas.teachers.toList)(_.id) flatMap withUsers
|
||||
|
||||
def withUsers(teachers: List[Teacher]): Fu[List[Teacher.WithUser]] =
|
||||
userRepo.coll.idsMap[User, User.ID](
|
||||
teachers.map(_.userId),
|
||||
ReadPreference.secondaryPreferred
|
||||
)(_.id) map { users =>
|
||||
teachers.flatMap { s =>
|
||||
users.get(s.userId) map { Teacher.WithUser(s, _) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object clas {
|
||||
|
||||
val coll = colls.clas
|
||||
|
||||
def byId(id: Clas.Id) = coll.byId[Clas](id.value)
|
||||
|
||||
def of(teacher: Teacher): Fu[List[Clas]] =
|
||||
def of(teacher: User): Fu[List[Clas]] =
|
||||
coll.ext
|
||||
.find($doc("teachers" -> teacher.id))
|
||||
.sort($doc("archived" -> 1, "viewedAt" -> -1))
|
||||
|
@ -67,16 +41,16 @@ final class ClasApi(
|
|||
.sort($sort desc "createdAt")
|
||||
.list[Clas]()
|
||||
|
||||
def create(data: ClasForm.ClasData, teacher: Teacher): Fu[Clas] = {
|
||||
def create(data: ClasForm.ClasData, teacher: User): Fu[Clas] = {
|
||||
val clas = Clas.make(teacher, data.name, data.desc)
|
||||
coll.insert.one(clas) inject clas
|
||||
}
|
||||
|
||||
def update(from: Clas, data: ClasForm.ClasData): Fu[Clas] = {
|
||||
val clas = data update from
|
||||
userRepo.filterByRole(clas.teachers.toList.map(_.value), Permission.Teacher.dbKey) flatMap { filtered =>
|
||||
userRepo.filterByRole(clas.teachers.toList, Permission.Teacher.dbKey) flatMap { filtered =>
|
||||
val checked = clas.copy(
|
||||
teachers = clas.teachers.toList.filter(t => filtered(t.value)).toNel | from.teachers
|
||||
teachers = clas.teachers.toList.filter(filtered.contains).toNel | from.teachers
|
||||
)
|
||||
coll.update.one($id(clas.id), checked) inject checked
|
||||
}
|
||||
|
@ -85,7 +59,7 @@ final class ClasApi(
|
|||
def updateWall(clas: Clas, text: String): Funit =
|
||||
coll.updateField($id(clas.id), "wall", text).void
|
||||
|
||||
def getAndView(id: Clas.Id, teacher: Teacher): Fu[Option[Clas]] =
|
||||
def getAndView(id: Clas.Id, teacher: User): Fu[Option[Clas]] =
|
||||
coll.ext
|
||||
.findAndUpdate[Clas](
|
||||
selector = $id(id) ++ $doc("teachers" -> teacher.id),
|
||||
|
@ -93,6 +67,9 @@ final class ClasApi(
|
|||
fetchNewObject = true
|
||||
)
|
||||
|
||||
def teachers(clas: Clas): Fu[List[User]] =
|
||||
userRepo.byOrderedIds(clas.teachers.toList, ReadPreference.secondaryPreferred)
|
||||
|
||||
def isTeacherOf(teacher: User, clasId: Clas.Id): Fu[Boolean] =
|
||||
coll.exists($id(clasId) ++ $doc("teachers" -> teacher.id))
|
||||
|
||||
|
@ -102,7 +79,7 @@ final class ClasApi(
|
|||
coll.exists($inIds(clasIds) ++ $doc("teachers" -> teacherId))
|
||||
}
|
||||
|
||||
def archive(c: Clas, t: Teacher, v: Boolean): Funit =
|
||||
def archive(c: Clas, t: User, v: Boolean): Funit =
|
||||
coll.update
|
||||
.one(
|
||||
$id(c.id),
|
||||
|
@ -168,11 +145,11 @@ final class ClasApi(
|
|||
def create(
|
||||
clas: Clas,
|
||||
data: ClasForm.NewStudent,
|
||||
teacher: Teacher.WithUser
|
||||
teacher: User
|
||||
): Fu[(User, ClearPassword)] = {
|
||||
val email = EmailAddress(s"noreply.class.${clas.id}.${data.username}@lichess.org")
|
||||
val password = Student.password.generate
|
||||
lila.mon.clas.studentCreate(teacher.user.id)
|
||||
lila.mon.clas.studentCreate(teacher.id)
|
||||
userRepo
|
||||
.create(
|
||||
username = data.username,
|
||||
|
@ -181,25 +158,25 @@ final class ClasApi(
|
|||
blind = false,
|
||||
mobileApiVersion = none,
|
||||
mustConfirmEmail = false,
|
||||
lang = teacher.user.lang
|
||||
lang = teacher.lang
|
||||
)
|
||||
.orFail(s"No user could be created for ${data.username}")
|
||||
.flatMap { user =>
|
||||
userRepo.setKid(user, true) >>
|
||||
userRepo.setManagedUserInitialPerfs(user.id) >>
|
||||
coll.insert.one(Student.make(user, clas, teacher.teacher.id, data.realName, managed = true)) >>
|
||||
coll.insert.one(Student.make(user, clas, teacher.id, data.realName, managed = true)) >>
|
||||
sendWelcomeMessage(teacher, user, clas) inject
|
||||
(user -> password)
|
||||
}
|
||||
}
|
||||
|
||||
def invite(clas: Clas, user: User, realName: String, teacher: Teacher.WithUser): Fu[Option[Student]] = {
|
||||
lila.mon.clas.studentInvite(teacher.user.id)
|
||||
val student = Student.make(user, clas, teacher.teacher.id, realName, managed = false)
|
||||
def invite(clas: Clas, user: User, realName: String, teacher: User): Fu[Option[Student]] = {
|
||||
lila.mon.clas.studentInvite(teacher.id)
|
||||
val student = Student.make(user, clas, teacher.id, realName, managed = false)
|
||||
coll.insert.one(student) >> sendWelcomeMessage(teacher, user, clas) inject student.some
|
||||
}.recover(lila.db.recoverDuplicateKey(_ => none))
|
||||
|
||||
private[ClasApi] def join(clas: Clas, user: User, teacherId: Teacher.Id): Fu[Student] = {
|
||||
private[ClasApi] def join(clas: Clas, user: User, teacherId: User.ID): Fu[Student] = {
|
||||
val student = Student.make(user, clas, teacherId, "", managed = false)
|
||||
coll.insert.one(student) inject student
|
||||
}
|
||||
|
@ -209,7 +186,7 @@ final class ClasApi(
|
|||
authenticator.setPassword(s.userId, password) inject password
|
||||
}
|
||||
|
||||
def archive(s: Student, t: Teacher, v: Boolean): Funit =
|
||||
def archive(s: Student, t: User, v: Boolean): Funit =
|
||||
coll.update
|
||||
.one(
|
||||
$id(s.id),
|
||||
|
@ -229,10 +206,10 @@ final class ClasApi(
|
|||
}
|
||||
}
|
||||
|
||||
private def sendWelcomeMessage(teacher: Teacher.WithUser, student: User, clas: Clas): Funit =
|
||||
private def sendWelcomeMessage(teacher: User, student: User, clas: Clas): Funit =
|
||||
msgApi
|
||||
.post(
|
||||
orig = teacher.user.id,
|
||||
orig = teacher.id,
|
||||
dest = student.id,
|
||||
text = s"""${lila.i18n.I18nKeys.clas.welcomeToClass
|
||||
.txt(clas.name)(student.realLang | lila.i18n.defaultLang)}
|
||||
|
|
|
@ -22,7 +22,7 @@ final class ClasForm(
|
|||
"teachers" -> nonEmptyText.verifying("Invalid teacher list", str => {
|
||||
val ids = readTeacherIds(str)
|
||||
ids.nonEmpty && ids.size <= 10 && ids.forall { id =>
|
||||
blockingFetchUser(id.value).isDefined
|
||||
blockingFetchUser(id).isDefined
|
||||
}
|
||||
})
|
||||
)(ClasData.apply)(ClasData.unapply)
|
||||
|
@ -64,7 +64,7 @@ final class ClasForm(
|
|||
mapping(
|
||||
"username" -> lila.user.DataForm.historicalUsernameField
|
||||
.verifying("Unknown username", { blockingFetchUser(_).isDefined })
|
||||
.verifying("This is a teacher", u => !c.teachers.toList.exists(_.value == u.toLowerCase)),
|
||||
.verifying("This is a teacher", u => !c.teachers.toList.exists(_ == u.toLowerCase)),
|
||||
"realName" -> nonEmptyText
|
||||
)(NewStudent.apply)(NewStudent.unapply)
|
||||
)
|
||||
|
@ -106,7 +106,7 @@ object ClasForm {
|
|||
}
|
||||
|
||||
private def readTeacherIds(str: String) =
|
||||
str.linesIterator.map(_.trim).filter(_.nonEmpty).map(User.normalize).distinct.map(Teacher.Id.apply).toList
|
||||
str.linesIterator.map(_.trim).filter(_.nonEmpty).map(User.normalize).distinct.toList
|
||||
|
||||
case class NewStudent(
|
||||
username: String,
|
||||
|
|
|
@ -45,7 +45,6 @@ final class Env(
|
|||
}
|
||||
|
||||
private class ClasColls(db: lila.db.Db) {
|
||||
val teacher = db(CollName("clas_teacher"))
|
||||
val clas = db(CollName("clas_clas"))
|
||||
val student = db(CollName("clas_student"))
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ object Student {
|
|||
|
||||
def id(userId: User.ID, clasId: Clas.Id) = Id(s"${userId}:${clasId}")
|
||||
|
||||
def make(user: User, clas: Clas, teacherId: Teacher.Id, realName: String, managed: Boolean) = Student(
|
||||
def make(user: User, clas: Clas, teacherId: User.ID, realName: String, managed: Boolean) = Student(
|
||||
_id = id(user.id, clas.id),
|
||||
userId = user.id,
|
||||
clasId = clas.id,
|
||||
|
|
Loading…
Reference in New Issue