Merge branch 'master' into production

This commit is contained in:
phoenixeliot 2016-08-01 16:46:33 -07:00
commit fc78c5af82
12 changed files with 140 additions and 82 deletions

View file

@ -1351,6 +1351,7 @@
update_account_students_warning: "Warning: You will not be able to manage any classes that you have previously created or create new classes." update_account_students_warning: "Warning: You will not be able to manage any classes that you have previously created or create new classes."
update_account_remain_student: "Remain a Student" update_account_remain_student: "Remain a Student"
update_account_update_student: "Update to Student" update_account_update_student: "Update to Student"
need_a_class_code: "You'll need a Class Code for the class you're joining:"
update_account_not_sure: "Not sure which one to choose? Email" update_account_not_sure: "Not sure which one to choose? Email"
update_account_confirm_update_student: "Are you sure you want to update your account to a Student experience?" update_account_confirm_update_student: "Are you sure you want to update your account to a Student experience?"
update_account_confirm_update_student2: "You will not be able to manage any classes that you have previously created or create new classes. Your previously created classes will be removed from CodeCombat and cannot be restored." update_account_confirm_update_student2: "You will not be able to manage any classes that you have previously created or create new classes. Your previously created classes will be removed from CodeCombat and cannot be restored."

View file

@ -65,13 +65,13 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# setup_a_class: "Set Up a Class" # setup_a_class: "Set Up a Class"
have_an_account: "Tens uma conta?" have_an_account: "Tens uma conta?"
logged_in_as: "Atualmente tens sessão iniciada como" logged_in_as: "Atualmente tens sessão iniciada como"
# view_my_classes: "View my classes" view_my_classes: "Ver as minhas turmas"
computer_science: "Cursos de ciência da computação para todas as idades" computer_science: "Cursos de ciência da computação para todas as idades"
show_me_lesson_time: "Mostrar estimativas do tempo de aula para:" show_me_lesson_time: "Mostrar estimativas do tempo de aula para:"
curriculum: "Horas totais do currículo:" curriculum: "Horas totais do currículo:"
ffa: "Grátis para todos os estudantes" ffa: "Grátis para todos os estudantes"
lesson_time: "Tempo de aula:" lesson_time: "Tempo de aula:"
coming_soon: "Brevemente!" coming_soon: "Chega neste outono!"
courses_available_in: "Os cursos estão disponíveis em JavaScript, Python, e Java (brevemente!)" courses_available_in: "Os cursos estão disponíveis em JavaScript, Python, e Java (brevemente!)"
# boast: "Boasts riddles that are complex enough to fascinate gamers and coders alike." # boast: "Boasts riddles that are complex enough to fascinate gamers and coders alike."
# winning: "A winning combination of RPG gameplay and programming homework that pulls off making kid-friendly education legitimately enjoyable." # winning: "A winning combination of RPG gameplay and programming homework that pulls off making kid-friendly education legitimately enjoyable."
@ -86,8 +86,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# student_count: "Number of students:" # student_count: "Number of students:"
# start_playing_for_free: "Start Playing for Free!" # start_playing_for_free: "Start Playing for Free!"
# students_and_players: "Students & Players" # students_and_players: "Students & Players"
# goto_classes: "Go to My Classes" goto_classes: "Ir para As Minhas Turmas"
# view_profile: "View My Profile" view_profile: "Ver o Meu Perfil"
view_progress: "Ver Progresso" view_progress: "Ver Progresso"
# check_out_wiki: "Check out our new Educator Wiki" # check_out_wiki: "Check out our new Educator Wiki"
# want_coco: "Want CodeCombat at your school?" # want_coco: "Want CodeCombat at your school?"
@ -132,7 +132,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
help_suff: "e nós entraremos em contacto!" help_suff: "e nós entraremos em contacto!"
modal: modal:
# cancel: "Cancel" cancel: "Cancelar"
close: "Fechar" close: "Fechar"
okay: "Ok" okay: "Ok"
@ -243,7 +243,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
login: login:
sign_up: "Criar Conta" sign_up: "Criar Conta"
# email_or_username: "Email or username" email_or_username: "E-mail ou nome de utilizador"
log_in: "Iniciar Sessão" log_in: "Iniciar Sessão"
logging_in: "A Iniciar Sessão" logging_in: "A Iniciar Sessão"
log_out: "Sair" log_out: "Sair"
@ -256,13 +256,13 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
signup_switch: "Queres criar uma conta?" signup_switch: "Queres criar uma conta?"
signup: signup:
# create_student_header: "Create Student Account" create_student_header: "Criar Conta de Estudante"
# create_teacher_header: "Create Teacher Account" create_teacher_header: "Criar Conta de Professor"
# create_individual_header: "Create Individual Account" create_individual_header: "Criar Conta Individual"
# create_header: "Create Account" create_header: "Criar Conta"
email_announcements: "Receber anúncios por e-mail" # {change} email_announcements: "Receber anúncios sobre níveis e funcionalidades novos do CodeCombat!"
creating: "A Criar Conta..." creating: "A Criar Conta..."
# create_account: "Create Account" create_account: "Criar Conta"
sign_up: "Registar" sign_up: "Registar"
log_in: "iniciar sessão com palavra-passe" log_in: "iniciar sessão com palavra-passe"
required: "Precisas de iniciar sessão antes de prosseguires." required: "Precisas de iniciar sessão antes de prosseguires."
@ -270,7 +270,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
school_name: "Nome e Cidade da Escola" school_name: "Nome e Cidade da Escola"
optional: "opcional" optional: "opcional"
school_name_placeholder: "Exemplo: Escola Secundária, Springfield, Illinois" school_name_placeholder: "Exemplo: Escola Secundária, Springfield, Illinois"
# connect_with: "Connect with:" connect_with: "Conectar com:"
# connected_gplus_header: "You've successfully connected with Google+!" # connected_gplus_header: "You've successfully connected with Google+!"
# connected_gplus_p: "Finish signing up so you can log in with your Google+ account." # connected_gplus_p: "Finish signing up so you can log in with your Google+ account."
# gplus_exists: "You already have an account associated with Google+!" # gplus_exists: "You already have an account associated with Google+!"
@ -340,8 +340,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
saving: "A Guardar..." saving: "A Guardar..."
sending: "A Enviar..." sending: "A Enviar..."
send: "Enviar" send: "Enviar"
# sent: "Sent" sent: "Enviado"
# type: "Type" type: "Tipo"
cancel: "Cancelar" cancel: "Cancelar"
save: "Guardar" save: "Guardar"
publish: "Publicar" publish: "Publicar"
@ -411,7 +411,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
wizard: "Feiticeiro" wizard: "Feiticeiro"
first_name: "Nome" first_name: "Nome"
last_name: "Apelido" last_name: "Apelido"
# last_initial: "Last Initial" last_initial: "Última Inicial"
username: "Nome de utilizador" username: "Nome de utilizador"
units: units:
@ -480,12 +480,12 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
tome_cast_button_running: "A Executar" tome_cast_button_running: "A Executar"
tome_cast_button_ran: "Executado" tome_cast_button_ran: "Executado"
tome_submit_button: "Submeter" tome_submit_button: "Submeter"
tome_reload_method: "Recarregar o código original para este método" # {change} tome_reload_method: "Recarregar o código original para recomeçar o nível"
tome_available_spells: "Feitiços Disponíveis" tome_available_spells: "Feitiços Disponíveis"
tome_your_skills: "As Tuas Habilidades" tome_your_skills: "As Tuas Habilidades"
tome_current_method: "Método Atual" tome_current_method: "Método Atual"
# hints: "Hints" hints: "Dicas"
# hints_title: "Hint {{number}}" hints_title: "Dica {{number}}"
code_saved: "Código Guardado" code_saved: "Código Guardado"
skip_tutorial: "Saltar (esc)" skip_tutorial: "Saltar (esc)"
keyboard_shortcuts: "Atalhos de Teclado" keyboard_shortcuts: "Atalhos de Teclado"
@ -799,8 +799,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
phoenix_title: "Engenheira de 'Software'" phoenix_title: "Engenheira de 'Software'"
nolan_title: "Gestor de Território" nolan_title: "Gestor de Território"
elliot_title: "Gestor de Parcerias" elliot_title: "Gestor de Parcerias"
# elliot_blurb: "Mindreader" elliot_blurb: "Leitora de Mentes"
# lisa_title: "Market Development Rep" lisa_title: "Representante do Desenvolvimento de Mercado"
retrostyle_title: "Ilustração" retrostyle_title: "Ilustração"
retrostyle_blurb: "'RetroStyle Games'" retrostyle_blurb: "'RetroStyle Games'"
jose_title: "Música" jose_title: "Música"
@ -861,7 +861,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
more_info_1: "O nosso" more_info_1: "O nosso"
more_info_2: "fórum para professores" more_info_2: "fórum para professores"
more_info_3: "é um bom sítio para te ligares a outros professores que também usam o CodeCombat." more_info_3: "é um bom sítio para te ligares a outros professores que também usam o CodeCombat."
# licenses_needed: "Licenses needed" licenses_needed: "Licenças necessárias"
# teachers_quote: # teachers_quote:
# name: "Demo Form" # name: "Demo Form"
@ -960,7 +960,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
manage_subscription: "Clica aqui para gerires a tua subscrição." manage_subscription: "Clica aqui para gerires a tua subscrição."
new_password: "Nova Palavra-passe" new_password: "Nova Palavra-passe"
new_password_verify: "Verificar" new_password_verify: "Verificar"
type_in_email: "Escreve o teu e-mail para confirmares a eliminação." # {change} type_in_email: "Escreve o teu e-mail ou nome de utilizador para confirmares a eliminação da conta."
type_in_email_progress: "Escreve o teu e-mail para confirmares a eliminação do teu progresso." type_in_email_progress: "Escreve o teu e-mail para confirmares a eliminação do teu progresso."
type_in_password: "Escreve também a tua palavra-passe." type_in_password: "Escreve também a tua palavra-passe."
email_subscriptions: "Subscrições de E-mail" email_subscriptions: "Subscrições de E-mail"
@ -1161,9 +1161,9 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
get_free: "Obter curso GRÁTIS" get_free: "Obter curso GRÁTIS"
enroll_paid: "Inscrever Estudantes em Cursos Pagos" enroll_paid: "Inscrever Estudantes em Cursos Pagos"
you_have1: "Tens" you_have1: "Tens"
you_have2: "inscrições pagas por usar" # {change} you_have2: "licenças de estudante por usar"
# use_one: "Use 1 student license for" use_one: "Usar 1 licença de estudante para"
# use_multiple: "Use licenses for the following students:" use_multiple: "Usar licenças para os seguintes estudantes:"
# already_enrolled: "already enrolled" # already_enrolled: "already enrolled"
# licenses_remaining: "licenses remaining:" # licenses_remaining: "licenses remaining:"
# insufficient_enrollments: "insufficient student licenses" # insufficient_enrollments: "insufficient student licenses"
@ -1177,11 +1177,11 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# edit_details: "Edit class details" # edit_details: "Edit class details"
# enrolled_courses: "enrolled in paid courses:" # enrolled_courses: "enrolled in paid courses:"
# purchase_enrollments: "Purchase Student Licenses" # purchase_enrollments: "Purchase Student Licenses"
# remove_student: "remove student" remove_student: "remover estudante"
# assign: "Assign" # assign: "Assign"
# to_assign: "to assign paid courses." # to_assign: "to assign paid courses."
# student: "Student" student: "Estudante"
# teacher: "Teacher" teacher: "Professor"
# complete: "Complete" # complete: "Complete"
# none: "None" # none: "None"
# save: "Save" # save: "Save"
@ -1216,10 +1216,10 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# ready_for_more_3: "Learn even more programming!" # ready_for_more_3: "Learn even more programming!"
# saved_games: "Saved Games" # saved_games: "Saved Games"
# hoc: "Hour of Code" # hoc: "Hour of Code"
# my_classes: "My Classes" my_classes: "As Minhas Turmas"
# class_added: "Class successfully added!" # class_added: "Class successfully added!"
# view_class: "view class" view_class: "ver turma"
# view_levels: "view levels" view_levels: "ver níveis"
# join_class: "Join A Class" # join_class: "Join A Class"
# join_class_2: "Join class" # join_class_2: "Join class"
# ask_teacher_for_code: "Ask your teacher if you have a CodeCombat class code! If so, enter it below:" # ask_teacher_for_code: "Ask your teacher if you have a CodeCombat class code! If so, enter it below:"
@ -1235,7 +1235,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
not_you: "Não és tu?" not_you: "Não és tu?"
# welcome_back: "Hi adventurer, welcome back!" # welcome_back: "Hi adventurer, welcome back!"
continue_playing: "Continuar a Jogar" continue_playing: "Continuar a Jogar"
# more_options: "More options:" more_options: "Mais opções:"
# option1_header: "Option 1: Invite students via email" # option1_header: "Option 1: Invite students via email"
# option1_body: "Students will automatically be sent an invitation to join this class, and will need to create an account with a username and password." # option1_body: "Students will automatically be sent an invitation to join this class, and will need to create an account with a username and password."
# option2_header: "Option 2: Send URL to your students" # option2_header: "Option 2: Send URL to your students"
@ -1252,18 +1252,18 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# each_student_access: "Each student in a class will get access to Courses 2-4 once they are enrolled in paid courses. You may assign each course to each student individually." # each_student_access: "Each student in a class will get access to Courses 2-4 once they are enrolled in paid courses. You may assign each course to each student individually."
# purchase_now: "Purchase Now" # purchase_now: "Purchase Now"
# enrollments: "licenses" # enrollments: "licenses"
# remove_student1: "Remove Student" remove_student1: "Remover Estudante"
# are_you_sure: "Are you sure you want to remove this student from this class?" # are_you_sure: "Are you sure you want to remove this student from this class?"
# remove_description1: "Student will lose access to this classroom and assigned classes. Progress and gameplay is NOT lost, and the student can be added back to the classroom at any time." # remove_description1: "Student will lose access to this classroom and assigned classes. Progress and gameplay is NOT lost, and the student can be added back to the classroom at any time."
# remove_description2: "The activated paid license will not be returned." # remove_description2: "The activated paid license will not be returned."
# keep_student: "Keep Student" # keep_student: "Keep Student"
# removing_user: "Removing user" removing_user: "A remover utilizador"
# to_join_ask: "To join a class, ask your teacher for an unlock code." # to_join_ask: "To join a class, ask your teacher for an unlock code."
# join_this_class: "Join Class" # join_this_class: "Join Class"
# enter_here: "<enter unlock code here>" # enter_here: "<enter unlock code here>"
# successfully_joined: "Successfully joined" # successfully_joined: "Successfully joined"
# click_to_start: "Click here to start taking" # click_to_start: "Click here to start taking"
# my_courses: "My Courses" my_courses: "Os Meus Cursos"
# classroom: "Classroom" # classroom: "Classroom"
# use_school_email: "use your school email if you have one" # use_school_email: "use your school email if you have one"
# unique_name: "a unique name no one has chosen" # unique_name: "a unique name no one has chosen"
@ -1295,12 +1295,12 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# students_enrolled: "students enrolled" # students_enrolled: "students enrolled"
# students_assigned: "students assigned" # students_assigned: "students assigned"
# length: "Length:" # length: "Length:"
title: "Título" # Flat style redesign title: "Cursos" # Flat style redesign
# subtitle: "Review course guidelines, solutions, and levels" # subtitle: "Review course guidelines, solutions, and levels"
# changelog: "View latest changes to course levels." # changelog: "View latest changes to course levels."
# select_language: "Select language" # select_language: "Select language"
# select_level: "Select level" select_level: "Selecionar nível"
# play_level: "Play Level" play_level: "Jogar Nível"
concepts_covered: "Conceitos Abordados" concepts_covered: "Conceitos Abordados"
# print_guide: "Print Guide (PDF)" # print_guide: "Print Guide (PDF)"
# view_guide_online: "View Guide Online (PDF)" # view_guide_online: "View Guide Online (PDF)"
@ -1369,26 +1369,26 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# select_your_hero_description: "You can always change your hero by going to your Courses page and clicking \"Select Hero\"" # select_your_hero_description: "You can always change your hero by going to your Courses page and clicking \"Select Hero\""
# select_this_hero: "Select this Hero" # select_this_hero: "Select this Hero"
# teacher: teacher:
# teacher_dashboard: "Teacher Dashboard" # Navbar # teacher_dashboard: "Teacher Dashboard" # Navbar
# my_classes: "My Classes" my_classes: "As Minhas Turmas"
# courses: "Course Guides" # courses: "Course Guides"
# enrollments: "Student Licenses" # enrollments: "Student Licenses"
# resources: "Resources" resources: "Recursos"
# help: "Help" help: "Ajuda"
# students: "Students" # Shared students: "Estudantes" # Shared
# language: "Language" language: "Linguagem"
# edit_class_settings: "edit class settings" # edit_class_settings: "edit class settings"
# complete: "Complete" # complete: "Complete"
# access_restricted: "Account Update Required" # access_restricted: "Account Update Required"
# teacher_account_required: "A teacher account is required to access this content." # teacher_account_required: "A teacher account is required to access this content."
# create_teacher_account: "Create Teacher Account" create_teacher_account: "Criar Conta de Professor"
# what_is_a_teacher_account: "What's a Teacher Account?" what_is_a_teacher_account: "O que é uma Conta de Professor?"
# teacher_account_explanation: "A CodeCombat Teacher account allows you to set up classrooms, monitor students progress as they work through courses, manage licenses and access resources to aid in your curriculum-building." # teacher_account_explanation: "A CodeCombat Teacher account allows you to set up classrooms, monitor students progress as they work through courses, manage licenses and access resources to aid in your curriculum-building."
# current_classes: "Current Classes" current_classes: "Turmas Atuais"
# archived_classes: "Archived Classes" archived_classes: "Turmas Arquivadas"
# archived_classes_blurb: "Classes can be archived for future reference. Unarchive a class to view it in the Current Classes list again." # archived_classes_blurb: "Classes can be archived for future reference. Unarchive a class to view it in the Current Classes list again."
# view_class: "view class" view_class: "ver turma"
# archive_class: "archive class" # archive_class: "archive class"
# unarchive_class: "unarchive class" # unarchive_class: "unarchive class"
# unarchive_this_class: "Unarchive this class" # unarchive_this_class: "Unarchive this class"
@ -1494,8 +1494,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# victory_course_share_suffix: "you just created." # victory_course_share_suffix: "you just created."
# copy_url: "Copy URL" # copy_url: "Copy URL"
# game_dev: game_dev:
# creator: "Creator" creator: "Criador"
# web_dev: # web_dev:
# image_gallery_title: "Image Gallery" # image_gallery_title: "Image Gallery"
@ -1657,7 +1657,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
# scribe_introduction_url_mozilla: "Mozilla Developer Network" # scribe_introduction_url_mozilla: "Mozilla Developer Network"
# scribe_introduction_suf: " has built. If your idea of fun is articulating the concepts of programming in Markdown form, then this class might be for you." # scribe_introduction_suf: " has built. If your idea of fun is articulating the concepts of programming in Markdown form, then this class might be for you."
scribe_attribute_1: "Habilidade com palavras é basicamente o que precisas. Não apenas gramática e ortografia, mas seres capaz de explicar ideias complicadas a outros." scribe_attribute_1: "Habilidade com palavras é basicamente o que precisas. Não apenas gramática e ortografia, mas seres capaz de explicar ideias complicadas a outros."
contact_us_url: "Contacta-nos" # {change} contact_us_url: "Contacta-nos"
scribe_join_description: "fala-nos um bocado de ti, da tua experiência com a programação e do tipo de coisas sobre as quais gostarias de escrever. Começamos a partir daí!" scribe_join_description: "fala-nos um bocado de ti, da tua experiência com a programação e do tipo de coisas sobre as quais gostarias de escrever. Começamos a partir daí!"
scribe_subscribe_desc: "Receber e-mails sobre anúncios relativos à escrita de artigos." scribe_subscribe_desc: "Receber e-mails sobre anúncios relativos à escrita de artigos."
diplomat_introduction_pref: "Portanto, se há uma coisa que aprendemos com o nosso " diplomat_introduction_pref: "Portanto, se há uma coisa que aprendemos com o nosso "
@ -1800,15 +1800,15 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
card: "Cartão" card: "Cartão"
status_unsubscribed_active: "Não estás subscrito e não te vamos cobrar, mas a tua conta ainda está ativa, por agora." status_unsubscribed_active: "Não estás subscrito e não te vamos cobrar, mas a tua conta ainda está ativa, por agora."
status_unsubscribed: "Ganha acesso a novos níveis, heróis, itens e gemas de bónus com uma subscrição do CodeCombat!" status_unsubscribed: "Ganha acesso a novos níveis, heróis, itens e gemas de bónus com uma subscrição do CodeCombat!"
# not_yet_verified: "Not yet verified." not_yet_verified: "Ainda não foi verificado."
# resend_email: "Resend email" resend_email: "Reenviar e-mail"
# email_sent: "Email sent! Check your inbox." email_sent: "E-mail enviado! Verifica a tua caixa de entrada."
# verifying_email: "Verifying your email address..." verifying_email: "A verificar o teu endereço de e-mail..."
# successfully_verified: "You've successfully verified your email address!" successfully_verified: "Verificaste o teu endereço de e-mail com sucesso!"
# back_to_student_page: "Go back to student things" back_to_student_page: "Voltar às coisas de estudante"
# back_to_teacher_page: "Go to My Classes" back_to_teacher_page: "Ir para As Minhas Turmas"
# back_to_game: "Go play some more levels!" back_to_game: "Ir jogar mais alguns níveis!"
# verify_error: "Something went wrong when verifying your email :(" verify_error: "Algo correu mal aquando da verificação do teu e-mail :("
account_invoices: account_invoices:
amount: "Quantidade em dólares americanos" amount: "Quantidade em dólares americanos"
@ -1844,7 +1844,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
coppa_deny: coppa_deny:
text1: "Não podes esperar para aprender programação?" text1: "Não podes esperar para aprender programação?"
text2: "Pede aos teus educadores para criarem uma conta para ti!" # {change} text2: "Os teus educadores vão precisar de criar uma conta para tu usares! Envia um e-mail para team@codecombat.com se tiveres alguma pergunta."
close: "Fechar Janela" close: "Fechar Janela"
loading_error: loading_error:

