This commit is contained in:
Jasper D'haene 2014-04-13 15:24:58 +02:00
commit 7aa2a5f0c8
62 changed files with 317 additions and 433 deletions

View file

@ -3,7 +3,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
loading: "Загрузка..." loading: "Загрузка..."
saving: "Сохранение..." saving: "Сохранение..."
sending: "Отправка..." sending: "Отправка..."
# send: "Send" send: "Отправить"
cancel: "Отмена" cancel: "Отмена"
save: "Сохранить" save: "Сохранить"
create: "Создать" create: "Создать"
@ -115,8 +115,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
forum_page: "наш форум" forum_page: "наш форум"
forum_suffix: "." forum_suffix: "."
send: "Отправить отзыв" send: "Отправить отзыв"
# contact_candidate: "Contact Candidate" contact_candidate: "Связаться с кандидатом"
# recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 18% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns." recruitment_reminder: "Используйте эту форму, чтобы обратиться к кандидатам, если вы заинтересованы в интервью. Помните, что CodeCombat взимает 18% от первого года зарплаты. Плата производится по найму сотрудника и подлежит возмещению в течение 90 дней, если работник не остаётся на рабочем месте. Работники с частичной занятостью, удалённые и работающие по контракту свободны, как стажёры."
diplomat_suggestion: diplomat_suggestion:
title: "Помогите перевести CodeCombat!" title: "Помогите перевести CodeCombat!"
@ -151,7 +151,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
wizard_tab: "Волшебник" wizard_tab: "Волшебник"
password_tab: "Пароль" password_tab: "Пароль"
emails_tab: "Email-адреса" emails_tab: "Email-адреса"
# job_profile_tab: "Job Profile" job_profile_tab: "Профиль соискателя"
admin: "Админ" admin: "Админ"
wizard_color: "Цвет одежды волшебника" wizard_color: "Цвет одежды волшебника"
new_password: "Новый пароль" new_password: "Новый пароль"
@ -169,37 +169,37 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
error_saving: "Ошибка сохранения" error_saving: "Ошибка сохранения"
saved: "Изменения сохранены" saved: "Изменения сохранены"
password_mismatch: "Пароли не совпадают." password_mismatch: "Пароли не совпадают."
# job_profile: "Job Profile" job_profile: "Профиль соискателя"
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks." job_profile_approved: "Ваш профиль соискателя был одобрен CodeCombat. Работодатели смогут видеть его, пока вы не отметите его неактивным или он не будет изменен в течение четырёх недель."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." job_profile_explanation: "Привет! Заполните это, и мы свяжемся с вами при нахождении работы разработчика программного обеспечения для вас."
account_profile: account_profile:
edit_settings: "Изменить настройки" edit_settings: "Изменить настройки"
profile_for_prefix: "Профиль для " profile_for_prefix: "Профиль для "
profile_for_suffix: "" profile_for_suffix: ""
# approved: "Approved" approved: "Одобрено"
# not_approved: "Not Approved" not_approved: "Не одобрено"
# looking_for: "Looking for:" looking_for: "Ищет:"
# last_updated: "Last updated:" last_updated: "Последнее обновление:"
# contact: "Contact" contact: "Контакты"
# work_experience: "Work Experience" work_experience: "Опыт работы"
# education: "Education" education: "Образование"
# our_notes: "Our Notes" our_notes: "Наши заметки"
# projects: "Projects" projects: "Проекты"
# employers: employers:
# want_to_hire_our_players: "Want to hire expert CodeCombat players?" want_to_hire_our_players: "Хотите нанимать игроков-экспертов CodeCombat?"
# contact_george: "Contact George to see our candidates" contact_george: "Свяжитесь с Джорджем, чтобы посмотреть наших кандидатов"
# candidates_count_prefix: "We currently have " candidates_count_prefix: "Сейчас у нас есть "
# candidates_count_many: "many" candidates_count_many: "много"
# candidates_count_suffix: "highly skilled and vetted developers looking for work." candidates_count_suffix: "высококвалифицированных и проверенных разработчиков, ищущих работу."
# candidate_name: "Name" candidate_name: "Имя"
# candidate_location: "Location" candidate_location: "Местонахождение"
# candidate_looking_for: "Looking For" candidate_looking_for: "Ищет"
# candidate_role: "Role" candidate_role: "Роль"
# candidate_top_skills: "Top Skills" candidate_top_skills: "Лучшие навыки"
# candidate_years_experience: "Yrs Exp" candidate_years_experience: "Лет опыта"
# candidate_last_updated: "Last Updated" candidate_last_updated: "Последнее обновление"
play_level: play_level:
level_load_error: "Уровень не может быть загружен: " level_load_error: "Уровень не может быть загружен: "
@ -379,7 +379,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
results: "Результаты" results: "Результаты"
description: "Описание" description: "Описание"
or: "или" or: "или"
# subject: "Subject" subject: "Тема"
email: "Email" email: "Email"
password: "Пароль" password: "Пароль"
message: "Сообщение" message: "Сообщение"
@ -661,5 +661,5 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
gplus_friends: "Друзья G+" gplus_friends: "Друзья G+"
gplus_friend_sessions: "Сессии друзей G+" gplus_friend_sessions: "Сессии друзей G+"
leaderboard: "таблица лидеров" leaderboard: "таблица лидеров"
# user_schema: "User Schema" user_schema: "Пользовательская Schema"
# user_profile: "User Profile" user_profile: "Пользовательский профиль"

View file

@ -318,15 +318,15 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
contact_us: "联系我们!" contact_us: "联系我们!"
hipchat_prefix: "你也可以在这里找到我们" hipchat_prefix: "你也可以在这里找到我们"
hipchat_url: "HipChat 房间。" hipchat_url: "HipChat 房间。"
# back: "Back" back: "后退"
revert: "还原" revert: "还原"
revert_models: "还原模式" revert_models: "还原模式"
# fork_title: "Fork New Version" fork_title: "派生新版本"
# fork_creating: "Creating Fork..." fork_creating: "正在执行派生..."
# more: "More" more: "更多"
# wiki: "Wiki" wiki: "维基"
# live_chat: "Live Chat" live_chat: "在线聊天"
# level_publish: "Publish This Level (irreversible)?" level_publish: "发布这个关卡吗 (发布后不能撤销)?"
level_some_options: "有哪些选项?" level_some_options: "有哪些选项?"
level_tab_thangs: "物体" level_tab_thangs: "物体"
level_tab_scripts: "脚本" level_tab_scripts: "脚本"
@ -334,11 +334,11 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
level_tab_components: "组件" level_tab_components: "组件"
level_tab_systems: "系统" level_tab_systems: "系统"
level_tab_thangs_title: "目前所有物体" level_tab_thangs_title: "目前所有物体"
# level_tab_thangs_all: "All" level_tab_thangs_all: "所有"
level_tab_thangs_conditions: "启动条件" level_tab_thangs_conditions: "启动条件"
level_tab_thangs_add: "增加物体" level_tab_thangs_add: "增加物体"
# delete: "Delete" delete: "删除"
# duplicate: "Duplicate" duplicate: "复制"
level_settings_title: "设置" level_settings_title: "设置"
level_component_tab_title: "目前所有组件" level_component_tab_title: "目前所有组件"
level_component_btn_new: "创建新的组件" level_component_btn_new: "创建新的组件"

View file

@ -11,14 +11,11 @@ class CocoModel extends Backbone.Model
initialize: -> initialize: ->
super() super()
@constructor.schema ?= @urlRoot[4..].replace '.', '_' @constructor.schema ?= require "schemas/models/#{@urlRoot[4..].replace '.', '_'}"
if not @constructor.className if not @constructor.className
console.error("#{@} needs a className set.") console.error("#{@} needs a className set.")
@markToRevert() @markToRevert()
if @constructor.schema?.loaded @addSchemaDefaults()
@addSchemaDefaults()
else
@loadSchema()
@once 'sync', @onLoaded, @ @once 'sync', @onLoaded, @
@saveBackup = _.debounce(@saveBackup, 500) @saveBackup = _.debounce(@saveBackup, 500)
@ -34,9 +31,8 @@ class CocoModel extends Backbone.Model
onLoaded: -> onLoaded: ->
@loaded = true @loaded = true
@loading = false @loading = false
if @constructor.schema?.loaded @markToRevert()
@markToRevert() @loadFromBackup()
@loadFromBackup()
set: -> set: ->
res = super(arguments...) res = super(arguments...)
@ -55,18 +51,6 @@ class CocoModel extends Backbone.Model
CocoModel.backedUp[@id] = @ CocoModel.backedUp[@id] = @
@backedUp = {} @backedUp = {}
loadSchema: ->
return if @constructor.schema.loading
@constructor.schema = require 'schemas/' + @constructor.schema + '_schema' unless @constructor.schema.loaded
@onConstructorSync()
onConstructorSync: ->
@constructor.schema.loaded = true
@addSchemaDefaults()
@trigger 'schema-loaded'
@hasSchema: -> return @schema?.loaded
schema: -> return @constructor.schema schema: -> return @constructor.schema
validate: -> validate: ->
@ -129,7 +113,7 @@ class CocoModel extends Backbone.Model
@set "permissions", (@get("permissions") or []).concat({access: 'read', target: 'public'}) @set "permissions", (@get("permissions") or []).concat({access: 'read', target: 'public'})
addSchemaDefaults: -> addSchemaDefaults: ->
return if @addedSchemaDefaults or not @constructor.hasSchema() return if @addedSchemaDefaults
@addedSchemaDefaults = true @addedSchemaDefaults = true
for prop, defaultValue of @constructor.schema.default or {} for prop, defaultValue of @constructor.schema.default or {}
continue if @get(prop)? continue if @get(prop)?

