mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
Merge branch 'master' into production
This commit is contained in:
commit
03bc785201
12 changed files with 121 additions and 64 deletions
|
@ -15,19 +15,31 @@ userPropsToSave =
|
|||
module.exports = FacebookHandler = class FacebookHandler extends CocoClass
|
||||
subscriptions:
|
||||
'auth:logged-in-with-facebook': 'onFacebookLoggedIn'
|
||||
|
||||
loggedIn: false
|
||||
|
||||
onFacebookLoggedIn: (e) ->
|
||||
# user is logged in also when the page first loads, so check to see
|
||||
# if we really need to do the lookup
|
||||
return if not me
|
||||
|
||||
doIt = false
|
||||
@loggedIn = false
|
||||
@authResponse = e.response.authResponse
|
||||
for fbProp, userProp of userPropsToSave
|
||||
unless me.get(userProp)
|
||||
doIt = true
|
||||
@loggedIn = true
|
||||
break
|
||||
FB.api('/me', @onReceiveMeInfo) if doIt
|
||||
|
||||
if @waitingForLogin and @loggedIn
|
||||
@fetchMeForLogin()
|
||||
|
||||
loginThroughFacebook: ->
|
||||
if @loggedIn
|
||||
@fetchMeForLogin()
|
||||
else
|
||||
FB.login()
|
||||
@waitingForLogin = true
|
||||
|
||||
fetchMeForLogin: ->
|
||||
FB.api('/me', @onReceiveMeInfo)
|
||||
|
||||
onReceiveMeInfo: (r) =>
|
||||
unless r.email
|
||||
|
|
|
@ -4,7 +4,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
no_ie: "O CodeCombat não funciona no Internet Explorer 8 ou anterior. Desculpa!" # Warning that only shows up in IE8 and older
|
||||
no_mobile: "O CodeCombat não foi feito para dispositivos móveis e pode não funcionar!" # Warning that shows up on mobile devices
|
||||
play: "Jogar" # The big play button that opens up the campaign view.
|
||||
# play_campaign_version: "Play Campaign Version" # Shows up under big play button if you only play /courses
|
||||
play_campaign_version: "Jogar Versão da Campanha" # Shows up under big play button if you only play /courses
|
||||
old_browser: "Uh oh, o teu navegador é demasiado antigo para que o CodeCombat funcione. Desculpa!" # Warning that shows up on really old Firefox/Chrome/Safari
|
||||
old_browser_suffix: "Podes tentar na mesma, mas provavelmente não vai funcionar."
|
||||
ipad_browser: "Más notícias: o CodeCombat não funciona no navegador do iPad. Boas notícias: a nossa aplicação nativa para iPad está à espera da aprovação da Apple."
|
||||
|
@ -78,7 +78,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
subscription_required: "Subscrição Necessária"
|
||||
anonymous: "Jogador Anónimo"
|
||||
level_difficulty: "Dificuldade: "
|
||||
# play_classroom_version: "Play Classroom Version" # Choose a level in campaign version that you also can play in one of your courses
|
||||
play_classroom_version: "Jogar Versão da Turma" # Choose a level in campaign version that you also can play in one of your courses
|
||||
campaign_beginner: "Campanha para Iniciantes"
|
||||
awaiting_levels_adventurer_prefix: "Lançamos novos níveis todas as semanas."
|
||||
awaiting_levels_adventurer: "Regista-te como Aventureiro"
|
||||
|
@ -118,9 +118,9 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
social_signup: "Ou podes registar-te através do FB ou do Google+:"
|
||||
required: "Precisas de iniciar sessão antes de prosseguires."
|
||||
login_switch: "Já tens uma conta?"
|
||||
# school_name: "School Name and City"
|
||||
# optional: "optional"
|
||||
# school_name_placeholder: "Example High School, Springfield, IL"
|
||||
school_name: "Nome e Cidade da Escola"
|
||||
optional: "opcional"
|
||||
school_name_placeholder: "Exemplo: Escola Secundária, Springfield, Illinois"
|
||||
|
||||
recover:
|
||||
recover_account_title: "Recuperar Conta"
|
||||
|
@ -674,8 +674,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
being_reviewed_1: "A tua aplicação para uma avaliação gratuita está a ser"
|
||||
being_reviewed_2: "revista."
|
||||
approved_1: "A tua aplicação para uma avaliação gratuita foi"
|
||||
approved_2: "aprovada." # {change}
|
||||
approved_4: "Inscreve os teus alunos na" # {change}
|
||||
approved_2: "aprovada!"
|
||||
approved_4: "Agora podes inscrever os teus alunos na"
|
||||
approved_5: "página"
|
||||
approved_6: "dos cursos."
|
||||
denied_1: "A tua aplicação para uma avaliação gratuita foi"
|
||||
|
@ -860,24 +860,24 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
playtime: "Tempo de jogo"
|
||||
last_played: "Última vez jogado"
|
||||
leagues_explanation: "Joga numa liga contra outros membros do clã nestas instâncias de arenas multijogador."
|
||||
# track_concepts1: "Track concepts"
|
||||
# track_concepts2a: "learned by each student"
|
||||
# track_concepts2b: "learned by each member"
|
||||
# track_concepts3a: "Track levels completed for each student"
|
||||
# track_concepts3b: "Track levels completed for each member"
|
||||
# track_concepts4a: "See your students'"
|
||||
# track_concepts4b: "See your members'"
|
||||
# track_concepts5: "solutions"
|
||||
# track_concepts6a: "Sort students by name or progress"
|
||||
# track_concepts6b: "Sort members by name or progress"
|
||||
# track_concepts7: "Requires invitation"
|
||||
# track_concepts8: "to join"
|
||||
# private_require_sub: "Private clans require a subscription to create or join."
|
||||
track_concepts1: "Acompanhe os conceitos"
|
||||
track_concepts2a: "aprendidos por cada estudante"
|
||||
track_concepts2b: "aprendidos por cada membro"
|
||||
track_concepts3a: "Acompanhe os níveis completados por cada estudante"
|
||||
track_concepts3b: "Acompanhe os níveis completados por cada membro"
|
||||
track_concepts4a: "Veja, dos seus alunos, as"
|
||||
track_concepts4b: "Veja, dos seus membros, as"
|
||||
track_concepts5: "soluções"
|
||||
track_concepts6a: "Ordene os alunos por nome ou progresso"
|
||||
track_concepts6b: "Ordene os membros por nome ou progresso"
|
||||
track_concepts7: "É necessário um convite"
|
||||
track_concepts8: "para se juntar"
|
||||
private_require_sub: "É necessária uma subscrição para criar ou entrar num clã privado."
|
||||
|
||||
courses:
|
||||
course: "Curso"
|
||||
courses: "cursos"
|
||||
# create_new_class: "Create New Class"
|
||||
create_new_class: "Criar Turma Nova"
|
||||
not_enrolled: "Não estás inscrito neste curso."
|
||||
visit_pref: "Por favor visita a página dos"
|
||||
visit_suf: "para te inscreveres."
|
||||
|
@ -1316,7 +1316,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
tutorial_skip: "Saltar Tutorial"
|
||||
tutorial_not_sure: "Não tens a certeza do que se passa?"
|
||||
tutorial_play_first: "Joga o Tutorial primeiro."
|
||||
simple_ai: "IA Simples" # {change}
|
||||
simple_ai: "CPU Simples"
|
||||
warmup: "Aquecimento"
|
||||
friends_playing: "Amigos a Jogar"
|
||||
log_in_for_friends: "Inicia sessão para jogares com os teus amigos!"
|
||||
|
@ -1338,8 +1338,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
rules: "Regras"
|
||||
winners: "Vencedores"
|
||||
league: "Liga"
|
||||
red_ai: "IA Vermelha" # "Red AI Wins", at end of multiplayer match playback
|
||||
blue_ai: "IA Azul" # {change}
|
||||
red_ai: "CPU Vermelho" # "Red AI Wins", at end of multiplayer match playback
|
||||
blue_ai: "CPU Azul"
|
||||
wins: "Vence" # At end of multiplayer match playback
|
||||
humans: "Vermelho" # Ladder page display team name
|
||||
ogres: "Azul"
|
||||
|
@ -1491,16 +1491,16 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
campaigns: "Campanhas"
|
||||
poll: "Votações"
|
||||
user_polls_record: "Histórico das Votações"
|
||||
# course: "Course"
|
||||
# courses: "Courses"
|
||||
# course_instance: "Course Instance"
|
||||
# course_instances: "Course Instances"
|
||||
# classroom: "Classroom"
|
||||
# classrooms: "Classrooms"
|
||||
# clan: "Clan"
|
||||
# clans: "Clans"
|
||||
# members: "Members"
|
||||
# users: "Users"
|
||||
course: "Curso"
|
||||
courses: "Cursos"
|
||||
course_instance: "Instância do Curso"
|
||||
course_instances: "Instâncias do Curso"
|
||||
classroom: "Turma"
|
||||
classrooms: "Turmas"
|
||||
clan: "Clã"
|
||||
clans: "Clãs"
|
||||
members: "Membros"
|
||||
users: "Utilizadores"
|
||||
|
||||
concepts:
|
||||
advanced_strings: "'Strings' Avançadas"
|
||||
|
|
|
@ -4,6 +4,20 @@
|
|||
#main-account-view
|
||||
#account-links
|
||||
width: 300px
|
||||
|
||||
|
||||
#account-links .btn
|
||||
width: 100%
|
||||
width: 100%
|
||||
padding: 35px
|
||||
margin-bottom: 10%
|
||||
font-size: 25px
|
||||
background-image: linear-gradient(to bottom, rgba(181,169,125,0), rgba(181,169,125,255))
|
||||
font-weight: 600
|
||||
|
||||
.logout-btn
|
||||
font-weight: bold
|
||||
|
||||
.row-top-buffer
|
||||
margin-top: 5%
|
||||
|
||||
.row-bot-buffer
|
||||
margin-bottom: 7%
|
|
@ -11,17 +11,23 @@ block content
|
|||
a(href="/")
|
||||
span.glyphicon.glyphicon-home
|
||||
li.active(data-i18n="nav.account")
|
||||
|
||||
#account-links.panel.panel-default
|
||||
.panel-heading(data-i18n="nav.account")
|
||||
ul.list-group
|
||||
li.list-group-item
|
||||
a.btn.btn-lg.btn-primary(href="/user/#{me.getSlugOrID()}", data-i18n="nav.profile")
|
||||
li.list-group-item
|
||||
div.row.row-top-buffer
|
||||
div.col-md-4
|
||||
#account-links
|
||||
a.btn.btn-lg.btn-primary(href="/user/#{me.getSlugOrID()}", data-i18n="nav.profile")
|
||||
div.col-md-4
|
||||
#account-links
|
||||
a.btn.btn-lg.btn-primary(href="/account/settings", data-i18n="play.settings")
|
||||
li.list-group-item
|
||||
div.col-md-4
|
||||
#account-links
|
||||
a.btn.btn-lg.btn-primary(href="/account/payments", data-i18n="account.payments")
|
||||
li.list-group-item
|
||||
div.row.row-bot-buffer
|
||||
div.col-md-4
|
||||
#account-links
|
||||
a.btn.btn-lg.btn-primary(href="/account/subscription", data-i18n="account.subscription")
|
||||
li.list-group-item
|
||||
div.col-md-4
|
||||
#account-links
|
||||
a.btn.btn-lg.btn-primary(href="/account/prepaid", data-i18n="account.prepaid_codes") Prepaid Codes
|
||||
div.col-md-4
|
||||
#account-links
|
||||
a.btn.btn-lg.btn-primary.logout-btn(href="/account", data-i18n="login.log_out")
|
||||
|
|
|
@ -88,11 +88,9 @@
|
|||
// btn.btn.btn-sm.github-login-button#github-login-button
|
||||
// img(src="/images/pages/modal/auth/github_icon.png")
|
||||
// | GitHub
|
||||
.btn.btn-primary.btn-lg.btn-illustrated.network-login
|
||||
#facebook-login-btn.btn.btn-primary.btn-lg.btn-illustrated.network-login
|
||||
img.network-logo(src="/images/pages/community/logo_facebook.png", draggable="false")
|
||||
span.sign-in-blurb(data-i18n="login.sign_in_with_facebook") Sign in with Facebook
|
||||
.facebook-login-wrapper
|
||||
.fb-login-button(data-show-faces="false", data-width="200", data-max-rows="1", data-scope="email")
|
||||
.btn.btn-danger.btn-lg.btn-illustrated.network-login
|
||||
img.network-logo(src="/images/pages/community/logo_g+.png", draggable="false")
|
||||
span.sign-in-blurb(data-i18n="login.sign_in_with_gplus") Sign in with G+
|
||||
|
|
|
@ -139,23 +139,30 @@ block content
|
|||
th(data-i18n="courses.concepts")
|
||||
tbody
|
||||
if campaign
|
||||
- var lastLevelCompleted = true;
|
||||
- var previousLevelCompleted = true;
|
||||
- var lastLevelCompleted = view.getLastLevelCompleted();
|
||||
- var passedLastCompletedLevel = false;
|
||||
- var levelCount = 0;
|
||||
each level, levelID in campaign.get('levels')
|
||||
- var levelStatus = null;
|
||||
if userLevelStateMap[me.id]
|
||||
- levelStatus = userLevelStateMap[me.id][levelID]
|
||||
tr
|
||||
td
|
||||
if lastLevelCompleted || view.teacherMode
|
||||
if previousLevelCompleted || view.teacherMode || !passedLastCompletedLevel || levelStatus
|
||||
- var i18n = level.type === 'course-ladder' ? 'play.compete' : 'home.play';
|
||||
button.btn.btn-success.btn-play-level(data-level-slug=level.slug, data-i18n=i18n, data-level-id=levelID)
|
||||
td
|
||||
if userLevelStateMap[me.id]
|
||||
div= userLevelStateMap[me.id][levelID]
|
||||
- lastLevelCompleted = userLevelStateMap[me.id][levelID] === 'complete'
|
||||
- previousLevelCompleted = userLevelStateMap[me.id][levelID] === 'complete'
|
||||
else
|
||||
- lastLevelCompleted = false
|
||||
- previousLevelCompleted = false
|
||||
td= ++levelCount + '. ' + level.name.replace('Course: ', '')
|
||||
td
|
||||
if levelConceptMap[levelID]
|
||||
each concept in course.get('concepts')
|
||||
if levelConceptMap[levelID][concept]
|
||||
span.spr.concept(data-i18n="concepts." + concept)
|
||||
if levelID === lastLevelCompleted
|
||||
- passedLastCompletedLevel = true
|
||||
|
|
|
@ -66,7 +66,7 @@ block content
|
|||
span.spr :
|
||||
span.spr(data-i18n="courses.course")
|
||||
span 1
|
||||
span.spr= (me.get('aceConfig') || {}).language === 'python' ? 'Python' : 'JavaScript'
|
||||
span.spr= (me.get('aceConfig') || {}).language === 'javascript' ? 'JavaScript' : 'Python'
|
||||
small
|
||||
a#change-language-link(data-i18n="courses.change_language")
|
||||
+course-instance-body(view.hocCourseInstance)
|
||||
|
@ -86,7 +86,7 @@ block content
|
|||
div(class=classroomClass)
|
||||
h3
|
||||
span.spr= classroom.get('name')
|
||||
span.spr (#{(classroom.get('aceConfig') || {}).language === 'python' ? 'Python' : 'JavaScript'})
|
||||
span.spr (#{(classroom.get('aceConfig') || {}).language === 'javascript' ? 'JavaScript' : 'Python'})
|
||||
a(href="/courses/"+classroom.id, data-i18n="courses.view_class")
|
||||
|
||||
- var courseInstances = view.courseInstances.where({classroomID: classroom.id});
|
||||
|
|
|
@ -3,4 +3,7 @@ template = require 'templates/account/main-account-view'
|
|||
|
||||
module.exports = class MainAccountView extends RootView
|
||||
id: 'main-account-view'
|
||||
template: template
|
||||
template: template
|
||||
|
||||
events:
|
||||
'click .logout-btn': 'logoutAccount'
|
|
@ -19,6 +19,7 @@ module.exports = class AuthModal extends ModalView
|
|||
'keyup #name': 'onNameChange'
|
||||
'click #gplus-login-button': 'onClickGPlusLogin'
|
||||
'click #close-modal': 'hide'
|
||||
'click #facebook-login-btn': 'onClickFacebookLoginButton'
|
||||
|
||||
subscriptions:
|
||||
'errors:server-error': 'onServerError'
|
||||
|
@ -158,6 +159,9 @@ module.exports = class AuthModal extends ModalView
|
|||
@$el.find('.modal-body:visible').empty().append(el)
|
||||
@$el.find('.modal-footer').remove()
|
||||
|
||||
onClickFacebookLoginButton: ->
|
||||
application.facebookHandler.loginThroughFacebook()
|
||||
|
||||
onHidden: ->
|
||||
super()
|
||||
@playSound 'game-menu-close'
|
||||
|
|
|
@ -238,3 +238,10 @@ module.exports = class CourseDetailsView extends RootView
|
|||
else
|
||||
storage.save 'no-school', true
|
||||
@$el.find('#school-form').slideUp('slow')
|
||||
|
||||
getLastLevelCompleted: ->
|
||||
lastLevelCompleted = null
|
||||
for levelID in _.keys(@campaign.get('levels'))
|
||||
if @userLevelStateMap?[me.id]?[levelID] is 'complete'
|
||||
lastLevelCompleted = levelID
|
||||
return lastLevelCompleted
|
||||
|
|
|
@ -348,7 +348,11 @@ module.exports = class Handler
|
|||
return @sendForbiddenError(res) if @modelClass.schema.uses_coco_versions and not req.user.isAdmin() # Campaign editor just saves over things.
|
||||
return @sendBadInputError(res, 'No input.') if _.isEmpty(req.body)
|
||||
return @sendForbiddenError(res) unless @hasAccess(req)
|
||||
@getDocumentForIdOrSlug req.body._id or id, (err, document) =>
|
||||
idOrSlug = req.body._id or id
|
||||
if not idOrSlug or idOrSlug is 'undefined'
|
||||
console.error "Bad PUT trying to fetching the slug: #{idOrSlug} for #{@modelClass.collection?.name} from #{req.headers['x-current-path']}?"
|
||||
return @sendBadInputError(res, 'No _id field provided.')
|
||||
@getDocumentForIdOrSlug idOrSlug, (err, document) =>
|
||||
return @sendBadInputError(res, 'Bad id.') if err and err.name is 'CastError'
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res) unless document?
|
||||
|
@ -502,7 +506,7 @@ module.exports = class Handler
|
|||
query = @modelClass.findById(idOrSlug)
|
||||
else
|
||||
if not idOrSlug or idOrSlug is 'undefined'
|
||||
console.error "What? Why are we fetching the slug: #{idOrSlug}?"
|
||||
console.error "Bad request trying to fetching the slug: #{idOrSlug} for #{@modelClass.collection?.name}"
|
||||
console.trace()
|
||||
return done null, null
|
||||
query = @modelClass.findOne {slug: idOrSlug}
|
||||
|
|
|
@ -51,6 +51,7 @@ mockMe =
|
|||
|
||||
window.FB ?= {
|
||||
api: ->
|
||||
login: ->
|
||||
}
|
||||
|
||||
describe 'lib/FacebookHandler.coffee', ->
|
||||
|
@ -61,7 +62,8 @@ describe 'lib/FacebookHandler.coffee', ->
|
|||
|
||||
spyOn FB, 'api'
|
||||
|
||||
new FacebookHandler()
|
||||
facebookHandler = new FacebookHandler()
|
||||
facebookHandler.loginThroughFacebook()
|
||||
Backbone.Mediator.publish 'auth:logged-in-with-facebook', mockAuthEvent
|
||||
|
||||
expect(FB.api).toHaveBeenCalled()
|
||||
|
|
Loading…
Reference in a new issue