View file

@ -2,6 +2,8 @@
//- Fixed save button //- Fixed save button
#site-content-area #site-content-area
width: auto
max-width: 1024px
padding-bottom: 44px padding-bottom: 44px
#save-button-container #save-button-container
@ -20,9 +22,7 @@
opacity: 1.0 opacity: 1.0
#account-settings-view #account-settings-view
padding-top: 20px
.row
padding-top: 20px
//- Panels //- Panels
.panel-heading .panel-heading

View file

@ -10,15 +10,17 @@ else
.panel-body .panel-body
.form .form
- var name = me.get('name') || ''; - var name = me.get('name') || '';
- var firstName = me.get('firstName') || '';
- var lastName = me.get('lastName') || '';
- var email = me.get('email') || ''; - var email = me.get('email') || '';
- var admin = me.get('permissions', true).indexOf('admin') != -1; - var admin = me.get('permissions', true).indexOf('admin') != -1;
- var godmode = me.get('permissions', true).indexOf('godmode') != -1; - var godmode = me.get('permissions', true).indexOf('godmode') != -1;
.form-group .form-group
label.control-label(for="name", data-i18n="general.name") Name label.control-label(for="name", data-i18n="general.username")
input#name-input.form-control(name="name", type="text", value="#{name}") input#name-input.form-control(name="name", type="text", value="#{name}")
.form-group .form-group
label.control-label(for="email") label.control-label(for="email")
span(data-i18n="general.email") Email span(data-i18n="general.email")
unless me.get('emailVerified') unless me.get('emailVerified')
span.spl ( span.spl (
span.spr(data-i18n="account.not_yet_verified") span.spr(data-i18n="account.not_yet_verified")
@ -27,12 +29,23 @@ else
span.sent-text.hide(data-i18n="account.email_sent") span.sent-text.hide(data-i18n="account.email_sent")
span ) span )
input#email.form-control(name="email", type="text", value="#{email}") input#email.form-control(name="email", type="text", value="#{email}")
.row
.form-group.col-sm-6
label.control-label(for="firstName", data-i18n="general.first_name")
input#first-name-input.form-control(name="firstName", type="text", value="#{firstName}")
.form-group.col-sm-6
if me.isStudent()
label.control-label(for="lastName", data-i18n="general.last_initial")
input#last-name-input.form-control(name="lastName", type="text", value="#{lastName}", maxlength="1")
else
label.control-label(for="lastName", data-i18n="general.last_name")
input#last-name-input.form-control(name="lastName", type="text", value="#{lastName}")
if !isProduction if !isProduction
.form-group.checkbox .form-group.checkbox
label(for="admin", data-i18n="account_settings.admin") Admin label(for="admin", data-i18n="account_settings.admin")
input#admin(name="admin", type="checkbox", checked=admin) input#admin(name="admin", type="checkbox", checked=admin)
.form-group.checkbox .form-group.checkbox
label(for="godmode", data-i18n="account_settings.god_mode") God Mode label(for="godmode", data-i18n="account_settings.god_mode")
input#godmode(name="godmode", type="checkbox", checked=godmode) input#godmode(name="godmode", type="checkbox", checked=godmode)
if me.hasSubscription() if me.hasSubscription()
.form-group .form-group