View file

@ -2,7 +2,6 @@ class SuperModel
constructor: -> constructor: ->
@models = {} @models = {}
@collections = {} @collections = {}
@schemas = {}
_.extend(@, Backbone.Events) _.extend(@, Backbone.Events)
populateModel: (model) -> populateModel: (model) ->
@ -26,11 +25,7 @@ class SuperModel
@removeEventsFromModel(model) @removeEventsFromModel(model)
modelLoaded: (model) -> modelLoaded: (model) ->
model.loadSchema()
schema = model.schema() schema = model.schema()
unless schema.loaded
@schemas[model.urlRoot] = schema
return schema.once('sync', => @modelLoaded(model))
refs = model.getReferencedModels(model.attributes, schema, '/', @shouldLoadProjection) refs = model.getReferencedModels(model.attributes, schema, '/', @shouldLoadProjection)
refs = [] unless @mustPopulate is model or @shouldPopulate(model) refs = [] unless @mustPopulate is model or @shouldPopulate(model)
# console.log 'Loaded', model.get('name') # console.log 'Loaded', model.get('name')
@ -103,9 +98,6 @@ class SuperModel
for model in _.values @models for model in _.values @models
total += 1 total += 1
loaded += 1 if model.loaded loaded += 1 if model.loaded
for schema in _.values @schemas
total += 1
loaded += 1 if schema.loaded
return 1.0 unless total return 1.0 unless total
return loaded / total return loaded / total

View file

@ -1,4 +1,4 @@
c = require './schemas' c = require './../schemas'
ArticleSchema = c.object() ArticleSchema = c.object()
c.extendNamedProperties ArticleSchema # name first c.extendNamedProperties ArticleSchema # name first

View file

@ -1,5 +1,5 @@
c = require './schemas' c = require './../schemas'
ThangComponentSchema = require './thang_component_schema' ThangComponentSchema = require './../models/thang_component'
SpecificArticleSchema = c.object() SpecificArticleSchema = c.object()
c.extendNamedProperties SpecificArticleSchema # name first c.extendNamedProperties SpecificArticleSchema # name first

View file

@ -1,5 +1,5 @@
c = require './schemas' c = require './../schemas'
metaschema = require './metaschema' metaschema = require './../metaschema'
attackSelfCode = """ attackSelfCode = """
class AttacksSelf extends Component class AttacksSelf extends Component

View file

