mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-01 03:16:56 -05:00
8dbc86ca04
Hide TeachersContactModal after sending message Fix GET /db/level/:handle/session, more extensively test Fix EnrollmentView number of students input to stop losing focus on input Fix EnrollmentsView syntax Fix ActivateLicensesModal "Get Enrollments" button when already in the enrollments page Update EnrollmentsView with new credit numbers when ActivateLicensesModal closes Hide search box in TeacherClassView "Enrollment Status" tab Tweak EnrollmentsView styling Fix EnrollmentsView tests Fix AnalyticsView Make EnrollmentsView more explicitly handle undefined and empty array prepaid groups Remove log CoursesView handles JoinClassModal cancel Re-enable EditStudentModal set password button when the form changes Fix course instance tests, next level endpoint bug Fix EditStudentModal tests
424 lines
17 KiB
Text
424 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
|
|
// TODO: Have search input in all tabs
|
|
|
|
//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.m-t-3
|
|
thead
|
|
// Checkbox code works, but don't need it yet.
|
|
//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)
|