diff --git a/app/controllers/Clas.scala b/app/controllers/Clas.scala index ec8ac03c0b..77c8612c55 100644 --- a/app/controllers/Clas.scala +++ b/app/controllers/Clas.scala @@ -113,7 +113,9 @@ final class Clas( def edit(id: String) = Secure(_.Teacher) { implicit ctx => me => WithClass(me, id) { _ => clas => - Ok(html.clas.clas.edit(clas, env.clas.forms.edit(clas))).fuccess + env.clas.api.student.activeWithUsers(clas) map { students => + Ok(html.clas.clas.edit(clas, students, env.clas.forms.edit(clas))) + } } } @@ -123,7 +125,10 @@ final class Clas( .edit(clas) .bindFromRequest()(ctx.body) .fold( - err => BadRequest(html.clas.clas.edit(clas, err)).fuccess, + err => + env.clas.api.student.activeWithUsers(clas) map { students => + BadRequest(html.clas.clas.edit(clas, students, err)) + }, data => env.clas.api.clas.update(clas, data) map { clas => Redirect(routes.Clas.show(clas.id.value)).flashSuccess diff --git a/app/views/clas/clas.scala b/app/views/clas/clas.scala index 2e14e7022c..87991c8b32 100644 --- a/app/views/clas/clas.scala +++ b/app/views/clas/clas.scala @@ -5,7 +5,7 @@ import play.api.data.Form import lila.api.Context import lila.app.templating.Environment._ import lila.app.ui.ScalatagsTemplate._ -import lila.clas.Clas +import lila.clas.{ Clas, Student } import lila.clas.ClasForm.ClasData import controllers.routes @@ -39,7 +39,7 @@ object clas { h1("Lichess Classes"), a( href := routes.Clas.form, - cls := "new button button-green button-empty", + cls := "new button button-empty", title := "New Class", dataIcon := "O" ) @@ -86,19 +86,19 @@ object clas { innerForm(form, none) ) - def edit(c: lila.clas.Clas, form: Form[ClasData])(implicit ctx: Context) = - bits.layout(c.name, Left(c withStudents Nil))( - cls := "box-pad", - h1("Edit ", c.name), - innerForm(form, c.some), - hr, - c.isActive option postForm( - action := routes.Clas.archive(c.id.value, true), - cls := "clas-edit__archive" - )( - form3.submit("Archive", icon = none)( - cls := "confirm button-red button-empty", - title := "Disband the class" + def edit(c: lila.clas.Clas, students: List[Student.WithUser], form: Form[ClasData])(implicit ctx: Context) = + teacherDashboard.layout(c, students, "edit")( + div(cls := "box-pad")( + innerForm(form, c.some), + hr, + c.isActive option postForm( + action := routes.Clas.archive(c.id.value, true), + cls := "clas-edit__archive" + )( + form3.submit("Archive", icon = none)( + cls := "confirm button-red button-empty", + title := "Disband the class" + ) ) ) ) diff --git a/app/views/clas/teacherDashboard.scala b/app/views/clas/teacherDashboard.scala index 290246e985..e312c12641 100644 --- a/app/views/clas/teacherDashboard.scala +++ b/app/views/clas/teacherDashboard.scala @@ -10,48 +10,48 @@ import lila.common.String.html.richText object teacherDashboard { - private def dashboard( + private[clas] def layout( c: Clas, students: List[Student.WithUser], active: String )(modifiers: Modifier*)(implicit ctx: Context) = bits.layout(c.name, Left(c withStudents students.map(_.student)))( - cls := "clas-show dashboard dashboard-teacher", - div(cls := "box__top")( - h1(dataIcon := "f", cls := "text")(c.name), - div(cls := "box__top__actions")( + cls := s"clas-show dashboard dashboard-teacher dashboard-teacher-$active", + div(cls := "clas-show__top")( + div(cls := "box__top")( + h1(dataIcon := "f", cls := "text")(c.name), + div(cls := "box__top__actions")( + a( + href := routes.Clas.studentForm(c.id.value), + cls := "button button-green text", + dataIcon := "O" + )("Add student") + ) + ), + st.nav(cls := "dashboard-nav")( + a(cls := active.active("overview"), href := routes.Clas.show(c.id.value))("Overview"), a( - href := routes.Clas.edit(c.id.value), - cls := "button button-empty" - )("Edit"), - a( - href := routes.Clas.studentForm(c.id.value), - cls := "button button-green text", - dataIcon := "O" - )("Add student") + cls := active.active("progress"), + href := routes.Clas.progress(c.id.value, PerfType.Blitz.key, 7) + )( + "Progress" + ), + a(cls := active.active("edit"), href := routes.Clas.edit(c.id.value))("Edit"), + a(cls := active.active("archived"), href := routes.Clas.archived(c.id.value))("Archived") ) ), - div(cls := "box__pad")( - standardFlash(), - c.archived map { archived => - div(cls := "clas-show__archived archived")( - bits.showArchived(archived), - postForm(action := routes.Clas.archive(c.id.value, false))( - form3.submit("Restore", icon = none)( - cls := "confirm button-empty", - title := "Revive the class" - ) + standardFlash(), + c.archived map { archived => + div(cls := "clas-show__archived archived")( + bits.showArchived(archived), + postForm(action := routes.Clas.archive(c.id.value, false))( + form3.submit("Restore", icon = none)( + cls := "confirm button-empty", + title := "Revive the class" ) ) - } - ), - st.nav(cls := "dashboard-nav tabs-horiz")( - a(cls := active.active("overview"), href := routes.Clas.show(c.id.value))("Overview"), - a(cls := active.active("progress"), href := routes.Clas.progress(c.id.value, PerfType.Blitz.key, 7))( - "Progress" - ), - a(cls := active.active("archived"), href := routes.Clas.archived(c.id.value))("Archived") - ), + ) + }, modifiers ) @@ -59,7 +59,7 @@ object teacherDashboard { c: Clas, students: List[Student.WithUser] )(implicit ctx: Context) = - dashboard(c, students, "overview")( + layout(c, students, "overview")( div(cls := "clas-show__overview")( c.desc.trim.nonEmpty option div(cls := "clas-desc")(richText(c.desc)), clas.teachers(c) @@ -74,7 +74,7 @@ object teacherDashboard { c: Clas, students: List[Student.WithUser] )(implicit ctx: Context) = - dashboard(c, students.filter(_.student.isActive), "archived") { + layout(c, students.filter(_.student.isActive), "archived") { val archived = students.filter(_.student.isArchived) if (archived.isEmpty) p(cls := "box__pad students__empty")("No archived students.") @@ -87,7 +87,7 @@ object teacherDashboard { students: List[Student.WithUser], progress: ClasProgress )(implicit ctx: Context) = - dashboard(c, students, "progress")( + layout(c, students, "progress")( div(cls := "progress")( div(cls := "progress-perf")( label("Variant"), diff --git a/ui/common/css/abstract/_box.scss b/ui/common/css/abstract/_box.scss index d21fe4b371..ab18f83eed 100644 --- a/ui/common/css/abstract/_box.scss +++ b/ui/common/css/abstract/_box.scss @@ -17,6 +17,12 @@ %box-radius-bottom { border-radius: 0 0 $box-radius-size $box-radius-size; } +%box-radius-top-left { + border-radius: $box-radius-size 0 0 0; +} +%box-radius-top-right { + border-radius: 0 $box-radius-size 0 0; +} %box-shadow { @include box-shadow; } diff --git a/ui/common/css/component/_tabs-horiz.scss b/ui/common/css/component/_tabs-horiz.scss index 8a03d6c864..61c1793384 100644 --- a/ui/common/css/component/_tabs-horiz.scss +++ b/ui/common/css/component/_tabs-horiz.scss @@ -1,3 +1,5 @@ +$c-tabs-active: $c-accent !default; + .tabs-horiz { @extend %flex-center-nowrap, %page-text; justify-content: center; @@ -6,7 +8,7 @@ @include breakpoint($mq-not-xx-small) { font-size: .9em; } - span, > a { + span { @extend %roboto; flex: 1 1 auto; text-align: center; @@ -21,7 +23,7 @@ } &::after { content: ''; - background: fade-out($c-accent, .3); + background: fade-out($c-tabs-active, .3); height: 2px; position: absolute; width: 96%; @@ -37,7 +39,7 @@ } } &.active { - color: $c-accent; + color: $c-tabs-active; } } .unread { diff --git a/ui/site/css/_clas.scss b/ui/site/css/_clas.scss index 33139d842a..9d6b48e168 100644 --- a/ui/site/css/_clas.scss +++ b/ui/site/css/_clas.scss @@ -1,4 +1,9 @@ -$clas-color: rgb(127, 90, 240); +$c-clas: rgb(127, 90, 240); + +$c-font-clas: mix($c-font-clear, $c-clas, 30%); +$c-bg-clas: $c-clas; +$c-bg-clas-over: white; +$c-bg-clas-over-dim: mix($c-bg-clas-over, $c-bg-clas, 80%); %archived { @extend %box-radius, %flex-between; @@ -13,6 +18,12 @@ $clas-color: rgb(127, 90, 240); @include breakpoint($mq-medium) { max-width: 15vw; } + &.active { + color: $c-font-clas; + } + &::after { + background: $c-clas; + } &.student { em { @extend %roboto; @@ -21,12 +32,6 @@ $clas-color: rgb(127, 90, 240); @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; @@ -37,7 +42,12 @@ $clas-color: rgb(127, 90, 240); .clas-index { .box__top { + background: $c-bg-clas; + &, a { + color: $c-bg-clas-over; + } flex-flow: row nowrap; + h1 { margin: 0 } } .new::before { font-size: 3em; @@ -53,7 +63,7 @@ $clas-color: rgb(127, 90, 240); position: relative; @include transition(); &::before { - color: mix($c-link, $c-bg-box, 80%); + color: mix($c-clas, $c-bg-box, 80%); font-size: 5em; margin-right: .4em; @include transition(); @@ -62,9 +72,9 @@ $clas-color: rgb(127, 90, 240); } } &:hover { - background: mix($c-link, $c-bg-box, 10%); + background: mix($c-clas, $c-bg-box, 10%); &::before { - color: mix($c-link, $c-bg-box, 100%); + color: mix($c-clas, $c-bg-box, 100%); } } .overlay { @@ -72,7 +82,7 @@ $clas-color: rgb(127, 90, 240); } h3 { @include fluid-size('font-size', 23px, 35px); - color: $c-link; + color: $c-clas; } p { margin: .5em 0 0 0; @@ -88,6 +98,13 @@ $clas-color: rgb(127, 90, 240); .clas-show { + &__top { + background: $c-bg-clas; + &, a, .button, .title { + color: $c-bg-clas-over; + } + } + &__overview { @extend %box-padding; background: $c-bg-zebra; @@ -100,12 +117,11 @@ $clas-color: rgb(127, 90, 240); .dashboard { - .tabs-horiz a { - letter-spacing: normal; - font-size: 1.1em; - color: $c-font; - &.active { - color: $c-accent; + .flash { + margin: 0; + &__content { + padding: 2em var(--box-padding); + border-radius: 0; } } @@ -141,6 +157,39 @@ $clas-color: rgb(127, 90, 240); } } + &-nav { + @extend %flex-center-nowrap; + justify-content: center; + align-items: flex-end; + @include breakpoint($mq-not-xx-small) { + font-size: .9em; + } + a { + @extend %box-radius-top; + flex: 1 1 auto; + text-align: center; + padding: 1.2em 0 .8em 0; + &:first-child { + @extend %box-radius-top-right; + } + &:last-child { + @extend %box-radius-top-left; + } + &:hover { + background: mix($c-bg-zebra, $c-clas, 20%); + } + &.active { + background: $c-bg-zebra; + color: $c-font-clas; + font-weight: bold; + .dashboard-teacher-edit &, + .dashboard-teacher-archived & { + background: $c-bg-box; + } + } + } + } + &-student { .teachers { margin-bottom: 2em; @@ -170,6 +219,9 @@ $clas-color: rgb(127, 90, 240); } &-choices { @extend %flex-center, %box-neat-force; + @if $theme-dark { + box-shadow: none; + } flex: 1 1 auto; background: $c-bg-box; } @@ -178,13 +230,13 @@ $clas-color: rgb(127, 90, 240); text-align: center; font-weight: bold; padding: .7em; - color: $c-good; + color: $c-clas; &:hover { - background: mix($c-bg-box, $c-good, 70%); + background: mix($c-bg-box, $c-clas, 70%); color: $c-font-clear; } &.active { - background: $c-good; + background: $c-clas; color: $c-good-over; } border-right: 1px solid $c-border; @@ -213,22 +265,18 @@ $clas-color: rgb(127, 90, 240); .student-show { - $top-background: $clas-color; - $top-font: white; - $top-font-dim: mix($top-font, $top-background, 80%); - padding-bottom: 3em; &__top { padding: calc(5vh - 1rem) var(--box-padding); - background: $top-background; + background: $c-bg-clas; margin-bottom: 3em; &, a, .button, .title { - color: $top-font; + color: $c-bg-clas-over; } a:not(.button) { font-weight: bold; - border-bottom: 1px dotted $top-font-dim; + border-bottom: 1px dotted $c-bg-clas-over-dim; } h1 { @extend %flex-center; @@ -236,14 +284,14 @@ $clas-color: rgb(127, 90, 240); &::before { font-size: 2.5em; margin-right: .4em; - color: $top-font-dim; + color: $c-bg-clas-over-dim; } strong { display: block; } em { @extend %roboto; - color: $top-font-dim; + color: $c-bg-clas-over-dim; } } &__meta { diff --git a/ui/site/css/build/_clas.scss b/ui/site/css/build/_clas.scss index 1ab0fbef96..06d366c73f 100644 --- a/ui/site/css/build/_clas.scss +++ b/ui/site/css/build/_clas.scss @@ -2,6 +2,5 @@ @import '../../../common/css/form/form3'; @import '../../../common/css/component/slist'; @import '../../../common/css/component/tablesort'; -@import '../../../common/css/component/tabs-horiz'; @import '../user/activity'; @import '../clas';