@ -1,4 +1,4 @@
c = require './schemas' c = require './../schemas'
LevelFeedbackLevelSchema = c.object {required: ['original', 'majorVersion']}, { LevelFeedbackLevelSchema = c.object {required: ['original', 'majorVersion']}, {
original: c.objectId({}) original: c.objectId({})

View file

@ -1,4 +1,4 @@
c = require './schemas' c = require './../schemas'
LevelSessionPlayerSchema = c.object LevelSessionPlayerSchema = c.object
id: c.objectId id: c.objectId

View file

@ -1,5 +1,5 @@
c = require './schemas' c = require './../schemas'
metaschema = require './metaschema' metaschema = require './../metaschema'
jitterSystemCode = """ jitterSystemCode = """
class Jitter extends System class Jitter extends System

View file

@ -1,4 +1,4 @@
c = require './schemas' c = require './../schemas'
patchables = ['level', 'thang_type', 'level_system', 'level_component', 'article'] patchables = ['level', 'thang_type', 'level_system', 'level_component', 'article']

View file

@ -1,4 +1,4 @@
c = require './schemas' c = require './../schemas'
module.exports = ThangComponentSchema = c.object { module.exports = ThangComponentSchema = c.object {
title: "Component" title: "Component"

View file

@ -1,5 +1,5 @@
c = require './schemas' c = require './../schemas'
ThangComponentSchema = require './thang_component_schema' ThangComponentSchema = require './thang_component'
ThangTypeSchema = c.object() ThangTypeSchema = c.object()
c.extendNamedProperties ThangTypeSchema # name first c.extendNamedProperties ThangTypeSchema # name first

View file

@ -1,4 +1,4 @@
c = require './schemas' c = require './../schemas'
emailSubscriptions = ['announcement', 'tester', 'level_creator', 'developer', 'article_editor', 'translator', 'support', 'notification'] emailSubscriptions = ['announcement', 'tester', 'level_creator', 'developer', 'article_editor', 'translator', 'support', 'notification']
UserSchema = c.object {}, UserSchema = c.object {},

View file

@ -49,9 +49,15 @@
&:hover &:hover
background-color: rgba(200, 244, 255, 0.2) background-color: rgba(200, 244, 255, 0.2)
h4 a:not(.has-github)
text-align: center cursor: default
text-decoration: none
img img
max-width: 100px max-width: 100px
max-height: 100px max-height: 100px
.caption
background-color: transparent
h4
text-align: center

View file

@ -53,30 +53,12 @@ block content
span(data-i18n="contribute.adventurer_join_suf") span(data-i18n="contribute.adventurer_join_suf")
| so if you prefer to be notified those ways, sign up there! | so if you prefer to be notified those ways, sign up there!
if me.attributes.anonymous .contributor-signup-anonymous
div#sign-up.alert.alert-info .contributor-signup(data-contributor-class-id="tester", data-contributor-class-name="adventurer")
strong(data-i18n="contribute.alert_account_message_intro")
| Hey there!
span
span(data-i18n="contribute.alert_account_message_pref")
| To subscribe for class emails, you'll need to
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
| create an account
span
span(data-i18n="contribute.alert_account_message_suf")
| first.
label.checkbox(for="tester").well //h3(data-i18n="contribute.brave_adventurers")
input(type='checkbox', name="tester", id="tester") // | Our Brave Adventurers:
span(data-i18n="contribute.adventurer_subscribe_desc") //
| Get emails when there are new levels to test. //#contributor-list
.saved-notification ✓ Saved
//#Contributors
// h3(data-i18n="contribute.brave_adventurers")
// | Our Brave Adventurers:
// ul.adventurers
// li Kieizroe
// li ... many, many more
div.clearfix div.clearfix

View file

@ -47,29 +47,12 @@ block content
| solving levels can summon higher level wizards to help them. | solving levels can summon higher level wizards to help them.
| This will be a great way for ambassadors to do their thing. We'll keep you posted! | This will be a great way for ambassadors to do their thing. We'll keep you posted!
if me.attributes.anonymous .contributor-signup-anonymous
div#sign-up.alert.alert-info .contributor-signup(data-contributor-class-id="support", data-contributor-class-name="ambassador")
strong(data-i18n="contribute.alert_account_message_intro")
| Hey there!
span
span(data-i18n="contribute.alert_account_message_pref")
| To subscribe for class emails, you'll need to
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
| create an account
span
span(data-i18n="contribute.alert_account_message_suf")
| first.
label.checkbox(for="support").well //h3(data-i18n="contribute.helpful_ambassadors")
input(type='checkbox', name="support", id="support") // | Our Helpful Ambassadorsd:
span(data-i18n="contribute.ambassador_subscribe_desc") //
| Get emails on support updates and multiplayer developments. //#contributor-list
.saved-notification ✓ Saved
//#Contributors
// h3(data-i18n="contribute.helpful_ambassadors")
// | Our Helpful Ambassadorsd:
// ul.ambassadors
// li
div.clearfix div.clearfix

View file

@ -57,37 +57,12 @@ block content
span(data-i18n="contribute.join_desc_4") span(data-i18n="contribute.join_desc_4")
| and we'll go from there! | and we'll go from there!
if me.attributes.anonymous .contributor-signup-anonymous
div#sign-up.alert.alert-info .contributor-signup(data-contributor-class-id="developer", data-contributor-class-name="archmage")
strong(data-i18n="contribute.alert_account_message_intro")
| Hey there!
span
span(data-i18n="contribute.alert_account_message_pref")
| To subscribe for class emails, you'll need to
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
| create an account
span
span(data-i18n="contribute.alert_account_message_suf")
| first.
label.checkbox(for="developer").well h3(data-i18n="contribute.powerful_archmages")
input(type='checkbox', name="developer", id="developer") | Our Powerful Archmages:
span(data-i18n="contribute.archmage_subscribe_desc")
| Get emails on new coding opportunities and announcements.
.saved-notification ✓ Saved
#Contributors #contributor-list
h3(data-i18n="contribute.powerful_archmages")
| Our Powerful Archmages:
.row
for contributor in contributors
.col-xs-6.col-md-3
.thumbnail
if contributor.avatar
img.img-responsive(src="/images/pages/contribute/archmage/" + contributor.avatar + "_small.png", alt="")
else
img.img-responsive(src="/images/pages/contribute/archmage.png", alt="")
.caption
h4= contributor.name
div.clearfix div.clearfix

View file

@ -54,38 +54,13 @@ block content
li li
a(href="http://discourse.codecombat.com", data-i18n="contribute.artisan_join_step4") Post your levels on the forum for feedback. a(href="http://discourse.codecombat.com", data-i18n="contribute.artisan_join_step4") Post your levels on the forum for feedback.
if me.attributes.anonymous .contributor-signup-anonymous
div#sign-up.alert.alert-info .contributor-signup(data-contributor-class-id="level_creator", data-contributor-class-name="artisan")
strong(data-i18n="contribute.alert_account_message_intro")
| Hey there!
span
span(data-i18n="contribute.alert_account_message_pref")
| To subscribe for class emails, you'll need to
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
| create an account
span
span(data-i18n="contribute.alert_account_message_suf")
| first.
label.checkbox(for="level_creator").well h3(data-i18n="contribute.creative_artisans")
input(type='checkbox', name="level_creator", id="level_creator") | Our Creative Artisans:
span(data-i18n="contribute.artisan_subscribe_desc")
| Get emails on level editor updates and announcements.
.saved-notification ✓ Saved
#Contributors #contributor-list
h3(data-i18n="contribute.creative_artisans")
| Our Creative Artisans:
.row
for contributor in contributors
.col-xs-6.col-md-3
.thumbnail
if contributor.avatar
img.img-responsive(src="/images/pages/contribute/artisan/" + contributor.avatar + "_small.png", alt="")
else
img.img-responsive(src="/images/pages/contribute/artisan.png", alt="")
.caption
h4= contributor.name
div.clearfix div.clearfix

View file

@ -37,18 +37,7 @@ block content
| - Nick, George, Scott, Michael, Jeremy and Glen | - Nick, George, Scott, Michael, Jeremy and Glen
hr hr
if me.attributes.anonymous .contributor-signup-anonymous
div#sign-up.alert.alert-info
strong(data-i18n="contribute.alert_account_message_intro")
| Hey there!
span
span(data-i18n="contribute.alert_account_message_pref")
| To subscribe for class emails, you'll need to
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
| create an account
span
span(data-i18n="contribute.alert_account_message_suf")
| first.
#archmage.header-scrolling-fix #archmage.header-scrolling-fix
.class_image .class_image
@ -69,13 +58,7 @@ block content
p.lead(data-i18n="contribute.more_about_archmage") p.lead(data-i18n="contribute.more_about_archmage")
| Learn More About Becoming an Archmage | Learn More About Becoming an Archmage
label.checkbox(for="developer").well .contributor-signup(data-contributor-class-id="developer", data-contributor-class-name="archmage")
input(type='checkbox', name="developer", id="developer")
span(data-i18n="contribute.archmage_subscribe_desc")
| Get emails on new coding opportunities and announcements.
.saved-notification
| ✓
span(data-i18n="contribute.saved") Saved
#artisan.header-scrolling-fix #artisan.header-scrolling-fix
@ -102,13 +85,7 @@ block content
p.lead(data-i18n="contribute.more_about_artisan") p.lead(data-i18n="contribute.more_about_artisan")
| Learn More About Becoming An Artisan | Learn More About Becoming An Artisan
label.checkbox(for="level_creator").well .contributor-signup(data-contributor-class-id="level_creator", data-contributor-class-name="artisan")
input(type='checkbox', name="level_creator", id="level_creator")
span(data-i18n="contribute.artisan_subscribe_desc")
| Get emails on level editor updates and announcements.
.saved-notification
| ✓
span(data-i18n="contribute.saved") Saved
#adventurer.header-scrolling-fix #adventurer.header-scrolling-fix
@ -130,13 +107,7 @@ block content
p.lead(data-i18n="contribute.more_about_adventurer") p.lead(data-i18n="contribute.more_about_adventurer")
| Learn More About Becoming an Adventurer | Learn More About Becoming an Adventurer
label.checkbox(for="tester").well .contributor-signup(data-contributor-class-id="tester", data-contributor-class-name="adventurer")
input(type='checkbox', name="tester", id="tester")
span(data-i18n="contribute.adventurer_subscribe_desc")
| Get emails when there are new levels to test.
.saved-notification
| ✓
span(data-i18n="contribute.saved") Saved
#scribe.header-scrolling-fix #scribe.header-scrolling-fix
@ -162,13 +133,7 @@ block content
p.lead(data-i18n="contribute.more_about_scribe") p.lead(data-i18n="contribute.more_about_scribe")
| Learn More About Becoming a Scribe | Learn More About Becoming a Scribe
label.checkbox(for="article_editor").well .contributor-signup(data-contributor-class-id="article_editor", data-contributor-class-name="scribe")
input(type='checkbox', name="article_editor", id="article_editor")
span(data-i18n="contribute.scribe_subscribe_desc")
| Get emails about article writing announcements.
.saved-notification
| ✓
span(data-i18n="contribute.saved") Saved
#diplomat.header-scrolling-fix #diplomat.header-scrolling-fix
@ -191,14 +156,8 @@ block content
p.lead(data-i18n="contribute.more_about_diplomat") p.lead(data-i18n="contribute.more_about_diplomat")
| Learn More About Becoming a Diplomat | Learn More About Becoming a Diplomat
label.checkbox(for="translator").well .contributor-signup(data-contributor-class-id="translator", data-contributor-class-name="diplomat")
input(type='checkbox', name="translator", id="translator")
span(data-i18n="contribute.diplomat_subscribe_desc")
| Get emails about i18n developments and levels to translate.
.saved-notification
| ✓
span(data-i18n="contribute.saved") Saved
#ambassador.header-scrolling-fix #ambassador.header-scrolling-fix
.class_image .class_image
@ -218,13 +177,7 @@ block content
p.lead(data-i18n="contribute.more_about_ambassador") p.lead(data-i18n="contribute.more_about_ambassador")
| Learn More About Becoming an Ambassador | Learn More About Becoming an Ambassador
label.checkbox(for="support").well .contributor-signup(data-contributor-class-id="support", data-contributor-class-name="ambassador")
input(type='checkbox', name="support", id="support")
span(data-i18n="contribute.ambassador_subscribe_desc")
| Get emails on support updates and multiplayer developments.
.saved-notification
| ✓
span(data-i18n="contribute.saved") Saved
#counselor.header-scrolling-fix #counselor.header-scrolling-fix

View file

@ -0,0 +1,13 @@
.row
for contributor in contributors
.col-xs-6.col-md-3
.thumbnail
- var src = "/images/pages/contribute/" + contributorClassName + ".png";
- if(contributor.avatar)
- src = src.replace(contributorClassName, contributorClassName + "/" + contributor.avatar + "_small");
- if(contributor.id)
- src = "/db/user/" + contributor.id + "/avatar?s=100&fallback=" + src;
a(href=contributor.github ? "https://github.com/codecombat/codecombat/commits?author=" + contributor.github : null, class=contributor.github ? 'has-github' : '')
img.img-responsive(src=src, alt=contributor.name)
.caption
h4= contributor.name

View file

@ -0,0 +1,5 @@
label.checkbox(for=contributorClassID).well
input(type='checkbox', name=contributorClassID, id=contributorClassID)
span(data-i18n="contribute.#{contributorClassName}_subscribe_desc")
.saved-notification ✓ Saved

View file

@ -0,0 +1,12 @@
if me.attributes.anonymous
div#sign-up.alert.alert-info
strong(data-i18n="contribute.alert_account_message_intro")
| Hey there!
span
span(data-i18n="contribute.alert_account_message_pref")
| To subscribe for class emails, you'll need to
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
| create an account
span
span(data-i18n="contribute.alert_account_message_suf")
| first.

View file

@ -44,51 +44,37 @@ block content
| , edit it online, and submit a pull request. Also, check this box below to | , edit it online, and submit a pull request. Also, check this box below to
| keep up-to-date on new internationalization developments! | keep up-to-date on new internationalization developments!
if me.attributes.anonymous .contributor-signup-anonymous
div#sign-up.alert.alert-info .contributor-signup(data-contributor-class-id="translator", data-contributor-class-name="diplomat")
strong(data-i18n="contribute.alert_account_message_intro")
| Hey there!
span
span(data-i18n="contribute.alert_account_message_pref")
| To subscribe for class emails, you'll need to
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
| create an account
span
span(data-i18n="contribute.alert_account_message_suf")
| first.
label.checkbox(for="translator").well h3(data-i18n="contribute.translating_diplomats")
input(type='checkbox', name="translator", id="translator") | Our Translating Diplomats:
span(data-i18n="contribute.diplomat_subscribe_desc")
| Get emails about i18n developments and levels to translate.
.saved-notification ✓ Saved
#Contributors //#contributor-list
h3(data-i18n="contribute.translating_diplomats") // TODO: collect CodeCombat userids for these guys so we can include a tiled list
| Our Translating Diplomats: ul.diplomats
ul.diplomats li Turkish - Nazım Gediz Aydındoğmuş, cobaimelan, wakeup
li Turkish - Nazım Gediz Aydındoğmuş, cobaimelan, wakeup li Brazilian Portuguese - Gutenberg Barros, Kieizroe, Matthew Burt, brunoporto, cassiocardoso
li Brazilian Portuguese - Gutenberg Barros, Kieizroe, Matthew Burt, brunoporto, cassiocardoso li Portugal Portuguese - Matthew Burt, ReiDuKuduro
li Portugal Portuguese - Matthew Burt, ReiDuKuduro li German - Dirk, faabsen, HiroP0, Anon, bkimminich
li German - Dirk, faabsen, HiroP0, Anon, bkimminich li Thai - Kamolchanok Jittrepit
li Thai - Kamolchanok Jittrepit li Vietnamese - An Nguyen Hoang Thien
li Vietnamese - An Nguyen Hoang Thien li Dutch - Glen De Cauwsemaecker, Guido Zuidhof, Ruben Vereecken, Jasper D'haene
li Dutch - Glen De Cauwsemaecker, Guido Zuidhof, Ruben Vereecken, Jasper D'haene li Greek - Stergios
li Greek - Stergios li Latin American Spanish - Jesús Ruppel, Matthew Burt, Mariano Luzza
li Latin American Spanish - Jesús Ruppel, Matthew Burt, Mariano Luzza li Spain Spanish - Matthew Burt, DanielRodriguezRivero, Anon, Pouyio
li Spain Spanish - Matthew Burt, DanielRodriguezRivero, Anon, Pouyio li French - Xeonarno, Elfisen, Armaldio, MartinDelille, pstweb, veritable, jaybi, xavismeh, Anon, Feugy
li French - Xeonarno, Elfisen, Armaldio, MartinDelille, pstweb, veritable, jaybi, xavismeh, Anon, Feugy li Hungarian - ferpeter, csuvsaregal, atlantisguru, Anon
li Hungarian - ferpeter, csuvsaregal, atlantisguru, Anon li Japanese - g1itch, kengos
li Japanese - g1itch, kengos li Chinese - Adam23, spacepope, yangxuan8282, Cheng Zheng
li Chinese - Adam23, spacepope, yangxuan8282, Cheng Zheng li Polish - Anon, Kacper Ciepielewski
li Polish - Anon, Kacper Ciepielewski li Danish - Einar Rasmussen, sorsjen, Randi Hillerøe, Anon
li Danish - Einar Rasmussen, sorsjen, Randi Hillerøe, Anon li Slovak - Anon
li Slovak - Anon li Persian - Reza Habibi (Rehb)
li Persian - Reza Habibi (Rehb) li Czech - vanous
li Czech - vanous li Russian - fess89, ser-storchak, Mr A
li Russian - fess89, ser-storchak, Mr A li Ukrainian - fess89
li Ukrainian - fess89 li Italian - flauta
li Italian - flauta li Norwegian - bardeh
li Norwegian - bardeh
div.clearfix div.clearfix

View file

@ -44,37 +44,12 @@ block content
| tell us a little about yourself, your experience with programming and | tell us a little about yourself, your experience with programming and
| what sort of things you'd like to write about. We'll go from there! | what sort of things you'd like to write about. We'll go from there!
if me.attributes.anonymous .contributor-signup-anonymous
div#sign-up.alert.alert-info .contributor-signup(data-contributor-class-id="article_editor", data-contributor-class-name="scribe")
strong(data-i18n="contribute.alert_account_message_intro")
| Hey there!
span
span(data-i18n="contribute.alert_account_message_pref")
| To subscribe for class emails, you'll need to
a(data-toggle="coco-modal", data-target="modal/signup", data-i18n="contribute.alert_account_message_create_url")
| create an account
span
span(data-i18n="contribute.alert_account_message_suf")
| first.
label.checkbox(for="article_editor").well h3(data-i18n="contribute.diligent_scribes")
input(type='checkbox', name="article_editor", id="article_editor") | Our Diligent Scribes:
span(data-i18n="contribute.scribe_subscribe_desc")
| Get emails about article writing announcements. #contributor-list(data-contributor-class-name="scribe")
.saved-notification ✓ Saved
#Contributors
h3(data-i18n="contribute.diligent_scribes")
| Our Diligent Scribes:
ul.scribes
li Ryan Faidley
li Glen De Cauwsemaecker
li Mischa Lewis-Norelle
li Tavio
li Ronnie Cheng
li engstrom
li Dman19993
li mattinsler
div.clearfix div.clearfix

View file

@ -14,12 +14,6 @@ module.exports = class JobProfileView extends CocoView
'updated' 'updated'
] ]
constructor: (options) ->
super options
unless me.schema().loaded
@addSomethingToLoad("user_schema")
@listenToOnce me, 'schema-loaded', => @somethingLoaded 'user_schema'
afterRender: -> afterRender: ->
super() super()
return if @loading() return if @loading()
@ -29,6 +23,7 @@ module.exports = class JobProfileView extends CocoView
visibleSettings = @editableSettings.concat @readOnlySettings visibleSettings = @editableSettings.concat @readOnlySettings
data = _.pick (me.get('jobProfile') ? {}), (value, key) => key in visibleSettings data = _.pick (me.get('jobProfile') ? {}), (value, key) => key in visibleSettings
data.name ?= (me.get('firstName') + ' ' + me.get('lastName')).trim() if me.get('firstName') data.name ?= (me.get('firstName') + ' ' + me.get('lastName')).trim() if me.get('firstName')
console.log 'schema?', me.schema()
schema = _.cloneDeep me.schema().properties.jobProfile schema = _.cloneDeep me.schema().properties.jobProfile
schema.properties = _.pick schema.properties, (value, key) => key in visibleSettings schema.properties = _.pick schema.properties, (value, key) => key in visibleSettings
schema.required = _.intersection schema.required, visibleSettings schema.required = _.intersection schema.required, visibleSettings

View file

@ -43,11 +43,7 @@ module.exports = class SettingsView extends View
@jobProfileView = new JobProfileView() @jobProfileView = new JobProfileView()
@listenTo @jobProfileView, 'change', @save @listenTo @jobProfileView, 'change', @save
@insertSubView @jobProfileView @insertSubView @jobProfileView
@buildPictureTreema()
if me.schema().loaded
@buildPictureTreema()
else
@listenToOnce me, 'schema-loaded', @buildPictureTreema
chooseTab: (category) -> chooseTab: (category) ->
id = "##{category}-pane" id = "##{category}-pane"
@ -85,6 +81,7 @@ module.exports = class SettingsView extends View
schema = _.cloneDeep me.schema() schema = _.cloneDeep me.schema()
schema.properties = _.pick me.schema().properties, 'photoURL' schema.properties = _.pick me.schema().properties, 'photoURL'
schema.required = ['photoURL'] schema.required = ['photoURL']
console.log 'have data', data, 'schema', schema
treemaOptions = treemaOptions =
filePath: "db/user/#{me.id}" filePath: "db/user/#{me.id}"
schema: schema schema: schema
@ -92,8 +89,8 @@ module.exports = class SettingsView extends View
callbacks: {change: @onPictureChanged} callbacks: {change: @onPictureChanged}
@pictureTreema = @$el.find('#picture-treema').treema treemaOptions @pictureTreema = @$el.find('#picture-treema').treema treemaOptions
@pictureTreema.build() @pictureTreema?.build()
@pictureTreema.open() @pictureTreema?.open()
@$el.find('.gravatar-fallback').toggle not me.get 'photoURL' @$el.find('.gravatar-fallback').toggle not me.get 'photoURL'
onPictureChanged: (e) => onPictureChanged: (e) =>

View file

@ -4,4 +4,5 @@ template = require 'templates/contribute/adventurer'
module.exports = class AdventurerView extends ContributeClassView module.exports = class AdventurerView extends ContributeClassView
id: "adventurer-view" id: "adventurer-view"
template: template template: template
contributorClassName: 'adventurer'

View file

@ -5,3 +5,4 @@ template = require 'templates/contribute/ambassador'
module.exports = class AmbassadorView extends ContributeClassView module.exports = class AmbassadorView extends ContributeClassView
id: "ambassador-view" id: "ambassador-view"
template: template template: template
contributorClassName: 'ambassador'

View file

@ -4,28 +4,30 @@ template = require 'templates/contribute/archmage'
module.exports = class ArchmageView extends ContributeClassView module.exports = class ArchmageView extends ContributeClassView
id: "archmage-view" id: "archmage-view"
template: template template: template
contributorClassName: 'archmage'
contributors: [ contributors: [
{name: "Tom Steinbrecher", avatar: "tom"} {id: "52bfc3ecb7ec628868001297", name: "Tom Steinbrecher", github: "TomSteinbrecher"}
{name: "Sébastien Moratinos", avatar: "sebastien"} {id: "5272806093680c5817033f73", name: "Sébastien Moratinos", github: "smoratinos"}
{name: "deepak1556", avatar: "deepak"} {name: "deepak1556", avatar: "deepak", github: "deepak1556"}
{name: "Ronnie Cheng", avatar: "ronald"} {name: "Ronnie Cheng", avatar: "ronald", github: "rhc2104"}
{name: "Chloe Fan", avatar: "chloe"} {name: "Chloe Fan", avatar: "chloe", github: "chloester"}
{name: "Rachel Xiang", avatar: "rachel"} {name: "Rachel Xiang", avatar: "rachel", github: "rdxiang"}
{name: "Dan Ristic", avatar: "dan"} {name: "Dan Ristic", avatar: "dan", github: "dristic"}
{name: "Brad Dickason", avatar: "brad"} {name: "Brad Dickason", avatar: "brad", github: "bdickason"}
{name: "Rebecca Saines", avatar: "becca"} {name: "Rebecca Saines", avatar: "becca"}
{name: "Laura Watiker", avatar: "laura"} {name: "Laura Watiker", avatar: "laura", github: "lwatiker"}
{name: "Shiying Zheng", avatar: "shiying"} {name: "Shiying Zheng", avatar: "shiying", github: "shiyingzheng"}
{name: "Mischa Lewis-Norelle", avatar: "mischa"} {name: "Mischa Lewis-Norelle", avatar: "mischa", github: "mlewisno"}
{name: "Paul Buser", avatar: "paul"} {name: "Paul Buser", avatar: "paul"}
{name: "Benjamin Stern", avatar: "ben"} {name: "Benjamin Stern", avatar: "ben"}
{name: "Alex Cotsarelis", avatar: "alex"} {name: "Alex Cotsarelis", avatar: "alex"}
{name: "Ken Stanley", avatar: "ken"} {name: "Ken Stanley", avatar: "ken"}
{name: "devast8a", avatar: ""} {name: "devast8a", avatar: "", github: "devast8a"}
{name: "phansch", avatar: ""} {name: "phansch", avatar: "", github: "phansch"}
{name: "Zach Martin", avatar: ""} {name: "Zach Martin", avatar: "", github: "zachster01"}
{name: "David Golds", avatar: ""} {name: "David Golds", avatar: ""}
{name: "gabceb", avatar: ""} {name: "gabceb", avatar: "", github: "gabceb"}
{name: "MDP66", avatar: ""} {name: "MDP66", avatar: "", github: "MDP66"}
{name: "Alexandru Caciulescu", avatar: "", github: "Darredevil"}
] ]

View file

@ -5,10 +5,11 @@ template = require 'templates/contribute/artisan'
module.exports = class ArtisanView extends ContributeClassView module.exports = class ArtisanView extends ContributeClassView
id: "artisan-view" id: "artisan-view"
template: template template: template
contributorClassName: 'artisan'
contributors: [ contributors: [
{name: "Sootn", avatar: ""} {name: "Sootn", avatar: ""}
{name: "Zach Martin", avatar: ""} {name: "Zach Martin", avatar: "", github: "zachster01"}
{name: "Aftermath", avatar: ""} {name: "Aftermath", avatar: ""}
{name: "mcdavid1991", avatar: ""} {name: "mcdavid1991", avatar: ""}
{name: "dwhittaker", avatar: ""} {name: "dwhittaker", avatar: ""}
@ -19,6 +20,6 @@ module.exports = class ArtisanView extends ContributeClassView
{name: "Axandre Oge", avatar: "axandre"} {name: "Axandre Oge", avatar: "axandre"}
{name: "Katharine Chan", avatar: "katharine"} {name: "Katharine Chan", avatar: "katharine"}
{name: "Derek Wong", avatar: "derek"} {name: "Derek Wong", avatar: "derek"}
{name: "Alexandru Caciulescu", avatar: ""} {name: "Alexandru Caciulescu", avatar: "", github: "Darredevil"}
{name: "Prabh Simran Singh Baweja", avatar: ""} {name: "Prabh Simran Singh Baweja", avatar: "", github: "prabh27"}
] ]

View file

@ -1,6 +1,9 @@
SignupModalView = require 'views/modal/signup_modal' SignupModalView = require 'views/modal/signup_modal'
View = require 'views/kinds/RootView' View = require 'views/kinds/RootView'
{me} = require('lib/auth') {me} = require('lib/auth')
contributorSignupAnonymousTemplate = require 'templates/contribute/contributor_signup_anonymous'
contributorSignupTemplate = require 'templates/contribute/contributor_signup'
contributorListTemplate = require 'templates/contribute/contributor_list'
module.exports = class ContributeClassView extends View module.exports = class ContributeClassView extends View
navPrefix: '/contribute' navPrefix: '/contribute'
@ -16,6 +19,12 @@ module.exports = class ContributeClassView extends View
afterRender: -> afterRender: ->
super() super()
@$el.find('.contributor-signup-anonymous').replaceWith(contributorSignupAnonymousTemplate(me: me))
@$el.find('.contributor-signup').each ->
context = me: me, contributorClassID: $(@).data('contributor-class-id'), contributorClassName: $(@).data('contributor-class-name')
$(@).replaceWith(contributorSignupTemplate(context))
@$el.find('#contributor-list').replaceWith(contributorListTemplate(contributors: @contributors, contributorClassName: @contributorClassName))
checkboxes = @$el.find('input[type="checkbox"]').toArray() checkboxes = @$el.find('input[type="checkbox"]').toArray()
_.forEach checkboxes, (el) -> _.forEach checkboxes, (el) ->
el = $(el) el = $(el)

View file

@ -5,3 +5,4 @@ template = require 'templates/contribute/counselor'
module.exports = class CounselorView extends ContributeClassView module.exports = class CounselorView extends ContributeClassView
id: "counselor-view" id: "counselor-view"
template: template template: template
contributorClassName: 'counselor'

View file

@ -5,3 +5,4 @@ template = require 'templates/contribute/diplomat'
module.exports = class DiplomatView extends ContributeClassView module.exports = class DiplomatView extends ContributeClassView
id: "diplomat-view" id: "diplomat-view"
template: template template: template
contributorClassName: 'diplomat'

View file

@ -5,3 +5,14 @@ template = require 'templates/contribute/scribe'
module.exports = class ScribeView extends ContributeClassView module.exports = class ScribeView extends ContributeClassView
id: "scribe-view" id: "scribe-view"
template: template template: template
contributorClassName: 'scribe'
contributors: [
{name: "Ryan Faidley"}
{name: "Mischa Lewis-Norelle", github: "mlewisno"}
{name: "Tavio"}
{name: "Ronnie Cheng", github: "rhc2104"}
{name: "engstrom"}
{name: "Dman19993"}
{name: "mattinsler"}
]

View file

@ -35,17 +35,11 @@ module.exports = class ArticleEditView extends View
) )
@article.fetch() @article.fetch()
@article.loadSchema() @listenToOnce(@article, 'sync', @buildTreema)
@listenToOnce(@article, 'sync', @onArticleSync)
@listenToOnce(@article, 'schema-loaded', @buildTreema)
@pushChangesToPreview = _.throttle(@pushChangesToPreview, 500) @pushChangesToPreview = _.throttle(@pushChangesToPreview, 500)
onArticleSync: ->
@article.loaded = true
@buildTreema()
buildTreema: -> buildTreema: ->
return if @treema? or (not @article.loaded) or (not Article.hasSchema()) return if @treema? or (not @article.loaded)
unless @article.attributes.body unless @article.attributes.body
@article.set('body', '') @article.set('body', '')
@startsLoading = false @startsLoading = false