View file

@ -73,6 +73,9 @@ block content
if me.isStudent() if me.isStudent()
button.remain-student-btn.btn.btn-navy(data-i18n="courses.update_account_remain_student") button.remain-student-btn.btn.btn-navy(data-i18n="courses.update_account_remain_student")
else else
label
span(data-i18n="courses.need_a_class_code")
input(name='classCode')
button.update-student-btn.btn.btn-forest(data-i18n="courses.update_account_update_student") button.update-student-btn.btn.btn-forest(data-i18n="courses.update_account_update_student")
br br
br br

View file

@ -266,6 +266,8 @@ module.exports = class AccountSettingsView extends CocoView
grabOtherData: -> grabOtherData: ->
@$el.find('#name-input').val @suggestedName if @suggestedName @$el.find('#name-input').val @suggestedName if @suggestedName
me.set 'name', @$el.find('#name-input').val() me.set 'name', @$el.find('#name-input').val()
me.set 'firstName', @$el.find('#first-name-input').val()
me.set 'lastName', @$el.find('#last-name-input').val()
me.set 'email', @$el.find('#email').val() me.set 'email', @$el.find('#email').val()
for emailName, enabled of @getSubscriptions() for emailName, enabled of @getSubscriptions()
me.setEmailSubscription emailName, enabled me.setEmailSubscription emailName, enabled

