diff --git a/app/core/Router.coffee b/app/core/Router.coffee index 13c6de310..a6c42752b 100644 --- a/app/core/Router.coffee +++ b/app/core/Router.coffee @@ -73,8 +73,8 @@ module.exports = class CocoRouter extends Backbone.Router 'Courses': go('courses/CoursesView') # , { studentsOnly: true }) 'courses/students': redirect('/courses') 'courses/teachers': redirect('/teachers/classes') - 'courses/purchase': redirect('/teachers/enrollments') - 'courses/enroll(/:courseID)': redirect('/teachers/enrollments') + 'courses/purchase': redirect('/teachers/licenses') + 'courses/enroll(/:courseID)': redirect('/teachers/licenses') 'courses/update-account': go('courses/CoursesUpdateAccountView') 'courses/:classroomID': go('courses/ClassroomView') #, { studentsOnly: true }) 'courses/:courseID/:courseInstanceID': go('courses/CourseDetailsView') @@ -146,7 +146,8 @@ module.exports = class CocoRouter extends Backbone.Router 'teachers/classes/:classroomID': go('courses/TeacherClassView') #, { teachersOnly: true }) 'teachers/courses': go('courses/TeacherCoursesView') 'teachers/demo': go('teachers/RequestQuoteView') - 'teachers/enrollments': go('courses/EnrollmentsView') #, { teachersOnly: true }) + 'teachers/enrollments': redirect('/teachers/licenses') + 'teachers/licenses': go('courses/EnrollmentsView') #, { teachersOnly: true }) 'teachers/freetrial': go('teachers/RequestQuoteView') 'teachers/quote': go('teachers/RequestQuoteView') 'teachers/signup': -> diff --git a/app/locale/en.coffee b/app/locale/en.coffee index 55a5383d1..504663152 100644 --- a/app/locale/en.coffee +++ b/app/locale/en.coffee @@ -860,7 +860,7 @@ signup_with: "Sign up with:" connect_with: "Connect with:" conversion_warning: "WARNING: Your current account is a Student Account. Once you submit this form, your account will be updated to a Teacher Account." - learn_more_modal: "Teacher accounts on CodeCombat have the ability to monitor student progress, assign enrollments and manage classrooms. Teacher accounts cannot be a part of a classroom - if you are currently enrolled in a class using this account, you will no longer be able to access it once you update to a Teacher Account." + learn_more_modal: "Teacher accounts on CodeCombat have the ability to monitor student progress, assign licenses and manage classrooms. Teacher accounts cannot be a part of a classroom - if you are currently enrolled in a class using this account, you will no longer be able to access it once you update to a Teacher Account." # {change} create_account: "Create a Teacher Account" create_account_subtitle: "Get access to teacher-only tools for using CodeCombat in the classroom. Set up a class, add your students, and monitor their progress!" convert_account_title: "Update to Teacher Account" @@ -1114,13 +1114,13 @@ get_free: "Get FREE course" enroll_paid: "Enroll Students in Paid Courses" you_have1: "You have" - you_have2: "unused paid enrollments" - use_one: "Use 1 paid enrollment for" - use_multiple: "Use paid enrollments for the following students:" + you_have2: "unused student licenses" # {change} + use_one: "Use 1 student license for" # {change} + use_multiple: "Use licenses for the following students:" # {change} already_enrolled: "already enrolled" licenses_remaining: "licenses remaining:" - insufficient_enrollments: "insufficient paid enrollments" - get_enrollments: "Get Enrollments" # {change} + insufficient_enrollments: "insufficient student licenses" # {change} + get_enrollments: "Get More Licenses" # {change} change_language: "Change Course Language" keep_using: "Keep Using" switch_to: "Switch To" @@ -1129,7 +1129,7 @@ back_courses: "Back to my courses" edit_details: "Edit class details" enrolled_courses: "enrolled in paid courses:" - purchase_enrollments: "Purchase Enrollments" + purchase_enrollments: "Purchase Student Licenses" # {change} remove_student: "remove student" assign: "Assign" to_assign: "to assign paid courses." @@ -1201,10 +1201,10 @@ return_to_course_man: "Return to course management." students_not_enrolled: "students not enrolled" total_all_classes: "Total Across All Classes" - how_many_enrollments: "How many additional paid enrollments do you need?" + how_many_enrollments: "How many additional student licenses do you need?" # {change} each_student_access: "Each student in a class will get access to Courses 2-4 once they are enrolled in paid courses. You may assign each course to each student individually." purchase_now: "Purchase Now" - enrollments: "enrollments" + enrollments: "licenses" # {change} remove_student1: "Remove Student" are_you_sure: "Are you sure you want to remove this student from this class?" remove_description1: "Student will lose access to this classroom and assigned classes. Progress and gameplay is NOT lost, and the student can be added back to the classroom at any time." @@ -1232,20 +1232,6 @@ getting_started_1: "Create a new class by clicking the green 'Create New Class' button below." getting_started_2: "Once you've created a class, click the blue 'Add Students' button." getting_started_3: "You'll see student's progress below as they sign up and join your class." - additional_resources: "Additional Resources" - additional_resources_1_pref: "Download/print our" - additional_resources_1_mid: "Course 1" - additional_resources_1_mid2: "and" - additional_resources_1_mid3: "Course 2" - additional_resources_1_suff: "teacher's guides with solutions for each level." - additional_resources_2_pref: "Complete our" - additional_resources_2_suff: "to get two free enrollments for the rest of our paid courses." - additional_resources_3_pref: "Visit our" - additional_resources_3_mid: "Teacher Forums" - additional_resources_3_suff: "to connect to fellow educators who are using CodeCombat." - additional_resources_4_pref: "Check out our" - additional_resources_4_mid: "Schools Page" - additional_resources_4_suff: "to learn more about CodeCombat's classroom offerings." educator_wiki_pref: "Or check out our new" educator_wiki_mid: "educator wiki" educator_wiki_suff: "to browse the guide online." @@ -1253,8 +1239,8 @@ no_classes: "No classes yet!" create_new_class1: "create new class" available_courses: "Available Courses" - unused_enrollments: "Unused enrollments available:" - students_access: "All students get access to Introduction to Computer Science for free. One enrollment per student is required to assign them to paid CodeCombat courses. A single student does not need multiple enrollments to access all paid courses." + unused_enrollments: "Unused licenses available:" # {change} + students_access: "All students get access to Introduction to Computer Science for free. One license per student is required to assign them to paid CodeCombat courses. A single student does not need multiple licenses to access all paid courses." # {change} active_courses: "active courses" no_students: "No students yet!" add_students1: "add students" @@ -1273,7 +1259,7 @@ view_guide_online: "View Guide Online (PDF)" last_updated: "Last updated:" grants_lifetime_access: "Grants access to all Courses." - enrollment_credits_available: "Enrollment Credits Available:" + enrollment_credits_available: "Licenses Available:" # {change} description: "Description" # ClassroomSettingsModal language_select: "Select a language" language_cannot_change: "Language cannot be changed once students join a class." @@ -1334,8 +1320,8 @@ teacher: teacher_dashboard: "Teacher Dashboard" # Navbar my_classes: "My Classes" - courses: "Courses" - enrollments: "Enrollments" + courses: "Course Guides" # {change} + enrollments: "Student Licenses" # {change} resources: "Resources" help: "Help" students: "Students" # Shared @@ -1346,7 +1332,7 @@ teacher_account_required: "A teacher account is required to access this content." create_teacher_account: "Create Teacher Account" what_is_a_teacher_account: "What's a Teacher Account?" - teacher_account_explanation: "A CodeCombat Teacher account allows you to set up classrooms, monitor students’ progress as they work through courses, manage enrollments and access resources to aid in your curriculum-building." + teacher_account_explanation: "A CodeCombat Teacher account allows you to set up classrooms, monitor students’ progress as they work through courses, manage licenses and access resources to aid in your curriculum-building." # {change} current_classes: "Current Classes" archived_classes: "Archived Classes" archived_classes_blurb: "Classes can be archived for future reference. Unarchive a class to view it in the Current Classes list again." @@ -1398,14 +1384,14 @@ enroll_the_following_students: "Enroll the following students" all_students: "All Students" enroll_students: "Enroll Students" - not_enough_enrollments: "Not enough Enrollments available." - enrollments_blurb_1: "Students taking Computer Science" # Enrollments page - enrollments_blurb_2: "require enrollments to access the courses." - credits_available: "Credits Available" - total_unique_students: "Total Students (unique)" # {change} - total_enrolled_students: "Total Enrolled" # {change} + not_enough_enrollments: "Not enough licenses available." # {change} + enrollments_blurb_1: "Students taking Computer Science" # {change} + enrollments_blurb_2: "require a license to access the courses." # {change} + credits_available: "Licenses Available" # {change} + total_unique_students: "Total Students" # {change} + total_enrolled_students: "Enrolled Students" # {change} unenrolled_students: "Unenrolled Students" - add_enrollment_credits: "Add Enrollment Credits" + add_enrollment_credits: "Add Licenses" # {change} purchasing: "Purchasing..." purchased: "Purchased!" purchase_now: "Purchase Now" @@ -1422,12 +1408,12 @@ enter_new_password_below: "Enter new password below:" change_password: "Change Password" changed: "Changed" - available_credits: "Available Credits" - pending_credits: "Pending Credits" - credits: "credits" + available_credits: "Available Licenses" # {change} + pending_credits: "Pending Licenses" # {change} + credits: "licenses" # {change} start_date: "start date:" end_date: "end date:" - num_enrollments_needed: "Number of enrollments needed:" + num_enrollments_needed: "Number of licenses needed:" # {change} get_enrollments_blurb: " We'll help you build a solution that meets the needs of your class, school or district." enroll_request_sent_blurb1: "Thanks! Your request has been sent." enroll_request_sent_blurb2: "Our classroom success team will be in touch shortly to help you find the best solution for your students' needs!" diff --git a/app/templates/admin/administer-user-modal.jade b/app/templates/admin/administer-user-modal.jade index 0e0c8d202..00b55b972 100644 --- a/app/templates/admin/administer-user-modal.jade +++ b/app/templates/admin/administer-user-modal.jade @@ -7,9 +7,51 @@ block modal-header-content h4 #{view.user.get('name') || 'Unnamed'} / #{view.user.get('email')} span= view.user.id - block modal-body-content - + + h3.m-t-3 Grant Student Licenses + #prepaid-form.form + if view.state === 'creating-prepaid' + .progress.progress-striped.active + .progress-bar(style="width: 100%") + + else if view.state === 'made-prepaid' + .alert.alert-success Licenses created! + + else + .form-group + label Number of Licenses + input#seats-input.form-control(type="number", name="maxRedeemers") + .form-group + label Start Date + input.form-control(type="date" name="startDate" value=moment().format('YYYY-MM-DD')) + .form-group + label End Date + input.form-control(type="date" name="endDate" value=moment().add(1, 'year').format('YYYY-MM-DD'))) + .form-group + button#add-seats-btn.btn.btn-primary Add Licenses + + if view.prepaids.size() + h3.m-t-3 Existing Prepaids + table.table.table-condensed + tr + th ID + th Type + th Start + th End + th Used + for prepaid in view.prepaids.models + tr + td= prepaid.id + td= prepaid.get('type') + td + if prepaid.get('startDate') + = moment(prepaid.get('startDate')).utc().format('lll') + td + if prepaid.get('endDate') + = moment(prepaid.get('endDate')).utc().format('lll') + td #{(prepaid.get('redeemers') || []).length} / #{prepaid.get('maxRedeemers') || 0} + h3 Stripe Benefit .form .form-group @@ -34,50 +76,5 @@ block modal-body-content for coupon in view.coupons.models option(value=coupon.id selected=coupon.id===view.currentCouponID)= coupon.formatString() button#save-changes.btn.btn-primary Save Changes - - if view.prepaids.size() - h3.m-t-3 Existing Prepaids - table.table.table-condensed - tr - th ID - th Type - th Start - th End - th Used - for prepaid in view.prepaids.models - tr - td= prepaid.id - td= prepaid.get('type') - td - if prepaid.get('startDate') - = moment(prepaid.get('startDate')).utc().format('lll') - td - if prepaid.get('endDate') - = moment(prepaid.get('endDate')).utc().format('lll') - td #{(prepaid.get('redeemers') || []).length} / #{prepaid.get('maxRedeemers') || 0} - - h3.m-t-3 Grant Prepaid for Courses - #prepaid-form.form - if view.state === 'creating-prepaid' - .progress.progress-striped.active - .progress-bar(style="width: 100%") - - else if view.state === 'made-prepaid' - .alert.alert-success Prepaid created! - - else - .form-group - label Seats - input#seats-input.form-control(type="number", name="maxRedeemers") - .form-group - label Start Date - input.form-control(type="date" name="startDate" value=moment().format('YYYY-MM-DD')) - .form-group - label End Date - input.form-control(type="date" name="endDate" value=moment().add(1, 'year').format('YYYY-MM-DD'))) - .form-group - button#add-seats-btn.btn.btn-primary Add Seats - -block modal-footer - +block modal-footer diff --git a/app/templates/admin/analytics.jade b/app/templates/admin/analytics.jade index e67d95d4d..51dc0c100 100644 --- a/app/templates/admin/analytics.jade +++ b/app/templates/admin/analytics.jade @@ -149,7 +149,7 @@ block content h3 Classroom Monthly Active Users 365 days .classroom-monthly-active-users-chart-365.line-chart-container - h3 Enrollments Issued and Redeemed 90 days + h3 Licenses Issued and Redeemed 90 days .paid-courses-chart.line-chart-container #furthest-course @@ -282,14 +282,14 @@ block content each eventName in eventNames td= activeUser.events[eventName] || 0 - h1#enrollments-table Enrollments + h1#enrollments-table Licenses table.table.table-striped.table-condensed tr th Day - th Paid Enrollments Issued - th Paid Enrollments Redeemed - th Trial Enrollments Issued - th Trial Enrollments Redeemed + th Paid Licenses Issued + th Paid Licenses Redeemed + th Trial Licenses Issued + th Trial Licenses Redeemed each day in view.enrollmentDays tr td= day diff --git a/app/templates/courses/activate-licenses-modal.jade b/app/templates/courses/activate-licenses-modal.jade index 8d88ae36d..2509cbf20 100644 --- a/app/templates/courses/activate-licenses-modal.jade +++ b/app/templates/courses/activate-licenses-modal.jade @@ -70,6 +70,6 @@ block modal-body-content span.spl(data-i18n="courses.students1") p - a#get-more-licenses-btn.btn.btn-lg.btn-primary-alt(href="/teachers/enrollments", data-i18n="courses.get_enrollments") + a#get-more-licenses-btn.btn.btn-lg.btn-primary-alt(href="/teachers/licenses", data-i18n="courses.get_enrollments") block modal-footer-content diff --git a/app/templates/courses/teacher-dashboard-nav.jade b/app/templates/courses/teacher-dashboard-nav.jade index 164aea924..6ee1bb32b 100644 --- a/app/templates/courses/teacher-dashboard-nav.jade +++ b/app/templates/courses/teacher-dashboard-nav.jade @@ -18,8 +18,8 @@ li(class= path.indexOf('/teachers/courses') === 0 ? 'active' : '') a(href='/teachers/courses') small.label(data-i18n='teacher.courses') - li(class= path.indexOf('/teachers/enrollments') === 0 ? 'active' : '') - a(href='/teachers/enrollments') + li(class= path.indexOf('/teachers/licenses') === 0 ? 'active' : '') + a(href='/teachers/licenses') small.label(data-i18n='teacher.enrollments') //- li(class= path.indexOf('TODO') === 0 ? 'active' : '') //- a(href='TODO') diff --git a/app/views/courses/ActivateLicensesModal.coffee b/app/views/courses/ActivateLicensesModal.coffee index 28345d1a7..a1bf8afa5 100644 --- a/app/views/courses/ActivateLicensesModal.coffee +++ b/app/views/courses/ActivateLicensesModal.coffee @@ -116,4 +116,4 @@ module.exports = class ActivateLicensesModal extends ModalView @trigger 'redeem-users', @state.get('selectedUsers') onClickGetMoreLicensesButton: -> - @hide?() # In case this is opened in /teachers/enrollments itself, otherwise the button does nothing + @hide?() # In case this is opened in /teachers/licenses itself, otherwise the button does nothing diff --git a/app/views/teachers/TeachersContactModal.coffee b/app/views/teachers/TeachersContactModal.coffee index 5e2c1a183..57ee0bc58 100644 --- a/app/views/teachers/TeachersContactModal.coffee +++ b/app/views/teachers/TeachersContactModal.coffee @@ -33,7 +33,7 @@ module.exports = class TeachersContactModal extends ModalView Your Name: #{props.name || ''} Enrollments Needed: #{@enrollmentsNeeded} - Message: Hi CodeCombat! I want to learn more about the Classroom experience and get enrollments so that my students can access Computer Science 2 and on. + Message: Hi CodeCombat! I want to learn more about the Classroom experience and get licenses so that my students can access Computer Science 2 and on. """ email = props.email or me.get('email') or '' @state.set('formValues', { email, message }) diff --git a/server/middleware/prepaids.coffee b/server/middleware/prepaids.coffee index 14742fc04..09593e050 100644 --- a/server/middleware/prepaids.coffee +++ b/server/middleware/prepaids.coffee @@ -36,7 +36,7 @@ module.exports = redeem: wrap (req, res) -> if not req.user?.isTeacher() - throw new errors.Forbidden('Must be a teacher to use enrollments') + throw new errors.Forbidden('Must be a teacher to use licenses') prepaid = yield database.getDocFromHandle(req, Prepaid) if not prepaid @@ -45,7 +45,7 @@ module.exports = if prepaid._id.getTimestamp().getTime() < cutoffDate.getTime() throw new errors.Forbidden('Cannot redeem from prepaids older than November 11, 2015') unless prepaid.get('creator').equals(req.user._id) - throw new errors.Forbidden('You may not redeem enrollments from this prepaid') + throw new errors.Forbidden('You may not redeem licenses from this prepaid') if prepaid.get('redeemers')? and _.size(prepaid.get('redeemers')) >= prepaid.get('maxRedeemers') throw new errors.Forbidden('This prepaid is exhausted') unless prepaid.get('type') is 'course' diff --git a/spec/server/functional/level.spec.coffee b/spec/server/functional/level.spec.coffee index d97a68919..27cfc9783 100644 --- a/spec/server/functional/level.spec.coffee +++ b/spec/server/functional/level.spec.coffee @@ -115,7 +115,7 @@ describe 'GET /db/level/:handle/session', -> expect(res.statusCode).toBe(200) done() - it 'returns 402 if the user\'s enrollment is expired', utils.wrap (done) -> + it 'returns 402 if the user\'s license is expired', utils.wrap (done) -> @student.set({ coursePrepaid: { _id: {} diff --git a/spec/server/functional/prepaid.spec.coffee b/spec/server/functional/prepaid.spec.coffee index e528a8c70..4baacae41 100644 --- a/spec/server/functional/prepaid.spec.coffee +++ b/spec/server/functional/prepaid.spec.coffee @@ -109,7 +109,7 @@ describe 'POST /db/prepaid/:handle/redeemers', -> yield utils.loginUser(@otherTeacher) [res, body] = yield request.postAsync({uri: @url, json: { userID: @student.id } }) expect(res.statusCode).toBe(403) - expect(res.body.message).toBe('You may not redeem enrollments from this prepaid') + expect(res.body.message).toBe('You may not redeem licenses from this prepaid') done() it 'returns 403 if the prepaid is expired', utils.wrap (done) -> @@ -143,7 +143,7 @@ describe 'POST /db/prepaid/:handle/redeemers', -> expect(student.get('coursePrepaid')._id.equals(@prepaid._id)).toBe(true) done() - it 'updates the user if their enrollment is expired', utils.wrap (done) -> + it 'updates the user if their license is expired', utils.wrap (done) -> yield utils.loginUser(@admin) prepaid = yield utils.makePrepaid({ creator: @teacher.id diff --git a/test/app/views/courses/EnrollmentsView.spec.coffee b/test/app/views/courses/EnrollmentsView.spec.coffee index eb6c59a27..75ba21deb 100644 --- a/test/app/views/courses/EnrollmentsView.spec.coffee +++ b/test/app/views/courses/EnrollmentsView.spec.coffee @@ -65,10 +65,10 @@ describe 'EnrollmentsView', -> if @view.$('#actions-col').length isnt 1 fail('There should be an #action-col, other tests depend on it.') - describe '"Get Enrollments" area', -> + describe '"Get Licenses" area', -> describe '"Contact Us" button', -> - it 'opens a TeachersContactModal, passing in the number of enrollments', -> + it 'opens a TeachersContactModal, passing in the number of licenses', -> spyOn(@view, 'openModalView') @view.state.set('numberOfStudents', 20) @view.$('#contact-us-btn').click() @@ -86,7 +86,7 @@ describe 'EnrollmentsView', -> if not @view.$('#request-sent-btn').length fail('Request button not found.') if not @view.$('#enrollment-request-sent-blurb').length - fail('Enrollment request sent blurb not found.') + fail('License request sent blurb not found.') # TODO: Figure out why this fails in Travis. Seems like it's not loading en locale # if not @view.$('a[href="mailto:schools@codecombat.com"]').length # fail('Mailto: link not found.') diff --git a/test/app/views/teachers/ActivateLicensesModal.spec.coffee b/test/app/views/teachers/ActivateLicensesModal.spec.coffee index 2fb905456..2d7ee2d2a 100644 --- a/test/app/views/teachers/ActivateLicensesModal.spec.coffee +++ b/test/app/views/teachers/ActivateLicensesModal.spec.coffee @@ -82,7 +82,7 @@ describe 'ActivateLicensesModal', -> it 'should fire off one request when clicked' - describe 'when the teacher has enough enrollments', -> + describe 'when the teacher has enough licenses', -> beforeEach -> selected = @modal.state.get('selectedUsers') selected.remove(selected.first()) @@ -103,12 +103,12 @@ describe 'ActivateLicensesModal', -> if request.url.indexOf(@prepaidThatExpiresLater.id) is -1 fail('The second prepaid should be the prepaid that expires later') - describe 'when the teacher doesn\'t have enough enrollments', -> + describe 'when the teacher doesn\'t have enough licenses', -> it 'should be disabled', -> expect(@modal.$('#activate-licenses-btn').hasClass('disabled')).toBe(true) describe 'the Purchase More button', -> - it 'should redirect to the enrollment purchasing page' + it 'should redirect to the license purchasing page' @@ -122,7 +122,7 @@ describe 'ActivateLicensesModal', -> # it 'should display the correct total number of credits', -> # expect(@modal.$('#total-available').html()).toBe('2') # - # it 'should be disabled when teacher doesn\'t have enough enrollments', -> + # it 'should be disabled when teacher doesn\'t have enough licenses', -> # expect(@modal.$('#total-available').html()).toBe('2') # #