View file

@ -20,9 +20,6 @@ module.exports = class ThangComponentEditView extends CocoView
render: => render: =>
return if @destroyed return if @destroyed
for model in [Level, LevelComponent]
temp = new model()
@listenToOnce temp, 'schema-loaded', @render unless model.schema?.loaded
if not @componentCollection if not @componentCollection
@componentCollection = @supermodel.getCollection new ComponentsCollection() @componentCollection = @supermodel.getCollection new ComponentsCollection()
unless @componentCollection.loaded unless @componentCollection.loaded
@ -32,7 +29,7 @@ module.exports = class ThangComponentEditView extends CocoView
afterRender: -> afterRender: ->
super() super()
return @showLoading() unless @componentCollection?.loaded and Level.schema.loaded and LevelComponent.schema.loaded return @showLoading() unless @componentCollection?.loaded
@hideLoading() @hideLoading()
@buildExtantComponentTreema() @buildExtantComponentTreema()
@buildAddComponentTreema() @buildAddComponentTreema()

View file

@ -61,12 +61,11 @@ module.exports = class ThangTypeEditView extends View
) )
@thangType.fetch() @thangType.fetch()
@thangType.loadSchema()
@listenToOnce(@thangType, 'sync', @onThangTypeSync) @listenToOnce(@thangType, 'sync', @onThangTypeSync)
@refreshAnimation = _.debounce @refreshAnimation, 500 @refreshAnimation = _.debounce @refreshAnimation, 500
onThangTypeSync: -> onThangTypeSync: ->
return unless @thangType.loaded and ThangType.hasSchema() return unless @thangType.loaded
@startsLoading = false @startsLoading = false
@files = new DocumentFiles(@thangType) @files = new DocumentFiles(@thangType)
@files.fetch() @files.fetch()

