Add classroom name, description, and language editing, and classroom language infrastructure

This commit is contained in:
Scott Erickson 2015-11-17 16:09:29 -08:00
parent 08c7ad71a5
commit 6a54c7cf54
11 changed files with 114 additions and 60 deletions

View file

@ -8,6 +8,8 @@ _.extend ClassroomSchema.properties,
ownerID: c.objectId()
description: {type: 'string'}
code: c.shortString(title: "Unique code to redeem")
aceConfig:
language: {type: 'string', 'enum': ['python', 'javascript']}
c.extendBasicProperties ClassroomSchema, 'Classroom'

View file

@ -4,6 +4,11 @@
img.media-object
width: 300px
.edit-classroom-small
cursor: pointer
&:hover
color: grey
#fixed-area
position: fixed
bottom: 0

View file

@ -0,0 +1,24 @@
extends /templates/core/modal-base
block modal-header-content
button.close(data-dismiss='modal')
span ×
h3.modal-title(data-i18n="courses.edit_settings1")
block modal-body-content
.form
.form-group
label(data-i18n="courses.title")
input.form-control.settings-name-input(type='text', value="#{view.classroom.get('name') || ''}")
.form-group
label(data-i18n="courses.description")
textarea.form-control.settings-description-input(rows=2)= view.classroom.get('description')
.form-group
label(data-i18n="choose_hero.programming_language")
select.form-control#programming-language-select
- var aceConfig = view.classroom.get('aceConfig') || {};
option(value="python", selected=aceConfig.language==='python') Python
option(value="javascript", selected=aceConfig.language==='javascript') JavaScript
block modal-footer-content
button#save-settings-btn.btn(data-i18n="common.save_changes")

View file

@ -53,11 +53,6 @@ block content
if courseInstance.get('description')
each line in courseInstance.get('description').split('\n')
div= line
// TODO: migrate these settings to classrooms
//if adminMode && courseInstance
// +settings-dialog
// p
// button.btn.btn-xs(data-toggle='modal', data-target='#settingsModal', data-i18n="courses.edit_settings")
div.well.well-sm(role='tabpanel')
ul.nav.nav-pills(role='tablist')
@ -292,27 +287,3 @@ mixin levels-tab
if levelConceptMap[levelID][concept]
span.spr.progress-level-cell.progress-level-cell-not-started(data-i18n="concepts." + concept)
mixin settings-dialog
.modal#settingsModal
.modal-dialog
.modal-header
button.close(data-dismiss='modal')
span ×
h3.modal-title(data-i18n="courses.edit_settings1")
.modal-body
.form
.form-group
label(data-i18n="courses.title")
input.form-control.settings-name-input(type='text', value="#{courseInstance.get('name') || ''}")
.form-group
label(data-i18n="courses.description")
textarea.form-control.settings-description-input(rows=2)= courseInstance.get('description')
.form-group
label(data-i18n="choose_hero.programming_language")
select.form-control#programming-language-select
- var aceConfig = view.courseInstance.get('aceConfig') || {};
option(value="python", selected=aceConfig.language==='python') Python
option(value="javascript", selected=aceConfig.language==='javascript') JavaScript
.modal-footer
button.btn.btn-save-settings(data-i18n="common.save_changes")

View file

@ -102,7 +102,15 @@ block content
a.btn.btn-default.btn-xs(href="/courses/purchase") Add
for classroom in view.classrooms.models
h2= classroom.get('name')
h2
span.spr= classroom.get('name')
- var language = (classroom.get('aceConfig') || {}).language || 'python';
if language === 'python'
img(src="/images/common/code_languages/python_icon.png")
if language === 'javascript'
img(src="/images/common/code_languages/javascript_icon.png")
small.spl.edit-classroom-small(data-classroom-id=classroom.id)
span.glyphicon.glyphicon-pencil
- var courseInstances = view.courseInstances.where({classroomID: classroom.id})
@ -111,6 +119,9 @@ block content
.progress-bar(style="width: 100%")
else
- var description = classroom.get('description');
if description
p= description
table.table
tr
th Student

View file

@ -0,0 +1,26 @@
ModalView = require 'views/core/ModalView'
template = require 'templates/courses/classroom-settings-modal'
module.exports = class AddLevelSystemModal extends ModalView
id: 'classroom-settings-modal'
template: template
events:
'click #save-settings-btn': 'onClickSaveSettingsButton'
initialize: (options) ->
@classroom = options.classroom
onClickSaveSettingsButton: ->
return unless @classroom
if name = $('.settings-name-input').val()
@classroom.set('name', name)
description = $('.settings-description-input').val()
@classroom.set('description', description)
@classroom.set('aceConfig', {
language: @$('#programming-language-select').val()
})
@classroom.patch()
@hide()

View file

