mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 09:35:39 -05:00
Add classroom name, description, and language editing, and classroom language infrastructure
This commit is contained in:
parent
08c7ad71a5
commit
6a54c7cf54
11 changed files with 114 additions and 60 deletions
|
@ -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'
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
img.media-object
|
||||
width: 300px
|
||||
|
||||
.edit-classroom-small
|
||||
cursor: pointer
|
||||
&:hover
|
||||
color: grey
|
||||
|
||||
#fixed-area
|
||||
position: fixed
|
||||
|
|
24
app/templates/courses/classroom-settings-modal.jade
Normal file
24
app/templates/courses/classroom-settings-modal.jade
Normal 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")
|
|
@ -53,12 +53,7 @@ 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')
|
||||
if adminMode
|
||||
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
26
app/views/courses/ClassroomSettingsModal.coffee
Normal file
26
app/views/courses/ClassroomSettingsModal.coffee
Normal 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()
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -11,6 +11,7 @@ ClassroomSchema.statics.privateProperties = []
|
|||
ClassroomSchema.statics.editableProperties = [
|
||||
'description'
|
||||
'name'
|
||||
'aceConfig'
|
||||
]
|
||||
|
||||
ClassroomSchema.statics.generateNewCode = (done) ->
|
||||
|
|
|
@ -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)
|
||||
aceConfig = _.filter(aceConfigs)[0] or {}
|
||||
req.codeLanguage = aceConfig.language
|
||||
@createAndSaveNewSession(sessionQuery, req, res)
|
||||
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')
|
||||
|
||||
|
|
|
@ -68,29 +68,41 @@ describe 'GET /db/level/<id>/session', ->
|
|||
course.save (err) ->
|
||||
|
||||
expect(err).toBeNull()
|
||||
|
||||
|
||||
loginJoe (joe) ->
|
||||
|
||||
courseInstance = new CourseInstance({
|
||||
name: 'Course Instance'
|
||||
members: [
|
||||
joe.get('_id')
|
||||
]
|
||||
courseID: ObjectId(course.id)
|
||||
classroom = new Classroom({
|
||||
name: 'Test Classroom'
|
||||
members: [ joe.get('_id') ]
|
||||
aceConfig: { language: 'javascript' }
|
||||
})
|
||||
|
||||
courseInstance.save (err) ->
|
||||
|
||||
classroom.save (err, classroom) ->
|
||||
|
||||
expect(err).toBeNull()
|
||||
done()
|
||||
|
||||
courseInstance = new CourseInstance({
|
||||
name: 'Course Instance'
|
||||
members: [
|
||||
joe.get('_id')
|
||||
]
|
||||
courseID: ObjectId(course.id)
|
||||
classroomID: ObjectId(classroom.id)
|
||||
})
|
||||
|
||||
courseInstance.save (err) ->
|
||||
|
||||
expect(err).toBeNull()
|
||||
done()
|
||||
|
||||
it 'creates a new session if the user is in a course with that level', (done) ->
|
||||
loginJoe (joe) ->
|
||||
|
||||
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) ->
|
||||
|
|
Loading…
Reference in a new issue