View file

@ -41,13 +41,13 @@ module.exports = class RootView extends CocoView
hash = location.hash hash = location.hash
location.hash = '' location.hash = ''
location.hash = hash location.hash = hash
@buildLanguages()
@renderScrollbar() @renderScrollbar()
#@$('.antiscroll-wrap').antiscroll() # not yet, buggy #@$('.antiscroll-wrap').antiscroll() # not yet, buggy
afterRender: -> afterRender: ->
super(arguments...) super(arguments...)
@chooseTab(location.hash.replace('#','')) if location.hash @chooseTab(location.hash.replace('#','')) if location.hash
@buildLanguages()
$('body').removeClass('is-playing') $('body').removeClass('is-playing')
chooseTab: (category) -> chooseTab: (category) ->
@ -58,7 +58,7 @@ module.exports = class RootView extends CocoView
buildLanguages: -> buildLanguages: ->
$select = @$el.find(".language-dropdown").empty() $select = @$el.find(".language-dropdown").empty()
if $select.hasClass("fancified") if $select.hasClass("fancified")
$select.parent().find('.options,.trigger').remove() $select.parent().find('.options, .trigger').remove()
$select.unwrap().removeClass("fancified") $select.unwrap().removeClass("fancified")
preferred = me.lang() preferred = me.lang()
codes = _.keys(locale) codes = _.keys(locale)
@ -76,10 +76,8 @@ module.exports = class RootView extends CocoView
$.i18n.setLng(newLang, {}) $.i18n.setLng(newLang, {})
@saveLanguage(newLang) @saveLanguage(newLang)
@render() @render()
@buildLanguages()
unless newLang.split('-')[0] is "en" unless newLang.split('-')[0] is "en"
@openModalView(application.router.getView("modal/diplomat_suggestion", "_modal")) @openModalView(application.router.getView("modal/diplomat_suggestion", "_modal"))
$('body').attr('lang', newLang)
saveLanguage: (newLang) -> saveLanguage: (newLang) ->
me.set('preferredLanguage', newLang) me.set('preferredLanguage', newLang)