@ -19,7 +19,6 @@ module.exports = class CourseDetailsView extends RootView
events:
'change .progress-expand-checkbox': 'onCheckExpandedProgress'
'click .btn-play-level': 'onClickPlayLevel'
'click .btn-save-settings': 'onClickSaveSettings'
'click .btn-select-instance': 'onClickSelectInstance'
'click .progress-member-header': 'onClickMemberHeader'
'click .progress-header': 'onClickProgressHeader'
@ -228,19 +227,6 @@ module.exports = class CourseDetailsView extends RootView
getLevelURL: (levelSlug) ->
"/play/level/#{levelSlug}?course=#{@courseID}&course-instance=#{@courseInstanceID}"
onClickSaveSettings: (e) ->
return unless @courseInstance
if name = $('.settings-name-input').val()
@courseInstance.set('name', name)
description = $('.settings-description-input').val()
console.log 'onClickSaveSettings', description
@courseInstance.set('description', description)
@courseInstance.set('aceConfig', {
language: @$('#programming-language-select').val()
})
@courseInstance.patch()
$('#settingsModal').modal('hide')
onClickSelectInstance: (e) ->
courseInstanceID = $('.select-instance').val()
@noCourseInstanceSelected = false

View file

@ -11,6 +11,7 @@ RootView = require 'views/core/RootView'
template = require 'templates/courses/teacher-courses-view'
utils = require 'core/utils'
InviteToClassroomModal = require 'views/courses/InviteToClassroomModal'
ClassroomSettingsModal = require 'views/courses/ClassroomSettingsModal'
module.exports = class TeacherCoursesView extends RootView
id: 'teacher-courses-view'
@ -22,6 +23,7 @@ module.exports = class TeacherCoursesView extends RootView
'click .course-instance-membership-checkbox': 'onClickCourseInstanceMembershipCheckbox'
'click #save-changes-btn': 'onClickSaveChangesButton'
'click #manage-tab-link': 'onClickManageTabLink'
'click .edit-classroom-small': 'onClickEditClassroomSmall'
constructor: (options) ->
super(options)
@ -71,6 +73,13 @@ module.exports = class TeacherCoursesView extends RootView
@renderSelectors('#manage-tab-pane')
@$('#manage-tab-pane').toggleClass('active', isActive)
onClickEditClassroomSmall: (e) ->
classroomID = $(e.target).closest('small').data('classroom-id')
classroom = @classrooms.get(classroomID)
modal = new ClassroomSettingsModal({classroom: classroom})
@openModalView(modal)
@listenToOnce modal, 'hide', @renderManageTab
onClickAddStudentsButton: (e) ->
classroomID = $(e.target).data('classroom-id')
classroom = @classrooms.get(classroomID)

View file

@ -11,6 +11,7 @@ ClassroomSchema.statics.privateProperties = []
ClassroomSchema.statics.editableProperties = [
'description'
'name'
'aceConfig'
]
ClassroomSchema.statics.generateNewCode = (done) ->

View file

@ -11,6 +11,7 @@ log = require 'winston'
Campaign = require '../campaigns/Campaign'
Course = require '../courses/Course'
CourseInstance = require '../courses/CourseInstance'
Classroom = require '../classrooms/Classroom'
LevelHandler = class LevelHandler extends Handler
modelClass: Level
@ -129,10 +130,16 @@ LevelHandler = class LevelHandler extends Handler
courses = _.filter(courses, (course) -> course.get('campaignID').toString() in campaignStrings)
courseStrings = (course.id.toString() for course in courses)
courseInstances = _.filter(courseInstances, (courseInstance) -> courseInstance.get('courseID').toString() in courseStrings)
aceConfigs = (ci.get('aceConfig') for ci in courseInstances)
classroomIDs = (courseInstance.get('classroomID') for courseInstance in courseInstances)
classroomIDs = _.filter _.uniq classroomIDs, false, (objectID='') -> objectID.toString()
if classroomIDs.length
Classroom.find({ _id: { $in: classroomIDs }}).exec (err, classrooms) =>
aceConfigs = (c.get('aceConfig') for c in classrooms)
aceConfig = _.filter(aceConfigs)[0] or {}
req.codeLanguage = aceConfig.language
@createAndSaveNewSession(sessionQuery, req, res)
else
@createAndSaveNewSession(sessionQuery, req, res)
else
return @sendPaymentRequiredError(res, 'You must be in a course which includes this level to play it')

View file

@ -71,12 +71,23 @@ describe 'GET /db/level/<id>/session', ->
loginJoe (joe) ->
classroom = new Classroom({
name: 'Test Classroom'
members: [ joe.get('_id') ]
aceConfig: { language: 'javascript' }
})
classroom.save (err, classroom) ->
expect(err).toBeNull()
courseInstance = new CourseInstance({
name: 'Course Instance'
members: [
joe.get('_id')
]
courseID: ObjectId(course.id)
classroomID: ObjectId(classroom.id)
})
courseInstance.save (err) ->
@ -89,8 +100,9 @@ describe 'GET /db/level/<id>/session', ->
url = getURL("/db/level/#{levelID}/session")
request.get { uri: url }, (err, res, body) ->
request.get { uri: url, json: true }, (err, res, body) ->
expect(res.statusCode).toBe(200)
expect(body.codeLanguage).toBe('javascript')
done()
it 'does not create a new session if the user is not in a course with that level', (done) ->