mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-30 10:56:53 -05:00
Add required district field to teacher trial request forms
School now optional N/A placeholder on district field and don't save it if it's n/a Updating required field error UI a bit, and there is some larger refactoring needed here later. NCES phone number for district only entries will currently be a child school, will fix later. Closes #3818
This commit is contained in:
parent
f4c0e4144e
commit
6f08d5e422
18 changed files with 630 additions and 426 deletions
|
@ -45,7 +45,7 @@ module.exports.applyErrorsToForm = (el, errors, warning=false) ->
|
|||
for error in errors
|
||||
if error.code is tv4.errorCodes.OBJECT_REQUIRED
|
||||
prop = _.last(_.string.words(error.message)) # hack
|
||||
message = 'Required field'
|
||||
message = $.i18n.t('common.required_field')
|
||||
|
||||
else if error.dataPath
|
||||
prop = error.dataPath[1..]
|
||||
|
|
|
@ -356,7 +356,7 @@
|
|||
submit_patch: "Submit Patch"
|
||||
submit_changes: "Submit Changes"
|
||||
save_changes: "Save Changes"
|
||||
required_field: "Required field"
|
||||
required_field: "required" # {change}
|
||||
|
||||
general:
|
||||
and: "and"
|
||||
|
@ -885,7 +885,9 @@
|
|||
evaluate_recommend: "Evaluate/Recommend"
|
||||
approve_funds: "Approve Funds"
|
||||
no_purchaser_role: "No role in purchase decisions"
|
||||
organization_label: "Name of School/District"
|
||||
district_label: "District"
|
||||
district_na: "Enter N/A if not applicable"
|
||||
organization_label: "School" # {change}
|
||||
city: "City"
|
||||
state: "State"
|
||||
country: "Country"
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
@import "app/styles/mixins"
|
||||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
#request-quote-view
|
||||
#site-content-area
|
||||
margin: 50px 0 100px
|
||||
.row
|
||||
margin: 20px 0
|
||||
|
||||
#conversion-warning
|
||||
margin-top: 20px
|
||||
|
||||
.form-group
|
||||
label
|
||||
margin-bottom: 0
|
||||
|
||||
label.checkbox
|
||||
font-weight: normal
|
||||
|
||||
.help-block
|
||||
margin: -4px 0 2px
|
||||
|
||||
p
|
||||
margin: 0 0 20px
|
||||
|
||||
.checkbox, .checkbox-inline
|
||||
input
|
||||
margin-top: 8px
|
||||
|
||||
#other-education-level-input
|
||||
label
|
||||
display: inline-block
|
||||
display: inline-block
|
||||
width: 200px
|
||||
margin-left: 5px
|
||||
|
||||
#submit-request-btn
|
||||
margin-left: 10px
|
||||
|
||||
// After submit (anonymous)
|
||||
|
||||
h5
|
||||
margin-top: 50px
|
||||
|
||||
#social-network-signups
|
||||
margin: 20px 0
|
||||
button
|
||||
margin-left: 10px
|
||||
|
||||
.text-h1
|
||||
margin: 40px 0 30px
|
||||
|
||||
|
||||
.algolia-autocomplete
|
||||
width: 100%;
|
||||
|
||||
.aa-input
|
||||
width: 100%
|
||||
|
||||
.aa-hint
|
||||
color: #999
|
||||
width: 100%
|
||||
|
||||
.aa-dropdown-menu
|
||||
background-color: #fff
|
||||
border: 1px solid #999
|
||||
border-top: none
|
||||
width: 100%
|
||||
|
||||
.aa-suggestion
|
||||
cursor: pointer
|
||||
padding: 5px 4px
|
||||
border-top: 1px solid #ccc
|
||||
|
||||
.school
|
||||
font-family: Open Sans
|
||||
font-size: 14px
|
||||
line-height: 20px
|
||||
font-weight: bold
|
||||
|
||||
.district
|
||||
font-family: Open Sans
|
||||
font-size: 14px
|
||||
line-height: 20px
|
||||
|
||||
span
|
||||
white-space: nowrap
|
||||
|
||||
|
||||
.aa-suggestion.aa-cursor
|
||||
background-color: #B2D7FF
|
||||
|
||||
em
|
||||
font-weight: bold
|
||||
font-style: normal
|
||||
|
81
app/styles/teachers/teacher-trial-requests.sass
Normal file
81
app/styles/teachers/teacher-trial-requests.sass
Normal file
|
@ -0,0 +1,81 @@
|
|||
#create-teacher-account-view, #convert-to-teacher-account-view, #request-quote-view
|
||||
.algolia-autocomplete
|
||||
width: 100%;
|
||||
|
||||
.aa-input
|
||||
width: 100%
|
||||
|
||||
.aa-hint
|
||||
color: #999
|
||||
width: 100%
|
||||
|
||||
.aa-dropdown-menu
|
||||
background-color: #fff
|
||||
border: 1px solid #999
|
||||
border-top: none
|
||||
width: 100%
|
||||
|
||||
.aa-suggestion
|
||||
cursor: pointer
|
||||
padding: 5px 4px
|
||||
border-top: 1px solid #ccc
|
||||
|
||||
.school
|
||||
font-family: Open Sans
|
||||
font-size: 14px
|
||||
line-height: 20px
|
||||
font-weight: bold
|
||||
|
||||
.district
|
||||
font-family: Open Sans
|
||||
font-size: 14px
|
||||
line-height: 20px
|
||||
|
||||
span
|
||||
white-space: nowrap
|
||||
|
||||
|
||||
.aa-suggestion.aa-cursor
|
||||
background-color: #B2D7FF
|
||||
|
||||
em
|
||||
font-weight: bold
|
||||
font-style: normal
|
||||
|
||||
// TODO: update form validation instead of overwriting these styles
|
||||
|
||||
.control-label
|
||||
font-weight: bold
|
||||
width: 100%
|
||||
|
||||
.error-help-block
|
||||
margin-top: inherit
|
||||
margin-bottom: 0px
|
||||
float: right
|
||||
font-size: 13px
|
||||
font-style: italic
|
||||
font-weight: normal
|
||||
|
||||
.text-muted
|
||||
float: right
|
||||
font-size: 13px
|
||||
font-style: italic
|
||||
font-weight: normal
|
||||
|
||||
.nullify-form-control
|
||||
display: inherit
|
||||
width: inherit
|
||||
height: inherit
|
||||
padding: inherit
|
||||
font-size: inherit
|
||||
line-height: inherit
|
||||
color: inherit
|
||||
vertical-align: inherit
|
||||
background-color: inherit
|
||||
background-image: inherit
|
||||
border: inherit
|
||||
border-radius: inherit
|
||||
-webkit-box-shadow: inherit
|
||||
box-shadow: inherit
|
||||
-webkit-transition: inherit
|
||||
transition: inherit
|
|
@ -30,8 +30,8 @@ block content
|
|||
thead
|
||||
tr
|
||||
th Created
|
||||
th NCES District
|
||||
th School Name
|
||||
th School District
|
||||
th.number NCES District Schools
|
||||
th.number NCES District Students
|
||||
th.number NCES School Students
|
||||
|
@ -44,8 +44,8 @@ block content
|
|||
- continue;
|
||||
tr
|
||||
td.created= trialRequest.get('created').substring(0, 10)
|
||||
td= trialRequest.get('properties').nces_district || ''
|
||||
td= trialRequest.get('properties').organization || ''
|
||||
td= trialRequest.get('properties').nces_name || trialRequest.get('properties').organization || ''
|
||||
td= trialRequest.get('properties').nces_district || trialRequest.get('properties').district || ''
|
||||
td= trialRequest.get('properties').nces_district_schools || ''
|
||||
td= trialRequest.get('properties').nces_district_students || ''
|
||||
td= trialRequest.get('properties').nces_students || ''
|
||||
|
|
|
@ -28,40 +28,36 @@ block content
|
|||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.username")
|
||||
span.control-label(data-i18n="general.username")
|
||||
input.form-control(disabled=true value=me.get('name'))
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
#email-form-group.form-group
|
||||
label.control-label(data-i18n="general.email")
|
||||
span.control-label(data-i18n="general.email")
|
||||
input.form-control(name='email' disabled=true value=me.get('email'))
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.first_name")
|
||||
span.control-label(data-i18n="general.first_name")
|
||||
input.form-control(name="firstName" value=me.get('firstName') || '')
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.last_name")
|
||||
span.control-label(data-i18n="general.last_name")
|
||||
input.form-control(name="lastName" value=me.get('lastName') || '')
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.phone_number")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||
input.form-control(name="phoneNumber")
|
||||
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.role_help")
|
||||
span.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
select.form-control(name="role")
|
||||
option(data-i18n="teachers_quote.role_default", , value='')
|
||||
option(data-i18n="courses.teacher", value="Teacher")
|
||||
|
@ -75,30 +71,40 @@ block content
|
|||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.organization_label")
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.organization_label")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
input.form-control#organization-control(name="organization")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
//- TODO: algolia and form errors both change form-control
|
||||
//- TODO: District not red on validation error
|
||||
span.control-label.form-control.nullify-form-control(data-i18n="teachers_quote.district_label")
|
||||
input.form-control#district-control(name="district", data-i18n="[placeholder]teachers_quote.district_na")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
span.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-labellabel.control-label(data-i18n="teachers_quote.country")
|
||||
span.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
span.control-labelspan.control-label(data-i18n="teachers_quote.country")
|
||||
input.form-control(name="country")
|
||||
|
||||
#form-students-info
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="courses.number_programming_students")
|
||||
span.control-label(data-i18n="courses.number_programming_students")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||
select.form-control(name="numStudents")
|
||||
|
@ -113,7 +119,7 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="courses.number_total_students")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
select.form-control(name="numStudentsTotal")
|
||||
|
@ -126,11 +132,10 @@ block content
|
|||
|
||||
.form-group
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-10
|
||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.col-md-offset-2.col-md-4
|
||||
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||
.col-md-offset-2.col-md-5
|
||||
.checkbox
|
||||
label
|
||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||
|
@ -156,7 +161,7 @@ block content
|
|||
|
||||
#anything-else-row.row.m-y-2
|
||||
.col-md-offset-2.col-md-8
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.anything_else")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
textarea.form-control(rows=8, name="notes")
|
||||
|
|
|
@ -34,49 +34,47 @@ block content
|
|||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.username")
|
||||
span.control-label(data-i18n="general.username")
|
||||
input.form-control(name="name")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
#email-form-group.form-group
|
||||
label.control-label(data-i18n="general.email")
|
||||
span.control-label(data-i18n="general.email")
|
||||
input.form-control(name="email")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.first_name")
|
||||
span.control-label(data-i18n="general.first_name")
|
||||
input.form-control(name="firstName")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.last_name")
|
||||
span.control-label(data-i18n="general.last_name")
|
||||
input.form-control(name="lastName")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.password")
|
||||
span.control-label(data-i18n="general.password")
|
||||
input.form-control(name="password1", type="password")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.confirm_password")
|
||||
span.control-label(data-i18n="general.confirm_password")
|
||||
input.form-control(name="password2", type="password")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.phone_number")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||
input.form-control(name="phoneNumber")
|
||||
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
span.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
select.form-control(name="role")
|
||||
option(data-i18n="teachers_quote.role_default", , value='')
|
||||
option(data-i18n="courses.teacher", value="Teacher")
|
||||
|
@ -90,30 +88,40 @@ block content
|
|||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.organization_label")
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.organization_label")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
input.form-control#organization-control(name="organization")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
//- TODO: algolia and form errors both change form-control
|
||||
//- TODO: District not red on validation error
|
||||
span.control-label.form-control.nullify-form-control(data-i18n="teachers_quote.district_label")
|
||||
input.form-control#district-control(name="district", data-i18n="[placeholder]teachers_quote.district_na")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
span.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-labellabel.control-label(data-i18n="teachers_quote.country")
|
||||
span.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
span.control-label(data-i18n="teachers_quote.country")
|
||||
input.form-control(name="country")
|
||||
|
||||
#form-students-info
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="courses.number_programming_students")
|
||||
span.control-label(data-i18n="courses.number_programming_students")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||
select.form-control(name="numStudents")
|
||||
|
@ -128,7 +136,7 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="courses.number_total_students")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
select.form-control(name="numStudentsTotal")
|
||||
|
@ -140,14 +148,11 @@ block content
|
|||
option 10,000+
|
||||
|
||||
.form-group
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-10
|
||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.col-md-offset-2.col-md-4
|
||||
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||
|
||||
.col-md-offset-2.col-md-5
|
||||
.checkbox
|
||||
label
|
||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||
|
@ -173,7 +178,7 @@ block content
|
|||
|
||||
#anything-else-row.row.m-y-2
|
||||
.col-md-offset-2.col-md-8
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.anything_else")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ block content
|
|||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="general.username")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
- var name = me.get('name') || '';
|
||||
|
@ -44,20 +44,20 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="share_progress_modal.form_label")
|
||||
span.control-label(data-i18n="share_progress_modal.form_label")
|
||||
- var email = me.get('email') || '';
|
||||
input.form-control(name="email" value=email, disabled=!!email)
|
||||
|
||||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.first_name")
|
||||
span.control-label(data-i18n="general.first_name")
|
||||
- var firstName = me.get('firstName') || '';
|
||||
input.form-control(name="firstName" value=firstName, disabled=!!firstName)
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.last_name")
|
||||
span.control-label(data-i18n="general.last_name")
|
||||
- var lastName = me.get('lastName') || '';
|
||||
input.form-control(name="lastName" value=lastName, disabled=!!lastName)
|
||||
|
||||
|
@ -65,23 +65,20 @@ block content
|
|||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span(data-i18n="teachers_quote.phone_number")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||
input.form-control(name="phoneNumber")
|
||||
span.control-label(data-i18n="teachers_quote.phone_number")
|
||||
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||
|
||||
if me.isAnonymous()
|
||||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
#email-form-group.form-group
|
||||
label.control-label(data-i18n="general.email")
|
||||
span.control-label(data-i18n="general.email")
|
||||
- var email = me.get('email') || '';
|
||||
input.form-control(name="email" type="email", value=email, disabled=!!email)
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.phone_number")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||
|
@ -91,7 +88,7 @@ block content
|
|||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
span.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
select.form-control(name="role")
|
||||
option(data-i18n="teachers_quote.primary_role_default", , value='')
|
||||
option(data-i18n="courses.teacher", value="Teacher")
|
||||
|
@ -103,7 +100,7 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.purchaser_role_label")
|
||||
span.control-label(data-i18n="teachers_quote.purchaser_role_label")
|
||||
select.form-control(name="purchaserRole")
|
||||
option(data-i18n="teachers_quote.purchaser_role_default", , value='')
|
||||
option(data-i18n="teachers_quote.influence_advocate", value="Influence/Advocate")
|
||||
|
@ -112,33 +109,43 @@ block content
|
|||
option(data-i18n="teachers_quote.no_purchaser_role", value="No role in purchase decisions")
|
||||
|
||||
#form-school-info
|
||||
.row
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.organization_label")
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.organization_label")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
input.form-control#organization-control(name="organization")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
//- TODO: algolia and form errors both change form-control
|
||||
//- TODO: District not red on validation error
|
||||
span.control-label.form-control.nullify-form-control(data-i18n="teachers_quote.district_label")
|
||||
input.form-control#district-control(name="district", data-i18n="[placeholder]teachers_quote.district_na")
|
||||
|
||||
.row
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
span.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-labellabel.control-label(data-i18n="teachers_quote.country")
|
||||
span.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
span.control-labelspan.control-label(data-i18n="teachers_quote.country")
|
||||
input.form-control(name="country")
|
||||
|
||||
#form-students-info
|
||||
.row
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="courses.number_programming_students")
|
||||
span.control-label(data-i18n="courses.number_programming_students")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||
select.form-control(name="numStudents")
|
||||
|
@ -153,7 +160,7 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="courses.number_total_students")
|
||||
span.control-label(data-i18n="courses.number_total_students")
|
||||
select.form-control(name="numStudentsTotal")
|
||||
option(data-i18n="teachers_quote.num_students_default", value='')
|
||||
option 1-500
|
||||
|
@ -163,14 +170,11 @@ block content
|
|||
option 10,000+
|
||||
|
||||
.form-group
|
||||
|
||||
.row
|
||||
.col-md-offset-2.col-md-10
|
||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4
|
||||
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||
|
||||
.col-md-offset-2.col-md-5
|
||||
.checkbox
|
||||
label
|
||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||
|
@ -196,7 +200,7 @@ block content
|
|||
|
||||
#anything-else-row.row
|
||||
.col-md-offset-2.col-md-8
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.anything_else")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
|
||||
|
@ -210,7 +214,7 @@ block content
|
|||
input(type="hidden" name="nces_students")
|
||||
input(type="hidden" name="nces_phone")
|
||||
|
||||
#buttons-row.row.text-center
|
||||
#buttons-row.row.m-y-2.text-center
|
||||
input#submit-request-btn.btn.btn-lg.btn-primary(type="submit" data-i18n="[value]teachers_quote.title")
|
||||
|
||||
#form-submit-success.text-center(class=showDone ? '' : 'hide')
|
||||
|
@ -244,17 +248,17 @@ block content
|
|||
.row
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.username")
|
||||
span.control-label(data-i18n="general.username")
|
||||
input.form-control(name="name")
|
||||
|
||||
.row
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.password")
|
||||
span.control-label(data-i18n="general.password")
|
||||
input.form-control(name="password1", type="password")
|
||||
.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.confirm_password")
|
||||
span.control-label(data-i18n="general.confirm_password")
|
||||
input.form-control(name="password2", type="password")
|
||||
|
||||
.text-center
|
||||
|
|
|
@ -7,9 +7,9 @@ errors = require 'core/errors'
|
|||
User = require 'models/User'
|
||||
ConfirmModal = require 'views/editor/modal/ConfirmModal'
|
||||
algolia = require 'core/services/algolia'
|
||||
NCES_KEYS = ['id', 'name', 'district', 'district_id', 'district_schools', 'district_students', 'students', 'phone']
|
||||
|
||||
FORM_KEY = 'request-quote-form'
|
||||
DISTRICT_NCES_KEYS = ['district', 'district_id', 'district_schools', 'district_students', 'phone']
|
||||
SCHOOL_NCES_KEYS = DISTRICT_NCES_KEYS.concat(['id', 'name', 'students'])
|
||||
|
||||
module.exports = class ConvertToTeacherAccountView extends RootView
|
||||
id: 'convert-to-teacher-account-view'
|
||||
|
@ -40,7 +40,7 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
|||
return 'Your account has not been updated! If you continue, your changes will be lost.'
|
||||
|
||||
invalidateNCES: ->
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val ''
|
||||
|
||||
onLoaded: ->
|
||||
|
@ -75,16 +75,34 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
|||
"<div class='school'> #{hr.name.value} </div>" +
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="country"]').val 'USA'
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeForm()
|
||||
|
||||
$("#district-control").algolia_autocomplete({hint: false}, [
|
||||
source: (query, callback) ->
|
||||
algolia.schoolsIndex.search(query, { hitsPerPage: 5, aroundLatLngViaIP: false }).then (answer) ->
|
||||
callback answer.hits
|
||||
, ->
|
||||
callback []
|
||||
displayKey: 'district',
|
||||
templates:
|
||||
suggestion: (suggestion) ->
|
||||
hr = suggestion._highlightResult
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="organization"]').val '' # TODO: does not persist on tabbing: back to school, back to district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="country"]').val 'USA'
|
||||
for key in DISTRICT_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeForm()
|
||||
|
||||
onChangeForm: ->
|
||||
|
@ -97,28 +115,35 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
|||
|
||||
form = @$('form')
|
||||
attrs = forms.formToObject(form)
|
||||
trialRequestAttrs = _.cloneDeep(attrs)
|
||||
|
||||
# Don't save n/a district entries, but do validate required district client-side
|
||||
trialRequestAttrs = _.omit(trialRequestAttrs, 'district') if trialRequestAttrs.district?.replace(/\s/ig, '').match(/n\/a/ig)
|
||||
|
||||
if @$('#other-education-level-checkbox').is(':checked')
|
||||
val = @$('#other-education-level-input').val()
|
||||
attrs.educationLevel.push(val) if val
|
||||
trialRequestAttrs.educationLevel.push(val) if val
|
||||
|
||||
forms.clearFormAlerts(form)
|
||||
|
||||
result = tv4.validateMultiple(attrs, formSchema)
|
||||
result = tv4.validateMultiple(trialRequestAttrs, formSchema)
|
||||
error = false
|
||||
if not result.valid
|
||||
forms.applyErrorsToForm(form, result.errors)
|
||||
error = true
|
||||
if not _.size(attrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'Include at least one.')
|
||||
if not _.size(trialRequestAttrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'include at least one')
|
||||
error = true
|
||||
unless attrs.district
|
||||
forms.setErrorToProperty(form, 'district', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
if error
|
||||
forms.scrollToFirstError()
|
||||
return
|
||||
attrs['siteOrigin'] = 'convert teacher'
|
||||
trialRequestAttrs['siteOrigin'] = 'convert teacher'
|
||||
@trialRequest = new TrialRequest({
|
||||
type: 'course'
|
||||
properties: attrs
|
||||
properties: trialRequestAttrs
|
||||
})
|
||||
if me.get('role') is 'student' and not me.isAnonymous()
|
||||
modal = new ConfirmModal({
|
||||
|
@ -151,15 +176,14 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
|||
|
||||
formSchema = {
|
||||
type: 'object'
|
||||
required: [
|
||||
'firstName', 'lastName', 'organization', 'role', 'numStudents', 'city', 'state', 'country'
|
||||
]
|
||||
required: ['firstName', 'lastName', 'role', 'numStudents', 'city', 'state', 'country']
|
||||
properties:
|
||||
firstName: { type: 'string' }
|
||||
lastName: { type: 'string' }
|
||||
phoneNumber: { type: 'string' }
|
||||
role: { type: 'string' }
|
||||
organization: { type: 'string' }
|
||||
district: { type: 'string' }
|
||||
city: { type: 'string' }
|
||||
state: { type: 'string' }
|
||||
country: { type: 'string' }
|
||||
|
@ -172,5 +196,5 @@ formSchema = {
|
|||
notes: { type: 'string' }
|
||||
}
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
formSchema['nces_' + key] = type: 'string'
|
||||
|
|
|
@ -7,9 +7,9 @@ errors = require 'core/errors'
|
|||
User = require 'models/User'
|
||||
algolia = require 'core/services/algolia'
|
||||
|
||||
FORM_KEY = 'request-quote-form'
|
||||
SIGNUP_REDIRECT = '/teachers/classes'
|
||||
NCES_KEYS = ['id', 'name', 'district', 'district_id', 'district_schools', 'district_students', 'students', 'phone']
|
||||
DISTRICT_NCES_KEYS = ['district', 'district_id', 'district_schools', 'district_students', 'phone']
|
||||
SCHOOL_NCES_KEYS = DISTRICT_NCES_KEYS.concat(['id', 'name', 'students'])
|
||||
|
||||
module.exports = class CreateTeacherAccountView extends RootView
|
||||
id: 'create-teacher-account-view'
|
||||
|
@ -43,7 +43,7 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
super()
|
||||
|
||||
invalidateNCES: ->
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val ''
|
||||
|
||||
afterRender: ->
|
||||
|
@ -72,16 +72,34 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
"<div class='school'> #{hr.name.value} </div>" +
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="country"]').val 'USA'
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeForm()
|
||||
|
||||
$("#district-control").algolia_autocomplete({hint: false}, [
|
||||
source: (query, callback) ->
|
||||
algolia.schoolsIndex.search(query, { hitsPerPage: 5, aroundLatLngViaIP: false }).then (answer) ->
|
||||
callback answer.hits
|
||||
, ->
|
||||
callback []
|
||||
displayKey: 'district',
|
||||
templates:
|
||||
suggestion: (suggestion) ->
|
||||
hr = suggestion._highlightResult
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="organization"]').val '' # TODO: does not persist on tabbing: back to school, back to district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="country"]').val 'USA'
|
||||
for key in DISTRICT_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeForm()
|
||||
|
||||
onClickLoginLink: ->
|
||||
|
@ -101,6 +119,9 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
allAttrs = forms.formToObject(form)
|
||||
trialRequestAttrs = _.omit(allAttrs, 'name', 'password1', 'password2')
|
||||
|
||||
# Don't save n/a district entries, but do validate required district client-side
|
||||
trialRequestAttrs = _.omit(trialRequestAttrs, 'district') if trialRequestAttrs.district?.replace(/\s/ig, '').match(/n\/a/ig)
|
||||
|
||||
if @$('#other-education-level-checkbox').is(':checked')
|
||||
val = @$('#other-education-level-input').val()
|
||||
trialRequestAttrs.educationLevel.push(val) if val
|
||||
|
@ -112,18 +133,21 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
if not result.valid
|
||||
forms.applyErrorsToForm(form, result.errors)
|
||||
error = true
|
||||
if not forms.validateEmail(trialRequestAttrs.email)
|
||||
forms.setErrorToProperty(form, 'email', 'Invalid email.')
|
||||
if not error and not forms.validateEmail(trialRequestAttrs.email)
|
||||
forms.setErrorToProperty(form, 'email', 'invalid email')
|
||||
error = true
|
||||
if not _.size(trialRequestAttrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'Include at least one.')
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'include at least one')
|
||||
error = true
|
||||
unless allAttrs.district
|
||||
forms.setErrorToProperty(form, 'district', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
unless @gplusAttrs or @facebookAttrs
|
||||
if not allAttrs.password1
|
||||
forms.setErrorToProperty(form, 'password1', 'Required field')
|
||||
forms.setErrorToProperty(form, 'password1', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
else if not allAttrs.password2
|
||||
forms.setErrorToProperty(form, 'password2', 'Required field')
|
||||
forms.setErrorToProperty(form, 'password2', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
else if allAttrs.password1 isnt allAttrs.password2
|
||||
forms.setErrorToProperty(form, 'password1', 'Password fields are not equivalent')
|
||||
|
@ -225,7 +249,6 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
@$('input[type="password"]').attr('disabled', true)
|
||||
@$('#gplus-logged-in-row, #social-network-signups').toggleClass('hide')
|
||||
|
||||
|
||||
# Facebook signup
|
||||
|
||||
onClickFacebookSignupButton: ->
|
||||
|
@ -269,13 +292,9 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
@$('#facebook-logged-in-row, #social-network-signups').toggleClass('hide')
|
||||
|
||||
|
||||
|
||||
formSchema = {
|
||||
type: 'object'
|
||||
required: [
|
||||
'firstName', 'lastName', 'email', 'organization', 'role', 'numStudents', 'city'
|
||||
'state', 'country'
|
||||
]
|
||||
required: ['firstName', 'lastName', 'email', 'role', 'numStudents', 'city', 'state', 'country']
|
||||
properties:
|
||||
password1: { type: 'string' }
|
||||
password2: { type: 'string' }
|
||||
|
@ -286,6 +305,7 @@ formSchema = {
|
|||
phoneNumber: { type: 'string' }
|
||||
role: { type: 'string' }
|
||||
organization: { type: 'string' }
|
||||
district: { type: 'string' }
|
||||
city: { type: 'string' }
|
||||
state: { type: 'string' }
|
||||
country: { type: 'string' }
|
||||
|
@ -298,5 +318,5 @@ formSchema = {
|
|||
notes: { type: 'string' }
|
||||
}
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
formSchema['nces_' + key] = type: 'string'
|
||||
|
|
|
@ -8,7 +8,8 @@ ConfirmModal = require 'views/editor/modal/ConfirmModal'
|
|||
algolia = require 'core/services/algolia'
|
||||
|
||||
SIGNUP_REDIRECT = '/teachers'
|
||||
NCES_KEYS = ['id', 'name', 'district', 'district_id', 'district_schools', 'district_students', 'students', 'phone']
|
||||
DISTRICT_NCES_KEYS = ['district', 'district_id', 'district_schools', 'district_students', 'phone']
|
||||
SCHOOL_NCES_KEYS = DISTRICT_NCES_KEYS.concat(['id', 'name', 'students'])
|
||||
|
||||
module.exports = class RequestQuoteView extends RootView
|
||||
id: 'request-quote-view'
|
||||
|
@ -46,7 +47,7 @@ module.exports = class RequestQuoteView extends RootView
|
|||
super()
|
||||
|
||||
invalidateNCES: ->
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val ''
|
||||
|
||||
afterRender: ->
|
||||
|
@ -75,16 +76,34 @@ module.exports = class RequestQuoteView extends RootView
|
|||
"<div class='school'> #{hr.name.value} </div>" +
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="country"]').val 'USA'
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeRequestForm()
|
||||
|
||||
$("#district-control").algolia_autocomplete({hint: false}, [
|
||||
source: (query, callback) ->
|
||||
algolia.schoolsIndex.search(query, { hitsPerPage: 5, aroundLatLngViaIP: false }).then (answer) ->
|
||||
callback answer.hits
|
||||
, ->
|
||||
callback []
|
||||
displayKey: 'district',
|
||||
templates:
|
||||
suggestion: (suggestion) ->
|
||||
hr = suggestion._highlightResult
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="organization"]').val '' # TODO: does not persist on tabbing: back to school, back to district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="country"]').val 'USA'
|
||||
for key in DISTRICT_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeRequestForm()
|
||||
|
||||
onChangeRequestForm: ->
|
||||
|
@ -96,32 +115,39 @@ module.exports = class RequestQuoteView extends RootView
|
|||
e.preventDefault()
|
||||
form = @$('#request-form')
|
||||
attrs = forms.formToObject(form)
|
||||
trialRequestAttrs = _.cloneDeep(attrs)
|
||||
|
||||
# Don't save n/a district entries, but do validate required district client-side
|
||||
trialRequestAttrs = _.omit(trialRequestAttrs, 'district') if trialRequestAttrs.district?.replace(/\s/ig, '').match(/n\/a/ig)
|
||||
|
||||
# custom other input logic
|
||||
if @$('#other-education-level-checkbox').is(':checked')
|
||||
val = @$('#other-education-level-input').val()
|
||||
attrs.educationLevel.push(val) if val
|
||||
trialRequestAttrs.educationLevel.push(val) if val
|
||||
|
||||
forms.clearFormAlerts(form)
|
||||
requestFormSchema = if me.isAnonymous() then requestFormSchemaAnonymous else requestFormSchemaLoggedIn
|
||||
result = tv4.validateMultiple(attrs, requestFormSchemaAnonymous)
|
||||
result = tv4.validateMultiple(trialRequestAttrs, requestFormSchemaAnonymous)
|
||||
error = false
|
||||
if not result.valid
|
||||
forms.applyErrorsToForm(form, result.errors)
|
||||
error = true
|
||||
if not forms.validateEmail(attrs.email)
|
||||
forms.setErrorToProperty(form, 'email', 'Invalid email.')
|
||||
if not error and not forms.validateEmail(trialRequestAttrs.email)
|
||||
forms.setErrorToProperty(form, 'email', 'invalid email')
|
||||
error = true
|
||||
if not _.size(attrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'Include at least one.')
|
||||
if not _.size(trialRequestAttrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'include at least one')
|
||||
error = true
|
||||
unless attrs.district
|
||||
forms.setErrorToProperty(form, 'district', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
if error
|
||||
forms.scrollToFirstError()
|
||||
return
|
||||
attrs['siteOrigin'] = 'demo request'
|
||||
trialRequestAttrs['siteOrigin'] = 'demo request'
|
||||
@trialRequest = new TrialRequest({
|
||||
type: 'course'
|
||||
properties: attrs
|
||||
properties: trialRequestAttrs
|
||||
})
|
||||
if me.get('role') is 'student' and not me.isAnonymous()
|
||||
modal = new ConfirmModal({
|
||||
|
@ -262,7 +288,7 @@ module.exports = class RequestQuoteView extends RootView
|
|||
requestFormSchemaAnonymous = {
|
||||
type: 'object'
|
||||
required: [
|
||||
'firstName', 'lastName', 'email', 'organization', 'role', 'purchaserRole', 'numStudents',
|
||||
'firstName', 'lastName', 'email', 'role', 'purchaserRole', 'numStudents',
|
||||
'numStudentsTotal', 'phoneNumber', 'city', 'state', 'country']
|
||||
properties:
|
||||
firstName: { type: 'string' }
|
||||
|
@ -273,6 +299,7 @@ requestFormSchemaAnonymous = {
|
|||
role: { type: 'string' }
|
||||
purchaserRole: { type: 'string' }
|
||||
organization: { type: 'string' }
|
||||
district: { type: 'string' }
|
||||
city: { type: 'string' }
|
||||
state: { type: 'string' }
|
||||
country: { type: 'string' }
|
||||
|
@ -285,7 +312,7 @@ requestFormSchemaAnonymous = {
|
|||
notes: { type: 'string' },
|
||||
}
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
requestFormSchemaAnonymous['nces_' + key] = type: 'string'
|
||||
|
||||
# same form, but add username input
|
||||
|
|
|
@ -34,7 +34,8 @@ module.exports = class TeachersContactModal extends ModalView
|
|||
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.
|
||||
|
||||
Name of School/District: #{props.organization or ''}
|
||||
Name of School #{props.nces_name or props.organization or ''}
|
||||
Name of District: #{props.nces_district or props.district or ''}
|
||||
Role: #{props.role or ''}
|
||||
Phone Number: #{props.phoneNumber or ''}
|
||||
"""
|
||||
|
|
|
@ -16,7 +16,7 @@ if (process.argv.length !== 10) {
|
|||
// TODO: Cleanup country/status lookup code
|
||||
|
||||
// Save as custom fields instead of user-specific lead notes (also saving nces_ props)
|
||||
const commonTrialProperties = ['organization', 'city', 'state', 'country'];
|
||||
const commonTrialProperties = ['organization', 'district', 'city', 'state', 'country'];
|
||||
|
||||
// Old properties which are deprecated or moved
|
||||
const customFieldsToRemove = [
|
||||
|
@ -327,7 +327,7 @@ function findCocoLeads(done) {
|
|||
if (!trialRequest.properties || !trialRequest.properties.email) continue;
|
||||
const email = trialRequest.properties.email.toLowerCase();
|
||||
emails.push(email);
|
||||
const name = trialRequest.properties.nces_name || trialRequest.properties.organization || trialRequest.properties.school || email;
|
||||
const name = trialRequest.properties.nces_name || trialRequest.properties.organization || trialRequest.properties.school || trialRequest.properties.district || trialRequest.properties.nces_district || email;
|
||||
if (!leads[name]) leads[name] = new CocoLead(name);
|
||||
leads[name].addTrialRequest(email, trialRequest);
|
||||
emailLeadMap[email] = leads[name];
|
||||
|
|
|
@ -138,7 +138,7 @@ module.exports =
|
|||
trialRequests = yield TrialRequest.find({$and: [{type: 'course'}, {applicant: {$in: userIDs}}]}, {applicant: 1, properties: 1}).lean()
|
||||
schoolPrepaidsMap = {}
|
||||
for trialRequest in trialRequests
|
||||
school = trialRequest.properties?.organization ? trialRequest.properties?.school
|
||||
school = trialRequest.properties?.nces_name ? trialRequest.properties?.organization ? trialRequest.properties?.school
|
||||
continue unless school
|
||||
if userPrepaidsMap[trialRequest.applicant.valueOf()]?.length > 0
|
||||
schoolPrepaidsMap[school] ?= []
|
||||
|
|
|
@ -184,6 +184,7 @@ module.exports = {
|
|||
email: 'an@email.com'
|
||||
phoneNumber: '555-555-5555'
|
||||
organization: 'Greendale'
|
||||
district: 'Green District'
|
||||
}
|
||||
}, attrs)
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ describe 'ConvertToTeacherAccountView (/teachers/update-account)', ->
|
|||
phoneNumber: '555-555-5555'
|
||||
role: 'Teacher'
|
||||
organization: 'School'
|
||||
district: 'District'
|
||||
city: 'Springfield'
|
||||
state: 'AA'
|
||||
country: 'asdf'
|
||||
|
@ -168,3 +169,48 @@ describe 'ConvertToTeacherAccountView (/teachers/update-account)', ->
|
|||
})
|
||||
expect(me.get('role')).toBe(successForm.role.toLowerCase())
|
||||
|
||||
describe 'submitting the form without school', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include school setting', ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.organization).toBeUndefined()
|
||||
expect(attrs.properties?.district).toEqual('District')
|
||||
|
||||
describe 'submitting the form without district', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['district'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'displays a validation error on district and not school', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(true)
|
||||
|
||||
describe 'submitting the form district set to n/a', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
formData.district = 'N/A'
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include district setting', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(false)
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.district).toBeUndefined()
|
||||
|
|
|
@ -33,6 +33,7 @@ describe 'CreateTeacherAccountView', ->
|
|||
phoneNumber: '555-555-5555'
|
||||
role: 'Teacher'
|
||||
organization: 'School'
|
||||
district: 'District'
|
||||
city: 'Springfield'
|
||||
state: 'AA'
|
||||
country: 'asdf'
|
||||
|
@ -219,6 +220,8 @@ describe 'CreateTeacherAccountView', ->
|
|||
expect(attrs.password2).toBeUndefined()
|
||||
expect(attrs.name).toBeUndefined()
|
||||
expect(attrs.properties?.siteOrigin).toBe('create teacher')
|
||||
expect(attrs.properties?.organization).toEqual('School')
|
||||
expect(attrs.properties?.district).toEqual('District')
|
||||
|
||||
describe 'after saving the new trial request', ->
|
||||
beforeEach ->
|
||||
|
@ -267,4 +270,48 @@ describe 'CreateTeacherAccountView', ->
|
|||
view.$('#email-form-group .login-link').click()
|
||||
expect(view.openModalView).toHaveBeenCalled()
|
||||
|
||||
describe 'submitting the form without school', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include school setting', ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.organization).toBeUndefined()
|
||||
expect(attrs.properties?.district).toEqual('District')
|
||||
|
||||
describe 'submitting the form without district', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['district'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'displays a validation error on district and not school', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(true)
|
||||
|
||||
describe 'submitting the form district set to n/a', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
formData.district = 'N/A'
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include district setting', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(false)
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.district).toBeUndefined()
|
||||
|
|
|
@ -5,13 +5,14 @@ describe 'RequestQuoteView', ->
|
|||
|
||||
view = null
|
||||
|
||||
successFormValues = {
|
||||
successForm = {
|
||||
firstName: 'A'
|
||||
lastName: 'B'
|
||||
email: 'C@D.com'
|
||||
phoneNumber: '555-555-5555'
|
||||
role: 'Teacher'
|
||||
organization: 'School'
|
||||
district: 'District'
|
||||
city: 'Springfield'
|
||||
state: 'AA'
|
||||
country: 'asdf'
|
||||
|
@ -23,7 +24,7 @@ describe 'RequestQuoteView', ->
|
|||
|
||||
isSubmitRequest = (r) -> _.string.startsWith(r.url, '/db/trial.request') and r.method is 'POST'
|
||||
|
||||
describe 'when user is anonymous and has an existing trial request', ->
|
||||
describe 'when an anonymous user', ->
|
||||
beforeEach (done) ->
|
||||
me.clear()
|
||||
me.set('_id', '1234')
|
||||
|
@ -32,7 +33,10 @@ describe 'RequestQuoteView', ->
|
|||
view = new RequestQuoteView()
|
||||
view.render()
|
||||
jasmine.demoEl(view.$el)
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
describe 'has an existing trial request', ->
|
||||
beforeEach (done) ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({
|
||||
status: 200
|
||||
|
@ -50,43 +54,8 @@ describe 'RequestQuoteView', ->
|
|||
expect(view.$('#request-form').hasClass('hide')).toBe(true)
|
||||
expect(view.$('#form-submit-success').hasClass('hide')).toBe(false)
|
||||
|
||||
|
||||
describe 'when user is signed in and has an existing trial request', ->
|
||||
describe 'does NOT have an existing trial request', ->
|
||||
beforeEach (done) ->
|
||||
me.clear()
|
||||
me.set('_id', '1234')
|
||||
me._revertAttributes = {}
|
||||
spyOn(me, 'isAnonymous').and.returnValue(false)
|
||||
view = new RequestQuoteView()
|
||||
view.render()
|
||||
jasmine.demoEl(view.$el)
|
||||
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({
|
||||
status: 200
|
||||
responseText: JSON.stringify([{
|
||||
_id: '1'
|
||||
properties: {
|
||||
firstName: 'First'
|
||||
lastName: 'Last'
|
||||
}
|
||||
}])
|
||||
})
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
it 'shows form with data from the most recent request', ->
|
||||
expect(view.$('input[name="firstName"]').val()).toBe('First')
|
||||
|
||||
describe 'when a user is anonymous and does NOT have an existing trial request', ->
|
||||
beforeEach (done) ->
|
||||
me.clear()
|
||||
me.set('_id', '1234')
|
||||
me._revertAttributes = {}
|
||||
spyOn(me, 'isAnonymous').and.returnValue(true)
|
||||
view = new RequestQuoteView()
|
||||
view.render()
|
||||
jasmine.demoEl(view.$el)
|
||||
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({
|
||||
status: 200
|
||||
|
@ -108,12 +77,12 @@ describe 'RequestQuoteView', ->
|
|||
describe 'on successful form submit', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
forms.objectToForm(view.$el, successFormValues)
|
||||
forms.objectToForm(view.$el, successForm)
|
||||
view.$('#request-form').submit()
|
||||
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
@submitRequest.respondWith({
|
||||
status: 201
|
||||
responseText: JSON.stringify(_.extend({_id: 'a'}, successFormValues))
|
||||
responseText: JSON.stringify(_.extend({_id: 'a'}, successForm))
|
||||
})
|
||||
|
||||
it 'does not prevent navigating away', ->
|
||||
|
@ -167,10 +136,9 @@ describe 'RequestQuoteView', ->
|
|||
expect(request.method).toBe('PUT')
|
||||
expect(request.url).toBe('/db/user/1234')
|
||||
|
||||
describe 'when an anonymous user tries to submit a request with an existing user\'s email', ->
|
||||
|
||||
describe 'tries to submit a request with an existing user\'s email', ->
|
||||
beforeEach ->
|
||||
forms.objectToForm(view.$el, successFormValues)
|
||||
forms.objectToForm(view.$el, successForm)
|
||||
view.$('#request-form').submit()
|
||||
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
@submitRequest.respondWith({
|
||||
|
@ -182,15 +150,86 @@ describe 'RequestQuoteView', ->
|
|||
expect(view.$('#email-form-group').hasClass('has-error')).toBe(true)
|
||||
expect(view.$('#email-form-group .error-help-block').length).toBe(1)
|
||||
|
||||
describe 'when user is signed in and has role "student"', ->
|
||||
describe 'submits the form without school', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('#request-form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include school setting', ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.organization).toBeUndefined()
|
||||
expect(attrs.properties?.district).toEqual('District')
|
||||
|
||||
describe 'submits the form without district', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('#request-form')
|
||||
formData = _.omit(successForm, ['district'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'displays a validation error on district and not school', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(true)
|
||||
|
||||
describe 'submits form with district set to n/a', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('#request-form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
formData.district = 'N/A'
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include district setting', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(false)
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.district).toBeUndefined()
|
||||
|
||||
describe 'when a signed in user', ->
|
||||
beforeEach (done) ->
|
||||
me.set('role', 'student')
|
||||
me.set('name', 'Some User')
|
||||
me.clear()
|
||||
me.set('_id', '1234')
|
||||
me._revertAttributes = {}
|
||||
spyOn(me, 'isAnonymous').and.returnValue(false)
|
||||
view = new RequestQuoteView()
|
||||
view.render()
|
||||
jasmine.demoEl(view.$el)
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
describe 'has an existing trial request', ->
|
||||
beforeEach (done) ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({
|
||||
status: 200
|
||||
responseText: JSON.stringify([{
|
||||
_id: '1'
|
||||
properties: {
|
||||
firstName: 'First'
|
||||
lastName: 'Last'
|
||||
}
|
||||
}])
|
||||
})
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
it 'shows form with data from the most recent request', ->
|
||||
expect(view.$('input[name="firstName"]').val()).toBe('First')
|
||||
|
||||
describe 'has role "student"', ->
|
||||
beforeEach (done) ->
|
||||
me.clear()
|
||||
me.set('role', 'student')
|
||||
me.set('name', 'Some User')
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({ status: 200, responseText: '[]'})
|
||||
_.defer done # Let SuperModel finish
|
||||
|
@ -200,7 +239,7 @@ describe 'RequestQuoteView', ->
|
|||
|
||||
it 'requires confirmation to submit the form', ->
|
||||
form = view.$('#request-form')
|
||||
forms.objectToForm(form, successFormValues)
|
||||
forms.objectToForm(form, successForm)
|
||||
spyOn(view, 'openModalView')
|
||||
form.submit()
|
||||
expect(view.openModalView).toHaveBeenCalled()
|
||||
|
@ -211,5 +250,3 @@ describe 'RequestQuoteView', ->
|
|||
confirmModal.trigger 'confirm'
|
||||
submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
expect(submitRequest).toBeTruthy()
|
||||
|
||||
|
Loading…
Reference in a new issue