View file

@ -227,4 +227,3 @@ module.exports = class PlayView extends View
super() super()
@$el.find('.modal').on 'shown.bs.modal', -> @$el.find('.modal').on 'shown.bs.modal', ->
$('input:visible:first', @).focus() $('input:visible:first', @).focus()

View file

@ -0,0 +1,10 @@
‹¨æ¥­§¨ï MIT (Œ’ˆ)
Copyright (c) 2014 CodeCombat Inc. ¨ ¤à㣨¥ ãç áâ­¨ª¨
„ ­­ ï «¨æ¥­§¨ï à §à¥è ¥â «¨æ ¬, ¯®«ã稢訬 ª®¯¨î ¤ ­­®£® ¯à®£à ¬¬­®£® ®¡¥á¯¥ç¥­¨ï ¨ ᮯãâáâ¢ãî饩 ¤®ªã¬¥­â æ¨¨ (¢ ¤ «ì­¥©è¥¬ ¨¬¥­ã¥¬ë¬¨ <<3C>ணࠬ¬­®¥ Ž¡¥á¯¥ç¥­¨¥>), ¡¥§¢®§¬¥§¤­® ¨á¯®«ì§®¢ âì <20>ணࠬ¬­®¥ Ž¡¥á¯¥ç¥­¨¥ ¡¥§ ®£à ­¨ç¥­¨©, ¢ª«îç ï ­¥®£à ­¨ç¥­­®¥ ¯à ¢® ­  ¨á¯®«ì§®¢ ­¨¥, ª®¯¨à®¢ ­¨¥, ¨§¬¥­¥­¨¥, ¤®¡ ¢«¥­¨¥, ¯ã¡«¨ª æ¨î, à á¯à®áâà ­¥­¨¥, áã¡«¨æ¥­§¨à®¢ ­¨¥ ¨/¨«¨ ¯à®¤ ¦ã ª®¯¨© <20>ணࠬ¬­®£® Ž¡¥á¯¥ç¥­¨ï, â ª¦¥ ª ª ¨ «¨æ ¬, ª®â®àë¬ ¯à¥¤®áâ ¢«ï¥âáï ¤ ­­®¥ <20>ணࠬ¬­®¥ Ž¡¥á¯¥ç¥­¨¥, ¯à¨ ᮡ«î¤¥­¨¨ á«¥¤ãîé¨å ãá«®¢¨©:
“ª § ­­®¥ ¢ëè¥ ã¢¥¤®¬«¥­¨¥ ®¡  ¢â®à᪮¬ ¯à ¢¥ ¨ ¤ ­­ë¥ ãá«®¢¨ï ¤®«¦­ë ¡ëâì ¢ª«îç¥­ë ¢® ¢á¥ ª®¯¨¨ ¨«¨ §­ ç¨¬ë¥ ç á⨠¤ ­­®£® <20>ணࠬ¬­®£® Ž¡¥á¯¥ç¥­¨ï.
„€<EFBFBD><EFBFBD>Ž… <20><>Žƒ<C5BD>€ŒŒ<C592>Ž… Ž<><E280A6>…—…<E28094>ˆ<20><>…„ŽŸ…Ÿ <ЀР…‘’œ>, <20>…‡ Š€Šˆ•-ˆ<E280B9>Ž ƒ€<C692><EFBFBD>ˆ‰, Ÿ<C5B8>Ž <E2809A>€†…<E280A0><E280A6>ˆˆ <20>Ž„<C5BD>€‡“Œ…€…Œ•, ‚Š‹ž—€Ÿ, <20>Ž <20>… Žƒ<C5BD><EFBFBD>ˆˆ€Ÿœ ƒ€<C692><EFBFBD>ˆŸŒˆ Ž<E2809A><E282AC>މ <20><>ˆƒŽ„<C5BD>Žˆ, ‘ŽŽ’‚…’‘’‚ˆŸ <20>Ž …ƒŽ ŠŽ<C5A0>Š<EFBFBD><E280A6>ŽŒ“ <20>€‡<E282AC>€—…<E28094>ˆž ˆ Ž’‘“’‘’‚ˆŸ <20><EFBFBD>˜<CB9C>ˆ<20><>. <20>ˆ Š€ŠŽŒ ‘‹“—€… €Ž<E28099> ˆˆ <20><>ŽŽ<C5BD>€„€ˆ <20><20> Ž<E2809A><E280A6>Žˆ <20>Ž ˆ‘Š€Œ Ž Ž‡Œ…™…<E284A2>ˆˆ “™…<E284A2><E280A6>€, “<>ŠŽ ˆˆ<>“ƒˆ<><EFBFBD>Ž<E2809A>ˆ<20>Ž „…‰‘’‚“ž™ˆŒ ŠŽ<C5A0><EFBFBD>€Š€Œ, „…‹ˆŠ’€Œ ˆˆ ˆ<>ŽŒ“, އ<C5BD>ˆŠ˜ˆŒ ˆ‡, ˆŒ…ž™ˆŒ <20><>ˆˆ<E28094>މ ˆˆ Ÿ‡€<E280A1><E282AC>Œ <20><>Žƒ<C5BD>€ŒŒ<C592>Œ Ž<><E280A6>…—…<E28094>ˆ…Œ ˆˆ ˆ<CB86>Žœ‡Ž<E2809A>ˆ…Œ <20><>Žƒ<C5BD>€ŒŒ<C592>ŽƒŽ Ž<><E280A6>…—…<E28094>ˆŸ ˆˆ ˆ<>Œˆ „…‰‘’‚ˆŸŒˆ <20><>Žƒ<C5BD>€ŒŒ<C592>Œ Ž<><E280A6>…—…<E28094>ˆ…Œ.

View file

@ -0,0 +1,29 @@
_____ _ _____ _ _
/ __ \ | | / __ \ | | | |
| / \/ ___ __| | ___ | / \/ ___ _ __ ___ | |__ __ _| |_
| | / _ \ / _` |/ _ \ | | / _ \| '_ ` _ \| '_ \ / _` | __|
| \__/\ (_) | (_| | __/ | \__/\ (_) | | | | | | |_) | (_| | |_
\____/\___/ \__,_|\___| \____/\___/|_| |_| |_|_.__/ \__,_|\__|
=============================================================================
<EFBFBD>®§¤à ¢«ï¥¬, ⥯¥àì ¢ë ç áâì á®®¡é¥á⢠ CodeCombat.
’¥¯¥àì, ª®£¤  ¢ è  á।  à §à ¡®â稪  ãáâ ­®¢«¥­ , ¢ë £®â®¢ë ­ ç âì
¢­®á¨âì ¢ª« ¤ ¨ ¯®¬®çì ­ ¬ ᤥ« âì íâ®â ¬¨à «ãçè¥.
“ ¢ á ¥áâì ¢®¯à®áë ¨«¨ ¢ë å®â¥«¨ ¡ë á ­ ¬¨ ¢áâà¥â¨âìáï?
<EFBFBD>®£®¢®à¨â¥ á ­ ¬¨ ¢ hipchat @ https://www.hipchat.com/g3plnOKqa
…é¥ ®¤¨­ ᯮᮡ ¤®á⨦¥­¨ï í⮣® - ¯®á¥é¥­¨¥ ­ è¥£® ä®à㬠.
‚ë ¬®¦¥â¥ ­ ©â¨ ¥£® @ http://discourse.codecombat.com/
‚ë ¬®¦¥â¥ ¯à®ç¨â âì ® ¯®á«¥¤­¨å ¤®á⨦¥­¨ïå ¢ ­ è¥¬ ¡«®£¥.
…£® ¬®¦­® ­ ©â¨ @ http://blog.codecombat.com/
ˆ ¯®á«¥¤­¥¥, ­® ­¥ ¯® §­ ç¥­¨î, - ¢ë ¬®¦¥â¥ ­ ©â¨ ¡®«ìèãî ç áâì ¤®ªã¬¥­â æ¨¨
¨ ¨­ä®à¬ æ¨¨ ¢ ­ è¥© ¢¨ª¨ @ https://github.com/codecombat/codecombat/wiki
Œë ­ ¤¥¥¬áï, çâ® ¢ë ¡ã¤¥â¥ ­ á« ¦¤ âìáï ¢ ­ è¥¬ á®®¡é¥á⢥ â ª ¦¥, ª ª ¨ ¬ë.
- <20>¨ª, „¦®à¤¦, ‘ª®ââ, Œ¨å í«ì, „¦¥à¥¬¨ ¨ ƒ«¥­

View file

@ -0,0 +1,7 @@
1) Š®£¤  § ¤ ñâáï ¢®¯à®á, ¯®¦ «ã©áâ , ®â¢¥ç ©â¥ ¢­¨¬ â¥«ì­® ¨ ¯à ¢¨«ì­®
2) „ ­­ë© ãáâ ­®¢é¨ª ­ å®¤¨âáï ¢ áâ ¤¨¨ ¡¥âë ¨ ¬®¦¥â ᮤ¥à¦ âì ¡ £¨
3) ‚ë ¬®¦¥â¥ á®®¡é âì ® ¡ £ å @ 'https://github.com/codecombat/codecombat/issues'
4) …áâì ¢®¯à®áë/¯à¥¤«®¦¥­¨ï? <20>®£®¢®à¨â¥ á ­ ¬¨ ¢ HipChat ç¥à¥§ CodeCombat.com
‚ë ¬®¦¥â¥ ­ ©â¨ ¯®è £®¢®¥ à㪮¢®¤á⢮ ¤«ï ¤ ­­®£® ãáâ ­®¢é¨ª  ¢ ­ è¥© ¢¨ª¨.
github.com/codecombat/codecombat/wiki/Setup-on-Windows:-a-step-by-step-guide

