mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-02 20:07:25 -05:00
Add courses tab to teacher courses page
This commit is contained in:
parent
7daff0861f
commit
b0a0530d3c
3 changed files with 145 additions and 79 deletions
|
@ -1,6 +1,9 @@
|
||||||
#teacher-courses-view
|
#teacher-courses-view
|
||||||
margin-bottom: 50px
|
margin-bottom: 50px
|
||||||
|
|
||||||
|
img.media-object
|
||||||
|
width: 300px
|
||||||
|
|
||||||
#fixed-area
|
#fixed-area
|
||||||
position: fixed
|
position: fixed
|
||||||
bottom: 0
|
bottom: 0
|
||||||
|
|
|
@ -4,89 +4,147 @@ block content
|
||||||
|
|
||||||
span *UNDER CONSTRUCTION, please send feedback to
|
span *UNDER CONSTRUCTION, please send feedback to
|
||||||
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
|
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
|
||||||
|
|
||||||
hr
|
hr
|
||||||
|
|
||||||
p Create a class and add students to it.
|
ul.nav.nav-tabs(role='tablist')
|
||||||
|
li.active(role='presentation')
|
||||||
|
a(href="#courses-tab-pane" aria-controls="courses" role="tab" data-toggle="tab") Courses
|
||||||
|
li(role='presentation')
|
||||||
|
a(href="#manage-tab-pane" aria-controls="manage" role="tab" data-toggle="tab") Manage
|
||||||
|
|
||||||
- var totalRedeemers = view.prepaids.totalRedeemers();
|
.tab-content
|
||||||
- var totalMaxRedeemers = view.prepaids.totalMaxRedeemers();
|
#courses-tab-pane.tab-pane.active.well
|
||||||
|
h3 Your Courses
|
||||||
|
- var courseInstances = view.courseInstances.sliceWithMembers();
|
||||||
|
if !_.size(courseInstances)
|
||||||
|
.alert.alert-info
|
||||||
|
span.spr You currently have no students assigned to courses.
|
||||||
|
a#manage-tab-link Go to the manage tab to get set up.
|
||||||
|
|
||||||
.text-right
|
else
|
||||||
span.spr Available paid seats: #{totalRedeemers}/#{totalMaxRedeemers}
|
table.table
|
||||||
a.btn.btn-default.btn-xs(href="/courses/purchase") Add
|
tr
|
||||||
|
th Class
|
||||||
for classroom in view.classrooms.models
|
th Course
|
||||||
h2= classroom.get('name')
|
th Size
|
||||||
|
th
|
||||||
- var courseInstances = view.courseInstances.where({classroomID: classroom.id})
|
|
||||||
|
|
||||||
if classroom.saving
|
|
||||||
.progress
|
|
||||||
.progress-bar(style="width: 100%")
|
|
||||||
|
|
||||||
table.table
|
|
||||||
tr
|
|
||||||
th Student
|
|
||||||
for courseInstance in courseInstances
|
|
||||||
th
|
|
||||||
if courseInstance.course
|
|
||||||
| #{courseInstance.course.get('name')}
|
|
||||||
|
|
||||||
if !_.size(classroom.get('members'))
|
|
||||||
tr
|
|
||||||
td(colspan=1+view.courses.size())
|
|
||||||
em No students in this class yet.
|
|
||||||
|
|
||||||
for member in classroom.get('members') || []
|
|
||||||
- var user = view.members.get(member);
|
|
||||||
if !user
|
|
||||||
- continue;
|
|
||||||
tr
|
|
||||||
td= user.get('name')
|
|
||||||
for courseInstance in courseInstances
|
for courseInstance in courseInstances
|
||||||
td
|
- console.log('course instance!', courseInstance)
|
||||||
if _.contains(courseInstance.get('members'), user.id)
|
tr
|
||||||
span.glyphicon.glyphicon-ok
|
td
|
||||||
|
- var classroom = view.classrooms.get(courseInstance.get('classroomID'));
|
||||||
|
if classroom
|
||||||
|
| #{classroom.get('name')}
|
||||||
|
td
|
||||||
|
if courseInstance.course
|
||||||
|
| #{courseInstance.course.get('name')}
|
||||||
|
td= _.size(courseInstance.get('members'))
|
||||||
|
td
|
||||||
|
a.btn.btn-primary.btn-sm(href='/courses/#{courseInstance.get("courseID")}/#{courseInstance.id}') Enter
|
||||||
|
|
||||||
|
h3 Available Courses
|
||||||
|
|
||||||
|
for course in view.courses.models
|
||||||
|
.media
|
||||||
|
.pull-left
|
||||||
|
img.media-object(src=course.get('screenshot'))
|
||||||
|
.media-body
|
||||||
|
h3.media-heading
|
||||||
|
span.spr= course.get('name')
|
||||||
|
if course.get('free')
|
||||||
|
em (free!)
|
||||||
|
p= course.get('description')
|
||||||
|
p
|
||||||
|
strong.spr Concepts:
|
||||||
|
span= (course.get('concepts') || []).join(', ')
|
||||||
|
p
|
||||||
|
strong.spr Length:
|
||||||
|
span #{course.get('duration') || 0} hours
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#manage-tab-pane.tab-pane.well
|
||||||
|
|
||||||
|
p Create a class and add students to it.
|
||||||
|
|
||||||
|
- var totalRedeemers = view.prepaids.totalRedeemers();
|
||||||
|
- var totalMaxRedeemers = view.prepaids.totalMaxRedeemers();
|
||||||
|
|
||||||
|
.text-right
|
||||||
|
span.spr Available paid seats: #{totalRedeemers}/#{totalMaxRedeemers}
|
||||||
|
a.btn.btn-default.btn-xs(href="/courses/purchase") Add
|
||||||
|
|
||||||
|
for classroom in view.classrooms.models
|
||||||
|
h2= classroom.get('name')
|
||||||
|
|
||||||
|
- var courseInstances = view.courseInstances.where({classroomID: classroom.id})
|
||||||
|
|
||||||
|
if classroom.saving
|
||||||
|
.progress
|
||||||
|
.progress-bar(style="width: 100%")
|
||||||
|
|
||||||
|
table.table
|
||||||
|
tr
|
||||||
|
th Student
|
||||||
|
for courseInstance in courseInstances
|
||||||
|
th
|
||||||
|
if courseInstance.course
|
||||||
|
| #{courseInstance.course.get('name')}
|
||||||
|
|
||||||
|
if !_.size(classroom.get('members'))
|
||||||
|
tr
|
||||||
|
td(colspan=1+view.courses.size())
|
||||||
|
em No students in this class yet.
|
||||||
|
|
||||||
|
for member in classroom.get('members') || []
|
||||||
|
- var user = view.members.get(member);
|
||||||
|
if !user
|
||||||
|
- continue;
|
||||||
|
tr
|
||||||
|
td= user.get('name')
|
||||||
|
for courseInstance in courseInstances
|
||||||
|
td
|
||||||
|
if _.contains(courseInstance.get('members'), user.id)
|
||||||
|
span.glyphicon.glyphicon-ok
|
||||||
|
else
|
||||||
|
input.course-instance-membership-checkbox(
|
||||||
|
type='checkbox'
|
||||||
|
data-course-instance-id=courseInstance.id
|
||||||
|
data-user-id=user.id
|
||||||
|
)
|
||||||
|
|
||||||
|
button.add-students-btn.btn.btn-sm(data-classroom-id=classroom.id) Add Students
|
||||||
|
|
||||||
|
hr
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-sm-3.col-sm-offset-3
|
||||||
|
button#create-new-class-btn.btn.btn-default.btn-block Create New Class
|
||||||
|
.col-sm-3
|
||||||
|
input#new-classroom-name-input.form-control(placeholder='new class name')
|
||||||
|
|
||||||
|
#fixed-area
|
||||||
|
.container
|
||||||
|
.row.well
|
||||||
|
if view.state === 'saving-changes'
|
||||||
|
p Saving changes
|
||||||
|
- var total = view.membershipAdditions.originalSize + view.usersToRedeem.originalSize;
|
||||||
|
- var left = view.membershipAdditions.size() + view.usersToRedeem.size();
|
||||||
|
- var pct = Math.max(10, (100 * (total - left) / total)).toFixed(1) + '%';
|
||||||
|
.progress.progress-striped.active
|
||||||
|
.progress-bar(style="width: #{pct}")
|
||||||
|
else
|
||||||
|
- var seatsLeft = totalMaxRedeemers - totalRedeemers - view.usersToRedeem.size();
|
||||||
|
if seatsLeft < 0
|
||||||
|
.alert.alert-danger
|
||||||
|
span.spr You do not have enough seats to accommodate all students you have selected.
|
||||||
|
a(href="/courses/purchase") Buy more seats.
|
||||||
else
|
else
|
||||||
input.course-instance-membership-checkbox(
|
.col-sm-2
|
||||||
type='checkbox'
|
button#save-changes-btn.btn.btn-primary.btn-block(disabled=!view.numCourseInstancesToAddTo) Save Changes
|
||||||
data-course-instance-id=courseInstance.id
|
.col-sm-5
|
||||||
data-user-id=user.id
|
| Students to add to courses: #{view.numCourseInstancesToAddTo || 0}
|
||||||
)
|
.col-sm-5
|
||||||
|
| Seats to expend: #{view.usersToRedeem.size()} (will have #{seatsLeft} seats left)
|
||||||
button.add-students-btn.btn.btn-sm(data-classroom-id=classroom.id) Add Students
|
|
||||||
|
|
||||||
hr
|
|
||||||
|
|
||||||
.row
|
|
||||||
.col-sm-3.col-sm-offset-3
|
|
||||||
button#create-new-class-btn.btn.btn-default.btn-block Create New Class
|
|
||||||
.col-sm-3
|
|
||||||
input#new-classroom-name-input.form-control(placeholder='new class name')
|
|
||||||
|
|
||||||
#fixed-area
|
|
||||||
.container
|
|
||||||
.row.well
|
|
||||||
if view.state === 'saving-changes'
|
|
||||||
p Saving changes
|
|
||||||
- var total = view.membershipAdditions.originalSize + view.usersToRedeem.originalSize;
|
|
||||||
- var left = view.membershipAdditions.size() + view.usersToRedeem.size();
|
|
||||||
- var pct = Math.max(10, (100 * (total - left) / total)).toFixed(1) + '%';
|
|
||||||
.progress.progress-striped.active
|
|
||||||
.progress-bar(style="width: #{pct}")
|
|
||||||
else
|
|
||||||
- var seatsLeft = totalMaxRedeemers - totalRedeemers - view.usersToRedeem.size();
|
|
||||||
if seatsLeft < 0
|
|
||||||
.alert.alert-danger
|
|
||||||
span.spr You do not have enough seats to accommodate all students you have selected.
|
|
||||||
a(href="/courses/purchase") Buy more seats.
|
|
||||||
else
|
|
||||||
.col-sm-2
|
|
||||||
button#save-changes-btn.btn.btn-primary.btn-block(disabled=!view.numCourseInstancesToAddTo) Save Changes
|
|
||||||
.col-sm-5
|
|
||||||
| Students to add to courses: #{view.numCourseInstancesToAddTo || 0}
|
|
||||||
.col-sm-5
|
|
||||||
| Seats to expend: #{view.usersToRedeem.size()} (will have #{seatsLeft} seats left)
|
|
||||||
|
|
||||||
block footer
|
block footer
|
|
@ -21,6 +21,7 @@ module.exports = class TeacherCoursesView extends RootView
|
||||||
'click .add-students-btn': 'onClickAddStudentsButton'
|
'click .add-students-btn': 'onClickAddStudentsButton'
|
||||||
'click .course-instance-membership-checkbox': 'onClickCourseInstanceMembershipCheckbox'
|
'click .course-instance-membership-checkbox': 'onClickCourseInstanceMembershipCheckbox'
|
||||||
'click #save-changes-btn': 'onClickSaveChangesButton'
|
'click #save-changes-btn': 'onClickSaveChangesButton'
|
||||||
|
'click #manage-tab-link': 'onClickManageTabLink'
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super(options)
|
super(options)
|
||||||
|
@ -32,12 +33,13 @@ module.exports = class TeacherCoursesView extends RootView
|
||||||
@supermodel.loadCollection(@classrooms, 'classrooms', {data: {ownerID: me.id}})
|
@supermodel.loadCollection(@classrooms, 'classrooms', {data: {ownerID: me.id}})
|
||||||
@courseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance })
|
@courseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance })
|
||||||
@courseInstances.comparator = 'courseID'
|
@courseInstances.comparator = 'courseID'
|
||||||
|
@courseInstances.sliceWithMembers = -> return @filter (courseInstance) -> _.size(courseInstance.get('members'))
|
||||||
@supermodel.loadCollection(@courseInstances, 'course_instances', {data: {ownerID: me.id}})
|
@supermodel.loadCollection(@courseInstances, 'course_instances', {data: {ownerID: me.id}})
|
||||||
@members = new CocoCollection([], { model: User })
|
@members = new CocoCollection([], { model: User })
|
||||||
@prepaids = new CocoCollection([], { url: "/db/prepaid", model: Prepaid })
|
@prepaids = new CocoCollection([], { url: "/db/prepaid", model: Prepaid })
|
||||||
sum = (numbers) -> _.reduce(numbers, (a, b) -> a + b)
|
sum = (numbers) -> _.reduce(numbers, (a, b) -> a + b)
|
||||||
@prepaids.totalMaxRedeemers = -> sum((prepaid.get('maxRedeemers') for prepaid in @models))
|
@prepaids.totalMaxRedeemers = -> sum((prepaid.get('maxRedeemers') for prepaid in @models)) or 0
|
||||||
@prepaids.totalRedeemers = -> sum((_.size(prepaid.get('redeemers')) for prepaid in @models))
|
@prepaids.totalRedeemers = -> sum((_.size(prepaid.get('redeemers')) for prepaid in @models)) or 0
|
||||||
@prepaids.comparator = '_id'
|
@prepaids.comparator = '_id'
|
||||||
@supermodel.loadCollection(@prepaids, 'prepaids', {data: {creator: me.id}})
|
@supermodel.loadCollection(@prepaids, 'prepaids', {data: {creator: me.id}})
|
||||||
@listenTo @members, 'sync', @render
|
@listenTo @members, 'sync', @render
|
||||||
|
@ -187,3 +189,6 @@ module.exports = class TeacherCoursesView extends RootView
|
||||||
@stateMessage = "#{jqxhr.status}: #{jqxhr.responseText}"
|
@stateMessage = "#{jqxhr.status}: #{jqxhr.responseText}"
|
||||||
@renderSelectors '#fixed-area'
|
@renderSelectors '#fixed-area'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onClickManageTabLink: ->
|
||||||
|
@$('.nav-tabs a[href="#manage-tab-pane"]').tab('show')
|
Loading…
Reference in a new issue