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)