View file

@ -3,19 +3,19 @@
<global> <global>
<native>русский</native> <native>русский</native>
<description>Russian</description> <description>Russian</description>
<tips>Before we start the installation, here are some tips:</tips> <tips>Перед тем, как мы начнём установку, вот несколько советов:</tips>
<exit>Press any key to exit...</exit> <exit>Нажмите Enter для выхода...</exit>
</global> </global>
<language> <language>
<choosen>You have choosen ðóññêèé as your language.</choosen> <choosen>Вы выбрали русский в качестве вашего языка.</choosen>
<feedback>C данного момента мы будем общаться на русском.</feedback> <feedback>C данного момента мы будем общаться на русском.</feedback>
</language> </language>
<license> <license>
<s1>In order to continue the installation of the developers environment</s1> <s1>Для того, чтобы продолжить установку среды разработчика</s1>
<s2>you will have to read and agree with the following license:</s2> <s2>вы должны прочитать и согласиться со следующей лицензией:</s2>
<q1>Have you read the license and do you agree with it?</q1> <q1>Вы прочитали лицензию и согласны с ней?</q1>
<a1>This setup can't happen without an agreement.</a1> <a1>Данная установка не начнётся без согласия.</a1>
<a2>Installation and Setup of the CodeCombat environment is cancelled.</a2> <a2>Установка и настройка среды CodeCombat отменена.</a2>
</license> </license>
<install> <install>
<system> <system>
@ -38,7 +38,7 @@
<downloading>загружается...</downloading> <downloading>загружается...</downloading>
<installing>устанавливается...</installing> <installing>устанавливается...</installing>
<unzipping>распаковывается...</unzipping> <unzipping>распаковывается...</unzipping>
<cleaning>óáèðàåòñÿ...</cleaning> <cleaning>прибирается...</cleaning>
<mongodbpath>Пожалуйста, определите полный путь, куда должен быть установлен MongoDB</mongodbpath> <mongodbpath>Пожалуйста, определите полный путь, куда должен быть установлен MongoDB</mongodbpath>
</process> </process>
</install> </install>
@ -53,7 +53,7 @@
<question>Вы хотите провести установку Local Git вручную самостоятельно?</question> <question>Вы хотите провести установку Local Git вручную самостоятельно?</question>
<consequence>Убедитесь, что вы правильно настроили репозиторий перед выполнением.</consequence> <consequence>Убедитесь, что вы правильно настроили репозиторий перед выполнением.</consequence>
<donotclose>Не закрывайте это окно, пожалуйста.</donotclose> <donotclose>Не закрывайте это окно, пожалуйста.</donotclose>
<wait>Êîãäà âû áóäåòå ãîòîâû, íàæìèòå ëþáóþ êëàâèøó äëÿ ïðîäîëæåíèÿ...</wait> <wait>Когда вы будете готовы, нажмите Enter для продолжения...</wait>
</skip> </skip>
<process> <process>
<path>Пожалуйста, укажите полный путь до вашего CodeCombat репозитория git: </path> <path>Пожалуйста, укажите полный путь до вашего CodeCombat репозитория git: </path>

View file

@ -4,7 +4,7 @@ Handler = require('../commons/Handler')
ArticleHandler = class ArticleHandler extends Handler ArticleHandler = class ArticleHandler extends Handler
modelClass: Article modelClass: Article
editableProperties: ['body', 'name', 'i18n'] editableProperties: ['body', 'name', 'i18n']
jsonSchema: require './article_schema' jsonSchema: require '../../app/schemas/models/article'
hasAccess: (req) -> hasAccess: (req) ->
req.method is 'GET' or req.user?.isAdmin() req.method is 'GET' or req.user?.isAdmin()

View file

