From 00ce8219390f08300e7f816d0bbddb6a7f1e202e Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Wed, 4 Nov 2015 16:54:13 -0800 Subject: [PATCH] Add InviteToClassroomModal, begin join class in StudentCoursesView --- .../courses/invite-to-classroom-modal.jade | 22 +++++++ .../courses/student-courses-view.jade | 34 ++++++---- .../courses/teacher-courses-view.jade | 28 +++++++- app/views/core/CocoView.coffee | 1 + .../courses/InviteToClassroomModal.coffee | 32 ++++++++++ app/views/courses/StudentCoursesView.coffee | 64 +++++++++---------- app/views/courses/TeacherCoursesView.coffee | 25 +++++++- server/classrooms/classroom_handler.coffee | 3 +- 8 files changed, 158 insertions(+), 51 deletions(-) create mode 100644 app/templates/courses/invite-to-classroom-modal.jade create mode 100644 app/views/courses/InviteToClassroomModal.coffee diff --git a/app/templates/courses/invite-to-classroom-modal.jade b/app/templates/courses/invite-to-classroom-modal.jade new file mode 100644 index 000000000..e98d34b85 --- /dev/null +++ b/app/templates/courses/invite-to-classroom-modal.jade @@ -0,0 +1,22 @@ +extends /templates/core/modal-base + +block modal-header-content + h2 Invite Students to Classroom + h3= view.classroom.get('name') + +block modal-body-content + p(data-i18n="courses.invite_students") + h3(data-i18n="courses.invite_link_header") + p(data-i18n="courses.invite_link_p_1") + .alert.alert-info + + strong= document.location.origin + "/courses/students?_cc=" + view.classroom.get('code') + p(data-i18n="courses.invite_link_p_2") + .form + .form-group + textarea#invite-emails-textarea.form-control + .help-block(data-i18n="courses.enter_emails") + .form-group + button#send-invites-btn.btn.btn-success(data-i18n="courses.send_invites") + #invite-emails-sending-alert.alert.alert-info.hide(data-i18n="common.sending") + #invite-emails-success-alert.alert.alert-success.hide(data-i18n="play_level.done") diff --git a/app/templates/courses/student-courses-view.jade b/app/templates/courses/student-courses-view.jade index f3b63a05e..1f0d83e77 100644 --- a/app/templates/courses/student-courses-view.jade +++ b/app/templates/courses/student-courses-view.jade @@ -4,19 +4,29 @@ block content p To join a class, ask your teacher for an unlock code. - .form-horizontal + #join-classroom-form.form-horizontal .form-group .col-sm-2 - button.btn.btn-default.btn-block Join Class + button#join-class-btn.btn.btn-default.btn-block(disabled=view.state==='enrolling') Join Class .col-sm-6 - input#classroom-code.form-control(placeholder='') - - .panel.panel-default - .panel-heading - .panel-title My Courses + input#classroom-code-input.form-control( + placeholder='', + value=view.classCode, + disabled=view.state==='enrolling') - .panel-body.row - .col-sm-3 Class 1 - .col-sm-3 Course 1 - .col-sm-6 - button.btn.btn-default.btn-sm Enter \ No newline at end of file + if view.state === 'enrolling' + .progress.progress-striped.active + .progress-bar(style="width: 100%") Joining class + + if view.state === 'unknown_error' + .alert.alert-danger= view.stateMessage + + .panel.panel-default + .panel-heading + .panel-title My Courses + + .panel-body.row + .col-sm-3 Class 1 + .col-sm-3 Course 1 + .col-sm-6 + button.btn.btn-default.btn-sm Enter \ No newline at end of file diff --git a/app/templates/courses/teacher-courses-view.jade b/app/templates/courses/teacher-courses-view.jade index 1fd23c7ac..afb007e32 100644 --- a/app/templates/courses/teacher-courses-view.jade +++ b/app/templates/courses/teacher-courses-view.jade @@ -7,4 +7,30 @@ block content hr - p Teacher courses view \ No newline at end of file + for classroom in view.classrooms.models + h2= classroom.get('name') + + if classroom.saving + .progress + .progress-bar(style="width: 100%") + + table.table + tr + th Student + for course in view.courses.models + th= course.get('name') + + if !_.size(classroom.get('members')) + tr + td(colspan=1+view.courses.size()) + em No students in this class yet. + + 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') \ No newline at end of file diff --git a/app/views/core/CocoView.coffee b/app/views/core/CocoView.coffee index 6d9021c6e..ea7d8c602 100644 --- a/app/views/core/CocoView.coffee +++ b/app/views/core/CocoView.coffee @@ -132,6 +132,7 @@ module.exports = class CocoView extends Backbone.View context.translate = $.i18n.t context.view = @ context._ = _ + context.document = document context afterRender: -> diff --git a/app/views/courses/InviteToClassroomModal.coffee b/app/views/courses/InviteToClassroomModal.coffee new file mode 100644 index 000000000..fae1a2556 --- /dev/null +++ b/app/views/courses/InviteToClassroomModal.coffee @@ -0,0 +1,32 @@ +ModalView = require 'views/core/ModalView' +template = require 'templates/courses/invite-to-classroom-modal' + +module.exports = class InviteToClassroomModal extends ModalView + id: 'invite-to-classroom-modal' + template: template + + events: + 'click #send-invites-btn': 'onClickSendInvitesButton' + + initialize: (options) -> + @classroom = options.classroom + + onClickSendInvitesButton: -> + emails = @$('#invite-emails-textarea').val() + emails = emails.split('\n') + emails = _.filter((_.string.trim(email) for email in emails)) + if not emails.length + return + url = @classroom.url() + '/invite-members' + @$('#send-invites-btn, #invite-emails-textarea').addClass('hide') + @$('#invite-emails-sending-alert').removeClass('hide') + + $.ajax({ + url: url + data: {emails: emails} + method: 'POST' + context: @ + success: -> + @$('#invite-emails-sending-alert').addClass('hide') + @$('#invite-emails-success-alert').removeClass('hide') + }) diff --git a/app/views/courses/StudentCoursesView.coffee b/app/views/courses/StudentCoursesView.coffee index ae40a120d..da19455c0 100644 --- a/app/views/courses/StudentCoursesView.coffee +++ b/app/views/courses/StudentCoursesView.coffee @@ -22,40 +22,36 @@ module.exports = class StudentCoursesView extends RootView @courseInstances = new CocoCollection([], { url: "/db/user/#{me.id}/course_instances", model: CourseInstance}) @supermodel.loadCollection(@courseInstances, 'course_instances') -# if classCode = utils.getQueryVariable('_cc', false) and not me.isAnonymous() -# @joinClass(classCode) -# -# onClickJoinClassButton: (e) -> -# return @openModalView new AuthModal() if me.isAnonymous() -# courseID = $(e.target).data('course-id') -# classCode = ($(".code-input[data-course-id=#{courseID}]").val() ? '').trim() -# @courseEnrollByModal(prepaidCode) -# -# joinClass: (prepaidCode) -> -# @state = 'enrolling-by-modal' -# @renderSelectors '.student-dialog-state-row' -# $.ajax({ -# method: 'POST' -# url: '/db/course_instance/-/redeem_prepaid' -# data: prepaidCode: prepaidCode -# context: @ -# success: -> -# $('.continue-dialog').modal('hide') -# @onRedeemPrepaidSuccess(arguments...) -# error: (jqxhr, textStatus, errorThrown) -> -# application.tracker?.trackEvent 'Failed to redeem course prepaid code by modal', status: textStatus -# @state = 'unknown_error' -# if jqxhr.status is 422 -# @stateMessage = 'Please enter a code.' -# else if jqxhr.status is 404 -# @stateMessage = 'Code not found.' -# else -# @stateMessage = "#{jqxhr.responseText}" -# @renderSelectors '.student-dialog-state-row' -# }) -# -# onRedeemPrepaidSuccess: (data, textStatus, jqxhr) -> -# prepaidID = data[0]?.prepaidID + if (@classCode = utils.getQueryVariable('_cc', false)) and not me.isAnonymous() + @joinClass() + + onClickJoinClassButton: (e) -> + return @openModalView new AuthModal() if me.isAnonymous() + @classCode = @$('#classroom-code-input').val() + @joinClass() + + joinClass: () -> + @state = 'enrolling' + @renderSelectors '#join-classroom-form' + $.ajax({ + method: 'POST' + url: '/db/classroom/-/members' + data: code: @classCode + context: @ + success: @onJoinClassroomSuccess + error: (jqxhr, textStatus, errorThrown) -> + application.tracker?.trackEvent 'Failed to join classroom with code', status: textStatus + @state = 'unknown_error' + if jqxhr.status is 422 + @stateMessage = 'Please enter a code.' + else if jqxhr.status is 404 + @stateMessage = 'Code not found.' + else + @stateMessage = "#{jqxhr.responseText}" + @renderSelectors '#join-classroom-form' + }) + + onJoinClassroomSuccess: (data, textStatus, jqxhr) -> # application.tracker?.trackEvent 'Redeemed course prepaid code', {prepaidCode: prepaidID} # me.fetch(cache: false).always => # if data?.length > 0 && data[0].courseID && data[0]._id diff --git a/app/views/courses/TeacherCoursesView.coffee b/app/views/courses/TeacherCoursesView.coffee index a0f06ab15..4c7aa7614 100644 --- a/app/views/courses/TeacherCoursesView.coffee +++ b/app/views/courses/TeacherCoursesView.coffee @@ -7,12 +7,15 @@ CourseInstance = require 'models/CourseInstance' RootView = require 'views/core/RootView' template = require 'templates/courses/teacher-courses-view' utils = require 'core/utils' - -# +InviteToClassroomModal = require 'views/courses/InviteToClassroomModal' module.exports = class TeacherCoursesView extends RootView id: 'teacher-courses-view' template: template + + events: + 'click #create-new-class-btn': 'onClickCreateNewclassButton' + 'click .add-students-btn': 'onClickAddStudentsButton' constructor: (options) -> super(options) @@ -22,3 +25,21 @@ module.exports = class TeacherCoursesView extends RootView @listenToOnce @classrooms, 'sync', @onCourseInstancesLoaded @supermodel.loadCollection(@classrooms, 'classrooms', {data: {ownerID: me.id}}) @ + + onClickCreateNewclassButton: -> + name = @$('#new-classroom-name-input').val() + return unless name + classroom = new Classroom({ name: name }) + classroom.save() + @classrooms.add(classroom) + classroom.saving = true + @render() + @listenTo classroom, 'sync', -> + classroom.saving = false + @render() + + onClickAddStudentsButton: (e) -> + classroomID = $(e.target).data('classroom-id') + classroom = @classrooms.get(classroomID) + modal = new InviteToClassroomModal({classroom: classroom}) + @openModalView(modal) \ No newline at end of file diff --git a/server/classrooms/classroom_handler.coffee b/server/classrooms/classroom_handler.coffee index 9ac4d217a..734b37217 100644 --- a/server/classrooms/classroom_handler.coffee +++ b/server/classrooms/classroom_handler.coffee @@ -70,11 +70,10 @@ ClassroomHandler = class ClassroomHandler extends Handler email_id: sendwithus.templates.course_invite_email recipient: address: email - subject: classroom.get('name') email_data: class_name: classroom.get('name') # TODO: join_link -# join_link: "https://codecombat.com/courses/students?_ppc=" + prepaid.get('code') + join_link: "https://codecombat.com/courses/students?_cc=" + classroom.get('code') sendwithus.api.send context, _.noop return @sendSuccess(res, {})