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
|
||||
if error.code is tv4.errorCodes.OBJECT_REQUIRED
|
||||
prop = _.last(_.string.words(error.message)) # hack
|
||||
message = 'Required field'
|
||||
message = $.i18n.t('common.required_field')
|
||||
|
||||
else if error.dataPath
|
||||
prop = error.dataPath[1..]
|
||||
|
|
|
@ -22,6 +22,9 @@ LOG = false
|
|||
# * Sprite map generation
|
||||
# * 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
|
||||
|
||||
constructor: (options) ->
|
||||
|
|
|
@ -356,7 +356,7 @@
|
|||
submit_patch: "Submit Patch"
|
||||
submit_changes: "Submit Changes"
|
||||
save_changes: "Save Changes"
|
||||
required_field: "Required field"
|
||||
required_field: "required" # {change}
|
||||
|
||||
general:
|
||||
and: "and"
|
||||
|
@ -885,7 +885,9 @@
|
|||
evaluate_recommend: "Evaluate/Recommend"
|
||||
approve_funds: "Approve Funds"
|
||||
no_purchaser_role: "No role in purchase decisions"
|
||||
organization_label: "Name of School/District"
|
||||
district_label: "District"
|
||||
district_na: "Enter N/A if not applicable"
|
||||
organization_label: "School" # {change}
|
||||
city: "City"
|
||||
state: "State"
|
||||
country: "Country"
|
||||
|
|
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' }
|
||||
'it': { nativeDescription: 'Italiano', englishDescription: 'Italian' }
|
||||
'he': { nativeDescription: 'עברית', englishDescription: 'Hebrew' }
|
||||
'hr': { nativeDescription: 'hrvatski jezik', englishDescription: 'Croatian' }
|
||||
'hu': { nativeDescription: 'magyar', englishDescription: 'Hungarian' }
|
||||
'lt': { nativeDescription: 'lietuvių kalba', englishDescription: 'Lithuanian' }
|
||||
'mi': { nativeDescription: 'te reo Māori', englishDescription: 'Māori' }
|
||||
'mk-MK': { nativeDescription: 'Македонски', englishDescription: 'Macedonian' }
|
||||
'hi': { nativeDescription: 'मानक हिन्दी', englishDescription: 'Hindi' }
|
||||
'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: "и мы свяжемся!"
|
||||
|
||||
modal:
|
||||
# cancel: "Cancel"
|
||||
cancel: "Отмена"
|
||||
close: "Закрыть"
|
||||
okay: "OK"
|
||||
|
||||
|
@ -234,7 +234,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
None: "значение, которое не указывает ни на один объект (ничто)"
|
||||
|
||||
share_progress_modal:
|
||||
blurb: "Вы отлично продвигаетесь! Расскажите своим родителям, как много вы уже выучили с CodeCombat."
|
||||
blurb: "Вы показываете отличные результаты! Расскажите своим родителям, как много вы уже выучили с CodeCombat."
|
||||
email_invalid: "Email-адрес некорректен."
|
||||
form_blurb: "Введите их email-адреса ниже, и мы покажем им!"
|
||||
form_label: "Email-адрес"
|
||||
|
@ -243,9 +243,9 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
|
||||
login:
|
||||
sign_up: "Создать аккаунт"
|
||||
# email_or_username: "Email or username"
|
||||
email_or_username: "Email или имя пользователя"
|
||||
log_in: "Войти"
|
||||
logging_in: "Вход..."
|
||||
logging_in: "Входим..."
|
||||
log_out: "Выйти"
|
||||
forgot_password: "Забыли пароль?"
|
||||
authenticate_gplus: "Аутентификация G+"
|
||||
|
@ -256,72 +256,72 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
signup_switch: "Хотите создать аккаунт?"
|
||||
|
||||
signup:
|
||||
# create_student_header: "Create Student Account"
|
||||
# create_teacher_header: "Create Teacher Account"
|
||||
# create_individual_header: "Create Individual Account"
|
||||
# create_header: "Create Account"
|
||||
email_announcements: "Получать оповещения по email" # {change}
|
||||
creating: "Создание аккаунта..."
|
||||
# create_account: "Create Account"
|
||||
create_student_header: "Создать учетную запись Ученика"
|
||||
create_teacher_header: "Создать учетную запись Учителя"
|
||||
create_individual_header: "Создать личную учетную запись"
|
||||
create_header: "Создать учетную запись"
|
||||
email_announcements: "Получать оповещения по email о новых уровнях и возможностях на CodeCombat"
|
||||
creating: "Создаем учетную запись..."
|
||||
create_account: "Создать учетную запись"
|
||||
sign_up: "Регистрация"
|
||||
log_in: "вход с паролем"
|
||||
required: "Войдите для того, чтобы продолжить."
|
||||
login_switch: "Уже есть аккаунт?"
|
||||
school_name: "Название школы and город"
|
||||
login_switch: "Уже есть учетная запись?"
|
||||
school_name: "Название школы и город"
|
||||
optional: "не обязательно"
|
||||
school_name_placeholder: "Школа № 2, город Электросталь, Московская область"
|
||||
# connect_with: "Connect with:"
|
||||
connect_with: "Зарегистрироваться с помощью:"
|
||||
connected_gplus_header: "Вы успешно авторизовались через Google+!"
|
||||
connected_gplus_p: "Теперь можно войти используя аккаунт Google+."
|
||||
gplus_exists: "У вас уже имеется аккаунт связанный с Google+!"
|
||||
connected_facebook_header: "Вы успешно авторизовались через Facebook!"
|
||||
connected_facebook_p: "Теперь можно войти используя аккаунт Facebook."
|
||||
facebook_exists: "У вас уже имеется аккаунт связанный сh Facebook!"
|
||||
facebook_exists: "У вас уже имеется аккаунт связанный с Facebook!"
|
||||
hey_students: "Студенты, введите код от класса вашего учителя."
|
||||
# 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."
|
||||
# classroom_not_found: "No classes exist with this Class Code. Check your spelling or ask your teacher for help."
|
||||
# checking: "Checking..."
|
||||
# account_exists: "This email is already in use:" # {change}
|
||||
# sign_in: "Sign in"
|
||||
# email_good: "Email looks good!"
|
||||
# name_taken: "Username already taken! Try {{suggestedName}}?"
|
||||
# name_available: "Username available!"
|
||||
# name_is_email: "Username may not be an email"
|
||||
# choose_type: "Choose your account type:"
|
||||
# teacher_type_1: "Teach programming using CodeCombat!"
|
||||
# teacher_type_2: "Set up your class"
|
||||
# teacher_type_3: "Access Course Guides"
|
||||
# teacher_type_4: "View student progress"
|
||||
# signup_as_teacher: "Sign up as a Teacher"
|
||||
# student_type_1: "Learn to program while playing an engaging game!"
|
||||
# student_type_2: "Play with your class"
|
||||
# student_type_3: "Compete in arenas"
|
||||
# student_type_4: "Choose your hero!"
|
||||
# student_type_5: "Have your Class Code ready!"
|
||||
# signup_as_student: "Sign up as a Student"
|
||||
# individuals_or_parents: "Individuals & Parents"
|
||||
# individual_type: "For players learning to code outside of a class. Parents should sign up for an account here."
|
||||
# signup_as_individual: "Sign up as an Individual"
|
||||
# enter_class_code: "Enter your Class Code"
|
||||
# enter_birthdate: "Enter your birthdate:"
|
||||
# ask_teacher_1: "Ask your teacher for your Class Code."
|
||||
# ask_teacher_2: "Not part of a class? Create an "
|
||||
# ask_teacher_3: "Individual Account"
|
||||
# ask_teacher_4: " instead."
|
||||
# about_to_join: "You're about to join:"
|
||||
# enter_parent_email: "Enter your parent’s email address:"
|
||||
# parent_email_error: "Something went wrong when trying to send the email. Check the email address and try again."
|
||||
# parent_email_sent: "We’ve sent an email with further instructions on how to create an account. Ask your parent to check their inbox."
|
||||
# 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_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:"
|
||||
# start_playing: "Start Playing!"
|
||||
# sso_connected: "Successfully connected with:"
|
||||
birthday: "День рождения"
|
||||
parent_email_blurb: "Мы знаем что вы в нетерпении начать учиться программировать — мы тоже! Ваши родители получат письмо с дальнейшими инструкциями, как создать учетную запись. Пишите нам на email {{email_link}} если есть любые вопросы."
|
||||
classroom_not_found: "Нет класса с таким кодом. Проверьте написание или попросите учителя помочь."
|
||||
checking: "Проверяем..."
|
||||
account_exists: "Этот email-адрес уже используется:" # {change}
|
||||
sign_in: "Зарегистрироваться"
|
||||
email_good: "С email-адресом все в порядке!"
|
||||
name_taken: "Имя пользователя уже используется! Может {{suggestedName}}?"
|
||||
name_available: "Имя пользователя доступно!"
|
||||
name_is_email: "Имя пользователя не должно быть email-адресом"
|
||||
choose_type: "Выбирите тип учетной записи:"
|
||||
teacher_type_1: "Обучайте с помощью CodeCombat!"
|
||||
teacher_type_2: "Настраивайте ваш класс"
|
||||
teacher_type_3: "Получите доступ к учебным материалам "
|
||||
teacher_type_4: "Следите за прогрессом учеников"
|
||||
signup_as_teacher: "Зарегистрироваться как Учитель"
|
||||
student_type_1: "Учитесь программировать, пока играете в захватывающую игру!"
|
||||
student_type_2: "Играйте вместе с классом"
|
||||
student_type_3: "Соревнуйтесь на аренах"
|
||||
student_type_4: "Выбирайте своего героя!"
|
||||
student_type_5: "Нужен актуальный код для класса!"
|
||||
signup_as_student: "Зарегистрироваться как Ученик"
|
||||
individuals_or_parents: "Индивидуальный и Родители"
|
||||
individual_type: "Для игроков, которые учатся без класса. Родители должны создать учетную запись."
|
||||
signup_as_individual: "Зарегистрироваться как индивидуальный игрок"
|
||||
enter_class_code: "Введите ваш код для класса"
|
||||
enter_birthdate: "Введите вашу дату рождения:"
|
||||
ask_teacher_1: "Спросите вашего учителя код для класса."
|
||||
ask_teacher_2: "Не относишься к учебному классу? Создай "
|
||||
ask_teacher_3: "Личную учетную запись"
|
||||
ask_teacher_4: " вместо этого."
|
||||
about_to_join: "Вы присоединяетесь к:"
|
||||
enter_parent_email: "Введите email-адрес одного из родителей:"
|
||||
parent_email_error: "Что-то пошло не так, когда мы отправляли письмо. Проверьте email-адрес и повторите."
|
||||
parent_email_sent: "Мы послали электронное письмо с дальнейшими инструкциями, как создать учетную запись. Попроси родителей проверить их входящие письма."
|
||||
account_created: "Учетная запись создана!"
|
||||
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!"
|
||||
write_this_down: "Запишите это:"
|
||||
start_playing: "Начать играть!"
|
||||
sso_connected: "Успешно подключились с помощью:"
|
||||
|
||||
recover:
|
||||
recover_account_title: "Восстановить аккаунт"
|
||||
recover_account_title: "Восстановить учетную запись"
|
||||
send_password: "Отправить пароль для восстановления"
|
||||
recovery_sent: "Письмо с паролем отправлено."
|
||||
|
||||
|
@ -340,8 +340,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
saving: "Сохранение..."
|
||||
sending: "Отправка..."
|
||||
send: "Отправить"
|
||||
# sent: "Sent"
|
||||
# type: "Type"
|
||||
sent: "Отправлено"
|
||||
type: "Тип"
|
||||
cancel: "Отмена"
|
||||
save: "Сохранить"
|
||||
publish: "Опубликовать"
|
||||
|
@ -411,8 +411,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
wizard: "Волшебник"
|
||||
first_name: "Имя"
|
||||
last_name: "Фамилия"
|
||||
# last_initial: "Last Initial"
|
||||
username: "Имя юзера"
|
||||
last_initial: "Инициалы фамилии"
|
||||
username: "Имя пользователя"
|
||||
|
||||
units:
|
||||
second: "секунда"
|
||||
|
@ -431,13 +431,13 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
years: "лет"
|
||||
|
||||
play_level:
|
||||
level_complete: "Уровень завершен"
|
||||
completed_level: "Завершённый уровень:"
|
||||
level_complete: "Уровень пройден"
|
||||
completed_level: "Пройденный уровень:"
|
||||
course: "Курс:"
|
||||
done: "Готово"
|
||||
next_level: "Следующий уровень"
|
||||
next_game: "Следующая игра"
|
||||
# programming_language: "Programming language"
|
||||
programming_language: "Язык программирования"
|
||||
show_menu: "Показать меню игры"
|
||||
home: "На главную" # Not used any more, will be removed soon.
|
||||
level: "Уровень" # Like "Level: Dungeons of Kithgard"
|
||||
|
@ -458,12 +458,12 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
reload_confirm: "Перезагрузить всё"
|
||||
victory: "Победа"
|
||||
victory_title_prefix: "Уровень "
|
||||
victory_title_suffix: " завершён"
|
||||
victory_title_suffix: " пройден"
|
||||
victory_sign_up: "Зарегистрируйтесь, чтобы сохранить прогресс"
|
||||
victory_sign_up_poke: "Хотите сохранить ваш код? Создайте бесплатный аккаунт!"
|
||||
victory_sign_up_poke: "Хотите сохранить ваш код? Создайте бесплатную учетную запись!"
|
||||
victory_rate_the_level: "Оцените уровень:" # {change}
|
||||
victory_return_to_ladder: "Вернуться к ладдеру"
|
||||
victory_saving_progress: "Процесс сохранения"
|
||||
victory_return_to_ladder: "Вернуться к таблице"
|
||||
victory_saving_progress: "Сохранить прогресс"
|
||||
victory_go_home: "На главную"
|
||||
victory_review: "Расскажите нам больше!"
|
||||
victory_review_placeholder: "Как вам уровень?"
|
||||
|
@ -474,13 +474,13 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
victory_new_item: "Новый предмет"
|
||||
victory_viking_code_school: "Ого, это было тяжелый уровень! Если вы еще не разработчик программ, вам стоит им стать. Вы только что ускорири принятие в Школу Викингов, где вы сможете поднять свои навыки на новый уровень и стать профессиональным веб-разработчиком за 14 недель."
|
||||
victory_become_a_viking: "Станьте Викингом"
|
||||
victory_no_progress_for_teachers: "Прогресс не сохраняется для учителей. Но, вы можете для себя добавить аккаунт студента в свою классную комнату."
|
||||
victory_no_progress_for_teachers: "Прогресс не сохраняется для учителей. Но, вы можете для себя добавить учетную запись ученика в свою классную комнату."
|
||||
guide_title: "Руководство"
|
||||
tome_cast_button_run: "Запустить"
|
||||
tome_cast_button_running: "В процессе"
|
||||
tome_cast_button_ran: "Запущен"
|
||||
tome_submit_button: "Завершить"
|
||||
tome_reload_method: "Загрузить оригинальный код для этого метода" # {change}
|
||||
tome_reload_method: "Загрузить оригинальный код и начать уровень заново" # {change}
|
||||
tome_available_spells: "Доступные заклинания"
|
||||
tome_your_skills: "Ваши навыки"
|
||||
tome_current_method: "Текущий метод"
|
||||
|
@ -491,13 +491,13 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
keyboard_shortcuts: "Горячие клавиши"
|
||||
loading_ready: "Готово!"
|
||||
loading_start: "Начать уровень"
|
||||
problem_alert_title: "Исправьте ваш Код"
|
||||
problem_alert_title: "Исправьте код"
|
||||
time_current: "Текущее:"
|
||||
time_total: "Максимальное:"
|
||||
time_goto: "Перейти на:"
|
||||
non_user_code_problem_title: "Невозможно загрузить уровень"
|
||||
infinite_loop_title: "Обнаружен бесконечный цикл"
|
||||
infinite_loop_description: "Код сотворения мира не завершил выполнение. Это могло случиться из-за реально медленного кода или наличия бесконечного цикла. Или там может быть баг. Вы можете попытаться запустить этот код еще раз или сбросить код в состояние по умолчанию. Если проблема не будет решена, дайте нам знать."
|
||||
infinite_loop_description: "Код сотворения мира не завершил выполнение. Это могло случиться из-за очень медленного кода или наличия бесконечного цикла. Или там может быть баг. Вы можете попытаться запустить этот код еще раз или сбросить код в состояние по умолчанию. Если проблема не будет решена, дайте нам знать."
|
||||
check_dev_console: "Вы так же можете открыть консоль разработчика, чтобы увидеть, что может идти не так."
|
||||
check_dev_console_link: "(инструкции)"
|
||||
infinite_loop_try_again: "Попробовать снова"
|
||||
|
@ -542,32 +542,32 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
tip_optimization_operator: "В каждом языке есть оператор оптимизации. В большинстве языков это оператор ‘//’"
|
||||
tip_lines_of_code: "Измерение прогресса программирования в строках кода - это как измерять прогресс построения самолета по его весу. — Bill Gates"
|
||||
tip_source_code: "Я хочу изменить мир, но они вряд ли дадут мне исходники."
|
||||
tip_javascript_java: "Java к JavaScript относится так же, как кол относится к колготкам. - Chris Heilmann (перефраз.)"
|
||||
tip_move_forward: "Что бы вы ни делали, вы должны двигаться вперед. - Martin Luther King Jr"
|
||||
tip_javascript_java: "Java к JavaScript относится так же, как кол относится к колготкам. (перефраз.) - Крис Хейльман"
|
||||
tip_move_forward: "Что бы вы ни делали, вы должны двигаться вперед. - Мартин Лютер Кинг Мл."
|
||||
tip_google: "У вас проблема, которую вы не можете решить? Гуглите!"
|
||||
tip_adding_evil: "Добавим щепотку зла."
|
||||
tip_hate_computers: "Есть одна вещь в людях, которые думают, что они ненавидят компьютеры. Что они на самом деле ненавидят, так это плохих программистов. - Larry Niven"
|
||||
tip_open_source_contribute: "Вы можете помочь сделать CodeCombat лучше!"
|
||||
tip_hate_computers: "Есть одна вещь в людях, которые думают, что они ненавидят компьютеры. Что они на самом деле ненавидят, так это плохих программистов. - Ларри Нивен"
|
||||
tip_open_source_contribute: "Ты можешь помочь сделать CodeCombat лучше!"
|
||||
tip_recurse: "Итерация свойственна человеку, рекурсия божественна. - L. Peter Deutsch"
|
||||
tip_free_your_mind: "Отвлекись от всего, Нео. Страх, неверие, сомнения отбрось — очисти свой разум. - Morpheus"
|
||||
tip_strong_opponents: "Даже сильнейший противник имеет слабость. - Itachi Uchiha"
|
||||
tip_free_your_mind: "Отвлекись от всего, Нео. Страх, неверие, сомнения отбрось — очисти свой разум. - Морфей"
|
||||
tip_strong_opponents: "Даже сильнейший противник имеет слабость. - Итачи Учиха"
|
||||
tip_paper_and_pen: "Прежде чем начать программировать, вы всегда можете попробовать с листом бумаги и ручкой."
|
||||
tip_solve_then_write: "Сперва реши задачу, затем пиши код. - Джон Джонсон"
|
||||
tip_compiler_ignores_comments: "Порой мне кажется, что компилятор игнорирует мои комментарии."
|
||||
tip_understand_recursion: "Единственный способ понять рекурсию, это понять рекурсию."
|
||||
tip_life_and_polymorphism: "Открытый исходный код это как полоностью полиморфная гетерогенная структура: Все типы приветствуются."
|
||||
tip_mistakes_proof_of_trying: "Ошибка в коде подтвердила твои старания."
|
||||
# tip_adding_orgres: "Rounding up ogres."
|
||||
# tip_sharpening_swords: "Sharpening the swords."
|
||||
tip_adding_orgres: "Собираем огров."
|
||||
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_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_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_luna_lovegood: "Don't worry, you're just as sane as I am. - Luna Lovegood"
|
||||
# tip_good_idea: "The best way to have a good idea is to have a lot of ideas. - Linus Pauling"
|
||||
tip_self_taught: "Я самостоятельно научился 90% из того чему учился. И это нормально! - Хэнк Грин"
|
||||
tip_luna_lovegood: "Не переживай, ты также в своем уме, как и я. - Луна Лавгуд"
|
||||
tip_good_idea: "Лучший способ найти хорошую идею - иметь множество идей. - Линус Полинг"
|
||||
# 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:
|
||||
inventory_tab: "Инвентарь"
|
||||
|
@ -694,7 +694,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
javascript_blurb: "Язык для Сети."
|
||||
coffeescript_blurb: "Улучшенный синтаксис JavaScript."
|
||||
lua_blurb: "Скриптовый язык для игр."
|
||||
# java_blurb: "(Subscriber Only) Android and enterprise."
|
||||
java_blurb: "(только для подписчиков) Андроид и бизнес."
|
||||
status: "Статус"
|
||||
hero_type: "Тип"
|
||||
weapons: "Оружие"
|
||||
|
@ -705,7 +705,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
health: "Жизнь"
|
||||
speed: "Скорость"
|
||||
regeneration: "Регенерация"
|
||||
range: "Зона" # As in "attack or visual range"
|
||||
range: "Дальность" # As in "attack or visual range"
|
||||
blocks: "Блокирует" # As in "this shield blocks this much damage"
|
||||
backstab: "Со спины" # As in "this dagger does this much backstab damage"
|
||||
skills: "Умения"
|
||||
|
@ -775,32 +775,33 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
story_link: "История"
|
||||
press_link: "Прессе"
|
||||
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_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."
|
||||
mission_description_1: "<strong>Программирование - это магия</strong>.
|
||||
Это способность создавать что-то с помощью воображения. Мы создавали CodeCombat, чтобы дать учащимся чувство силы волшебства на кончиках пальцев, когда они <strong>пишут код</strong>."
|
||||
mission_description_2: "Как оказалось, это позволяет им учится быстрее. СИЛЬНО быстрее. Это как живой рассказ вместо чтения учебника. Мы хотим принести этот метод в каждую школу и <strong>каждому ученику</strong>, потому что все должны иметь шанс научится магии программирования."
|
||||
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."
|
||||
nick_title: "Сооснователь" # {change}
|
||||
team_values: "Мы ценим открытый и вежливый диалог, где побеждают лучшие идеи. Наши решения основаны на иследовании пожеланий клиентов и наш процесс направлен на то, чтобы приносить осязаемые результаты им. У нас все при деле, от CEO до контрибьютеров на GitHub, потому что мы ценим рост и обучение в нашей команде."
|
||||
nick_title: "Сооснователь, CEO"
|
||||
nick_blurb: "Гуру мотивации"
|
||||
matt_title: "Сооснователь" # {change}
|
||||
cat_title: "Главный ремесленник" # {change}
|
||||
matt_title: "Сооснователь, CTO"
|
||||
cat_title: "Гейм дизайнер"
|
||||
cat_blurb: "Повелитель стихий"
|
||||
scott_title: "Сооснователь" # {change}
|
||||
scott_blurb: "Разумный"
|
||||
# maka_title: "Customer Advocate"
|
||||
# maka_blurb: "Storyteller"
|
||||
# rob_title: "Software Engineer"
|
||||
# rob_blurb: "Codes things and stuff"
|
||||
# josh_c_title: "Game Designer"
|
||||
# josh_c_blurb: "Designs games"
|
||||
# robin_title: "UX Design & Research"
|
||||
# robin_blurb: "Scaffolding"
|
||||
josh_title: "Дизайнер игры"
|
||||
scott_title: "Сооснователь, инженер программист" # {change}
|
||||
scott_blurb: "Благоразумный"
|
||||
maka_title: "Адвокат клиентов"
|
||||
maka_blurb: "Рассказчик"
|
||||
rob_title: "Инженер программист"
|
||||
rob_blurb: "Программирует все"
|
||||
josh_c_title: "Гейм дизайнер"
|
||||
josh_c_blurb: "Делает игры"
|
||||
robin_title: "UX дизайнер & Исследования"
|
||||
# robin_blurb: "Scaffolding"
|
||||
josh_title: "Гейм дизайнер"
|
||||
josh_blurb: "Пол - это лава"
|
||||
# phoenix_title: "Software Engineer"
|
||||
# nolan_title: "Territory Manager"
|
||||
# elliot_title: "Partnership Manager"
|
||||
# elliot_blurb: "Mindreader"
|
||||
# lisa_title: "Market Development Rep"
|
||||
phoenix_title: "Инженер программист"
|
||||
nolan_title: "Региональный менеджер"
|
||||
elliot_title: "Менеджер партнерства"
|
||||
elliot_blurb: "Читающий мысли"
|
||||
lisa_title: "Представитель по развитию рынка"
|
||||
retrostyle_title: "Иллюстрирование"
|
||||
retrostyle_blurb: "RetroStyle Games"
|
||||
jose_title: "Музыка"
|
||||
|
|
|
@ -298,6 +298,10 @@ class ModelResource extends Resource
|
|||
@loadsAttempted = 0
|
||||
|
||||
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
|
||||
tryLoad = =>
|
||||
return if this.isLoaded
|
||||
|
|
|
@ -38,7 +38,7 @@ module.exports = class ThangType extends CocoModel
|
|||
urlRoot: '/db/thang.type'
|
||||
building: {}
|
||||
editableByArtisans: true
|
||||
@defaultActions: ['idle', 'die', 'move', 'attack']
|
||||
@defaultActions: ['idle', 'die', 'move', 'attack', 'trick', 'cast']
|
||||
|
||||
initialize: ->
|
||||
super()
|
||||
|
|
|
@ -9,7 +9,7 @@ _.extend CampaignSchema.properties, {
|
|||
i18n: {type: 'object', title: 'i18n', format: 'i18n', props: ['name', 'fullName', 'description']}
|
||||
fullName: { type: 'string', title: 'Full Name', description: 'Ex.: "Kithgard Dungeon"' }
|
||||
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 {},
|
||||
mp3: { type: 'string', format: 'sound-file' }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#components-documentation-view
|
||||
background-color: #e4cf8c
|
||||
height: 100%
|
||||
height: calc(100% - 90px)
|
||||
|
||||
#toggle-all-component-code
|
||||
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
|
||||
each course in view.courses.models
|
||||
- var campaign = view.campaigns.get(course.get('campaignID'));
|
||||
if !campaign
|
||||
- continue;
|
||||
- var levels = campaign.getLevels().models;
|
||||
- levelsTotal += levels.length;
|
||||
tr
|
||||
|
@ -26,6 +28,8 @@ block content
|
|||
td All
|
||||
each course in view.courses.models
|
||||
- var campaign = view.campaigns.get(course.get('campaignID'));
|
||||
if !campaign
|
||||
- continue;
|
||||
- var levels = campaign.getLevels().models;
|
||||
- levelCounts = levels.length;
|
||||
strong #{course.get('name')}
|
||||
|
|
|
@ -30,8 +30,8 @@ block content
|
|||
thead
|
||||
tr
|
||||
th Created
|
||||
th NCES District
|
||||
th School Name
|
||||
th School District
|
||||
th.number NCES District Schools
|
||||
th.number NCES District Students
|
||||
th.number NCES School Students
|
||||
|
@ -44,8 +44,8 @@ block content
|
|||
- continue;
|
||||
tr
|
||||
td.created= trialRequest.get('created').substring(0, 10)
|
||||
td= trialRequest.get('properties').nces_district || ''
|
||||
td= trialRequest.get('properties').organization || ''
|
||||
td= trialRequest.get('properties').nces_name || trialRequest.get('properties').organization || ''
|
||||
td= trialRequest.get('properties').nces_district || trialRequest.get('properties').district || ''
|
||||
td= trialRequest.get('properties').nces_district_schools || ''
|
||||
td= trialRequest.get('properties').nces_district_students || ''
|
||||
td= trialRequest.get('properties').nces_students || ''
|
||||
|
|
|
@ -144,12 +144,12 @@ block outer_content
|
|||
div.tab-pane#related-achievements-view
|
||||
|
||||
div.tab-pane#editor-level-documentation
|
||||
ul.nav.nav-pills.nav-justified
|
||||
li
|
||||
a(href="#components-documentation-view", data-toggle="pill", data-i18n="resources.components") Components
|
||||
li
|
||||
a(href="#systems-documentation-view", data-toggle="pill", data-i18n="resources.systems") Systems
|
||||
div.tab-content
|
||||
ul.nav.nav-pills.nav-justified
|
||||
li
|
||||
a(href="#components-documentation-view", data-toggle="pill", data-i18n="resources.components") Components
|
||||
li
|
||||
a(href="#systems-documentation-view", data-toggle="pill", data-i18n="resources.systems") Systems
|
||||
div.tab-pane#components-documentation-view
|
||||
div.tab-pane#systems-documentation-view
|
||||
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
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
|
||||
.panel
|
||||
.panel-body
|
||||
p(data-i18n="editor.no_achievements") No achievements added for this level yet.
|
||||
else
|
||||
table.table.table-hover
|
||||
thead
|
||||
tr
|
||||
th
|
||||
th(data-i18n="general.name") Name
|
||||
th(data-i18n="general.description") Description
|
||||
th XP
|
||||
tbody
|
||||
each achievement in view.achievements.models
|
||||
tr
|
||||
td(style="width: 20px")
|
||||
img.achievement-icon-small(src=achievement.getImageURL() alt="#{achievement.get('name') icon")
|
||||
td
|
||||
a(href="/editor/achievement/#{achievement.get('slug')}")= achievement.get('name', true)
|
||||
td= achievement.get('description', true)
|
||||
td= achievement.get('worth', true)
|
||||
if !view.achievements.models.length
|
||||
.panel
|
||||
.panel-body
|
||||
p(data-i18n="editor.no_achievements") No achievements added for this level yet.
|
||||
else
|
||||
table.table.table-hover
|
||||
thead
|
||||
tr
|
||||
th
|
||||
th(data-i18n="general.name") Name
|
||||
th(data-i18n="general.description") Description
|
||||
th XP
|
||||
tbody
|
||||
each achievement in view.achievements.models
|
||||
tr
|
||||
td(style="width: 20px")
|
||||
img.achievement-icon-small(src=achievement.getImageURL() alt="#{achievement.get('name') icon")
|
||||
td
|
||||
a(href="/editor/achievement/#{achievement.get('slug')}")= achievement.get('name', true)
|
||||
td= achievement.get('description', true)
|
||||
td= achievement.get('worth', true)
|
||||
|
|
|
@ -1,42 +1,44 @@
|
|||
mixin task-row(cid)
|
||||
- var task = view.getTaskByCID(cid)
|
||||
- var taskName = task.get('name');
|
||||
- var isComplete = task.get('complete')
|
||||
tr.task-row(data-task-cid=cid)
|
||||
td.task-check
|
||||
div.checkbox
|
||||
input(type='checkbox', checked=(isComplete || false)).task-input
|
||||
if task.get('curEdit') == true
|
||||
td.edit-cell
|
||||
td.task-name
|
||||
input(type="input", value=taskName)#cur-edit
|
||||
else
|
||||
td.edit-cell
|
||||
span.glyphicon.glyphicon-edit.start-edit
|
||||
td.task-name
|
||||
- var result = view.getTaskURL(taskName)
|
||||
if result !== null
|
||||
// https://github.com/codecombat/codecombat/wiki/Tasks-Tab#<slug goes here>
|
||||
a(href='https://github.com/codecombat/codecombat/wiki/Tasks-Tab#' + result, target='blank')= taskName
|
||||
.nano.editor-nano-container
|
||||
.nano-content
|
||||
mixin task-row(cid)
|
||||
- var task = view.getTaskByCID(cid)
|
||||
- var taskName = task.get('name');
|
||||
- var isComplete = task.get('complete')
|
||||
tr.task-row(data-task-cid=cid)
|
||||
td.task-check
|
||||
div.checkbox
|
||||
input(type='checkbox', checked=(isComplete || false)).task-input
|
||||
if task.get('curEdit') == true
|
||||
td.edit-cell
|
||||
td.task-name
|
||||
input(type="input", value=taskName)#cur-edit
|
||||
else
|
||||
span= taskName
|
||||
td.edit-cell
|
||||
span.glyphicon.glyphicon-edit.start-edit
|
||||
td.task-name
|
||||
- var result = view.getTaskURL(taskName)
|
||||
if result !== null
|
||||
// https://github.com/codecombat/codecombat/wiki/Tasks-Tab#<slug goes here>
|
||||
a(href='https://github.com/codecombat/codecombat/wiki/Tasks-Tab#' + result, target='blank')= taskName
|
||||
else
|
||||
span= taskName
|
||||
|
||||
block
|
||||
table.table.table-striped.table-hover
|
||||
tr
|
||||
th.task-check Complete
|
||||
th.edit-cell Edit
|
||||
th Incomplete Tasks
|
||||
for task in (view.taskArray() || [])
|
||||
if task.get('revert').complete !== true
|
||||
+task-row(task.cid)
|
||||
tr
|
||||
th.task-check
|
||||
th.edit-cell
|
||||
th Completed Tasks
|
||||
for task in (view.taskArray() || [])
|
||||
if task.get('revert').complete === true
|
||||
+task-row(task.cid)
|
||||
button#create-task.btn.btn-primary Add Task
|
||||
if view.missingDefaults().length !== 0
|
||||
button#add-default-tasks.btn.btn-default Add Default Tasks
|
||||
block
|
||||
table.table.table-striped.table-hover
|
||||
tr
|
||||
th.task-check Complete
|
||||
th.edit-cell Edit
|
||||
th Incomplete Tasks
|
||||
for task in (view.taskArray() || [])
|
||||
if task.get('revert').complete !== true
|
||||
+task-row(task.cid)
|
||||
tr
|
||||
th.task-check
|
||||
th.edit-cell
|
||||
th Completed Tasks
|
||||
for task in (view.taskArray() || [])
|
||||
if task.get('revert').complete === true
|
||||
+task-row(task.cid)
|
||||
button#create-task.btn.btn-primary Add Task
|
||||
if view.missingDefaults().length !== 0
|
||||
button#add-default-tasks.btn.btn-default Add Default Tasks
|
||||
|
|
|
@ -28,40 +28,36 @@ block content
|
|||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.username")
|
||||
span.control-label(data-i18n="general.username")
|
||||
input.form-control(disabled=true value=me.get('name'))
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
#email-form-group.form-group
|
||||
label.control-label(data-i18n="general.email")
|
||||
span.control-label(data-i18n="general.email")
|
||||
input.form-control(name='email' disabled=true value=me.get('email'))
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.first_name")
|
||||
span.control-label(data-i18n="general.first_name")
|
||||
input.form-control(name="firstName" value=me.get('firstName') || '')
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.last_name")
|
||||
span.control-label(data-i18n="general.last_name")
|
||||
input.form-control(name="lastName" value=me.get('lastName') || '')
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.phone_number")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||
input.form-control(name="phoneNumber")
|
||||
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.role_help")
|
||||
span.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
select.form-control(name="role")
|
||||
option(data-i18n="teachers_quote.role_default", , value='')
|
||||
option(data-i18n="courses.teacher", value="Teacher")
|
||||
|
@ -75,30 +71,40 @@ block content
|
|||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.organization_label")
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.organization_label")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
input.form-control#organization-control(name="organization")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
//- TODO: algolia and form errors both change form-control
|
||||
//- TODO: District not red on validation error
|
||||
span.control-label.form-control.nullify-form-control(data-i18n="teachers_quote.district_label")
|
||||
input.form-control#district-control(name="district", data-i18n="[placeholder]teachers_quote.district_na")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
span.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-labellabel.control-label(data-i18n="teachers_quote.country")
|
||||
span.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
span.control-labelspan.control-label(data-i18n="teachers_quote.country")
|
||||
input.form-control(name="country")
|
||||
|
||||
#form-students-info
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="courses.number_programming_students")
|
||||
span.control-label(data-i18n="courses.number_programming_students")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||
select.form-control(name="numStudents")
|
||||
|
@ -113,7 +119,7 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="courses.number_total_students")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
select.form-control(name="numStudentsTotal")
|
||||
|
@ -126,11 +132,10 @@ block content
|
|||
|
||||
.form-group
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-10
|
||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.col-md-offset-2.col-md-4
|
||||
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||
.col-md-offset-2.col-md-5
|
||||
.checkbox
|
||||
label
|
||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||
|
@ -156,7 +161,7 @@ block content
|
|||
|
||||
#anything-else-row.row.m-y-2
|
||||
.col-md-offset-2.col-md-8
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.anything_else")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
textarea.form-control(rows=8, name="notes")
|
||||
|
|
|
@ -34,49 +34,47 @@ block content
|
|||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.username")
|
||||
span.control-label(data-i18n="general.username")
|
||||
input.form-control(name="name")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
#email-form-group.form-group
|
||||
label.control-label(data-i18n="general.email")
|
||||
span.control-label(data-i18n="general.email")
|
||||
input.form-control(name="email")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.first_name")
|
||||
span.control-label(data-i18n="general.first_name")
|
||||
input.form-control(name="firstName")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.last_name")
|
||||
span.control-label(data-i18n="general.last_name")
|
||||
input.form-control(name="lastName")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.password")
|
||||
span.control-label(data-i18n="general.password")
|
||||
input.form-control(name="password1", type="password")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.confirm_password")
|
||||
span.control-label(data-i18n="general.confirm_password")
|
||||
input.form-control(name="password2", type="password")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.phone_number")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||
input.form-control(name="phoneNumber")
|
||||
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
span.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
select.form-control(name="role")
|
||||
option(data-i18n="teachers_quote.role_default", , value='')
|
||||
option(data-i18n="courses.teacher", value="Teacher")
|
||||
|
@ -90,30 +88,40 @@ block content
|
|||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.organization_label")
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.organization_label")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
input.form-control#organization-control(name="organization")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
//- TODO: algolia and form errors both change form-control
|
||||
//- TODO: District not red on validation error
|
||||
span.control-label.form-control.nullify-form-control(data-i18n="teachers_quote.district_label")
|
||||
input.form-control#district-control(name="district", data-i18n="[placeholder]teachers_quote.district_na")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
span.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-labellabel.control-label(data-i18n="teachers_quote.country")
|
||||
span.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
span.control-label(data-i18n="teachers_quote.country")
|
||||
input.form-control(name="country")
|
||||
|
||||
#form-students-info
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="courses.number_programming_students")
|
||||
span.control-label(data-i18n="courses.number_programming_students")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||
select.form-control(name="numStudents")
|
||||
|
@ -128,7 +136,7 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="courses.number_total_students")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
select.form-control(name="numStudentsTotal")
|
||||
|
@ -140,14 +148,11 @@ block content
|
|||
option 10,000+
|
||||
|
||||
.form-group
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-10
|
||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||
|
||||
.col-md-offset-2.col-md-5
|
||||
.col-md-offset-2.col-md-4
|
||||
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||
.checkbox
|
||||
label
|
||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||
|
@ -173,7 +178,7 @@ block content
|
|||
|
||||
#anything-else-row.row.m-y-2
|
||||
.col-md-offset-2.col-md-8
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.anything_else")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@ if completed
|
|||
.small-details.nowrap
|
||||
span.spr(data-i18n='teacher.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
|
||||
//- .small-details
|
||||
//- i(data-i18n='teacher.click_to_view_solution')
|
||||
|
|
|
@ -36,7 +36,7 @@ block content
|
|||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="general.username")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
- var name = me.get('name') || '';
|
||||
|
@ -44,20 +44,20 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="share_progress_modal.form_label")
|
||||
span.control-label(data-i18n="share_progress_modal.form_label")
|
||||
- var email = me.get('email') || '';
|
||||
input.form-control(name="email" value=email, disabled=!!email)
|
||||
|
||||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.first_name")
|
||||
span.control-label(data-i18n="general.first_name")
|
||||
- var firstName = me.get('firstName') || '';
|
||||
input.form-control(name="firstName" value=firstName, disabled=!!firstName)
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.last_name")
|
||||
span.control-label(data-i18n="general.last_name")
|
||||
- var lastName = me.get('lastName') || '';
|
||||
input.form-control(name="lastName" value=lastName, disabled=!!lastName)
|
||||
|
||||
|
@ -65,23 +65,20 @@ block content
|
|||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span(data-i18n="teachers_quote.phone_number")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||
input.form-control(name="phoneNumber")
|
||||
span.control-label(data-i18n="teachers_quote.phone_number")
|
||||
input.form-control(name="phoneNumber", data-i18n="[placeholder]teachers_quote.phone_number_help")
|
||||
|
||||
if me.isAnonymous()
|
||||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
#email-form-group.form-group
|
||||
label.control-label(data-i18n="general.email")
|
||||
span.control-label(data-i18n="general.email")
|
||||
- var email = me.get('email') || '';
|
||||
input.form-control(name="email" type="email", value=email, disabled=!!email)
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.phone_number")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.phone_number_help")
|
||||
|
@ -91,7 +88,7 @@ block content
|
|||
.row
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
span.control-label(data-i18n="teachers_quote.primary_role_label")
|
||||
select.form-control(name="role")
|
||||
option(data-i18n="teachers_quote.primary_role_default", , value='')
|
||||
option(data-i18n="courses.teacher", value="Teacher")
|
||||
|
@ -103,7 +100,7 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.purchaser_role_label")
|
||||
span.control-label(data-i18n="teachers_quote.purchaser_role_label")
|
||||
select.form-control(name="purchaserRole")
|
||||
option(data-i18n="teachers_quote.purchaser_role_default", , value='')
|
||||
option(data-i18n="teachers_quote.influence_advocate", value="Influence/Advocate")
|
||||
|
@ -112,33 +109,43 @@ block content
|
|||
option(data-i18n="teachers_quote.no_purchaser_role", value="No role in purchase decisions")
|
||||
|
||||
#form-school-info
|
||||
.row
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.organization_label")
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.organization_label")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
input.form-control#organization-control(name="organization")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
//- TODO: algolia and form errors both change form-control
|
||||
//- TODO: District not red on validation error
|
||||
span.control-label.form-control.nullify-form-control(data-i18n="teachers_quote.district_label")
|
||||
input.form-control#district-control(name="district", data-i18n="[placeholder]teachers_quote.district_na")
|
||||
|
||||
.row
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
span.control-label(data-i18n="teachers_quote.city")
|
||||
input.form-control(name="city")
|
||||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-labellabel.control-label(data-i18n="teachers_quote.country")
|
||||
span.control-label(data-i18n="teachers_quote.state")
|
||||
input.form-control(name="state")
|
||||
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4.col-sm-6
|
||||
.form-group
|
||||
span.control-labelspan.control-label(data-i18n="teachers_quote.country")
|
||||
input.form-control(name="country")
|
||||
|
||||
#form-students-info
|
||||
.row
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="courses.number_programming_students")
|
||||
span.control-label(data-i18n="courses.number_programming_students")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.num_students_help")
|
||||
select.form-control(name="numStudents")
|
||||
|
@ -153,7 +160,7 @@ block content
|
|||
|
||||
.col-md-4.col-sm-6
|
||||
.form-group
|
||||
label.control-label(data-i18n="courses.number_total_students")
|
||||
span.control-label(data-i18n="courses.number_total_students")
|
||||
select.form-control(name="numStudentsTotal")
|
||||
option(data-i18n="teachers_quote.num_students_default", value='')
|
||||
option 1-500
|
||||
|
@ -163,14 +170,11 @@ block content
|
|||
option 10,000+
|
||||
|
||||
.form-group
|
||||
|
||||
.row
|
||||
.col-md-offset-2.col-md-10
|
||||
label.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||
|
||||
.col-md-offset-2.col-md-5
|
||||
.row.m-y-2
|
||||
.col-md-offset-2.col-md-4
|
||||
span.control-label(data-i18n="teachers_quote.education_level_label")
|
||||
.help-block.small
|
||||
em.text-info(data-i18n="teachers_quote.education_level_help")
|
||||
.checkbox
|
||||
label
|
||||
input(type="checkbox" name="educationLevel" value="Elementary")
|
||||
|
@ -196,7 +200,7 @@ block content
|
|||
|
||||
#anything-else-row.row
|
||||
.col-md-offset-2.col-md-8
|
||||
label.control-label
|
||||
span.control-label
|
||||
span(data-i18n="teachers_quote.anything_else")
|
||||
span.spl.text-muted(data-i18n="signup.optional")
|
||||
|
||||
|
@ -210,7 +214,7 @@ block content
|
|||
input(type="hidden" name="nces_students")
|
||||
input(type="hidden" name="nces_phone")
|
||||
|
||||
#buttons-row.row.text-center
|
||||
#buttons-row.row.m-y-2.text-center
|
||||
input#submit-request-btn.btn.btn-lg.btn-primary(type="submit" data-i18n="[value]teachers_quote.title")
|
||||
|
||||
#form-submit-success.text-center(class=showDone ? '' : 'hide')
|
||||
|
@ -244,17 +248,17 @@ block content
|
|||
.row
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.username")
|
||||
span.control-label(data-i18n="general.username")
|
||||
input.form-control(name="name")
|
||||
|
||||
.row
|
||||
.col-md-offset-2.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.password")
|
||||
span.control-label(data-i18n="general.password")
|
||||
input.form-control(name="password1", type="password")
|
||||
.col-md-4
|
||||
.form-group
|
||||
label.control-label(data-i18n="general.confirm_password")
|
||||
span.control-label(data-i18n="general.confirm_password")
|
||||
input.form-control(name="password2", type="password")
|
||||
|
||||
.text-center
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
RootView = require 'views/core/RootView'
|
||||
CocoCollection = require 'collections/CocoCollection'
|
||||
Campaigns = require 'collections/Campaigns'
|
||||
Campaign = require 'models/Campaign'
|
||||
Course = require 'models/Course'
|
||||
|
||||
module.exports = class AdminClassroomLevelsView extends RootView
|
||||
|
@ -9,8 +9,8 @@ module.exports = class AdminClassroomLevelsView extends RootView
|
|||
|
||||
initialize: ->
|
||||
return super() unless me.isAdmin()
|
||||
@campaigns = new Campaigns()
|
||||
@supermodel.trackRequest @campaigns.fetchByType('course', { data: { project: 'levels,levelsUpdated' } })
|
||||
@campaigns = new CocoCollection([], { url: "/db/campaign", model: Campaign})
|
||||
@supermodel.loadCollection(@campaigns, 'campaigns')
|
||||
@courses = new CocoCollection([], { url: "/db/course", model: Course})
|
||||
@supermodel.loadCollection(@courses, 'courses')
|
||||
super()
|
||||
|
|
|
@ -56,6 +56,8 @@ require("locale/eo")
|
|||
require("locale/uz")
|
||||
require("locale/my")
|
||||
require("locale/et")
|
||||
require("locale/hr")
|
||||
require("locale/mi")
|
||||
|
||||
module.exports = class DiplomatView extends ContributeClassView
|
||||
id: 'diplomat-view'
|
||||
|
@ -140,3 +142,5 @@ module.exports = class DiplomatView extends ContributeClassView
|
|||
uz: [] # O'zbekcha, Uzbek
|
||||
my: [] # မြန်မာစကား, Myanmar language
|
||||
et: [] # Eesti, Estonian
|
||||
hr: [] # hrvatski jezik, Croatian
|
||||
mi: [] # te reo Māori, Māori
|
||||
|
|
|
@ -41,7 +41,10 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
@ownedClassrooms.fetchMine({data: {project: '_id'}})
|
||||
@supermodel.trackCollection(@ownedClassrooms)
|
||||
@courses = new Courses()
|
||||
@supermodel.trackRequest @courses.fetchReleased()
|
||||
if me.isAdmin()
|
||||
@supermodel.trackRequest @courses.fetch()
|
||||
else
|
||||
@supermodel.trackRequest @courses.fetchReleased()
|
||||
@campaigns = new Campaigns()
|
||||
@supermodel.trackRequest @campaigns.fetchByType('course', { data: { project: 'levels,levelsUpdated' } })
|
||||
@
|
||||
|
|
|
@ -365,12 +365,16 @@ module.exports = class CampaignView extends RootView
|
|||
return experienceScore
|
||||
|
||||
createLine: (o1, o2) ->
|
||||
p1 = x: o1.x, y: 0.66 * o1.y + 0.5
|
||||
p2 = x: o2.x, y: 0.66 * o2.y + 0.5
|
||||
mapHeight = parseFloat($(".map").css("height"))
|
||||
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))
|
||||
angle = Math.atan2(p1.y - p2.y, p2.x - p1.x) * 180 / Math.PI
|
||||
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">'))
|
||||
|
||||
applyCampaignStyles: ->
|
||||
|
|
|
@ -7,9 +7,9 @@ errors = require 'core/errors'
|
|||
User = require 'models/User'
|
||||
ConfirmModal = require 'views/editor/modal/ConfirmModal'
|
||||
algolia = require 'core/services/algolia'
|
||||
NCES_KEYS = ['id', 'name', 'district', 'district_id', 'district_schools', 'district_students', 'students', 'phone']
|
||||
|
||||
FORM_KEY = 'request-quote-form'
|
||||
DISTRICT_NCES_KEYS = ['district', 'district_id', 'district_schools', 'district_students', 'phone']
|
||||
SCHOOL_NCES_KEYS = DISTRICT_NCES_KEYS.concat(['id', 'name', 'students'])
|
||||
|
||||
module.exports = class ConvertToTeacherAccountView extends RootView
|
||||
id: 'convert-to-teacher-account-view'
|
||||
|
@ -40,7 +40,7 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
|||
return 'Your account has not been updated! If you continue, your changes will be lost.'
|
||||
|
||||
invalidateNCES: ->
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val ''
|
||||
|
||||
onLoaded: ->
|
||||
|
@ -75,16 +75,34 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
|||
"<div class='school'> #{hr.name.value} </div>" +
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="country"]').val 'USA'
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeForm()
|
||||
|
||||
$("#district-control").algolia_autocomplete({hint: false}, [
|
||||
source: (query, callback) ->
|
||||
algolia.schoolsIndex.search(query, { hitsPerPage: 5, aroundLatLngViaIP: false }).then (answer) ->
|
||||
callback answer.hits
|
||||
, ->
|
||||
callback []
|
||||
displayKey: 'district',
|
||||
templates:
|
||||
suggestion: (suggestion) ->
|
||||
hr = suggestion._highlightResult
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="organization"]').val '' # TODO: does not persist on tabbing: back to school, back to district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="country"]').val 'USA'
|
||||
for key in DISTRICT_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeForm()
|
||||
|
||||
onChangeForm: ->
|
||||
|
@ -97,28 +115,35 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
|||
|
||||
form = @$('form')
|
||||
attrs = forms.formToObject(form)
|
||||
trialRequestAttrs = _.cloneDeep(attrs)
|
||||
|
||||
# Don't save n/a district entries, but do validate required district client-side
|
||||
trialRequestAttrs = _.omit(trialRequestAttrs, 'district') if trialRequestAttrs.district?.replace(/\s/ig, '').match(/n\/a/ig)
|
||||
|
||||
if @$('#other-education-level-checkbox').is(':checked')
|
||||
val = @$('#other-education-level-input').val()
|
||||
attrs.educationLevel.push(val) if val
|
||||
trialRequestAttrs.educationLevel.push(val) if val
|
||||
|
||||
forms.clearFormAlerts(form)
|
||||
|
||||
result = tv4.validateMultiple(attrs, formSchema)
|
||||
result = tv4.validateMultiple(trialRequestAttrs, formSchema)
|
||||
error = false
|
||||
if not result.valid
|
||||
forms.applyErrorsToForm(form, result.errors)
|
||||
error = true
|
||||
if not _.size(attrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'Include at least one.')
|
||||
if not _.size(trialRequestAttrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'include at least one')
|
||||
error = true
|
||||
unless attrs.district
|
||||
forms.setErrorToProperty(form, 'district', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
if error
|
||||
forms.scrollToFirstError()
|
||||
return
|
||||
attrs['siteOrigin'] = 'convert teacher'
|
||||
trialRequestAttrs['siteOrigin'] = 'convert teacher'
|
||||
@trialRequest = new TrialRequest({
|
||||
type: 'course'
|
||||
properties: attrs
|
||||
properties: trialRequestAttrs
|
||||
})
|
||||
if me.get('role') is 'student' and not me.isAnonymous()
|
||||
modal = new ConfirmModal({
|
||||
|
@ -151,15 +176,14 @@ module.exports = class ConvertToTeacherAccountView extends RootView
|
|||
|
||||
formSchema = {
|
||||
type: 'object'
|
||||
required: [
|
||||
'firstName', 'lastName', 'organization', 'role', 'numStudents', 'city', 'state', 'country'
|
||||
]
|
||||
required: ['firstName', 'lastName', 'role', 'numStudents', 'city', 'state', 'country']
|
||||
properties:
|
||||
firstName: { type: 'string' }
|
||||
lastName: { type: 'string' }
|
||||
phoneNumber: { type: 'string' }
|
||||
role: { type: 'string' }
|
||||
organization: { type: 'string' }
|
||||
district: { type: 'string' }
|
||||
city: { type: 'string' }
|
||||
state: { type: 'string' }
|
||||
country: { type: 'string' }
|
||||
|
@ -172,5 +196,5 @@ formSchema = {
|
|||
notes: { type: 'string' }
|
||||
}
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
formSchema['nces_' + key] = type: 'string'
|
||||
|
|
|
@ -7,9 +7,9 @@ errors = require 'core/errors'
|
|||
User = require 'models/User'
|
||||
algolia = require 'core/services/algolia'
|
||||
|
||||
FORM_KEY = 'request-quote-form'
|
||||
SIGNUP_REDIRECT = '/teachers/classes'
|
||||
NCES_KEYS = ['id', 'name', 'district', 'district_id', 'district_schools', 'district_students', 'students', 'phone']
|
||||
DISTRICT_NCES_KEYS = ['district', 'district_id', 'district_schools', 'district_students', 'phone']
|
||||
SCHOOL_NCES_KEYS = DISTRICT_NCES_KEYS.concat(['id', 'name', 'students'])
|
||||
|
||||
module.exports = class CreateTeacherAccountView extends RootView
|
||||
id: 'create-teacher-account-view'
|
||||
|
@ -43,7 +43,7 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
super()
|
||||
|
||||
invalidateNCES: ->
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val ''
|
||||
|
||||
afterRender: ->
|
||||
|
@ -72,16 +72,34 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
"<div class='school'> #{hr.name.value} </div>" +
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="country"]').val 'USA'
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeForm()
|
||||
|
||||
$("#district-control").algolia_autocomplete({hint: false}, [
|
||||
source: (query, callback) ->
|
||||
algolia.schoolsIndex.search(query, { hitsPerPage: 5, aroundLatLngViaIP: false }).then (answer) ->
|
||||
callback answer.hits
|
||||
, ->
|
||||
callback []
|
||||
displayKey: 'district',
|
||||
templates:
|
||||
suggestion: (suggestion) ->
|
||||
hr = suggestion._highlightResult
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="organization"]').val '' # TODO: does not persist on tabbing: back to school, back to district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="country"]').val 'USA'
|
||||
for key in DISTRICT_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeForm()
|
||||
|
||||
onClickLoginLink: ->
|
||||
|
@ -101,6 +119,9 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
allAttrs = forms.formToObject(form)
|
||||
trialRequestAttrs = _.omit(allAttrs, 'name', 'password1', 'password2')
|
||||
|
||||
# Don't save n/a district entries, but do validate required district client-side
|
||||
trialRequestAttrs = _.omit(trialRequestAttrs, 'district') if trialRequestAttrs.district?.replace(/\s/ig, '').match(/n\/a/ig)
|
||||
|
||||
if @$('#other-education-level-checkbox').is(':checked')
|
||||
val = @$('#other-education-level-input').val()
|
||||
trialRequestAttrs.educationLevel.push(val) if val
|
||||
|
@ -112,18 +133,21 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
if not result.valid
|
||||
forms.applyErrorsToForm(form, result.errors)
|
||||
error = true
|
||||
if not forms.validateEmail(trialRequestAttrs.email)
|
||||
forms.setErrorToProperty(form, 'email', 'Invalid email.')
|
||||
if not error and not forms.validateEmail(trialRequestAttrs.email)
|
||||
forms.setErrorToProperty(form, 'email', 'invalid email')
|
||||
error = true
|
||||
if not _.size(trialRequestAttrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'Include at least one.')
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'include at least one')
|
||||
error = true
|
||||
unless allAttrs.district
|
||||
forms.setErrorToProperty(form, 'district', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
unless @gplusAttrs or @facebookAttrs
|
||||
if not allAttrs.password1
|
||||
forms.setErrorToProperty(form, 'password1', 'Required field')
|
||||
forms.setErrorToProperty(form, 'password1', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
else if not allAttrs.password2
|
||||
forms.setErrorToProperty(form, 'password2', 'Required field')
|
||||
forms.setErrorToProperty(form, 'password2', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
else if allAttrs.password1 isnt allAttrs.password2
|
||||
forms.setErrorToProperty(form, 'password1', 'Password fields are not equivalent')
|
||||
|
@ -225,7 +249,6 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
@$('input[type="password"]').attr('disabled', true)
|
||||
@$('#gplus-logged-in-row, #social-network-signups').toggleClass('hide')
|
||||
|
||||
|
||||
# Facebook signup
|
||||
|
||||
onClickFacebookSignupButton: ->
|
||||
|
@ -269,13 +292,9 @@ module.exports = class CreateTeacherAccountView extends RootView
|
|||
@$('#facebook-logged-in-row, #social-network-signups').toggleClass('hide')
|
||||
|
||||
|
||||
|
||||
formSchema = {
|
||||
type: 'object'
|
||||
required: [
|
||||
'firstName', 'lastName', 'email', 'organization', 'role', 'numStudents', 'city'
|
||||
'state', 'country'
|
||||
]
|
||||
required: ['firstName', 'lastName', 'email', 'role', 'numStudents', 'city', 'state', 'country']
|
||||
properties:
|
||||
password1: { type: 'string' }
|
||||
password2: { type: 'string' }
|
||||
|
@ -286,6 +305,7 @@ formSchema = {
|
|||
phoneNumber: { type: 'string' }
|
||||
role: { type: 'string' }
|
||||
organization: { type: 'string' }
|
||||
district: { type: 'string' }
|
||||
city: { type: 'string' }
|
||||
state: { type: 'string' }
|
||||
country: { type: 'string' }
|
||||
|
@ -298,5 +318,5 @@ formSchema = {
|
|||
notes: { type: 'string' }
|
||||
}
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
formSchema['nces_' + key] = type: 'string'
|
||||
|
|
|
@ -8,7 +8,8 @@ ConfirmModal = require 'views/editor/modal/ConfirmModal'
|
|||
algolia = require 'core/services/algolia'
|
||||
|
||||
SIGNUP_REDIRECT = '/teachers'
|
||||
NCES_KEYS = ['id', 'name', 'district', 'district_id', 'district_schools', 'district_students', 'students', 'phone']
|
||||
DISTRICT_NCES_KEYS = ['district', 'district_id', 'district_schools', 'district_students', 'phone']
|
||||
SCHOOL_NCES_KEYS = DISTRICT_NCES_KEYS.concat(['id', 'name', 'students'])
|
||||
|
||||
module.exports = class RequestQuoteView extends RootView
|
||||
id: 'request-quote-view'
|
||||
|
@ -46,7 +47,7 @@ module.exports = class RequestQuoteView extends RootView
|
|||
super()
|
||||
|
||||
invalidateNCES: ->
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val ''
|
||||
|
||||
afterRender: ->
|
||||
|
@ -75,16 +76,34 @@ module.exports = class RequestQuoteView extends RootView
|
|||
"<div class='school'> #{hr.name.value} </div>" +
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="district"]').val suggestion.district
|
||||
@$('input[name="country"]').val 'USA'
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeRequestForm()
|
||||
|
||||
$("#district-control").algolia_autocomplete({hint: false}, [
|
||||
source: (query, callback) ->
|
||||
algolia.schoolsIndex.search(query, { hitsPerPage: 5, aroundLatLngViaIP: false }).then (answer) ->
|
||||
callback answer.hits
|
||||
, ->
|
||||
callback []
|
||||
displayKey: 'district',
|
||||
templates:
|
||||
suggestion: (suggestion) ->
|
||||
hr = suggestion._highlightResult
|
||||
"<div class='district'>#{hr.district.value}, " +
|
||||
"<span>#{hr.city?.value}, #{hr.state.value}</span></div>"
|
||||
]).on 'autocomplete:selected', (event, suggestion, dataset) =>
|
||||
@$('input[name="organization"]').val '' # TODO: does not persist on tabbing: back to school, back to district
|
||||
@$('input[name="city"]').val suggestion.city
|
||||
@$('input[name="state"]').val suggestion.state
|
||||
@$('input[name="country"]').val 'USA'
|
||||
for key in DISTRICT_NCES_KEYS
|
||||
@$('input[name="nces_' + key + '"]').val suggestion[key]
|
||||
@onChangeRequestForm()
|
||||
|
||||
onChangeRequestForm: ->
|
||||
|
@ -96,32 +115,39 @@ module.exports = class RequestQuoteView extends RootView
|
|||
e.preventDefault()
|
||||
form = @$('#request-form')
|
||||
attrs = forms.formToObject(form)
|
||||
trialRequestAttrs = _.cloneDeep(attrs)
|
||||
|
||||
# Don't save n/a district entries, but do validate required district client-side
|
||||
trialRequestAttrs = _.omit(trialRequestAttrs, 'district') if trialRequestAttrs.district?.replace(/\s/ig, '').match(/n\/a/ig)
|
||||
|
||||
# custom other input logic
|
||||
if @$('#other-education-level-checkbox').is(':checked')
|
||||
val = @$('#other-education-level-input').val()
|
||||
attrs.educationLevel.push(val) if val
|
||||
trialRequestAttrs.educationLevel.push(val) if val
|
||||
|
||||
forms.clearFormAlerts(form)
|
||||
requestFormSchema = if me.isAnonymous() then requestFormSchemaAnonymous else requestFormSchemaLoggedIn
|
||||
result = tv4.validateMultiple(attrs, requestFormSchemaAnonymous)
|
||||
result = tv4.validateMultiple(trialRequestAttrs, requestFormSchemaAnonymous)
|
||||
error = false
|
||||
if not result.valid
|
||||
forms.applyErrorsToForm(form, result.errors)
|
||||
error = true
|
||||
if not forms.validateEmail(attrs.email)
|
||||
forms.setErrorToProperty(form, 'email', 'Invalid email.')
|
||||
if not error and not forms.validateEmail(trialRequestAttrs.email)
|
||||
forms.setErrorToProperty(form, 'email', 'invalid email')
|
||||
error = true
|
||||
if not _.size(attrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'Include at least one.')
|
||||
if not _.size(trialRequestAttrs.educationLevel)
|
||||
forms.setErrorToProperty(form, 'educationLevel', 'include at least one')
|
||||
error = true
|
||||
unless attrs.district
|
||||
forms.setErrorToProperty(form, 'district', $.i18n.t('common.required_field'))
|
||||
error = true
|
||||
if error
|
||||
forms.scrollToFirstError()
|
||||
return
|
||||
attrs['siteOrigin'] = 'demo request'
|
||||
trialRequestAttrs['siteOrigin'] = 'demo request'
|
||||
@trialRequest = new TrialRequest({
|
||||
type: 'course'
|
||||
properties: attrs
|
||||
properties: trialRequestAttrs
|
||||
})
|
||||
if me.get('role') is 'student' and not me.isAnonymous()
|
||||
modal = new ConfirmModal({
|
||||
|
@ -262,7 +288,7 @@ module.exports = class RequestQuoteView extends RootView
|
|||
requestFormSchemaAnonymous = {
|
||||
type: 'object'
|
||||
required: [
|
||||
'firstName', 'lastName', 'email', 'organization', 'role', 'purchaserRole', 'numStudents',
|
||||
'firstName', 'lastName', 'email', 'role', 'purchaserRole', 'numStudents',
|
||||
'numStudentsTotal', 'phoneNumber', 'city', 'state', 'country']
|
||||
properties:
|
||||
firstName: { type: 'string' }
|
||||
|
@ -273,6 +299,7 @@ requestFormSchemaAnonymous = {
|
|||
role: { type: 'string' }
|
||||
purchaserRole: { type: 'string' }
|
||||
organization: { type: 'string' }
|
||||
district: { type: 'string' }
|
||||
city: { type: 'string' }
|
||||
state: { type: 'string' }
|
||||
country: { type: 'string' }
|
||||
|
@ -285,7 +312,7 @@ requestFormSchemaAnonymous = {
|
|||
notes: { type: 'string' },
|
||||
}
|
||||
|
||||
for key in NCES_KEYS
|
||||
for key in SCHOOL_NCES_KEYS
|
||||
requestFormSchemaAnonymous['nces_' + key] = type: 'string'
|
||||
|
||||
# same form, but add username input
|
||||
|
|
|
@ -34,7 +34,8 @@ module.exports = class TeachersContactModal extends ModalView
|
|||
message = """
|
||||
Hi CodeCombat! I want to learn more about the Classroom experience and get licenses so that my students can access Computer Science 2 and on.
|
||||
|
||||
Name of School/District: #{props.organization or ''}
|
||||
Name of School #{props.nces_name or props.organization or ''}
|
||||
Name of District: #{props.nces_district or props.district or ''}
|
||||
Role: #{props.role or ''}
|
||||
Phone Number: #{props.phoneNumber or ''}
|
||||
"""
|
||||
|
|
|
@ -16,7 +16,7 @@ if (process.argv.length !== 10) {
|
|||
// TODO: Cleanup country/status lookup code
|
||||
|
||||
// Save as custom fields instead of user-specific lead notes (also saving nces_ props)
|
||||
const commonTrialProperties = ['organization', 'city', 'state', 'country'];
|
||||
const commonTrialProperties = ['organization', 'district', 'city', 'state', 'country'];
|
||||
|
||||
// Old properties which are deprecated or moved
|
||||
const customFieldsToRemove = [
|
||||
|
@ -327,7 +327,7 @@ function findCocoLeads(done) {
|
|||
if (!trialRequest.properties || !trialRequest.properties.email) continue;
|
||||
const email = trialRequest.properties.email.toLowerCase();
|
||||
emails.push(email);
|
||||
const name = trialRequest.properties.nces_name || trialRequest.properties.organization || trialRequest.properties.school || email;
|
||||
const name = trialRequest.properties.nces_name || trialRequest.properties.organization || trialRequest.properties.school || trialRequest.properties.district || trialRequest.properties.nces_district || email;
|
||||
if (!leads[name]) leads[name] = new CocoLead(name);
|
||||
leads[name].addTrialRequest(email, trialRequest);
|
||||
emailLeadMap[email] = leads[name];
|
||||
|
|
|
@ -105,7 +105,7 @@ module.exports =
|
|||
members = classroom.get('members') or []
|
||||
members = members.slice(memberSkip, memberSkip + memberLimit)
|
||||
dbqs = []
|
||||
select = 'state.complete level creator playtime changed dateFirstCompleted submitted'
|
||||
select = 'state.complete level creator playtime changed created dateFirstCompleted submitted'
|
||||
for member in members
|
||||
dbqs.push(LevelSession.find({creator: member.toHexString()}).select(select).exec())
|
||||
results = yield dbqs
|
||||
|
|
|
@ -11,10 +11,6 @@ cutoffDate = new Date(2015,11,11)
|
|||
cutoffID = mongoose.Types.ObjectId(Math.floor(cutoffDate/1000).toString(16)+'0000000000000000')
|
||||
|
||||
module.exports =
|
||||
logError: (user, msg) ->
|
||||
console.warn "Prepaid Error: [#{user.get('slug')} (#{user._id})] '#{msg}'"
|
||||
|
||||
|
||||
post: wrap (req, res) ->
|
||||
validTypes = ['course']
|
||||
unless req.body.type in validTypes
|
||||
|
@ -71,7 +67,7 @@ module.exports =
|
|||
update = { $push: { redeemers : { date: new Date(), userID: user._id } }}
|
||||
result = yield Prepaid.update(query, update)
|
||||
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')
|
||||
|
||||
update = {
|
||||
|
@ -142,7 +138,7 @@ module.exports =
|
|||
trialRequests = yield TrialRequest.find({$and: [{type: 'course'}, {applicant: {$in: userIDs}}]}, {applicant: 1, properties: 1}).lean()
|
||||
schoolPrepaidsMap = {}
|
||||
for trialRequest in trialRequests
|
||||
school = trialRequest.properties?.organization ? trialRequest.properties?.school
|
||||
school = trialRequest.properties?.nces_name ? trialRequest.properties?.organization ? trialRequest.properties?.school
|
||||
continue unless school
|
||||
if userPrepaidsMap[trialRequest.applicant.valueOf()]?.length > 0
|
||||
schoolPrepaidsMap[school] ?= []
|
||||
|
|
|
@ -184,6 +184,7 @@ module.exports = {
|
|||
email: 'an@email.com'
|
||||
phoneNumber: '555-555-5555'
|
||||
organization: 'Greendale'
|
||||
district: 'Green District'
|
||||
}
|
||||
}, attrs)
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ describe 'ConvertToTeacherAccountView (/teachers/update-account)', ->
|
|||
phoneNumber: '555-555-5555'
|
||||
role: 'Teacher'
|
||||
organization: 'School'
|
||||
district: 'District'
|
||||
city: 'Springfield'
|
||||
state: 'AA'
|
||||
country: 'asdf'
|
||||
|
@ -168,3 +169,48 @@ describe 'ConvertToTeacherAccountView (/teachers/update-account)', ->
|
|||
})
|
||||
expect(me.get('role')).toBe(successForm.role.toLowerCase())
|
||||
|
||||
describe 'submitting the form without school', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include school setting', ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.organization).toBeUndefined()
|
||||
expect(attrs.properties?.district).toEqual('District')
|
||||
|
||||
describe 'submitting the form without district', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['district'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'displays a validation error on district and not school', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(true)
|
||||
|
||||
describe 'submitting the form district set to n/a', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
formData.district = 'N/A'
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include district setting', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(false)
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.district).toBeUndefined()
|
||||
|
|
|
@ -33,6 +33,7 @@ describe 'CreateTeacherAccountView', ->
|
|||
phoneNumber: '555-555-5555'
|
||||
role: 'Teacher'
|
||||
organization: 'School'
|
||||
district: 'District'
|
||||
city: 'Springfield'
|
||||
state: 'AA'
|
||||
country: 'asdf'
|
||||
|
@ -219,6 +220,8 @@ describe 'CreateTeacherAccountView', ->
|
|||
expect(attrs.password2).toBeUndefined()
|
||||
expect(attrs.name).toBeUndefined()
|
||||
expect(attrs.properties?.siteOrigin).toBe('create teacher')
|
||||
expect(attrs.properties?.organization).toEqual('School')
|
||||
expect(attrs.properties?.district).toEqual('District')
|
||||
|
||||
describe 'after saving the new trial request', ->
|
||||
beforeEach ->
|
||||
|
@ -267,4 +270,48 @@ describe 'CreateTeacherAccountView', ->
|
|||
view.$('#email-form-group .login-link').click()
|
||||
expect(view.openModalView).toHaveBeenCalled()
|
||||
|
||||
describe 'submitting the form without school', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include school setting', ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.organization).toBeUndefined()
|
||||
expect(attrs.properties?.district).toEqual('District')
|
||||
|
||||
describe 'submitting the form without district', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['district'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'displays a validation error on district and not school', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(true)
|
||||
|
||||
describe 'submitting the form district set to n/a', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
formData.district = 'N/A'
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include district setting', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(false)
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.district).toBeUndefined()
|
||||
|
|
|
@ -5,13 +5,14 @@ describe 'RequestQuoteView', ->
|
|||
|
||||
view = null
|
||||
|
||||
successFormValues = {
|
||||
successForm = {
|
||||
firstName: 'A'
|
||||
lastName: 'B'
|
||||
email: 'C@D.com'
|
||||
phoneNumber: '555-555-5555'
|
||||
role: 'Teacher'
|
||||
organization: 'School'
|
||||
district: 'District'
|
||||
city: 'Springfield'
|
||||
state: 'AA'
|
||||
country: 'asdf'
|
||||
|
@ -23,7 +24,7 @@ describe 'RequestQuoteView', ->
|
|||
|
||||
isSubmitRequest = (r) -> _.string.startsWith(r.url, '/db/trial.request') and r.method is 'POST'
|
||||
|
||||
describe 'when user is anonymous and has an existing trial request', ->
|
||||
describe 'when an anonymous user', ->
|
||||
beforeEach (done) ->
|
||||
me.clear()
|
||||
me.set('_id', '1234')
|
||||
|
@ -32,145 +33,112 @@ describe 'RequestQuoteView', ->
|
|||
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 request received', ->
|
||||
expect(view.$('#request-form').hasClass('hide')).toBe(true)
|
||||
expect(view.$('#form-submit-success').hasClass('hide')).toBe(false)
|
||||
|
||||
|
||||
describe 'when user is signed in and has an existing trial request', ->
|
||||
beforeEach (done) ->
|
||||
me.clear()
|
||||
me.set('_id', '1234')
|
||||
me._revertAttributes = {}
|
||||
spyOn(me, 'isAnonymous').and.returnValue(false)
|
||||
view = new RequestQuoteView()
|
||||
view.render()
|
||||
jasmine.demoEl(view.$el)
|
||||
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({
|
||||
status: 200
|
||||
responseText: JSON.stringify([{
|
||||
_id: '1'
|
||||
properties: {
|
||||
firstName: 'First'
|
||||
lastName: 'Last'
|
||||
}
|
||||
}])
|
||||
})
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
it 'shows form with data from the most recent request', ->
|
||||
expect(view.$('input[name="firstName"]').val()).toBe('First')
|
||||
|
||||
describe 'when a user is anonymous and does NOT have an existing trial request', ->
|
||||
beforeEach (done) ->
|
||||
me.clear()
|
||||
me.set('_id', '1234')
|
||||
me._revertAttributes = {}
|
||||
spyOn(me, 'isAnonymous').and.returnValue(true)
|
||||
view = new RequestQuoteView()
|
||||
view.render()
|
||||
jasmine.demoEl(view.$el)
|
||||
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({
|
||||
status: 200
|
||||
responseText: '[]'
|
||||
})
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
describe 'when the form is unchanged', ->
|
||||
it 'does not prevent navigating away', ->
|
||||
expect(_.result(view, 'onLeaveMessage')).toBeFalsy()
|
||||
|
||||
describe 'when the form has changed but is not submitted', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change')
|
||||
|
||||
it 'prevents navigating away', ->
|
||||
expect(_.result(view, 'onLeaveMessage')).toBeTruthy()
|
||||
|
||||
describe 'on successful form submit', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
forms.objectToForm(view.$el, successFormValues)
|
||||
view.$('#request-form').submit()
|
||||
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
@submitRequest.respondWith({
|
||||
status: 201
|
||||
responseText: JSON.stringify(_.extend({_id: 'a'}, successFormValues))
|
||||
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 'does not prevent navigating away', ->
|
||||
expect(_.result(view, 'onLeaveMessage')).toBeFalsy()
|
||||
|
||||
it 'creates a new trial request', ->
|
||||
expect(@submitRequest).toBeTruthy()
|
||||
expect(@submitRequest.method).toBe('POST')
|
||||
attrs = JSON.parse(@submitRequest.params)
|
||||
expect(attrs.properties?.siteOrigin).toBe('demo request')
|
||||
|
||||
it 'sets the user\'s role to the one they chose', ->
|
||||
request = _.last(jasmine.Ajax.requests.filter((r) -> _.string.startsWith(r.url, '/db/user')))
|
||||
expect(request).toBeTruthy()
|
||||
expect(request.method).toBe('PUT')
|
||||
expect(JSON.parse(request.params).role).toBe('teacher')
|
||||
|
||||
it 'shows a signup form', ->
|
||||
expect(view.$('#form-submit-success').hasClass('hide')).toBe(false)
|
||||
it 'shows request received', ->
|
||||
expect(view.$('#request-form').hasClass('hide')).toBe(true)
|
||||
expect(view.$('#form-submit-success').hasClass('hide')).toBe(false)
|
||||
|
||||
describe 'signup form', ->
|
||||
describe 'does NOT have an existing trial request', ->
|
||||
beforeEach (done) ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({
|
||||
status: 200
|
||||
responseText: '[]'
|
||||
})
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
describe 'when the form is unchanged', ->
|
||||
it 'does not prevent navigating away', ->
|
||||
expect(_.result(view, 'onLeaveMessage')).toBeFalsy()
|
||||
|
||||
describe 'when the form has changed but is not submitted', ->
|
||||
beforeEach ->
|
||||
application.facebookHandler.fakeAPI()
|
||||
application.gplusHandler.fakeAPI()
|
||||
view.$el.find('#request-form').trigger('change')
|
||||
|
||||
it 'fills the username field with the given first and last names', ->
|
||||
expect(view.$('input[name="name"]').val()).toBe('A B')
|
||||
it 'prevents navigating away', ->
|
||||
expect(_.result(view, 'onLeaveMessage')).toBeTruthy()
|
||||
|
||||
it 'includes a facebook button which will sign them in immediately', ->
|
||||
view.$('#facebook-signup-btn').click()
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.method).toBe('PUT')
|
||||
expect(request.url).toBe('/db/user?facebookID=abcd&facebookAccessToken=1234')
|
||||
|
||||
it 'includes a gplus button which will sign them in immediately', ->
|
||||
view.$('#gplus-signup-btn').click()
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.method).toBe('PUT')
|
||||
expect(request.url).toBe('/db/user?gplusID=abcd&gplusAccessToken=1234')
|
||||
|
||||
it 'can sign them up with username and password', ->
|
||||
form = view.$('#signup-form')
|
||||
forms.objectToForm(form, {
|
||||
password1: 'asdf'
|
||||
password2: 'asdf'
|
||||
name: 'some name'
|
||||
describe 'on successful form submit', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
forms.objectToForm(view.$el, successForm)
|
||||
view.$('#request-form').submit()
|
||||
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
@submitRequest.respondWith({
|
||||
status: 201
|
||||
responseText: JSON.stringify(_.extend({_id: 'a'}, successForm))
|
||||
})
|
||||
form.submit()
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
|
||||
it 'does not prevent navigating away', ->
|
||||
expect(_.result(view, 'onLeaveMessage')).toBeFalsy()
|
||||
|
||||
it 'creates a new trial request', ->
|
||||
expect(@submitRequest).toBeTruthy()
|
||||
expect(@submitRequest.method).toBe('POST')
|
||||
attrs = JSON.parse(@submitRequest.params)
|
||||
expect(attrs.properties?.siteOrigin).toBe('demo request')
|
||||
|
||||
it 'sets the user\'s role to the one they chose', ->
|
||||
request = _.last(jasmine.Ajax.requests.filter((r) -> _.string.startsWith(r.url, '/db/user')))
|
||||
expect(request).toBeTruthy()
|
||||
expect(request.method).toBe('PUT')
|
||||
expect(request.url).toBe('/db/user/1234')
|
||||
expect(JSON.parse(request.params).role).toBe('teacher')
|
||||
|
||||
describe 'when an anonymous user tries to submit a request with an existing user\'s email', ->
|
||||
it 'shows a signup form', ->
|
||||
expect(view.$('#form-submit-success').hasClass('hide')).toBe(false)
|
||||
expect(view.$('#request-form').hasClass('hide')).toBe(true)
|
||||
|
||||
describe 'signup form', ->
|
||||
beforeEach ->
|
||||
application.facebookHandler.fakeAPI()
|
||||
application.gplusHandler.fakeAPI()
|
||||
|
||||
it 'fills the username field with the given first and last names', ->
|
||||
expect(view.$('input[name="name"]').val()).toBe('A B')
|
||||
|
||||
it 'includes a facebook button which will sign them in immediately', ->
|
||||
view.$('#facebook-signup-btn').click()
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.method).toBe('PUT')
|
||||
expect(request.url).toBe('/db/user?facebookID=abcd&facebookAccessToken=1234')
|
||||
|
||||
it 'includes a gplus button which will sign them in immediately', ->
|
||||
view.$('#gplus-signup-btn').click()
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.method).toBe('PUT')
|
||||
expect(request.url).toBe('/db/user?gplusID=abcd&gplusAccessToken=1234')
|
||||
|
||||
it 'can sign them up with username and password', ->
|
||||
form = view.$('#signup-form')
|
||||
forms.objectToForm(form, {
|
||||
password1: 'asdf'
|
||||
password2: 'asdf'
|
||||
name: 'some name'
|
||||
})
|
||||
form.submit()
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.method).toBe('PUT')
|
||||
expect(request.url).toBe('/db/user/1234')
|
||||
|
||||
describe 'tries to submit a request with an existing user\'s email', ->
|
||||
beforeEach ->
|
||||
forms.objectToForm(view.$el, successFormValues)
|
||||
forms.objectToForm(view.$el, successForm)
|
||||
view.$('#request-form').submit()
|
||||
@submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
@submitRequest.respondWith({
|
||||
|
@ -182,34 +150,103 @@ describe 'RequestQuoteView', ->
|
|||
expect(view.$('#email-form-group').hasClass('has-error')).toBe(true)
|
||||
expect(view.$('#email-form-group .error-help-block').length).toBe(1)
|
||||
|
||||
describe 'when user is signed in and has role "student"', ->
|
||||
describe 'submits the form without school', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('#request-form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include school setting', ->
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.organization).toBeUndefined()
|
||||
expect(attrs.properties?.district).toEqual('District')
|
||||
|
||||
describe 'submits the form without district', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('#request-form')
|
||||
formData = _.omit(successForm, ['district'])
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'displays a validation error on district and not school', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(true)
|
||||
|
||||
describe 'submits form with district set to n/a', ->
|
||||
beforeEach ->
|
||||
view.$el.find('#request-form').trigger('change') # to confirm navigating away isn't prevented
|
||||
form = view.$('#request-form')
|
||||
formData = _.omit(successForm, ['organization'])
|
||||
formData.district = 'N/A'
|
||||
forms.objectToForm(form, formData)
|
||||
form.submit()
|
||||
|
||||
it 'submits a trial request, which does not include district setting', ->
|
||||
expect(view.$('#organization-control').parent().hasClass('has-error')).toEqual(false)
|
||||
expect(view.$('#district-control').parent().hasClass('has-error')).toEqual(false)
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
expect(request.url).toBe('/db/trial.request')
|
||||
expect(request.method).toBe('POST')
|
||||
attrs = JSON.parse(request.params)
|
||||
expect(attrs.properties?.district).toBeUndefined()
|
||||
|
||||
describe 'when a signed in user', ->
|
||||
beforeEach (done) ->
|
||||
me.set('role', 'student')
|
||||
me.set('name', 'Some User')
|
||||
me.clear()
|
||||
me.set('_id', '1234')
|
||||
me._revertAttributes = {}
|
||||
spyOn(me, 'isAnonymous').and.returnValue(false)
|
||||
view = new RequestQuoteView()
|
||||
view.render()
|
||||
jasmine.demoEl(view.$el)
|
||||
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({ status: 200, responseText: '[]'})
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
it 'shows a conversion warning', ->
|
||||
expect(view.$('#conversion-warning').length).toBe(1)
|
||||
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 'requires confirmation to submit the form', ->
|
||||
form = view.$('#request-form')
|
||||
forms.objectToForm(form, successFormValues)
|
||||
spyOn(view, 'openModalView')
|
||||
form.submit()
|
||||
expect(view.openModalView).toHaveBeenCalled()
|
||||
it 'shows form with data from the most recent request', ->
|
||||
expect(view.$('input[name="firstName"]').val()).toBe('First')
|
||||
|
||||
submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
expect(submitRequest).toBeFalsy()
|
||||
confirmModal = view.openModalView.calls.argsFor(0)[0]
|
||||
confirmModal.trigger 'confirm'
|
||||
submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
expect(submitRequest).toBeTruthy()
|
||||
describe 'has role "student"', ->
|
||||
beforeEach (done) ->
|
||||
me.clear()
|
||||
me.set('role', 'student')
|
||||
me.set('name', 'Some User')
|
||||
request = jasmine.Ajax.requests.mostRecent()
|
||||
request.respondWith({ status: 200, responseText: '[]'})
|
||||
_.defer done # Let SuperModel finish
|
||||
|
||||
it 'shows a conversion warning', ->
|
||||
expect(view.$('#conversion-warning').length).toBe(1)
|
||||
|
||||
it 'requires confirmation to submit the form', ->
|
||||
form = view.$('#request-form')
|
||||
forms.objectToForm(form, successForm)
|
||||
spyOn(view, 'openModalView')
|
||||
form.submit()
|
||||
expect(view.openModalView).toHaveBeenCalled()
|
||||
|
||||
submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
expect(submitRequest).toBeFalsy()
|
||||
confirmModal = view.openModalView.calls.argsFor(0)[0]
|
||||
confirmModal.trigger 'confirm'
|
||||
submitRequest = _.last(jasmine.Ajax.requests.filter(isSubmitRequest))
|
||||
expect(submitRequest).toBeTruthy()
|
||||
|
|
Loading…
Reference in a new issue