@ -10,21 +10,6 @@ module.exports.handlers =
'thang_type': 'levels/thangs/thang_type_handler' 'thang_type': 'levels/thangs/thang_type_handler'
'user': 'users/user_handler' 'user': 'users/user_handler'
module.exports.schemas =
'article': 'articles/article_schema'
'common': 'commons/schemas'
'i18n': 'commons/i18n_schema'
'level': 'levels/level_schema'
'level_component': 'levels/components/level_component_schema'
'level_feedback': 'levels/feedbacks/level_feedback_schema'
'level_session': 'levels/sessions/level_session_schema'
'level_system': 'levels/systems/level_system_schema'
'metaschema': 'commons/metaschema'
'patch': 'patches/patch_schema'
'thang_component': 'levels/thangs/thang_component_schema'
'thang_type': 'levels/thangs/thang_type_schema'
'user': 'users/user_schema'
module.exports.routes = module.exports.routes =
[ [
'routes/auth' 'routes/auth'

View file

@ -1,6 +1,6 @@
mongoose = require('mongoose') mongoose = require('mongoose')
plugins = require('../plugins/plugins') plugins = require('../plugins/plugins')
jsonschema = require('../../app/schemas/level_schema') jsonschema = require('../../app/schemas/models/level')
LevelSchema = new mongoose.Schema({ LevelSchema = new mongoose.Schema({
description: String description: String

View file

@ -1,6 +1,6 @@
mongoose = require('mongoose') mongoose = require('mongoose')
plugins = require('../../plugins/plugins') plugins = require('../../plugins/plugins')
jsonschema = require('../../../app/schemas/level_component_schema') jsonschema = require('../../../app/schemas/models/level_component')
LevelComponentSchema = new mongoose.Schema { LevelComponentSchema = new mongoose.Schema {
description: String description: String

View file

@ -3,7 +3,7 @@ Handler = require('../../commons/Handler')
LevelComponentHandler = class LevelComponentHandler extends Handler LevelComponentHandler = class LevelComponentHandler extends Handler
modelClass: LevelComponent modelClass: LevelComponent
jsonSchema: require '../../../app/schemas/level_component_schema' jsonSchema: require '../../../app/schemas/models/level_component'
editableProperties: [ editableProperties: [
'system' 'system'
'description' 'description'

View file

@ -2,7 +2,7 @@
mongoose = require('mongoose') mongoose = require('mongoose')
plugins = require('../../plugins/plugins') plugins = require('../../plugins/plugins')
jsonschema = require('../../../app/schemas/level_feedback_schema') jsonschema = require('../../../app/schemas/models/level_feedback')
LevelFeedbackSchema = new mongoose.Schema({ LevelFeedbackSchema = new mongoose.Schema({
created: created:

View file

@ -4,7 +4,7 @@ Handler = require('../../commons/Handler')
class LevelFeedbackHandler extends Handler class LevelFeedbackHandler extends Handler
modelClass: LevelFeedback modelClass: LevelFeedback
editableProperties: ['rating', 'review', 'level', 'levelID', 'levelName'] editableProperties: ['rating', 'review', 'level', 'levelID', 'levelName']
jsonSchema: require '../../../app/schemas/level_feedback_schema' jsonSchema: require '../../../app/schemas/models/level_feedback'
makeNewInstance: (req) -> makeNewInstance: (req) ->
feedback = super(req) feedback = super(req)

View file

@ -8,7 +8,7 @@ mongoose = require('mongoose')
LevelHandler = class LevelHandler extends Handler LevelHandler = class LevelHandler extends Handler
modelClass: Level modelClass: Level
jsonSchema: require '../../app/schemas/level_schema' jsonSchema: require '../../app/schemas/models/level'
editableProperties: [ editableProperties: [
'description' 'description'
'documentation' 'documentation'

View file

@ -2,7 +2,7 @@
mongoose = require('mongoose') mongoose = require('mongoose')
plugins = require('../../plugins/plugins') plugins = require('../../plugins/plugins')
jsonschema = require('../../../app/schemas/level_session_schema') jsonschema = require('../../../app/schemas/models/level_session')
LevelSessionSchema = new mongoose.Schema({ LevelSessionSchema = new mongoose.Schema({
created: created:

View file

@ -9,7 +9,7 @@ class LevelSessionHandler extends Handler
editableProperties: ['multiplayer', 'players', 'code', 'completed', 'state', editableProperties: ['multiplayer', 'players', 'code', 'completed', 'state',
'levelName', 'creatorName', 'levelID', 'screenshot', 'levelName', 'creatorName', 'levelID', 'screenshot',
'chat', 'teamSpells', 'submitted', 'unsubscribed'] 'chat', 'teamSpells', 'submitted', 'unsubscribed']
jsonSchema: require '../../../app/schemas/level_session_schema' jsonSchema: require '../../../app/schemas/models/level_session'
getByRelationship: (req, res, args...) -> getByRelationship: (req, res, args...) ->
return @getActiveSessions req, res if args.length is 2 and args[1] is 'active' return @getActiveSessions req, res if args.length is 2 and args[1] is 'active'

View file

@ -1,6 +1,6 @@
mongoose = require('mongoose') mongoose = require('mongoose')
plugins = require('../../plugins/plugins') plugins = require('../../plugins/plugins')
jsonschema = require('../../../app/schemas/level_system_schema') jsonschema = require('../../../app/schemas/models/level_system')
LevelSystemSchema = new mongoose.Schema { LevelSystemSchema = new mongoose.Schema {
description: String description: String

View file

@ -13,7 +13,7 @@ LevelSystemHandler = class LevelSystemHandler extends Handler
'configSchema' 'configSchema'
] ]
postEditableProperties: ['name'] postEditableProperties: ['name']
jsonSchema: require '../../../app/schemas/level_system_schema' jsonSchema: require '../../../app/schemas/models/level_system'
getEditableProperties: (req, document) -> getEditableProperties: (req, document) ->
props = super(req, document) props = super(req, document)

View file

@ -3,7 +3,7 @@ Handler = require('../../commons/Handler')
ThangTypeHandler = class ThangTypeHandler extends Handler ThangTypeHandler = class ThangTypeHandler extends Handler
modelClass: ThangType modelClass: ThangType
jsonSchema: require '../../../app/schemas/thang_type_schema' jsonSchema: require '../../../app/schemas/models/thang_type'
editableProperties: [ editableProperties: [
'name', 'name',
'raw', 'raw',

View file

@ -1,6 +1,6 @@
Patch = require('./Patch') Patch = require('./Patch')
Handler = require('../commons/Handler') Handler = require('../commons/Handler')
schema = require '../../app/schemas/patch_schema' schema = require '../../app/schemas/models/patch'
{handlers} = require '../commons/mapping' {handlers} = require '../commons/mapping'
mongoose = require('mongoose') mongoose = require('mongoose')
@ -8,7 +8,7 @@ PatchHandler = class PatchHandler extends Handler
modelClass: Patch modelClass: Patch
editableProperties: [] editableProperties: []
postEditableProperties: ['delta', 'target', 'commitMessage'] postEditableProperties: ['delta', 'target', 'commitMessage']
jsonSchema: require '../../app/schemas/patch_schema' jsonSchema: require '../../app/schemas/models/patch'
makeNewInstance: (req) -> makeNewInstance: (req) ->
patch = super(req) patch = super(req)

View file

@ -1,7 +1,6 @@
log = require 'winston' log = require 'winston'
errors = require '../commons/errors' errors = require '../commons/errors'
handlers = require('../commons/mapping').handlers handlers = require('../commons/mapping').handlers
schemas = require('../commons/mapping').schemas
mongoose = require 'mongoose' mongoose = require 'mongoose'
module.exports.setup = (app) -> module.exports.setup = (app) ->
@ -48,7 +47,7 @@ module.exports.setup = (app) ->
getSchema = (req, res, moduleName) -> getSchema = (req, res, moduleName) ->
try try
name = moduleName.replace '.', '_' name = moduleName.replace '.', '_'
schema = require('../../app/schemas/' + name + '_schema') schema = require('../../app/schemas/models/' + name)
res.send(JSON.stringify(schema, null, '\t')) res.send(JSON.stringify(schema, null, '\t'))
res.end() res.end()

View file

@ -19,7 +19,7 @@ fileGet = (req, res) ->
objectId = mongoose.Types.ObjectId(path) objectId = mongoose.Types.ObjectId(path)
query = objectId query = objectId
catch e catch e
path = path.split('/') path = path.split('/')
filename = path[path.length-1] filename = path[path.length-1]
path = path[...path.length-1].join('/') path = path[...path.length-1].join('/')
query = query =
@ -34,7 +34,7 @@ fileGet = (req, res) ->
res.setHeader('Content-Type', 'text/json') res.setHeader('Content-Type', 'text/json')
res.send(results) res.send(results)
res.end() res.end()
else else
Grid.gfs.collection('media').findOne query, (err, filedata) => Grid.gfs.collection('media').findOne query, (err, filedata) =>
return errors.notFound(res) if not filedata return errors.notFound(res) if not filedata
@ -42,7 +42,7 @@ fileGet = (req, res) ->
if req.headers['if-modified-since'] is filedata.uploadDate if req.headers['if-modified-since'] is filedata.uploadDate
res.status(304) res.status(304)
return res.end() return res.end()
res.setHeader('Content-Type', filedata.contentType) res.setHeader('Content-Type', filedata.contentType)
res.setHeader('Last-Modified', filedata.uploadDate) res.setHeader('Last-Modified', filedata.uploadDate)
res.setHeader('Cache-Control', 'public') res.setHeader('Cache-Control', 'public')
@ -70,7 +70,7 @@ postFileSchema =
required: ['filename', 'mimetype', 'path'] required: ['filename', 'mimetype', 'path']
filePost = (req, res) -> filePost = (req, res) ->
return errors.forbidden(res) unless req.user?.isAdmin() return errors.forbidden(res) unless req.user
options = req.body options = req.body
tv4 = require('tv4').tv4 tv4 = require('tv4').tv4
valid = tv4.validate(options, postFileSchema) valid = tv4.validate(options, postFileSchema)
@ -83,7 +83,8 @@ filePost = (req, res) ->
saveURL = (req, res) -> saveURL = (req, res) ->
options = createPostOptions(req) options = createPostOptions(req)
checkExistence options, res, req.body.force, (err) -> force = req.user.isAdmin() and req.body.force
checkExistence options, res, force, (err) ->
return errors.serverError(res) if err return errors.serverError(res) if err
writestream = Grid.gfs.createWriteStream(options) writestream = Grid.gfs.createWriteStream(options)
request(req.body.url).pipe(writestream) request(req.body.url).pipe(writestream)
@ -91,7 +92,8 @@ saveURL = (req, res) ->
saveFile = (req, res) -> saveFile = (req, res) ->
options = createPostOptions(req) options = createPostOptions(req)
checkExistence options, res, req.body.force, (err) -> force = req.user.isAdmin() and req.body.force
checkExistence options, res, force, (err) ->
return if err return if err
writestream = Grid.gfs.createWriteStream(options) writestream = Grid.gfs.createWriteStream(options)
f = req.files[req.body.postName] f = req.files[req.body.postName]
@ -101,7 +103,8 @@ saveFile = (req, res) ->
savePNG = (req, res) -> savePNG = (req, res) ->
options = createPostOptions(req) options = createPostOptions(req)
checkExistence options, res, req.body.force, (err) -> force = req.user.isAdmin() and req.body.force
checkExistence options, res, force, (err) ->
return errors.serverError(res) if err return errors.serverError(res) if err
writestream = Grid.gfs.createWriteStream(options) writestream = Grid.gfs.createWriteStream(options)
img = new Buffer(req.body.b64png, 'base64') img = new Buffer(req.body.b64png, 'base64')
@ -143,11 +146,11 @@ createPostOptions = (req) ->
unless req.body.name unless req.body.name
name = req.body.filename.split('.')[0] name = req.body.filename.split('.')[0]
req.body.name = _.str.humanize(name) req.body.name = _.str.humanize(name)
path = req.body.path or '' path = req.body.path or ''
path = path[1...] if path and path[0] is '/' path = path[1...] if path and path[0] is '/'
path = path[...path.length-2] if path and path[path.length-1] is '/' path = path[...path.length-2] if path and path[path.length-1] is '/'
options = options =
mode: 'w' mode: 'w'
filename: req.body.filename filename: req.body.filename
@ -158,6 +161,6 @@ createPostOptions = (req) ->
name: req.body.name name: req.body.name
path: path path: path
creator: ''+req.user._id creator: ''+req.user._id
options.metadata.description = req.body.description if req.body.description? options.metadata.description = req.body.description if req.body.description?
options options

View file

@ -1,5 +1,5 @@
mongoose = require('mongoose') mongoose = require('mongoose')
jsonschema = require('../../app/schemas/user_schema') jsonschema = require('../../app/schemas/models/user')
crypto = require('crypto') crypto = require('crypto')
{salt, isProduction} = require('../../server_config') {salt, isProduction} = require('../../server_config')
mail = require '../commons/mail' mail = require '../commons/mail'

View file

@ -1,4 +1,4 @@
schema = require '../../app/schemas/user_schema' schema = require '../../app/schemas/models/user'
crypto = require 'crypto' crypto = require 'crypto'
request = require 'request' request = require 'request'
User = require './User' User = require './User'
@ -198,7 +198,10 @@ UserHandler = class UserHandler extends Handler
@modelClass.findById(id).exec (err, document) => @modelClass.findById(id).exec (err, document) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
photoURL = document?.get('photoURL') photoURL = document?.get('photoURL')
photoURL ||= @buildGravatarURL document if photoURL
photoURL = "/file/#{photoURL}"
else
photoURL = @buildGravatarURL document, req.query.s, req.query.fallback
res.redirect photoURL res.redirect photoURL
res.end() res.end()
@ -239,10 +242,11 @@ UserHandler = class UserHandler extends Handler
obj.jobProfile = _.pick obj.jobProfile, subfields obj.jobProfile = _.pick obj.jobProfile, subfields
obj obj
buildGravatarURL: (user) -> buildGravatarURL: (user, size, fallback) ->
emailHash = @buildEmailHash user emailHash = @buildEmailHash user
defaultAvatar = "http://codecombat.com/file/db/thang.type/52a00d55cf1818f2be00000b/portrait.png" fallback ?= "http://codecombat.com/file/db/thang.type/52a00d55cf1818f2be00000b/portrait.png"
"https://www.gravatar.com/avatar/#{emailHash}?default=#{defaultAvatar}" fallback = "http://codecombat.com#{fallback}" unless /^http/.test fallback
"https://www.gravatar.com/avatar/#{emailHash}?s=#{size}&default=#{fallback}"
buildEmailHash: (user) -> buildEmailHash: (user) ->
# emailHash is used by gravatar # emailHash is used by gravatar