Merge branch 'master' into production

This commit is contained in:
Phoenix Eliot 2016-08-19 14:03:23 -07:00
commit 44651108d4
9 changed files with 96 additions and 73 deletions

View file

@ -35,6 +35,8 @@ function receiveMessage(event) {
case 'create': case 'create':
create(_.pick(data, 'dom', 'styles', 'scripts')); create(_.pick(data, 'dom', 'styles', 'scripts'));
checkGoals(data.goals, source, origin); checkGoals(data.goals, source, origin);
$('body').first().off('click', checkRememberedGoals);
$('body').first().on('click', checkRememberedGoals);
break; break;
case 'update': case 'update':
if (virtualDom) if (virtualDom)
@ -108,7 +110,13 @@ function update(options) {
virtualScripts = scripts; virtualScripts = scripts;
} }
var lastGoalArgs = [];
function checkRememberedGoals() {
checkGoals.apply(this, lastGoalArgs);
}
function checkGoals(goals, source, origin) { function checkGoals(goals, source, origin) {
lastGoalArgs = [goals, source, origin]; // Memoize for checkRememberedGoals
// Check right now and also in one second, since our 1-second CSS transition might be affecting things until it is done. // Check right now and also in one second, since our 1-second CSS transition might be affecting things until it is done.
doCheckGoals(goals, source, origin); doCheckGoals(goals, source, origin);
_.delay(function() { doCheckGoals(goals, source, origin); }, 1001); _.delay(function() { doCheckGoals(goals, source, origin); }, 1001);

View file

@ -83,6 +83,8 @@ module.exports = Surface = class Surface extends CocoClass
constructor: (@world, @normalCanvas, @webGLCanvas, givenOptions) -> constructor: (@world, @normalCanvas, @webGLCanvas, givenOptions) ->
super() super()
$(window).on('keydown', @onKeyEvent)
$(window).on('keyup', @onKeyEvent)
@normalLayers = [] @normalLayers = []
@options = _.clone(@defaults) @options = _.clone(@defaults)
@options = _.extend(@options, givenOptions) if givenOptions @options = _.extend(@options, givenOptions) if givenOptions
@ -540,7 +542,13 @@ module.exports = Surface = class Surface extends CocoClass
event.screenPos = @mouseScreenPos if @mouseScreenPos event.screenPos = @mouseScreenPos if @mouseScreenPos
Backbone.Mediator.publish 'surface:mouse-scrolled', event unless @disabled Backbone.Mediator.publish 'surface:mouse-scrolled', event unless @disabled
@gameUIState.trigger('surface:mouse-scrolled', event) @gameUIState.trigger('surface:mouse-scrolled', event)
#- Keyboard callbacks
onKeyEvent: (e) =>
return unless @realTime
@realTimeInputEvents.add(_.pick(e, 'type', 'keyCode', 'ctrlKey', 'metaKey', 'shiftKey'))
#- Canvas callbacks #- Canvas callbacks
@ -758,6 +766,8 @@ module.exports = Surface = class Surface extends CocoClass
@webGLStage.enableMouseOver 0 @webGLStage.enableMouseOver 0
@webGLCanvas.off 'mousewheel', @onMouseWheel @webGLCanvas.off 'mousewheel', @onMouseWheel
$(window).off 'resize', @onResize $(window).off 'resize', @onResize
$(window).off('keydown', @onKeyEvent)
$(window).off('keyup', @onKeyEvent)
clearTimeout @surfacePauseTimeout if @surfacePauseTimeout clearTimeout @surfacePauseTimeout if @surfacePauseTimeout
clearTimeout @surfaceZoomPauseTimeout if @surfaceZoomPauseTimeout clearTimeout @surfaceZoomPauseTimeout if @surfaceZoomPauseTimeout
super() super()

View file

@ -1419,7 +1419,7 @@
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"
no_students_yet: "This class has no students yet." no_students_yet: "View class to add students." # {change}
try_refreshing: "(You may need to refresh the page)" try_refreshing: "(You may need to refresh the page)"
add_students: "Add Students" add_students: "Add Students"
create_new_class: "Create a New Class" create_new_class: "Create a New Class"

View file

@ -237,7 +237,7 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
email_invalid: "Endereço de email inválido." email_invalid: "Endereço de email inválido."
form_blurb: "Informe os e-mails abaixo e mostraremos a eles!" form_blurb: "Informe os e-mails abaixo e mostraremos a eles!"
form_label: "Endereço de Email" form_label: "Endereço de Email"
placeholder: "endereço de email" placeholder: "Endereço de email"
title: "Excelente Trabalho, Aprendiz" title: "Excelente Trabalho, Aprendiz"
login: login:
@ -277,34 +277,34 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
connected_facebook_p: "Conclua sua inscrição para que você possa fazer login com sua conta do Facebook." connected_facebook_p: "Conclua sua inscrição para que você possa fazer login com sua conta do Facebook."
facebook_exists: "Você já tem uma conta associada com o Facebook!" facebook_exists: "Você já tem uma conta associada com o Facebook!"
hey_students: "Estudantes, insira o código de classe do seu professor." hey_students: "Estudantes, insira o código de classe do seu professor."
# birthday: "Birthday" birthday: "Aniversário"
# parent_email_blurb: "We know you can't wait to learn programming — we're excited too! Your parents will receive an email with further instructions on how to create an account for you. Email {{email_link}} if you have any questions." parent_email_blurb: "Nós sabemos que você não vê a hora de aprender programação ; nós estamos animados tambem ! Seus responsáveis irão receber um email com mais instruçoes em como criar uma conta para você .Mande um email {{email_link}} se ouver alguma pergunta."
# classroom_not_found: "No classes exist with this Class Code. Check your spelling or ask your teacher for help." classroom_not_found: "Nenhuma classe existe com esse codigo.Veja se o codigo esta correto ou peça ajuda ao seu professor."
# checking: "Checking..." checking: "Checando..."
# account_exists: "This email is already in use:" account_exists: "Esse email já esta sendo usado:"
# sign_in: "Sign in" sign_in: "Logar"
# email_good: "Email looks good!" email_good: "Email parece bom!"
# name_taken: "Username already taken! Try {{suggestedName}}?" name_taken: "Esse nome de usuario já esta sendo usado! Tente {{suggestedName}}?"
# name_available: "Username available!" name_available: "Nome disponivel!"
# name_is_email: "Username may not be an email" name_is_email: "O nome de usuario não pode ser um email"
# choose_type: "Choose your account type:" choose_type: "Escolha seu tipo de conta:"
# teacher_type_1: "Teach programming using CodeCombat!" teacher_type_1: "Ensine programação usando CodeCombat!"
# teacher_type_2: "Set up your class" teacher_type_2: "Organize sua sala"
# teacher_type_3: "Access Course Guides" teacher_type_3: "Acessar seus guias de curso"
# teacher_type_4: "View student progress" teacher_type_4: "Ver progresso do estudante"
# signup_as_teacher: "Sign up as a Teacher" signup_as_teacher: "Cadastrar como professor"
# student_type_1: "Learn to program while playing an engaging game!" student_type_1: "Aprenda programação enquanto se diverte jogando!"
# student_type_2: "Play with your class" student_type_2: "Jogue com sua classe"
# student_type_3: "Compete in arenas" student_type_3: "Competir em arenas"
# student_type_4: "Choose your hero!" student_type_4: "Escolha seu herói!"
# student_type_5: "Have your Class Code ready!" student_type_5: "Tenha o seu codigo de classe pronto!"
# signup_as_student: "Sign up as a Student" signup_as_student: "Cadastrar como estudante"
# individuals_or_parents: "Individuals & Parents" individuals_or_parents: "Individuais e resposáveis"
# individual_type: "For players learning to code outside of a class. Parents should sign up for an account here." individual_type: "Para aprender a programar fora da classe.Os responsáveis devem requerer uma conta aqui."
# signup_as_individual: "Sign up as an Individual" signup_as_individual: "Registrar como individual"
# enter_class_code: "Enter your Class Code" enter_class_code: "Coloque seu código de classe"
# enter_birthdate: "Enter your birthdate:" enter_birthdate: "Coloque sua data de aniversário:"
# parent_use_birthdate: "Parents, use your own birthdate." parent_use_birthdate: "Responsáveis, usem o seu propio dia de nascimento."
# ask_teacher_1: "Ask your teacher for your Class Code." # ask_teacher_1: "Ask your teacher for your Class Code."
# ask_teacher_2: "Not part of a class? Create an " # ask_teacher_2: "Not part of a class? Create an "
# ask_teacher_3: "Individual Account" # ask_teacher_3: "Individual Account"

View file

@ -92,10 +92,6 @@ mixin addStudentsButton(classroom)
.add-students .add-students
.text-center .text-center
div.small-details(data-i18n='teacher.no_students_yet') div.small-details(data-i18n='teacher.no_students_yet')
| This class has no students yet.
a.add-students-btn.btn.btn-lg.btn-primary(data-classroom-id=classroom.id )
span(data-i18n='teacher.add_students')
| Add Students
mixin createClassButton mixin createClassButton
.create-class .create-class

View file

@ -242,7 +242,7 @@ block content
h6.course-name= i18n(course.attributes, 'name') + ':' h6.course-name= i18n(course.attributes, 'name') + ':'
p.small p.small
- var total = 0; - var total = 0;
each concept in course.get('concepts') each concept in course.get('concepts') || []
- if (conceptsSeen[concept]) continue; - if (conceptsSeen[concept]) continue;
- conceptsSeen[concept] = true; - conceptsSeen[concept] = true;
if total === 3 if total === 3

View file

@ -5,10 +5,10 @@ if view.options.level.isType('game-dev')
span(data-i18n="play_level.done") span(data-i18n="play_level.done")
else else
button.btn.btn-lg.btn-illustrated.cast-button(title=view.castVerbose()) button.btn.btn-lg.btn-illustrated.cast-button(title=view.castVerbose())
span(data-i18n="play_level.tome_run_button_ran") Ran span(data-i18n="play_level.tome_cast_button_ran") Ran
if !view.observing if !view.observing
if view.mirror if view.mirror
.ladder-submission-view .ladder-submission-view
@ -16,10 +16,10 @@ else
button.btn.btn-lg.btn-illustrated.submit-button(title=view.castRealTimeVerbose()) button.btn.btn-lg.btn-illustrated.submit-button(title=view.castRealTimeVerbose())
span(data-i18n="play_level.tome_submit_button") Submit span(data-i18n="play_level.tome_submit_button") Submit
span.spl.secret.submit-again-time span.spl.secret.submit-again-time
button.btn.btn-lg.btn-illustrated.btn-success.done-button.secret button.btn.btn-lg.btn-illustrated.btn-success.done-button.secret
span(data-i18n="play_level.done") Done span(data-i18n="play_level.done") Done
if view.autoSubmitsToLadder if view.autoSubmitsToLadder
.hidden .hidden
.ladder-submission-view .ladder-submission-view

View file

@ -0,0 +1,35 @@
// Find classrooms referencing invalid courses
// Usage:
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
print("Finding classrooms..");
var courseIDMap = {};
db.classrooms.find({}, {name: 1, courses: 1}).toArray().forEach(function (classroom) {
for (var i = 0; i < classroom.courses.length; i++) {
courseIDMap[classroom.courses[i]._id.valueOf()] = true;
}
});
var courseIDs = [];
for (var courseID in courseIDMap) {
print(courseID);
courseIDs.push(ObjectId(courseID));
}
print("Unique courses referenced from classrooms: " + courseIDs.length);
print("Finding referenced courses..");
var foundMap = {};
db.courses.find({_id: {$in: courseIDs}}).toArray().forEach(function (course) {
foundMap[course._id.valueOf()] = true;
});
print("Finding invalid courses and their classrooms..");
for (var courseID in courseIDMap) {
if (!foundMap[courseID]) {
print("Missing course: " + courseID);
db.classrooms.find({'courses._id': ObjectId(courseID)}, {name: 1}).toArray().forEach(function (classroom) {
print("Missing classroom: " + classroom._id.valueOf() + " " + classroom.name);
});
}
}

View file

@ -4,8 +4,7 @@
// mongo <address>:<port>/<database> <script file> -u <username> -p <password> // mongo <address>:<port>/<database> <script file> -u <username> -p <password>
// eg: mongo localhost:27017/coco scripts/mongodb/updateCourses.js // eg: mongo localhost:27017/coco scripts/mongodb/updateCourses.js
// NOTE: uses name as unique identifier, so changing the name will insert a new course // NOTE: uses slug as unique identifier, so changing the slug will insert a new course
// NOTE: pricePerSeat in USD cents
load('bower_components/lodash/dist/lodash.js'); load('bower_components/lodash/dist/lodash.js');
var courses = var courses =
@ -96,33 +95,6 @@ var courses =
screenshot: "/images/pages/courses/105_info.png", screenshot: "/images/pages/courses/105_info.png",
releasePhase: 'released' releasePhase: 'released'
}, },
{
name: "CS: Game Development 1",
slug: "game-dev-1",
campaignID: ObjectId("5789236960deed1f00ec2ab8"),
description: "Learn to create your own games which you can share with your friends.",
duration: NumberInt(1),
free: false,
releasePhase: 'released'
},
{
name: "CS: Web Development 1",
slug: "web-dev-1",
campaignID: ObjectId("578913f2c8871ac2326fa3e4"),
description: "Learn the basics of web development in this introductory HTML & CSS course.",
duration: NumberInt(1),
free: false,
releasePhase: 'released'
},
{
name: "CS: Web Development 2",
slug: "web-dev-2",
campaignID: ObjectId("57891570c8871ac2326fa3f8"),
description: "Learn more advanced web development, including scripting to make interactive webpages.",
duration: NumberInt(2),
free: false,
releasePhase: 'beta'
},
{ {
name: "JS Primer", name: "JS Primer",
slug: "js-primer", slug: "js-primer",
@ -147,13 +119,15 @@ _.forEach(courses, function(course) {
} }
} }
course.concepts = Object.keys(concepts); course.concepts = Object.keys(concepts);
}); });
print("Updating courses.."); print("Updating courses..");
for (var i = 0; i < courses.length; i++) { for (var i = 0; i < courses.length; i++) {
db.courses.update({slug: courses[i].slug}, {$set: courses[i]}, {upsert: true}); var result = db.courses.update({slug: courses[i].slug}, {$set: courses[i]});
if (result.nMatched !== 1) {
print("Failed to update " + courses[i].slug);
print(JSON.stringify(result, null, 2));
}
} }
print("Upserting i18n", db.courses.update( print("Upserting i18n", db.courses.update(