View file

@ -2,6 +2,7 @@ errors = require 'core/errors'
RootView = require 'views/core/RootView' RootView = require 'views/core/RootView'
template = require 'templates/courses/courses-update-account-view' template = require 'templates/courses/courses-update-account-view'
AuthModal = require 'views/core/AuthModal' AuthModal = require 'views/core/AuthModal'
JoinClassModal = require 'views/courses/JoinClassModal'
{logoutUser, me} = require('core/auth') {logoutUser, me} = require('core/auth')
module.exports = class CoursesUpdateAccountView extends RootView module.exports = class CoursesUpdateAccountView extends RootView
@ -41,8 +42,11 @@ module.exports = class CoursesUpdateAccountView extends RootView
@becomeStudent(e.target, 'Remain student') @becomeStudent(e.target, 'Remain student')
onClickUpdateStudentButton: (e) -> onClickUpdateStudentButton: (e) ->
return unless window.confirm($.i18n.t('courses.update_account_confirm_update_student') + '\n\n' + $.i18n.t('courses.update_account_confirm_update_student2')) joinClassModal = new JoinClassModal { classCode: @$('input[name="classCode"]').val() }
@becomeStudent(e.target, 'Update student') @openModalView joinClassModal
@listenTo joinClassModal, 'join:success', => @becomeStudent(e.target, 'Update student')
# return unless window.confirm($.i18n.t('courses.update_account_confirm_update_student') + '\n\n' + $.i18n.t('courses.update_account_confirm_update_student2'))
# @becomeStudent(e.target, 'Update student')
becomeStudent: (targetElem, trackEventMsg) -> becomeStudent: (targetElem, trackEventMsg) ->
$(targetElem).prop('disabled', true) $(targetElem).prop('disabled', true)

