codecombat/app/templates/courses/teacher-class-view.jade
phoenixeliot 3d705e5d70 Fix bugquest bugs
Fix link to /teachers/classes (fixes bugquest#20)

Fix edit button color/icon (bugquest#23)

Fix bugquest#34

Fix password input width (bugquest#33)

Center new pasword text

Fix teacher password reset endpoint (bugquest#4)

Refactor+use NewHomeView logic for user page button (Fixes bugquest#2)

Refactor teacher-password-reset endpoint

This makes it much easier to prevent collisions with other logic when PUTing new User attributes.

Add regression test for converting to teacher account

Fix email verified links, require login (fix bugquest#16)

Fix me having stale emailVerified value (Fixes bugquest#40)

Don't show JoinClassModal to students

Add paragraph to JoinClassModal (fixes bugquest#14)

Update change-password label text (fixes bugquest#30)

Fix prompting for login on Account Settings page (bugquest #10)

Show validation errors for teacher password reset (bugquest#36)

Show yellow progress dot in My Classes if anyone has started (bugquest#55)

Remove confusing text (bugquest#100)
2016-05-24 14:10:17 -07:00

421 lines
17 KiB
Text

extends /templates/base-flat
block page_nav
include ./teacher-dashboard-nav.jade
block content
- var classroom = view.classroom
if !me.isTeacher()
.alert.alert-danger.text-center
.container
// DNT: Temporary
h3 ATTENTION: Please upgrade your account to a Teacher Account.
p
| We are transitioning to a new improved classroom management system for instructors.
| Please convert your account to ensure you retain access to your classrooms.
a.btn.btn-primary.btn-lg(href="/teachers/update-account") Upgrade to teacher account
if classroom.loaded
.container
+breadcrumbs
if classroom.get('archived')
.row.center-block.text-center.m-t-3.m-b-3
.unarchive-btn.btn.btn-lg.btn-navy
span(data-i18n='teacher.unarchive_this_class')
h3.m-t-2= classroom.get('name')
a.label.edit-classroom(data-classroom-id=classroom.id)
span(data-i18n='teacher.edit_class_settings')
h4= classroom.get('description')
.classroom-info-row.row.m-t-5
.classroom-details.col-md-3
- var stats = state.get('classStats')
h4.m-b-2(data-i18n='teacher.class_overview')
.language.small-details
span(data-i18n='teacher.language')
span.spr :
span= classroom.capitalLanguage
.student-count.small-details
span(data-i18n='teacher.students')
span.spr :
span= classroom.get('members').length
.average-playtime.small-details
span(data-i18n='teacher.avg_playtime')
span.spr :
span= stats.averagePlaytime
.total-playtime.small-details
span(data-i18n='teacher.total_playtime')
span.spr :
span= stats.totalPlaytime
.average-complete.small-details
span(data-i18n='teacher.avg_completed')
span.spr :
span= stats.averageLevelsComplete
.total-complete.small-details
span(data-i18n='teacher.total_completed')
span.spr :
span= stats.totalLevelsComplete
.total-complete.small-details
span(data-i18n='teacher.created')
span.spr :
span= moment(classroom.created()).format('l')
if view.students && view.students.models.length > 0
button.export-student-progress-btn.btn.btn-lg.btn-primary
span(data-i18n='teacher.export_student_progress')
//- .concepts.small-details
//- if state.get('progressData')
//- div
//- span(data-i18n='teacher.concepts_covered')
//- span :
//- - console.log('concepts', view.conceptData)
//- - concepts = view.conceptData
//- each state, name in view.conceptData[view.classroom.id]
//- if state.get('started')
//- b.concept(class=state.get('completed') ? 'forest' : 'gold')
//- span(data-i18n='concepts.'+name)
.completeness-info.col-md-4
h4.m-b-2
 
if state.get('earliestIncompleteLevel')
div.small-details
span(data-i18n='teacher.earliest_incomplete')
span :
+longLevelName(state.get('earliestIncompleteLevel'))
+inlineUserList(state.get('earliestIncompleteLevel').users)
if state.get('latestCompleteLevel')
div.small-details.m-t-3
span(data-i18n='teacher.latest_complete')
span :
+longLevelName(state.get('latestCompleteLevel'))
+inlineUserList(state.get('latestCompleteLevel').users)
.adding-students.col-md-5
h4.m-b-2
span(data-i18n='teacher.adding_students')
span :
+copyCodes
+addStudentsButton
ul.nav.nav-tabs.m-t-5(role='tablist')
- var activeTab = state.get('activeTab');
li(class=(activeTab === "#students-tab" ? 'active' : ''))
a.students-tab-btn(href='#students-tab')
.small-details.text-center(data-i18n='teacher.students')
.tab-spacer
li(class=(activeTab === "#course-progress-tab" ? 'active' : ''))
a.course-progress-tab-btn(href='#course-progress-tab')
.small-details.text-center(data-i18n='teacher.course_progress')
.tab-spacer
li(class=(activeTab === "#enrollment-status-tab" ? 'active' : ''))
a.course-progress-tab-btn(href='#enrollment-status-tab')
.small-details.text-center(data-i18n='teacher.enrollment_status')
.tab-filler
.tab-content
if activeTab === '#students-tab'
+studentsTab
else if activeTab === '#course-progress-tab'
+courseProgressTab
else
+enrollmentStatusTab
mixin breadcrumbs
.breadcrumbs
a(data-i18n='teacher.my_classes' href='/teachers/classes')
span.spl.spr >
//- TODO: Use .glyphicon-menu-right when we update bootstrap
span
= view.classroom.get('name')
mixin longLevelName(data)
if data
div.level-name
span.spr Course
span= data.courseNumber
span.spr , Level
span= data.levelNumber
span.spr :
span= data.levelName
else
div.level-name(data-i18n='teacher.not_applicable')
mixin inlineUserList(users)
if users
ul.inline-student-list.small
each student in users
li
//- a(href='TODO')
//- = student.broadName()
span.inline-student-name
= student.broadName()
mixin addStudentsButton
.add-students.text-center
a.add-students-btn.btn.btn-lg.btn-primary(data-classroom-id=view.classroom.id)
span(data-i18n='teacher.add_students_manually')
mixin studentsTab
#students-tab
+bulkAssignControls
table.students-table
thead
th.checkbox-col.select-all
span Select All
.checkbox-flat
input(type='checkbox' id='checkbox-all-students')
label.checkmark(for='checkbox-all-students')
th
+sortButtons
tbody
each student in state.get('students').models
+studentRow(student)
mixin sortButtons
.sort-buttons.small
span(data-i18n='teacher.sort_by')
span.spr :
button.sort-button.sort-by-name(data-i18n='general.name', value='name')
button.sort-button.sort-by-progress(data-i18n='teacher.progress', value='progress')
mixin studentRow(student)
tr.student-row.alternating-background
td.checkbox-col.student-checkbox
.checkbox-flat
input(type='checkbox' id='checkbox-student-' + student.id, data-student-id=student.id)
label.checkmark(for='checkbox-student-' + student.id)
td.student-info-col
.student-info
if student.get('deleted')
em (deleted)
div.student-name= student.broadName()
div.student-email.small-details= student.get('email')
td.hidden
a.edit-student-button(data-student-id=student.id)
span.glyphicon.glyphicon-edit
span(data-i18n='teacher.edit')
td.latest-level-col.small
div
i
span(data-i18n='teacher.latest_completed')
span :
div
+longLevelName(student.latestCompleteLevel)
td
if state.get('progressData')
each trimCourse, index in view.classroom.get('courses')
- var course = view.courses.get(trimCourse._id);
- var instance = view.courseInstances.findWhere({ courseID: course.id, classroomID: classroom.id })
if instance && instance.hasMember(student)
- var progress = state.get('progressData').get({ classroom: view.classroom, course: course, user: student })
- var levelsTotal = trimCourse.levels.length
//- - var level = ???
+studentCourseProgressDot(progress, levelsTotal, level, 'CS' + (index+1))
unless student.isEnrolled()
+enrollStudentButton(student)
//- td
//- span.view-class-arrow.glyphicon.glyphicon-chevron-right
td
.pull-right
a.edit-student-link.small.center-block.text-center.m-r-2(data-student-id=student.id)
div.glyphicon.glyphicon-edit
div(data-i18n='teacher.edit')
a.remove-student-link.small.center-block.text-center.m-r-2(data-student-id=student.id)
div.glyphicon.glyphicon-remove
div(data-i18n='teacher.remove')
mixin enrollStudentButton(student)
a.enroll-student-button.btn.btn-lg.btn-primary(data-classroom-id=view.classroom.id data-user-id=student.id)
span(data-i18n='teacher.enroll_student')
mixin courseProgressTab
#course-progress-tab.m-t-3
if view.courses
.text-center
span(data-i18n='teacher.select_course')
span.spr :
select.course-select
each trimCourse in view.classroom.get('courses')
- var course = view.courses.get(trimCourse._id);
option(value=course.id selected=(course===state.get('selectedCourse')))
= course.get('name')
if state.get('progressData')
.render-on-course-sync
+courseOverview
.student-levels-table
+sortButtons
each student in state.get('students').models
if _.contains(state.get('selectedCourse').members, student.id)
+studentLevelsRow(student)
//- TODO: If any students aren't assigned the course
.unassigned-students.render-on-course-sync
if state.get('selectedCourse') && state.get('selectedCourse').members.length < state.get('students').length
h2
span(data-i18n='TODO')
| Students who have not been assigned
|
span= state.get('selectedCourse').get('name')
for student in state.get('students').models
unless _.contains(state.get('selectedCourse').members, student.id)
.row.unassigned-student-row.alternating-background
.student-name.col-sm-3
= student.broadName()
.student-email.small-details.col-sm-3
= student.get('email')
.col-sm-4
.latest-completed.truncate.small
i.m-r-1
span(data-i18n='TODO')
| Latest completed
| :
+longLevelName(student.latestCompleteLevel)
.col-sm-2
if student.isEnrolled()
.assign-student-button.btn.btn-md.btn-navy.pull-right(data-user-id=student.id data-course-id=state.get('selectedCourse').id)
span(data-i18n='TODO')
| Assign Course
else
.enroll-student-button.btn.btn-md.btn-navy.pull-right(data-user-id=student.id)
span(data-i18n='TODO')
| Enroll Student
mixin courseOverview
- var course = state.get('selectedCourse')
- var levels = view.classroom.getLevels({courseID: course.id, withoutLadderLevels: true}).models
.course-overview-row
.course-title.student-name
span= course.get('name')
span :
span(data-i18n='teacher.course_overview')
.course-overview-progress
each level, index in levels
- var progress = state.get('progressData').get({ classroom: view.classroom, course: course, level: level })
+allStudentsLevelProgressDot(progress, level, index+1)
mixin studentLevelsRow(student)
.student-levels-row.alternating-background
div.student-info
div.student-name= student.broadName()
div.student-email.small-details= student.get('email')
div.student-levels-progress
- var course = state.get('selectedCourse')
- var levels = view.classroom.getLevels({courseID: course.id, withoutLadderLevels: true}).models
each level, index in levels
- var progress = state.get('progressData').get({ classroom: view.classroom, course: course, level: level, user: student })
+studentLevelProgressDot(progress, level, index+1)
mixin studentCourseProgressDot(progress, levelsTotal, level, label)
//- TODO: Refactor with TeacherClassesView jade
//- TODO: Give classes abbreviations instead of using index?
- dotClass = progress.completed ? 'forest' : (progress.started ? 'gold' : '');
- _.assign(progress, { levelsTotal: levelsTotal })
.progress-dot(class=dotClass, data-html='true', data-title=view.singleStudentCourseProgressDotTemplate(progress))
+progressDotLabel(label)
mixin allStudentsLevelProgressDot(progress, level, levelNumber)
- dotClass = progress.completed ? 'forest' : (progress.started ? 'gold' : '');
- levelName = level.get('name')
- context = _.merge(progress, { levelName: levelName, levelNumber: levelNumber, numStudents: view.students.length })
.progress-dot.level-progress-dot(class=dotClass, data-html='true', data-title=view.allStudentsLevelProgressDotTemplate(context))
+progressDotLabel(levelNumber)
mixin studentLevelProgressDot(progress, level, levelNumber)
//- TODO: Refactor with TeacherClassesView jade
- dotClass = progress.completed ? 'forest' : (progress.started ? 'gold' : '');
- levelName = level.get('name')
- context = _.merge(progress, { levelName: levelName, levelNumber: levelNumber })
.progress-dot.level-progress-dot(class=dotClass, data-html='true', data-title=view.singleStudentLevelProgressDotTemplate(context))
+progressDotLabel(levelNumber)
mixin progressDotLabel(label)
.dot-label.text-center
.dot-label-inner
= label
mixin copyCodes
div.copy-button-group.form-inline.m-b-3
.form-group
input.text-h4.semibold#join-code-input(value=state.get('classCode'))
button#copy-code-btn.form-control.btn.btn-lg.btn-forest
span(data-i18n='teacher.copy_class_code')
div.text-center.small(data-i18n='teacher.class_code_blurb')
div.copy-button-group.form-inline.m-b-3
.form-group
input.form-control.text-h4.semibold#join-url-input(value=state.get('joinURL'))
button#copy-url-btn.form-control.btn.btn-lg.btn-forest
span(data-i18n='teacher.copy_class_url')
div.text-center.small(data-i18n='teacher.class_join_url_blurb')
mixin bulkAssignControls
.bulk-assign-controls.form-inline
.no-students-selected.small-details(class=state.get('errors').assigningToNobody ? 'visible' : '')
span(data-i18n='teacher.no_students_selected')
.cant-assign-to-unenrolled.small-details(class=state.get('errors').assigningToUnenrolled ? 'visible' : '')
span(data-i18n='teacher.cant_assign_to_unenrolled')
span.small
span(data-i18n='teacher.bulk_assign')
span :
select.bulk-course-select.form-control
each trimCourse in _.rest(view.classroom.get('courses'))
- var course = view.courses.get(trimCourse._id)
option(value=course.id selected=(course===state.get('selectedCourse')))
= course.get('name')
button.btn.btn-primary-alt.assign-to-selected-students
span(data-i18n='teacher.assign_to_selected_students')
button.btn.btn-primary-alt.enroll-selected-students
span(data-i18n='teacher.enroll_selected_students')
mixin enrollmentStatusTab
form.form-inline.text-center.m-t-3
#search-form-group.form-group
label(for="student-search") Search for student:
input#student-search.form-control.m-l-1(type="search")
span.glyphicon.glyphicon-search.form-control-feedback
table.table#enrollment-status-table.table-condensed
thead
//th.checkbox-col.select-all
.checkbox-flat
input(type='checkbox' id='checkbox-all-students')
label.checkmark(for='checkbox-all-students')
th
.sort-buttons.small
span(data-i18n='teacher.sort_by')
span.spr :
button.sort-button.sort-by-name(data-i18n='general.name', value='name')
button.sort-button.sort-by-status(data-i18n='user.status', value='status')
tbody
- var searchTerm = view.state.get('searchTerm');
each student in state.get('students').search(searchTerm)
- var status = student.prepaidStatus()
tr.student-row.alternating-background
//td.checkbox-col.student-checkbox
.checkbox-flat
input(type='checkbox' id='checkbox-student-' + student.id, data-student-id=student.id)
label.checkmark(for='checkbox-student-' + student.id)
td.student-info-col
.student-info
div.student-name= student.broadName()
div.student-email.small-details= student.get('email')
td.status-col
span(data-i18n='user.status')
span.spr :
strong(class= status === 'expired' ? 'text-danger' : '')= view.studentStatusString(student)
td.enroll-col
if status !== 'enrolled'
button.enroll-student-button.btn.btn-navy(data-i18n="teacher.enroll_student", data-user-id=student.id)
td.revoke-col
if status === 'enrolled'
button.revoke-student-button.btn.btn-burgandy-alt(data-i18n="teacher.revoke_enrollment", data-user-id=student.id)