mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-12 00:31:21 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
8baa57748a
37 changed files with 4888 additions and 619 deletions
|
@ -45,7 +45,7 @@ module.exports.applyErrorsToForm = (el, errors, warning=false) ->
|
||||||
for error in errors
|
for error in errors
|
||||||
if error.code is tv4.errorCodes.OBJECT_REQUIRED
|
if error.code is tv4.errorCodes.OBJECT_REQUIRED
|
||||||
prop = _.last(_.string.words(error.message)) # hack
|
prop = _.last(_.string.words(error.message)) # hack
|
||||||
message = 'Required field'
|
message = $.i18n.t('common.required_field')
|
||||||
|
|
||||||
else if error.dataPath
|
else if error.dataPath
|
||||||
prop = error.dataPath[1..]
|
prop = error.dataPath[1..]
|
||||||
|
|
|
@ -22,6 +22,9 @@ LOG = false
|
||||||
# * Sprite map generation
|
# * Sprite map generation
|
||||||
# * Connecting to Firebase
|
# * Connecting to Firebase
|
||||||
|
|
||||||
|
# LevelLoader depends on SuperModel retrying timed out requests, as these occasionally happen during play.
|
||||||
|
# If LevelLoader ever moves away from SuperModel, it will have to manage its own retries.
|
||||||
|
|
||||||
module.exports = class LevelLoader extends CocoClass
|
module.exports = class LevelLoader extends CocoClass
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
|
|
|
@ -356,7 +356,7 @@
|
||||||
submit_patch: "Submit Patch"
|
submit_patch: "Submit Patch"
|
||||||
submit_changes: "Submit Changes"
|
submit_changes: "Submit Changes"
|
||||||
save_changes: "Save Changes"
|
save_changes: "Save Changes"
|
||||||
required_field: "Required field"
|
required_field: "required" # {change}
|
||||||
|
|
||||||
general:
|
general:
|
||||||
and: "and"
|
and: "and"
|
||||||
|
@ -885,7 +885,9 @@
|
||||||
evaluate_recommend: "Evaluate/Recommend"
|
evaluate_recommend: "Evaluate/Recommend"
|
||||||
approve_funds: "Approve Funds"
|
approve_funds: "Approve Funds"
|
||||||
no_purchaser_role: "No role in purchase decisions"
|
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"
|
city: "City"
|
||||||
state: "State"
|
state: "State"
|
||||||
country: "Country"
|
country: "Country"
|
||||||
|
|
2019
app/locale/hr.coffee
Normal file
2019
app/locale/hr.coffee
Normal file
File diff suppressed because it is too large
Load diff
|
@ -39,8 +39,10 @@ module.exports =
|
||||||
'id': { nativeDescription: 'Bahasa Indonesia', englishDescription: 'Indonesian' }
|
'id': { nativeDescription: 'Bahasa Indonesia', englishDescription: 'Indonesian' }
|
||||||
'it': { nativeDescription: 'Italiano', englishDescription: 'Italian' }
|
'it': { nativeDescription: 'Italiano', englishDescription: 'Italian' }
|
||||||
'he': { nativeDescription: 'עברית', englishDescription: 'Hebrew' }
|
'he': { nativeDescription: 'עברית', englishDescription: 'Hebrew' }
|
||||||
|
'hr': { nativeDescription: 'hrvatski jezik', englishDescription: 'Croatian' }
|
||||||
'hu': { nativeDescription: 'magyar', englishDescription: 'Hungarian' }
|
'hu': { nativeDescription: 'magyar', englishDescription: 'Hungarian' }
|
||||||
'lt': { nativeDescription: 'lietuvių kalba', englishDescription: 'Lithuanian' }
|
'lt': { nativeDescription: 'lietuvių kalba', englishDescription: 'Lithuanian' }
|
||||||
|
'mi': { nativeDescription: 'te reo Māori', englishDescription: 'Māori' }
|
||||||
'mk-MK': { nativeDescription: 'Македонски', englishDescription: 'Macedonian' }
|
'mk-MK': { nativeDescription: 'Македонски', englishDescription: 'Macedonian' }
|
||||||
'hi': { nativeDescription: 'मानक हिन्दी', englishDescription: 'Hindi' }
|
'hi': { nativeDescription: 'मानक हिन्दी', englishDescription: 'Hindi' }
|
||||||
'ms': { nativeDescription: 'Bahasa Melayu', englishDescription: 'Bahasa Malaysia' }
|
'ms': { nativeDescription: 'Bahasa Melayu', englishDescription: 'Bahasa Malaysia' }
|
||||||
|
|
2019
app/locale/mi.coffee
Normal file
2019
app/locale/mi.coffee
Normal file
File diff suppressed because it is too large
Load diff
|
@ -132,7 +132,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
help_suff: "и мы свяжемся!"
|
help_suff: "и мы свяжемся!"
|
||||||
|
|
||||||
modal:
|
modal:
|
||||||
# cancel: "Cancel"
|
cancel: "Отмена"
|
||||||
close: "Закрыть"
|
close: "Закрыть"
|
||||||
okay: "OK"
|
okay: "OK"
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
None: "значение, которое не указывает ни на один объект (ничто)"
|
None: "значение, которое не указывает ни на один объект (ничто)"
|
||||||
|
|
||||||
share_progress_modal:
|
share_progress_modal:
|
||||||
blurb: "Вы отлично продвигаетесь! Расскажите своим родителям, как много вы уже выучили с CodeCombat."
|
blurb: "Вы показываете отличные результаты! Расскажите своим родителям, как много вы уже выучили с CodeCombat."
|
||||||
email_invalid: "Email-адрес некорректен."
|
email_invalid: "Email-адрес некорректен."
|
||||||
form_blurb: "Введите их email-адреса ниже, и мы покажем им!"
|
form_blurb: "Введите их email-адреса ниже, и мы покажем им!"
|
||||||
form_label: "Email-адрес"
|
form_label: "Email-адрес"
|
||||||
|
@ -243,9 +243,9 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
|
|
||||||
login:
|
login:
|
||||||
sign_up: "Создать аккаунт"
|
sign_up: "Создать аккаунт"
|
||||||
# email_or_username: "Email or username"
|
email_or_username: "Email или имя пользователя"
|
||||||
log_in: "Войти"
|
log_in: "Войти"
|
||||||
logging_in: "Вход..."
|
logging_in: "Входим..."
|
||||||
log_out: "Выйти"
|
log_out: "Выйти"
|
||||||
forgot_password: "Забыли пароль?"
|
forgot_password: "Забыли пароль?"
|
||||||
authenticate_gplus: "Аутентификация G+"
|
authenticate_gplus: "Аутентификация G+"
|
||||||
|
@ -256,72 +256,72 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
signup_switch: "Хотите создать аккаунт?"
|
signup_switch: "Хотите создать аккаунт?"
|
||||||
|
|
||||||
signup:
|
signup:
|
||||||
# create_student_header: "Create Student Account"
|
create_student_header: "Создать учетную запись Ученика"
|
||||||
# create_teacher_header: "Create Teacher Account"
|
create_teacher_header: "Создать учетную запись Учителя"
|
||||||
# create_individual_header: "Create Individual Account"
|
create_individual_header: "Создать личную учетную запись"
|
||||||
# create_header: "Create Account"
|
create_header: "Создать учетную запись"
|
||||||
email_announcements: "Получать оповещения по email" # {change}
|
email_announcements: "Получать оповещения по email о новых уровнях и возможностях на CodeCombat"
|
||||||
creating: "Создание аккаунта..."
|
creating: "Создаем учетную запись..."
|
||||||
# create_account: "Create Account"
|
create_account: "Создать учетную запись"
|
||||||
sign_up: "Регистрация"
|
sign_up: "Регистрация"
|
||||||
log_in: "вход с паролем"
|
log_in: "вход с паролем"
|
||||||
required: "Войдите для того, чтобы продолжить."
|
required: "Войдите для того, чтобы продолжить."
|
||||||
login_switch: "Уже есть аккаунт?"
|
login_switch: "Уже есть учетная запись?"
|
||||||
school_name: "Название школы and город"
|
school_name: "Название школы и город"
|
||||||
optional: "не обязательно"
|
optional: "не обязательно"
|
||||||
school_name_placeholder: "Школа № 2, город Электросталь, Московская область"
|
school_name_placeholder: "Школа № 2, город Электросталь, Московская область"
|
||||||
# connect_with: "Connect with:"
|
connect_with: "Зарегистрироваться с помощью:"
|
||||||
connected_gplus_header: "Вы успешно авторизовались через Google+!"
|
connected_gplus_header: "Вы успешно авторизовались через Google+!"
|
||||||
connected_gplus_p: "Теперь можно войти используя аккаунт Google+."
|
connected_gplus_p: "Теперь можно войти используя аккаунт Google+."
|
||||||
gplus_exists: "У вас уже имеется аккаунт связанный с Google+!"
|
gplus_exists: "У вас уже имеется аккаунт связанный с Google+!"
|
||||||
connected_facebook_header: "Вы успешно авторизовались через Facebook!"
|
connected_facebook_header: "Вы успешно авторизовались через Facebook!"
|
||||||
connected_facebook_p: "Теперь можно войти используя аккаунт Facebook."
|
connected_facebook_p: "Теперь можно войти используя аккаунт Facebook."
|
||||||
facebook_exists: "У вас уже имеется аккаунт связанный сh Facebook!"
|
facebook_exists: "У вас уже имеется аккаунт связанный с Facebook!"
|
||||||
hey_students: "Студенты, введите код от класса вашего учителя."
|
hey_students: "Студенты, введите код от класса вашего учителя."
|
||||||
# birthday: "Birthday"
|
birthday: "День рождения"
|
||||||
# parent_email_blurb: "We know you can't wait to learn programming — we're excited too! Your parents will receive an email with further instructions on how to create an account for you. Email {{email_link}} if you have any questions."
|
parent_email_blurb: "Мы знаем что вы в нетерпении начать учиться программировать — мы тоже! Ваши родители получат письмо с дальнейшими инструкциями, как создать учетную запись. Пишите нам на email {{email_link}} если есть любые вопросы."
|
||||||
# classroom_not_found: "No classes exist with this Class Code. Check your spelling or ask your teacher for help."
|
classroom_not_found: "Нет класса с таким кодом. Проверьте написание или попросите учителя помочь."
|
||||||
# checking: "Checking..."
|
checking: "Проверяем..."
|
||||||
# account_exists: "This email is already in use:" # {change}
|
account_exists: "Этот email-адрес уже используется:" # {change}
|
||||||
# sign_in: "Sign in"
|
sign_in: "Зарегистрироваться"
|
||||||
# email_good: "Email looks good!"
|
email_good: "С email-адресом все в порядке!"
|
||||||
# name_taken: "Username already taken! Try {{suggestedName}}?"
|
name_taken: "Имя пользователя уже используется! Может {{suggestedName}}?"
|
||||||
# name_available: "Username available!"
|
name_available: "Имя пользователя доступно!"
|
||||||
# name_is_email: "Username may not be an email"
|
name_is_email: "Имя пользователя не должно быть email-адресом"
|
||||||
# choose_type: "Choose your account type:"
|
choose_type: "Выбирите тип учетной записи:"
|
||||||
# teacher_type_1: "Teach programming using CodeCombat!"
|
teacher_type_1: "Обучайте с помощью CodeCombat!"
|
||||||
# teacher_type_2: "Set up your class"
|
teacher_type_2: "Настраивайте ваш класс"
|
||||||
# teacher_type_3: "Access Course Guides"
|
teacher_type_3: "Получите доступ к учебным материалам "
|
||||||
# teacher_type_4: "View student progress"
|
teacher_type_4: "Следите за прогрессом учеников"
|
||||||
# signup_as_teacher: "Sign up as a Teacher"
|
signup_as_teacher: "Зарегистрироваться как Учитель"
|
||||||
# student_type_1: "Learn to program while playing an engaging game!"
|
student_type_1: "Учитесь программировать, пока играете в захватывающую игру!"
|
||||||
# student_type_2: "Play with your class"
|
student_type_2: "Играйте вместе с классом"
|
||||||
# student_type_3: "Compete in arenas"
|
student_type_3: "Соревнуйтесь на аренах"
|
||||||
# student_type_4: "Choose your hero!"
|
student_type_4: "Выбирайте своего героя!"
|
||||||
# student_type_5: "Have your Class Code ready!"
|
student_type_5: "Нужен актуальный код для класса!"
|
||||||
# signup_as_student: "Sign up as a Student"
|
signup_as_student: "Зарегистрироваться как Ученик"
|
||||||
# individuals_or_parents: "Individuals & Parents"
|
individuals_or_parents: "Индивидуальный и Родители"
|
||||||
# individual_type: "For players learning to code outside of a class. Parents should sign up for an account here."
|
individual_type: "Для игроков, которые учатся без класса. Родители должны создать учетную запись."
|
||||||
# signup_as_individual: "Sign up as an Individual"
|
signup_as_individual: "Зарегистрироваться как индивидуальный игрок"
|
||||||
# enter_class_code: "Enter your Class Code"
|
enter_class_code: "Введите ваш код для класса"
|
||||||
# enter_birthdate: "Enter your birthdate:"
|
enter_birthdate: "Введите вашу дату рождения:"
|
||||||
# ask_teacher_1: "Ask your teacher for your Class Code."
|
ask_teacher_1: "Спросите вашего учителя код для класса."
|
||||||
# ask_teacher_2: "Not part of a class? Create an "
|
ask_teacher_2: "Не относишься к учебному классу? Создай "
|
||||||
# ask_teacher_3: "Individual Account"
|
ask_teacher_3: "Личную учетную запись"
|
||||||
# ask_teacher_4: " instead."
|
ask_teacher_4: " вместо этого."
|
||||||
# about_to_join: "You're about to join:"
|
about_to_join: "Вы присоединяетесь к:"
|
||||||
# enter_parent_email: "Enter your parent’s email address:"
|
enter_parent_email: "Введите email-адрес одного из родителей:"
|
||||||
# parent_email_error: "Something went wrong when trying to send the email. Check the email address and try again."
|
parent_email_error: "Что-то пошло не так, когда мы отправляли письмо. Проверьте email-адрес и повторите."
|
||||||
# parent_email_sent: "We’ve sent an email with further instructions on how to create an account. Ask your parent to check their inbox."
|
parent_email_sent: "Мы послали электронное письмо с дальнейшими инструкциями, как создать учетную запись. Попроси родителей проверить их входящие письма."
|
||||||
# account_created: "Account Created!"
|
account_created: "Учетная запись создана!"
|
||||||
# confirm_student_blurb: "Write down your information so that you don't forget it. Your teacher can also help you reset your password at any time."
|
confirm_student_blurb: "Запишите ваши данные, чтобы не забыть их. Ваш учитель, если что сможет помочь сбросить пароль в любое время."
|
||||||
# confirm_individual_blurb: "Write down your login information in case you need it later. Verify your email so you can recover your account if you ever forget your password - check your inbox!"
|
confirm_individual_blurb: "Write down your login information in case you need it later. Verify your email so you can recover your account if you ever forget your password - check your inbox!"
|
||||||
# write_this_down: "Write this down:"
|
write_this_down: "Запишите это:"
|
||||||
# start_playing: "Start Playing!"
|
start_playing: "Начать играть!"
|
||||||
# sso_connected: "Successfully connected with:"
|
sso_connected: "Успешно подключились с помощью:"
|
||||||
|
|
||||||
recover:
|
recover:
|
||||||
recover_account_title: "Восстановить аккаунт"
|
recover_account_title: "Восстановить учетную запись"
|
||||||
send_password: "Отправить пароль для восстановления"
|
send_password: "Отправить пароль для восстановления"
|
||||||
recovery_sent: "Письмо с паролем отправлено."
|
recovery_sent: "Письмо с паролем отправлено."
|
||||||
|
|
||||||
|
@ -340,8 +340,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
saving: "Сохранение..."
|
saving: "Сохранение..."
|
||||||
sending: "Отправка..."
|
sending: "Отправка..."
|
||||||
send: "Отправить"
|
send: "Отправить"
|
||||||
# sent: "Sent"
|
sent: "Отправлено"
|
||||||
# type: "Type"
|
type: "Тип"
|
||||||
cancel: "Отмена"
|
cancel: "Отмена"
|
||||||
save: "Сохранить"
|
save: "Сохранить"
|
||||||
publish: "Опубликовать"
|
publish: "Опубликовать"
|
||||||
|
@ -411,8 +411,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
wizard: "Волшебник"
|
wizard: "Волшебник"
|
||||||
first_name: "Имя"
|
first_name: "Имя"
|
||||||
last_name: "Фамилия"
|
last_name: "Фамилия"
|
||||||
# last_initial: "Last Initial"
|
last_initial: "Инициалы фамилии"
|
||||||
username: "Имя юзера"
|
username: "Имя пользователя"
|
||||||
|
|
||||||
units:
|
units:
|
||||||
second: "секунда"
|
second: "секунда"
|
||||||
|
@ -431,13 +431,13 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
years: "лет"
|
years: "лет"
|
||||||
|
|
||||||
play_level:
|
play_level:
|
||||||
level_complete: "Уровень завершен"
|
level_complete: "Уровень пройден"
|
||||||
completed_level: "Завершённый уровень:"
|
completed_level: "Пройденный уровень:"
|
||||||
course: "Курс:"
|
course: "Курс:"
|
||||||
done: "Готово"
|
done: "Готово"
|
||||||
next_level: "Следующий уровень"
|
next_level: "Следующий уровень"
|
||||||
next_game: "Следующая игра"
|
next_game: "Следующая игра"
|
||||||
# programming_language: "Programming language"
|
programming_language: "Язык программирования"
|
||||||
show_menu: "Показать меню игры"
|
show_menu: "Показать меню игры"
|
||||||
home: "На главную" # Not used any more, will be removed soon.
|
home: "На главную" # Not used any more, will be removed soon.
|
||||||
level: "Уровень" # Like "Level: Dungeons of Kithgard"
|
level: "Уровень" # Like "Level: Dungeons of Kithgard"
|
||||||
|
@ -458,12 +458,12 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
reload_confirm: "Перезагрузить всё"
|
reload_confirm: "Перезагрузить всё"
|
||||||
victory: "Победа"
|
victory: "Победа"
|
||||||
victory_title_prefix: "Уровень "
|
victory_title_prefix: "Уровень "
|
||||||
victory_title_suffix: " завершён"
|
victory_title_suffix: " пройден"
|
||||||
victory_sign_up: "Зарегистрируйтесь, чтобы сохранить прогресс"
|
victory_sign_up: "Зарегистрируйтесь, чтобы сохранить прогресс"
|
||||||
victory_sign_up_poke: "Хотите сохранить ваш код? Создайте бесплатный аккаунт!"
|
victory_sign_up_poke: "Хотите сохранить ваш код? Создайте бесплатную учетную запись!"
|
||||||
victory_rate_the_level: "Оцените уровень:" # {change}
|
victory_rate_the_level: "Оцените уровень:" # {change}
|
||||||
victory_return_to_ladder: "Вернуться к ладдеру"
|
victory_return_to_ladder: "Вернуться к таблице"
|
||||||
victory_saving_progress: "Процесс сохранения"
|
victory_saving_progress: "Сохранить прогресс"
|
||||||
victory_go_home: "На главную"
|
victory_go_home: "На главную"
|
||||||
victory_review: "Расскажите нам больше!"
|
victory_review: "Расскажите нам больше!"
|
||||||
victory_review_placeholder: "Как вам уровень?"
|
victory_review_placeholder: "Как вам уровень?"
|
||||||
|
@ -474,13 +474,13 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
victory_new_item: "Новый предмет"
|
victory_new_item: "Новый предмет"
|
||||||
victory_viking_code_school: "Ого, это было тяжелый уровень! Если вы еще не разработчик программ, вам стоит им стать. Вы только что ускорири принятие в Школу Викингов, где вы сможете поднять свои навыки на новый уровень и стать профессиональным веб-разработчиком за 14 недель."
|
victory_viking_code_school: "Ого, это было тяжелый уровень! Если вы еще не разработчик программ, вам стоит им стать. Вы только что ускорири принятие в Школу Викингов, где вы сможете поднять свои навыки на новый уровень и стать профессиональным веб-разработчиком за 14 недель."
|
||||||
victory_become_a_viking: "Станьте Викингом"
|
victory_become_a_viking: "Станьте Викингом"
|
||||||
victory_no_progress_for_teachers: "Прогресс не сохраняется для учителей. Но, вы можете для себя добавить аккаунт студента в свою классную комнату."
|
victory_no_progress_for_teachers: "Прогресс не сохраняется для учителей. Но, вы можете для себя добавить учетную запись ученика в свою классную комнату."
|
||||||
guide_title: "Руководство"
|
guide_title: "Руководство"
|
||||||
tome_cast_button_run: "Запустить"
|
tome_cast_button_run: "Запустить"
|
||||||
tome_cast_button_running: "В процессе"
|
tome_cast_button_running: "В процессе"
|
||||||
tome_cast_button_ran: "Запущен"
|
tome_cast_button_ran: "Запущен"
|
||||||
tome_submit_button: "Завершить"
|
tome_submit_button: "Завершить"
|
||||||
tome_reload_method: "Загрузить оригинальный код для этого метода" # {change}
|
tome_reload_method: "Загрузить оригинальный код и начать уровень заново" # {change}
|
||||||
tome_available_spells: "Доступные заклинания"
|
tome_available_spells: "Доступные заклинания"
|
||||||
tome_your_skills: "Ваши навыки"
|
tome_your_skills: "Ваши навыки"
|
||||||
tome_current_method: "Текущий метод"
|
tome_current_method: "Текущий метод"
|
||||||
|
@ -491,13 +491,13 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
keyboard_shortcuts: "Горячие клавиши"
|
keyboard_shortcuts: "Горячие клавиши"
|
||||||
loading_ready: "Готово!"
|
loading_ready: "Готово!"
|
||||||
loading_start: "Начать уровень"
|
loading_start: "Начать уровень"
|
||||||
problem_alert_title: "Исправьте ваш Код"
|
problem_alert_title: "Исправьте код"
|
||||||
time_current: "Текущее:"
|
time_current: "Текущее:"
|
||||||
time_total: "Максимальное:"
|
time_total: "Максимальное:"
|
||||||
time_goto: "Перейти на:"
|
time_goto: "Перейти на:"
|
||||||
non_user_code_problem_title: "Невозможно загрузить уровень"
|
non_user_code_problem_title: "Невозможно загрузить уровень"
|
||||||
infinite_loop_title: "Обнаружен бесконечный цикл"
|
infinite_loop_title: "Обнаружен бесконечный цикл"
|
||||||
infinite_loop_description: "Код сотворения мира не завершил выполнение. Это могло случиться из-за реально медленного кода или наличия бесконечного цикла. Или там может быть баг. Вы можете попытаться запустить этот код еще раз или сбросить код в состояние по умолчанию. Если проблема не будет решена, дайте нам знать."
|
infinite_loop_description: "Код сотворения мира не завершил выполнение. Это могло случиться из-за очень медленного кода или наличия бесконечного цикла. Или там может быть баг. Вы можете попытаться запустить этот код еще раз или сбросить код в состояние по умолчанию. Если проблема не будет решена, дайте нам знать."
|
||||||
check_dev_console: "Вы так же можете открыть консоль разработчика, чтобы увидеть, что может идти не так."
|
check_dev_console: "Вы так же можете открыть консоль разработчика, чтобы увидеть, что может идти не так."
|
||||||
check_dev_console_link: "(инструкции)"
|
check_dev_console_link: "(инструкции)"
|
||||||
infinite_loop_try_again: "Попробовать снова"
|
infinite_loop_try_again: "Попробовать снова"
|
||||||
|
@ -542,32 +542,32 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
tip_optimization_operator: "В каждом языке есть оператор оптимизации. В большинстве языков это оператор ‘//’"
|
tip_optimization_operator: "В каждом языке есть оператор оптимизации. В большинстве языков это оператор ‘//’"
|
||||||
tip_lines_of_code: "Измерение прогресса программирования в строках кода - это как измерять прогресс построения самолета по его весу. — Bill Gates"
|
tip_lines_of_code: "Измерение прогресса программирования в строках кода - это как измерять прогресс построения самолета по его весу. — Bill Gates"
|
||||||
tip_source_code: "Я хочу изменить мир, но они вряд ли дадут мне исходники."
|
tip_source_code: "Я хочу изменить мир, но они вряд ли дадут мне исходники."
|
||||||
tip_javascript_java: "Java к JavaScript относится так же, как кол относится к колготкам. - Chris Heilmann (перефраз.)"
|
tip_javascript_java: "Java к JavaScript относится так же, как кол относится к колготкам. (перефраз.) - Крис Хейльман"
|
||||||
tip_move_forward: "Что бы вы ни делали, вы должны двигаться вперед. - Martin Luther King Jr"
|
tip_move_forward: "Что бы вы ни делали, вы должны двигаться вперед. - Мартин Лютер Кинг Мл."
|
||||||
tip_google: "У вас проблема, которую вы не можете решить? Гуглите!"
|
tip_google: "У вас проблема, которую вы не можете решить? Гуглите!"
|
||||||
tip_adding_evil: "Добавим щепотку зла."
|
tip_adding_evil: "Добавим щепотку зла."
|
||||||
tip_hate_computers: "Есть одна вещь в людях, которые думают, что они ненавидят компьютеры. Что они на самом деле ненавидят, так это плохих программистов. - Larry Niven"
|
tip_hate_computers: "Есть одна вещь в людях, которые думают, что они ненавидят компьютеры. Что они на самом деле ненавидят, так это плохих программистов. - Ларри Нивен"
|
||||||
tip_open_source_contribute: "Вы можете помочь сделать CodeCombat лучше!"
|
tip_open_source_contribute: "Ты можешь помочь сделать CodeCombat лучше!"
|
||||||
tip_recurse: "Итерация свойственна человеку, рекурсия божественна. - L. Peter Deutsch"
|
tip_recurse: "Итерация свойственна человеку, рекурсия божественна. - L. Peter Deutsch"
|
||||||
tip_free_your_mind: "Отвлекись от всего, Нео. Страх, неверие, сомнения отбрось — очисти свой разум. - Morpheus"
|
tip_free_your_mind: "Отвлекись от всего, Нео. Страх, неверие, сомнения отбрось — очисти свой разум. - Морфей"
|
||||||
tip_strong_opponents: "Даже сильнейший противник имеет слабость. - Itachi Uchiha"
|
tip_strong_opponents: "Даже сильнейший противник имеет слабость. - Итачи Учиха"
|
||||||
tip_paper_and_pen: "Прежде чем начать программировать, вы всегда можете попробовать с листом бумаги и ручкой."
|
tip_paper_and_pen: "Прежде чем начать программировать, вы всегда можете попробовать с листом бумаги и ручкой."
|
||||||
tip_solve_then_write: "Сперва реши задачу, затем пиши код. - Джон Джонсон"
|
tip_solve_then_write: "Сперва реши задачу, затем пиши код. - Джон Джонсон"
|
||||||
tip_compiler_ignores_comments: "Порой мне кажется, что компилятор игнорирует мои комментарии."
|
tip_compiler_ignores_comments: "Порой мне кажется, что компилятор игнорирует мои комментарии."
|
||||||
tip_understand_recursion: "Единственный способ понять рекурсию, это понять рекурсию."
|
tip_understand_recursion: "Единственный способ понять рекурсию, это понять рекурсию."
|
||||||
tip_life_and_polymorphism: "Открытый исходный код это как полоностью полиморфная гетерогенная структура: Все типы приветствуются."
|
tip_life_and_polymorphism: "Открытый исходный код это как полоностью полиморфная гетерогенная структура: Все типы приветствуются."
|
||||||
tip_mistakes_proof_of_trying: "Ошибка в коде подтвердила твои старания."
|
tip_mistakes_proof_of_trying: "Ошибка в коде подтвердила твои старания."
|
||||||
# tip_adding_orgres: "Rounding up ogres."
|
tip_adding_orgres: "Собираем огров."
|
||||||
# tip_sharpening_swords: "Sharpening the swords."
|
tip_sharpening_swords: "Точим мечи."
|
||||||
# tip_ratatouille: "You must not let anyone define your limits because of where you come from. Your only limit is your soul. - Gusteau, Ratatouille"
|
# tip_ratatouille: "You must not let anyone define your limits because of where you come from. Your only limit is your soul. - Gusteau, Ratatouille"
|
||||||
# tip_nemo: "When life gets you down, want to know what you've gotta do? Just keep swimming, just keep swimming. - Dory, Finding Nemo"
|
# tip_nemo: "When life gets you down, want to know what you've gotta do? Just keep swimming, just keep swimming. - Dory, Finding Nemo"
|
||||||
# tip_internet_weather: "Just move to the internet, it's great here. We get to live inside where the weather is always awesome. - John Green"
|
# tip_internet_weather: "Just move to the internet, it's great here. We get to live inside where the weather is always awesome. - John Green"
|
||||||
# tip_nerds: "Nerds are allowed to love stuff, like jump-up-and-down-in-the-chair-can't-control-yourself love it. - John Green"
|
# tip_nerds: "Nerds are allowed to love stuff, like jump-up-and-down-in-the-chair-can't-control-yourself love it. - John Green"
|
||||||
# tip_self_taught: "I taught myself 90% of what I've learned. And that's normal! - Hank Green"
|
tip_self_taught: "Я самостоятельно научился 90% из того чему учился. И это нормально! - Хэнк Грин"
|
||||||
# tip_luna_lovegood: "Don't worry, you're just as sane as I am. - Luna Lovegood"
|
tip_luna_lovegood: "Не переживай, ты также в своем уме, как и я. - Луна Лавгуд"
|
||||||
# tip_good_idea: "The best way to have a good idea is to have a lot of ideas. - Linus Pauling"
|
tip_good_idea: "Лучший способ найти хорошую идею - иметь множество идей. - Линус Полинг"
|
||||||
# tip_programming_not_about_computers: "Computer Science is no more about computers than astronomy is about telescopes. - Edsger Dijkstra"
|
# tip_programming_not_about_computers: "Computer Science is no more about computers than astronomy is about telescopes. - Edsger Dijkstra"
|
||||||
# tip_mulan: "Believe you can, then you will. - Mulan"
|
tip_mulan: "Верь, что можешь и получится. - Мулан"
|
||||||
|
|
||||||
game_menu:
|
game_menu:
|
||||||
inventory_tab: "Инвентарь"
|
inventory_tab: "Инвентарь"
|
||||||
|
@ -694,7 +694,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
javascript_blurb: "Язык для Сети."
|
javascript_blurb: "Язык для Сети."
|
||||||
coffeescript_blurb: "Улучшенный синтаксис JavaScript."
|
coffeescript_blurb: "Улучшенный синтаксис JavaScript."
|
||||||
lua_blurb: "Скриптовый язык для игр."
|
lua_blurb: "Скриптовый язык для игр."
|
||||||
# java_blurb: "(Subscriber Only) Android and enterprise."
|
java_blurb: "(только для подписчиков) Андроид и бизнес."
|
||||||
status: "Статус"
|
status: "Статус"
|
||||||
hero_type: "Тип"
|
hero_type: "Тип"
|
||||||
weapons: "Оружие"
|
weapons: "Оружие"
|
||||||
|
@ -705,7 +705,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
health: "Жизнь"
|
health: "Жизнь"
|
||||||
speed: "Скорость"
|
speed: "Скорость"
|
||||||
regeneration: "Регенерация"
|
regeneration: "Регенерация"
|
||||||
range: "Зона" # As in "attack or visual range"
|
range: "Дальность" # As in "attack or visual range"
|
||||||
blocks: "Блокирует" # As in "this shield blocks this much damage"
|
blocks: "Блокирует" # As in "this shield blocks this much damage"
|
||||||
backstab: "Со спины" # As in "this dagger does this much backstab damage"
|
backstab: "Со спины" # As in "this dagger does this much backstab damage"
|
||||||
skills: "Умения"
|
skills: "Умения"
|
||||||
|
@ -775,32 +775,33 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
||||||
story_link: "История"
|
story_link: "История"
|
||||||
press_link: "Прессе"
|
press_link: "Прессе"
|
||||||
mission_title: "Наша задача: сделать доступным программирование для каждого учащегося на земле."
|
mission_title: "Наша задача: сделать доступным программирование для каждого учащегося на земле."
|
||||||
# mission_description_1: "<strong>Programming is magic</strong>. It's the ability to create things from pure imagination. We started CodeCombat to give learners the feeling of wizardly power at their fingertips by using <strong>typed code</strong>."
|
mission_description_1: "<strong>Программирование - это магия</strong>.
|
||||||
# mission_description_2: "As it turns out, that enables them to learn faster too. WAY faster. It's like having a conversation instead of reading a manual. We want to bring that conversation to every school and to <strong>every student</strong>, because everyone should have the chance to learn the magic of programming."
|
Это способность создавать что-то с помощью воображения. Мы создавали CodeCombat, чтобы дать учащимся чувство силы волшебства на кончиках пальцев, когда они <strong>пишут код</strong>."
|
||||||
|
mission_description_2: "Как оказалось, это позволяет им учится быстрее. СИЛЬНО быстрее. Это как живой рассказ вместо чтения учебника. Мы хотим принести этот метод в каждую школу и <strong>каждому ученику</strong>, потому что все должны иметь шанс научится магии программирования."
|
||||||
team_title: "Присоединяйтесь к команде CodeCombat"
|
team_title: "Присоединяйтесь к команде CodeCombat"
|
||||||
# team_values: "We value open and respectful dialog, where the best idea wins. Our decisions are grounded in customer research and our process is focused on delivering tangible results for them. Everyone is hands-on, from our CEO to our GitHub contributors, because we value growth and learning in our team."
|
team_values: "Мы ценим открытый и вежливый диалог, где побеждают лучшие идеи. Наши решения основаны на иследовании пожеланий клиентов и наш процесс направлен на то, чтобы приносить осязаемые результаты им. У нас все при деле, от CEO до контрибьютеров на GitHub, потому что мы ценим рост и обучение в нашей команде."
|
||||||
nick_title: "Сооснователь" # {change}
|
nick_title: "Сооснователь, CEO"
|
||||||
nick_blurb: "Гуру мотивации"
|
nick_blurb: "Гуру мотивации"
|
||||||
matt_title: "Сооснователь" # {change}
|
matt_title: "Сооснователь, CTO"
|
||||||
cat_title: "Главный ремесленник" # {change}
|
cat_title: "Гейм дизайнер"
|
||||||
cat_blurb: "Повелитель стихий"
|
cat_blurb: "Повелитель стихий"
|
||||||
scott_title: "Сооснователь" # {change}
|
scott_title: "Сооснователь, инженер программист" # {change}
|
||||||
scott_blurb: "Разумный"
|
scott_blurb: "Благоразумный"
|
||||||
# maka_title: "Customer Advocate"
|
maka_title: "Адвокат клиентов"
|
||||||
# maka_blurb: "Storyteller"
|
maka_blurb: "Рассказчик"
|
||||||
# rob_title: "Software Engineer"
|
rob_title: "Инженер программист"
|
||||||
# rob_blurb: "Codes things and stuff"
|
rob_blurb: "Программирует все"
|
||||||
# josh_c_title: "Game Designer"
|
josh_c_title: "Гейм дизайнер"
|
||||||
# josh_c_blurb: "Designs games"
|
josh_c_blurb: "Делает игры"
|
||||||
# robin_title: "UX Design & Research"
|
robin_title: "UX дизайнер & Исследования"
|
||||||
# robin_blurb: "Scaffolding"
|
# robin_blurb: "Scaffolding"
|
||||||
josh_title: "Дизайнер игры"
|
josh_title: "Гейм дизайнер"
|
||||||
josh_blurb: "Пол - это лава"
|
josh_blurb: "Пол - это лава"
|
||||||
# phoenix_title: "Software Engineer"
|
phoenix_title: "Инженер программист"
|
||||||
# nolan_title: "Territory Manager"
|
nolan_title: "Региональный менеджер"
|
||||||
# elliot_title: "Partnership Manager"
|
elliot_title: "Менеджер партнерства"
|
||||||
# elliot_blurb: "Mindreader"
|
elliot_blurb: "Читающий мысли"
|
||||||
# lisa_title: "Market Development Rep"
|
lisa_title: "Представитель по развитию рынка"
|
||||||
retrostyle_title: "Иллюстрирование"
|
retrostyle_title: "Иллюстрирование"
|
||||||
retrostyle_blurb: "RetroStyle Games"
|
retrostyle_blurb: "RetroStyle Games"
|
||||||
jose_title: "Музыка"
|
jose_title: "Музыка"
|
||||||
|
|
|
@ -298,6 +298,10 @@ class ModelResource extends Resource
|
||||||
@loadsAttempted = 0
|
@loadsAttempted = 0
|
||||||
|
|
||||||
load: ->
|
load: ->
|
||||||
|
# TODO: Track progress on requests and don't retry if progress was made recently.
|
||||||
|
# Probably use _.debounce and attach event listeners to xhr objects.
|
||||||
|
|
||||||
|
# This logic is for handling failed responses for level loading.
|
||||||
timeToWait = 5000
|
timeToWait = 5000
|
||||||
tryLoad = =>
|
tryLoad = =>
|
||||||
return if this.isLoaded
|
return if this.isLoaded
|
||||||
|
|
|
@ -38,7 +38,7 @@ module.exports = class ThangType extends CocoModel
|
||||||
urlRoot: '/db/thang.type'
|
urlRoot: '/db/thang.type'
|
||||||
building: {}
|
building: {}
|
||||||
editableByArtisans: true
|
editableByArtisans: true
|
||||||
@defaultActions: ['idle', 'die', 'move', 'attack']
|
@defaultActions: ['idle', 'die', 'move', 'attack', 'trick', 'cast']
|
||||||
|
|
||||||
initialize: ->
|
initialize: ->
|
||||||
super()
|
super()
|
||||||
|
|
|
@ -9,7 +9,7 @@ _.extend CampaignSchema.properties, {
|
||||||
i18n: {type: 'object', title: 'i18n', format: 'i18n', props: ['name', 'fullName', 'description']}
|
i18n: {type: 'object', title: 'i18n', format: 'i18n', props: ['name', 'fullName', 'description']}
|
||||||
fullName: { type: 'string', title: 'Full Name', description: 'Ex.: "Kithgard Dungeon"' }
|
fullName: { type: 'string', title: 'Full Name', description: 'Ex.: "Kithgard Dungeon"' }
|
||||||
description: { type: 'string', format: 'string', description: 'How long it takes and what players learn.' }
|
description: { type: 'string', format: 'string', description: 'How long it takes and what players learn.' }
|
||||||
type: c.shortString(title: 'Type', description: 'What kind of campaign this is.', 'enum': ['hero', 'course'])
|
type: c.shortString(title: 'Type', description: 'What kind of campaign this is.', 'enum': ['hero', 'course','hidden'])
|
||||||
|
|
||||||
ambientSound: c.object {},
|
ambientSound: c.object {},
|
||||||
mp3: { type: 'string', format: 'sound-file' }
|
mp3: { type: 'string', format: 'sound-file' }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#components-documentation-view
|
#components-documentation-view
|
||||||
background-color: #e4cf8c
|
background-color: #e4cf8c
|
||||||
height: 100%
|
height: calc(100% - 90px)
|
||||||
|
|
||||||
#toggle-all-component-code
|
#toggle-all-component-code
|
||||||
margin: 10px
|
margin: 10px
|
||||||
|
|
|
@ -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
|
|
@ -16,6 +16,8 @@ block content
|
||||||
th Course
|
th Course
|
||||||
each course in view.courses.models
|
each course in view.courses.models
|
||||||
- var campaign = view.campaigns.get(course.get('campaignID'));
|
- var campaign = view.campaigns.get(course.get('campaignID'));
|
||||||
|
if !campaign
|
||||||
|
- continue;
|
||||||
- var levels = campaign.getLevels().models;
|
- var levels = campaign.getLevels().models;
|
||||||
- levelsTotal += levels.length;
|
- levelsTotal += levels.length;
|
||||||
tr
|
tr
|
||||||
|
@ -26,6 +28,8 @@ block content
|
||||||
td All
|
td All
|
||||||
each course in view.courses.models
|
each course in view.courses.models
|
||||||
- var campaign = view.campaigns.get(course.get('campaignID'));
|
- var campaign = view.campaigns.get(course.get('campaignID'));
|
||||||
|
if !campaign
|
||||||
|
- continue;
|
||||||
- var levels = campaign.getLevels().models;
|
- var levels = campaign.getLevels().models;
|
||||||
- levelCounts = levels.length;
|
- levelCounts = levels.length;
|
||||||
strong #{course.get('name')}
|
strong #{course.get('name')}
|
||||||
|
|
|
@ -30,8 +30,8 @@ block content
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th Created
|
th Created
|
||||||
th NCES District
|
|
||||||
th School Name
|
th School Name
|
||||||
|
th School District
|
||||||
th.number NCES District Schools
|
th.number NCES District Schools
|
||||||
th.number NCES District Students
|
th.number NCES District Students
|
||||||
th.number NCES School Students
|
th.number NCES School Students
|
||||||
|
@ -44,8 +44,8 @@ block content
|
||||||
- continue;
|
- continue;
|
||||||
tr
|
tr
|
||||||
td.created= trialRequest.get('created').substring(0, 10)
|
td.created= trialRequest.get('created').substring(0, 10)
|
||||||
td= trialRequest.get('properties').nces_district || ''
|
td= trialRequest.get('properties').nces_name || trialRequest.get('properties').organization || ''
|
||||||
td= 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_schools || ''
|
||||||
td= trialRequest.get('properties').nces_district_students || ''
|
td= trialRequest.get('properties').nces_district_students || ''
|
||||||
td= trialRequest.get('properties').nces_students || ''
|
td= trialRequest.get('properties').nces_students || ''
|
||||||
|
|
|
@ -144,12 +144,12 @@ block outer_content
|
||||||
div.tab-pane#related-achievements-view
|
div.tab-pane#related-achievements-view
|
||||||
|
|
||||||
div.tab-pane#editor-level-documentation
|
div.tab-pane#editor-level-documentation
|
||||||
|
div.tab-content
|
||||||
ul.nav.nav-pills.nav-justified
|
ul.nav.nav-pills.nav-justified
|
||||||
li
|
li
|
||||||
a(href="#components-documentation-view", data-toggle="pill", data-i18n="resources.components") Components
|
a(href="#components-documentation-view", data-toggle="pill", data-i18n="resources.components") Components
|
||||||
li
|
li
|
||||||
a(href="#systems-documentation-view", data-toggle="pill", data-i18n="resources.systems") Systems
|
a(href="#systems-documentation-view", data-toggle="pill", data-i18n="resources.systems") Systems
|
||||||
div.tab-content
|
|
||||||
div.tab-pane#components-documentation-view
|
div.tab-pane#components-documentation-view
|
||||||
div.tab-pane#systems-documentation-view
|
div.tab-pane#systems-documentation-view
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
button.btn.btn-primary#new-achievement-button(disabled=(me.isAdmin() === true || me.isArtisan() === true) ? undefined : "true" data-i18n="editor.new_achievement_title") Create a New Achievement
|
.nano.editor-nano-container
|
||||||
|
.nano-content
|
||||||
|
button.btn.btn-primary#new-achievement-button(disabled=(me.isAdmin() === true || me.isArtisan() === true) ? undefined : "true" data-i18n="editor.new_achievement_title") Create a New Achievement
|
||||||
|
|
||||||
if !view.achievements.models.length
|
if !view.achievements.models.length
|
||||||
.panel
|
.panel
|
||||||
.panel-body
|
.panel-body
|
||||||
p(data-i18n="editor.no_achievements") No achievements added for this level yet.
|
p(data-i18n="editor.no_achievements") No achievements added for this level yet.
|
||||||
else
|
else
|
||||||
table.table.table-hover
|
table.table.table-hover
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
mixin task-row(cid)
|
.nano.editor-nano-container
|
||||||
|
.nano-content
|
||||||
|
mixin task-row(cid)
|
||||||
- var task = view.getTaskByCID(cid)
|
- var task = view.getTaskByCID(cid)
|
||||||
- var taskName = task.get('name');
|
- var taskName = task.get('name');
|
||||||
- var isComplete = task.get('complete')
|
- var isComplete = task.get('complete')
|
||||||
|
@ -21,7 +23,7 @@ mixin task-row(cid)
|
||||||
else
|
else
|
||||||
span= taskName
|
span= taskName
|
||||||
|
|
||||||
block
|
block
|
||||||
table.table.table-striped.table-hover
|
table.table.table-striped.table-hover
|
||||||
tr
|
tr
|
||||||
th.task-check Complete
|
th.task-check Complete
|
||||||
|
|
|
@ -28,40 +28,36 @@ block content
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.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'))
|
input.form-control(disabled=true value=me.get('name'))
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
#email-form-group.form-group
|
#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'))
|
input.form-control(name='email' disabled=true value=me.get('email'))
|
||||||
|
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.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') || '')
|
input.form-control(name="firstName" value=me.get('firstName') || '')
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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') || '')
|
input.form-control(name="lastName" value=me.get('lastName') || '')
|
||||||
|
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="teachers_quote.phone_number")
|
span(data-i18n="teachers_quote.phone_number")
|
||||||
span.spl.text-muted(data-i18n="signup.optional")
|
span.spl.text-muted(data-i18n="signup.optional")
|
||||||
.help-block.small
|
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
|
||||||
input.form-control(name="phoneNumber")
|
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="teachers_quote.primary_role_label")
|
span.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||||
.help-block.small
|
|
||||||
em.text-info(data-i18n="teachers_quote.role_help")
|
|
||||||
select.form-control(name="role")
|
select.form-control(name="role")
|
||||||
option(data-i18n="teachers_quote.role_default", , value='')
|
option(data-i18n="teachers_quote.role_default", , value='')
|
||||||
option(data-i18n="courses.teacher", value="Teacher")
|
option(data-i18n="courses.teacher", value="Teacher")
|
||||||
|
@ -75,30 +71,40 @@ block content
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
input.form-control#organization-control(name="organization")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="teachers_quote.city")
|
//- TODO: algolia and form errors both change form-control
|
||||||
input.form-control(name="city")
|
//- 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
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="teachers_quote.state")
|
span.control-label(data-i18n="teachers_quote.city")
|
||||||
input.form-control(name="state")
|
input.form-control(name="city")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
input.form-control(name="country")
|
||||||
|
|
||||||
#form-students-info
|
#form-students-info
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4
|
.col-md-offset-2.col-md-4
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="courses.number_programming_students")
|
span.control-label(data-i18n="courses.number_programming_students")
|
||||||
.help-block.small
|
.help-block.small
|
||||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||||
select.form-control(name="numStudents")
|
select.form-control(name="numStudents")
|
||||||
|
@ -113,7 +119,7 @@ block content
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="courses.number_total_students")
|
span(data-i18n="courses.number_total_students")
|
||||||
span.spl.text-muted(data-i18n="signup.optional")
|
span.spl.text-muted(data-i18n="signup.optional")
|
||||||
select.form-control(name="numStudentsTotal")
|
select.form-control(name="numStudentsTotal")
|
||||||
|
@ -126,11 +132,10 @@ block content
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-10
|
.col-md-offset-2.col-md-4
|
||||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||||
.help-block.small
|
.help-block.small
|
||||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||||
.col-md-offset-2.col-md-5
|
|
||||||
.checkbox
|
.checkbox
|
||||||
label
|
label
|
||||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||||
|
@ -156,7 +161,7 @@ block content
|
||||||
|
|
||||||
#anything-else-row.row.m-y-2
|
#anything-else-row.row.m-y-2
|
||||||
.col-md-offset-2.col-md-8
|
.col-md-offset-2.col-md-8
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="teachers_quote.anything_else")
|
span(data-i18n="teachers_quote.anything_else")
|
||||||
span.spl.text-muted(data-i18n="signup.optional")
|
span.spl.text-muted(data-i18n="signup.optional")
|
||||||
textarea.form-control(rows=8, name="notes")
|
textarea.form-control(rows=8, name="notes")
|
||||||
|
|
|
@ -34,49 +34,47 @@ block content
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="general.username")
|
span.control-label(data-i18n="general.username")
|
||||||
input.form-control(name="name")
|
input.form-control(name="name")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
#email-form-group.form-group
|
#email-form-group.form-group
|
||||||
label.control-label(data-i18n="general.email")
|
span.control-label(data-i18n="general.email")
|
||||||
input.form-control(name="email")
|
input.form-control(name="email")
|
||||||
|
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="general.first_name")
|
span.control-label(data-i18n="general.first_name")
|
||||||
input.form-control(name="firstName")
|
input.form-control(name="firstName")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="general.last_name")
|
span.control-label(data-i18n="general.last_name")
|
||||||
input.form-control(name="lastName")
|
input.form-control(name="lastName")
|
||||||
|
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="general.password")
|
span.control-label(data-i18n="general.password")
|
||||||
input.form-control(name="password1", type="password")
|
input.form-control(name="password1", type="password")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
input.form-control(name="password2", type="password")
|
||||||
|
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="teachers_quote.phone_number")
|
span(data-i18n="teachers_quote.phone_number")
|
||||||
span.spl.text-muted(data-i18n="signup.optional")
|
span.spl.text-muted(data-i18n="signup.optional")
|
||||||
.help-block.small
|
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
|
||||||
input.form-control(name="phoneNumber")
|
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
select.form-control(name="role")
|
||||||
option(data-i18n="teachers_quote.role_default", , value='')
|
option(data-i18n="teachers_quote.role_default", , value='')
|
||||||
option(data-i18n="courses.teacher", value="Teacher")
|
option(data-i18n="courses.teacher", value="Teacher")
|
||||||
|
@ -90,30 +88,40 @@ block content
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
input.form-control#organization-control(name="organization")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="teachers_quote.city")
|
//- TODO: algolia and form errors both change form-control
|
||||||
input.form-control(name="city")
|
//- 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
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="teachers_quote.state")
|
span.control-label(data-i18n="teachers_quote.city")
|
||||||
input.form-control(name="state")
|
input.form-control(name="city")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
input.form-control(name="country")
|
||||||
|
|
||||||
#form-students-info
|
#form-students-info
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4
|
.col-md-offset-2.col-md-4
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="courses.number_programming_students")
|
span.control-label(data-i18n="courses.number_programming_students")
|
||||||
.help-block.small
|
.help-block.small
|
||||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||||
select.form-control(name="numStudents")
|
select.form-control(name="numStudents")
|
||||||
|
@ -128,7 +136,7 @@ block content
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="courses.number_total_students")
|
span(data-i18n="courses.number_total_students")
|
||||||
span.spl.text-muted(data-i18n="signup.optional")
|
span.spl.text-muted(data-i18n="signup.optional")
|
||||||
select.form-control(name="numStudentsTotal")
|
select.form-control(name="numStudentsTotal")
|
||||||
|
@ -140,14 +148,11 @@ block content
|
||||||
option 10,000+
|
option 10,000+
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
|
|
||||||
.row.m-y-2
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-10
|
.col-md-offset-2.col-md-4
|
||||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||||
.help-block.small
|
.help-block.small
|
||||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||||
|
|
||||||
.col-md-offset-2.col-md-5
|
|
||||||
.checkbox
|
.checkbox
|
||||||
label
|
label
|
||||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||||
|
@ -173,7 +178,7 @@ block content
|
||||||
|
|
||||||
#anything-else-row.row.m-y-2
|
#anything-else-row.row.m-y-2
|
||||||
.col-md-offset-2.col-md-8
|
.col-md-offset-2.col-md-8
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="teachers_quote.anything_else")
|
span(data-i18n="teachers_quote.anything_else")
|
||||||
span.spl.text-muted(data-i18n="signup.optional")
|
span.spl.text-muted(data-i18n="signup.optional")
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,9 @@ if completed
|
||||||
.small-details.nowrap
|
.small-details.nowrap
|
||||||
span.spr(data-i18n='teacher.completed')
|
span.spr(data-i18n='teacher.completed')
|
||||||
| Completed
|
| Completed
|
||||||
span= new Date(session.get('dateFirstCompleted')).toLocaleString()
|
- var dateCompleted = session.get('dateFirstCompleted') || session.get('created') || session.get('changed');
|
||||||
|
if dateCompleted
|
||||||
|
span= new Date(dateCompleted).toLocaleString()
|
||||||
+timePlayed
|
+timePlayed
|
||||||
//- .small-details
|
//- .small-details
|
||||||
//- i(data-i18n='teacher.click_to_view_solution')
|
//- i(data-i18n='teacher.click_to_view_solution')
|
||||||
|
|
|
@ -36,7 +36,7 @@ block content
|
||||||
.row
|
.row
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="general.username")
|
span(data-i18n="general.username")
|
||||||
span.spl.text-muted(data-i18n="signup.optional")
|
span.spl.text-muted(data-i18n="signup.optional")
|
||||||
- var name = me.get('name') || '';
|
- var name = me.get('name') || '';
|
||||||
|
@ -44,20 +44,20 @@ block content
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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') || '';
|
- var email = me.get('email') || '';
|
||||||
input.form-control(name="email" value=email, disabled=!!email)
|
input.form-control(name="email" value=email, disabled=!!email)
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="general.first_name")
|
span.control-label(data-i18n="general.first_name")
|
||||||
- var firstName = me.get('firstName') || '';
|
- var firstName = me.get('firstName') || '';
|
||||||
input.form-control(name="firstName" value=firstName, disabled=!!firstName)
|
input.form-control(name="firstName" value=firstName, disabled=!!firstName)
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="general.last_name")
|
span.control-label(data-i18n="general.last_name")
|
||||||
- var lastName = me.get('lastName') || '';
|
- var lastName = me.get('lastName') || '';
|
||||||
input.form-control(name="lastName" value=lastName, disabled=!!lastName)
|
input.form-control(name="lastName" value=lastName, disabled=!!lastName)
|
||||||
|
|
||||||
|
@ -65,23 +65,20 @@ block content
|
||||||
.row
|
.row
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label
|
span.control-label(data-i18n="teachers_quote.phone_number")
|
||||||
span(data-i18n="teachers_quote.phone_number")
|
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||||
.help-block.small
|
|
||||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
|
||||||
input.form-control(name="phoneNumber")
|
|
||||||
|
|
||||||
if me.isAnonymous()
|
if me.isAnonymous()
|
||||||
.row
|
.row
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
#email-form-group.form-group
|
#email-form-group.form-group
|
||||||
label.control-label(data-i18n="general.email")
|
span.control-label(data-i18n="general.email")
|
||||||
- var email = me.get('email') || '';
|
- var email = me.get('email') || '';
|
||||||
input.form-control(name="email" type="email", value=email, disabled=!!email)
|
input.form-control(name="email" type="email", value=email, disabled=!!email)
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="teachers_quote.phone_number")
|
span(data-i18n="teachers_quote.phone_number")
|
||||||
.help-block.small
|
.help-block.small
|
||||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||||
|
@ -91,7 +88,7 @@ block content
|
||||||
.row
|
.row
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
select.form-control(name="role")
|
||||||
option(data-i18n="teachers_quote.primary_role_default", , value='')
|
option(data-i18n="teachers_quote.primary_role_default", , value='')
|
||||||
option(data-i18n="courses.teacher", value="Teacher")
|
option(data-i18n="courses.teacher", value="Teacher")
|
||||||
|
@ -103,7 +100,7 @@ block content
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
select.form-control(name="purchaserRole")
|
||||||
option(data-i18n="teachers_quote.purchaser_role_default", , value='')
|
option(data-i18n="teachers_quote.purchaser_role_default", , value='')
|
||||||
option(data-i18n="teachers_quote.influence_advocate", value="Influence/Advocate")
|
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")
|
option(data-i18n="teachers_quote.no_purchaser_role", value="No role in purchase decisions")
|
||||||
|
|
||||||
#form-school-info
|
#form-school-info
|
||||||
.row
|
.row.m-y-2
|
||||||
.col-md-offset-2.col-md-4.col-sm-6
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
input.form-control#organization-control(name="organization")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="teachers_quote.city")
|
//- TODO: algolia and form errors both change form-control
|
||||||
input.form-control(name="city")
|
//- 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
|
.col-md-offset-2.col-md-4.col-sm-6
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="teachers_quote.state")
|
span.control-label(data-i18n="teachers_quote.city")
|
||||||
input.form-control(name="state")
|
input.form-control(name="city")
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
input.form-control(name="country")
|
||||||
|
|
||||||
#form-students-info
|
#form-students-info
|
||||||
.row
|
.row
|
||||||
.col-md-offset-2.col-md-4
|
.col-md-offset-2.col-md-4
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="courses.number_programming_students")
|
span.control-label(data-i18n="courses.number_programming_students")
|
||||||
.help-block.small
|
.help-block.small
|
||||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||||
select.form-control(name="numStudents")
|
select.form-control(name="numStudents")
|
||||||
|
@ -153,7 +160,7 @@ block content
|
||||||
|
|
||||||
.col-md-4.col-sm-6
|
.col-md-4.col-sm-6
|
||||||
.form-group
|
.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")
|
select.form-control(name="numStudentsTotal")
|
||||||
option(data-i18n="teachers_quote.num_students_default", value='')
|
option(data-i18n="teachers_quote.num_students_default", value='')
|
||||||
option 1-500
|
option 1-500
|
||||||
|
@ -163,14 +170,11 @@ block content
|
||||||
option 10,000+
|
option 10,000+
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
|
.row.m-y-2
|
||||||
.row
|
.col-md-offset-2.col-md-4
|
||||||
.col-md-offset-2.col-md-10
|
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
|
||||||
.help-block.small
|
.help-block.small
|
||||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||||
|
|
||||||
.col-md-offset-2.col-md-5
|
|
||||||
.checkbox
|
.checkbox
|
||||||
label
|
label
|
||||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||||
|
@ -196,7 +200,7 @@ block content
|
||||||
|
|
||||||
#anything-else-row.row
|
#anything-else-row.row
|
||||||
.col-md-offset-2.col-md-8
|
.col-md-offset-2.col-md-8
|
||||||
label.control-label
|
span.control-label
|
||||||
span(data-i18n="teachers_quote.anything_else")
|
span(data-i18n="teachers_quote.anything_else")
|
||||||
span.spl.text-muted(data-i18n="signup.optional")
|
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_students")
|
||||||
input(type="hidden" name="nces_phone")
|
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")
|
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')
|
#form-submit-success.text-center(class=showDone ? '' : 'hide')
|
||||||
|
@ -244,17 +248,17 @@ block content
|
||||||
.row
|
.row
|
||||||
.col-md-offset-2.col-md-4
|
.col-md-offset-2.col-md-4
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="general.username")
|
span.control-label(data-i18n="general.username")
|
||||||
input.form-control(name="name")
|
input.form-control(name="name")
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.col-md-offset-2.col-md-4
|
.col-md-offset-2.col-md-4
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(data-i18n="general.password")
|
span.control-label(data-i18n="general.password")
|
||||||
input.form-control(name="password1", type="password")
|
input.form-control(name="password1", type="password")
|
||||||
.col-md-4
|
.col-md-4
|
||||||
.form-group
|
.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")
|
input.form-control(name="password2", type="password")
|
||||||
|
|
||||||
.text-center
|
.text-center
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
RootView = require 'views/core/RootView'
|
RootView = require 'views/core/RootView'
|
||||||
CocoCollection = require 'collections/CocoCollection'
|
CocoCollection = require 'collections/CocoCollection'
|
||||||
Campaigns = require 'collections/Campaigns'
|
Campaign = require 'models/Campaign'
|
||||||
Course = require 'models/Course'
|
Course = require 'models/Course'
|
||||||
|
|
||||||
module.exports = class AdminClassroomLevelsView extends RootView
|
module.exports = class AdminClassroomLevelsView extends RootView
|
||||||
|
@ -9,8 +9,8 @@ module.exports = class AdminClassroomLevelsView extends RootView
|
||||||
|
|
||||||
initialize: ->
|
initialize: ->
|
||||||
return super() unless me.isAdmin()
|
return super() unless me.isAdmin()
|
||||||
@campaigns = new Campaigns()
|
@campaigns = new CocoCollection([], { url: "/db/campaign", model: Campaign})
|
||||||
@supermodel.trackRequest @campaigns.fetchByType('course', { data: { project: 'levels,levelsUpdated' } })
|
@supermodel.loadCollection(@campaigns, 'campaigns')
|
||||||
@courses = new CocoCollection([], { url: "/db/course", model: Course})
|
@courses = new CocoCollection([], { url: "/db/course", model: Course})
|
||||||
@supermodel.loadCollection(@courses, 'courses')
|
@supermodel.loadCollection(@courses, 'courses')
|
||||||
super()
|
super()
|
||||||
|
|
|
@ -56,6 +56,8 @@ require("locale/eo")
|
||||||
require("locale/uz")
|
require("locale/uz")
|
||||||
require("locale/my")
|
require("locale/my")
|
||||||
require("locale/et")
|
require("locale/et")
|
||||||
|
require("locale/hr")
|
||||||
|
require("locale/mi")
|
||||||
|
|
||||||
module.exports = class DiplomatView extends ContributeClassView
|
module.exports = class DiplomatView extends ContributeClassView
|
||||||
id: 'diplomat-view'
|
id: 'diplomat-view'
|
||||||
|
@ -140,3 +142,5 @@ module.exports = class DiplomatView extends ContributeClassView
|
||||||
uz: [] # O'zbekcha, Uzbek
|
uz: [] # O'zbekcha, Uzbek
|
||||||
my: [] # မြန်မာစကား, Myanmar language
|
my: [] # မြန်မာစကား, Myanmar language
|
||||||
et: [] # Eesti, Estonian
|
et: [] # Eesti, Estonian
|
||||||
|
hr: [] # hrvatski jezik, Croatian
|
||||||
|
mi: [] # te reo Māori, Māori
|
||||||
|
|
|
@ -41,6 +41,9 @@ module.exports = class TeacherCoursesView extends RootView
|
||||||
@ownedClassrooms.fetchMine({data: {project: '_id'}})
|
@ownedClassrooms.fetchMine({data: {project: '_id'}})
|
||||||
@supermodel.trackCollection(@ownedClassrooms)
|
@supermodel.trackCollection(@ownedClassrooms)
|
||||||
@courses = new Courses()
|
@courses = new Courses()
|
||||||
|
if me.isAdmin()
|
||||||
|
@supermodel.trackRequest @courses.fetch()
|
||||||
|
else
|
||||||
@supermodel.trackRequest @courses.fetchReleased()
|
@supermodel.trackRequest @courses.fetchReleased()
|
||||||
@campaigns = new Campaigns()
|
@campaigns = new Campaigns()
|
||||||
@supermodel.trackRequest @campaigns.fetchByType('course', { data: { project: 'levels,levelsUpdated' } })
|
@supermodel.trackRequest @campaigns.fetchByType('course', { data: { project: 'levels,levelsUpdated' } })
|
||||||
|
|
|
@ -365,12 +365,16 @@ module.exports = class CampaignView extends RootView
|
||||||
return experienceScore
|
return experienceScore
|
||||||
|
|
||||||
createLine: (o1, o2) ->
|
createLine: (o1, o2) ->
|
||||||
p1 = x: o1.x, y: 0.66 * o1.y + 0.5
|
mapHeight = parseFloat($(".map").css("height"))
|
||||||
p2 = x: o2.x, y: 0.66 * o2.y + 0.5
|
mapWidth = parseFloat($(".map").css("width"))
|
||||||
|
return unless mapHeight > 0
|
||||||
|
ratio = mapWidth / mapHeight
|
||||||
|
p1 = x: o1.x, y: o1.y / ratio - 0.5
|
||||||
|
p2 = x: o2.x, y: o2.y / ratio
|
||||||
length = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))
|
length = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y))
|
||||||
angle = Math.atan2(p1.y - p2.y, p2.x - p1.x) * 180 / Math.PI
|
angle = Math.atan2(p1.y - p2.y, p2.x - p1.x) * 180 / Math.PI
|
||||||
transform = "rotate(#{angle}deg)"
|
transform = "rotate(#{angle}deg)"
|
||||||
line = $('<div>').appendTo('.map').addClass('next-level-line').css(transform: transform, width: length + '%', left: o1.x + '%', bottom: (o1.y + 0.5) + '%')
|
line = $('<div>').appendTo('.map').addClass('next-level-line').css(transform: transform, width: length + '%', left: o1.x + '%', bottom: (o1.y - 0.5) + '%')
|
||||||
line.append($('<div class="line">')).append($('<div class="point">'))
|
line.append($('<div class="line">')).append($('<div class="point">'))
|
||||||
|
|
||||||
applyCampaignStyles: ->
|
applyCampaignStyles: ->
|
||||||
|
|
|
@ -7,9 +7,9 @@ errors = require 'core/errors'
|
||||||
User = require 'models/User'
|
User = require 'models/User'
|
||||||
ConfirmModal = require 'views/editor/modal/ConfirmModal'
|
ConfirmModal = require 'views/editor/modal/ConfirmModal'
|
||||||
algolia = require 'core/services/algolia'
|
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
|
module.exports = class ConvertToTeacherAccountView extends RootView
|
||||||
id: 'convert-to-teacher-account-view'
|
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.'
|
return 'Your account has not been updated! If you continue, your changes will be lost.'
|
||||||
|
|
||||||
invalidateNCES: ->
|
invalidateNCES: ->
|
||||||
for key in NCES_KEYS
|
for key in SCHOOL_NCES_KEYS
|
||||||
@$('input[name="nces_' + key + '"]').val ''
|
@$('input[name="nces_' + key + '"]').val ''
|
||||||
|
|
||||||
onLoaded: ->
|
onLoaded: ->
|
||||||
|
@ -75,16 +75,34 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
||||||
"<div class='school'> #{hr.name.value} </div>" +
|
"<div class='school'> #{hr.name.value} </div>" +
|
||||||
"<div class='district'>#{hr.district.value}, " +
|
"<div class='district'>#{hr.district.value}, " +
|
||||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||||
|
|
||||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||||
|
@$('input[name="district"]').val suggestion.district
|
||||||
@$('input[name="city"]').val suggestion.city
|
@$('input[name="city"]').val suggestion.city
|
||||||
@$('input[name="state"]').val suggestion.state
|
@$('input[name="state"]').val suggestion.state
|
||||||
@$('input[name="district"]').val suggestion.district
|
|
||||||
@$('input[name="country"]').val 'USA'
|
@$('input[name="country"]').val 'USA'
|
||||||
|
for key in SCHOOL_NCES_KEYS
|
||||||
for key in NCES_KEYS
|
|
||||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
@$('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()
|
||||||
|
|
||||||
onChangeForm: ->
|
onChangeForm: ->
|
||||||
|
@ -97,28 +115,35 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
||||||
|
|
||||||
form = @$('form')
|
form = @$('form')
|
||||||
attrs = forms.formToObject(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')
|
if @$('#other-education-level-checkbox').is(':checked')
|
||||||
val = @$('#other-education-level-input').val()
|
val = @$('#other-education-level-input').val()
|
||||||
attrs.educationLevel.push(val) if val
|
trialRequestAttrs.educationLevel.push(val) if val
|
||||||
|
|
||||||
forms.clearFormAlerts(form)
|
forms.clearFormAlerts(form)
|
||||||
|
|
||||||
result = tv4.validateMultiple(attrs, formSchema)
|
result = tv4.validateMultiple(trialRequestAttrs, formSchema)
|
||||||
error = false
|
error = false
|
||||||
if not result.valid
|
if not result.valid
|
||||||
forms.applyErrorsToForm(form, result.errors)
|
forms.applyErrorsToForm(form, result.errors)
|
||||||
error = true
|
error = true
|
||||||
if not _.size(attrs.educationLevel)
|
if not _.size(trialRequestAttrs.educationLevel)
|
||||||
forms.setErrorToProperty(form, 'educationLevel', 'Include at least one.')
|
forms.setErrorToProperty(form, 'educationLevel', 'include at least one')
|
||||||
|
error = true
|
||||||
|
unless attrs.district
|
||||||
|
forms.setErrorToProperty(form, 'district', $.i18n.t('common.required_field'))
|
||||||
error = true
|
error = true
|
||||||
if error
|
if error
|
||||||
forms.scrollToFirstError()
|
forms.scrollToFirstError()
|
||||||
return
|
return
|
||||||
attrs['siteOrigin'] = 'convert teacher'
|
trialRequestAttrs['siteOrigin'] = 'convert teacher'
|
||||||
@trialRequest = new TrialRequest({
|
@trialRequest = new TrialRequest({
|
||||||
type: 'course'
|
type: 'course'
|
||||||
properties: attrs
|
properties: trialRequestAttrs
|
||||||
})
|
})
|
||||||
if me.get('role') is 'student' and not me.isAnonymous()
|
if me.get('role') is 'student' and not me.isAnonymous()
|
||||||
modal = new ConfirmModal({
|
modal = new ConfirmModal({
|
||||||
|
@ -151,15 +176,14 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
||||||
|
|
||||||
formSchema = {
|
formSchema = {
|
||||||
type: 'object'
|
type: 'object'
|
||||||
required: [
|
required: ['firstName', 'lastName', 'role', 'numStudents', 'city', 'state', 'country']
|
||||||
'firstName', 'lastName', 'organization', 'role', 'numStudents', 'city', 'state', 'country'
|
|
||||||
]
|
|
||||||
properties:
|
properties:
|
||||||
firstName: { type: 'string' }
|
firstName: { type: 'string' }
|
||||||
lastName: { type: 'string' }
|
lastName: { type: 'string' }
|
||||||
phoneNumber: { type: 'string' }
|
phoneNumber: { type: 'string' }
|
||||||
role: { type: 'string' }
|
role: { type: 'string' }
|
||||||
organization: { type: 'string' }
|
organization: { type: 'string' }
|
||||||
|
district: { type: 'string' }
|
||||||
city: { type: 'string' }
|
city: { type: 'string' }
|
||||||
state: { type: 'string' }
|
state: { type: 'string' }
|
||||||
country: { type: 'string' }
|
country: { type: 'string' }
|
||||||
|
@ -172,5 +196,5 @@ formSchema = {
|
||||||
notes: { type: 'string' }
|
notes: { type: 'string' }
|
||||||
}
|
}
|
||||||
|
|
||||||
for key in NCES_KEYS
|
for key in SCHOOL_NCES_KEYS
|
||||||
formSchema['nces_' + key] = type: 'string'
|
formSchema['nces_' + key] = type: 'string'
|
||||||
|
|
|
@ -7,9 +7,9 @@ errors = require 'core/errors'
|
||||||
User = require 'models/User'
|
User = require 'models/User'
|
||||||
algolia = require 'core/services/algolia'
|
algolia = require 'core/services/algolia'
|
||||||
|
|
||||||
FORM_KEY = 'request-quote-form'
|
|
||||||
SIGNUP_REDIRECT = '/teachers/classes'
|
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
|
module.exports = class CreateTeacherAccountView extends RootView
|
||||||
id: 'create-teacher-account-view'
|
id: 'create-teacher-account-view'
|
||||||
|
@ -43,7 +43,7 @@ module.exports = class CreateTeacherAccountView extends RootView
|
||||||
super()
|
super()
|
||||||
|
|
||||||
invalidateNCES: ->
|
invalidateNCES: ->
|
||||||
for key in NCES_KEYS
|
for key in SCHOOL_NCES_KEYS
|
||||||
@$('input[name="nces_' + key + '"]').val ''
|
@$('input[name="nces_' + key + '"]').val ''
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
@ -72,16 +72,34 @@ module.exports = class CreateTeacherAccountView extends RootView
|
||||||
"<div class='school'> #{hr.name.value} </div>" +
|
"<div class='school'> #{hr.name.value} </div>" +
|
||||||
"<div class='district'>#{hr.district.value}, " +
|
"<div class='district'>#{hr.district.value}, " +
|
||||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||||
|
|
||||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||||
|
@$('input[name="district"]').val suggestion.district
|
||||||
@$('input[name="city"]').val suggestion.city
|
@$('input[name="city"]').val suggestion.city
|
||||||
@$('input[name="state"]').val suggestion.state
|
@$('input[name="state"]').val suggestion.state
|
||||||
@$('input[name="district"]').val suggestion.district
|
|
||||||
@$('input[name="country"]').val 'USA'
|
@$('input[name="country"]').val 'USA'
|
||||||
|
for key in SCHOOL_NCES_KEYS
|
||||||
for key in NCES_KEYS
|
|
||||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
@$('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()
|
||||||
|
|
||||||
onClickLoginLink: ->
|
onClickLoginLink: ->
|
||||||
|
@ -101,6 +119,9 @@ module.exports = class CreateTeacherAccountView extends RootView
|
||||||
allAttrs = forms.formToObject(form)
|
allAttrs = forms.formToObject(form)
|
||||||
trialRequestAttrs = _.omit(allAttrs, 'name', 'password1', 'password2')
|
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')
|
if @$('#other-education-level-checkbox').is(':checked')
|
||||||
val = @$('#other-education-level-input').val()
|
val = @$('#other-education-level-input').val()
|
||||||
trialRequestAttrs.educationLevel.push(val) if val
|
trialRequestAttrs.educationLevel.push(val) if val
|
||||||
|
@ -112,18 +133,21 @@ module.exports = class CreateTeacherAccountView extends RootView
|
||||||
if not result.valid
|
if not result.valid
|
||||||
forms.applyErrorsToForm(form, result.errors)
|
forms.applyErrorsToForm(form, result.errors)
|
||||||
error = true
|
error = true
|
||||||
if not forms.validateEmail(trialRequestAttrs.email)
|
if not error and not forms.validateEmail(trialRequestAttrs.email)
|
||||||
forms.setErrorToProperty(form, 'email', 'Invalid email.')
|
forms.setErrorToProperty(form, 'email', 'invalid email')
|
||||||
error = true
|
error = true
|
||||||
if not _.size(trialRequestAttrs.educationLevel)
|
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
|
error = true
|
||||||
unless @gplusAttrs or @facebookAttrs
|
unless @gplusAttrs or @facebookAttrs
|
||||||
if not allAttrs.password1
|
if not allAttrs.password1
|
||||||
forms.setErrorToProperty(form, 'password1', 'Required field')
|
forms.setErrorToProperty(form, 'password1', $.i18n.t('common.required_field'))
|
||||||
error = true
|
error = true
|
||||||
else if not allAttrs.password2
|
else if not allAttrs.password2
|
||||||
forms.setErrorToProperty(form, 'password2', 'Required field')
|
forms.setErrorToProperty(form, 'password2', $.i18n.t('common.required_field'))
|
||||||
error = true
|
error = true
|
||||||
else if allAttrs.password1 isnt allAttrs.password2
|
else if allAttrs.password1 isnt allAttrs.password2
|
||||||
forms.setErrorToProperty(form, 'password1', 'Password fields are not equivalent')
|
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)
|
@$('input[type="password"]').attr('disabled', true)
|
||||||
@$('#gplus-logged-in-row, #social-network-signups').toggleClass('hide')
|
@$('#gplus-logged-in-row, #social-network-signups').toggleClass('hide')
|
||||||
|
|
||||||
|
|
||||||
# Facebook signup
|
# Facebook signup
|
||||||
|
|
||||||
onClickFacebookSignupButton: ->
|
onClickFacebookSignupButton: ->
|
||||||
|
@ -269,13 +292,9 @@ module.exports = class CreateTeacherAccountView extends RootView
|
||||||
@$('#facebook-logged-in-row, #social-network-signups').toggleClass('hide')
|
@$('#facebook-logged-in-row, #social-network-signups').toggleClass('hide')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
formSchema = {
|
formSchema = {
|
||||||
type: 'object'
|
type: 'object'
|
||||||
required: [
|
required: ['firstName', 'lastName', 'email', 'role', 'numStudents', 'city', 'state', 'country']
|
||||||
'firstName', 'lastName', 'email', 'organization', 'role', 'numStudents', 'city'
|
|
||||||
'state', 'country'
|
|
||||||
]
|
|
||||||
properties:
|
properties:
|
||||||
password1: { type: 'string' }
|
password1: { type: 'string' }
|
||||||
password2: { type: 'string' }
|
password2: { type: 'string' }
|
||||||
|
@ -286,6 +305,7 @@ formSchema = {
|
||||||
phoneNumber: { type: 'string' }
|
phoneNumber: { type: 'string' }
|
||||||
role: { type: 'string' }
|
role: { type: 'string' }
|
||||||
organization: { type: 'string' }
|
organization: { type: 'string' }
|
||||||
|
district: { type: 'string' }
|
||||||
city: { type: 'string' }
|
city: { type: 'string' }
|
||||||
state: { type: 'string' }
|
state: { type: 'string' }
|
||||||
country: { type: 'string' }
|
country: { type: 'string' }
|
||||||
|
@ -298,5 +318,5 @@ formSchema = {
|
||||||
notes: { type: 'string' }
|
notes: { type: 'string' }
|
||||||
}
|
}
|
||||||
|
|
||||||
for key in NCES_KEYS
|
for key in SCHOOL_NCES_KEYS
|
||||||
formSchema['nces_' + key] = type: 'string'
|
formSchema['nces_' + key] = type: 'string'
|
||||||
|
|
|
@ -8,7 +8,8 @@ ConfirmModal = require 'views/editor/modal/ConfirmModal'
|
||||||
algolia = require 'core/services/algolia'
|
algolia = require 'core/services/algolia'
|
||||||
|
|
||||||
SIGNUP_REDIRECT = '/teachers'
|
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
|
module.exports = class RequestQuoteView extends RootView
|
||||||
id: 'request-quote-view'
|
id: 'request-quote-view'
|
||||||
|
@ -46,7 +47,7 @@ module.exports = class RequestQuoteView extends RootView
|
||||||
super()
|
super()
|
||||||
|
|
||||||
invalidateNCES: ->
|
invalidateNCES: ->
|
||||||
for key in NCES_KEYS
|
for key in SCHOOL_NCES_KEYS
|
||||||
@$('input[name="nces_' + key + '"]').val ''
|
@$('input[name="nces_' + key + '"]').val ''
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
@ -75,16 +76,34 @@ module.exports = class RequestQuoteView extends RootView
|
||||||
"<div class='school'> #{hr.name.value} </div>" +
|
"<div class='school'> #{hr.name.value} </div>" +
|
||||||
"<div class='district'>#{hr.district.value}, " +
|
"<div class='district'>#{hr.district.value}, " +
|
||||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||||
|
|
||||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||||
|
@$('input[name="district"]').val suggestion.district
|
||||||
@$('input[name="city"]').val suggestion.city
|
@$('input[name="city"]').val suggestion.city
|
||||||
@$('input[name="state"]').val suggestion.state
|
@$('input[name="state"]').val suggestion.state
|
||||||
@$('input[name="district"]').val suggestion.district
|
|
||||||
@$('input[name="country"]').val 'USA'
|
@$('input[name="country"]').val 'USA'
|
||||||
|
for key in SCHOOL_NCES_KEYS
|
||||||
for key in NCES_KEYS
|
|
||||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
@$('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()
|
||||||
|
|
||||||
onChangeRequestForm: ->
|
onChangeRequestForm: ->
|
||||||
|
@ -96,32 +115,39 @@ module.exports = class RequestQuoteView extends RootView
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
form = @$('#request-form')
|
form = @$('#request-form')
|
||||||
attrs = forms.formToObject(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
|
# custom other input logic
|
||||||
if @$('#other-education-level-checkbox').is(':checked')
|
if @$('#other-education-level-checkbox').is(':checked')
|
||||||
val = @$('#other-education-level-input').val()
|
val = @$('#other-education-level-input').val()
|
||||||
attrs.educationLevel.push(val) if val
|
trialRequestAttrs.educationLevel.push(val) if val
|
||||||
|
|
||||||
forms.clearFormAlerts(form)
|
forms.clearFormAlerts(form)
|
||||||
requestFormSchema = if me.isAnonymous() then requestFormSchemaAnonymous else requestFormSchemaLoggedIn
|
requestFormSchema = if me.isAnonymous() then requestFormSchemaAnonymous else requestFormSchemaLoggedIn
|
||||||
result = tv4.validateMultiple(attrs, requestFormSchemaAnonymous)
|
result = tv4.validateMultiple(trialRequestAttrs, requestFormSchemaAnonymous)
|
||||||
error = false
|
error = false
|
||||||
if not result.valid
|
if not result.valid
|
||||||
forms.applyErrorsToForm(form, result.errors)
|
forms.applyErrorsToForm(form, result.errors)
|
||||||
error = true
|
error = true
|
||||||
if not forms.validateEmail(attrs.email)
|
if not error and not forms.validateEmail(trialRequestAttrs.email)
|
||||||
forms.setErrorToProperty(form, 'email', 'Invalid email.')
|
forms.setErrorToProperty(form, 'email', 'invalid email')
|
||||||
error = true
|
error = true
|
||||||
if not _.size(attrs.educationLevel)
|
if not _.size(trialRequestAttrs.educationLevel)
|
||||||
forms.setErrorToProperty(form, 'educationLevel', 'Include at least one.')
|
forms.setErrorToProperty(form, 'educationLevel', 'include at least one')
|
||||||
|
error = true
|
||||||
|
unless attrs.district
|
||||||
|
forms.setErrorToProperty(form, 'district', $.i18n.t('common.required_field'))
|
||||||
error = true
|
error = true
|
||||||
if error
|
if error
|
||||||
forms.scrollToFirstError()
|
forms.scrollToFirstError()
|
||||||
return
|
return
|
||||||
attrs['siteOrigin'] = 'demo request'
|
trialRequestAttrs['siteOrigin'] = 'demo request'
|
||||||
@trialRequest = new TrialRequest({
|
@trialRequest = new TrialRequest({
|
||||||
type: 'course'
|
type: 'course'
|
||||||
properties: attrs
|
properties: trialRequestAttrs
|
||||||
})
|
})
|
||||||
if me.get('role') is 'student' and not me.isAnonymous()
|
if me.get('role') is 'student' and not me.isAnonymous()
|
||||||
modal = new ConfirmModal({
|
modal = new ConfirmModal({
|
||||||
|
@ -262,7 +288,7 @@ module.exports = class RequestQuoteView extends RootView
|
||||||
requestFormSchemaAnonymous = {
|
requestFormSchemaAnonymous = {
|
||||||
type: 'object'
|
type: 'object'
|
||||||
required: [
|
required: [
|
||||||
'firstName', 'lastName', 'email', 'organization', 'role', 'purchaserRole', 'numStudents',
|
'firstName', 'lastName', 'email', 'role', 'purchaserRole', 'numStudents',
|
||||||
'numStudentsTotal', 'phoneNumber', 'city', 'state', 'country']
|
'numStudentsTotal', 'phoneNumber', 'city', 'state', 'country']
|
||||||
properties:
|
properties:
|
||||||
firstName: { type: 'string' }
|
firstName: { type: 'string' }
|
||||||
|
@ -273,6 +299,7 @@ requestFormSchemaAnonymous = {
|
||||||
role: { type: 'string' }
|
role: { type: 'string' }
|
||||||
purchaserRole: { type: 'string' }
|
purchaserRole: { type: 'string' }
|
||||||
organization: { type: 'string' }
|
organization: { type: 'string' }
|
||||||
|
district: { type: 'string' }
|
||||||
city: { type: 'string' }
|
city: { type: 'string' }
|
||||||
state: { type: 'string' }
|
state: { type: 'string' }
|
||||||
country: { type: 'string' }
|
country: { type: 'string' }
|
||||||
|
@ -285,7 +312,7 @@ requestFormSchemaAnonymous = {
|
||||||
notes: { type: 'string' },
|
notes: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
for key in NCES_KEYS
|
for key in SCHOOL_NCES_KEYS
|
||||||
requestFormSchemaAnonymous['nces_' + key] = type: 'string'
|
requestFormSchemaAnonymous['nces_' + key] = type: 'string'
|
||||||
|
|
||||||
# same form, but add username input
|
# same form, but add username input
|
||||||
|
|
|
@ -34,7 +34,8 @@ module.exports = class TeachersContactModal extends ModalView
|
||||||
message = """
|
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.
|
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 ''}
|
Role: #{props.role or ''}
|
||||||
Phone Number: #{props.phoneNumber or ''}
|
Phone Number: #{props.phoneNumber or ''}
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -16,7 +16,7 @@ if (process.argv.length !== 10) {
|
||||||
// TODO: Cleanup country/status lookup code
|
// TODO: Cleanup country/status lookup code
|
||||||
|
|
||||||
// Save as custom fields instead of user-specific lead notes (also saving nces_ props)
|
// 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
|
// Old properties which are deprecated or moved
|
||||||
const customFieldsToRemove = [
|
const customFieldsToRemove = [
|
||||||
|
@ -327,7 +327,7 @@ function findCocoLeads(done) {
|
||||||
if (!trialRequest.properties || !trialRequest.properties.email) continue;
|
if (!trialRequest.properties || !trialRequest.properties.email) continue;
|
||||||
const email = trialRequest.properties.email.toLowerCase();
|
const email = trialRequest.properties.email.toLowerCase();
|
||||||
emails.push(email);
|
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);
|
if (!leads[name]) leads[name] = new CocoLead(name);
|
||||||
leads[name].addTrialRequest(email, trialRequest);
|
leads[name].addTrialRequest(email, trialRequest);
|
||||||
emailLeadMap[email] = leads[name];
|
emailLeadMap[email] = leads[name];
|
||||||
|
|
|
@ -105,7 +105,7 @@ module.exports =
|
||||||
members = classroom.get('members') or []
|
members = classroom.get('members') or []
|
||||||
members = members.slice(memberSkip, memberSkip + memberLimit)
|
members = members.slice(memberSkip, memberSkip + memberLimit)
|
||||||
dbqs = []
|
dbqs = []
|
||||||
select = 'state.complete level creator playtime changed dateFirstCompleted submitted'
|
select = 'state.complete level creator playtime changed created dateFirstCompleted submitted'
|
||||||
for member in members
|
for member in members
|
||||||
dbqs.push(LevelSession.find({creator: member.toHexString()}).select(select).exec())
|
dbqs.push(LevelSession.find({creator: member.toHexString()}).select(select).exec())
|
||||||
results = yield dbqs
|
results = yield dbqs
|
||||||
|
|
|
@ -11,10 +11,6 @@ cutoffDate = new Date(2015,11,11)
|
||||||
cutoffID = mongoose.Types.ObjectId(Math.floor(cutoffDate/1000).toString(16)+'0000000000000000')
|
cutoffID = mongoose.Types.ObjectId(Math.floor(cutoffDate/1000).toString(16)+'0000000000000000')
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
logError: (user, msg) ->
|
|
||||||
console.warn "Prepaid Error: [#{user.get('slug')} (#{user._id})] '#{msg}'"
|
|
||||||
|
|
||||||
|
|
||||||
post: wrap (req, res) ->
|
post: wrap (req, res) ->
|
||||||
validTypes = ['course']
|
validTypes = ['course']
|
||||||
unless req.body.type in validTypes
|
unless req.body.type in validTypes
|
||||||
|
@ -71,7 +67,7 @@ module.exports =
|
||||||
update = { $push: { redeemers : { date: new Date(), userID: user._id } }}
|
update = { $push: { redeemers : { date: new Date(), userID: user._id } }}
|
||||||
result = yield Prepaid.update(query, update)
|
result = yield Prepaid.update(query, update)
|
||||||
if result.nModified is 0
|
if result.nModified is 0
|
||||||
@logError(req.user, "POST prepaid redeemer lost race on maxRedeemers")
|
console.error("Prepaid redeem error: [#{req.user.get('slug')} (#{req.user._id})] 'POST prepaid redeemer lost race on maxRedeemers'")
|
||||||
throw new errors.Forbidden('This prepaid is exhausted')
|
throw new errors.Forbidden('This prepaid is exhausted')
|
||||||
|
|
||||||
update = {
|
update = {
|
||||||
|
@ -142,7 +138,7 @@ module.exports =
|
||||||
trialRequests = yield TrialRequest.find({$and: [{type: 'course'}, {applicant: {$in: userIDs}}]}, {applicant: 1, properties: 1}).lean()
|
trialRequests = yield TrialRequest.find({$and: [{type: 'course'}, {applicant: {$in: userIDs}}]}, {applicant: 1, properties: 1}).lean()
|
||||||
schoolPrepaidsMap = {}
|
schoolPrepaidsMap = {}
|
||||||
for trialRequest in trialRequests
|
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
|
continue unless school
|
||||||
if userPrepaidsMap[trialRequest.applicant.valueOf()]?.length > 0
|
if userPrepaidsMap[trialRequest.applicant.valueOf()]?.length > 0
|
||||||
schoolPrepaidsMap[school] ?= []
|
schoolPrepaidsMap[school] ?= []
|
||||||
|
|
|
@ -184,6 +184,7 @@ module.exports = {
|
||||||
email: 'an@email.com'
|
email: 'an@email.com'
|
||||||
phoneNumber: '555-555-5555'
|
phoneNumber: '555-555-5555'
|
||||||
organization: 'Greendale'
|
organization: 'Greendale'
|
||||||
|
district: 'Green District'
|
||||||
}
|
}
|
||||||
}, attrs)
|
}, attrs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ describe 'ConvertToTeacherAccountView (/teachers/update-account)', ->
|
||||||
phoneNumber: '555-555-5555'
|
phoneNumber: '555-555-5555'
|
||||||
role: 'Teacher'
|
role: 'Teacher'
|
||||||
organization: 'School'
|
organization: 'School'
|
||||||
|
district: 'District'
|
||||||
city: 'Springfield'
|
city: 'Springfield'
|
||||||
state: 'AA'
|
state: 'AA'
|
||||||
country: 'asdf'
|
country: 'asdf'
|
||||||
|
@ -168,3 +169,48 @@ describe 'ConvertToTeacherAccountView (/teachers/update-account)', ->
|
||||||
})
|
})
|
||||||
expect(me.get('role')).toBe(successForm.role.toLowerCase())
|
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'
|
phoneNumber: '555-555-5555'
|
||||||
role: 'Teacher'
|
role: 'Teacher'
|
||||||
organization: 'School'
|
organization: 'School'
|
||||||
|
district: 'District'
|
||||||
city: 'Springfield'
|
city: 'Springfield'
|
||||||
state: 'AA'
|
state: 'AA'
|
||||||
country: 'asdf'
|
country: 'asdf'
|
||||||
|
@ -219,6 +220,8 @@ describe 'CreateTeacherAccountView', ->
|
||||||
expect(attrs.password2).toBeUndefined()
|
expect(attrs.password2).toBeUndefined()
|
||||||
expect(attrs.name).toBeUndefined()
|
expect(attrs.name).toBeUndefined()
|
||||||
expect(attrs.properties?.siteOrigin).toBe('create teacher')
|
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', ->
|
describe 'after saving the new trial request', ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
@ -267,4 +270,48 @@ describe 'CreateTeacherAccountView', ->
|
||||||
view.$('#email-form-group .login-link').click()
|
view.$('#email-form-group .login-link').click()
|
||||||
expect(view.openModalView).toHaveBeenCalled()
|
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
|
view = null
|
||||||
|
|
||||||
successFormValues = {
|
successForm = {
|
||||||
firstName: 'A'
|
firstName: 'A'
|
||||||
lastName: 'B'
|
lastName: 'B'
|
||||||
email: 'C@D.com'
|
email: 'C@D.com'
|
||||||
phoneNumber: '555-555-5555'
|
phoneNumber: '555-555-5555'
|
||||||
role: 'Teacher'
|
role: 'Teacher'
|
||||||
organization: 'School'
|
organization: 'School'
|
||||||
|
district: 'District'
|
||||||
city: 'Springfield'
|
city: 'Springfield'
|
||||||
state: 'AA'
|
state: 'AA'
|
||||||
country: 'asdf'
|
country: 'asdf'
|
||||||
|
@ -23,7 +24,7 @@ describe 'RequestQuoteView', ->
|
||||||
|
|
||||||
isSubmitRequest = (r) -> _.string.startsWith(r.url, '/db/trial.request') and r.method is 'POST'
|
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) ->
|
beforeEach (done) ->
|
||||||
me.clear()
|
me.clear()
|
||||||
me.set('_id', '1234')
|
me.set('_id', '1234')
|
||||||
|
@ -32,7 +33,10 @@ describe 'RequestQuoteView', ->
|
||||||
view = new RequestQuoteView()
|
view = new RequestQuoteView()
|
||||||
view.render()
|
view.render()
|
||||||
jasmine.demoEl(view.$el)
|
jasmine.demoEl(view.$el)
|
||||||
|
_.defer done # Let SuperModel finish
|
||||||
|
|
||||||
|
describe 'has an existing trial request', ->
|
||||||
|
beforeEach (done) ->
|
||||||
request = jasmine.Ajax.requests.mostRecent()
|
request = jasmine.Ajax.requests.mostRecent()
|
||||||
request.respondWith({
|
request.respondWith({
|
||||||
status: 200
|
status: 200
|
||||||
|
@ -50,43 +54,8 @@ describe 'RequestQuoteView', ->
|
||||||
expect(view.$('#request-form').hasClass('hide')).toBe(true)
|
expect(view.$('#request-form').hasClass('hide')).toBe(true)
|
||||||
expect(view.$('#form-submit-success').hasClass('hide')).toBe(false)
|
expect(view.$('#form-submit-success').hasClass('hide')).toBe(false)
|
||||||
|
|
||||||
|
describe 'does NOT have an existing trial request', ->
|
||||||
describe 'when user is signed in and has an existing trial request', ->
|
|
||||||
beforeEach (done) ->
|
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 = jasmine.Ajax.requests.mostRecent()
|
||||||
request.respondWith({
|
request.respondWith({
|
||||||
status: 200
|
status: 200
|
||||||
|
@ -108,12 +77,12 @@ describe 'RequestQuoteView', ->
|
||||||
describe 'on successful form submit', ->
|
describe 'on successful form submit', ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
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()
|
view.$('#request-form').submit()
|
||||||
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||||
@submitRequest.respondWith({
|
@submitRequest.respondWith({
|
||||||
status: 201
|
status: 201
|
||||||
responseText: JSON.stringify(_.extend({_id: 'a'}, successFormValues))
|
responseText: JSON.stringify(_.extend({_id: 'a'}, successForm))
|
||||||
})
|
})
|
||||||
|
|
||||||
it 'does not prevent navigating away', ->
|
it 'does not prevent navigating away', ->
|
||||||
|
@ -167,10 +136,9 @@ describe 'RequestQuoteView', ->
|
||||||
expect(request.method).toBe('PUT')
|
expect(request.method).toBe('PUT')
|
||||||
expect(request.url).toBe('/db/user/1234')
|
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 ->
|
beforeEach ->
|
||||||
forms.objectToForm(view.$el, successFormValues)
|
forms.objectToForm(view.$el, successForm)
|
||||||
view.$('#request-form').submit()
|
view.$('#request-form').submit()
|
||||||
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||||
@submitRequest.respondWith({
|
@submitRequest.respondWith({
|
||||||
|
@ -182,15 +150,86 @@ describe 'RequestQuoteView', ->
|
||||||
expect(view.$('#email-form-group').hasClass('has-error')).toBe(true)
|
expect(view.$('#email-form-group').hasClass('has-error')).toBe(true)
|
||||||
expect(view.$('#email-form-group .error-help-block').length).toBe(1)
|
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) ->
|
beforeEach (done) ->
|
||||||
me.set('role', 'student')
|
me.clear()
|
||||||
me.set('name', 'Some User')
|
me.set('_id', '1234')
|
||||||
|
me._revertAttributes = {}
|
||||||
spyOn(me, 'isAnonymous').and.returnValue(false)
|
spyOn(me, 'isAnonymous').and.returnValue(false)
|
||||||
view = new RequestQuoteView()
|
view = new RequestQuoteView()
|
||||||
view.render()
|
view.render()
|
||||||
jasmine.demoEl(view.$el)
|
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 = jasmine.Ajax.requests.mostRecent()
|
||||||
request.respondWith({ status: 200, responseText: '[]'})
|
request.respondWith({ status: 200, responseText: '[]'})
|
||||||
_.defer done # Let SuperModel finish
|
_.defer done # Let SuperModel finish
|
||||||
|
@ -200,7 +239,7 @@ describe 'RequestQuoteView', ->
|
||||||
|
|
||||||
it 'requires confirmation to submit the form', ->
|
it 'requires confirmation to submit the form', ->
|
||||||
form = view.$('#request-form')
|
form = view.$('#request-form')
|
||||||
forms.objectToForm(form, successFormValues)
|
forms.objectToForm(form, successForm)
|
||||||
spyOn(view, 'openModalView')
|
spyOn(view, 'openModalView')
|
||||||
form.submit()
|
form.submit()
|
||||||
expect(view.openModalView).toHaveBeenCalled()
|
expect(view.openModalView).toHaveBeenCalled()
|
||||||
|
@ -211,5 +250,3 @@ describe 'RequestQuoteView', ->
|
||||||
confirmModal.trigger 'confirm'
|
confirmModal.trigger 'confirm'
|
||||||
submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||||
expect(submitRequest).toBeTruthy()
|
expect(submitRequest).toBeTruthy()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue