diff --git a/app/application.coffee b/app/application.coffee index f44287599..be9db6a97 100644 --- a/app/application.coffee +++ b/app/application.coffee @@ -5,6 +5,8 @@ locale = require 'locale/locale' Tracker = require 'lib/Tracker' CocoView = require 'views/kinds/CocoView' +marked.setOptions {gfm: true, sanitize: true, smartLists: true, breaks: false} + # Prevent Ctrl/Cmd + [ / ], P, S ctrlDefaultPrevented = [219, 221, 80, 83] preventBackspace = (event) -> diff --git a/app/assets/javascripts/workers/aether_worker.js b/app/assets/javascripts/workers/aether_worker.js new file mode 100644 index 000000000..9fbad8155 --- /dev/null +++ b/app/assets/javascripts/workers/aether_worker.js @@ -0,0 +1,99 @@ +var window = self; +var Global = self; + +importScripts("/javascripts/tome_aether.js"); +console.log("imported scripts!"); +var aethers = {}; + +var createAether = function (spellKey, options) +{ + aethers[spellKey] = new Aether(options); + return JSON.stringify({ + "message": "Created aether for " + spellKey, + "function": "createAether" + }); +}; + +var hasChangedSignificantly = function(spellKey, a,b,careAboutLineNumbers,careAboutLint) { + + var hasChanged = aethers[spellKey].hasChangedSignificantly(a,b,careAboutLineNumbers,careAboutLint); + var functionName = "hasChangedSignificantly"; + var returnObject = { + "function":functionName, + "hasChanged": hasChanged, + "spellKey": spellKey + }; + return JSON.stringify(returnObject); +}; + +var updateLanguageAether = function(newLanguage) +{ + for (var spellKey in aethers) + { + if (aethers.hasOwnProperty(spellKey)) + { + aethers[spellKey].setLanguage(newLanguage); + } + + } +}; + +var lint = function(spellKey, source) +{ + var currentAether = aethers[spellKey]; + var lintMessages = currentAether.lint(source); + var functionName = "lint"; + var returnObject = { + "lintMessages": lintMessages, + "function": functionName + }; + return JSON.stringify(returnObject); +}; + +var transpile = function(spellKey, source) +{ + var currentAether = aethers[spellKey]; + currentAether.transpile(source); + var functionName = "transpile"; + var returnObject = { + "problems": currentAether.problems, + "function": functionName, + "spellKey": spellKey + }; + return JSON.stringify(returnObject); +}; +self.addEventListener('message', function(e) { + var data = JSON.parse(e.data); + if (data.function == "createAether") + { + self.postMessage(createAether(data.spellKey, data.options)); + } + else if (data.function == "updateLanguageAether") + { + updateLanguageAether(data.newLanguage) + } + else if (data.function == "hasChangedSignificantly") + { + self.postMessage(hasChangedSignificantly( + data.spellKey, + data.a, + data.b, + data.careAboutLineNumbers, + data.careAboutLint + )); + } + else if (data.function == "lint") + { + self.postMessage(lint(data.spellKey, data.source)); + } + else if (data.function == "transpile") + { + self.postMessage(transpile(data.spellKey, data.source)); + } + else + { + var message = "Didn't execute any function..."; + var returnObject = {"message":message, "function":"none"}; + self.postMessage(JSON.stringify(returnObject)); + } +}, false); \ No newline at end of file diff --git a/app/models/CocoCollection.coffee b/app/collections/CocoCollection.coffee similarity index 100% rename from app/models/CocoCollection.coffee rename to app/collections/CocoCollection.coffee diff --git a/app/collections/ComponentsCollection.coffee b/app/collections/ComponentsCollection.coffee index 14db7a2b6..1f930576b 100644 --- a/app/collections/ComponentsCollection.coffee +++ b/app/collections/ComponentsCollection.coffee @@ -1,5 +1,5 @@ LevelComponent = require 'models/LevelComponent' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' module.exports = class ComponentsCollection extends CocoCollection url: '/db/level.component/search' diff --git a/app/collections/DocumentFiles.coffee b/app/collections/DocumentFiles.coffee index d78c41bd9..b4cf40ea1 100644 --- a/app/collections/DocumentFiles.coffee +++ b/app/collections/DocumentFiles.coffee @@ -1,4 +1,4 @@ -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' module.exports = class ModelFiles extends CocoCollection constructor: (model) -> diff --git a/app/collections/LeaderboardCollection.coffee b/app/collections/LeaderboardCollection.coffee index d00f16d1b..207ef6742 100644 --- a/app/collections/LeaderboardCollection.coffee +++ b/app/collections/LeaderboardCollection.coffee @@ -1,4 +1,4 @@ -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' LevelSession = require 'models/LevelSession' module.exports = class LeaderboardCollection extends CocoCollection diff --git a/app/collections/PatchesCollection.coffee b/app/collections/PatchesCollection.coffee index 456db1e42..f3f1a6d8e 100644 --- a/app/collections/PatchesCollection.coffee +++ b/app/collections/PatchesCollection.coffee @@ -1,5 +1,5 @@ PatchModel = require 'models/Patch' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' module.exports = class PatchesCollection extends CocoCollection model: PatchModel diff --git a/app/collections/SimulatorsLeaderboardCollection.coffee b/app/collections/SimulatorsLeaderboardCollection.coffee index 733017cf4..341b3ef03 100644 --- a/app/collections/SimulatorsLeaderboardCollection.coffee +++ b/app/collections/SimulatorsLeaderboardCollection.coffee @@ -1,4 +1,4 @@ -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' User = require 'models/User' module.exports = class SimulatorsLeaderboardCollection extends CocoCollection diff --git a/app/lib/NameLoader.coffee b/app/lib/NameLoader.coffee index 6e51d21af..ce3fe5520 100644 --- a/app/lib/NameLoader.coffee +++ b/app/lib/NameLoader.coffee @@ -18,6 +18,6 @@ class NameLoader extends CocoClass loadedNames: (newNames) => _.extend namesCache, newNames - getName: (id) -> namesCache[id] + getName: (id) -> namesCache[id].name module.exports = new NameLoader() diff --git a/app/lib/SystemNameLoader.coffee b/app/lib/SystemNameLoader.coffee new file mode 100644 index 000000000..f23dbe491 --- /dev/null +++ b/app/lib/SystemNameLoader.coffee @@ -0,0 +1,10 @@ +CocoClass = require 'lib/CocoClass' + +namesCache = {} + +class SystemNameLoader extends CocoClass + getName: (id) -> namesCache[id]?.name + + setName: (system) -> namesCache[system.get('original')] = {name:system.get('name')} + +module.exports = new SystemNameLoader() diff --git a/app/lib/deltas.coffee b/app/lib/deltas.coffee index 9629139e8..e817551d1 100644 --- a/app/lib/deltas.coffee +++ b/app/lib/deltas.coffee @@ -1,3 +1,4 @@ +SystemNameLoader = require 'lib/SystemNameLoader' ### Good-to-knows: dataPath: an array of keys that walks you up a JSON object that's being patched @@ -67,13 +68,13 @@ expandFlattenedDelta = (delta, left, schema) -> parentLeft = left parentSchema = schema for key, i in delta.dataPath - # TODO: A more comprehensive way of getting child schemas + # TODO: Better schema/json walking childSchema = parentSchema?.items or parentSchema?.properties?[key] or {} childLeft = parentLeft?[key] humanKey = null childData = if i is delta.dataPath.length-1 and delta.action is 'added' then o[0] else childLeft humanKey ?= childData.name or childData.id if childData - humanKey ?= "#{childSchema.title} ##{key+1}" if childSchema.title and _.isNumber(key) + humanKey ?= SystemNameLoader.getName(childData?.original) humanKey ?= "#{childSchema.title}" if childSchema.title humanKey ?= _.string.titleize key humanPath.push humanKey @@ -155,4 +156,4 @@ prunePath = (delta, path) -> else prunePath delta[path[0]], path.slice(1) keys = (k for k in _.keys(delta[path[0]]) when k isnt '_t') - delete delta[path[0]] if keys.length is 0 \ No newline at end of file + delete delta[path[0]] if keys.length is 0 diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee index f09410e12..80b30ec09 100644 --- a/app/lib/surface/CocoSprite.coffee +++ b/app/lib/surface/CocoSprite.coffee @@ -323,7 +323,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass if not action and @thang?.actionActivated and not @stopLogging console.error "action is", action, "for", @thang?.id, "from", @currentRootAction, @thang.action, @thang.getActionName?() @stopLogging = true - @queueAction(action) if isDifferent or (@thang?.actionActivated and action.name isnt 'move') + @queueAction(action) if action and (isDifferent or (@thang?.actionActivated and action.name isnt 'move')) @updateActionDirection() determineAction: -> @@ -332,8 +332,11 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass action = thang.action if thang?.acts action ?= @currentRootAction.name if @currentRootAction? action ?= 'idle' - action = null unless @actions[action]? - return null unless action + unless @actions[action]? + @warnedFor ?= {} + console.warn 'Cannot show action', action, 'for', @thangType.get('name'), 'because it DNE' unless @warnedFor[action] + @warnedFor[action] = true + return null action = 'break' if @actions.break? and @thang?.erroredOut action = 'die' if @actions.die? and thang?.health? and thang.health <= 0 @actions[action] diff --git a/app/lib/world/names.coffee b/app/lib/world/names.coffee index fc0a6aff9..d52471998 100644 --- a/app/lib/world/names.coffee +++ b/app/lib/world/names.coffee @@ -69,25 +69,18 @@ module.exports.thangNames = thangNames = "Buffy" "Allankrita" ] - "Peasant": [ + "Peasant M": [ "Yorik" "Hector" "Thad" "Victor" "Lyle" "Charles" - "Mary" - "Brandy" - "Gwendolin" - "Tabitha" - "Regan" "Yusef" "Hingle" "Azgot" "Piers" "Carlton" - "Giselle" - "Bernadette" "Hershell" "Gawain" "Durfkor" @@ -99,6 +92,13 @@ module.exports.thangNames = thangNames = "Icey" "Matilda" "Mertia" + "Mary" + "Brandy" + "Gwendolin" + "Tabitha" + "Regan" + "Giselle" + "Bernadette" ] "Archer F": [ "Phoebe" diff --git a/app/lib/world/vector.coffee b/app/lib/world/vector.coffee index 72f761775..ed5112f2c 100644 --- a/app/lib/world/vector.coffee +++ b/app/lib/world/vector.coffee @@ -8,7 +8,7 @@ class Vector a.copy()[name](b, useZ) isVector: true - apiProperties: ['x', 'y', 'magnitude', 'heading', 'distance', 'dot', 'equals', 'copy'] + apiProperties: ['x', 'y', 'magnitude', 'heading', 'distance', 'dot', 'equals', 'copy', 'distanceSquared'] constructor: (@x=0, @y=0, @z=0) -> diff --git a/app/locale/ar.coffee b/app/locale/ar.coffee index 3c650e49e..bd0f57c94 100644 --- a/app/locale/ar.coffee +++ b/app/locale/ar.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/bg.coffee b/app/locale/bg.coffee index 7ce8698c0..3205e568b 100644 --- a/app/locale/bg.coffee +++ b/app/locale/bg.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "български език", englishDescri # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "български език", englishDescri editor: "Редактор" blog: "Блог" forum: "Форум" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "български език", englishDescri # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Промени настройките" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "български език", englishDescri # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "български език", englishDescri # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/ca.coffee b/app/locale/ca.coffee index 1d671de6f..3589c67ee 100644 --- a/app/locale/ca.coffee +++ b/app/locale/ca.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr fork: "Fork" play: "Jugar" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr editor: "Editor" blog: "Blog" forum: "Fòrum" +# account: "Account" admin: "Admin" home: "Inici" contribute: "Col·laborar" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/cs.coffee b/app/locale/cs.coffee index 8d3c43d49..6b7434341 100644 --- a/app/locale/cs.coffee +++ b/app/locale/cs.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr fork: "Klonovat" play: "Přehrát" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr editor: "Editor" blog: "Blog" forum: "Fórum" +# account: "Account" admin: "Admin" home: "Domů" contribute: "Přispívat" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Editovat Nastavení" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr lg_title: "Poslední hry" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Editory CodeCombatu" main_description: "Vytvořte vlastní úrovně, kampaně, jednotky a vzdělávací obsah. My vám poskytujeme všechny potřebné nástroje!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr thang_description: "Vytvořte jednotky, definujte jejich logiku, vlastnosti, grafiku a zvuk. Momentálně jsou podporovány pouze importy vektorové grafiky exportované z Flashe." level_title: "Editor úrovní" level_description: "Zahrnuje pomůcky pro skriptování, nahrávání audia a tvorbu vlastní logiky pro vytvoření vlastních úrovní. Obsahuje vše, čeho využíváme k tvorbě úrovní my!" - security_notice: "Velké množství důležitých funkcí těchto editorů je standardně vypnuto. Jak postupem času vylepšujeme bezpečnost celého systému, jsou tyto funkce uvolňovány k veřejnému použití. Potřebujete-li některé funkce dříve, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "kontaktujte nás!" hipchat_prefix: "Můžete nás také najít v naší" hipchat_url: "HipChat diskusní místnosti." diff --git a/app/locale/da.coffee b/app/locale/da.coffee index e81fa0955..c468447fb 100644 --- a/app/locale/da.coffee +++ b/app/locale/da.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans fork: "Forgren" play: "Spil" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans editor: "Editor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Admin" home: "Hjem" contribute: "Bidrag" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Redigér Indstillinger" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans lg_title: "Seneste spil" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." level_title: "Bane Redigeringsværktøj" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "kontact os!" hipchat_prefix: "Du kan også finde os på vores" hipchat_url: "HipChat kanal." diff --git a/app/locale/de-AT.coffee b/app/locale/de-AT.coffee index 5ef340fbc..d543cb3b7 100644 --- a/app/locale/de-AT.coffee +++ b/app/locale/de-AT.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription: # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription: # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription: # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription: # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription: # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/de-CH.coffee b/app/locale/de-CH.coffee index 3d241fcc3..b612ddf60 100644 --- a/app/locale/de-CH.coffee +++ b/app/locale/de-CH.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge # fork: "Fork" play: "Spiele" retry: "nomol versuche" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "sekunde" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" contribute: "Spende" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/de-DE.coffee b/app/locale/de-DE.coffee index e159b5827..a083f5d78 100644 --- a/app/locale/de-DE.coffee +++ b/app/locale/de-DE.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription: # fork: "Fork" play: "Abspielen" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "Sekunde" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription: editor: "Editor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Administration" home: "Home" contribute: "Helfen" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription: # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Einstellungen ändern" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription: lg_title: "Letzte Spiele" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombat Editoren" main_description: "Entwerfe deine eigenen Level, Kampagnen, Einheiten und Lernmaterial. Wir stellen alle Werkzeuge zur Verfügung, die Du dafür benötigst!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription: thang_description: "Entwerfe Einheiten, definiere ihre Standardlogik, Grafiken und Töne. Zurzeit werden nur Flash Vektorgrafiken unterstützt." level_title: "Level Editor" level_description: "Beinhaltet die Werkzeuge zum Scripten, Hochladen von Tönen und zur Konstruktion eigener Logik, damit jedes erdenkliches Level erstellt werden kann. Genau die Sachen, die wir selber benutzen!" - security_notice: "Viele Hauptfunktionen der Editoren sind standardmäßig noch nicht aktiviert. Sobald die Sicherheit dieser Systeme gewährleistet ist, werden sie generell freigeschaltet. Falls Du diese Funktionen früher nutzen möchtest, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "setze dich mit uns in Verbindung!" hipchat_prefix: "Besuche uns auch in unserem" hipchat_url: "HipChat room." diff --git a/app/locale/de.coffee b/app/locale/de.coffee index b663a249b..28a5824ae 100644 --- a/app/locale/de.coffee +++ b/app/locale/de.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra # fork: "Fork" play: "Abspielen" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "Sekunde" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra editor: "Editor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Administration" home: "Home" contribute: "Helfen" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Einstellungen ändern" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra lg_title: "Letzte Spiele" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombat Editoren" main_description: "Entwerfe deine eigenen Level, Kampagnen, Einheiten und Lernmaterial. Wir stellen alle Werkzeuge zur Verfügung, die Du dafür benötigst!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra thang_description: "Entwerfe Einheiten, definiere ihre Standardlogik, Grafiken und Töne. Zurzeit werden nur Flash Vektorgrafiken unterstützt." level_title: "Level Editor" level_description: "Beinhaltet die Werkzeuge zum Scripten, Hochladen von Tönen und zur Konstruktion eigener Logik, damit jedes erdenkliches Level erstellt werden kann. Genau die Sachen, die wir selber benutzen!" - security_notice: "Viele Hauptfunktionen der Editoren sind standardmäßig noch nicht aktiviert. Sobald die Sicherheit dieser Systeme gewährleistet ist, werden sie generell freigeschaltet. Falls Du diese Funktionen früher nutzen möchtest, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "setze dich mit uns in Verbindung!" hipchat_prefix: "Besuche uns auch in unserem" hipchat_url: "HipChat room." diff --git a/app/locale/el.coffee b/app/locale/el.coffee index a67a3bfdb..ca846b61a 100644 --- a/app/locale/el.coffee +++ b/app/locale/el.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre # editor: "Editor" blog: "Μπλόγκ" forum: "Φόρουμ" +# account: "Account" admin: "Διαχειριστής" home: "Αρχική" contribute: "Συμβάλλω" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Επεξεργασία ρυθμίσεων" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/en-AU.coffee b/app/locale/en-AU.coffee index a5ff9b044..a3d06b8d0 100644 --- a/app/locale/en-AU.coffee +++ b/app/locale/en-AU.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/en-GB.coffee b/app/locale/en-GB.coffee index 0ae817a19..a5c291760 100644 --- a/app/locale/en-GB.coffee +++ b/app/locale/en-GB.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/en-US.coffee b/app/locale/en-US.coffee index 4d5b615fe..7c7d9b170 100644 --- a/app/locale/en-US.coffee +++ b/app/locale/en-US.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/en.coffee b/app/locale/en.coffee index 4696d8dae..3605d0557 100644 --- a/app/locale/en.coffee +++ b/app/locale/en.coffee @@ -204,6 +204,8 @@ candidate_top_skills: "Top Skills" candidate_years_experience: "Yrs Exp" candidate_last_updated: "Last Updated" + candidate_approved: "Us?" + candidate_active: "Them?" play_level: level_load_error: "Level could not be loaded: " @@ -370,10 +372,12 @@ new_article_title: "Create a New Article" new_thang_title: "Create a New Thang Type" new_level_title: "Create a New Level" + new_article_title_signup: "Sign Up to Create a New Article" + new_thang_title_signup: "Sign Up to Create a New Thang Type" + new_level_title_signup: "Sign Up to Create a New Level" article_search_title: "Search Articles Here" thang_search_title: "Search Thang Types Here" level_search_title: "Search Levels Here" - signup_to_create: "Sign Up to Create a New Content" read_only_warning2: "Note: you can't save any edits here, because you're not logged in." article: diff --git a/app/locale/es-419.coffee b/app/locale/es-419.coffee index fedde9aa0..65bf1688b 100644 --- a/app/locale/es-419.coffee +++ b/app/locale/es-419.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "segundo" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip editor: "Editor" blog: "Blog" forum: "Foro" +# account: "Account" admin: "Admin" home: "Inicio" contribute: "Contribuir" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Editar Configuración" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/es-ES.coffee b/app/locale/es-ES.coffee index 40c3b7807..b735eaa3d 100644 --- a/app/locale/es-ES.coffee +++ b/app/locale/es-ES.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis fork: "Bifurcar" play: "Jugar" retry: "Reintentar" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "segundo" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis editor: "Editor" blog: "Blog" forum: "Foro" +# account: "Account" admin: "Admin" home: "Inicio" contribute: "Colaborar" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis job_profile: "Perfil de trabajo" job_profile_approved: "Tu perfil de trabajo ha sido aprobado por CodeCombat. Los empleadores podrán verlo hasta que lo marques como inactivo o no haya sido cambiado durante cuatro semanas." job_profile_explanation: "¡Hola! Rellena esto y estaremos en contacto para hablar sobre encontrarte un trabajo como desarrollador de software." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Ajustes" @@ -185,7 +191,6 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis our_notes: "Nuestras notas" projects: "Proyectos" - employers: want_to_hire_our_players: "¿Quieres contratar jugadores expertos de CodeCombat?" contact_george: "Contacta con George para ver a nuestros candidatos" @@ -307,6 +312,13 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis lg_title: "Últimos Juegos" clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Editores de CodeCombat" main_description: "Construye tus propios niveles, campañas, unidades y contenido educativo. ¡Nosotros te ofrecemos todas las herramientas que necesitas!" @@ -316,7 +328,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis thang_description: "Construye unidades, su lógica predeterminada, gráficos y audio. Actualmente sólo se permite importar gráficos vectoriales exportados de Flash." level_title: "Editor de Niveles" level_description: "Incluye las herramientas para escribir scripts, subir audio, y construir una lógica personalidad con la que crear todo tipo de niveles. ¡Todo lo que usamos nosotros!" - security_notice: "Muchas de las funciones principales de estos editores no están habilitadas todavía por defecto. A medida que mejoremos la seguridad de los sistemas, se irán poniendo a disposición de todos. Si quieres utilizar estas funciones antes, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "¡Contacta con nosotros!" hipchat_prefix: "También puedes encontrarnos en nuestra" hipchat_url: "sala de HipChat." diff --git a/app/locale/es.coffee b/app/locale/es.coffee index cce4b4c11..74c4b2827 100644 --- a/app/locale/es.coffee +++ b/app/locale/es.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t # fork: "Fork" play: "Jugar" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t editor: "Editor" blog: "Blog" forum: "Foro" +# account: "Account" admin: "Admin" home: "Inicio" contribute: "Contribuir" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Editar Ajustes" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t lg_title: "Últimos juegos" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." level_title: "Editor de nivel" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/fa.coffee b/app/locale/fa.coffee index 54373a554..cb8f81869 100644 --- a/app/locale/fa.coffee +++ b/app/locale/fa.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian", # fork: "Fork" play: "سطوح" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian", editor: "ویرایشگر" blog: "بلاگ" forum: "انجمن" +# account: "Account" admin: "مدیر" home: "خانه" contribute: "همکاری" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian", # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian", # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian", # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/fi.coffee b/app/locale/fi.coffee index 487f11fd2..36e79fb4b 100644 --- a/app/locale/fi.coffee +++ b/app/locale/fi.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee index ad8d03579..75f6a2940 100644 --- a/app/locale/fr.coffee +++ b/app/locale/fr.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "français", englishDescription: "French", t fork: "Fork" play: "Jouer" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t editor: "Éditeur" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Admin" home: "Accueil" contribute: "Contribuer" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "français", englishDescription: "French", t # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Éditer les préférences" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "français", englishDescription: "French", t lg_title: "Dernières parties" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Éditeurs CodeCombat" main_description: "Créé tes propres niveaux, campagnes, unités et contenus éducatifs. Nous vous fournissons tous les outils dont vous avez besoin!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t thang_description: "Créé des unités, définis leur comportement de base, graphisme et son. Pour l'instant cette fonctionnalité ne supporte que l'importation d'images vectorielles exportées depuis Flash." level_title: "Éditeur de niveau" level_description: "Inclut les outils de script, l'upload de vidéos, et l'élaboration de logiques personnalisées pour créer toutes sortes de niveaux. Tout ce que nous utilisons nous-mêmes!" - security_notice: "Plusieurs caractéristiques majeures de cet éditeur ne sont pas encore activées par défaut. Quand nous aurons amélioré la sécurité de ces éléments, ils seront rendus disponibles. Si vous voulez les utiliser plus rapidement, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "contactez nous!" hipchat_prefix: "Vous pouvez aussi nous trouver dans notre " hipchat_url: "conversation HipChat." diff --git a/app/locale/he.coffee b/app/locale/he.coffee index 129a2544c..b96876c29 100644 --- a/app/locale/he.coffee +++ b/app/locale/he.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew", fork: "קילשון" play: "שחק" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew", editor: "עורך" blog: "בלוג" forum: "פורום" +# account: "Account" admin: "אדמין" home: "בית" contribute: "תרום" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew", # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "ערוך הגדרות" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew", # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew", # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/hi.coffee b/app/locale/hi.coffee index 5238b7fd8..3c3618c83 100644 --- a/app/locale/hi.coffee +++ b/app/locale/hi.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/hu.coffee b/app/locale/hu.coffee index 9ad4fcb80..9455fa056 100644 --- a/app/locale/hu.coffee +++ b/app/locale/hu.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t # fork: "Fork" play: "Játék" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "másodperc" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t editor: "Szerkesztő" blog: "Blog" forum: "Fórum" +# account: "Account" admin: "Admin" home: "Kezdőlap" contribute: "Segítségnyújtás" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t job_profile: "Munkaköri leírás" job_profile_approved: "Munkaköri leírásodat a Codecombat jóváhagyta. Munkaadók mindaddig láthatják, amíg meg nem jelölöd inaktíként, vagy négy hétig,ha addig nem kerül megváltoztatásra." job_profile_explanation: "Szió! Töltsd ki ezt és majd kapcsolatba lépünk veled és keresünk neked egy szoftware fejlesztői állást." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Beállítások szerkesztése" @@ -185,7 +191,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t # our_notes: "Our Notes" projects: "Projektek" - munkaadók: + employers: want_to_hire_our_players: "Akarsz szakértő CodeCombat játékosokat alkalmazni?" contact_george: "Vedd fel a kapcsolatot George-dzsal, hogy megtekinthesd jelöltjeinket" candidates_count_prefix: "Pillanatnyilag van" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" @@ -495,7 +508,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t # alert_account_message_suf: "first." # alert_account_message_create_url: "create an account" # archmage_summary: "Interested in working on game graphics, user interface design, database and server organization, multiplayer networking, physics, sound, or game engine performance? Want to help build a game to help other people learn what you are good at? We have a lot to do and if you are an experienced programmer and want to develop for CodeCombat, this class is for you. We would love your help building the best programming game ever." -# archmage_introduction: "One of the best parts about building games is they synthesize so many different things. Graphics, sound, real-time networking, social networking, and of course many of the more common aspects of programming, from low-level database management, and server administration to user facing design and i +# archmage_introduction: "One of the best parts about building games is they synthesize so many different things. Graphics, sound, real-time networking, social networking, and of course many of the more common aspects of programming, from low-level database management, and server administration to user facing design and interface building. There's a lot to do, and if you're an experienced programmer with a hankering to really dive into the nitty-gritty of CodeCombat, this class might be for you. We would love to have your help building the best programming game ever." # class_attributes: "Class Attributes" # archmage_attribute_1_pref: "Knowledge in " # archmage_attribute_1_suf: ", or a desire to learn. Most of our code is in this language. If you're a fan of Ruby or Python, you'll feel right at home. It's JavaScript, but with a nicer syntax." diff --git a/app/locale/id.coffee b/app/locale/id.coffee index 638a78899..8c238a638 100644 --- a/app/locale/id.coffee +++ b/app/locale/id.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/it.coffee b/app/locale/it.coffee index cca118653..5e030b82e 100644 --- a/app/locale/it.coffee +++ b/app/locale/it.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t fork: "Fork" play: "Gioca" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t editor: "Editor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Amministratore" home: "Pagina iniziale" contribute: "Contribuisci" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Modifica impostazioni" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t lg_title: "Ultime partite" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Editor di CodeCombat" main_description: "Costruisci i tuoi livelli, le tue campagne, unità e contenuti educativi. Ti forniamo tutti gli attrezzi necessari!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t thang_description: "Costruisci unità di gioco, definendo la loro logica di base, la grafica e l'audio. Per il momento si può soltanto importare grafica vettoriale esportata da Flash." level_title: "Modifica livello" level_description: "Comprende gli attrezzi per programmare, inviare audio e costruire unità logiche personalizzate per creare qualsiasi tipo di livello. Tutto quello che noi stessi usiamo!" - security_notice: "Molte funzioni importanti in questi editor non sono ancora attive. Mano a mano che miglioreremo la sicurezza di questi sistemi, essi verranno messi a disposizione di tutti. Per usare queste funzioni al più presto, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "scrivici!" hipchat_prefix: "Ci puoi anche trovare nella nostra" hipchat_url: "stanza HipChat." diff --git a/app/locale/ja.coffee b/app/locale/ja.coffee index 3e5f73a93..c738ad6c8 100644 --- a/app/locale/ja.coffee +++ b/app/locale/ja.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese", # fork: "Fork" play: "ゲームスタート" retry: "リトライ" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese", editor: "レベルエディタ" blog: "ブログ" forum: "掲示板" +# account: "Account" admin: "管理" home: "ホーム" contribute: "貢献" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese", # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "設定" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese", lg_title: "最近のゲーム" clas: "CLA" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombatエディター" main_description: "新しいレベル、キャンペーン、ユニットそして教育コンテンツを構築しましょう。" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese", # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/ko.coffee b/app/locale/ko.coffee index 40ad69d68..67de792e5 100644 --- a/app/locale/ko.coffee +++ b/app/locale/ko.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t fork: "Fork" play: "시작" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t editor: "에디터" blog: "블로그" forum: "포럼" +# account: "Account" admin: "관리자" home: "홈" contribute: "참여하기" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "설정사항 변경" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t lg_title: "가장 최근 게임" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "코드 컴뱃 에디터들" main_description: "당신의 레벨들, 캠페인들, 유닛 그리고 교육 컨텐츠들을 구축하세요. 우리는 당신이 필요한 모든 도구들을 제공합니다!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t thang_description: "유닛들, 기본적인 인공지능, 그래픽과 오디오등을 직접 빌드하세요. 현재는 백터 그래픽으로 추출된 플래시파일만 임폴트 가능합니다." level_title: "레벨 에디터" level_description: "스크립팅, 오디오 업로드, 모든 레벨을 생성하기 위한 사용자 정의 로직등 우리가 사용하는 모든 것들을 구축하는 것을 위한 툴들을 포함합니다." - security_notice: "이러한 에디터들의 중요한 특징들은 현재 대부분 기본적으로 제공되지 않습니다. 조만간 이런 시스템들의 안정성을 업그레이트 한후에, 이러한 기능들이 제공될 것입니다." +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "연락하기!" hipchat_prefix: "당신은 또한 우리를 여기에서 찾을 수 있습니다 : " hipchat_url: "힙챗 룸" diff --git a/app/locale/lt.coffee b/app/locale/lt.coffee index 62e2868a0..ee8a72a7b 100644 --- a/app/locale/lt.coffee +++ b/app/locale/lt.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/ms.coffee b/app/locale/ms.coffee index 0afee741e..13676820e 100644 --- a/app/locale/ms.coffee +++ b/app/locale/ms.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa # fork: "Fork" play: "Mula" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" home: "Halaman" contribute: "Sumbangan" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/nb.coffee b/app/locale/nb.coffee index 3a2d4b38a..c724493c3 100644 --- a/app/locale/nb.coffee +++ b/app/locale/nb.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg # fork: "Fork" play: "Spill" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg editor: "Editor" blog: "Blogg" forum: "Forum" +# account: "Account" admin: "Administrator" home: "Hjem" contribute: "Bidra" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Rediger Innstillinger" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/nl-BE.coffee b/app/locale/nl-BE.coffee index 7fa0c3cde..f0de8e61d 100644 --- a/app/locale/nl-BE.coffee +++ b/app/locale/nl-BE.coffee @@ -1,11 +1,11 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription: "Dutch (Belgium)", translation: common: - loading: "Aan het laden..." + loading: "Bezig met laden..." saving: "Opslaan..." sending: "Verzenden..." send: "Verzend" cancel: "Annuleren" - save: "Opslagen" + save: "Opslaan" publish: "Publiceren" create: "Creëer" delay_1_sec: "1 seconde" @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription: fork: "Fork" play: "Spelen" retry: "Probeer opnieuw" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "seconde" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription: editor: "Editor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Administrator" home: "Home" contribute: "Bijdragen" @@ -46,7 +50,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription: employers: "Werkgevers" versions: - save_version_title: "Nieuwe versie opslagen" + save_version_title: "Nieuwe versie opslaan" new_major_version: "Nieuwe hoofd versie" cla_prefix: "Om bewerkingen op te slaan, moet je eerst akkoord gaan met onze" cla_url: "CLA" @@ -73,7 +77,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription: creating: "Account aanmaken..." sign_up: "Aanmelden" log_in: "inloggen met wachtwoord" - social_signup: "Of je kunt je registreren met Facebook of G+:" + social_signup: "Of je kunt je registreren met Facebook of G+:" home: slogan: "Leer programmeren in JavaScript door het spelen van een spel" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription: job_profile: "Job Profiel" job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken." job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Instellingen Aanpassen" @@ -293,7 +299,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription: time_goto: "Ga naar:" infinite_loop_try_again: "Probeer opnieuw" infinite_loop_reset_level: "Level resetten" - infinite_loop_comment_out: "Mijn code weg commentariëren" + infinite_loop_comment_out: "Mijn code weg commentariëren" admin: av_title: "Administrator panels" @@ -306,16 +312,23 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription: lg_title: "Laatste Spelletjes" clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombat Editors" - main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die u nodig heeft!" + main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die je nodig hebt!" article_title: "Artikel Editor" article_description: "Schrijf artikels die spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes." thang_title: "Thang Editor" thang_description: "Maak eenheden, beschrijf hun standaard logica, graphics en audio. Momenteel is enkel het importeren van vector graphics geëxporteerd uit Flash ondersteund." level_title: "Level Editor" level_description: "Bevat de benodigdheden om scripts te schrijven, audio te uploaden en aangepaste logica te creëren om alle soorten levels te maken. Het is alles wat wij zelf ook gebruiken!" - security_notice: "Veel belangrijke elementen in deze editors zijn momenteel niet actief. Als wij de veiligheid van deze systemen verbeteren, zullen ook deze elementen beschikbaar worden. Indien u deze elementen al eerder wil gebruiken, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "contacteer ons!" hipchat_prefix: "Je kan ons ook vinden in ons" hipchat_url: "(Engelstalig) HipChat kanaal." diff --git a/app/locale/nl-NL.coffee b/app/locale/nl-NL.coffee index 9d74a74fb..1c4680d86 100644 --- a/app/locale/nl-NL.coffee +++ b/app/locale/nl-NL.coffee @@ -1,11 +1,11 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription: "Dutch (Netherlands)", translation: common: - loading: "Aan het laden..." + loading: "Bezig met laden..." saving: "Opslaan..." sending: "Verzenden..." send: "Verzend" cancel: "Annuleren" - save: "Opslagen" + save: "Opslaan" publish: "Publiceren" create: "Creëer" delay_1_sec: "1 seconde" @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription fork: "Fork" play: "Spelen" retry: "Probeer opnieuw" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "seconde" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription editor: "Editor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Administrator" home: "Home" contribute: "Bijdragen" @@ -46,7 +50,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription employers: "Werkgevers" versions: - save_version_title: "Nieuwe versie opslagen" + save_version_title: "Nieuwe versie opslaan" new_major_version: "Nieuwe hoofd versie" cla_prefix: "Om bewerkingen op te slaan, moet je eerst akkoord gaan met onze" cla_url: "CLA" @@ -73,7 +77,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription creating: "Account aanmaken..." sign_up: "Aanmelden" log_in: "inloggen met wachtwoord" - social_signup: "Of je kunt je registreren met Facebook of G+:" + social_signup: "Of je kunt je registreren met Facebook of G+:" home: slogan: "Leer programmeren in JavaScript door het spelen van een spel" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription job_profile: "Job Profiel" job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken." job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Instellingen Aanpassen" @@ -293,7 +299,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription time_goto: "Ga naar:" infinite_loop_try_again: "Probeer opnieuw" infinite_loop_reset_level: "Level resetten" - infinite_loop_comment_out: "Mijn code weg commentariëren" + infinite_loop_comment_out: "Mijn code weg commentariëren" admin: av_title: "Administrator panels" @@ -306,16 +312,23 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription lg_title: "Laatste Spelletjes" clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombat Editors" - main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die u nodig heeft!" + main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die je nodig hebt!" article_title: "Artikel Editor" article_description: "Schrijf artikels die spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes." thang_title: "Thang Editor" thang_description: "Maak eenheden, beschrijf hun standaard logica, graphics en audio. Momenteel is enkel het importeren van vector graphics geëxporteerd uit Flash ondersteund." level_title: "Level Editor" level_description: "Bevat de benodigdheden om scripts te schrijven, audio te uploaden en aangepaste logica te creëren om alle soorten levels te maken. Het is alles wat wij zelf ook gebruiken!" - security_notice: "Veel belangrijke elementen in deze editors zijn momenteel niet actief. Als wij de veiligheid van deze systemen verbeteren, zullen ook deze elementen beschikbaar worden. Indien u deze elementen al eerder wil gebruiken, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "contacteer ons!" hipchat_prefix: "Je kan ons ook vinden in ons" hipchat_url: "(Engelstalig) HipChat kanaal." diff --git a/app/locale/nl.coffee b/app/locale/nl.coffee index b69517de9..f610f5de5 100644 --- a/app/locale/nl.coffee +++ b/app/locale/nl.coffee @@ -1,11 +1,11 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", translation: common: - loading: "Aan het laden..." + loading: "Bezig met laden..." saving: "Opslaan..." sending: "Verzenden..." send: "Verzend" cancel: "Annuleren" - save: "Opslagen" + save: "Opslaan" publish: "Publiceren" create: "Creëer" delay_1_sec: "1 seconde" @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t fork: "Fork" play: "Spelen" retry: "Probeer opnieuw" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "seconde" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t editor: "Editor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Administrator" home: "Home" contribute: "Bijdragen" @@ -46,7 +50,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t employers: "Werkgevers" versions: - save_version_title: "Nieuwe versie opslagen" + save_version_title: "Nieuwe versie opslaan" new_major_version: "Nieuwe hoofd versie" cla_prefix: "Om bewerkingen op te slaan, moet je eerst akkoord gaan met onze" cla_url: "CLA" @@ -73,7 +77,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t creating: "Account aanmaken..." sign_up: "Aanmelden" log_in: "inloggen met wachtwoord" - social_signup: "Of je kunt je registreren met Facebook of G+:" + social_signup: "Of je kunt je registreren met Facebook of G+:" home: slogan: "Leer programmeren in JavaScript door het spelen van een spel" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t job_profile: "Job Profiel" job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken." job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Instellingen Aanpassen" @@ -293,7 +299,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t time_goto: "Ga naar:" infinite_loop_try_again: "Probeer opnieuw" infinite_loop_reset_level: "Level resetten" - infinite_loop_comment_out: "Mijn code weg commentariëren" + infinite_loop_comment_out: "Mijn code weg commentariëren" admin: av_title: "Administrator panels" @@ -306,16 +312,23 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t lg_title: "Laatste Spelletjes" clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombat Editors" - main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die u nodig heeft!" + main_description: "Maak je eigen levels, campagnes, eenheden en leermateriaal. Wij bieden alle programma's aan die je nodig hebt!" article_title: "Artikel Editor" article_description: "Schrijf artikels die spelers een overzicht geven over programmeer concepten die kunnen gebruikt worden over een variëteit van levels en campagnes." thang_title: "Thang Editor" thang_description: "Maak eenheden, beschrijf hun standaard logica, graphics en audio. Momenteel is enkel het importeren van vector graphics geëxporteerd uit Flash ondersteund." level_title: "Level Editor" level_description: "Bevat de benodigdheden om scripts te schrijven, audio te uploaden en aangepaste logica te creëren om alle soorten levels te maken. Het is alles wat wij zelf ook gebruiken!" - security_notice: "Veel belangrijke elementen in deze editors zijn momenteel niet actief. Als wij de veiligheid van deze systemen verbeteren, zullen ook deze elementen beschikbaar worden. Indien u deze elementen al eerder wil gebruiken, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "contacteer ons!" hipchat_prefix: "Je kan ons ook vinden in ons" hipchat_url: "(Engelstalig) HipChat kanaal." diff --git a/app/locale/nn.coffee b/app/locale/nn.coffee index 80805c946..9b46ee572 100644 --- a/app/locale/nn.coffee +++ b/app/locale/nn.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/no.coffee b/app/locale/no.coffee index fffbd449b..0468a52f0 100644 --- a/app/locale/no.coffee +++ b/app/locale/no.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr # fork: "Fork" play: "Spill" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr editor: "Editor" blog: "Blogg" forum: "Forum" +# account: "Account" admin: "Administrator" home: "Hjem" contribute: "Bidra" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Rediger Innstillinger" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/pl.coffee b/app/locale/pl.coffee index bfe258c77..4d086f110 100644 --- a/app/locale/pl.coffee +++ b/app/locale/pl.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish fork: "Fork" play: "Graj" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish editor: "Edytor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Admin" home: "Główna" contribute: "Współpraca" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Edytuj ustawienia" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish lg_title: "Ostatnie gry" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Edytory CodeCombat" main_description: "Stwórz własne poziomy, kampanie, jednostki i materiały edukacyjne. Zapewniamy wszystkie narzędzia, jakich będziesz potrzebował!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish thang_description: "Twórz jednostki, definiuj ich domyślną logikę, grafiki i dźwięki. Aktualnie wspiera wyłącznie importowanie grafik wektorowych wyeksportowanych przez Flash." level_title: "Edytor poziomów" level_description: "Zawiera narzędzia do skryptowania, przesyłania dźwięków i konstruowania spersonalizowanych logik, by móc tworzyć najrozmaitsze poziomy. Wszystko to, czego sami używamy!" - security_notice: "Wiele ważnych funkcji nie jest obecnie domyślnie włączonych we wspomnianych edytorach. Wraz z ulepszeniem zabezpieczenia tych narzędzi, staną się one dostępne publicznie. Jeśli chciałbyś użyć ich już teraz, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "skontaktuj się z nami!" hipchat_prefix: "Możesz nas też spotkać w naszym" hipchat_url: "pokoju HipChat." diff --git a/app/locale/pt-BR.coffee b/app/locale/pt-BR.coffee index 83d592fc9..aac12c77b 100644 --- a/app/locale/pt-BR.coffee +++ b/app/locale/pt-BR.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: fork: "Fork" play: "Jogar" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "segundo" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: editor: "Editor" blog: "Blog" forum: "Fórum" +# account: "Account" admin: "Administrador" home: "Início" contribute: "Contribuir" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Editar as configurações" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: lg_title: "Últimos Jogos" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Editores do CodeCombat" main_description: "Construa seus próprios níveis, campanhas, unidades e conteúdo educacional. Nós fornecemos todas as ferramentas que você precisa!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription: thang_description: "Construa unidades, definindo sua lógica padrão, gráfico e áudio. Atualmente só é suportado importação de vetores gráficos exportados do Flash." level_title: "Editor de Niível" level_description: "Inclui as ferramentas para codificar, fazer o upload de áudio e construir uma lógica diferente para criar todos os tipos de níveis. Tudo o que nós mesmos utilizamos!" - security_notice: "Muitos recursos principais nestes editores não estão habilitados por padrão atualmente. A maneira que melhoramos a segurança desses sistemas, eles serão colocados a disposição. Se você quiser utilizar um desses recursos mais rápido, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "entre em contato!" hipchat_prefix: "Você também pode nos encontrar na nossa" hipchat_url: "Sala do HipChat." diff --git a/app/locale/pt-PT.coffee b/app/locale/pt-PT.coffee index 4692e2279..5f1766961 100644 --- a/app/locale/pt-PT.coffee +++ b/app/locale/pt-PT.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P fork: "Fork" play: "Jogar" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P editor: "Editor" blog: "Blog" forum: "Fórum" +# account: "Account" admin: "Administrador" home: "Início" contribute: "Contribuir" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Editar Definições" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P lg_title: "Últimos Jogos" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Editores para CodeCombat" main_description: "Constrói os teus níveis, campanhas, unidades e conteúdo educacional. Nós fornecemos todas as ferramentas que precisas!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P thang_description: "Constrói unidades, definindo a sua logica, visual e audio por defeito. De momento só é suportado 'importing Flash exported vector graphics'." level_title: "Editor de níveis" level_description: "Inclui ferramentas para a criação de scripts, upload de áudio, e construção de lógica personalizada para criar todos os tipos de níveis. Tudo o que nós usamos!" - security_notice: "Muitas das principais funcionalidades nestes editores não estão activas por defeito. À medida que a segurança destes sistemas é melhorada, eles serão disponibilizados. Se quiseres utilizar estas uncionalidades mais cedo, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "contacta-nos!" hipchat_prefix: "Podes encontrar-nos no nosso" hipchat_url: "canal HipChat." diff --git a/app/locale/pt.coffee b/app/locale/pt.coffee index ace10e931..a82ee92b6 100644 --- a/app/locale/pt.coffee +++ b/app/locale/pt.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues # fork: "Fork" play: "Jogar" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues editor: "Editor" blog: "Blog" forum: "Fórum" +# account: "Account" admin: "Administrador" home: "Início" contribute: "Contribuir" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Editar as configurações" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/ro.coffee b/app/locale/ro.coffee index d11bf98f4..57e83e5f8 100644 --- a/app/locale/ro.coffee +++ b/app/locale/ro.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman fork: "Fork" play: "Joacă" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "secundă" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman editor: "Editor" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Admin" home: "Acasa" contribute: "Contribuie" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Modifică setările" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman lg_title: "Ultimele jocuri" clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Editori CodeCombat" main_description: "Construiește propriile nivele, campanii, unități și conținut educațional. Noi îți furnizăm toate uneltele necesare!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman thang_description: "Construiește unități, definește logica lor, grafica și sunetul. Momentan suportă numai importare de grafică vectorială exportată din Flash." level_title: "Editor Nivele" level_description: "Include uneltele pentru scriptare, upload audio, și construcție de logică costum pentru toate tipurile de nivele.Tot ce folosim noi înșine!" - security_notice: "Multe setări majore de securitate în aceste editoare nu sunt momentan disponibile.Pe măsură ce îmbunătățim securitatea acestor sisteme, ele vor deveni disponibile. Dacă doriți să folosiți aceste setări mai devrme, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "contactați-ne!" hipchat_prefix: "Ne puteți de asemenea găsi la" hipchat_url: "HipChat." diff --git a/app/locale/ru.coffee b/app/locale/ru.coffee index 9bfe247ca..c1aafb04c 100644 --- a/app/locale/ru.coffee +++ b/app/locale/ru.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi fork: "Форк" play: "Играть" retry: "Повторить" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "секунда" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi editor: "Редактор" blog: "Блог" forum: "Форум" +# account: "Account" admin: "Админ" home: "Домой" contribute: "Сотрудничество" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi job_profile: "Профиль соискателя" job_profile_approved: "Ваш профиль соискателя был одобрен CodeCombat. Работодатели смогут видеть его, пока вы не отметите его неактивным или он не будет изменен в течение четырёх недель." job_profile_explanation: "Привет! Заполните это, и мы свяжемся с вами при нахождении работы разработчика программного обеспечения для вас." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Изменить настройки" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi lg_title: "Последние игры" clas: "ЛСС" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Редакторы CodeCombat" main_description: "Создавайте ваши собственные уровни, кампании, юнитов и обучающий контент. Мы предоставляем все необходимые инструменты!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi thang_description: "Создавайте юнитов, определяйте их логику по умолчанию, графику и звук. В настоящий момент поддерживается импорт только векторной графики Flash." level_title: "Редактор уровней" level_description: "Включает в себя инструменты для написания сценариев, загрузки аудио и построения собственной логики для создания всевозможных уровней. Всё, что мы используем сами!" - security_notice: "Многие основные возможности в этих редакторах в настоящее время не включены по умолчанию. Как только мы повысим безопасность этих систем, они станут общедоступными. Если вам хотелось бы использовать эти возможности раньше, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "свяжитесь с нами!" hipchat_prefix: "Также вы можете найти нас в нашей" hipchat_url: "комнате HipChat." diff --git a/app/locale/sk.coffee b/app/locale/sk.coffee index 543ab000a..5100cddf3 100644 --- a/app/locale/sk.coffee +++ b/app/locale/sk.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak", # fork: "Fork" play: "Hraj" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak", editor: "Editor" blog: "Blog" forum: "Fórum" +# account: "Account" admin: "Spravuj" home: "Domov" contribute: "Prispej" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak", # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak", # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak", # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/sl.coffee b/app/locale/sl.coffee index 6614a51ef..bbd20d75a 100644 --- a/app/locale/sl.coffee +++ b/app/locale/sl.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/sr.coffee b/app/locale/sr.coffee index b19c7db87..d58228ccb 100644 --- a/app/locale/sr.coffee +++ b/app/locale/sr.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian # fork: "Fork" play: "Нивои" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian editor: "Уређивач" blog: "Блог" forum: "Форум" +# account: "Account" admin: "Админ" home: "Почетна" contribute: "Допринеси" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Измени подешавања" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/sv.coffee b/app/locale/sv.coffee index 4ef8fc4bf..efc862ffa 100644 --- a/app/locale/sv.coffee +++ b/app/locale/sv.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr fork: "Förgrena" play: "Spela" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr editor: "Nivåredigerare" blog: "Blogg" forum: "Forum" +# account: "Account" admin: "Admin" home: "Hem" contribute: "Bidra" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Ändra inställningar" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr lg_title: "Senaste matcher" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombatredigerare" main_description: "Bygg dina egna banor, kampanjer, enheter och undervisningsinnehåll. Vi tillhandahåller alla verktyg du behöver!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr thang_description: "Bygg enheter, genom att definerade deras förinställda logik, grafik och ljud. Stöder för närvarande endast import av Flashexporterad vektorgrafik." level_title: "Nivåredigerare" level_description: "Innehåller verktygen för att skripta, ladda upp ljud och konstruera skräddarsydd logik för att skapa alla möjliga sorters nivåer. Allting vi själva använder!" - security_notice: "Många huvudfunktioner i dessa redigerare är för närvarande inte aktiverade från början. Allt eftersom vi ökar säkerheten i dessa system, okmmer de att bli allmänt tillgängliga. Om du skulle vilja använda dessa funktioner tidigare, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "kontakta oss!" hipchat_prefix: "Du kan också hitta oss i vårt" hipchat_url: "HipChat-rum." diff --git a/app/locale/th.coffee b/app/locale/th.coffee index a4884c40b..f0a4f0179 100644 --- a/app/locale/th.coffee +++ b/app/locale/th.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra # fork: "Fork" play: "เล่น" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra editor: "Editor" blog: "บล็อก" forum: "กระดานสนทนา" +# account: "Account" admin: "ผู้ดูแลระบบ" home: "Home" contribute: "สนับสนุน" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "แก้ไขการตั้งค่า" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/tr.coffee b/app/locale/tr.coffee index 81fe200f2..0de56c4a0 100644 --- a/app/locale/tr.coffee +++ b/app/locale/tr.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t fork: "Çatalla" play: "Oyna" retry: "Yeniden Dene" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "saniye" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t editor: "Düzenleyici" blog: "Blog" forum: "Forum" +# account: "Account" admin: "Yönetici" home: "Anasayfa" contribute: "Katkıda bulun" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Ayarları Düzenle" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t lg_title: "Yeni Oyunlar" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombat Düzenleyici" main_description: "Kendi bölümlerinizi, seferberliklerinizi, birimlerinizi ve eğitimsel içeriklerinizi oluşturun. Gereken tüm araçları sağlıyoruz!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t thang_description: "Öntanımlı mantıkları, grafik ve seslerini tanımlayarak birimler üretin. Şimdilik sadece Flash ile dışa aktarılmış vektör grafikleri desteklenmektedir." level_title: "Bölüm Düzenleyici" level_description: "Her türde bölüm oluşturmak için betik yazma, ses yükleme ve özel mantık inşası için araçları içermektedir. Kendi kullandığımız her şey!" - security_notice: "Bu düzenleyicilerin çoğu özelliği öntanımlı olarak şimdilik etkin değildir. Bu sistemlerin güvenliklerini arttırdığımızda herkese açık olacaklar. Eğer bu özellikleri daha önceden kullanmak isterseniz," +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "bize ulaşın!" hipchat_prefix: "Bizi ayrıca" hipchat_url: "HipChat otasında bulabilirsiniz." diff --git a/app/locale/uk.coffee b/app/locale/uk.coffee index e99eef979..e9e6221ba 100644 --- a/app/locale/uk.coffee +++ b/app/locale/uk.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "українська мова", englishDesc fork: "Форк" play: "Грати" retry: "Повтор" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "Секунда" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "українська мова", englishDesc editor: "Редактор" blog: "Блог" forum: "Форум" +# account: "Account" admin: "Адміністратор" home: "На головну" contribute: "Співпраця" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "українська мова", englishDesc # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Змінити налаштування" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "українська мова", englishDesc lg_title: "Останні ігри" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "Редактори CodeCombat" main_description: "Створюйте власні рівні, кампанії, юнітів та навчальний контекнт. Ми надаємо всіх необхидних інструментів! " @@ -315,7 +328,7 @@ module.exports = nativeDescription: "українська мова", englishDesc thang_description: "Створюйте юнітів, візначайте їхню логіку, графіку та аудіо. Наразі підтримується тільки імпорт векторної flash-графіки." level_title: "Редактор рівнів" level_description: "Включає інструменти для створення сценаріїв, аудіо й конструювання логіки задля створення усіх типів рівнив. Усе, що ми самі використовуємо! " - security_notice: "Багато базових можливостей у цих редакторах зараз не доступні за замовчуванням. Як тільки ми вдосконалимо безпеку цих систем, вони стануть загальнодоступними. Якщо ви хочете використовувати ці можливості раніше, " +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "зв’яжіться з нами!" hipchat_prefix: "Ви можете також знайти нас в нашій" hipchat_url: "кімнаті HipChat." diff --git a/app/locale/ur.coffee b/app/locale/ur.coffee index 2f7ab791d..5ef7e396d 100644 --- a/app/locale/ur.coffee +++ b/app/locale/ur.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu", # fork: "Fork" # play: "Play" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu", # editor: "Editor" # blog: "Blog" # forum: "Forum" +# account: "Account" # admin: "Admin" # home: "Home" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu", # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu", # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu", # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/vi.coffee b/app/locale/vi.coffee index dd5991ab0..4c49d6373 100644 --- a/app/locale/vi.coffee +++ b/app/locale/vi.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn # fork: "Fork" play: "Các cấp độ" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn editor: "Chỉnh sửa" # blog: "Blog" forum: "Diễn đàn" +# account: "Account" admin: "Quản trị viên" home: "Nhà" contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "Chỉnh sửa cài đặt" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/zh-HANS.coffee b/app/locale/zh-HANS.coffee index 4c5469376..433a26034 100644 --- a/app/locale/zh-HANS.coffee +++ b/app/locale/zh-HANS.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese fork: "派生" play: "开始" retry: "重试" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" units: second: "秒" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese editor: "编辑器" blog: "博客" forum: "论坛" +# account: "Account" admin: "管理" home: "首页" contribute: "贡献" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese job_profile: "工作经历" job_profile_approved: "你填写的工作经历将由CodeCombat认证. 雇主将看到这些信息,除非你将它设置为不启用状态或者连续四周没有更新." job_profile_explanation: "你好! 填写这些信息, 我们将使用它帮你寻找一份软件开发的工作." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "编辑设置" @@ -185,7 +191,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese # our_notes: "Our Notes" projects: "项目" -# employers: + employers: want_to_hire_our_players: "想要雇用CodeCombat上的专业玩家?" contact_george: "联系George查看”为我们义务工作的人" candidates_count_prefix: "我们当前有 " @@ -306,6 +312,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese lg_title: "最新的游戏" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + editor: main_title: "CodeCombat 编辑器" main_description: "建立你自己的关卡、 战役、单元和教育内容。我们会提供所有你需要的工具!" @@ -315,7 +328,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese thang_description: "创建单元,并定义单元的逻辑、图形和音频。目前只支持导入 Flash 导出的矢量图形。" level_title: "关卡编辑器" level_description: "所有用来创造所有难度的关卡的工具,包括脚本、上传音频和构建自定义逻辑。" - security_notice: "编辑器的许多主要功能并不是目前默认启动的。当我们改善完这些系统的安全性的时候,它们就会成为通常可用的。如果你想要马上使用这些功能," +# got_questions: "Questions about using the CodeCombat editors?" contact_us: "联系我们!" hipchat_prefix: "你也可以在这里找到我们" hipchat_url: "HipChat 房间。" diff --git a/app/locale/zh-HANT.coffee b/app/locale/zh-HANT.coffee index d5d7456df..8824ebd9b 100644 --- a/app/locale/zh-HANT.coffee +++ b/app/locale/zh-HANT.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese fork: "Fork" play: "播放" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese editor: "編輯" blog: "官方部落格" forum: "論壇" +# account: "Account" admin: "系統管理員" home: "首頁" contribute: "貢獻" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" account_profile: edit_settings: "帳號設定" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/locale/zh.coffee b/app/locale/zh.coffee index 3f33a7be0..87003013f 100644 --- a/app/locale/zh.coffee +++ b/app/locale/zh.coffee @@ -15,6 +15,9 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra fork: "Fork" play: "玩" # retry: "Retry" +# watch: "Watch" +# unwatch: "Unwatch" +# submit_patch: "Submit Patch" # units: # second: "second" @@ -36,6 +39,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra editor: "编辑" blog: "博客" forum: "论坛" +# account: "Account" admin: "超级管理员" home: "首页" # contribute: "Contribute" @@ -170,6 +174,8 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra # 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." +# sample_profile: "See a sample profile" +# view_profile: "View Your Profile" # account_profile: # edit_settings: "Edit Settings" @@ -306,6 +312,13 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra # lg_title: "Latest Games" # clas: "CLAs" +# community: +# level_editor: "Level Editor" +# main_title: "CodeCombat Community" +# facebook: "Facebook" +# twitter: "Twitter" +# gplus: "Google+" + # editor: # main_title: "CodeCombat Editors" # main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!" @@ -315,8 +328,8 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra # thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics." # level_title: "Level Editor" # level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!" -# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, " -# contact_us: "contact us!" +# got_questions: "Questions about using the CodeCombat editors?" +# contact_us: "Contact us!" # hipchat_prefix: "You can also find us in our" # hipchat_url: "HipChat room." # back: "Back" diff --git a/app/models/Article.coffee b/app/models/Article.coffee index 29e5dd8c5..e93c6102a 100644 --- a/app/models/Article.coffee +++ b/app/models/Article.coffee @@ -2,5 +2,6 @@ CocoModel = require('./CocoModel') module.exports = class Article extends CocoModel @className: "Article" + @schema: require 'schemas/models/article' urlRoot: "/db/article" saveBackups: true diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee index b33177a3a..1c93ea125 100644 --- a/app/models/CocoModel.coffee +++ b/app/models/CocoModel.coffee @@ -11,7 +11,6 @@ class CocoModel extends Backbone.Model initialize: -> super() - @constructor.schema ?= require "schemas/models/#{@urlRoot[4..].replace '.', '_'}" if not @constructor.className console.error("#{@} needs a className set.") @markToRevert() @@ -120,6 +119,7 @@ class CocoModel extends Backbone.Model @set prop, defaultValue for prop, sch of @constructor.schema.properties or {} continue if @get(prop)? + continue if prop is 'emails' # hack, defaults are handled through User.coffee's email-specific methods. #console.log "setting", prop, "to", sch.default, "from sch.default" if sch.default? @set prop, sch.default if sch.default? if @loaded @@ -133,6 +133,7 @@ class CocoModel extends Backbone.Model schema ?= @schema() models = [] + # TODO: Better schema/json walking if $.isArray(data) and schema.items? for subData, i in data models = models.concat(@getReferencedModels(subData, schema.items, path+i+'/', shouldLoadProjection)) @@ -223,8 +224,30 @@ class CocoModel extends Backbone.Model watch: (doWatch=true) -> $.ajax("#{@urlRoot}/#{@id}/watch", {type:'PUT', data:{on:doWatch}}) @watching = -> doWatch - + watching: -> return me.id in (@get('watchers') or []) + + populateI18N: (data, schema, path='') -> + # TODO: Better schema/json walking + sum = 0 + data ?= $.extend true, {}, @attributes + schema ?= @schema() or {} + if schema.properties?.i18n and _.isPlainObject(data) and not data.i18n? + data.i18n = {} + sum += 1 + + if _.isPlainObject data + for key, value of data + numChanged = 0 + numChanged = @populateI18N(value, childSchema, path+'/'+key) if childSchema = schema.properties?[key] + if numChanged and not path # should only do this for the root object + @set key, value + sum += numChanged + + if schema.items and _.isArray data + sum += @populateI18N(value, schema.items, path+'/'+index) for value, index in data + + sum module.exports = CocoModel diff --git a/app/models/File.coffee b/app/models/File.coffee index de68d3893..e8241d291 100644 --- a/app/models/File.coffee +++ b/app/models/File.coffee @@ -2,4 +2,5 @@ CocoModel = require('./CocoModel') module.exports = class File extends CocoModel @className: "File" - urlRoot: "/db/file" \ No newline at end of file + @schema: require 'schemas/models/file' + urlRoot: "/db/file" diff --git a/app/models/Level.coffee b/app/models/Level.coffee index 353f5d447..4fbb1a04e 100644 --- a/app/models/Level.coffee +++ b/app/models/Level.coffee @@ -5,6 +5,7 @@ ThangType = require './ThangType' module.exports = class Level extends CocoModel @className: "Level" + @schema: require 'schemas/models/level' urlRoot: "/db/level" serialize: (supermodel) -> diff --git a/app/models/LevelComponent.coffee b/app/models/LevelComponent.coffee index 7f9300bce..9a7569ad0 100644 --- a/app/models/LevelComponent.coffee +++ b/app/models/LevelComponent.coffee @@ -2,6 +2,7 @@ CocoModel = require('./CocoModel') module.exports = class LevelComponent extends CocoModel @className: "LevelComponent" + @schema: require 'schemas/models/level_component' urlRoot: "/db/level.component" set: (key, val, options) -> diff --git a/app/models/LevelFeedback.coffee b/app/models/LevelFeedback.coffee index fc4eff896..a4bc1f3a9 100644 --- a/app/models/LevelFeedback.coffee +++ b/app/models/LevelFeedback.coffee @@ -2,4 +2,5 @@ CocoModel = require('./CocoModel') module.exports = class LevelFeedback extends CocoModel @className: "LevelFeedback" + @schema: require 'schemas/models/level_feedback' urlRoot: "/db/level.feedback" diff --git a/app/models/LevelSession.coffee b/app/models/LevelSession.coffee index c7f359670..fade84cd1 100644 --- a/app/models/LevelSession.coffee +++ b/app/models/LevelSession.coffee @@ -2,6 +2,7 @@ CocoModel = require('./CocoModel') module.exports = class LevelSession extends CocoModel @className: "LevelSession" + @schema: require 'schemas/models/level_session' urlRoot: "/db/level.session" initialize: -> @@ -10,7 +11,7 @@ module.exports = class LevelSession extends CocoModel state = @get('state') or {} state.scripts ?= {} @set('state', state) - + updatePermissions: -> permissions = @get 'permissions' permissions = (p for p in permissions when p.target isnt 'public') diff --git a/app/models/LevelSystem.coffee b/app/models/LevelSystem.coffee index 8123c6f79..f2ca539b4 100644 --- a/app/models/LevelSystem.coffee +++ b/app/models/LevelSystem.coffee @@ -1,7 +1,9 @@ CocoModel = require('./CocoModel') +SystemNameLoader = require('lib/SystemNameLoader') module.exports = class LevelSystem extends CocoModel @className: "LevelSystem" + @schema: require 'schemas/models/level_system' urlRoot: "/db/level.system" set: (key, val, options) -> @@ -16,6 +18,7 @@ module.exports = class LevelSystem extends CocoModel onLoaded: -> super() @set 'js', @compile(@get 'code') unless @get 'js' + SystemNameLoader.setName @ compile: (code) -> if @get('language') and @get('language') isnt 'coffeescript' diff --git a/app/models/Patch.coffee b/app/models/Patch.coffee index c505c93c0..3416ee44d 100644 --- a/app/models/Patch.coffee +++ b/app/models/Patch.coffee @@ -2,10 +2,11 @@ CocoModel = require('./CocoModel') module.exports = class PatchModel extends CocoModel @className: "Patch" - urlRoot: "/db/patch" - + @schema: require 'schemas/models/patch' + urlRoot: "/db/patch" + setStatus: (status) -> PatchModel.setStatus @id, status - + @setStatus: (id, status) -> - $.ajax("/db/patch/#{id}/status", {type:"PUT", data: {status:status}}) \ No newline at end of file + $.ajax("/db/patch/#{id}/status", {type:"PUT", data: {status:status}}) diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee index 281a31c2d..21cd1fadd 100644 --- a/app/models/ThangType.coffee +++ b/app/models/ThangType.coffee @@ -5,6 +5,7 @@ buildQueue = [] module.exports = class ThangType extends CocoModel @className: "ThangType" + @schema: require 'schemas/models/thang_type' urlRoot: "/db/thang.type" building: {} diff --git a/app/models/User.coffee b/app/models/User.coffee index 9f688f46b..a80ad8f14 100644 --- a/app/models/User.coffee +++ b/app/models/User.coffee @@ -4,10 +4,12 @@ CocoModel = require('./CocoModel') module.exports = class User extends CocoModel @className: "User" + @schema: require 'schemas/models/user' urlRoot: "/db/user" initialize: -> super() + @migrateEmails() isAdmin: -> permissions = @attributes['permissions'] or [] @@ -42,3 +44,33 @@ module.exports = class User extends CocoModel ) cache[id] = user user + + getEnabledEmails: -> + @migrateEmails() + emails = _.clone(@get('emails')) or {} + emails = _.defaults emails, @schema().properties.emails.default + (emailName for emailName, emailDoc of emails when emailDoc.enabled) + + setEmailSubscription: (name, enabled) -> + newSubs = _.clone(@get('emails')) or {} + (newSubs[name] ?= {}).enabled = enabled + @set 'emails', newSubs + + emailMap: + announcement: 'generalNews' + developer: 'archmageNews' + tester: 'adventurerNews' + level_creator: 'artisanNews' + article_editor: 'scribeNews' + translator: 'diplomatNews' + support: 'ambassadorNews' + notification: 'anyNotes' + + migrateEmails: -> + return if @attributes.emails or not @attributes.emailSubscriptions + oldSubs = @get('emailSubscriptions') or [] + newSubs = {} + newSubs[newSubName] = { enabled: oldSubName in oldSubs } for oldSubName, newSubName of @emailMap + @set('emails', newSubs) + + isEmailSubscriptionEnabled: (name) -> (@get('emails') or {})[name]?.enabled diff --git a/app/schemas/models/level.coffee b/app/schemas/models/level.coffee index 7180c6a67..0daf000a2 100644 --- a/app/schemas/models/level.coffee +++ b/app/schemas/models/level.coffee @@ -1,5 +1,5 @@ c = require './../schemas' -ThangComponentSchema = require './../models/thang_component' +ThangComponentSchema = require './thang_component' SpecificArticleSchema = c.object() c.extendNamedProperties SpecificArticleSchema # name first @@ -130,7 +130,7 @@ NoteGroupSchema = c.object {title: "Note Group", description: "A group of notes surface: c.object {title: "Surface", description: "Commands to issue to the Surface itself."}, focus: c.object {title: "Camera", description: "Focus the camera on a specific point on the Surface.", format:'viewport'}, - target: {anyOf: [PointSchema, thang, {type: 'null'}], title: "Target", description: "Where to center the camera view."} + target: {anyOf: [PointSchema, thang, {type: 'null'}], title: "Target", description: "Where to center the camera view.", default: {x:0, y:0}} zoom: {type: 'number', minimum: 0, exclusiveMinimum: true, maximum: 64, title: "Zoom", description: "What zoom level to use."} duration: {type:'number', minimum: 0, title: "Duration", description: "in ms"} bounds: c.array {title:'Boundary', maxItems: 2, minItems: 2, default:[{x:0,y:0}, {x:46, y:39}], format: 'bounds'}, PointSchema diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee index b91c4571b..4ec00f8c4 100644 --- a/app/schemas/models/user.coffee +++ b/app/schemas/models/user.coffee @@ -20,7 +20,20 @@ UserSchema = c.object {}, autocastDelay: {type: 'integer', 'default': 5000 } lastLevel: { type: 'string' } - emailSubscriptions: c.array {uniqueItems: true, 'default': ['announcement', 'notification']}, {'enum': emailSubscriptions} + emailSubscriptions: c.array {uniqueItems: true}, {'enum': emailSubscriptions} + emails: c.object {title: "Email Settings", default: {generalNews: {enabled:true}, anyNotes: {enabled:true}, recruitNotes: {enabled:true}}}, + # newsletters + generalNews: { $ref: '#/definitions/emailSubscription' } + adventurerNews: { $ref: '#/definitions/emailSubscription' } + ambassadorNews: { $ref: '#/definitions/emailSubscription' } + archmageNews: { $ref: '#/definitions/emailSubscription' } + artisanNews: { $ref: '#/definitions/emailSubscription' } + diplomatNews: { $ref: '#/definitions/emailSubscription' } + scribeNews: { $ref: '#/definitions/emailSubscription' } + + # notifications + anyNotes: { $ref: '#/definitions/emailSubscription' } # overrides any other notifications settings + recruitNotes: { $ref: '#/definitions/emailSubscription' } # server controlled permissions: c.array {'default': []}, c.shortString() @@ -99,4 +112,10 @@ UserSchema = c.object {}, c.extendBasicProperties UserSchema, 'user' +c.definitions = + emailSubscription = + enabled: {type: 'boolean'} + lastSent: c.date() + count: {type: 'integer'} + module.exports = UserSchema diff --git a/app/styles/account/settings.sass b/app/styles/account/settings.sass index ae607c086..9780b6c50 100644 --- a/app/styles/account/settings.sass +++ b/app/styles/account/settings.sass @@ -43,6 +43,12 @@ .form max-width: 600px + + #email-pane + #specific-notification-settings + padding-left: 20px + margin-left: 20px + border-left: 1px solid gray #job-profile-view .profile-preview-button @@ -79,10 +85,6 @@ padding-top: 6px .treema-image-file - .btn:after - content: "Upload Picture" - margin-left: 20px - img display: block clear: both diff --git a/app/styles/editor/level/components_tab.sass b/app/styles/editor/level/components_tab.sass index c70a5f4d6..2903a25e3 100644 --- a/app/styles/editor/level/components_tab.sass +++ b/app/styles/editor/level/components_tab.sass @@ -1,6 +1,14 @@ #editor-level-components-tab-view h3 margin-top: 0 + @media screen and (max-width: 800px) + display: none + + .toggle + padding: 6px 8px + z-index: 11 + margin-top: 1px + margin-left: 2px .components-container position: absolute @@ -16,6 +24,9 @@ .treema-children .treema-row * cursor: pointer !important + + #components-treema + z-index: 11 .edit-component-container margin-left: 290px @@ -24,7 +35,15 @@ left: 0px top: 0 bottom: 0 - + @media screen and (max-width: 800px) + margin-left: 0px + + .nav-tabs + margin-left: 80px + + li + z-index: 11 + .treema-root position: absolute top: 35px @@ -37,3 +56,18 @@ position: absolute top: 0 right: 0 + left: auto + @media screen and (max-width: 800px) + left: 40px + top: 1px + bottom: auto + padding: 8px 10px + .text + display: block + @media screen and (max-width: 800px) + display: none + [class^='icon-'] + display: none + @media screen and (max-width: 800px) + display: block + diff --git a/app/styles/editor/level/edit.sass b/app/styles/editor/level/edit.sass index 02ff286c8..09bb03fe0 100644 --- a/app/styles/editor/level/edit.sass +++ b/app/styles/editor/level/edit.sass @@ -1,6 +1,6 @@ #editor-level-view &, #level-editor-top-nav - min-width: 1024px + // min-width: 1024px a font-family: helvetica, arial, sans serif @@ -13,7 +13,27 @@ $BG: rgba(228, 207, 140, 1.0) $NAVBG: #2f261d - + + .dropdown-menu + position: absolute + background-color: #FFF + border: 1px solid rgba(0, 0, 0, 0.15) + border-radius: 4px + box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176) + left: 0px + right: auto + + li a + color: #555 + padding: 3px 20px + + .navbar-nav + float: left + margin: 0 + + > li + float: left + li.navbar-btn margin-right: 5px @@ -29,6 +49,11 @@ .navbar-right // not sure why bootstrap puts a big negative margin in, but this overrides it margin-right: 10px + float: right + + .dropdown-menu + right: 0px + left: auto // custom navbar styling .navbar-brand @@ -40,15 +65,46 @@ border-right: 2px solid lighten($NAVBG, 20%) background: lighten($NAVBG, 10%) margin-left: 20px + float: left .nav-tabs margin-left: 5px border-bottom: 0 !important + + li + float: left + display: block + + @media only screen and (max-width: 800px) + + li + float: none + display: none + z-index: 12 + + a + background-color: $BG + border-color: darken($BG, 50%) + border-width: 0px 1px + border-radius: 0px + + li:first-child > a + border-radius: 5px 5px 0px 0px + border-top-width: 1px + + li:last-child > a + border-radius: 0px 0px 5px 5px + border-bottom-width: 1px + + li.active + display: block + .active > a, .active > a:hover, .active > a:focus background-color: $BG !important border-color: darken($BG, 50%) border-bottom: 0 a padding: 7px 5px !important + .dropdown-menu a cursor: pointer &:hover diff --git a/app/styles/editor/level/scripts_tab.sass b/app/styles/editor/level/scripts_tab.sass index b0a308e59..a74bacdfa 100644 --- a/app/styles/editor/level/scripts_tab.sass +++ b/app/styles/editor/level/scripts_tab.sass @@ -1,5 +1,11 @@ #editor-level-scripts-tab-view + .toggle + z-index: 11 + margin-top: -10px + margin-left: -10px + float: left + .treema-script cursor: pointer @@ -9,9 +15,15 @@ bottom: 0 width: 250px overflow: scroll + @media screen and (max-width: 800px) + top: 40px + z-index: 11 #script-treema margin-left: 290px max-height: 100% overflow: scroll box-sizing: border-box + @media screen and (max-width: 800px) + margin-left: 30px + top: -50px diff --git a/app/styles/editor/level/settings_tab.sass b/app/styles/editor/level/settings_tab.sass index 81b0f8a97..613881b66 100644 --- a/app/styles/editor/level/settings_tab.sass +++ b/app/styles/editor/level/settings_tab.sass @@ -1,2 +1,5 @@ #editor-level-settings-tab-view color: black + + .treema-value img + width: 100% \ No newline at end of file diff --git a/app/styles/editor/level/systems_tab.sass b/app/styles/editor/level/systems_tab.sass index 0d1aa6b33..c74f79be9 100644 --- a/app/styles/editor/level/systems_tab.sass +++ b/app/styles/editor/level/systems_tab.sass @@ -1,6 +1,14 @@ #editor-level-systems-tab-view h3 margin-top: 0 + @media screen and (max-width: 800px) + display: none + + .toggle + padding: 6px 8px + z-index: 11 + margin-top: 0px + margin-left: 2px .systems-container position: absolute @@ -13,6 +21,9 @@ bottom: 0 width: 250px overflow: scroll + @media screen and (max-width: 800px) + z-index: 10 + bottom: -35px .treema-children .treema-row * cursor: pointer !important @@ -21,6 +32,21 @@ position: absolute bottom: 0 left: 170px + top: auto + @media screen and (max-width: 800px) + left: 40px + top: 1px + bottom: auto + padding: 8px 10px + + .text + display: block + @media screen and (max-width: 800px) + display: none + [class^='icon-'] + display: none + @media screen and (max-width: 800px) + display: block .edit-system-container margin-left: 290px @@ -29,6 +55,14 @@ left: 0px top: 0 bottom: 0 + @media screen and (max-width: 800px) + margin-left: 0px + + .nav-tabs + margin-left: 120px + + li + z-index: 11 .treema-root position: absolute @@ -42,3 +76,17 @@ position: absolute top: 0 right: 0 + left: auto + @media screen and (max-width: 800px) + left: 80px + top: 1px + bottom: auto + padding: 8px 10px + .text + display: block + @media screen and (max-width: 800px) + display: none + [class^='icon-'] + display: none + @media screen and (max-width: 800px) + display: block diff --git a/app/styles/editor/level/thangs_tab.sass b/app/styles/editor/level/thangs_tab.sass index 9edfe6958..e37db3036 100644 --- a/app/styles/editor/level/thangs_tab.sass +++ b/app/styles/editor/level/thangs_tab.sass @@ -1,5 +1,7 @@ @import "../../bootstrap/mixins" - + +$mobile: 1050px + #editor-level-thangs-tab-view $addPaletteIconColumns: 3 $extantThangsWidth: 300px @@ -8,12 +10,60 @@ $addPaletteIconMargin: 2px $addPaletteWidth: ($addPaletteIconWidth + 2 * $addPaletteIconPadding + 2 * $addPaletteIconMargin) * $addPaletteIconColumns + 20 + #toggle + display: none + position: absolute + z-index: 11 + left: -14px + @media screen and (max-width: $mobile) + display: block + + .toggle + left: 0 + + .toggle + display: none + float: none + z-index: 11 + position: absolute + right: -14px + z-index: 11 + margin: 0 + padding: 8px + @media screen and (max-width: $mobile) + display: block + + .thangs-column + background-color: #E4CF8C + + @media screen and (max-width: $mobile) + display: block + + h3 + @media screen and (max-width: $mobile) + display: none + + #all-thangs + display: block + @media screen and (max-width: $mobile) + display: none + .thangs-container width: $extantThangsWidth position: absolute left: 0 top: 0 bottom: 0 + z-index: 11 + @media screen and (max-width: $mobile) + width: auto + left: 18px + bottom: -18px + + .btn-group + margin: 0 + @media screen and (max-width: $mobile) + margin: 5px h3 margin: 0 -20px 0 0 @@ -25,6 +75,10 @@ right: 0 bottom: 0 overflow: scroll + margin: 0 + @media screen and (max-width: $mobile) + margin: 5px + top: 40px &.hide-except-Unit .treema-node @@ -62,11 +116,15 @@ .world-container margin-left: $extantThangsWidth margin-right: $addPaletteWidth + @media screen and (max-width: $mobile) + margin-left: 0 + margin-right: 0 padding: 0 20px box-sizing: border-box h3 margin: 0 -10px 0 0 + text-align: center .add-thangs-palette width: $addPaletteWidth @@ -75,6 +133,20 @@ right: 0 top: 0 bottom: 0 + @media screen and (max-width: $mobile) + display: none + right: 18px + z-index: 11 + width: $addPaletteWidth + 10 + bottom: -15px + //height: auto + //padding-bottom: 10px + + input + width: $addPaletteWidth + margin: 0 + @media screen and (max-width: $mobile) + margin: 0 5px #thangs-list position: relative @@ -83,6 +155,9 @@ bottom: 10px overflow: scroll height: 100% + margin: 0 + @media screen and (max-width: $mobile) + margin: 0 5px h3 margin: 0 -20px 0 0 diff --git a/app/styles/employers.sass b/app/styles/employers.sass index 6e64b44a0..d0da4c1b2 100644 --- a/app/styles/employers.sass +++ b/app/styles/employers.sass @@ -11,7 +11,7 @@ &:first-child // Make sure that "Developer #56" doesn't wrap onto second row min-width: 110px - + .tablesorter-headerAsc background-color: #cfc @@ -27,3 +27,10 @@ margin: 2px 0 display: inline-block text-transform: lowercase + + td:nth-child(3) select + min-width: 100px + td:nth-child(6) select + min-width: 50px + td:nth-child(7) select + min-width: 100px diff --git a/app/styles/play/level.sass b/app/styles/play/level.sass index 03b78c558..7e39ca986 100644 --- a/app/styles/play/level.sass +++ b/app/styles/play/level.sass @@ -18,7 +18,7 @@ body.is-playing position: relative canvas#surface - background-color: #ddd + background-color: #333 width: 100% display: block z-index: 1 diff --git a/app/styles/treema-ext.sass b/app/styles/treema-ext.sass index 9e59b7773..be549724c 100644 --- a/app/styles/treema-ext.sass +++ b/app/styles/treema-ext.sass @@ -18,20 +18,6 @@ border: 3px inset rgba(0, 100, 100, 0.2) box-sizing: border-box padding: 5px - -.treema-node a.btn - height: 17px - display: inline-block - position: relative - width: 20px - padding: 0 - float: left - margin-right: 2px - - i - position: absolute - top: 1px - left: 3px .treema-selection-map position: fixed diff --git a/app/templates/account/profile.jade b/app/templates/account/profile.jade index fbd3e15f5..e2f5f32ea 100644 --- a/app/templates/account/profile.jade +++ b/app/templates/account/profile.jade @@ -105,7 +105,7 @@ block content li a(href=project.link) if project.picture - .project-image(style="background-image: url(/file/" + project.picture + ")") + .project-image(style="background-image: url('/file/" + project.picture + "')") p= project.name div!= marked(project.description) diff --git a/app/templates/account/settings.jade b/app/templates/account/settings.jade index 96179d5ba..89a1fe014 100644 --- a/app/templates/account/settings.jade +++ b/app/templates/account/settings.jade @@ -67,16 +67,28 @@ block content p .form .form-group.checkbox - label.control-label(for="email_announcement", data-i18n="account_settings.email_announcements") Announcements - input#email_announcement(name="email_announcement", type="checkbox", checked=subs.announcement) + label.control-label(for="email_generalNews", data-i18n="account_settings.email_announcements") Announcements + input#email_generalNews(name="email_generalNews", type="checkbox", checked=subs.generalNews) span.help-block(data-i18n="account_settings.email_announcements_description") Get emails on the latest news and developments at CodeCombat. - + + hr + h4(data-i18n="account_settings.email_notifications") Notifications + span Controls for transactional emails, ie emails specific to your account. + .form .form-group.checkbox - label.control-label(for="email_notification", data-i18n="account_settings.email_notifications") Notifications - input#email_notification(name="email_notification", type="checkbox", checked=subs.notification) - span.help-block(data-i18n="account_settings.email_notifications_description") Get periodic notifications for your account. - hr + label.control-label(for="email_anyNotes", data-i18n="account_settings.any_notifications") Any Notifications + input#email_anyNotes(name="email_anyNotes", type="checkbox", checked=subs.anyNotes) + span.help-block(data-i18n="account_settings.email_any_notes_description") Disable to universally stop ALL notifications for this account. + + fieldset#specific-notification-settings + + .form-group.checkbox + label.control-label(for="email_recruitNotes", data-i18n="account_settings.recruit_notes") Recruitment Opportunities + input#email_recruitNotes(name="email_recruitNotes", type="checkbox", checked=subs.recruitNotes) + span.help-block(data-i18n="account_settings.email_recruit_notes_description") If you play really well, we may contact you about getting you a (better) job. + + hr h4(data-i18n="account_settings.contributor_emails") Contributor Class Emails span(data-i18n="account_settings.contribute_prefix") We're looking for people to join our party! Check out the @@ -85,63 +97,63 @@ block content .form .form-group.checkbox - label.control-label(for="email_developer") + label.control-label(for="email_archmageNews") span(data-i18n="classes.archmage_title") | Archmage | span(data-i18n="classes.archmage_title_description") | (Coder) - input#email_developer(name="email_developer", type="checkbox", checked=subs.developer) + input#email_archmageNews(name="email_archmageNews", type="checkbox", checked=subs.archmageNews) span(data-i18n="contribute.archmage_subscribe_desc").help-block Get emails about general news and announcements about CodeCombat. .form-group.checkbox - label.control-label(for="email_level_creator") + label.control-label(for="email_artisanNews") span(data-i18n="classes.artisan_title") | Artisan | span(data-i18n="classes.artisan_title_description") | (Level Builder) - input#email_level_creator(name="email_level_creator", type="checkbox", checked=subs.level_creator) + input#email_artisanNews(name="email_artisanNews", type="checkbox", checked=subs.artisanNews) span(data-i18n="contribute.artisan_subscribe_desc").help-block Get emails on level editor updates and announcements. .form-group.checkbox - label.control-label(for="email_tester") + label.control-label(for="email_adventurerNews") span(data-i18n="classes.adventurer_title") | Adventurer | span(data-i18n="classes.adventurer_title_description") | (Level Playtester) - input#email_tester(name="email_tester", type="checkbox", checked=subs.tester) + input#email_adventurerNews(name="email_adventurerNews", type="checkbox", checked=subs.adventurerNews) span(data-i18n="contribute.adventurer_subscribe_desc").help-block Get emails when there are new levels to test. .form-group.checkbox - label.control-label(for="email_article_editor") + label.control-label(for="email_scribeNews") span(data-i18n="classes.scribe_title") | Scribe | span(data-i18n="classes.scribe_title_description") | (Article Editor) - input#email_article_editor(name="email_article_editor", type="checkbox", checked=subs.article_editor) + input#email_scribeNews(name="email_scribeNews", type="checkbox", checked=subs.scribeNews) span(data-i18n="contribute.scribe_subscribe_desc").help-block Get emails about article writing announcements. .form-group.checkbox - label.control-label(for="email_translator") + label.control-label(for="email_diplomatNews") span(data-i18n="classes.diplomat_title") | Diplomat | span(data-i18n="classes.diplomat_title_description") | (Translator) - input#email_translator(name="email_translator", type="checkbox", checked=subs.translator) + input#email_diplomatNews(name="email_diplomatNews", type="checkbox", checked=subs.diplomatNews) span(data-i18n="contribute.diplomat_subscribe_desc").help-block Get emails about i18n developments and, eventually, levels to translate. .form-group.checkbox - label.control-label(for="email_support") + label.control-label(for="email_ambassadorNews") span(data-i18n="classes.ambassador_title") | Ambassador | span(data-i18n="classes.ambassador_title_description") | (Support) - input#email_support(name="email_support", type="checkbox", checked=subs.support) + input#email_ambassadorNews(name="email_ambassadorNews", type="checkbox", checked=subs.ambassadorNews) span(data-i18n="contribute.ambassador_subscribe_desc").help-block Get emails on support updates and multiplayer developments. button.btn#toggle-all-button(data-i18n="account_settings.email_toggle") Toggle All diff --git a/app/templates/contribute/contribute.jade b/app/templates/contribute/contribute.jade index 800b383e7..d9457e6d8 100644 --- a/app/templates/contribute/contribute.jade +++ b/app/templates/contribute/contribute.jade @@ -171,7 +171,7 @@ block content | We are trying to build a community, and every community needs a support team when | there are troubles. We have got chats, emails, and social networks so that our users | can get acquainted with the game. If you want to help people get involved, have fun, - | and learn some programming, then this class is for you. + | and learn some programming, then this c lass is for you. a(href="/contribute/ambassador") p.lead(data-i18n="contribute.more_about_ambassador") diff --git a/app/templates/contribute/contributor_signup.jade b/app/templates/contribute/contributor_signup.jade index 2b9a8f188..cd47b26f4 100644 --- a/app/templates/contribute/contributor_signup.jade +++ b/app/templates/contribute/contributor_signup.jade @@ -1,5 +1,5 @@ -label.checkbox(for=contributorClassID).well - input(type='checkbox', name=contributorClassID, id=contributorClassID) +label.checkbox(for=contributorClassName).well + input(type='checkbox', name=contributorClassName, id=contributorClassName) span(data-i18n="contribute.#{contributorClassName}_subscribe_desc") .saved-notification ✓ Saved diff --git a/app/templates/editor/level/components_tab.jade b/app/templates/editor/level/components_tab.jade index 9cd86545e..3d62ca0ce 100644 --- a/app/templates/editor/level/components_tab.jade +++ b/app/templates/editor/level/components_tab.jade @@ -1,9 +1,13 @@ .components-container h3(data-i18n="editor.level_component_tab_title") Current Components + button.navbar-toggle.toggle.btn-primary(type="button" data-toggle="collapse" data-target="#components-treema") + span.icon-list #components-treema .edit-component-container if me.isAdmin() - button(data-i18n="editor.level_component_btn_new").btn.btn-primary#create-new-component-button-no-select Create New Component + button.btn.btn-primary#create-new-component-button-no-select + span.icon-plus + span.text(data-i18n="editor.level_component_btn_new") Create New Component #editor-level-component-edit-view diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade index 6b010912d..415ff9e20 100644 --- a/app/templates/editor/level/edit.jade +++ b/app/templates/editor/level/edit.jade @@ -15,8 +15,8 @@ block header li a(href="/editor/level") span.glyphicon-home.glyphicon + ul.nav.navbar-nav.nav-tabs - li.active a(href="#editor-level-thangs-tab-view", data-toggle="tab", data-i18n="editor.level_tab_thangs") Thangs li @@ -68,6 +68,8 @@ block header a(data-i18n="common.fork")#fork-level-start-button Fork li(class=anonymous ? "disabled": "") a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert + li(class=anonymous ? "disabled": "") + a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n li.divider li.dropdown-header Info li#level-history-button diff --git a/app/templates/editor/level/scripts_tab.jade b/app/templates/editor/level/scripts_tab.jade index 85618f619..b3b074f17 100644 --- a/app/templates/editor/level/scripts_tab.jade +++ b/app/templates/editor/level/scripts_tab.jade @@ -1,3 +1,6 @@ +button.navbar-toggle.toggle.btn-primary(type="button", data-toggle="collapse", data-target="#scripts-treema") + span.icon-list + #scripts-treema #script-treema diff --git a/app/templates/editor/level/systems_tab.jade b/app/templates/editor/level/systems_tab.jade index f09edb2c6..8cb062bac 100644 --- a/app/templates/editor/level/systems_tab.jade +++ b/app/templates/editor/level/systems_tab.jade @@ -1,11 +1,17 @@ .systems-container + button.navbar-toggle.toggle.btn-primary(type="button" data-toggle="collapse" data-target="#systems-treema") + span.icon-list h3(data-i18n="editor.level_systems_tab_title") Current Systems #systems-treema .edit-system-container if me.isAdmin() - button(data-i18n="editor.level_systems_btn_new").btn.btn-primary#create-new-system-button Create New System + button.btn.btn-primary#create-new-system-button + span.icon-file + span.text(data-i18n="editor.level_systems_btn_new") Create New System #editor-level-system-edit-view -button(data-i18n="editor.level_systems_btn_add").btn.btn-primary#add-system-button Add System +button.btn.btn-primary#add-system-button + span.icon-plus + span.text(data-i18n="editor.level_systems_btn_add") Add System \ No newline at end of file diff --git a/app/templates/editor/level/thangs_tab.jade b/app/templates/editor/level/thangs_tab.jade index c41c727b8..70dff55e0 100644 --- a/app/templates/editor/level/thangs_tab.jade +++ b/app/templates/editor/level/thangs_tab.jade @@ -1,4 +1,9 @@ -.thangs-container.thangs-column +div#toggle + button.navbar-toggle.toggle.btn-primary#thangs-container-toggle(type="button", data-toggle="collapse", data-target="#all-thangs") + span.icon-list +button.navbar-toggle.toggle.btn-primary#thangs-palette-toggle(type="button", data-toggle="collapse", data-target="#add-thangs-column") + span.icon-plus +.thangs-container.thangs-column#all-thangs h3(data-i18n="editor.level_tab_thangs_title") Current Thangs .btn-group(data-toggle="buttons-radio")#extant-thangs-filter button.btn.btn-primary(data-i18n="editor.level_tab_thangs_all") All diff --git a/app/templates/employers.jade b/app/templates/employers.jade index efeb59429..f69721ae4 100644 --- a/app/templates/employers.jade +++ b/app/templates/employers.jade @@ -27,7 +27,8 @@ block content th(data-i18n="employers.candidate_years_experience") Yrs Exp th(data-i18n="employers.candidate_last_updated") Last Updated if me.isAdmin() - th ✓? + th(data-i18n="employers.candidate_us") Us? + th(data-i18n="employers.candidate_them") Them? tbody for candidate, index in candidates @@ -52,9 +53,13 @@ block content code= skill span td= profile.experience - td= moment(profile.updated).fromNow() + td(data-profile-age=(new Date() - new Date(profile.updated)) / 86400 / 1000)= moment(profile.updated).fromNow() if me.isAdmin() if candidate.get('jobProfileApproved') td ✓ + else + td ✗ + if profile.active + td ✓ else td ✗ \ No newline at end of file diff --git a/app/templates/kinds/search.jade b/app/templates/kinds/search.jade index 77dce78db..2475710db 100644 --- a/app/templates/kinds/search.jade +++ b/app/templates/kinds/search.jade @@ -9,7 +9,7 @@ block content | #{currentEditor} if me.get('anonymous') - a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="modal/signup", role="button", data-i18n="editor.signup_to_create") Sign Up to Create a New Content + a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="modal/signup", role="button", data-i18n="#{currentNewSignup}") Sign Up to Create a New Content else a.btn.btn-primary.open-modal-button(href='#new-model-modal', role="button", data-toggle="modal", data-i18n="#{currentNew}") Create a New Something input#search(data-i18n="[placeholder]#{currentSearch}") diff --git a/app/treema-ext.coffee b/app/treema-ext.coffee index a52e1da91..044c7e6d4 100644 --- a/app/treema-ext.coffee +++ b/app/treema-ext.coffee @@ -1,5 +1,5 @@ CocoModel = require 'models/CocoModel' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' {me} = require('lib/auth') locale = require 'locale/locale' @@ -28,7 +28,7 @@ class LiveEditingMarkup extends TreemaNode.nodeMap.ace valEl.append( $('
').append( $('') - .addClass('btn') + .addClass('btn btn-sm btn-primary') .click(=> filepicker.pick @onFileChosen) ) ) @@ -70,19 +70,19 @@ class SoundFileTreema extends TreemaNode.nodeMap.string buildValueForDisplay: (valEl) -> mimetype = "audio/#{@keyForParent}" - pickButton = $('') + pickButton = $('') .click(=> filepicker.pick {mimetypes:[mimetype]}, @onFileChosen) - playButton = $('') + playButton = $('') .click(@playFile) - stopButton = $('') + stopButton = $('') .click(@stopFile) dropdown = $('') dropdownButton = $('') - .addClass('btn dropdown-toggle') + .addClass('btn btn-primary btn-xs dropdown-toggle') .attr('href', '#') - .append($('')) + .append($('')) .dropdown() dropdown.append dropdownButton @@ -107,7 +107,7 @@ class SoundFileTreema extends TreemaNode.nodeMap.string if @data valEl.append(playButton) valEl.append(stopButton) - valEl.append(dropdown) if files.length and @canEdit() + valEl.append(dropdown) # if files.length and @canEdit() if @data path = @data.split('/') name = path[path.length-1] @@ -168,7 +168,7 @@ class ImageFileTreema extends TreemaNode.nodeMap.string buildValueForDisplay: (valEl) -> mimetype = 'image/*' - pickButton = $('') + pickButton = $(' Upload Picture') .click(=> filepicker.pick {mimetypes:[mimetype]}, @onFileChosen) valEl.append(pickButton) @@ -233,6 +233,7 @@ class InternationalizationNode extends TreemaNode.nodeMap.object type: "object" properties: {} } + return i18nChildSchema unless @parent unless @schema.props? console.warn "i18n props array is empty! Filling with all parent properties by default" @schema.props = (prop for prop,_ of @parent.schema.properties when prop isnt "i18n") diff --git a/app/views/account/profile_view.coffee b/app/views/account/profile_view.coffee index 854f9e985..3c269657e 100644 --- a/app/views/account/profile_view.coffee +++ b/app/views/account/profile_view.coffee @@ -59,11 +59,11 @@ module.exports = class ProfileView extends View iconForLink: (link) -> icons = [ - {icon: 'facebook', name: 'Facebook', domain: 'facebook.com', match: /facebook/i} - {icon: 'twitter', name: 'Twitter', domain: 'twitter.com', match: /twitter/i} - {icon: 'github', name: 'GitHub', domain: 'github.com', match: /github/i} - {icon: 'gplus', name: 'Google Plus', domain: 'plus.google.com', match: /(google|^g).?(\+|plus)/i} - {icon: 'linkedin', name: 'LinkedIn', domain: 'linkedin.com', match: /(google|^g).?(\+|plus)/i} + {icon: 'facebook', name: 'Facebook', domain: /facebook\.com/, match: /facebook/i} + {icon: 'twitter', name: 'Twitter', domain: /twitter\.com/, match: /twitter/i} + {icon: 'github', name: 'GitHub', domain: /github\.(com|io)/, match: /github/i} + {icon: 'gplus', name: 'Google Plus', domain: /plus\.google\.com/, match: /(google|^g).?(\+|plus)/i} + {icon: 'linkedin', name: 'LinkedIn', domain: /linkedin\.com/, match: /(google|^g).?(\+|plus)/i} ] for icon in icons if (link.name.search(icon.match) isnt -1) or (link.link.search(icon.domain) isnt -1) diff --git a/app/views/account/settings_view.coffee b/app/views/account/settings_view.coffee index 16ea6b059..ea3d7b0a4 100644 --- a/app/views/account/settings_view.coffee +++ b/app/views/account/settings_view.coffee @@ -65,20 +65,19 @@ module.exports = class SettingsView extends View c = super() return c unless me c.subs = {} - c.subs[sub] = 1 for sub in c.me.get('emailSubscriptions') or ['announcement', 'notification', 'tester', 'level_creator', 'developer'] + c.subs[sub] = 1 for sub in c.me.getEnabledEmails() c.showsJobProfileTab = me.isAdmin() or me.get('jobProfile') or location.hash.search('job-profile-') isnt -1 c getSubscriptions: -> - inputs = $('#email-pane input[type="checkbox"]', @$el) - inputs = ($(i) for i in inputs) - subs = (i.attr('name') for i in inputs when i.prop('checked')) - subs = (s.replace('email_', '') for s in subs) - subs + inputs = ($(i) for i in $('#email-pane input[type="checkbox"].changed', @$el)) + emailNames = (i.attr('name').replace('email_', '') for i in inputs) + enableds = (i.prop('checked') for i in inputs) + _.zipObject emailNames, enableds toggleEmailSubscriptions: => subs = @getSubscriptions() - $('#email-pane input[type="checkbox"]', @$el).prop('checked', not Boolean(subs.length)) + $('#email-pane input[type="checkbox"]', @$el).prop('checked', not _.any(_.values(subs))).addClass('changed') @save() buildPictureTreema: -> @@ -102,7 +101,8 @@ module.exports = class SettingsView extends View @trigger 'change' @$el.find('.gravatar-fallback').toggle not me.get 'photoURL' - save: -> + save: (e) -> + $(e.target).addClass('changed') if e forms.clearFormAlerts(@$el) @grabData() res = me.validate() @@ -143,7 +143,8 @@ module.exports = class SettingsView extends View grabOtherData: -> me.set 'name', $('#name', @$el).val() me.set 'email', $('#email', @$el).val() - me.set 'emailSubscriptions', @getSubscriptions() + for emailName, enabled of @getSubscriptions() + me.setEmailSubscription emailName, enabled me.set 'photoURL', @pictureTreema.get('/photoURL') adminCheckbox = @$el.find('#admin') diff --git a/app/views/contribute/contribute_class_view.coffee b/app/views/contribute/contribute_class_view.coffee index 246499694..d9110c3fd 100644 --- a/app/views/contribute/contribute_class_view.coffee +++ b/app/views/contribute/contribute_class_view.coffee @@ -21,30 +21,23 @@ module.exports = class ContributeClassView extends View 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') + context = me: me, 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() _.forEach checkboxes, (el) -> el = $(el) - if el.attr('name') in me.get('emailSubscriptions') - el.prop('checked', true) + el.prop('checked', true) if me.isEmailSubscriptionEnabled(el.attr('name')+'News') onCheckboxChanged: (e) -> el = $(e.target) checked = el.prop('checked') subscription = el.attr('name') - subscriptions = me.get('emailSubscriptions') ? [] - if checked and not (subscription in subscriptions) - subscriptions.push(subscription) - if me.get 'anonymous' - @openModalView new SignupModalView() - if not checked - subscriptions = _.without subscriptions, subscription + + me.setEmailSubscription subscription+'News', checked + me.save() + @openModalView new SignupModalView() if me.get 'anonymous' el.parent().find('.saved-notification').finish().show('fast').delay(3000).fadeOut(2000) - me.set('emailSubscriptions', subscriptions) - me.save() - contributors: [] diff --git a/app/views/editor/components/main.coffee b/app/views/editor/components/main.coffee index 29eee1b06..6a2b3c617 100644 --- a/app/views/editor/components/main.coffee +++ b/app/views/editor/components/main.coffee @@ -153,17 +153,18 @@ module.exports = class ThangComponentEditView extends CocoView @reportChanges() onAddComponentEnterPressed: (node) => - extantSystems = - (@supermodel.getModelByOriginalAndMajorVersion LevelSystem, sn.original, sn.majorVersion).attributes.name.toLowerCase() for idx, sn of @level.get('systems') - requireSystem = node.data.system.toLowerCase() + if extantSystems + extantSystems = + (@supermodel.getModelByOriginalAndMajorVersion LevelSystem, sn.original, sn.majorVersion).attributes.name.toLowerCase() for idx, sn of @level.get('systems') + requireSystem = node.data.system.toLowerCase() - if requireSystem not in extantSystems - warn_element = 'Component ' + node.data.name + ' requires system ' + requireSystem + ' which is currently not specified in this level.' - noty({ - text: warn_element, - layout: 'bottomLeft', - type: 'warning' - }) + if requireSystem not in extantSystems + warn_element = 'Component ' + node.data.name + ' requires system ' + requireSystem + ' which is currently not specified in this level.' + noty({ + text: warn_element, + layout: 'bottomLeft', + type: 'warning' + }) currentSelection = @addComponentsTreema?.getLastSelectedTreema()?.data._id diff --git a/app/views/editor/level/add_thangs_view.coffee b/app/views/editor/level/add_thangs_view.coffee index 9c64a9ab5..527224cfe 100644 --- a/app/views/editor/level/add_thangs_view.coffee +++ b/app/views/editor/level/add_thangs_view.coffee @@ -1,7 +1,7 @@ View = require 'views/kinds/CocoView' add_thangs_template = require 'templates/editor/level/add_thangs' ThangType = require 'models/ThangType' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' class ThangTypeSearchCollection extends CocoCollection url: '/db/thang.type/search?project=true' diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee index 66537bd2e..d5c1764a6 100644 --- a/app/views/editor/level/edit.coffee +++ b/app/views/editor/level/edit.coffee @@ -30,13 +30,8 @@ module.exports = class EditorLevelView extends View 'click #patches-tab': -> @patchesView.load() 'click #level-patch-button': 'startPatchingLevel' 'click #level-watch-button': 'toggleWatchLevel' - - subscriptions: - 'refresh-level-editor': 'rerenderAllViews' - - rerenderAllViews: -> - for view in [@thangsTab, @settingsTab, @scriptsTab, @componentsTab, @systemsTab, @patchesView] - view.render() + 'click #pop-level-i18n-button': -> @level.populateI18N() + 'mouseup .nav-tabs > li a': 'toggleTab' constructor: (options, @levelID) -> super options @@ -136,3 +131,13 @@ module.exports = class EditorLevelView extends View button = @$el.find('#level-watch-button') @level.watch(button.find('.watch').is(':visible')) button.find('> span').toggleClass('secret') + + toggleTab: (e) -> + return unless $(document).width() <= 800 + li = $(e.target).closest('li') + if li.hasClass('active') + li.parent().find('li').show() + else + li.parent().find('li').hide() + li.show() + console.log li.hasClass('active') diff --git a/app/views/editor/level/system/add.coffee b/app/views/editor/level/system/add.coffee index a106e3d39..64caa52b4 100644 --- a/app/views/editor/level/system/add.coffee +++ b/app/views/editor/level/system/add.coffee @@ -2,7 +2,7 @@ View = require 'views/kinds/ModalView' template = require 'templates/editor/level/system/add' availableSystemTemplate = require 'templates/editor/level/system/available_system' LevelSystem = require 'models/LevelSystem' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' class LevelSystemSearchCollection extends CocoCollection url: '/db/level_system/search' diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee index 6e31e17c9..b878347a1 100644 --- a/app/views/editor/level/thangs_tab_view.coffee +++ b/app/views/editor/level/thangs_tab_view.coffee @@ -4,7 +4,7 @@ thangs_template = require 'templates/editor/level/thangs_tab' Level = require 'models/Level' ThangType = require 'models/ThangType' LevelComponent = require 'models/LevelComponent' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' {isObjectID} = require 'models/CocoModel' Surface = require 'lib/surface/Surface' Thang = require 'lib/world/thang' @@ -50,6 +50,9 @@ module.exports = class ThangsTabView extends View 'click #extant-thangs-filter button': 'onFilterExtantThangs' 'click #delete': 'onDeleteClicked' 'click #duplicate': 'onDuplicateClicked' + 'click #thangs-container-toggle': 'toggleThangsContainer' + 'click #thangs-palette-toggle': 'toggleThangsPalette' + 'click .add-thang-palette-icon': 'toggleThangsPalette' shortcuts: 'esc': 'selectAddThang' @@ -112,7 +115,11 @@ module.exports = class ThangsTabView extends View $('#thangs-list').height('100%') thangsHeaderHeight = $('#thangs-header').height() oldHeight = $('#thangs-list').height() - $('#thangs-list').height(oldHeight - thangsHeaderHeight - 80) + if $(document).width() < 1050 + $('#thangs-list').height(oldHeight - thangsHeaderHeight - 40) + else + $('#thangs-list').height(oldHeight - thangsHeaderHeight - 80) + afterRender: -> super() @@ -450,6 +457,14 @@ module.exports = class ThangsTabView extends View thang = @selectedExtantThang.spriteName e.target = $(".add-thang-palette-icon[data-thang-type='" + thang + "']").get 0 @selectAddThang e + + toggleThangsContainer: (e) -> + $('#all-thangs').toggle() + + toggleThangsPalette: (e) -> + $('#add-thangs-column').toggle() + @onWindowResize e + class ThangsNode extends TreemaNode.nodeMap.array valueClass: 'treema-array-replacement' diff --git a/app/views/editor/level/treema_nodes.coffee b/app/views/editor/level/treema_nodes.coffee index fda09a79b..f968e2446 100644 --- a/app/views/editor/level/treema_nodes.coffee +++ b/app/views/editor/level/treema_nodes.coffee @@ -1,7 +1,7 @@ WorldSelectModal = require './modal/world_select' ThangType = require '/models/ThangType' -makeButton = -> $('') +makeButton = -> $('') shorten = (f) -> parseFloat(f.toFixed(1)) WIDTH = 1848 @@ -13,11 +13,11 @@ module.exports.WorldPointNode = class WorldPointNode extends TreemaNode.nodeMap. buildValueForDisplay: (valEl) -> super(valEl) - valEl.prepend(makeButton()) + valEl.find('.treema-shortened').prepend(makeButton()) buildValueForEditing: (valEl) -> super(valEl) - valEl.prepend(makeButton()) + valEl.find('.treema-shortened').prepend(makeButton()) onClick: (e) -> btn = $(e.target).closest('.treema-map-button') @@ -44,11 +44,11 @@ class WorldRegionNode extends TreemaNode.nodeMap.object buildValueForDisplay: (valEl) -> super(valEl) - valEl.prepend(makeButton()) + valEl.find('.treema-shortened').prepend(makeButton()) buildValueForEditing: (valEl) -> super(valEl) - valEl.prepend(makeButton()) + valEl.find('.treema-shortened').prepend(makeButton()) onClick: (e) -> btn = $(e.target).closest('.treema-map-button') @@ -80,11 +80,11 @@ module.exports.WorldViewportNode = class WorldViewportNode extends TreemaNode.no buildValueForDisplay: (valEl) -> super(valEl) - valEl.prepend(makeButton()) + valEl.find('.treema-shortened').prepend(makeButton()) buildValueForEditing: (valEl) -> super(valEl) - valEl.prepend(makeButton()) + valEl.find('.treema-shortened').prepend(makeButton()) onClick: (e) -> btn = $(e.target).closest('.treema-map-button') @@ -121,11 +121,11 @@ module.exports.WorldBoundsNode = class WorldBoundsNode extends TreemaNode.nodeMa buildValueForDisplay: (valEl) -> super(valEl) - valEl.prepend(makeButton()) + valEl.find('.treema-shortened').prepend(makeButton()) buildValueForEditing: (valEl) -> super(valEl) - valEl.prepend(makeButton()) + valEl.find('.treema-shortened').prepend(makeButton()) onClick: (e) -> btn = $(e.target).closest('.treema-map-button') diff --git a/app/views/employers_view.coffee b/app/views/employers_view.coffee index cdbf8f074..19c57aed2 100644 --- a/app/views/employers_view.coffee +++ b/app/views/employers_view.coffee @@ -2,7 +2,7 @@ View = require 'views/kinds/RootView' template = require 'templates/employers' app = require 'application' User = require 'models/User' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' EmployerSignupView = require 'views/modal/employer_signup_modal' class CandidatesCollection extends CocoCollection @@ -56,27 +56,105 @@ module.exports = class EmployersView extends View even: "" # odd row zebra striping odd: "" # even row zebra striping + + # e = exact text from cell + # n = normalized value returned by the column parser + # f = search filter input value + # i = column index + # $r = ??? + filterSelectExactMatch = (e, n, f, i, $r) -> e is f + # call the tablesorter plugin and apply the uitheme widget - @$el.find(".tablesorter").tablesorter( + @$el.find(".tablesorter").tablesorter theme: "bootstrap" widthFixed: true headerTemplate: "{content} {icon}" + textSorter: + 6: (a, b, direction, column, table) -> + days = [] + for s in [a, b] + n = parseInt s + n = 0 unless _.isNumber n + for [duration, factor] in [ + [/second/i, 1 / (86400 * 1000)] + [/minute/i, 1 / 1440] + [/hour/i, 1 / 24] + [/week/i, 7] + [/month/i, 30.42] + [/year/i, 365.2425] + ] + if duration.test s + n *= factor + break + if /^in /i.test s + n *= -1 + days.push n + days[0] - days[1] + sortList: [[6, 0]] # widget code contained in the jquery.tablesorter.widgets.js file # use the zebra stripe widget if you plan on hiding any rows (filter widget) - widgets: [ - "uitheme" - "zebra" - ] + widgets: ["uitheme", "zebra", "filter"] widgetOptions: # using the default zebra striping class name, so it actually isn't included in the theme variable above # this is ONLY needed for bootstrap theming if you are using the filter widget, because rows are hidden - zebra: [ - "even" - "odd" - ] - # reset filters button + zebra: ["even", "odd"] + + # extra css class applied to the table row containing the filters & the inputs within that row + filter_cssFilter: "" + + # If there are child rows in the table (rows with class name from "cssChildRow" option) + # and this option is true and a match is found anywhere in the child row, then it will make that row + # visible; default is false + filter_childRows: false + + # if true, filters are collapsed initially, but can be revealed by hovering over the grey bar immediately + # below the header row. Additionally, tabbing through the document will open the filter row when an input gets focus + filter_hideFilters: false + + # Set this option to false to make the searches case sensitive + filter_ignoreCase: true + + # jQuery selector string of an element used to reset the filters filter_reset: ".reset" - ) + + # Use the $.tablesorter.storage utility to save the most recent filters + filter_saveFilters: true + + # Delay in milliseconds before the filter widget starts searching; This option prevents searching for + # every character while typing and should make searching large tables faster. + filter_searchDelay: 150 + + # Set this option to true to use the filter to find text from the start of the column + # So typing in "a" will find "albert" but not "frank", both have a's; default is false + filter_startsWith: false + + filter_functions: + 2: + "Full-time": filterSelectExactMatch + "Part-time": filterSelectExactMatch + "Contracting": filterSelectExactMatch + "Remote": filterSelectExactMatch + "Internship": filterSelectExactMatch + 5: + "0-1": (e, n, f, i, $r) -> n <= 1 + "2-5": (e, n, f, i, $r) -> 2 <= n <= 5 + "6+": (e, n, f, i, $r) -> 6 <= n + 6: + "Last day": (e, n, f, i, $r) -> + days = parseFloat $($r.find('td')[i]).data('profile-age') + days <= 1 + "Last week": (e, n, f, i, $r) -> + days = parseFloat $($r.find('td')[i]).data('profile-age') + days <= 7 + "Last 4 weeks": (e, n, f, i, $r) -> + days = parseFloat $($r.find('td')[i]).data('profile-age') + days <= 28 + 7: + "✓": filterSelectExactMatch + "✗": filterSelectExactMatch + 8: + "✓": filterSelectExactMatch + "✗": filterSelectExactMatch onCandidateClicked: (e) -> id = $(e.target).closest('tr').data('candidate-id') diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee index ca661bdfa..471eb071a 100644 --- a/app/views/kinds/CocoView.coffee +++ b/app/views/kinds/CocoView.coffee @@ -41,6 +41,7 @@ module.exports = class CocoView extends Backbone.View @subviews = {} @listenToShortcuts() @updateProgressBar = _.debounce @updateProgressBar, 100 + @toggleModal = _.debounce @toggleModal, 100 # Backbone.Mediator handles subscription setup/teardown automatically @listenToOnce(@supermodel, 'loaded-all', @onLoaded) @@ -138,7 +139,6 @@ module.exports = class CocoView extends Backbone.View # Modals toggleModal: (e) -> - return if visibleModal if $(e.currentTarget).prop('target') is '_blank' return true # special handler for opening modals that are dynamically loaded, rather than static in the page. It works (or should work) like Bootstrap's modals, except use coco-modal for the data-toggle value. diff --git a/app/views/kinds/SearchView.coffee b/app/views/kinds/SearchView.coffee index 9ce303b7c..0b1a2e979 100644 --- a/app/views/kinds/SearchView.coffee +++ b/app/views/kinds/SearchView.coffee @@ -32,14 +32,17 @@ module.exports = class SearchView extends View when 'Level' context.currentEditor = 'editor.level_title' context.currentNew = 'editor.new_level_title' + context.currentNewSignup = 'editor.new_level_title_signup' context.currentSearch = 'editor.level_search_title' when 'Thang Type' context.currentEditor = 'editor.thang_title' context.currentNew = 'editor.new_thang_title' + context.currentNewSignup = 'editor.new_thang_title_signup' context.currentSearch = 'editor.thang_search_title' when 'Article' context.currentEditor = 'editor.article_title' context.currentNew = 'editor.new_article_title' + context.currentNewSignup = 'editor.new_article_title_signup' context.currentSearch = 'editor.article_search_title' @$el.i18n() context diff --git a/app/views/modal/diplomat_suggestion_modal.coffee b/app/views/modal/diplomat_suggestion_modal.coffee index 35d173c57..511fe369a 100644 --- a/app/views/modal/diplomat_suggestion_modal.coffee +++ b/app/views/modal/diplomat_suggestion_modal.coffee @@ -11,8 +11,7 @@ module.exports = class DiplomatSuggestionView extends View "click #subscribe-button": "subscribeAsDiplomat" subscribeAsDiplomat: -> - currentSubscriptions = me.get("emailSubscriptions") - me.set("emailSubscriptions", currentSubscriptions.concat ["translator"]) if "translator" not in currentSubscriptions + me.setEmailSubscription 'diplomatNews', true me.save() $("#email_translator").prop("checked", 1) @hide() diff --git a/app/views/modal/signup_modal.coffee b/app/views/modal/signup_modal.coffee index 63174261f..6a6ee2646 100644 --- a/app/views/modal/signup_modal.coffee +++ b/app/views/modal/signup_modal.coffee @@ -48,15 +48,12 @@ module.exports = class SignupModalView extends View userObject = forms.formToObject @$el delete userObject.subscribe delete userObject["confirm-age"] - for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emailSubscriptions"] + for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emails"] userObject[key] ?= val subscribe = @$el.find('#signup-subscribe').prop('checked') - userObject.emailSubscriptions ?= [] - if subscribe - userObject.emailSubscriptions.push 'announcement' unless 'announcement' in userObject.emailSubscriptions - userObject.emailSubscriptions.push 'notification' unless 'notification' in userObject.emailSubscriptions - else - userObject.emailSubscriptions = _.without (userObject.emailSubscriptions ? []), 'announcement', 'notification' + userObject.emails ?= {} + userObject.emails.generalNews ?= {} + userObject.emails.generalNews.enabled = subscribe res = tv4.validateMultiple userObject, User.schema return forms.applyErrorsToForm(@$el, res.errors) unless res.valid window.tracker?.trackEvent 'Finished Signup' diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/ladder_tab.coffee index a58a40479..090ec8d4d 100644 --- a/app/views/play/ladder/ladder_tab.coffee +++ b/app/views/play/ladder/ladder_tab.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' CocoClass = require 'lib/CocoClass' Level = require 'models/Level' LevelSession = require 'models/LevelSession' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' User = require 'models/User' LeaderboardCollection = require 'collections/LeaderboardCollection' {teamDataFromLevel} = require './utils' diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/my_matches_tab.coffee index e3f0fc62a..a725a1b16 100644 --- a/app/views/play/ladder/my_matches_tab.coffee +++ b/app/views/play/ladder/my_matches_tab.coffee @@ -35,7 +35,7 @@ module.exports = class MyMatchesTabView extends CocoView for session in @sessions.models for match in session.get('matches') or [] opponent = match.opponents[0] - @nameMap[opponent.userID] ?= nameMap[opponent.userID] + @nameMap[opponent.userID] ?= nameMap[opponent.userID].name @finishRendering() $.ajax('/db/user/-/names', { diff --git a/app/views/play/ladder_view.coffee b/app/views/play/ladder_view.coffee index 1f7eb9842..cea54bf46 100644 --- a/app/views/play/ladder_view.coffee +++ b/app/views/play/ladder_view.coffee @@ -1,7 +1,7 @@ RootView = require 'views/kinds/RootView' Level = require 'models/Level' LevelSession = require 'models/LevelSession' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' {teamDataFromLevel} = require './ladder/utils' {me} = require 'lib/auth' application = require 'application' diff --git a/app/views/play/level/modal/docs_modal.coffee b/app/views/play/level/modal/docs_modal.coffee index 88336fb64..294a9ae3c 100644 --- a/app/views/play/level/modal/docs_modal.coffee +++ b/app/views/play/level/modal/docs_modal.coffee @@ -24,7 +24,6 @@ module.exports = class DocsModal extends View general = (article.attributes for article in general when article) @docs = specific.concat(general) - marked.setOptions {gfm: true, sanitize: false, smartLists: true, breaks: false} @docs = $.extend(true, [], @docs) doc.html = marked(utils.i18n doc, 'body') for doc in @docs doc.name = (utils.i18n doc, 'name') for doc in @docs diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/playback_view.coffee index 191a00c22..8c0959130 100644 --- a/app/views/play/level/playback_view.coffee +++ b/app/views/play/level/playback_view.coffee @@ -112,7 +112,7 @@ module.exports = class PlaybackView extends View @$el.find('.toggle-fullscreen').hide() updatePopupContent: -> - @timePopup.updateContent "

#{@timeToString @newTime}

#{@formatTime(@current, @currentTime)}
#{@formatTime(@total, @totalTime)}" + @timePopup?.updateContent "

#{@timeToString @newTime}

#{@formatTime(@current, @currentTime)}
#{@formatTime(@total, @totalTime)}" # These functions could go to some helper class diff --git a/app/views/play/level/tome/cast_button_view.coffee b/app/views/play/level/tome/cast_button_view.coffee index 5b2f0e094..4b9608f94 100644 --- a/app/views/play/level/tome/cast_button_view.coffee +++ b/app/views/play/level/tome/cast_button_view.coffee @@ -74,16 +74,20 @@ module.exports = class CastButtonView extends View updateCastButton: -> return if _.some @spells, (spell) => not spell.loaded - castable = _.some @spells, (spell) => spell.hasChangedSignificantly spell.getSource() - @castButtonGroup.toggleClass('castable', castable).toggleClass('casting', @casting) - if @casting - s = $.i18n.t("play_level.tome_cast_button_casting", defaultValue: "Casting") - else if castable - s = $.i18n.t("play_level.tome_cast_button_castable", defaultValue: "Cast Spell") + " " + @castShortcut - else - s = $.i18n.t("play_level.tome_cast_button_cast", defaultValue: "Spell Cast") - @castButton.text s - @castButton.prop 'disabled', not castable + + async.some _.values(@spells), (spell, callback) => + spell.hasChangedSignificantly spell.getSource(), null, callback + , (castable) => + + @castButtonGroup.toggleClass('castable', castable).toggleClass('casting', @casting) + if @casting + s = $.i18n.t("play_level.tome_cast_button_casting", defaultValue: "Casting") + else if castable + s = $.i18n.t("play_level.tome_cast_button_castable", defaultValue: "Cast Spell") + " " + @castShortcut + else + s = $.i18n.t("play_level.tome_cast_button_cast", defaultValue: "Spell Cast") + @castButton.text s + @castButton.prop 'disabled', not castable setAutocastDelay: (delay) -> #console.log "Set autocast delay to", delay diff --git a/app/views/play/level/tome/spell.coffee b/app/views/play/level/tome/spell.coffee index 573ff9206..719f8488e 100644 --- a/app/views/play/level/tome/spell.coffee +++ b/app/views/play/level/tome/spell.coffee @@ -23,7 +23,7 @@ module.exports = class Spell @parameters = p.parameters @permissions = read: p.permissions?.read ? [], readwrite: p.permissions?.readwrite ? [] # teams @thangs = {} - @view = new SpellView {spell: @, session: @session} + @view = new SpellView {spell: @, session: @session, worker: @worker} @view.render() # Get it ready and code loaded in advance @tabView = new SpellListTabEntryView spell: @, supermodel: @supermodel @tabView.render() @@ -75,15 +75,27 @@ module.exports = class Spell hasChanged: (newSource=null, currentSource=null) -> (newSource ? @originalSource) isnt (currentSource ? @source) - hasChangedSignificantly: (newSource=null, currentSource=null) -> + hasChangedSignificantly: (newSource=null, currentSource=null, cb) -> for thangID, spellThang of @thangs aether = spellThang.aether break unless aether console.error @toString(), "couldn't find a spellThang with aether of", @thangs - return false - aether.hasChangedSignificantly (newSource ? @originalSource), (currentSource ? @source), true, true - + cb false + workerMessage = + function: "hasChangedSignificantly" + a: (newSource ? @originalSource) + spellKey: @spellKey + b: (currentSource ? @source) + careAboutLineNumbers: true + careAboutLint: true + @worker.addEventListener "message", (e) => + workerData = JSON.parse e.data + if workerData.function is "hasChangedSignificantly" and workerData.spellKey is @spellKey + @worker.removeEventListener("message",arguments.callee, false) + cb(workerData.hasChanged) + @worker.postMessage JSON.stringify(workerMessage) + createAether: (thang) -> aceConfig = me.get('aceConfig') ? {} aetherOptions = @@ -111,13 +123,23 @@ module.exports = class Spell aetherOptions.includeFlow = false #console.log "creating aether with options", aetherOptions aether = new Aether aetherOptions + workerMessage = + function: "createAether" + spellKey: @spellKey + options: aetherOptions + @worker.postMessage JSON.stringify workerMessage aether updateLanguageAether: -> aceConfig = me.get('aceConfig') ? {} + newLanguage = (aceConfig.language ? 'javascript') for thangId, spellThang of @thangs - spellThang.aether?.setLanguage (aceConfig.language ? 'javascript') + spellThang.aether?.setLanguage newLanguage spellThang.castAether = null + workerMessage = + function: "updateLanguageAether" + newLanguage: newLanguage + @worker.postMessage JSON.stringify workerMessage @transpile() toString: -> diff --git a/app/views/play/level/tome/spell_palette_entry_view.coffee b/app/views/play/level/tome/spell_palette_entry_view.coffee index ba6665931..5a610d984 100644 --- a/app/views/play/level/tome/spell_palette_entry_view.coffee +++ b/app/views/play/level/tome/spell_palette_entry_view.coffee @@ -6,9 +6,6 @@ filters = require 'lib/image_filter' {downTheChain} = require 'lib/world/world_utils' window.Vector = require 'lib/world/vector' # So we can document it -# If we use marked somewhere else, we'll have to make sure to preserve options -marked.setOptions {gfm: true, sanitize: false, smartLists: true, breaks: true} - safeJSONStringify = (input, maxDepth) -> recursion = (input, path, depth) -> output = {} diff --git a/app/views/play/level/tome/spell_view.coffee b/app/views/play/level/tome/spell_view.coffee index 4951b6915..6d1b81aa6 100644 --- a/app/views/play/level/tome/spell_view.coffee +++ b/app/views/play/level/tome/spell_view.coffee @@ -47,6 +47,7 @@ module.exports = class SpellView extends View constructor: (options) -> super options + @worker = options.worker @session = options.session @listenTo(@session, 'change:multiplayer', @onMultiplayerChanged) @spell = options.spell @@ -106,8 +107,8 @@ module.exports = class SpellView extends View name: 'end-current-script' bindKey: {win: 'Shift-Space', mac: 'Shift-Space'} passEvent: true # https://github.com/ajaxorg/ace/blob/master/lib/ace/keyboard/keybinding.js#L114 - # No easy way to selectively cancel shift+space, since we don't get access to the event. - # Maybe we could temporarily set ourselves to read-only if we somehow know that a script is active? + # No easy way to selectively cancel shift+space, since we don't get access to the event. + # Maybe we could temporarily set ourselves to read-only if we somehow know that a script is active? exec: -> Backbone.Mediator.publish 'level:shift-space-pressed' addCommand name: 'end-all-scripts' @@ -157,7 +158,7 @@ module.exports = class SpellView extends View @firepad?.dispose() createFirepad: -> - # load from firebase or the original source if there's nothing there + # load from firebase or the original source if there's nothing there return if @firepadLoading @eventsSuppressed = true @loaded = false @@ -278,9 +279,10 @@ module.exports = class SpellView extends View ] @onCodeChangeMetaHandler = => return if @eventsSuppressed - if not @spellThang or @spell.hasChangedSignificantly @getSource(), @spellThang.aether.raw - callback() for callback in onSignificantChange # Do these first - callback() for callback in onAnyChange # Then these + @spell.hasChangedSignificantly @getSource(), @spellThang.aether.raw, (hasChanged) => + if not @spellThang or hasChanged + callback() for callback in onSignificantChange # Do these first + callback() for callback in onAnyChange # Then these @aceDoc.on 'change', @onCodeChangeMetaHandler setRecompileNeeded: (needed=true) => @@ -317,20 +319,40 @@ module.exports = class SpellView extends View # to a new spellThang, we may want to refresh our Aether display. return unless aether = @spellThang?.aether source = @getSource() - codeHasChangedSignificantly = force or @spell.hasChangedSignificantly source, aether.raw - needsUpdate = codeHasChangedSignificantly or @spellThang isnt @lastUpdatedAetherSpellThang - return if not needsUpdate and aether is @displayedAether - castAether = @spellThang.castAether - codeIsAsCast = castAether and not @spell.hasChangedSignificantly source, castAether.raw - aether = castAether if codeIsAsCast - return if not needsUpdate and aether is @displayedAether + @spell.hasChangedSignificantly source, aether.raw, (hasChanged) => + codeHasChangedSignificantly = force or hasChanged + needsUpdate = codeHasChangedSignificantly or @spellThang isnt @lastUpdatedAetherSpellThang + return if not needsUpdate and aether is @displayedAether + castAether = @spellThang.castAether + codeIsAsCast = castAether and not hasChanged + aether = castAether if codeIsAsCast + return if not needsUpdate and aether is @displayedAether + + # Now that that's figured out, perform the update. + # The web worker Aether won't track state, so don't have to worry about updating it + finishUpdatingAether = (aether) => + @displayAether aether + @lastUpdatedAetherSpellThang = @spellThang + @guessWhetherFinished aether if fromCodeChange + + @clearAetherDisplay() + if codeHasChangedSignificantly and not codeIsAsCast + workerMessage = + function: "transpile" + spellKey: @spell.spellKey + source: source + + @worker.addEventListener "message", (e) => + workerData = JSON.parse e.data + if workerData.function is "transpile" and workerData.spellKey is @spell.spellKey + @worker.removeEventListener("message",arguments.callee, false) + aether.problems = workerData.problems + aether.raw = source + finishUpdatingAether(aether) + @worker.postMessage JSON.stringify(workerMessage) + else + finishUpdatingAether(aether) - # Now that that's figured out, perform the update. - @clearAetherDisplay() - aether.transpile source if codeHasChangedSignificantly and not codeIsAsCast - @displayAether aether - @lastUpdatedAetherSpellThang = @spellThang - @guessWhetherFinished aether if fromCodeChange clearAetherDisplay: -> problem.destroy() for problem in @problems @@ -378,12 +400,12 @@ module.exports = class SpellView extends View #console.log "finished?", valid, endOfLine, beginningOfLine, cursorPosition, currentLine.length, aether, new Date() - 0, currentLine if valid and endOfLine or beginningOfLine @recompile() - #console.log "recompile now!" - #else if not valid - # # if this works, we can get rid of all @recompileValid logic - # console.log "not valid, but so we'll wait to do it in", @autocastDelay + "ms" - #else - # console.log "valid but not at end of line; recompile in", @autocastDelay + "ms" + #console.log "recompile now!" + #else if not valid + # # if this works, we can get rid of all @recompileValid logic + # console.log "not valid, but so we'll wait to do it in", @autocastDelay + "ms" + #else + # console.log "valid but not at end of line; recompile in", @autocastDelay + "ms" onSpellChanged: (e) -> @spellHasChanged = true @@ -400,10 +422,11 @@ module.exports = class SpellView extends View return @onInfiniteLoop e if e.problem.id is "runtime_InfiniteLoop" return unless e.problem.userInfo.methodName is @spell.name return unless spellThang = _.find @spell.thangs, (spellThang, thangID) -> thangID is e.problem.userInfo.thangID - return if @spell.hasChangedSignificantly @getSource() # don't show this error if we've since edited the code - spellThang.aether.addProblem e.problem - @lastUpdatedAetherSpellThang = null # force a refresh without a re-transpile - @updateAether false, false + @spell.hasChangedSignificantly @getSource(), null, (hasChanged) => + return if hasChanged + spellThang.aether.addProblem e.problem + @lastUpdatedAetherSpellThang = null # force a refresh without a re-transpile + @updateAether false, false onInfiniteLoop: (e) -> return unless @spellThang @@ -418,7 +441,7 @@ module.exports = class SpellView extends View aether = e.world.userCodeMap[thangID]?[@spell.name] # Might not be there if this is a new Programmable Thang. spellThang.castAether = aether spellThang.aether = @spell.createAether thang - #console.log thangID, @spell.spellKey, "ran", aether.metrics.callsExecuted, "times over", aether.metrics.statementsExecuted, "statements, with max recursion depth", aether.metrics.maxDepth, "and full flow/metrics", aether.metrics, aether.flow + #console.log thangID, @spell.spellKey, "ran", aether.metrics.callsExecuted, "times over", aether.metrics.statementsExecuted, "statements, with max recursion depth", aether.metrics.maxDepth, "and full flow/metrics", aether.metrics, aether.flow @spell.transpile() @updateAether false, false @@ -469,7 +492,7 @@ module.exports = class SpellView extends View break _.last(executed).push state executedRows[state.range[0].row] = true - #state.executing = true if state.userInfo?.time is @thang.world.age # no work + #state.executing = true if state.userInfo?.time is @thang.world.age # no work currentCallIndex ?= callNumber - 1 #console.log "got call index", currentCallIndex, "for time", @thang.world.age, "out of", states.length @@ -571,14 +594,16 @@ module.exports = class SpellView extends View @ace.setDisplayIndentGuides aceConfig.indentGuides # default false @ace.setShowInvisibles aceConfig.invisibles # default false @ace.setKeyboardHandler @keyBindings[aceConfig.keyBindings ? 'default'] - # @aceSession.setMode @editModes[aceConfig.language ? 'javascript'] + # @aceSession.setMode @editModes[aceConfig.language ? 'javascript'] onChangeLanguage: (e) -> aceConfig = me.get('aceConfig') ? {} @aceSession.setMode @editModes[aceConfig.language ? 'javascript'] dismiss: -> - @recompile() if @spell.hasChangedSignificantly @getSource() + @spell.hasChangedSignificantly @getSource(), null, (hasChanged) => + @recompile() if hasChanged + destroy: -> $(@ace?.container).find('.ace_gutter').off 'click', '.ace_error, .ace_warning, .ace_info', @onAnnotationClick diff --git a/app/views/play/level/tome/tome_view.coffee b/app/views/play/level/tome/tome_view.coffee index 569f205bf..7ae29a53f 100644 --- a/app/views/play/level/tome/tome_view.coffee +++ b/app/views/play/level/tome/tome_view.coffee @@ -88,26 +88,7 @@ module.exports = class TomeView extends View @cast() createWorker: -> - return - # In progress - worker = cw - initialize: (scope) -> - self.window = self - self.global = self - console.log 'Tome worker initialized.' - doIt: (data, callback, scope) -> - console.log 'doing', what - try - importScripts '/javascripts/tome_aether.js' - catch err - console.log err.toString() - a = new Aether() - callback 'good' - undefined - onAccepted = (s) -> console.log 'accepted', s - onRejected = (s) -> console.log 'rejected', s - worker.doIt('hmm').then onAccepted, onRejected - worker + return new Worker("/javascripts/workers/aether_worker.js") generateTeamSpellMap: (spellObject) -> teamSpellMap = {} @@ -139,7 +120,7 @@ module.exports = class TomeView extends View @thangSpells[thang.id].push spellKey unless method.cloneOf skipProtectAPI = @getQueryVariable "skip_protect_api", not @options.ladderGame - skipFlow = @getQueryVariable "skip_flow", @options.levelID is 'brawlwood' or @options.levelID is 'resource-gathering-multiplayer' + skipFlow = @getQueryVariable "skip_flow", (@options.levelID in ['brawlwood', 'greed', 'gold-rush']) spell = @spells[spellKey] = new Spell programmableMethod: method, spellKey: spellKey, pathComponents: pathPrefixComponents.concat(pathComponents), session: @options.session, supermodel: @supermodel, skipFlow: skipFlow, skipProtectAPI: skipProtectAPI, worker: @worker for thangID, spellKeys of @thangSpells thang = world.getThangByID thangID @@ -222,7 +203,7 @@ module.exports = class TomeView extends View @spellPaletteView.toggleControls {}, spell.view.controlsEnabled # TODO: know when palette should have been disabled but didn't exist reloadAllCode: -> - spell.view.reloadCode false for spellKey, spell of @spells when spell.team is me.team + spell.view.reloadCode false for spellKey, spell of @spells when spell.team is me.team or (spell.team in ["common", "neutral", null]) Backbone.Mediator.publish 'tome:cast-spells', spells: @spells updateLanguageForAllSpells: -> @@ -230,5 +211,5 @@ module.exports = class TomeView extends View destroy: -> spell.destroy() for spellKey, spell of @spells - @worker?._close() + @worker?.terminate() super() diff --git a/app/views/play_view.coffee b/app/views/play_view.coffee index 3a61c9a8b..38e70ebd1 100644 --- a/app/views/play_view.coffee +++ b/app/views/play_view.coffee @@ -1,7 +1,7 @@ View = require 'views/kinds/RootView' template = require 'templates/play' LevelSession = require 'models/LevelSession' -CocoCollection = require 'models/CocoCollection' +CocoCollection = require 'collections/CocoCollection' class LevelSessionsCollection extends CocoCollection url: '' @@ -159,6 +159,14 @@ module.exports = class PlayView extends View description: "Combat the armies of other Wizards in a strategic forest arena! (Fast computer required.)" levelPath: 'ladder' } + { + name: 'Gold Rush' + difficulty: 3 + id: 'gold-rush' + image: '/file/db/level/525ef8ef06e1ab0962000003/commanding_followers_icon.png' + description: "Prove you are better at collecting gold than your opponent!" + levelPath: 'ladder' + } ] playerCreated = [ diff --git a/config.coffee b/config.coffee index b95413164..27ad5562b 100644 --- a/config.coffee +++ b/config.coffee @@ -59,6 +59,7 @@ exports.config = # Aether before box2d for some strange Object.defineProperty thing 'bower_components/aether/build/aether.js' 'bower_components/d3/d3.min.js' + 'vendor/scripts/async.js' ] stylesheets: defaultExtension: 'sass' diff --git a/scripts/mail.coffee b/scripts/mail.coffee index 140697370..b9983b619 100644 --- a/scripts/mail.coffee +++ b/scripts/mail.coffee @@ -65,7 +65,7 @@ collapseSessions = (sessionLists) -> grabUser = (session, callback) -> findParameters = _id: session.creator - selectString = 'email emailSubscriptions name jobProfile' + selectString = 'email emailSubscriptions emails name jobProfile' query = User .findOne(findParameters) .select(selectString) @@ -77,7 +77,8 @@ grabUser = (session, callback) -> totalEmailsSent = 0 emailUser = (user, callback) -> - return callback null, false if user.emails?.recruiting?.enabled is false # TODO: later, obey also "announcements" when that's untangled + #return callback null, false if user.emails?.anyNotes?.enabled is false # TODO: later, uncomment to obey also "anyNotes" when that's untangled + return callback null, false if user.emails?.recruitNotes?.enabled is false return callback null, false if user.email in alreadyEmailed return callback null, false if DEBUGGING and (totalEmailsSent > 1 or Math.random() > 0.1) ++totalEmailsSent diff --git a/scripts/mongodb/migrations/2014-02-22-migrate-emails.js b/scripts/mongodb/migrations/2014-02-22-migrate-emails.js new file mode 100644 index 000000000..07ccd32ad --- /dev/null +++ b/scripts/mongodb/migrations/2014-02-22-migrate-emails.js @@ -0,0 +1,35 @@ +// Did not migrate anonymous users because they get their properties setup on signup. + +// migrate the most common subscription configs with mass update commands +db.users.update({anonymous:false, emailSubscriptions:['announcement', 'notification'], emails:{$exists:false}}, {$set:{emails:{}}}, {multi:true}); +db.users.update({anonymous:false, emailSubscriptions:[], emails:{$exists:false}}, {$set:{emails:{anyNotes:{enabled:false}, generalNews:{enabled:false}}}}, {multi:true}); + +// migrate the rest one by one +emailMap = { + announcement: 'generalNews', + developer: 'archmageNews', + tester: 'adventurerNews', + level_creator: 'artisanNews', + article_editor: 'scribeNews', + translator: 'diplomatNews', + support: 'ambassadorNews', + notification: 'anyNotes' +}; + +db.users.find({anonymous:false, emails:{$exists:false}}).forEach(function(u) { + emails = {anyNotes:{enabled:false}, generalNews:{enabled:false}}; + var oldEmailSubs = u.emailSubscriptions || ['notification', 'announcement']; + for(var email in oldEmailSubs) { + var oldEmailName = oldEmailSubs[email]; + var newEmailName = emailMap[oldEmailName]; + if(!newEmailName) { + print('STOP, COULD NOT FIND EMAIL NAME', oldEmailName); + return false; + } + emails[newEmailName] = {enabled:true}; + } + u.emails = emails; + db.users.save(u); +}); + +// Done. No STOP error when this was run. \ No newline at end of file diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee index d8d631846..c09ecead3 100644 --- a/server/commons/Handler.coffee +++ b/server/commons/Handler.coffee @@ -333,7 +333,7 @@ module.exports = class Handler res = tv4.validateMultiple(input, @jsonSchema) res - @isID: (id) -> _.isString(id) and id.length is 24 and id.match(/[a-z0-9]/gi)?.length is 24 + @isID: (id) -> _.isString(id) and id.length is 24 and id.match(/[a-f0-9]/gi)?.length is 24 getDocumentForIdOrSlug: (idOrSlug, done) -> idOrSlug = idOrSlug+'' @@ -374,3 +374,17 @@ module.exports = class Handler return done(validation) unless validation.valid document.save (err) -> done(err) + + getPropertiesFromMultipleDocuments: (res, model, properties, ids) -> + query = model.find() + ids = ids.split(',') if _.isString ids + ids = _.uniq ids + for id in ids + return errors.badInput(res, "Given an invalid id: #{id}") unless Handler.isID(id) + query.where({'_id': { $in: ids} }) + query.select(properties).exec (err, documents) -> + dict = {} + _.each documents, (document) -> + dict[document.id] = document + res.send dict + res.end() diff --git a/server/commons/mail.coffee b/server/commons/mail.coffee index 117f10bd7..96bb56e2d 100644 --- a/server/commons/mail.coffee +++ b/server/commons/mail.coffee @@ -2,14 +2,10 @@ config = require '../../server_config' module.exports.MAILCHIMP_LIST_ID = 'e9851239eb' module.exports.MAILCHIMP_GROUP_ID = '4529' -module.exports.MAILCHIMP_GROUP_MAP = - announcement: 'Announcements' - tester: 'Adventurers' - level_creator: 'Artisans' - developer: 'Archmages' - article_editor: 'Scribes' - translator: 'Diplomats' - support: 'Ambassadors' + +# these two need to be parallel +module.exports.MAILCHIMP_GROUPS = ['Announcements', 'Adventurers', 'Artisans', 'Archmages', 'Scribes', 'Diplomats', 'Ambassadors'] +module.exports.NEWS_GROUPS = ['generalNews', 'adventurerNews', 'artisanNews', 'archmageNews', 'scribeNews', 'diplomatNews', 'ambassadorNews'] nodemailer = require 'nodemailer' module.exports.transport = nodemailer.createTransport "SMTP", diff --git a/server/patches/patch_handler.coffee b/server/patches/patch_handler.coffee index 4e134d73d..7d30ce353 100644 --- a/server/patches/patch_handler.coffee +++ b/server/patches/patch_handler.coffee @@ -58,7 +58,7 @@ PatchHandler = class PatchHandler extends Handler log.error "Error sending patch created: could not find the loaded target on the patch object." unless doc.targetLoaded return unless doc.targetLoaded watchers = doc.targetLoaded.get('watchers') or [] - watchers = (w for w in watchers when not w.equals(editor.get('_id'))) + watchers = (w for w in watchers when not w.equals(req.user.get('_id'))) return unless watchers?.length User.find({_id:{$in:watchers}}).select({email:1, name:1}).exec (err, watchers) => for watcher in watchers diff --git a/server/routes/auth.coffee b/server/routes/auth.coffee index 76612e2e0..3b5c30b1d 100644 --- a/server/routes/auth.coffee +++ b/server/routes/auth.coffee @@ -131,11 +131,25 @@ module.exports.setup = (app) -> if not user return errors.notFound res, "No user found with email '#{req.query.email}'" - user.set('emailSubscriptions', []) - user.save (err) => + emails = _.clone(user.get('emails')) or {} + msg = '' + + if req.query.recruitNotes + emails.recruitNotes ?= {} + emails.recruitNotes.enabled = false + msg = "Unsubscribed #{req.query.email} from recruiting emails." + + else + msg = "Unsubscribed #{req.query.email} from all CodeCombat emails. Sorry to see you go!" + emailSettings.enabled = false for emailSettings in _.values(emails) + emails.generalNews ?= {} + emails.generalNews.enabled = false + emails.anyNotes ?= {} + emails.anyNotes.enabled = false + + user.update {$set: {emails: emails}}, {}, => return errors.serverError res, 'Database failure.' if err - - res.send "Unsubscribed #{req.query.email} from all CodeCombat emails. Sorry to see you go!

Account settings

" + res.send msg + "

Account settings

" res.end() module.exports.loginUser = loginUser = (req, res, user, send=true, next=null) -> diff --git a/server/routes/db.coffee b/server/routes/db.coffee index beb120573..9b31e2537 100644 --- a/server/routes/db.coffee +++ b/server/routes/db.coffee @@ -6,6 +6,7 @@ mongoose = require 'mongoose' module.exports.setup = (app) -> # This is hacky and should probably get moved somewhere else, I dunno app.get '/db/cla.submissions', (req, res) -> + return errors.unauthorized(res, "You must be an admin to view that information") unless req.user?.isAdmin() res.setHeader('Content-Type', 'application/json') collection = mongoose.connection.db.collection 'cla.submissions', (err, collection) -> return log.error "Couldn't fetch CLA submissions because #{err}" if err diff --git a/server/routes/file.coffee b/server/routes/file.coffee index f01f635e3..1cc0f73d7 100644 --- a/server/routes/file.coffee +++ b/server/routes/file.coffee @@ -83,8 +83,7 @@ filePost = (req, res) -> saveURL = (req, res) -> options = createPostOptions(req) - force = req.user.isAdmin() and req.body.force - checkExistence options, res, force, (err) -> + checkExistence options, req, res, req.body.force, (err) -> return errors.serverError(res) if err writestream = Grid.gfs.createWriteStream(options) request(req.body.url).pipe(writestream) @@ -92,8 +91,7 @@ saveURL = (req, res) -> saveFile = (req, res) -> options = createPostOptions(req) - force = req.user.isAdmin() and req.body.force - checkExistence options, res, force, (err) -> + checkExistence options, req, res, req.body.force, (err) -> return if err writestream = Grid.gfs.createWriteStream(options) f = req.files[req.body.postName] @@ -103,9 +101,8 @@ saveFile = (req, res) -> savePNG = (req, res) -> options = createPostOptions(req) - force = req.user.isAdmin() and req.body.force - checkExistence options, res, force, (err) -> - return errors.serverError(res) if err + checkExistence options, req, res, req.body.force, (err) -> + return if err writestream = Grid.gfs.createWriteStream(options) img = new Buffer(req.body.b64png, 'base64') streamBuffers = require 'stream-buffers' @@ -113,21 +110,32 @@ savePNG = (req, res) -> myReadableStreamBuffer.put(img) myReadableStreamBuffer.pipe(writestream) handleStreamEnd(res, writestream) + +userCanEditFile = (user=null, file=null) -> + # no user means 'anyone'. No file means 'any file' + return false unless user + return true if user.isAdmin() + return false unless file + return true if file.metadata.creator is user.id + return false -checkExistence = (options, res, force, done) -> +checkExistence = (options, req, res, force, done) -> q = { filename: options.filename 'metadata.path': options.metadata.path } Grid.gfs.collection('media').find(q).toArray (err, files) -> - if files.length and not force - errors.conflict(res) + file = files[0] + if file and ((not userCanEditFile(req.user, file) or (not force))) + errors.conflict(res, {canForce:userCanEditFile(req.user, file)}) done(true) - else if files.length - q = { _id: files[0]._id } + else if file + q = { _id: file._id } q.root = 'media' Grid.gfs.remove q, (err) -> - return errors.serverError(res) if err + if err + errors.serverError(res) + return done(true) done() else done() diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee index 9023209d2..0f400cc2a 100644 --- a/server/routes/mail.coffee +++ b/server/routes/mail.coffee @@ -1,5 +1,4 @@ mail = require '../commons/mail' -map = _.invert mail.MAILCHIMP_GROUP_MAP User = require '../users/User.coffee' errors = require '../commons/errors' #request = require 'request' @@ -77,12 +76,13 @@ handleLadderUpdate = (req, res) -> sendLadderUpdateEmail result, now, daysAgo for result in results sendLadderUpdateEmail = (session, now, daysAgo) -> - User.findOne({_id: session.creator}).select("name email firstName lastName emailSubscriptions preferredLanguage").lean().exec (err, user) -> + User.findOne({_id: session.creator}).select("name email firstName lastName emailSubscriptions emails preferredLanguage").lean().exec (err, user) -> if err log.error "Couldn't find user for #{session.creator} from session #{session._id}" return - unless user.email and ('notification' in user.emailSubscriptions) and not session.unsubscribed - log.info "Not sending email to #{user.email} #{user.name} because they only want emails about #{user.emailSubscriptions} - session unsubscribed: #{session.unsubscribed}" + allowNotes = user.isEmailSubscriptionEnabled 'anyNotes' + unless user.email and allowNotes and not session.unsubscribed + log.info "Not sending email to #{user.email} #{user.name} because they only want emails about #{user.emailSubscriptions}, #{user.emails} - session unsubscribed: #{session.unsubscribed}" return unless session.levelName log.info "Not sending email to #{user.email} #{user.name} because the session had no levelName in it." @@ -198,13 +198,11 @@ handleMailchimpWebHook = (req, res) -> return errors.serverError(res) if err res.end('Success') +module.exports.handleProfileUpdate = handleProfileUpdate = (user, post) -> + mailchimpSubs = post.data.merges.INTERESTS.split(', ') -handleProfileUpdate = (user, post) -> - groups = post.data.merges.INTERESTS.split(', ') - groups = (map[g] for g in groups when map[g]) - otherSubscriptions = (g for g in user.get('emailSubscriptions') when not mail.MAILCHIMP_GROUP_MAP[g]) - groups = groups.concat otherSubscriptions - user.set 'emailSubscriptions', groups + for [mailchimpEmailGroup, emailGroup] in _.zip(mail.MAILCHIMP_GROUPS, mail.NEWS_GROUPS) + user.setEmailSubscription emailGroup, mailchimpEmailGroup in mailchimpSubs fname = post.data.merges.FNAME user.set('firstName', fname) if fname @@ -217,7 +215,9 @@ handleProfileUpdate = (user, post) -> # badLog("Updating user object to: #{JSON.stringify(user.toObject(), null, '\t')}") -handleUnsubscribe = (user) -> +module.exports.handleUnsubscribe = handleUnsubscribe = (user) -> user.set 'emailSubscriptions', [] + for emailGroup in mail.NEWS_GROUPS + user.setEmailSubscription emailGroup, false # badLog("Unsubscribing user object to: #{JSON.stringify(user.toObject(), null, '\t')}") diff --git a/server/users/User.coffee b/server/users/User.coffee index b827a6916..1b591a304 100644 --- a/server/users/User.coffee +++ b/server/users/User.coffee @@ -16,6 +16,7 @@ UserSchema = new mongoose.Schema({ UserSchema.pre('init', (next) -> return next() unless jsonschema.properties? for prop, sch of jsonschema.properties + continue if prop is 'emails' # defaults may change, so don't carry them over just yet @set(prop, sch.default) if sch.default? @set('permissions', ['admin']) if not isProduction next() @@ -23,27 +24,60 @@ UserSchema.pre('init', (next) -> UserSchema.post('init', -> @set('anonymous', false) if @get('email') - @currentSubscriptions = JSON.stringify(@get('emailSubscriptions')) ) UserSchema.methods.isAdmin = -> p = @get('permissions') return p and 'admin' in p + +emailNameMap = + generalNews: 'announcement' + adventurerNews: 'tester' + artisanNews: 'level_creator' + archmageNews: 'developer' + scribeNews: 'article_editor' + diplomatNews: 'translator' + ambassadorNews: 'support' + anyNotes: 'notification' + +UserSchema.methods.setEmailSubscription = (newName, enabled) -> + oldSubs = _.clone @get('emailSubscriptions') + if oldSubs and oldName = emailNameMap[newName] + oldSubs = (s for s in oldSubs when s isnt oldName) + oldSubs.push(oldName) if enabled + @set('emailSubscriptions', oldSubs) + + newSubs = _.clone(@get('emails') or _.cloneDeep(jsonschema.properties.emails.default)) + newSubs[newName] ?= {} + newSubs[newName].enabled = enabled + @set('emails', newSubs) + @newsSubsChanged = true if newName in mail.NEWS_GROUPS + +UserSchema.methods.isEmailSubscriptionEnabled = (newName) -> + emails = @get 'emails' + if not emails + oldSubs = @get('emailSubscriptions') + oldName = emailNameMap[newName] + return oldName and oldName in oldSubs if oldSubs + emails ?= {} + _.defaults emails, _.cloneDeep(jsonschema.properties.emails.default) + return emails[newName]?.enabled UserSchema.statics.updateMailChimp = (doc, callback) -> - return callback?() unless isProduction + return callback?() unless isProduction or GLOBAL.testing return callback?() if doc.updatedMailChimp return callback?() unless doc.get('email') existingProps = doc.get('mailChimp') emailChanged = (not existingProps) or existingProps?.email isnt doc.get('email') - emailSubs = doc.get('emailSubscriptions') - gm = mail.MAILCHIMP_GROUP_MAP - newGroups = (gm[name] for name in emailSubs when gm[name]?) + return callback?() unless emailChanged or doc.newsSubsChanged + + newGroups = [] + for [mailchimpEmailGroup, emailGroup] in _.zip(mail.MAILCHIMP_GROUPS, mail.NEWS_GROUPS) + newGroups.push(mailchimpEmailGroup) if doc.isEmailSubscriptionEnabled(emailGroup) + if (not existingProps) and newGroups.length is 0 return callback?() # don't add totally unsubscribed people to the list - subsChanged = doc.currentSubscriptions isnt JSON.stringify(emailSubs) - return callback?() unless emailChanged or subsChanged - + params = {} params.id = mail.MAILCHIMP_LIST_ID params.email = if existingProps then {leid:existingProps.leid} else {email:doc.get('email')} diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee index 0073bf5ae..cc6f279d3 100644 --- a/server/users/user_handler.coffee +++ b/server/users/user_handler.coffee @@ -25,7 +25,7 @@ UserHandler = class UserHandler extends Handler editableProperties: [ 'name', 'photoURL', 'password', 'anonymous', 'wizardColor1', 'volume', - 'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emailSubscriptions', + 'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails', 'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage', 'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile' ] @@ -120,34 +120,11 @@ UserHandler = class UserHandler extends Handler return @sendSuccess(res, @formatEntity(req, req.user, 256)) super(req, res, id) - getNamesByIds: (req, res) -> + getNamesByIDs: (req, res) -> ids = req.query.ids or req.body.ids - ids = ids.split(',') if _.isString ids - ids = _.uniq ids - - # TODO: Extend and repurpose this handler to return other public info about a user more flexibly, - # say by a query parameter that lists public properties to return. returnWizard = req.query.wizard or req.body.wizard - query = if returnWizard then {name:1, wizard:1} else {name:1} - - makeFunc = (id) -> - (callback) -> - User.findById(id, query).exec (err, document) -> - return done(err) if err - if document and returnWizard - callback(null, {name:document.get('name'), wizard:document.get('wizard') or {}}) - else - callback(null, document?.get('name') or '') - - funcs = {} - for id in ids - return errors.badInput(res, "Given an invalid id: #{id}") unless Handler.isID(id) - funcs[id] = makeFunc(id) - - async.parallel funcs, (err, results) -> - return errors.serverError err if err - res.send results - res.end() + properties = if returnWizard then "name wizard" else "name" + @getPropertiesFromMultipleDocuments res, User, properties, ids nameToID: (req, res, name) -> User.findOne({nameLower:name.toLowerCase()}).exec (err, otherUser) -> @@ -206,7 +183,7 @@ UserHandler = class UserHandler extends Handler getByRelationship: (req, res, args...) -> return @agreeToCLA(req, res) if args[1] is 'agreeToCLA' return @avatar(req, res, args[0]) if args[1] is 'avatar' - return @getNamesByIds(req, res) if args[1] is 'names' + return @getNamesByIDs(req, res) if args[1] is 'names' return @nameToID(req, res, args[0]) if args[1] is 'nameToID' return @getLevelSessions(req, res, args[0]) if args[1] is 'level.sessions' return @getCandidates(req, res) if args[1] is 'candidates' @@ -258,9 +235,10 @@ UserHandler = class UserHandler extends Handler getCandidates: (req, res) -> authorized = req.user.isAdmin() or ('employer' in req.user.get('permissions')) since = (new Date((new Date()) - 2 * 30.4 * 86400 * 1000)).toISOString() - query = {'jobProfile.active': true, 'jobProfile.updated': {$gt: since}} - #query = {'jobProfile.updated': {$gt: since}} + #query = {'jobProfile.active': true, 'jobProfile.updated': {$gt: since}} + query = {'jobProfile.updated': {$gt: since}} query.jobProfileApproved = true unless req.user.isAdmin() + query['jobProfile.active'] = true unless req.user.isAdmin() selection = 'jobProfile' selection += ' email' if authorized selection += ' jobProfileApproved' if req.user.isAdmin() @@ -274,7 +252,7 @@ UserHandler = class UserHandler extends Handler fields = if authorized then ['jobProfile', 'jobProfileApproved', 'photoURL', '_id'] else ['jobProfile'] obj = _.pick document.toObject(), fields obj.photoURL ||= obj.jobProfile.photoURL if authorized - subfields = ['country', 'city', 'lookingFor', 'jobTitle', 'skills', 'experience', 'updated'] + subfields = ['country', 'city', 'lookingFor', 'jobTitle', 'skills', 'experience', 'updated', 'active'] if authorized subfields = subfields.concat ['name'] obj.jobProfile = _.pick obj.jobProfile, subfields diff --git a/test/server/functional/auth.spec.coffee b/test/server/functional/auth.spec.coffee index 750f4997e..15ef44171 100644 --- a/test/server/functional/auth.spec.coffee +++ b/test/server/functional/auth.spec.coffee @@ -1,5 +1,6 @@ require '../common' request = require 'request' +User = require '../../../server/users/User' urlLogin = getURL('/auth/login') urlReset = getURL('/auth/reset') @@ -16,7 +17,8 @@ describe '/auth/whoami', -> describe '/auth/login', -> it 'clears Users first', (done) -> - User.remove {}, (err) -> + clearModels [User], (err) -> + throw err if err request.get getURL('/auth/whoami'), -> throw err if err done() @@ -134,3 +136,21 @@ describe '/auth/reset', -> form = req.form() form.append('username', 'scott@gmail.com') form.append('password', 'nada') + +describe '/auth/unsubscribe', -> + it 'clears Users first', (done) -> + clearModels [User], (err) -> + throw err if err + request.get getURL('/auth/whoami'), -> + throw err if err + done() + + it 'removes just recruitment emails if you include ?recruitNotes=1', (done) -> + loginJoe (joe) -> + url = getURL('/auth/unsubscribe?recruitNotes=1&email='+joe.get('email')) + request.get url, (error, response) -> + expect(response.statusCode).toBe(200) + user = User.findOne(joe.get('_id')).exec (err, user) -> + expect(user.get('emails').recruitNotes.enabled).toBe(false) + expect(user.isEmailSubscriptionEnabled('generalNews')).toBeTruthy() + done() diff --git a/test/server/functional/mail.spec.coffee b/test/server/functional/mail.spec.coffee new file mode 100644 index 000000000..0910aab6f --- /dev/null +++ b/test/server/functional/mail.spec.coffee @@ -0,0 +1,38 @@ +require '../common' +mail = require '../../../server/routes/mail' +User = require '../../../server/users/User' + +testPost = + data: + email: 'scott@codecombat.com' + id: '12345678' + merges: + INTERESTS: 'Announcements, Adventurers, Archmages, Scribes, Diplomats, Ambassadors, Artisans' + FNAME: 'Scott' + LNAME: 'Erickson' + +describe 'handleProfileUpdate', -> + it 'updates emails from the data passed in', (done) -> + u = new User() + mail.handleProfileUpdate(u, testPost) + expect(u.isEmailSubscriptionEnabled('generalNews')).toBeTruthy() + expect(u.isEmailSubscriptionEnabled('adventurerNews')).toBeTruthy() + expect(u.isEmailSubscriptionEnabled('archmageNews')).toBeTruthy() + expect(u.isEmailSubscriptionEnabled('scribeNews')).toBeTruthy() + expect(u.isEmailSubscriptionEnabled('diplomatNews')).toBeTruthy() + expect(u.isEmailSubscriptionEnabled('ambassadorNews')).toBeTruthy() + expect(u.isEmailSubscriptionEnabled('artisanNews')).toBeTruthy() + done() + +describe 'handleUnsubscribe', -> + it 'turns off all news and notifications', (done) -> + u = new User({generalNews: {enabled:true}, archmageNews: {enabled:true}, anyNotes: {enabled:true}}) + mail.handleUnsubscribe(u) + expect(u.isEmailSubscriptionEnabled('generalNews')).toBeFalsy() + expect(u.isEmailSubscriptionEnabled('adventurerNews')).toBeFalsy() + expect(u.isEmailSubscriptionEnabled('archmageNews')).toBeFalsy() + expect(u.isEmailSubscriptionEnabled('scribeNews')).toBeFalsy() + expect(u.isEmailSubscriptionEnabled('diplomatNews')).toBeFalsy() + expect(u.isEmailSubscriptionEnabled('ambassadorNews')).toBeFalsy() + expect(u.isEmailSubscriptionEnabled('artisanNews')).toBeFalsy() + done() diff --git a/test/server/functional/user.spec.coffee b/test/server/functional/user.spec.coffee index 0ee2ff364..46c98fc24 100644 --- a/test/server/functional/user.spec.coffee +++ b/test/server/functional/user.spec.coffee @@ -1,8 +1,47 @@ require '../common' request = require 'request' +User = require '../../../server/users/User' urlUser = '/db/user' +describe 'Server user object', -> + + it 'uses the schema defaults to fill in email preferences', (done) -> + user = new User() + expect(user.isEmailSubscriptionEnabled('generalNews')).toBeTruthy() + expect(user.isEmailSubscriptionEnabled('anyNotes')).toBeTruthy() + expect(user.isEmailSubscriptionEnabled('recruitNotes')).toBeTruthy() + expect(user.isEmailSubscriptionEnabled('archmageNews')).toBeFalsy() + done() + + it 'uses old subs if they\'re around', (done) -> + user = new User() + user.set 'emailSubscriptions', ['tester'] + expect(user.isEmailSubscriptionEnabled('adventurerNews')).toBeTruthy() + expect(user.isEmailSubscriptionEnabled('generalNews')).toBeFalsy() + done() + + it 'maintains the old subs list if it\'s around', (done) -> + user = new User() + user.set 'emailSubscriptions', ['tester'] + user.setEmailSubscription('artisanNews', true) + expect(JSON.stringify(user.get('emailSubscriptions'))).toBe(JSON.stringify(['tester','level_creator'])) + done() + +describe 'User.updateMailChimp', -> + makeMC = (callback) -> + GLOBAL.mc = + lists: + subscribe: callback + + it 'uses emails to determine what to send to MailChimp', (done) -> + makeMC (params) -> + expect(JSON.stringify(params.merge_vars.groupings[0].groups)).toBe(JSON.stringify(['Announcements'])) + done() + + user = new User({emailSubscriptions:['announcement'], email:'tester@gmail.com'}) + User.updateMailChimp(user) + describe 'POST /db/user', -> it 'preparing test : clears the db first', (done) -> diff --git a/vendor/scripts/async.js b/vendor/scripts/async.js new file mode 100644 index 000000000..2bb5395db --- /dev/null +++ b/vendor/scripts/async.js @@ -0,0 +1,1043 @@ +/*jshint onevar: false, indent:4 */ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _toString = Object.prototype.toString; + + var _isArray = Array.isArray || function (obj) { + return _toString.call(obj) === '[object Array]'; + }; + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(done) ); + }); + function done(err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(); + } + } + } + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + var remainingTasks = keys.length + if (!remainingTasks) { + return callback(); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + remainingTasks-- + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (!remainingTasks) { + var theCallback = callback; + // prevent final callback from calling itself if it errors + callback = function () {}; + + theCallback(null, results); + } + }); + + _each(keys, function (k) { + var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.retry = function(times, task, callback) { + var DEFAULT_TIMES = 5; + var attempts = []; + // Use defaults if times not passed + if (typeof times === 'function') { + callback = task; + task = times; + times = DEFAULT_TIMES; + } + // Make sure times is a number + times = parseInt(times, 10) || DEFAULT_TIMES; + var wrappedTask = function(wrappedCallback, wrappedResults) { + var retryAttempt = function(task, finalAttempt) { + return function(seriesCallback) { + task(function(err, result){ + seriesCallback(!err || finalAttempt, {err: err, result: result}); + }, wrappedResults); + }; + }; + while (times) { + attempts.push(retryAttempt(task, !(times-=1))); + } + async.series(attempts, function(done, data){ + data = data[data.length - 1]; + (wrappedCallback || callback)(data.err, data.result); + }); + } + // If a callback is passed, run this as a controll flow + return callback ? wrappedTask() : wrappedTask + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (!_isArray(tasks)) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (_isArray(tasks)) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (_isArray(tasks)) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + var args = Array.prototype.slice.call(arguments, 1); + if (test.apply(null, args)) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + var args = Array.prototype.slice.call(arguments, 1); + if (!test.apply(null, args)) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if (!q.started){ + q.started = true; + } + if (!_isArray(data)) { + data = [data]; + } + if(data.length == 0) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + if (q.drain) { + q.drain(); + } + }); + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === q.concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + started: false, + paused: false, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + kill: function () { + q.drain = null; + q.tasks = []; + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (!q.paused && workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + }, + idle: function() { + return q.tasks.length + workers === 0; + }, + pause: function () { + if (q.paused === true) { return; } + q.paused = true; + q.process(); + }, + resume: function () { + if (q.paused === false) { return; } + q.paused = false; + q.process(); + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + drained: true, + push: function (data, callback) { + if (!_isArray(data)) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + cargo.drained = false; + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain && !cargo.drained) cargo.drain(); + cargo.drained = true; + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0, tasks.length); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + async.nextTick(function () { + callback.apply(null, memo[key]); + }); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.seq = function (/* functions... */) { + var fns = arguments; + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + async.compose = function (/* functions... */) { + return async.seq.apply(null, Array.prototype.reverse.call(arguments)); + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // Node.js + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // AMD / RequireJS + else if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // included directly via