View file

@ -10,7 +10,7 @@ module.exports = class JoinClassModal extends ModalView
events: events:
'click .join-class-btn': 'onClickJoinClassButton' 'click .join-class-btn': 'onClickJoinClassButton'
initialize: ({ @classCode }) -> initialize: ({ @classCode } = {}) ->
@classroom = new Classroom() @classroom = new Classroom()
@teacher = new User() @teacher = new User()
jqxhr = @supermodel.trackRequest @classroom.fetchByCode(@classCode) jqxhr = @supermodel.trackRequest @classroom.fetchByCode(@classCode)

View file

@ -22,7 +22,7 @@ co = require 'co'
module.exports = module.exports =
fetchByCode: wrap (req, res, next) -> fetchByCode: wrap (req, res, next) ->
code = req.query.code code = req.query.code
return next() unless code return next() unless req.query.hasOwnProperty('code')
classroom = yield Classroom.findOne({ code: code.toLowerCase().replace(RegExp(' ', 'g') , '') }).select('name ownerID aceConfig') classroom = yield Classroom.findOne({ code: code.toLowerCase().replace(RegExp(' ', 'g') , '') }).select('name ownerID aceConfig')
if not classroom if not classroom
log.debug("classrooms.fetchByCode: Couldn't find Classroom with code: #{code}") log.debug("classrooms.fetchByCode: Couldn't find Classroom with code: #{code}")

View file

@ -370,6 +370,11 @@ UserSchema.pre('save', (next) ->
@set('name', undefined) @set('name', undefined)
@set('nameLower', undefined) @set('nameLower', undefined)
if _.isEmpty(@get('firstName'))
@set('firstName', undefined)
if _.isEmpty(@get('lastName'))
@set('lastName', undefined)
unless email or name or @get('anonymous') or @get('deleted') unless email or name or @get('anonymous') or @get('deleted')
return next(new errors.UnprocessableEntity('User needs a username or email address')) return next(new errors.UnprocessableEntity('User needs a username or email address'))

View file

@ -24,8 +24,9 @@ describe '/courses/update-account', ->
it 'shows update to teacher button', -> it 'shows update to teacher button', ->
expect(@view.$el.find('.update-teacher-btn').length).toEqual(1) expect(@view.$el.find('.update-teacher-btn').length).toEqual(1)
it 'shows update to student button', -> it 'shows update to student button and classCode input', ->
expect(@view.$el.find('.update-student-btn').length).toEqual(1) expect(@view.$el.find('.update-student-btn').length).toEqual(1)
expect(@view.$el.find('input[name="classCode"]').length).toEqual(1)
describe 'when logged in as student', -> describe 'when logged in as student', ->
beforeEach (done) -> beforeEach (done) ->
@ -39,6 +40,7 @@ describe '/courses/update-account', ->
it 'shows remain a student button', -> it 'shows remain a student button', ->
expect(@view.$el.find('.remain-student-btn').length).toEqual(1) expect(@view.$el.find('.remain-student-btn').length).toEqual(1)
expect(@view.$el.find('input[name="classCode"]').length).toEqual(0)
it 'shows update to teacher button', -> it 'shows update to teacher button', ->
expect(@view.$el.find('.update-teacher-btn').length).toEqual(1) expect(@view.$el.find('.update-teacher-btn').length).toEqual(1)
@ -57,3 +59,4 @@ describe '/courses/update-account', ->
it 'shows update to student button', -> it 'shows update to student button', ->
expect(@view.$el.find('.update-student-btn').length).toEqual(1) expect(@view.$el.find('.update-student-btn').length).toEqual(1)
expect(@view.$el.find('input[name="classCode"]').length).toEqual(1)

View file

@ -24,7 +24,12 @@ describe 'TeacherClassView', ->
beforeEach (done) -> beforeEach (done) ->
me = factories.makeUser({}) me = factories.makeUser({})
@courses = new Courses([factories.makeCourse({name: 'First Course'}), factories.makeCourse({name: 'Second Course'})]) @courses = new Courses([
factories.makeCourse({name: 'First Course'}),
factories.makeCourse({name: 'Second Course'}),
factories.makeCourse({name: 'Beta Course', releasePhase: 'beta'}),
])
@releasedCourses = new Courses(@courses.where({ releasePhase: 'released' }))
available = factories.makePrepaid() available = factories.makePrepaid()
expired = factories.makePrepaid({endDate: moment().subtract(1, 'day').toISOString()}) expired = factories.makePrepaid({endDate: moment().subtract(1, 'day').toISOString()})
@students = new Users([ @students = new Users([
@ -35,11 +40,11 @@ describe 'TeacherClassView', ->
factories.makeUser({name: 'Ned'}, {prepaid: expired}) factories.makeUser({name: 'Ned'}, {prepaid: expired})
factories.makeUser({name: 'Ebner'}, {prepaid: expired}) factories.makeUser({name: 'Ebner'}, {prepaid: expired})
]) ])
@levels = new Levels(_.times(2, -> factories.makeLevel())) @levels = new Levels(_.times(2, -> factories.makeLevel({ concepts: ['basic_syntax', 'arguments', 'functions'] })))
@classroom = factories.makeClassroom({}, { @courses, members: @students, levels: [@levels, new Levels()] }) @classroom = factories.makeClassroom({}, { courses: @releasedCourses, members: @students, levels: [@levels, new Levels()] })
@courseInstances = new CourseInstances([ @courseInstances = new CourseInstances([
factories.makeCourseInstance({}, { course: @courses.first(), @classroom, members: @students }) factories.makeCourseInstance({}, { course: @releasedCourses.first(), @classroom, members: @students })
factories.makeCourseInstance({}, { course: @courses.last(), @classroom, members: @students }) factories.makeCourseInstance({}, { course: @releasedCourses.last(), @classroom, members: @students })
]) ])
sessions = [] sessions = []
@ -47,11 +52,11 @@ describe 'TeacherClassView', ->
@unfinishedStudent = @students.last() @unfinishedStudent = @students.last()
for level in @levels.models for level in @levels.models
sessions.push(factories.makeLevelSession( sessions.push(factories.makeLevelSession(
{state: {complete: true}}, {state: {complete: true}, playtime: 60},
{level, creator: @finishedStudent}) {level, creator: @finishedStudent})
) )
sessions.push(factories.makeLevelSession( sessions.push(factories.makeLevelSession(
{state: {complete: true}}, {state: {complete: true}, playtime: 60},
{level: @levels.first(), creator: @unfinishedStudent}) {level: @levels.first(), creator: @unfinishedStudent})
) )
@levelSessions = new LevelSessions(sessions) @levelSessions = new LevelSessions(sessions)
@ -118,3 +123,25 @@ describe 'TeacherClassView', ->
users = @view.enrollStudents.calls.argsFor(0)[0] users = @view.enrollStudents.calls.argsFor(0)[0]
expect(users.size()).toBe(1) expect(users.size()).toBe(1)
expect(users.first().id).toBe(@view.students.first().id) expect(users.first().id).toBe(@view.students.first().id)
describe 'Export Student Progress (CSV) button', ->
it 'downloads a CSV file', ->
spyOn(window, 'open').and.callFake (encodedCSV) =>
progressData = decodeURI(encodedCSV)
CSVHeader = 'data:text\/csv;charset=utf-8,'
expect(progressData).toMatch new RegExp('^' + CSVHeader)
lines = progressData.slice(CSVHeader.length).split('\n')
expect(lines.length).toBe(@students.length + 1)
for line in lines
simplerLine = line.replace(/"[^"]+"/g, '""')
# Username,Email,Total Playtime, [CS1-? Playtime], Concepts
expect(simplerLine.match(/[^,]+/g).length).toBe(3 + @releasedCourses.length + 1)
if simplerLine.match new RegExp(@finishedStudent.get('email'))
expect(simplerLine).toMatch /2 minutes,2 minutes,0/
else if simplerLine.match new RegExp(@unfinishedStudent.get('email'))
expect(simplerLine).toMatch /a minute,a minute,0/
else if simplerLine.match /@/
expect(simplerLine).toMatch /0,0,0/
return true
@view.$('.export-student-progress-btn').click()
expect(window.open).toHaveBeenCalled()