diff --git a/app/lib/Router.coffee b/app/Router.coffee similarity index 62% rename from app/lib/Router.coffee rename to app/Router.coffee index 2c3a026a3..ca6af592b 100644 --- a/app/lib/Router.coffee +++ b/app/Router.coffee @@ -6,7 +6,10 @@ NotFoundView = require('views/NotFoundView') go = (path) -> -> @routeDirectly path, arguments module.exports = class CocoRouter extends Backbone.Router - subscribe: -> + + initialize: -> + # http://nerds.airbnb.com/how-to-add-google-analytics-page-tracking-to-57536 + @bind 'route', @_trackPageView Backbone.Mediator.subscribe 'gapi-loaded', @onGPlusAPILoaded, @ Backbone.Mediator.subscribe 'router:navigate', @onNavigate, @ @@ -14,12 +17,24 @@ module.exports = class CocoRouter extends Backbone.Router '': go('HomeView') 'about': go('AboutView') - 'admin': go('AdminView') + + 'account/profile(/:userID)': go('account/JobProfileView') + 'account/settings': go('account/AccountSettingsView') + 'account/unsubscribe': go('account/UnsubscribeView') + + 'admin': go('admin/MainAdminView') + 'admin/candidates': go('admin/CandidatesView') + 'admin/clas': go('admin/CLAsView') + 'admin/employers': go('admin/EmployersListView') + 'admin/files': go('admin/FilesView') + 'admin/level-sessions': go('admin/LevelSessionsView') + 'admin/users': go('admin/UsersView') 'beta': go('HomeView') 'cla': go('CLAView') 'community': go('CommunityView') + 'contribute': go('contribute/MainContributeView') 'contribute/adventurer': go('contribute/AdventurerView') 'contribute/ambassador': go('contribute/AmbassadorView') @@ -28,71 +43,84 @@ module.exports = class CocoRouter extends Backbone.Router 'contribute/diplomat': go('contribute/DiplomatView') 'contribute/scribe': go('contribute/ScribeView') + 'db/*path': 'routeToServer' 'demo(/*subpath)': go('DemoView') + 'docs/components': go('docs/ComponentDocumentationView') 'editor': go('editor/MainEditorView') - 'employers': go('EmployersView') + + 'editor/achievement': go('editor/achievement/AchievementSearchView') + 'editor/achievement': go('editor/achievement/AchievementEditView') + 'editor/article': go('editor/article/ArticleSearchView') + 'editor/article/preview': go('editor/article/ArticlePreviewView') + 'editor/article/:articleID': go('editor/article/ArticleEditView') + 'editor/level': go('editor/level/LevelSearchView') + 'editor/level/:levelID': go('editor/level/LevelEditView') + 'editor/thang': go('editor/thang/ThangTypeSearchView') + 'editor/thang/:thangID': go('editor/thang/ThangTypeEditView') + 'employers': go('EmployersView') + + 'file/*path': 'routeToServer' + 'legal': go('LegalView') 'multiplayer': go('MultiplayerView') 'play': go('play/MainPlayView') + 'play/ladder/:levelID': go('play/ladder/LadderView') + 'play/ladder': go('play/ladder/MainLadderView') + 'play/level/:levelID': go('play/level/PlayLevelView') + 'play/spectate/:levelID': go('play/SpectateView') + 'preview': go('HomeView') 'teachers': go('TeachersView') + 'test(/*subpath)': go('TestView') + '*name': 'showNotFoundView' - # editor views tend to have the same general structure - 'editor/:model(/:slug_or_id)(/:subview)': 'editorModelView' + routeToServer: (e) -> + window.location.href = window.location.href - # Direct links - - - 'play/ladder/:levelID': go('play/ladder/ladder_view') - 'play/ladder': go('play/ladder_home') - - # db and file urls call the server directly - 'db/*path': 'routeToServer' - 'file/*path': 'routeToServer' - - # most go through here - '*name': 'general' - - home: -> @openRoute('home') - general: (name) -> - @openRoute(name) - - editorModelView: (modelName, slugOrId, subview) -> - modulePrefix = "views/editor/#{modelName}/" - suffix = subview or (if slugOrId then 'edit' else 'home') - ViewClass = @tryToLoadModule(modulePrefix + suffix) - unless ViewClass - #console.log('could not hack it', modulePrefix + suffix) - args = (a for a in arguments when a) - args.splice(0, 0, 'editor') - return @openRoute(args.join('/')) - view = new ViewClass({}, slugOrId) + routeDirectly: (path, args) -> + path = "views/#{path}" + ViewClass = @tryToLoadModule path + return @openView @notFoundView() if not ViewClass + view = new ViewClass({}, args...) # options, then any path fragment args view.render() - @openView if view then view else @notFoundView() - - cache: {} - openRoute: (route) -> - route = route.split('?')[0] - route = route.split('#')[0] - view = @getViewFromCache(route) @openView(view) + tryToLoadModule: (path) -> + try + return require(path) + catch error + if error.toString().search('Cannot find module "' + path + '" from') is -1 + throw error + + showNotFoundView: -> + @openView @notFoundView() + + notFoundView: -> + view = new NotFoundView() + view.render() + openView: (view) -> @closeCurrentView() $('#page-container').empty().append view.el window.currentView = view @activateTab() @renderLoginButtons() - window.scrollTo(0, view.scrollY) if view.scrollY? view.afterInsert() - view.didReappear() if view.fromCache + view.didReappear() + + closeCurrentView: -> + if window.currentView?.reloadOnClose + return document.location.reload() + window.currentModal?.hide?() + return unless window.currentView? + window.currentView.destroy() onGPlusAPILoaded: => @renderLoginButtons() @@ -117,71 +145,10 @@ module.exports = class CocoRouter extends Backbone.Router else console.warn 'Didn\'t have gapi.signin to render G+ login button. (DoNotTrackMe extension?)' - getViewFromCache: (route) -> - if route of @cache - @cache[route].fromCache = true - return @cache[route] - view = @getView(route) - @cache[route] = view if view?.cache - return view - - routeDirectly: (path, args) -> - if window.currentView?.reloadOnClose - return document.location.reload() - path = "views/#{path}" - ViewClass = @tryToLoadModule path - return @openView @notFoundView() if not ViewClass - view = new ViewClass({}, args...) # options, then any path fragment args - view.render() - @openView(view) - - getView: (route, suffix='_view') -> - # iteratively breaks down the url pieces looking for the view - # passing the broken off pieces as args. This way views like 'resource/14394893' - # will get passed to the resource view with arg '14394893' - pieces = _.string.words(route, '/') - split = Math.max(1, pieces.length-1) - while split > -1 - sub_route = _.string.join('/', pieces[0..split]...) - path = "views/#{sub_route}#{suffix}" - ViewClass = @tryToLoadModule(path) - break if ViewClass - split -= 1 - - return @notFoundView() if not ViewClass - args = pieces[split+1..] - view = new ViewClass({}, args...) # options, then any path fragment args - view.render() - - tryToLoadModule: (path) -> - try - return require(path) - catch error - if error.toString().search('Cannot find module "' + path + '" from') is -1 - throw error - - notFoundView: -> - view = new NotFoundView() - view.render() - - closeCurrentView: -> - window.currentModal?.hide?() - return unless window.currentView? - if window.currentView.cache - window.currentView.scrollY = window.scrollY - window.currentView.willDisappear() - else - window.currentView.destroy() - activateTab: -> base = _.string.words(document.location.pathname[1..], '/')[0] $("ul.nav li.#{base}").addClass('active') - initialize: -> - @cache = {} - # http://nerds.airbnb.com/how-to-add-google-analytics-page-tracking-to-57536 - @bind 'route', @_trackPageView - _trackPageView: -> window.tracker?.trackPageView() @@ -196,6 +163,3 @@ module.exports = class CocoRouter extends Backbone.Router @openView view else @openView e.view - - routeToServer: (e) -> - window.location.href = window.location.href diff --git a/app/application.coffee b/app/application.coffee index 8d71a3249..4eb829c88 100644 --- a/app/application.coffee +++ b/app/application.coffee @@ -35,7 +35,7 @@ preload = (arrayOfImages) -> $('')[0].src = @ Application = initialize: -> - Router = require('lib/Router') + Router = require('Router') @tracker = new Tracker() @facebookHandler = new FacebookHandler() @gplusHandler = new GPlusHandler() @@ -53,7 +53,6 @@ Application = initialize: -> #resPostPath: '/languages/add/__lng__/__ns__' }, (t) => @router = new Router() - @router.subscribe() onIdleChanged = (to) => => Backbone.Mediator.publish 'application:idle-changed', idle: @userIsIdle = to @idleTracker = new Idle onAway: onIdleChanged true diff --git a/app/assets/images/pages/editor/level/preset_grassy_large.jpg b/app/assets/images/pages/editor/level/preset_grassy_large.jpg new file mode 100644 index 000000000..53c8bc2a7 Binary files /dev/null and b/app/assets/images/pages/editor/level/preset_grassy_large.jpg differ diff --git a/app/assets/images/pages/editor/level/preset_grassy_small.jpg b/app/assets/images/pages/editor/level/preset_grassy_small.jpg new file mode 100644 index 000000000..ed9356944 Binary files /dev/null and b/app/assets/images/pages/editor/level/preset_grassy_small.jpg differ diff --git a/app/initialize.coffee b/app/initialize.coffee index b2d69ee13..a27c1f7a2 100644 --- a/app/initialize.coffee +++ b/app/initialize.coffee @@ -31,12 +31,11 @@ init = -> app.initialize() Backbone.history.start({ pushState: true }) handleNormalUrls() + setUpMoment() # Set up i18n for moment treemaExt = require 'treema-ext' treemaExt.setup() -$ -> init() - handleNormalUrls = -> # http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/ $(document).on 'click', "a[href^='/']", (event) -> @@ -66,6 +65,12 @@ setUpDefinitions = -> for definition of definitionSchemas Backbone.Mediator.addDefSchemas definitionSchemas[definition] +setUpMoment = -> + {me} = require 'lib/auth' + moment.lang me.lang(), {} + me.on 'change', (me) -> + moment.lang me.lang(), {} if me._previousAttributes.preferredLanguage isnt me.get 'preferredLanguage' + initializeServices = -> services = [ './lib/services/filepicker' @@ -93,3 +98,5 @@ watchForErrors = -> #msg += "\nError: #{error}" if error? #msg += "\nStack: #{stack}" if stack = error?.stack noty text: msg, layout: 'topCenter', type: 'error', killer: false, timeout: 5000, dismissQueue: true, maxVisible: 3, callback: {onClose: -> --currentErrors} + +$ -> init() diff --git a/app/lib/forms.coffee b/app/lib/forms.coffee index c617fa06d..86fe1530d 100644 --- a/app/lib/forms.coffee +++ b/app/lib/forms.coffee @@ -11,6 +11,7 @@ module.exports.formToObject = (el) -> module.exports.applyErrorsToForm = (el, errors, warning=false) -> errors = [errors] if not $.isArray(errors) + missingErrors = [] for error in errors if error.dataPath prop = error.dataPath[1..] @@ -23,8 +24,10 @@ module.exports.applyErrorsToForm = (el, errors, warning=false) -> message = error.message if error.formatted prop = error.property - setErrorToProperty el, prop, message, warning + missingErrors.push error unless setErrorToProperty el, prop, message, warning + missingErrors +# Returns the jQuery form group element in case of success, otherwise undefined module.exports.setErrorToField = setErrorToField = (el, message, warning=false) -> formGroup = el.closest('.form-group') unless formGroup.length diff --git a/app/lib/image_filter.coffee b/app/lib/image_filter.coffee index 11bf70d76..20a2ec9ae 100644 --- a/app/lib/image_filter.coffee +++ b/app/lib/image_filter.coffee @@ -28,10 +28,12 @@ Filters.brightness = (pixels, adjustment) -> i+=4 return pixels -module.exports.darkenImage = darkenImage = (img, pct=0.5) -> +module.exports.darkenImage = darkenImage = (img, borderImageSelector, pct=0.5) -> jqimg = $(img) cachedValue = jqimg.data('darkened') - return img.src = cachedValue if cachedValue + if cachedValue + $(borderImageSelector).css 'border-image-source', 'url(' + cachedValue + ')' + return img.src = cachedValue jqimg.data('original', img.src) unless jqimg.data('original') if not (img.naturalWidth > 0 and img.naturalHeight > 0) console.warn 'Tried to darken image', img, 'but it has natural dimensions', img.naturalWidth, img.naturalHeight @@ -41,9 +43,11 @@ module.exports.darkenImage = darkenImage = (img, pct=0.5) -> ctx = c.getContext('2d') ctx.putImageData(imageData, 0, 0) img.src = c.toDataURL() + $(borderImageSelector).css 'border-image-source', 'url(' + img.src + ')' jqimg.data('darkened', img.src) -module.exports.revertImage = revertImage = (img) -> +module.exports.revertImage = revertImage = (img, borderImageSelector) -> jqimg = $(img) return unless jqimg.data('original') + $(borderImageSelector).css 'border-image-source', 'url(' + jqimg.data('original') + ')' img.src = jqimg.data('original') diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee index b05fe99db..92d2a5f9b 100644 --- a/app/lib/surface/CocoSprite.coffee +++ b/app/lib/surface/CocoSprite.coffee @@ -391,7 +391,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass rotationType = @thangType.get('rotationType') return if rotationType is 'fixed' rotation = @getRotation() - if @thangType.get('name') in ['Arrow', 'Spear'] + if @thangType.get('name') in ['Arrow', 'Spear'] and @thang.velocity # Rotates the arrow to see it arc based on velocity.z. # Notice that rotation here does not affect thang's state - it is just the effect. # Thang's rotation is always pointing where it is heading. @@ -597,7 +597,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass if @thangType.get('name') in ['Arrow', 'Spear'] and @thang.action is 'die' @marks.shadow?.hide() mark.update() for name, mark of @marks - #@thang.effectNames = ['berserk', 'confuse', 'control', 'curse', 'fear', 'poison', 'paralyze', 'regen', 'sleep', 'slow', 'haste'] + #@thang.effectNames = ['warcry', 'confuse', 'control', 'curse', 'fear', 'poison', 'paralyze', 'regen', 'sleep', 'slow', 'haste'] @updateEffectMarks() if @thang?.effectNames?.length or @previousEffectNames?.length updateEffectMarks: -> diff --git a/app/lib/surface/SpriteBoss.coffee b/app/lib/surface/SpriteBoss.coffee index fb30b505a..634d5ea2d 100644 --- a/app/lib/surface/SpriteBoss.coffee +++ b/app/lib/surface/SpriteBoss.coffee @@ -180,7 +180,11 @@ module.exports = class SpriteBoss extends CocoClass adjustSpriteExistence: -> # Add anything new, remove anything old, update everything current updateCache = false + itemsJustEquipped = [] for thang in @world.thangs when thang.exists + if thang.equip and not thang.equipped + thang.equip() # Pretty hacky, since initialize may not be called + itemsJustEquipped.push thang if sprite = @sprites[thang.id] sprite.setThang thang # make sure Sprite has latest Thang else @@ -188,6 +192,7 @@ module.exports = class SpriteBoss extends CocoClass Backbone.Mediator.publish 'surface:new-thang-added', thang:thang, sprite:sprite updateCache = updateCache or sprite.imageObject.parent is @spriteLayers['Obstacle'] sprite.playSounds() + item.modifyStats() for item in itemsJustEquipped for thangID, sprite of @sprites missing = not (sprite.notOfThisWorld or @world.thangMap[thangID]?.exists) isObstacle = sprite.imageObject.parent is @spriteLayers['Obstacle'] diff --git a/app/lib/world/world.coffee b/app/lib/world/world.coffee index f94a6d26a..ca61daddb 100644 --- a/app/lib/world/world.coffee +++ b/app/lib/world/world.coffee @@ -240,7 +240,7 @@ module.exports = class World calculateBounds: -> bounds = {left: 0, top: 0, right: 0, bottom: 0} hasLand = _.some @thangs, 'isLand' - for thang in @thangs when thang.isLand or not hasLand # Look at Lands only + for thang in @thangs when thang.isLand or (not hasLand and thang.rectangle) # Look at Lands only rect = thang.rectangle().axisAlignedBoundingBox() bounds.left = Math.min(bounds.left, rect.x - rect.width / 2) bounds.right = Math.max(bounds.right, rect.x + rect.width / 2) diff --git a/app/locale/de-CH.coffee b/app/locale/de-CH.coffee index d83d4959a..770f088a0 100644 --- a/app/locale/de-CH.coffee +++ b/app/locale/de-CH.coffee @@ -1,7 +1,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "German (Switzerland)", translation: common: loading: "Lade..." - saving: "Spiichere..." + saving: "Speichere..." sending: "Sende..." send: "G'sendet" cancel: "Abbreche" @@ -40,7 +40,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge okay: "Okay" not_found: - page_not_found: "Siite nöd gfunde" + page_not_found: "Siite nid gfunde" nav: play: "Levels" @@ -51,8 +51,8 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge account: "Account" admin: "Admin" home: "Home" - contribute: "Spende" -# legal: "Legal" + contribute: "Mitmache" + legal: "Rechtlichs" about: "Über" contact: "Kontakt" twitter_follow: "Folge" @@ -100,26 +100,26 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge for_beginners: "Für Afänger" multiplayer: "Multiplayer" for_developers: "Für Entwickler" -# javascript_blurb: "The language of the web. Great for writing websites, web apps, HTML5 games, and servers." -# python_blurb: "Simple yet powerful, Python is a great general purpose programming language." -# coffeescript_blurb: "Nicer JavaScript syntax." + javascript_blurb: "D Internetsproch. Super zum Websiite, Web Apps, HTML5 Games und Server schriibe." + python_blurb: "Eifach und doch mächtig. Python isch grossartigi, allgemein isetzbari Programmiersproch." + coffeescript_blurb: "Nettere JavaScript Syntax." # clojure_blurb: "A modern Lisp." -# lua_blurb: "Game scripting language." -# io_blurb: "Simple but obscure." + lua_blurb: "D Sproch für Game Scripts." + io_blurb: "Eifach aber undurchsichtig." play: choose_your_level: "Wähl dis Level us" - adventurer_prefix: "Du chasch zu de untere Level zrugg goh oder die kommende Level diskutiere " - adventurer_forum: "s Abentürer-Forum" -# adventurer_suffix: "." + adventurer_prefix: "Du chasch zu de untere Level zrugg goh oder die kommende Level diskutiere im " + adventurer_forum: "Abentürer-Forum" + adventurer_suffix: "." campaign_beginner: "Afängerkampagne" campaign_beginner_description: "... i dere du d Zauberkunst vom Programmiere lernsch." campaign_dev: "Zuefälligi schwierigeri Level" campaign_dev_description: "... i dene du s Interface kenne lernsch, während du öppis chli Schwierigers machsch." campaign_multiplayer: "Multiplayer Arenas" campaign_multiplayer_description: "... i dene du Chopf a Chopf geg anderi Spieler spielsch." -# campaign_player_created: "Player-Created" -# campaign_player_created_description: "... in which you battle against the creativity of your fellow Artisan Wizards." + campaign_player_created: "Vo Spieler erstellti Level" + campaign_player_created_description: "... i dene du gege d Kreativität vome Handwerker Zauberer kämpfsch." level_difficulty: "Schwierigkeit: " play_as: "Spiel als" spectate: "Zueluege" @@ -127,21 +127,21 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge contact: contact_us: "CodeCombat kontaktiere" welcome: "Mir ghöred gern vo dir! Benutz das Formular zum üs e E-Mail schicke." - contribute_prefix: "Wenn du dra interessiert bisch, mitzhelfe denn lueg doch mol verbii uf üsere" + contribute_prefix: "Wenn du dra interessiert bisch, mitzhelfe denn lueg doch mol verbii uf üsere " contribute_page: "Contribute Page" -# contribute_suffix: "!" - forum_prefix: "Für öffentlichi Sache versuechs mol bi" + contribute_suffix: "!" + forum_prefix: "Für öffentlichi Sache versuechs mol stattdesse i " forum_page: "üsem Forum" - forum_suffix: " stattdesse." + forum_suffix: "." send: "Feedback schicke" -# contact_candidate: "Contact Candidate" -# recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 15% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns." + contact_candidate: "Kandidat kontaktiere" + recruitment_reminder: "Benutz das Formular zum mit Kandidate Kontakt ufneh, i die du interessiert bisch. Bhalt in Erinnerig, dass CodeCombat 15% vom erstjöhrige Lohn verrechnet. De Betrag wird fällig, sobald de Programmierer agstellt wird und chan 90 Täg lang zruggverrechnet werde wenn de Agstellti nid agstellt bliibt. Teilziitarbeit, Fernarbeit und temporäri Agstellti sind chostelos, s gliiche gilt für Interni Mitarbeiter." diplomat_suggestion: title: "Hilf, CodeCombat z übersetze!" sub_heading: "Mir bruuched dini Sprochfähigkeite." pitch_body: "Mir entwickled CodeCombat in Englisch, aber mir hend scho Spieler uf de ganze Welt. Vieli devo würed gern uf Schwiizerdütsch spiele, aber chönd kei Englisch. Wenn du beides chasch, denk doch mol drüber noh, dich bi üs als Diplomat izträge und z helfe, d CodeCombat Websiite und alli Level uf Schwiizerdütsch z übersetze." - missing_translations: "Until we can translate everything into Swiss German, you'll see generic German or English when Swiss German isn't available." + missing_translations: "Bis mir alles chönd uf Schwiizerdütsch übersetze wirsch du döt generisches Dütsch oder Englisch gseh, wo Schwiizerdütsch nid verfüegbar isch." learn_more: "Lern meh drüber, en Diplomat zsii" subscribe_as_diplomat: "Abonnier als en Diplomat" @@ -152,7 +152,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge color: "Farb" group: "Gruppe" clothes: "Chleider" - trim: "Zueschniide" + trim: "Deko" cloud: "Wolke" team: "Team" spell: "Zauberspruch" @@ -219,93 +219,93 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge next_name: "Name?" next_short_description: "schriibe e churzi Beschriibig." next_long_description: "beschriib dini Wunschstell." -# next_skills: "list at least five skills." -# next_work: "chronicle your work history." + next_skills: "liste mindestens füf Fähigkeite uf." + next_work: "liste din bruefliche Werdegang uf." # next_education: "recount your educational ordeals." next_projects: "Zeig üs bis zu drü Projekt a dene du scho gschaffet hesch." next_links: "füeg persönlichi oder Social Media Links ih." -# next_photo: "add an optional professional photo." -# next_active: "mark yourself open to offers to show up in searches." + next_photo: "füeg optional es professionells Foti hinzue." + next_active: "markier dich selber als offe für Agebot zum i Suechafroge uftauche." example_blog: "Blog" example_personal_site: "Eigeni Websiite" links_header: "Eigeni Links" -# links_blurb: "Link any other sites or profiles you want to highlight, like your GitHub, your LinkedIn, or your blog." -# links_name: "Link Name" -# links_name_help: "What are you linking to?" -# links_link_blurb: "Link URL" -# basics_header: "Update basic info" -# basics_active: "Open to Offers" -# basics_active_help: "Want interview offers right now?" -# basics_job_title: "Desired Job Title" -# basics_job_title_help: "What role are you looking for?" -# basics_city: "City" -# basics_city_help: "City you want to work in (or live in now)." -# basics_country: "Country" -# basics_country_help: "Country you want to work in (or live in now)." -# basics_visa: "US Work Status" -# basics_visa_help: "Are you authorized to work in the US, or do you need visa sponsorship? (If you live in Canada or Australia, mark authorized.)" -# basics_looking_for: "Looking For" -# basics_looking_for_full_time: "Full-time" -# basics_looking_for_part_time: "Part-time" + links_blurb: "Verlinke anderi Sitene oder Profil wo du willsch hervorhebe, wie zum Bispiel dis GitHub, dis LinkedIn Profil oder din Blog." + links_name: "Link Name" + links_name_help: "Woane verlinksch?" + links_link_blurb: "Link URL" + basics_header: "Eifachi infos update" + basics_active: "Offe für Agebot" + basics_active_help: "Wötsch ez gad Interview Agebot?" + basics_job_title: "Erwünschte Job Titel" + basics_job_title_help: "Noch welem Job suechsch?" + basics_city: "Stadt" + basics_city_help: "D Stadt wo du willsch schaffe (oder im Moment wohnsch)." + basics_country: "Land" + basics_country_help: "Country you want to work in (or live in now)." + basics_visa: "US Work Status" + basics_visa_help: "Hesch du d Berechtigung zum i de USA schaffe oder bruchsch du e Visa Sponsorship? (Wenn du in Kanada oder Australie wohnsch, markier als berechtigt.)" + basics_looking_for: "Ich sueche nach" + basics_looking_for_full_time: "Vollziit" + basics_looking_for_part_time: "Teilziit" # basics_looking_for_remote: "Remote" # basics_looking_for_contracting: "Contracting" -# basics_looking_for_internship: "Internship" -# basics_looking_for_help: "What kind of developer position do you want?" -# name_header: "Fill in your name" -# name_anonymous: "Anonymous Developer" -# name_help: "Name you want employers to see, like 'Nick Winter'." -# short_description_header: "Write a short description of yourself" -# short_description_blurb: "Add a tagline to help an employer quickly learn more about you." -# short_description: "Tagline" -# short_description_help: "Who are you, and what are you looking for? 140 characters max." -# skills_header: "Skills" -# skills_help: "Tag relevant developer skills in order of proficiency." -# long_description_header: "Describe your desired position" -# long_description_blurb: "Tell employers how awesome you are and what role you want." -# long_description: "Self Description" -# long_description_help: "Describe yourself to potential employers. Keep it short and to the point. We recommend outlining the position that would most interest you. Tasteful markdown okay; 600 characters max." -# work_experience: "Work Experience" -# work_header: "Chronicle your work history" -# work_years: "Years of Experience" -# work_years_help: "How many years of professional experience (getting paid) developing software do you have?" -# work_blurb: "List your relevant work experience, most recent first." -# work_employer: "Employer" -# work_employer_help: "Name of your employer." -# work_role: "Job Title" -# work_role_help: "What was your job title or role?" -# work_duration: "Duration" -# work_duration_help: "When did you hold this gig?" -# work_description: "Description" -# work_description_help: "What did you do there? (140 chars; optional)" -# education: "Education" + basics_looking_for_internship: "Praktikum" + basics_looking_for_help: "Weli Art vo Entwicklerposition möchtisch du?" + name_header: "Füll din Name us" + name_anonymous: "Anonyme Entwickler" + name_help: "De Name wo d Entwickler söled gseh, z.B. 'Nick Winter'." + short_description_header: "Schriib e churzi Beschriibi vo dir." + short_description_blurb: "Füeg e Tagline hinzue, damit Arbeitgeber chönd schnell öppis über dich erfahre." + short_description: "Tagline" + short_description_help: "Wer bisch du und noch wa suechsch? 140 Charakter max." + skills_header: "Fähigkeite" + skills_help: "Tagge relevanti Entwicklerfähigkeite gordnet nach Kenntnis." + long_description_header: "Beschriib dini Wunschposition" + long_description_blurb: "Verzell de Arbetgeber wie fantastisch du bisch und weli Position du gern hettsch." + long_description: "Selbstbeschriibig" + long_description_help: "Beschriib dich de potentielle Arbetgeber. Halte es churz und relevant. Mir empfehled, churz d Position z umrahme, wo dich am meiste interessiert. Stilvolli Herabsetzig okay; 600 Charakter max." + work_experience: "Arbeitserfahrig" + work_header: "Liste dini Arbeitserfahrig uf" + work_years: "Johr a Arbeitserfahrig" + work_years_help: "Wieviel (bezahlti) Johre Erfahrig hesch du im Bereich Softwareentwicklig?" + work_blurb: "Liste dini relevant Arbeitserfahrig uf, s neuste als Ersts." + work_employer: "Arbeitgeber" + work_employer_help: "Name vo dim Arbeitgeber." + work_role: "Job Titel" + work_role_help: "Was hesch für en Job Titel / Position gha?" + work_duration: "Ziitduur" + work_duration_help: "Wenn hesch die Astellig gha?" + work_description: "Beschriibig" + work_description_help: "Wa hesch du det gmacht? (140 Charakter; optional)" + education: "Usbildig" # education_header: "Recount your academic ordeals" # education_blurb: "List your academic ordeals." -# education_school: "School" -# education_school_help: "Name of your school." -# education_degree: "Degree" -# education_degree_help: "What was your degree and field of study?" -# education_duration: "Dates" -# education_duration_help: "When?" -# education_description: "Description" -# education_description_help: "Highlight anything about this educational experience. (140 chars; optional)" + education_school: "Schuel" + education_school_help: "De Name vo dinere Schuel." + education_degree: "Abschluss" + education_degree_help: "Was isch din Abschluss und dis Studiefach gsi?" + education_duration: "Date" + education_duration_help: "Wenn?" + education_description: "Beschriibig" + education_description_help: "Öppis wo du willsch hervorhebe bezüglich dere Usbildig. (140 Charakter; optional)" # our_notes: "CodeCombat's Notes" -# remarks: "Remarks" -# projects: "Projects" -# projects_header: "Add 3 projects" -# projects_header_2: "Projects (Top 3)" -# projects_blurb: "Highlight your projects to amaze employers." -# project_name: "Project Name" -# project_name_help: "What was the project called?" -# project_description: "Description" -# project_description_help: "Briefly describe the project." -# project_picture: "Picture" -# project_picture_help: "Upload a 230x115px or larger image showing off the project." -# project_link: "Link" -# project_link_help: "Link to the project." + remarks: "Bemerkige" + projects: "Projekt" + projects_header: "Füeg 3 Projekt hinzue" + projects_header_2: "Projekt (Top 3)" + projects_blurb: "Hebe dini Projekt hervor zum Arbeitgeber in Stuune z versetze." + project_name: "Projektname" + project_name_help: "Wie het s Projekt gheisse?" + project_description: "Beschriibig" + project_description_help: "Beschriib churz dis Projekt." + project_picture: "Bild" + project_picture_help: "Lad es Bild ufe wo 230x115px oder grösser isch zum dis Projekt präsentiere." + project_link: "Link" + project_link_help: "Link zum Projekt." # player_code: "Player Code" # employers: -# hire_developers_not_credentials: "Hire developers, not credentials." + hire_developers_not_credentials: "Stell Entwickler ah, nid Zügnis." # get_started: "Get Started" # already_screened: "We've already technically screened all our candidates" # filter_further: ", but you can also filter further:" @@ -381,94 +381,94 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge multiplayer_link_description: "Gib de Link jedem, wo mit dir will spiele." multiplayer_hint_label: "Hiiwis:" multiplayer_hint: " Klick uf de Link zum alles uswähle und druck ⌘-C or Ctrl-C zum de Link kopiere" -# multiplayer_coming_soon: "More multiplayer features to come!" + multiplayer_coming_soon: "Meh Multiplayer Features chömed no!" # multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard." -# guide_title: "Guide" -# tome_minion_spells: "Your Minions' Spells" -# tome_read_only_spells: "Read-Only Spells" -# tome_other_units: "Other Units" -# tome_cast_button_castable: "Cast Spell" -# tome_cast_button_casting: "Casting" + guide_title: "Handbuech" + tome_minion_spells: "Zaubersprüch vo dine Minions" + tome_read_only_spells: "Read-Only Zaubersprüch" + tome_other_units: "Anderi Einheite" + tome_cast_button_castable: "Zauber beschwöre" + tome_cast_button_casting: "Wird beschwore" # tome_cast_button_cast: "Spell Cast" # tome_autocast_delay: "Autocast Delay" -# tome_select_spell: "Select a Spell" -# tome_select_a_thang: "Select Someone for " -# tome_available_spells: "Available Spells" -# hud_continue: "Continue (shift+space)" -# spell_saved: "Spell Saved" -# skip_tutorial: "Skip (esc)" + tome_select_spell: "Wähl en Zauberspruch us" + tome_select_a_thang: "Wähl öpper us für" + tome_available_spells: "Verfüegbari Zaubersprüch" + hud_continue: "Wiiter (shift+space)" + spell_saved: "Zauberspruch gspeicheret" + skip_tutorial: "Überspringe (esc)" # editor_config: "Editor Config" -# editor_config_title: "Editor Configuration" -# editor_config_level_language_label: "Language for This Level" -# editor_config_level_language_description: "Define the programming language for this particular level." -# editor_config_default_language_label: "Default Programming Language" -# editor_config_default_language_description: "Define the programming language you want to code in when starting new levels." + editor_config_title: "Editor Konfiguration" + editor_config_level_language_label: "Sproch für das Level" + editor_config_level_language_description: "Wähl d Programmiersproch us für das bestimmte Level." + editor_config_default_language_label: "Vorigstellti Programmiersproch" + editor_config_default_language_description: "Wähl us i welere Programmiersproch du willsch code wenn du es neus Level startisch." # editor_config_keybindings_label: "Key Bindings" -# editor_config_keybindings_default: "Default (Ace)" + editor_config_keybindings_default: "Voristellig (Ace)" # editor_config_keybindings_description: "Adds additional shortcuts known from the common editors." -# editor_config_livecompletion_label: "Live Autocompletion" -# editor_config_livecompletion_description: "Displays autocomplete suggestions while typing." -# editor_config_invisibles_label: "Show Invisibles" -# editor_config_invisibles_description: "Displays invisibles such as spaces or tabs." -# editor_config_indentguides_label: "Show Indent Guides" -# editor_config_indentguides_description: "Displays vertical lines to see indentation better." -# editor_config_behaviors_label: "Smart Behaviors" -# editor_config_behaviors_description: "Autocompletes brackets, braces, and quotes." -# keyboard_shortcuts: "Key Shortcuts" + editor_config_livecompletion_label: "Live Auto-Vervollständigung" + editor_config_livecompletion_description: "Schlot dir möglichi Wortvervollständigunge vor während du tippsch." + editor_config_invisibles_label: "Unsichtbari Zeiche azeige" + editor_config_invisibles_description: "Zeigt unsichtbari Zeiche ah wie z.B. space und tab." + editor_config_indentguides_label: "Izüg azeige" + editor_config_indentguides_description: "Zeigt vertikali Linie zum de Zeileizug besser gseh." + editor_config_behaviors_label: "Intelligents Verhalte" + editor_config_behaviors_description: "Auto-vervollständigt Chlammere und Ahfüerigszeiche." + keyboard_shortcuts: "Shortcuts" # loading_ready: "Ready!" -# tip_insert_positions: "Shift+Click a point on the map to insert it into the spell editor." -# tip_toggle_play: "Toggle play/paused with Ctrl+P." + tip_insert_positions: "Shift+Klick uf en Punkt uf de Charte zums in Zauberspruch-Editor ifüege." + tip_toggle_play: "Play/Pausiert mit Ctrl+P ischalte." # tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward." -# tip_guide_exists: "Click the guide at the top of the page for useful info." -# tip_open_source: "CodeCombat is 100% open source!" -# tip_beta_launch: "CodeCombat launched its beta in October, 2013." -# tip_js_beginning: "JavaScript is just the beginning." -# tip_autocast_setting: "Adjust autocast settings by clicking the gear on the cast button." -# think_solution: "Think of the solution, not the problem." -# tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra" -# tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis" -# tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra" -# tip_forums: "Head over to the forums and tell us what you think!" -# tip_baby_coders: "In the future, even babies will be Archmages." -# tip_morale_improves: "Loading will continue until morale improves." -# tip_all_species: "We believe in equal opportunities to learn programming for all species." -# tip_reticulating: "Reticulating spines." -# tip_harry: "Yer a Wizard, " -# tip_great_responsibility: "With great coding skill comes great debug responsibility." -# tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep." -# tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't." -# tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda" -# tip_no_try: "Do. Or do not. There is no try. - Yoda" -# tip_patience: "Patience you must have, young Padawan. - Yoda" -# tip_documented_bug: "A documented bug is not a bug; it is a feature." -# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela" -# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds" -# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay" -# tip_hardware_problem: "Q: How many programmers does it take to change a light bulb? A: None, it's a hardware problem." -# time_current: "Now:" -# time_total: "Max:" -# time_goto: "Go to:" -# infinite_loop_try_again: "Try Again" -# infinite_loop_reset_level: "Reset Level" -# infinite_loop_comment_out: "Comment Out My Code" + tip_guide_exists: "Klick ufs Handbuech im obere Teil vo de Siite zum nützlichi Infos becho." + tip_open_source: "CodeCombat isch 100% Open Source!" + tip_beta_launch: "D CodeCombat Beta isch im Oktober 2013 online gange." + tip_js_beginning: "JavaScript isch nur de Afang." + tip_autocast_setting: "Passe d Auto-Beschwöre Istellige ah, indem du ufs Zahrad bim Beschwöre-Chnopf drucksch." + think_solution: "Denk über d Lösig noh, nid über s Problem." + tip_theory_practice: "Theoretisch gits kein Unterschied zwüsche Theorie und Praxis. Praktisch aber scho. - Yogi Berra" + tip_error_free: "Es git zwei Arte zum fehlerfreii Programm schriibe; nur di dritt funktioniert. - Alan Perils" + tip_debugging_program: "Wenn Debugging de Prozess isch, mit dem mehr Bugs entfernt, denn mues Programmiere de sii, mit dem mer sie dri tuet. - Edsger W. Dijkstra" + tip_forums: "Chum übere is Forum und verzell üs, wa du denksch!" + tip_baby_coders: "I de Zuekunft werded sogar Babies Erzmagier sii." + tip_morale_improves: "Es ladet bis d Moral besser worde isch..." + tip_all_species: "Mir glaubed a gliichi Möglichkeite zum Programmiere lerne für alli Lebewese." + tip_reticulating: "Rückgrat isch am wachse..." + tip_harry: "Yer a Wizard, " + tip_great_responsibility: "Mit grosse Coding Skills chunt grossi Debug Verantwortig." + tip_munchkin: "Wenn du dis Gmües nid issisch, chunt dich en Zwerg go hole wenn du schlofsch." + tip_binary: "Es git 10 Arte vo Mensche uf de Welt: die wo s Binärsystem verstönd und die wos nid verstönd." + tip_commitment_yoda: "En Programmierer mues tüüfsti Higob ha, en konzentrierte Geist. - Yoda" + tip_no_try: "Machs. Oder machs nid. Probiere existiert nid. - Yoda" + tip_patience: "Geduld du bruuchsch, junge Padawan. - Yoda" + tip_documented_bug: "En dokumentierte Bug isch kein Bug; es isch es Feature." + tip_impossible: "Es schiint immer unmöglich bis es gschafft isch. - Nelson Mandela" + tip_talk_is_cheap: "Rede isch billig. Zeig mir de Code. - Linus Torvalds" + tip_first_language: "S Katastrophalste wo du chasch lerne, isch dini erst Programmiersproch. - Alan Kay" + tip_hardware_problem: "Q: Wie viel Programmierer bruuchts zum e Glüehbire uswechsle? A: Keine, da isch es Hardware Problem." + time_current: "Jetzt:" + time_total: "Max:" + time_goto: "Goh zu:" + infinite_loop_try_again: "Versuechs nomol" + infinite_loop_reset_level: "Level zrugsetze" + infinite_loop_comment_out: "Min Code uskommentiere" -# keyboard_shortcuts: -# keyboard_shortcuts: "Keyboard Shortcuts" -# space: "Space" -# enter: "Enter" -# escape: "Escape" -# cast_spell: "Cast current spell." -# continue_script: "Continue past current script." -# skip_scripts: "Skip past all skippable scripts." -# toggle_playback: "Toggle play/pause." -# scrub_playback: "Scrub back and forward through time." -# single_scrub_playback: "Scrub back and forward through time by a single frame." -# scrub_execution: "Scrub through current spell execution." -# toggle_debug: "Toggle debug display." -# toggle_grid: "Toggle grid overlay." -# toggle_pathfinding: "Toggle pathfinding overlay." -# beautify: "Beautify your code by standardizing its formatting." -# move_wizard: "Move your Wizard around the level." + keyboard_shortcuts: + keyboard_shortcuts: "Shortcuts uf de Tastatur" + space: "Space" + enter: "Enter" + escape: "Escape" + cast_spell: "Aktuelle Zauberspruch beschwöre." + continue_script: "Nochem aktuelle Script fortsetze." + skip_scripts: "Alli überspringbare Scripts überspringe." + toggle_playback: "Play/Pause istelle." + scrub_playback: "Reise vorwärts und zrugg i de Ziit." + single_scrub_playback: "Reise eis einzels Frame vorwärts und zrugg i de Ziit." + scrub_execution: "Gang dur d Zauberusfüehrig." + toggle_debug: "Debug Display ischalte/usschalte." + toggle_grid: "Gitter ischalte/usschalte." + toggle_pathfinding: "Wegfinder ischalte/usschalte." + beautify: "Mach din Code schöner, indem du sini Formatierig standartisiersch." + move_wizard: "Beweg din Zauberer durs Level." # admin: # av_title: "Admin Views" @@ -482,12 +482,12 @@ 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+" + community: + level_editor: "Level Editor" + main_title: "CodeCombat Community" + facebook: "Facebook" + twitter: "Twitter" + gplus: "Google+" # editor: # main_title: "CodeCombat Editors" @@ -590,55 +590,55 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge # hard: "Hard" # player: "Player" -# about: -# who_is_codecombat: "Who is CodeCombat?" -# why_codecombat: "Why CodeCombat?" -# who_description_prefix: "together started CodeCombat in 2013. We also created " -# who_description_suffix: "in 2008, growing it to the #1 web and iOS application for learning to write Chinese and Japanese characters." -# who_description_ending: "Now it's time to teach people to write code." -# why_paragraph_1: "When making Skritter, George didn't know how to program and was constantly frustrated by his inability to implement his ideas. Afterwards, he tried learning, but the lessons were too slow. His housemate, wanting to reskill and stop teaching, tried Codecademy, but \"got bored.\" Each week another friend started Codecademy, then dropped off. We realized it was the same problem we'd solved with Skritter: people learning a skill via slow, intensive lessons when what they need is fast, extensive practice. We know how to fix that." -# why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it." -# why_paragraph_3_prefix: "That's what programming is about. It's gotta be fun. Not fun like" -# why_paragraph_3_italic: "yay a badge" -# why_paragraph_3_center: "but fun like" -# why_paragraph_3_italic_caps: "NO MOM I HAVE TO FINISH THE LEVEL!" -# why_paragraph_3_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing." -# why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age." -# why_ending: "And hey, it's free. " -# why_ending_url: "Start wizarding now!" -# george_description: "CEO, business guy, web designer, game designer, and champion of beginning programmers everywhere." -# scott_description: "Programmer extraordinaire, software architect, kitchen wizard, and master of finances. Scott is the reasonable one." -# nick_description: "Programming wizard, eccentric motivation mage, and upside-down experimenter. Nick can do anything and chooses to build CodeCombat." -# jeremy_description: "Customer support mage, usability tester, and community organizer; you've probably already spoken with Jeremy." -# michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online." -# glen_description: "Programmer and passionate game developer, with the motivation to make this world a better place, by developing things that matter. The word impossible can't be found in his dictionary. Learning new skills is his joy!" + about: + who_is_codecombat: "Wer isch CodeCombat?" + why_codecombat: "Warum CodeCombat?" + who_description_prefix: "hend im 2013 zeme CodeCombat gstartet. Mir hend au " + who_description_suffix: "im 2008 kreiert und drufabe isches zur Nummer 1 Web und iOS App zum Chinesischi und Japanischi Charakter schriibe worde." + who_description_ending: "Ez isches Ziit zum de Mensche biibringe wie sie Code schriibed." + why_paragraph_1: "Womer Skritter gmacht hend, het de George nid gwüsst wiemer programmiert und isch dauernd gfrustet gsi, will er unfähig gsi isch, sini Ideä z implementiere. Spöter het er probiert zums lerne, aber d Lektione sind z langsam gsi. Sin Mitbewohner, wo het wöle sini Fähigkeite uffrische und ufhöre sie öpperem biizbringe, het Codecademy probiert, aber ihm isch \"langwiilig worde\". Jedi Wuche het en andere Fründ agfange mit Codecademy und het wieder ufghört. Mir hend realisiert, dass es s gliiche Problem isch, wo mir mit Skitter glöst gha hend: Lüüt, wo öppis mit langsame, intensive Lektione lerned, obwohl sie schnelli, umfangriichi Üebig bruuched. Mir wüssed, wie mer das behebe." + why_paragraph_2: "Du muesch Programmiere lerne? Du bruchsch kei Lektione. Wa du bruuchsch, isch ganz viel Code schriibe und viel Spass ha, während du das machsch." + why_paragraph_3_prefix: "Um da gohts bim Programmiere. Es mues Spass mache. Nid Spass wie" + why_paragraph_3_italic: "wuhu en Badge" + why_paragraph_3_center: "eher Spass wie" + why_paragraph_3_italic_caps: "NEI MAMI, ICH MUES DAS LEVEL NO FERTIG MACHE!" + why_paragraph_3_suffix: "Darum isch CodeCombat es Multiplayer Spiel, nid en gamifizierte Kurs mit Lektione. Mir stopped nid, bis du nümm chasch stoppe--aber damol isch da öppis guets." + why_paragraph_4: "Wenn du süchtig wirsch nochme Spiel, wird süchtig noch dem Spiel und wird eine vo de Zauberer vom Tech-Ziitalter." + why_ending: "Und hey, es isch gratis. " + why_ending_url: "Fang ez a zaubere!" + george_description: "CEO, Business-Typ, Web Designer, Game Designer und de Held für d Programmierafänger uf de ganze Welt." + scott_description: "Programmierer extraordinaire, Software Architekt, Chuchi-Zauberer und de Meister vo de Finanze. De Scott isch de Vernünftig unter üs." + nick_description: "Programmier-Zauberer, exzentrische Motivations-Magier und Chopfüber-Experimentierer. De Nick chönti alles mache und het sich entschiede zum CodeCombat baue." + jeremy_description: "Kundesupport-Magier, Usability Tester und Community-Organisator; du hesch worschinli scho mitem Jeremy gredet." + michael_description: "Programmierer, Systemadmin und es technisches Wunderchind ohni Studium. Michael isch die Person wo üsi Server am Laufe bhaltet." + glen_description: "Programmierer und passionierte Gameentwickler mit de Motivation, die Welt zumene bessere Ort zmache, indem mer Sache entwickled wo e Rolle spieled. S Wort unmöglich findet mer nid i sim Wortschatz. Neui Fähigkeite erlerne isch sini Freud!" -# legal: -# page_title: "Legal" -# opensource_intro: "CodeCombat is free to play and completely open source." -# opensource_description_prefix: "Check out " -# github_url: "our GitHub" -# opensource_description_center: "and help out if you like! CodeCombat is built on dozens of open source projects, and we love them. See " -# archmage_wiki_url: "our Archmage wiki" -# opensource_description_suffix: "for a list of the software that makes this game possible." -# practices_title: "Respectful Best Practices" -# practices_description: "These are our promises to you, the player, in slightly less legalese." -# privacy_title: "Privacy" -# privacy_description: "We will not sell any of your personal information. We intend to make money through recruitment eventually, but rest assured we will not distribute your personal information to interested companies without your explicit consent." -# security_title: "Security" -# security_description: "We strive to keep your personal information safe. As an open source project, our site is freely open to anyone to review and improve our security systems." -# email_title: "Email" -# email_description_prefix: "We will not inundate you with spam. Through" -# email_settings_url: "your email settings" -# email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time." -# cost_title: "Cost" -# cost_description: "Currently, CodeCombat is 100% free! One of our main goals is to keep it that way, so that as many people can play as possible, regardless of place in life. If the sky darkens, we might have to charge subscriptions or for some content, but we'd rather not. With any luck, we'll be able to sustain the company with:" -# recruitment_title: "Recruitment" -# recruitment_description_prefix: "Here on CodeCombat, you're going to become a powerful wizard–not just in the game, but also in real life." -# url_hire_programmers: "No one can hire programmers fast enough" -# recruitment_description_suffix: "so once you've sharpened your skills and if you agree, we will demo your best coding accomplishments to the thousands of employers who are drooling for the chance to hire you. They pay us a little, they pay you" -# recruitment_description_italic: "a lot" -# recruitment_description_ending: "the site remains free and everybody's happy. That's the plan." + legal: + page_title: "Rechtlichs" + opensource_intro: "CodeCombat isch free to play und komplett Open Source." + opensource_description_prefix: "Lueg dir " + github_url: "üsi GitHub Siite" + opensource_description_center: "ah und hilf mit, wennd magsch! CodeCombat isch uf dutzendi Open Source Projekt ufbaut und mir liebed sie. Lueg i " + archmage_wiki_url: "üses Erzmagier-Wiki" + opensource_description_suffix: "ine zum d Liste a de Software finde, wo das Game möglich mached." + practices_title: "Respektvolli bewährti Praxis" + practices_description: "Das sind üsi Verspreche a dich, de Spieler, in bitz weniger Fachchinesisch." + privacy_title: "Dateschutz" + privacy_description: "Mir verchaufed kei vo dine persönliche Informatione. Mir hend vor zum irgendwenn durch Rekrutierig Geld z verdiene, aber bis versicheret, dass mir nid dini persönliche Date a interessierti Firmene wiiter gebed ohni dis usdrücklich Iverständnis." + security_title: "Sicherheit" + security_description: "Mir bemühed üs, dini persönliche Informatione sicher ufzbewahre. Als es Open Source Projekt isch üsi Siite offe für jede, wo gern möcht üsi Security System besichtige und verbessere." + email_title: "E-Mail" + email_description_prefix: "Mir werded dich nid mit Spam überfluete. I dine" + email_settings_url: "E-Mail Istellige" + email_description_suffix: "oder dur d Links i de E-Mails wo mir schicked, chasch du jederziit dini Preferänze ändere und dich ganz eifach us de Mailing-Liste neh." + cost_title: "Chöste" + cost_description: "Im Moment isch CodeCombat 100% gratis! Eis vo üsne Hauptziel isch, dass das so bliibt, damit so viel Lüüt wie möglich chönd spiele, egal wo sie sich im Lebe befinded. Sötted dunkli Wolke am Horizont ufzieh chas sii, dass mir müed en Teil vom Inhalt chostepflichtig mache, aber es isch üs lieber, wenn da nid passiert. Mit chli Glück werded mir fähig sii, s Unternehme ufrecht z erhalte und zwor mit:" + recruitment_title: "Rekrutierig" + recruitment_description_prefix: "Do uf CodeCombat wirsch du en mächtige Zauberer - nid nur ingame, sonder au im echte Lebe." + url_hire_programmers: "Niemer cha Programmierer schnell gnueg astelle" + recruitment_description_suffix: "das heisst, sobald du dini Fähigkeite gschärft hesch, und wenn du zuestimmsch, werded mir dini beste Programmiererfolg de tuusige vo Arbeitgeber zeige, wo nur druf warted, dich chöne azstelle. Sie zahled üs es bitz öppis, sie zahled dir" + recruitment_description_italic: "ziemli viel" + recruitment_description_ending: "d Siite bliibt gratis und alli sind glücklich. Das isch de Plan." # copyrights_title: "Copyrights and Licenses" # contributor_title: "Contributor License Agreement" # contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our" diff --git a/app/locale/ko.coffee b/app/locale/ko.coffee index 42e45af71..301159a1c 100644 --- a/app/locale/ko.coffee +++ b/app/locale/ko.coffee @@ -6,18 +6,18 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t send: "전송" cancel: "취소" save: "저장" -# publish: "Publish" -# create: "Create" + publish: "내보내기" + create: "생성" delay_1_sec: "1초" delay_3_sec: "3초" delay_5_sec: "5초" manual: "수동" fork: "Fork" play: "시작" -# retry: "Retry" -# watch: "Watch" -# unwatch: "Unwatch" -# submit_patch: "Submit Patch" + retry: "재시도" + watch: "보기" + unwatch: "보기 해제" + submit_patch: "패치 제출" # units: # second: "second" @@ -36,8 +36,8 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # years: "years" modal: - close: "Close" - okay: "Okay" + close: "닫기" + okay: "확인" not_found: page_not_found: "페이지를 찾을 수 없습니다" @@ -105,7 +105,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t coffeescript_blurb: "향상된 자바스크립트 문법." clojure_blurb: "현대적인 Lisp." lua_blurb: "게임 스크립팅 언어" - #io_blurb: "Simple but obscure." + io_blurb: "간단하지만 아직 잘 알려지지 않은 언어." play: choose_your_level: "레벨을 선택하세요." @@ -126,7 +126,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t contact: contact_us: "코드컴뱃에 전할 말" - welcome: "의견은 언제든지 환영합니다. 이 양식을 이메일에 사용해 주세요!" + welcome: "언제든 의견을 보내주세요. 이 양식을 이메일에 사용해 주세요!" contribute_prefix: "혹시 같이 코드컴뱃에 공헌하고 싶으시다면 홈페이지를 방문해주세요." contribute_page: "참여하기 페이지" contribute_suffix: "!" @@ -134,8 +134,8 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t forum_page: "포럼" forum_suffix: " 대신에." send: "의견 보내기" -# contact_candidate: "Contact Candidate" -# recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 15% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns." + contact_candidate: "지원자에게 연락하기" + recruitment_reminder: "인터뷰를 원하는 지원자에게 연락하고자 할 때, 이 양식을 사용해주세요. 코드 컴뱃에게 반드시 첫 해 연봉의 15%를 지급해야합니다. 수수료는 직원을 고용하자마자 즉시 지급되어야 합니다. 한편 90일 이내로 채용이 취소된다면 수수료를 환불받을 수 있습니다. 아르바이트, 재택근무, 계약직은 인턴의 경우와 마찬가지로 수수료가 없습니다." diplomat_suggestion: title: "코드 컴뱃 번역을 도와주세요!" @@ -177,13 +177,13 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t new_password_verify: "확인(다시한번 입력해주세요)" email_subscriptions: "이메일 구독" email_announcements: "공지사항" - email_announcements_description: "코드 컴뱃의 개발 또는 진행상황을 이메일로 구독 하세요" + email_announcements_description: "코드 컴뱃의 개발 및 진행 상황을 이메일로 구독하세요" email_notifications: "알람" -# email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity." -# email_any_notes: "Any Notifications" -# email_any_notes_description: "Disable to stop all activity notification emails." -# email_recruit_notes: "Job Opportunities" -# email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job." + email_notifications_summary: "당신의 코드 컴뱃 활동과 관련된 자동 알림 메일을 설정할 수 있습니다." + email_any_notes: "모든 알림 받기" + email_any_notes_description: "모든 알림 메일 받지 않기" + email_recruit_notes: "구인 정보" + email_recruit_notes_description: "정말 실력이 좋으시다고 판단되면, 보다 좋은 구직 정보와 관련하여 연락드릴 수도 있습니다." contributor_emails: "조력자들 이메일" contribute_prefix: "우리는 언제나 당신의 참여를 환영 합니다 : " contribute_page: "참여하기 페이지" @@ -207,16 +207,16 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t profile_for_suffix: "" # featured: "Featured" # not_featured: "Not Featured" -# looking_for: "Looking for:" + looking_for: "희망 채용형태" last_updated: "최근 업데이트:" contact: "연락하기" -# active: "Looking for interview offers now" -# inactive: "Not looking for offers right now" + active: "구직희망" + inactive: "구직희망 안함" complete: "완료" next: "다음으로" -# next_city: "city?" -# next_country: "pick your country." -# next_name: "name?" + next_city: "도시?" + next_country: "국가를 선택하세요." + next_name: "성명?" # next_short_description: "write a short description." # next_long_description: "describe your desired position." # next_skills: "list at least five skills." @@ -247,8 +247,8 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # basics_looking_for: "Looking For" basics_looking_for_full_time: "풀타임" basics_looking_for_part_time: "파트타임" -# basics_looking_for_remote: "Remote" -# basics_looking_for_contracting: "Contracting" + basics_looking_for_remote: "재택근무" + basics_looking_for_contracting: "계약직" basics_looking_for_internship: "인턴쉽" # basics_looking_for_help: "What kind of developer position do you want?" name_header: "성명을 기재하여 주십시오." @@ -382,7 +382,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t multiplayer_hint_label: "힌트:" multiplayer_hint: " 모두 선택하려면 링크를 클릭하세요, 그리고 ⌘-C 또는 Ctrl-C 를 눌러서 링크를 복사하세요." multiplayer_coming_soon: "곧 좀 더 다양한 멀티플레이어 모드가 업데이트 됩니다!" -# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard." + multiplayer_sign_in_leaderboard: "로그인하시거나 계정을 만드시고 상위권 순위 차트에 이름을 올려보세요." guide_title: "가이드" tome_minion_spells: "미니언의 마법" tome_read_only_spells: "읽기 전용 마법" @@ -431,7 +431,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # tip_forums: "Head over to the forums and tell us what you think!" # tip_baby_coders: "In the future, even babies will be Archmages." # tip_morale_improves: "Loading will continue until morale improves." -# tip_all_species: "We believe in equal opportunities to learn programming for all species." + tip_all_species: "우리는 모든 생물이 동등하게 프로그래밍을 배울 기회가 있어야 한다고 생각합니다." # tip_reticulating: "Reticulating spines." # tip_harry: "Yer a Wizard, " # tip_great_responsibility: "With great coding skill comes great debug responsibility." @@ -441,23 +441,23 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # tip_no_try: "Do. Or do not. There is no try. - Yoda" # tip_patience: "Patience you must have, young Padawan. - Yoda" # tip_documented_bug: "A documented bug is not a bug; it is a feature." -# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela" -# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds" + tip_impossible: "성공하기 전까진 불가능해 보이는 법이죠. - Nelson Mandela" + tip_talk_is_cheap: "떠드는 건 가치가 없어요. 코드를 보여줘봐요. - Linus Torvalds" # tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay" # tip_hardware_problem: "Q: How many programmers does it take to change a light bulb? A: None, it's a hardware problem." # time_current: "Now:" # time_total: "Max:" # time_goto: "Go to:" -# infinite_loop_try_again: "Try Again" -# infinite_loop_reset_level: "Reset Level" -# infinite_loop_comment_out: "Comment Out My Code" + infinite_loop_try_again: "다시 시도해보세요." + infinite_loop_reset_level: "레벨 리셋" + infinite_loop_comment_out: "내 코드를 일시적 주석처리하기" -# keyboard_shortcuts: -# keyboard_shortcuts: "Keyboard Shortcuts" -# space: "Space" -# enter: "Enter" -# escape: "Escape" -# cast_spell: "Cast current spell." + keyboard_shortcuts: + keyboard_shortcuts: "단축키" + space: "스페이스" + enter: "엔터" + escape: "Esc" + cast_spell: "현재 상태의 주문을 겁니다." # continue_script: "Continue past current script." # skip_scripts: "Skip past all skippable scripts." # toggle_playback: "Toggle play/pause." @@ -475,12 +475,12 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t av_entities_sub_title: "속성들" av_entities_users_url: "유저들" av_entities_active_instances_url: "액티브 인스턴스들" -# av_entities_employer_list_url: "Employer List" + av_entities_employer_list_url: "고용주 리스트" av_other_sub_title: "다른 사람들" av_other_debug_base_url: "베이스 (base.jade 디버깅)" u_title: "유저 목록" lg_title: "가장 최근 게임" -# clas: "CLAs" + clas: "컨트리뷰터 라이센스 약관" community: level_editor: "레벨 에디터" @@ -498,21 +498,21 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t thang_description: "유닛들, 기본적인 인공지능, 그래픽과 오디오등을 직접 빌드하세요. 현재는 백터 그래픽으로 추출된 플래시파일만 임폴트 가능합니다." level_title: "레벨 에디터" level_description: "스크립팅, 오디오 업로드, 모든 레벨을 생성하기 위한 사용자 정의 로직등 우리가 사용하는 모든 것들을 구축하는 것을 위한 툴들을 포함합니다." -# achievement_title: "Achievement Editor" -# got_questions: "Questions about using the CodeCombat editors?" + achievement_title: "업적 에디터" + got_questions: "코드 컴뱃 에디터 사용법에 대해 질문이 있으신가요?" contact_us: "연락하기!" hipchat_prefix: "당신은 또한 우리를 여기에서 찾을 수 있습니다 : " hipchat_url: "힙챗 룸" back: "뒤로" revert: "되돌리기" revert_models: "모델 되돌리기" -# pick_a_terrain: "Pick A Terrain" -# small: "Small" -# grassy: "Grassy" -# fork_title: "Fork New Version" -# fork_creating: "Creating Fork..." + pick_a_terrain: "지형을 선택하세요." + small: "작게" + grassy: "풀로 덮인" + fork_title: "새 버전 가져오기" + fork_creating: "포크 생성중..." # randomize: "Randomize" -# more: "More" + more: "더 보기" wiki: "위키" live_chat: "실시간 채팅" level_some_options: "다른 옵션들?" @@ -553,8 +553,8 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t article_search_title: "기사들은 여기에서 찾으세요" thang_search_title: "Thang 타입들은 여기에서 찾으세요" level_search_title: "레벨들은 여기에서 찾으세요" -# achievement_search_title: "Search Achievements" -# read_only_warning2: "Note: you can't save any edits here, because you're not logged in." + achievement_search_title: "업적 검색" + read_only_warning2: "주의: 로그인하지 않으셨기 때문에 내용을 저장할 수 없습니다." article: edit_btn_preview: "미리보기" @@ -566,7 +566,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t body: "구성" version: "버전" commit_msg: "커밋 메세지" -# version_history: "Version History" + version_history: "버전 히스토리" version_history_for: "버전 히스토리 : " result: "결과" results: "결과들" @@ -613,7 +613,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t michael_description: "프로그래머, 시스템 관리자, 기술 신동(대학생이래요),Michael 은 우리 서버를 계속 무결점상태로 유지시켜주는 사람입니다." glen_description: "프로그래머이자 열정적인 게임 개발자. 의미있는 것들을 개발함으로써 세상을 보다 더 나은 곳으로 변화시키고자 하는 개발자입니다. 그의 사전에 불가능이란 없습니다. 새로운 기술을 배우는 건 그에게 몹시 즐거운 일이죠!" -# legal: + legal: # page_title: "Legal" opensource_intro: "코드 컴뱃은 무료이며 전적으로 오픈 소스를 기반으로 합니다." opensource_description_prefix: "코드 컴뱃의" @@ -623,13 +623,13 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t opensource_description_suffix: "를 확인해보세요. 코드 컴뱃을 가능하게 만든 소프트웨어들을 찾아보실 수 있습니다." # practices_title: "Respectful Best Practices" # practices_description: "These are our promises to you, the player, in slightly less legalese." -# privacy_title: "Privacy" + privacy_title: "프라이버시" # privacy_description: "We will not sell any of your personal information. We intend to make money through recruitment eventually, but rest assured we will not distribute your personal information to interested companies without your explicit consent." # security_title: "Security" # security_description: "We strive to keep your personal information safe. As an open source project, our site is freely open to anyone to review and improve our security systems." -# email_title: "Email" + email_title: "이메일" # email_description_prefix: "We will not inundate you with spam. Through" -# email_settings_url: "your email settings" + email_settings_url: "이메일 설정" # email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time." # cost_title: "Cost" # cost_description: "Currently, CodeCombat is 100% free! One of our main goals is to keep it that way, so that as many people can play as possible, regardless of place in life. If the sky darkens, we might have to charge subscriptions or for some content, but we'd rather not. With any luck, we'll be able to sustain the company with:" @@ -655,7 +655,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t art_music: "뮤직" art_sound: "사운드" art_artwork: "원화" -# art_sprites: "Sprites" + art_sprites: "스프라이트" # art_other: "Any and all other non-code creative works that are made available when creating Levels." # art_access: "Currently there is no universal, easy system for fetching these assets. In general, fetch them from the URLs as used by the site, contact us for assistance, or help us in extending the site to make these assets more easily accessible." # art_paragraph_1: "For attribution, please name and link to codecombat.com near where the source is used or where appropriate for the medium. For example:" @@ -773,47 +773,47 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t ambassador_title: "대사" ambassador_title_description: "(지원)" -# ladder: -# please_login: "Please log in first before playing a ladder game." -# my_matches: "My Matches" -# simulate: "Simulate" -# simulation_explanation: "By simulating games you can get your game ranked faster!" -# simulate_games: "Simulate Games!" -# simulate_all: "RESET AND SIMULATE GAMES" -# games_simulated_by: "Games simulated by you:" -# games_simulated_for: "Games simulated for you:" -# games_simulated: "Games simulated" -# games_played: "Games played" -# ratio: "Ratio" -# leaderboard: "Leaderboard" + ladder: + please_login: "토너먼트 게임을 시작하기 앞서 로그인해주세요." + my_matches: "나의 경기들" + simulate: "시뮬레이션" + simulation_explanation: "시뮬레이션을 통해 더 빨리 랭킹 평가를 받을 수 있습니다." + simulate_games: "시뮬레이션 실행!" + simulate_all: "리셋하고 시뮬레이션 하기" + games_simulated_by: "내가 시뮬레이션한 게임 수:" + games_simulated_for: "다른 사람에 의해 시뮬레이션된 게임 수:" + games_simulated: "시뮬레이션 실행된 게임" + games_played: "플레이한 게임" + ratio: "비율" + leaderboard: "상위권 순위 차트" # battle_as: "Battle as " -# summary_your: "Your " + summary_your: "당신의 " # summary_matches: "Matches - " # summary_wins: " Wins, " # summary_losses: " Losses" # rank_no_code: "No New Code to Rank" -# rank_my_game: "Rank My Game!" -# rank_submitting: "Submitting..." + rank_my_game: "내 게임 순위 매기기!" + rank_submitting: "제출중..." # rank_submitted: "Submitted for Ranking" -# rank_failed: "Failed to Rank" + rank_failed: "순위 매기기 실패" # rank_being_ranked: "Game Being Ranked" -# rank_last_submitted: "submitted " + rank_last_submitted: "제출 완료" # help_simulate: "Help simulate games?" # code_being_simulated: "Your new code is being simulated by other players for ranking. This will refresh as new matches come in." # no_ranked_matches_pre: "No ranked matches for the " # no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked." # choose_opponent: "Choose an Opponent" -# select_your_language: "Select your language!" -# tutorial_play: "Play Tutorial" -# tutorial_recommended: "Recommended if you've never played before" -# tutorial_skip: "Skip Tutorial" + select_your_language: "언어를 고르세요!" + tutorial_play: "튜토리얼 보기" + tutorial_recommended: "전에 플레이해본 적이 없으시다면 튜토리얼을 보시는 걸 권장합니다." + tutorial_skip: "튜토리얼 넘기기" # tutorial_not_sure: "Not sure what's going on?" -# tutorial_play_first: "Play the Tutorial first." + tutorial_play_first: "튜토리얼을 먼저 플레이해보세요." # simple_ai: "Simple AI" # warmup: "Warmup" -# vs: "VS" + vs: "VS" # friends_playing: "Friends Playing" -# log_in_for_friends: "Log in to play with your friends!" + log_in_for_friends: "로그인하시고 친구들과 게임을 즐기세요!" # social_connect_blurb: "Connect and play against your friends!" # invite_friends_to_battle: "Invite your friends to join you in battle!" # fight: "Fight!" @@ -824,10 +824,10 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # tournament_rules: "Tournament Rules" # tournament_blurb: "Write code, collect gold, build armies, crush foes, win prizes, and upgrade your career in our $40,000 Greed tournament! Check out the details" # tournament_blurb_blog: "on our blog" -# rules: "Rules" -# winners: "Winners" + rules: "규칙" + winners: "승리자" -# ladder_prizes: + ladder_prizes: # title: "Tournament Prizes" # blurb_1: "These prizes will be awarded according to" # blurb_2: "the tournament rules" @@ -844,7 +844,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # credits: "credits" # one_month_coupon: "coupon: choose either Rails or HTML" # one_month_discount: "discount, 30% off: choose either Rails or HTML" -# license: "license" + license: "라이센스" # oreilly: "ebook of your choice" # multiplayer_launch: @@ -861,35 +861,35 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # new_to_programming: ". New to programming? Hit our beginner campaign to skill up." # so_ready: "I Am So Ready for This" -# loading_error: + loading_error: could_not_load: "서버로부터 로딩하는 데 문제가 발생했습니다." connection_failure: "연결 실패" -# unauthorized: "You need to be signed in. Do you have cookies disabled?" + unauthorized: "로그인한 상태가 아닙니다. 혹시 쿠키를 사용하지 못하게 설정해놓으셨나요?" forbidden: "권한이 필요합니다." -# not_found: "Not found." -# not_allowed: "Method not allowed." + not_found: "찾을 수 없습니다." + not_allowed: "잘못된 접근입니다." timeout: "서버 타임아웃" -# conflict: "Resource conflict." + conflict: "리소스 충돌" # bad_input: "Bad input." server_error: "서버 에러" unknown: "알 수 없는 에러 발생" -# resources: + resources: # your_sessions: "Your Sessions" -# level: "Level" + level: "레벨" # social_network_apis: "Social Network APIs" # facebook_status: "Facebook Status" -# facebook_friends: "Facebook Friends" + facebook_friends: "페이스북 친구들" # facebook_friend_sessions: "Facebook Friend Sessions" -# gplus_friends: "G+ Friends" + gplus_friends: "구글 플러스 친구들" # gplus_friend_sessions: "G+ Friend Sessions" -# leaderboard: "Leaderboard" + leaderboard: "상위권 순위 차트" # user_schema: "User Schema" -# user_profile: "User Profile" + user_profile: "유저 프로필" # patches: "Patches" # patched_model: "Source Document" # model: "Model" -# system: "System" + system: "시스템" # component: "Component" # components: "Components" # thang: "Thang" @@ -899,7 +899,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t # article: "Article" # user_names: "User Names" # thang_names: "Thang Names" -# files: "Files" + files: "파일들" # top_simulators: "Top Simulators" # source_document: "Source Document" # document: "Document" diff --git a/app/locale/pt-PT.coffee b/app/locale/pt-PT.coffee index 47879bfe7..df48abf89 100644 --- a/app/locale/pt-PT.coffee +++ b/app/locale/pt-PT.coffee @@ -14,7 +14,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: manual: "Manual" fork: "Bifurcar" play: "Jogar" - retry: "Tentar novamente" + retry: "Tentar Novamente" watch: "Vigiar" unwatch: "Desvigiar" submit_patch: "Submeter Versão" @@ -185,7 +185,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: email_recruit_notes: "Oportunidades de Emprego" email_recruit_notes_description: "Se joga muito bem, podemos contactá-lo para lhe arranjar um (melhor) emprego." contributor_emails: "Subscrições de E-mail (Contribuintes)" - contribute_prefix: "Estamos à procura de pessoas para se juntarem a nós! Visita a " + contribute_prefix: "Estamos à procura de pessoas para se juntarem a nós! Visite a " contribute_page: "página de contribuição" contribute_suffix: " para mais informações." email_toggle: "Alternar Todos" @@ -305,7 +305,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: # player_code: "Player Code" employers: - hire_developers_not_credentials: "Contrate desenvolvedores, não cartas de recomendação." + hire_developers_not_credentials: "Contrate programadores, não cartas de recomendação." get_started: "Começar" already_screened: "Nós já selecionamos tecnicamente todos os nossos candidatos" filter_further: ", mas ainda pode filtrar mais:" @@ -333,7 +333,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: # pass_screen_blurb: "Review each candidate's code before reaching out. One employer found that 5x as many of our devs passed their technical screen than hiring from Hacker News." # make_hiring_easier: "Make my hiring easier, please." what: "O que é o CodeCombat?" - what_blurb: "O CodeCombat é um jogo de programação, no navegador e multijogador. Os jogadores escrevem código para controlar as forças deles em batalha contra outros desenvolvedores. Os nossos jogadores têm experiência com todos os conceitos tecnológicos principais." + what_blurb: "O CodeCombat é um jogo de programação, no navegador e multijogador. Os jogadores escrevem código para controlar as forças deles em batalha contra outros programadores. Os nossos jogadores têm experiência com todos os conceitos tecnológicos principais." cost: "Quanto é que cobramos?" cost_blurb: "Cobramos 15% do salário do primeiro ano e ofereçemos uma garantia de devolução de 100% do dinheiro durante 90 dias. Não cobramos por candidatos que já estejam a ser ativamente entrevistados na sua companhia." candidate_name: "Nome" @@ -344,9 +344,9 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: candidate_years_experience: "Anos de Experiência" candidate_last_updated: "Última Vez Atualizado" candidate_who: "Quem" - featured_developers: "Desenvolvedores em Destaque" - other_developers: "Outros Desenvolvedores" - inactive_developers: "Desenvolvedores Inativos" + featured_developers: "Programadores em Destaque" + other_developers: "Outros Programadores" + inactive_developers: "Programadores Inativos" play_level: done: "Concluir" @@ -375,112 +375,112 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: victory_play_next_level: "Jogar Próximo Nível" victory_go_home: "Ir para o Início" victory_review: "Conte-nos mais!" - victory_hour_of_code_done: "É Tudo?" - victory_hour_of_code_done_yes: "Sim, a minha Hora de Código™ chegou ao fim!" - multiplayer_title: "Definições de Multiplayer" - multiplayer_link_description: "Dá este link a alguém para se juntar a ti." + victory_hour_of_code_done: "Terminou?" + victory_hour_of_code_done_yes: "Sim, terminei a minha Hora de Código™!" + multiplayer_title: "Definições Multijogador" + multiplayer_link_description: "Dê esta ligação a alguém para se juntar a si." multiplayer_hint_label: "Dica:" - multiplayer_hint: " Carrega no link para seleccionar tudp, depois pressiona ⌘-C ou Ctrl-C para copiar o link." - multiplayer_coming_soon: "Mais funcionalidades de multiplayer brevemente!" -# multiplayer_sign_in_leaderboard: "Sign in or create an account and get your solution on the leaderboard." + multiplayer_hint: " Clique na ligação para selecionar tudo. Depois carregue em ⌘-C ou Ctrl-C para copiá-la." + multiplayer_coming_soon: "Mais funcionalidades multijogador em breve!" + multiplayer_sign_in_leaderboard: "Inicie sessão ou crie uma conta para ter a sua solução na tabela de classificação." guide_title: "Guia" - tome_minion_spells: "Feitiços dos teus Minions" - tome_read_only_spells: "Feitiços apenas de leitura" + tome_minion_spells: "Feitiços dos Seus Minions" + tome_read_only_spells: "Feitiços Apenas de Leitura" tome_other_units: "Outras Unidades" tome_cast_button_castable: "Lançar Feitiço" - tome_cast_button_casting: "A Lançar Feitiço" - tome_cast_button_cast: "Lançar Feitiço" -# tome_autocast_delay: "Autocast Delay" - tome_select_spell: "Escolhe um Feitiço" - tome_select_a_thang: "Escolhe Alguém para " - tome_available_spells: "Feitiços disponíveis" + tome_cast_button_casting: "A Lançar" + tome_cast_button_cast: "Feitiço Lançado" + tome_autocast_delay: "Atraso de Auto-lançamento" + tome_select_spell: "Selecione um Feitiço" + tome_select_a_thang: "Selecione Alguém para " + tome_available_spells: "Feitiços Disponíveis" hud_continue: "Continuar (shift-espaço)" spell_saved: "Feitiço Guardado" skip_tutorial: "Saltar (esc)" editor_config: "Configurar Editor" - editor_config_title: "Configuração do Editor" -# editor_config_level_language_label: "Language for This Level" -# editor_config_level_language_description: "Define the programming language for this particular level." -# editor_config_default_language_label: "Default Programming Language" -# editor_config_default_language_description: "Define the programming language you want to code in when starting new levels." - editor_config_keybindings_label: "Atalhos de Teclado" + editor_config_title: "Configurar Editor" + editor_config_level_language_label: "Linguagem para Este Nível" + editor_config_level_language_description: "Define a linguagem de programação para este nível em particular." + editor_config_default_language_label: "Linguagem de Programação Predefinida" + editor_config_default_language_description: "Define a linguagem de programação na qual deseja programar aquando do começo de novos níveis." + editor_config_keybindings_label: "Atalhos do Teclado" editor_config_keybindings_default: "Predefinição (Ace)" - editor_config_keybindings_description: "Adiciona atalhos de teclado de acordo com o editor escolhido" -# editor_config_livecompletion_label: "Live Autocompletion" -# editor_config_livecompletion_description: "Displays autocomplete suggestions while typing." + editor_config_keybindings_description: "Adiciona atalhos de teclado adicionais conhecidos dos editores comuns." + editor_config_livecompletion_label: "Auto-completação em Tempo Real" + editor_config_livecompletion_description: "Mostra sugestões de auto-completação aquando da escrita." editor_config_invisibles_label: "Mostrar Invisíveis" - editor_config_invisibles_description: "Mostra caracteres invisíveis como espaços e tabulações" - editor_config_indentguides_label: "Mostrar Guias" - editor_config_indentguides_description: "Mostra linhas verticais de acordo com a identação." + editor_config_invisibles_description: "Mostra invisíveis tais como espaços e tabulações." + editor_config_indentguides_label: "Mostrar Guias de Indentação" + editor_config_indentguides_description: "Mostra linhas verticais para se ver melhor a indentação." editor_config_behaviors_label: "Comportamentos Inteligentes" - editor_config_behaviors_description: "Completa automaticamente chavetas, parêntesis e aspas" -# keyboard_shortcuts: "Key Shortcuts" -# loading_ready: "Ready!" -# tip_insert_positions: "Shift+Click a point on the map to insert it into the spell editor." -# tip_toggle_play: "Toggle play/paused with Ctrl+P." -# tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward." -# tip_guide_exists: "Click the guide at the top of the page for useful info." -# tip_open_source: "CodeCombat is 100% open source!" -# tip_beta_launch: "CodeCombat launched its beta in October, 2013." -# tip_js_beginning: "JavaScript is just the beginning." -# tip_autocast_setting: "Adjust autocast settings by clicking the gear on the cast button." -# think_solution: "Think of the solution, not the problem." -# tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra" -# tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis" -# tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra" -# tip_forums: "Head over to the forums and tell us what you think!" -# tip_baby_coders: "In the future, even babies will be Archmages." -# tip_morale_improves: "Loading will continue until morale improves." -# tip_all_species: "We believe in equal opportunities to learn programming for all species." -# tip_reticulating: "Reticulating spines." -# tip_harry: "Yer a Wizard, " + editor_config_behaviors_description: "Auto-completa parênteses, chavetas e aspas." + keyboard_shortcuts: "Atalhos do Teclado" + loading_ready: "Pronto!" + tip_insert_positions: "Pressione Shift e Clique num ponto do mapa para inseri-lo no editor de feitiços." + tip_toggle_play: "Alterne entre Jogar e Pausar com Ctrl+P." + tip_scrub_shortcut: "Ctrl+[ rebobina e Ctrl+] avança." + tip_guide_exists: "Clique no Guia no topo da página para informações úteis." + tip_open_source: "O CodeCombat é 100% open source!" + tip_beta_launch: "O CodeCombat lançou o seu beta em outubro de 2013." + tip_js_beginning: "O JavaScript é apenas o começo." + tip_autocast_setting: "Ajuste as definições de auto-lançamento ao clicar na engrenagem no botão lançar." + think_solution: "Pense na solução, não no problema." + tip_theory_practice: "Teoricamente, não há diferença entre a teoria e a prática. Mas na prática, há. - Yogi Berra" + tip_error_free: "Há duas formas de escrever programas sem erros; apenas a terceira funciona. - Alan Perlis" + tip_debugging_program: "Se depurar é o processo de remover erros, então programar deve ser o processo de os adicionar. - Edsger W. Dijkstra" + tip_forums: "Vá aos fóruns e diga-nos o que pensa!" + tip_baby_coders: "No futuro, até os bebés serão Arcomagos." + tip_morale_improves: "O carregamento irá continuar até que a moral melhore." + tip_all_species: "Acreditamos em oportunidades iguais para todas as espécies, em relação a aprenderem a programar." + tip_reticulating: "A reticular espinhas." + tip_harry: "Você é um Feitiçeiro, " # tip_great_responsibility: "With great coding skill comes great debug responsibility." # tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep." -# tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't." + tip_binary: "Há apenas 10 tipos de pessoas no mundo: aquelas que percebem binário e aquelas que não." # tip_commitment_yoda: "A programmer must have the deepest commitment, the most serious mind. ~ Yoda" -# tip_no_try: "Do. Or do not. There is no try. - Yoda" -# tip_patience: "Patience you must have, young Padawan. - Yoda" -# tip_documented_bug: "A documented bug is not a bug; it is a feature." -# tip_impossible: "It always seems impossible until it's done. - Nelson Mandela" -# tip_talk_is_cheap: "Talk is cheap. Show me the code. - Linus Torvalds" -# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay" -# tip_hardware_problem: "Q: How many programmers does it take to change a light bulb? A: None, it's a hardware problem." -# time_current: "Now:" -# time_total: "Max:" -# time_goto: "Go to:" -# infinite_loop_try_again: "Try Again" -# infinite_loop_reset_level: "Reset Level" + tip_no_try: "Fazer. Ou não fazer. Não há nenhum tentar. - Yoda" + tip_patience: "Paciência tu deves ter, jovem Padawan. - Yoda" + tip_documented_bug: "Um erro documentado não é um erro; é uma funcionalidade." + tip_impossible: "Parece sempre impossível até ser feito. - Nelson Mandela" + tip_talk_is_cheap: "Falar é fácil. Mostre-me o código. - Linus Torvalds" + tip_first_language: "A coisa mais desastrosa que pode aprender é a sua primeira linguagem de programação. - Alan Kay" + tip_hardware_problem: "P: Quantos programadores são necessários para mudar uma lâmpada? R: Nenhum, é um problema de hardware." + time_current: "Agora:" + time_total: "Máximo:" + time_goto: "Ir para:" + infinite_loop_try_again: "Tentar Novamente" + infinite_loop_reset_level: "Reiniciar Nível" # infinite_loop_comment_out: "Comment Out My Code" -# keyboard_shortcuts: -# keyboard_shortcuts: "Keyboard Shortcuts" -# space: "Space" -# enter: "Enter" -# escape: "Escape" -# cast_spell: "Cast current spell." + keyboard_shortcuts: + keyboard_shortcuts: "Atalhos de Teclado" + space: "Espaço" + enter: "Enter" + escape: "Esc" + cast_spell: "Lançar feitiço atual." # continue_script: "Continue past current script." # skip_scripts: "Skip past all skippable scripts." -# toggle_playback: "Toggle play/pause." -# scrub_playback: "Scrub back and forward through time." -# single_scrub_playback: "Scrub back and forward through time by a single frame." + toggle_playback: "Alternar entre Jogar e Pausar." + scrub_playback: "Andar para a frente e para trás no tempo." + single_scrub_playback: "Andar para a frente e para trás no tempo um único frame." # scrub_execution: "Scrub through current spell execution." # toggle_debug: "Toggle debug display." # toggle_grid: "Toggle grid overlay." # toggle_pathfinding: "Toggle pathfinding overlay." # beautify: "Beautify your code by standardizing its formatting." -# move_wizard: "Move your Wizard around the level." + move_wizard: "Mover o seu Feitiçeiro pelo nível." admin: - av_title: "Visualizações de Admin" + av_title: "Vistas de Administrador" av_entities_sub_title: "Entidades" av_entities_users_url: "Utilizadores" av_entities_active_instances_url: "Activar Instâncias" -# av_entities_employer_list_url: "Employer List" + av_entities_employer_list_url: "Lista de Empregadores" av_other_sub_title: "Outro" - av_other_debug_base_url: "Base (para fazer debug base.jade)" + av_other_debug_base_url: "Base (para depurar base.jade)" u_title: "Lista de Utilizadores" lg_title: "Últimos Jogos" -# clas: "CLAs" + clas: "CLA's" community: level_editor: "Editor de Níveis" @@ -545,16 +545,16 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: new_article_title: "Criar um Novo Artigo" new_thang_title: "Criar um Novo Tipo de Thang" new_level_title: "Criar um Novo Nível" -# new_article_title_login: "Log In to Create a New Article" -# new_thang_title_login: "Log In to Create a New Thang Type" -# new_level_title_login: "Log In to Create a New Level" -# new_achievement_title: "Create a New Achievement" -# new_achievement_title_login: "Log In to Create a New Achievement" + new_article_title_login: "Inicie Sessão para Criar um Novo Artigo" + new_thang_title_login: "Inicie Sessão para Criar um Novo Tipo de Thang" + new_level_title_login: "Inicie Sessão para Criar um Novo Nível" + new_achievement_title: "Criar uma Nova Conquista" + new_achievement_title_login: "Inicie Sessão para Criar uma Nova Conquista" article_search_title: "Procurar Artigos Aqui" thang_search_title: "Procurar Thangs Aqui" level_search_title: "Procurar Níveis Aqui" -# achievement_search_title: "Search Achievements" -# read_only_warning2: "Note: you can't save any edits here, because you're not logged in." + achievement_search_title: "Procurar Conquistas" + read_only_warning2: "Nota: não pode guardar nenhuma edição feita aqui, porque não tem sessão iniciada." article: edit_btn_preview: "Pré-visualizar" @@ -613,33 +613,33 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: # michael_description: "Programmer, sys-admin, and undergrad technical wunderkind, Michael is the person keeping our servers online." # glen_description: "Programmer and passionate game developer, with the motivation to make this world a better place, by developing things that matter. The word impossible can't be found in his dictionary. Learning new skills is his joy!" -# legal: -# page_title: "Legal" -# opensource_intro: "CodeCombat is free to play and completely open source." -# opensource_description_prefix: "Check out " -# github_url: "our GitHub" -# opensource_description_center: "and help out if you like! CodeCombat is built on dozens of open source projects, and we love them. See " -# archmage_wiki_url: "our Archmage wiki" -# opensource_description_suffix: "for a list of the software that makes this game possible." -# practices_title: "Respectful Best Practices" -# practices_description: "These are our promises to you, the player, in slightly less legalese." -# privacy_title: "Privacy" + legal: + page_title: "Legal" + opensource_intro: "O CodeCombat é gratuito para jogar e é totalmente open source." + opensource_description_prefix: "Confira " + github_url: "o nosso GitHub" + opensource_description_center: "e ajude se quiser! O CodeCombat é construído tendo por base dezenas de projetos open source, os quais nós amamos. Veja " + archmage_wiki_url: "a nossa wiki dos Arcomagos" + opensource_description_suffix: "para uma lista do software que faz com que este jogo seja possível." + practices_title: "Melhores Práticas Respeitosas" + practices_description: "Estas são as nossas promessas para consigo, o jogador, com um pouco menos de politiquices." + privacy_title: "Privacidade" # privacy_description: "We will not sell any of your personal information. We intend to make money through recruitment eventually, but rest assured we will not distribute your personal information to interested companies without your explicit consent." -# security_title: "Security" + security_title: "Segurança" # security_description: "We strive to keep your personal information safe. As an open source project, our site is freely open to anyone to review and improve our security systems." -# email_title: "Email" -# email_description_prefix: "We will not inundate you with spam. Through" -# email_settings_url: "your email settings" -# email_description_suffix: "or through links in the emails we send, you can change your preferences and easily unsubscribe at any time." -# cost_title: "Cost" + email_title: "E-mail" + email_description_prefix: "Nós não o inundaremos com spam. Através das" + email_settings_url: "suas definições de e-mail" + email_description_suffix: "ou através de ligações presentes nos e-mails que enviamos, pode mudar as suas preferências e parar a sua subscrição facilmente, em qualquer momento." + cost_title: "Custo" # cost_description: "Currently, CodeCombat is 100% free! One of our main goals is to keep it that way, so that as many people can play as possible, regardless of place in life. If the sky darkens, we might have to charge subscriptions or for some content, but we'd rather not. With any luck, we'll be able to sustain the company with:" -# recruitment_title: "Recruitment" + recruitment_title: "Recrutamento" # recruitment_description_prefix: "Here on CodeCombat, you're going to become a powerful wizard–not just in the game, but also in real life." # url_hire_programmers: "No one can hire programmers fast enough" # recruitment_description_suffix: "so once you've sharpened your skills and if you agree, we will demo your best coding accomplishments to the thousands of employers who are drooling for the chance to hire you. They pay us a little, they pay you" # recruitment_description_italic: "a lot" # recruitment_description_ending: "the site remains free and everybody's happy. That's the plan." -# copyrights_title: "Copyrights and Licenses" + copyrights_title: "Direitos Autorais e Licensas" # contributor_title: "Contributor License Agreement" # contributor_description_prefix: "All contributions, both on the site and on our GitHub repository, are subject to our" # cla_url: "CLA" @@ -791,8 +791,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: summary_matches: "Partidas - " summary_wins: " Vitórias, " summary_losses: " Derrotas" - rank_no_code: "Sem código novo para classificar" - rank_my_game: "Classifica o meu jogo!" + rank_no_code: "Sem Código Novo para Classificar" + rank_my_game: "Classifique o Meu Jogo!" rank_submitting: "A submeter..." rank_submitted: "Submetido para Classificação" rank_failed: "Falhou a Classificar" @@ -805,9 +805,9 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: choose_opponent: "Escolhe um Adversário" # select_your_language: "Select your language!" tutorial_play: "Jogar Tutorial" - tutorial_recommended: "Recomendado se nunca jogaste antes" + tutorial_recommended: "Recomendado se nunca jogou antes" tutorial_skip: "Saltar Tutorial" - tutorial_not_sure: "Não tens a certeza do que se passa?" + tutorial_not_sure: "Não tem a certeza do que se passa?" tutorial_play_first: "Joga o Tutorial primeiro." simple_ai: "Inteligência Artificial Simples" warmup: "Aquecimento" @@ -824,8 +824,8 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: # tournament_rules: "Tournament Rules" # tournament_blurb: "Write code, collect gold, build armies, crush foes, win prizes, and upgrade your career in our $40,000 Greed tournament! Check out the details" # tournament_blurb_blog: "on our blog" -# rules: "Rules" -# winners: "Winners" + rules: "Regras" + winners: "Vencedores" # ladder_prizes: # title: "Tournament Prizes" @@ -849,30 +849,30 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: multiplayer_launch: introducing_dungeon_arena: "Introduzindo a Dungeon Arena" - new_way: "Uma nova forma de competir com código." - to_battle: "Às armas, Programadores!" - modern_day_sorcerer: "Sabes programar? És tão forte! És um feiticeiro dos tempos modernos! Será que não está na altura de usares os teus poderes mágicos de programação para comandar os teus servos em combates épicos? E não estamos a falar de robots." - arenas_are_here: "As arenas mano-a-mano multiplayer de CodeCombat estão aqui." - ladder_explanation: "Escolhe os teus heróis, encanta os teus exércitos de ogres ou humanos, e constrói o teu caminho, derrotando outros Feiticeiros para chegares ao topo da classificação. Depois, desafia os teus amigos para gloriosas arenas de programação multijogador. Se te sentes criativo, podes até" - fork_our_arenas: "alterar as nossas arenas" - create_worlds: "e criar os teus próprios mundos." - javascript_rusty: "O teu JavaScript está enferrujado? Não te preocupes; Existe um" + new_way: "A nova forma de competir com código." + to_battle: "Para o Combate, Programadores!" + modern_day_sorcerer: "Sabe programar? Isso é demais! É um feiticeiro dos tempos modernos! Não estará na altura de usar os seus poderes mágicos de programação para comandar os seus minions em combates épicos? E não estamos a falar de robôs." + arenas_are_here: "As arenas multijogador do CodeCombat estão aqui." + ladder_explanation: "Escolha os seus heróis, enfeitice os seus exércitos de ogres ou de humanos e passe por cima de Feiticeiros derrotados para chegar ao topo da tabela classificativa - depois, compita contra os seus amigos nas nossas arenas de programação multijogador gloriosas. Se se sentir criativo, pode ainda" + fork_our_arenas: "bifurcar as nossas arenas" + create_worlds: "e criar os seus próprios mundos." + javascript_rusty: "O seu JavaScript está um pouco enferrujado? Não se preocupe; existe um" tutorial: "tutorial" - new_to_programming: ". Novo na programação? Faz a Campanha para Iniciantes para expandires as tuas capacidades." - so_ready: "Estou mais que pronto para isto" + new_to_programming: ". Novo na programação? Faça a nossa Campanha para Iniciantes para melhorar as suas capacidades." + so_ready: "Estou Mais Que Pronto Para Isto" -# loading_error: -# could_not_load: "Error loading from server" -# connection_failure: "Connection failed." -# unauthorized: "You need to be signed in. Do you have cookies disabled?" -# forbidden: "You do not have the permissions." -# not_found: "Not found." -# not_allowed: "Method not allowed." -# timeout: "Server timeout." -# conflict: "Resource conflict." -# bad_input: "Bad input." -# server_error: "Server error." -# unknown: "Unknown error." + loading_error: + could_not_load: "Erro ao carregar do servidor" + connection_failure: "A conexão falhou." + unauthorized: "Precisa de ter sessão iniciada. Tem os cookies desativados?" + forbidden: "Não tem as permissões." + not_found: "Não encontrado." + not_allowed: "Método não permitido." + timeout: "O servidor expirou." + conflict: "Conflito de recursos." + bad_input: "Má entrada." + server_error: "Erro do servidor." + unknown: "Erro desconhecido." resources: your_sessions: "As Suas Sessões" @@ -895,14 +895,14 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription: thang: "Thang" thangs: "Thangs" level_session: "A Sua Sessão" - opponent_session: "Sessão Do Oponente" + opponent_session: "Sessão do Adversário" article: "Artigo" # user_names: "User Names" # thang_names: "Thang Names" # files: "Files" # top_simulators: "Top Simulators" # source_document: "Source Document" -# document: "Document" + document: "Documento" # sprite_sheet: "Sprite Sheet" # candidate_sessions: "Candidate Sessions" # user_remark: "User Remark" diff --git a/app/models/Level.coffee b/app/models/Level.coffee index f28bb9b00..cf7cfd52e 100644 --- a/app/models/Level.coffee +++ b/app/models/Level.coffee @@ -24,6 +24,28 @@ module.exports = class Level extends CocoModel o.thangTypes = (original: tt.get('original'), name: tt.get('name') for tt in supermodel.getModels ThangType) o + + denormalize: (supermodel) -> + o = $.extend true, {}, @attributes + for levelThang in o.thangs + @denormalizeThang(levelThang, supermodel) + o + + denormalizeThang: (levelThang, supermodel) -> + thangType = supermodel.getModelByOriginal(ThangType, levelThang.thangType) + configs = {} + for thangComponent in levelThang.components + configs[thangComponent.original] = thangComponent + + for defaultThangComponent in thangType.get('components') + if levelThangComponent = configs[defaultThangComponent.original] + # take the thang type default components and merge level-specific component config into it + copy = $.extend true, {}, defaultThangComponent.config + levelThangComponent.config = _.merge copy, levelThangComponent.config + + else + # just add the component as is + levelThang.components.push $.extend true, {}, defaultThangComponent sortSystems: (levelSystems, systemModels) -> [sorted, originalsSeen] = [[], {}] diff --git a/app/models/SuperModel.coffee b/app/models/SuperModel.coffee index c366d8285..e67b65436 100644 --- a/app/models/SuperModel.coffee +++ b/app/models/SuperModel.coffee @@ -78,6 +78,10 @@ module.exports = class SuperModel extends Backbone.Model getModelByURL: (modelURL) -> modelURL = modelURL() if _.isFunction(modelURL) return @models[modelURL] or null + + getModelByOriginal: (ModelClass, original) -> + _.find @models, (m) -> + m.get('original') is original and m.constructor.className is ModelClass.className getModelByOriginalAndMajorVersion: (ModelClass, original, majorVersion=0) -> _.find @models, (m) -> diff --git a/app/schemas/models/thang_type.coffee b/app/schemas/models/thang_type.coffee index 0203287af..d93b0e625 100644 --- a/app/schemas/models/thang_type.coffee +++ b/app/schemas/models/thang_type.coffee @@ -105,7 +105,7 @@ _.extend ThangTypeSchema.properties, shapes: c.object {title: 'Shapes', additionalProperties: ShapeObjectSchema} containers: c.object {title: 'Containers', additionalProperties: ContainerObjectSchema} animations: c.object {title: 'Animations', additionalProperties: RawAnimationObjectSchema} - kind: c.shortString {enum: ['Unit', 'Floor', 'Wall', 'Doodad', 'Misc', 'Mark'], default: 'Misc', title: 'Kind'} + kind: c.shortString {enum: ['Unit', 'Floor', 'Wall', 'Doodad', 'Misc', 'Mark', 'Item'], default: 'Misc', title: 'Kind'} actions: c.object {title: 'Actions', additionalProperties: {$ref: '#/definitions/action'}} soundTriggers: c.object {title: 'Sound Triggers', additionalProperties: c.array({}, {$ref: '#/definitions/sound'})}, diff --git a/app/styles/editor/components/main.sass b/app/styles/editor/components/main.sass index 5803020a7..3351694db 100644 --- a/app/styles/editor/components/main.sass +++ b/app/styles/editor/components/main.sass @@ -40,6 +40,9 @@ right: 0px bottom: 0 overflow: scroll + + .treema-row .add-button + margin-left: 10px #component-config-column-view border-left: 1px solid black diff --git a/app/styles/editor/level/modal/terrain_randomize.sass b/app/styles/editor/level/modal/terrain_randomize.sass index 892d4d52f..b6d1064e1 100644 --- a/app/styles/editor/level/modal/terrain_randomize.sass +++ b/app/styles/editor/level/modal/terrain_randomize.sass @@ -3,7 +3,7 @@ .choose-option margin-bottom: 15px width: 100% - height: 100px + height: 200px overflow: hidden background: white border: 1px solid #333 @@ -125,4 +125,7 @@ .hard-option .preset-name border-top: 25px solid black - color: white \ No newline at end of file + color: white + + .capitalize + text-transform: capitalize \ No newline at end of file diff --git a/app/styles/editor/level/thangs_tab.sass b/app/styles/editor/level/thangs_tab.sass index 5fe9e2f10..e8175462f 100644 --- a/app/styles/editor/level/thangs_tab.sass +++ b/app/styles/editor/level/thangs_tab.sass @@ -110,6 +110,12 @@ $mobile: 1050px .treema-node.treema-Wall display: block + &.hide-except-Item + .treema-node + display: none + .treema-node.treema-Item + display: block + &.hide-except-Misc .treema-node display: none @@ -151,6 +157,8 @@ $mobile: 1050px input width: $addPaletteWidth margin: 0 + margin-top: 5px + padding-left: 5px @media screen and (max-width: $mobile) margin: 0 5px @@ -208,6 +216,22 @@ $mobile: 1050px #canvas-wrapper width: 100% position: relative + + #canvas-overlay + display: none + position: absolute + width: 100% + height: 100% + background: white + opacity: 0.5 + text-align: center + + #randomize-button + position: absolute + top: 45% + height: 40px + + // Below snatched from play/level.sass; should refactor? diff --git a/app/styles/play/level.sass b/app/styles/play/level.sass index 3abc58d24..90e40715f 100644 --- a/app/styles/play/level.sass +++ b/app/styles/play/level.sass @@ -42,7 +42,6 @@ body.is-playing position: fixed width: 100% height: 100% - z-index: 20 #pointer position: absolute diff --git a/app/styles/play/level/tome/problem_alert.sass b/app/styles/play/level/tome/problem_alert.sass index d26a3ad5b..70920356d 100644 --- a/app/styles/play/level/tome/problem_alert.sass +++ b/app/styles/play/level/tome/problem_alert.sass @@ -3,18 +3,22 @@ .problem-alert z-index: 10 position: absolute - bottom: -120px + bottom: -135px left: 10px right: 10px background: transparent border: 0 - padding: 18px 35px 18px 14px + padding: 0 text-shadow: none color: white word-wrap: break-word border-image: url(/images/level/code_editor_error_background.png) 16 20 fill round border-width: 16px 20px + &.no-hint + // Since it's probably only one line, let's make it not look weird by being tiny. + padding: 7px + .close @include opacity(0.80) text-shadow: none @@ -35,10 +39,6 @@ &.alert-info border-image-source: url(/images/level/code_editor_info_background.png) - - &.alert-style - // Do we ever want to do this for style? - border-image-source: url(/images/level/code_editor_info_background.png) html.no-borderimage .problem-alert @@ -46,13 +46,10 @@ html.no-borderimage border-image: none background: transparent url(/images/level/code_editor_error_background.png) no-repeat background-size: 100% 100% - + padding: 18px 35px 18px 14px + &.alert-warning background-image: url(/images/level/code_editor_warning_background.png) &.alert-info background-image: url(/images/level/code_editor_info_background.png) - - &.alert-style - // Do we ever want to do this for style? - background-image: url(/images/level/code_editor_info_background.png) \ No newline at end of file diff --git a/app/styles/play/level/tome/spell.sass b/app/styles/play/level/tome/spell.sass index 291403dc0..653e30709 100644 --- a/app/styles/play/level/tome/spell.sass +++ b/app/styles/play/level/tome/spell.sass @@ -28,8 +28,8 @@ width: 100% span.code-background - border-width: 22px - border-image: url(/images/level/code_editor_background.png) 22 fill round + border-width: 40px + border-image: url(/images/level/code_editor_background.png) 40 fill round img.code-background display: none @@ -62,7 +62,7 @@ overflow: visible &.user-code-problem.spell-cast - @include editor-height(40px) + @include editor-height(60px) &.disabled @include opacity(80) diff --git a/app/styles/play/level/tome/tome.sass b/app/styles/play/level/tome/tome.sass index 370cc293d..e41128470 100644 --- a/app/styles/play/level/tome/tome.sass +++ b/app/styles/play/level/tome/tome.sass @@ -76,3 +76,11 @@ html.no-borderimage background: transparent url(/images/level/popover_background.png) background-size: 100% 100% border: 0 + +#code-area.fullscreen-editor + #tome-view + .popover.pinned + min-width: 600px + bottom: inherit + right: 50% + margin-right: -300px \ No newline at end of file diff --git a/app/templates/account/profile.jade b/app/templates/account/profile.jade index 46a15da4e..37ff7ef85 100644 --- a/app/templates/account/profile.jade +++ b/app/templates/account/profile.jade @@ -3,7 +3,10 @@ extends /templates/base block content if !allowedToEditJobProfile && me.get('anonymous') == true div(class="job-profile-container") - h1#login-message Please login to view this profile. + h1#login-message + |Please + a.auth-button login + | to view this profile. else if allowedToEditJobProfile .profile-control-bar @@ -191,7 +194,9 @@ block content span.spl - #{session.team} if session.codeLanguage != 'javascript' span.spl - #{{coffeescript: 'CoffeeScript', python: 'Python', lua: 'Lua', io: 'Io', clojure: 'Clojure'}[session.codeLanguage]} - + if !editing && !sessions.length + h3(data-i18n="account_profile.player_code") Player Code + p This player hasn't submitted code to our more recent tournaments. .middle-column.full-height-column .sub-column #name-container.editable-section diff --git a/app/templates/admin.jade b/app/templates/admin.jade index 5d583f703..79061e10d 100644 --- a/app/templates/admin.jade +++ b/app/templates/admin.jade @@ -22,9 +22,9 @@ block content li a(href="/admin/users", data-i18n="admin.av_entities_users_url") Users li - a(href="/admin/level_sessions", data-i18n="admin.av_entities_active_instances_url") Active Instances + a(href="/admin/level-sessions", data-i18n="admin.av_entities_active_instances_url") Active Instances li - a(href="/admin/employer_list", data-i18n="admin.av_entities_employer_list_url") Employer List + a(href="/admin/employers", data-i18n="admin.av_entities_employer_list_url") Employer List li a(href="/admin/candidates") Candidate List diff --git a/app/templates/base.jade b/app/templates/base.jade index 6c18d420c..d8bc8996f 100644 --- a/app/templates/base.jade +++ b/app/templates/base.jade @@ -67,7 +67,7 @@ body a(href='/contribute', title='Contribute', tabindex=-1, data-i18n="nav.contribute") Contribute a(href='/legal', title='Legal', tabindex=-1, data-i18n="nav.legal") Legal a(href='/about', title='About', tabindex=-1, data-i18n="nav.about") About - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Contact a(href='/editor', data-i18n="nav.editor") Editor a(href='http://blog.codecombat.com/', data-i18n="nav.blog") Blog a(href='http://discourse.codecombat.com/', data-i18n="nav.forum") Forum diff --git a/app/templates/contribute/ambassador.jade b/app/templates/contribute/ambassador.jade index 2d1f65564..d7be893da 100644 --- a/app/templates/contribute/ambassador.jade +++ b/app/templates/contribute/ambassador.jade @@ -31,7 +31,7 @@ block content h4(data-i18n="contribute.how_to_join") How to Join p - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.contact_us_url") + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="contribute.contact_us_url") | Contact us span , span(data-i18n="contribute.ambassador_join_desc") diff --git a/app/templates/contribute/archmage.jade b/app/templates/contribute/archmage.jade index ae982472e..0d00200c7 100644 --- a/app/templates/contribute/archmage.jade +++ b/app/templates/contribute/archmage.jade @@ -48,7 +48,7 @@ block content span(data-i18n="contribute.join_desc_2") | to get started, and check the box below to mark yourself as a brave Archmage and get the latest news by email. | Want to chat about what to do or how to get more deeply involved? - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.join_url_email") + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="contribute.join_url_email") | Email us span(data-i18n="contribute.join_desc_3") | , or find us in our diff --git a/app/templates/contribute/scribe.jade b/app/templates/contribute/scribe.jade index 92155143c..a4aae2b81 100644 --- a/app/templates/contribute/scribe.jade +++ b/app/templates/contribute/scribe.jade @@ -37,7 +37,7 @@ block content h4(data-i18n="contribute.how_to_join") How To Join p - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.contact_us_url") + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="contribute.contact_us_url") | Contact us span , span(data-i18n="contribute.scribe_join_description") diff --git a/app/templates/docs/components.jade b/app/templates/docs/components.jade index 88f442bcc..51fe52c5e 100644 --- a/app/templates/docs/components.jade +++ b/app/templates/docs/components.jade @@ -1,4 +1,4 @@ -extends /templates/base +//extends /templates/base block content diff --git a/app/templates/editor.jade b/app/templates/editor.jade index 82101e03f..f9541d33d 100644 --- a/app/templates/editor.jade +++ b/app/templates/editor.jade @@ -36,7 +36,7 @@ block content p span(data-i18n="editor.got_questions") Questions about using the CodeCombat editors? | - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="editor.contact_us") Contact us! + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="editor.contact_us") Contact us! | span(data-i18n="editor.hipchat_prefix") You can also find us in our | diff --git a/app/templates/editor/article/edit.jade b/app/templates/editor/article/edit.jade index f882cea08..76e8d255b 100644 --- a/app/templates/editor/article/edit.jade +++ b/app/templates/editor/article/edit.jade @@ -11,7 +11,7 @@ block content | #{article.attributes.name} button(data-i18n="general.version_history").btn.btn-primary#history-button Version History - button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary#revert-button Revert + button(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary#revert-button Revert button(data-i18n="article.edit_btn_preview", disabled=authorized === true ? undefined : "true").btn.btn-primary#preview-button Preview button(data-i18n="common.save", disabled=authorized === true ? undefined : "true").btn.btn-primary#save-button Save diff --git a/app/templates/editor/level/add_thangs.jade b/app/templates/editor/level/add_thangs.jade index fe9fbba39..cec7666f9 100644 --- a/app/templates/editor/level/add_thangs.jade +++ b/app/templates/editor/level/add_thangs.jade @@ -1,5 +1,5 @@ h3(data-i18n="editor.level_tab_thangs_add") Add Thangs -input(type="search", id="thang-search") +input(type="search", id="thang-search", placeholder="Search thangs") div.editor-nano-container.nano #thangs-list.nano-content for group in groups diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade index c1f372e29..3f16f5559 100644 --- a/app/templates/editor/level/edit.jade +++ b/app/templates/editor/level/edit.jade @@ -33,11 +33,18 @@ block header - var patches = level.get('patches') if patches && patches.length span.badge= patches.length - + li + a(href="#docs-components-view", data-toggle="tab", data-i18n="editor.level_tab_docs") Documentation .navbar-header span.navbar-brand #{level.attributes.name} ul.nav.navbar-nav.navbar-right + li#undo-button(title="Undo (Ctrl+Z)") + a + span.glyphicon-arrow-left.glyphicon + li#redo-button(title="Redo (Ctrl+Shift+Z)") + a + span.glyphicon-repeat.glyphicon if authorized li#commit-level-start-button a @@ -78,9 +85,9 @@ block header li(class=anonymous ? "disabled": "") 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 + a(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert")#revert-button Revert li(class=anonymous ? "disabled": "") - a(data-toggle="coco-modal", data-target="editor/level/modal/terrain_randomize", data-i18n="editor.randomize")#randomize-button Randomize + a(data-toggle="coco-modal", data-target="editor/level/modals/TerrainRandomizeModal", data-i18n="editor.randomize")#randomize-button Randomize li(class=anonymous ? "disabled": "") a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n li.divider @@ -96,7 +103,7 @@ block header li a(href='http://discourse.codecombat.com/category/artisan', data-i18n="nav.forum", target="_blank") Forum li - a(data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Email + a(data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Email block outer_content .outer-content @@ -114,6 +121,8 @@ block outer_content div.tab-pane#editor-level-patches .patches-view + div.tab-pane#docs-components-view + div#error-view block footer \ No newline at end of file diff --git a/app/templates/editor/level/modal/terrain_randomize.jade b/app/templates/editor/level/modal/terrain_randomize.jade index 8ea39185e..a4e45b2f2 100644 --- a/app/templates/editor/level/modal/terrain_randomize.jade +++ b/app/templates/editor/level/modal/terrain_randomize.jade @@ -5,11 +5,12 @@ block modal-header-content block modal-body-content div#normal-view - a(href="#") - div.choose-option(data-preset-type="grassy", data-preset-size="small") - div.preset-size.name-label - span(data-i18n="editor.small") Small - div.preset-name - span(data-i18n="editor.grassy") Grassy - //- for model in models + each sizeObject, size in presetSizes + each preset in presets + a(href="#") + div.choose-option(data-preset-type=preset.type, data-preset-size=size, style="background:url(/images/pages/editor/level/preset_"+preset.type+"_"+size+".jpg) no-repeat center; background-size: cover") + div.preset-size.name-label.capitalize + span(data-i18n="editor."+size) #{size} + div.preset-name.capitalize + span(data-i18n="editor."+preset.type) #{preset.type} block modal-footer diff --git a/app/templates/editor/level/thangs_tab.jade b/app/templates/editor/level/thangs_tab.jade index e76a0f0d9..3cb870ddd 100644 --- a/app/templates/editor/level/thangs_tab.jade +++ b/app/templates/editor/level/thangs_tab.jade @@ -15,6 +15,8 @@ button.navbar-toggle.toggle.btn-primary#thangs-palette-toggle(type="button", dat i.icon-globe button.btn.btn-primary(value="Doodad", title="Doodad") i.icon-leaf + button.btn.btn-primary(value="Item", title="Item") + i.icon-gift button.btn.btn-primary(value="Misc", title="Misc") i.icon-question-sign .editor-nano-container.nano @@ -23,6 +25,8 @@ button.navbar-toggle.toggle.btn-primary#thangs-palette-toggle(type="button", dat .world-container.thangs-column h3(data-i18n="editor.level_tab_thangs_conditions") Starting Conditions #canvas-wrapper + #canvas-overlay + button.btn.btn-primary(id="randomize-button", data-toggle="coco-modal", data-target="editor/level/modals/TerrainRandomizeModal", data-i18n="editor.randomize", title="Randomize Terrain") Randomize ul.dropdown-menu#contextmenu li#delete a(data-i18n="editor.delete") Delete diff --git a/app/templates/editor/thang/edit.jade b/app/templates/editor/thang/edit.jade index b1924f439..df7972622 100644 --- a/app/templates/editor/thang/edit.jade +++ b/app/templates/editor/thang/edit.jade @@ -14,7 +14,7 @@ block content button.btn.btn-secondary#history-button(data-i18n="general.version_history") Version History button.btn.btn-primary#save-button(data-i18n="common.save", disabled=authorized === true ? undefined : "true") Save - button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true") Revert + button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true") Revert h3 Edit Thang Type: "#{thangType.attributes.name}" diff --git a/app/templates/kinds/search.jade b/app/templates/kinds/search.jade index 59a9c880c..0e522d272 100644 --- a/app/templates/kinds/search.jade +++ b/app/templates/kinds/search.jade @@ -10,7 +10,7 @@ block content | #{currentEditor} if me.get('anonymous') - a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="modal/auth", role="button", data-i18n="#{currentNewSignup}") Log in to Create a New Content + a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="modal/AuthModal", role="button", data-i18n="#{currentNewSignup}") Log in 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/templates/modal/auth.jade b/app/templates/modal/auth.jade index 80444f4c1..0bb8f6b49 100644 --- a/app/templates/modal/auth.jade +++ b/app/templates/modal/auth.jade @@ -74,4 +74,4 @@ block modal-footer div.network-login .gplus-login-button#gplus-login-button div#recover-account-wrapper - a(data-toggle="coco-modal", data-target="modal/recover", data-i18n="login.recover")#link-to-recover recover account + a(data-toggle="coco-modal", data-target="modal/RecoverModal", data-i18n="login.recover")#link-to-recover recover account diff --git a/app/templates/modal/employer_signup_modal.jade b/app/templates/modal/employer_signup_modal.jade index 8d0429137..0c17755da 100644 --- a/app/templates/modal/employer_signup_modal.jade +++ b/app/templates/modal/employer_signup_modal.jade @@ -23,7 +23,7 @@ block modal-body-content br br | Already have a CodeCombat account? - a.login-link(data-toggle="coco-modal", data-target="modal/auth") Log in to continue! + a.login-link(data-toggle="coco-modal", data-target="modal/AuthModal") Log in to continue! else if !userIsAuthorized .modal-footer.linkedin p Please sign into your LinkedIn account to verify your identity. @@ -50,7 +50,7 @@ block modal-footer if userIsAnonymous if userIsAuthorized .modal-footer.linkedin - a.login-link(data-toggle="coco-modal", data-target="modal/auth") Please log in to continue. + a.login-link(data-toggle="coco-modal", data-target="modal/AuthModal") Please log in to continue. else if !userIsAnonymous && !userIsAuthorized .modal-footer.linkedin else if userIsAuthorized && !userHasSignedContract diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade index 515397e1f..2c74735eb 100644 --- a/app/templates/play/ladder/ladder_tab.jade +++ b/app/templates/play/ladder/ladder_tab.jade @@ -21,12 +21,12 @@ div#columns.row for session, rank in topSessions - var myRow = session.get('creator') == me.id tr(class=myRow ? "success" : "", data-player-id=session.get('creator'), data-session-id=session.id) - td.code-language-cell(style="background-image: url(/images/common/code_languages/" + session.get('submittedCodeLanguage') + "_icon.png)") + td.code-language-cell(style="background-image: url(/images/common/code_languages/" + session.get('submittedCodeLanguage') + "_icon.png)" title=capitalize(session.get('submittedCodeLanguage'))) td.rank-cell= rank + 1 td.score-cell= Math.round(session.get('totalScore') * 100) td.name-col-cell= session.get('creatorName') || "Anonymous" td.fight-cell - a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") + a(href="/play/level/#{level.get('slug') || level.id}?team=#{team.otherTeam}&opponent=#{session.id}") span(data-i18n="ladder.fight") Fight! if !showJustTop && team.leaderboard.nearbySessions().length @@ -40,7 +40,7 @@ div#columns.row td.score-cell= Math.round(session.get('totalScore') * 100) td.name-col-cell= session.get('creatorName') || "Anonymous" td.fight-cell - a(href="/play/level/#{level.get('slug') || level.id}/?team=#{team.otherTeam}&opponent=#{session.id}") + a(href="/play/level/#{level.get('slug') || level.id}?team=#{team.otherTeam}&opponent=#{session.id}") span(data-i18n="ladder.fight") Fight! if teamIndex == 1 .btn.btn-sm.load-more-ladder-entries More @@ -49,7 +49,7 @@ div#columns.row h4.friends-header(data-i18n="ladder.friends_playing") Friends Playing if me.get('anonymous') div.alert.alert-info - a(data-toggle="coco-modal", data-target="modal/auth", data-i18n="ladder.log_in_for_friends") Log in to play with your friends! + a(data-toggle="coco-modal", data-target="modal/AuthModal", data-i18n="ladder.log_in_for_friends") Log in to play with your friends! else if !onFacebook || !onGPlus diff --git a/app/templates/play/level.jade b/app/templates/play/level.jade index 89418e365..a4d9d4fd9 100644 --- a/app/templates/play/level.jade +++ b/app/templates/play/level.jade @@ -24,7 +24,7 @@ .footer .content p(class='footer-link-text') - a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact + a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Contact if explainHourOfCode // Does not show up unless lang is en-US. div.hour-of-code-explanation diff --git a/app/templates/play/level/modal/victory.jade b/app/templates/play/level/modal/victory.jade index 48ccd6af3..a58b39a3b 100644 --- a/app/templates/play/level/modal/victory.jade +++ b/app/templates/play/level/modal/victory.jade @@ -21,7 +21,7 @@ block modal-footer-content a.btn.btn-primary(href="/", data-dismiss="modal", data-i18n="play_level.victory_go_home") Go Home if me.get('anonymous') p.sign-up-poke - button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="modal/signup", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress + button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="modal/SignupModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account! p.clearfix else diff --git a/app/templates/play/level/tome/spell_list_tab_entry.jade b/app/templates/play/level/tome/spell_list_tab_entry.jade index d896baa5c..02726b131 100644 --- a/app/templates/play/level/tome/spell_list_tab_entry.jade +++ b/app/templates/play/level/tome/spell_list_tab_entry.jade @@ -1,3 +1,5 @@ +img(src="/images/level/code_editor_tab_background.png").spell-tab-image-hidden.hidden + .btn.btn-small.spell-list-button(title="See all spells you can edit") i.icon-chevron-down .thang-avatar-placeholder diff --git a/app/templates/play/spectate.jade b/app/templates/play/spectate.jade index ee9408d4c..720cd4b30 100644 --- a/app/templates/play/spectate.jade +++ b/app/templates/play/spectate.jade @@ -13,4 +13,4 @@ .footer .content p(class='footer-link-text') - a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact \ No newline at end of file + a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Contact \ No newline at end of file diff --git a/app/templates/teachers.jade b/app/templates/teachers.jade index 651de1205..529e3e50d 100644 --- a/app/templates/teachers.jade +++ b/app/templates/teachers.jade @@ -24,7 +24,7 @@ block content p More questions? Get in touch! Feature requests? We'd love to hear them! CodeCombat is new and needs to hear from you to learn what teachers would love to have in their classrooms of programming wizards-to-be. h3 - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact") Contact Us + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal") Contact Us .span5 diff --git a/app/views/EmployersView.coffee b/app/views/EmployersView.coffee index 57ca3c78f..b7699e428 100644 --- a/app/views/EmployersView.coffee +++ b/app/views/EmployersView.coffee @@ -1,11 +1,10 @@ RootView = require 'views/kinds/RootView' template = require 'templates/employers' -app = require 'application' User = require 'models/User' UserRemark = require 'models/UserRemark' {me} = require 'lib/auth' CocoCollection = require 'collections/CocoCollection' -EmployerSignupView = require 'views/modal/employer_signup_modal' +EmployerSignupModal = require 'views/modal/EmployerSignupModal' class CandidatesCollection extends CocoCollection url: '/db/user/x/candidates' @@ -75,7 +74,7 @@ module.exports = class EmployersView extends RootView @applyFilters() openSignupModal: -> - @openModalView new EmployerSignupView + @openModalView new EmployerSignupModal handleSelectAllChange: (e) -> checkedState = e.currentTarget.checked $('#filters :input').each -> @@ -222,7 +221,7 @@ module.exports = class EmployersView extends RootView checkForEmployerSignupHash: => if window.location.hash is '#employerSignupLoggingIn' and not ('employer' in me.get('permissions')) and not me.isAdmin() - @openModalView application.router.getView('modal/employer_signup', '_modal') + @openModalView new EmployerSignupModal window.location.hash = '' sortTable: -> @@ -356,4 +355,4 @@ module.exports = class EmployersView extends RootView url = "/account/profile/#{id}" window.open url, '_blank' else - @openModalView new EmployerSignupView + @openModalView new EmployerSignupModal diff --git a/app/views/HomeView.coffee b/app/views/HomeView.coffee index 05e9f78f0..4323f5ea0 100644 --- a/app/views/HomeView.coffee +++ b/app/views/HomeView.coffee @@ -4,7 +4,6 @@ WizardSprite = require 'lib/surface/WizardSprite' ThangType = require 'models/ThangType' Simulator = require 'lib/simulator/Simulator' {me} = require '/lib/auth' -application = require 'application' module.exports = class HomeView extends RootView id: 'home-view' diff --git a/app/views/TestView.coffee b/app/views/TestView.coffee index dceff7b36..3b6a52c01 100644 --- a/app/views/TestView.coffee +++ b/app/views/TestView.coffee @@ -9,6 +9,7 @@ module.exports = TestView = class TestView extends CocoView id: 'test-view' template: template reloadOnClose: true + loadedFileIDs: [] # INITIALIZE @@ -18,13 +19,19 @@ module.exports = TestView = class TestView extends CocoView @loadTestingLibs() loadTestingLibs: -> - @queue = new createjs.LoadQueue() + @queue = new createjs.LoadQueue() unless @queue @queue.on('complete', @scriptsLoaded, @) + @queue.on('fileload', @onFileLoad, @) for f in ['jasmine', 'jasmine-html', 'boot', 'mock-ajax', 'test-app'] - @queue.loadFile({ - src: "/javascripts/#{f}.js" - type: createjs.LoadQueue.JAVASCRIPT - }) + if f not in @loadedFileIDs + @queue.loadFile({ + id: f + src: "/javascripts/#{f}.js" + type: createjs.LoadQueue.JAVASCRIPT + }) + + onFileLoad: (e) -> + @loadedFileIDs.push e.item.id if e.item.id scriptsLoaded: -> @initSpecFiles() diff --git a/app/views/account/settings_view.coffee b/app/views/account/AccountSettingsView.coffee similarity index 94% rename from app/views/account/settings_view.coffee rename to app/views/account/AccountSettingsView.coffee index 39a335488..7dabe37fa 100644 --- a/app/views/account/settings_view.coffee +++ b/app/views/account/AccountSettingsView.coffee @@ -3,12 +3,12 @@ template = require 'templates/account/settings' {me} = require 'lib/auth' forms = require 'lib/forms' User = require 'models/User' -AuthModalView = require 'views/modal/auth_modal' +AuthModal = require 'views/modal/AuthModal' -WizardSettingsView = require './wizard_settings_view' -JobProfileView = require './job_profile_view' +WizardSettingsView = require './WizardSettingsView' +JobProfileTreemaView = require './JobProfileTreemaView' -module.exports = class SettingsView extends RootView +module.exports = class AccountSettingsView extends RootView id: 'account-settings-view' template: template changedFields: [] # DOM input fields @@ -97,9 +97,9 @@ module.exports = class SettingsView extends RootView @listenTo wizardSettingsView, 'change', @enableSaveButton @insertSubView wizardSettingsView - @jobProfileView = new JobProfileView() - @listenTo @jobProfileView, 'change', @enableSaveButton - @insertSubView @jobProfileView + @jobProfileTreemaView = new JobProfileTreemaView() + @listenTo @jobProfileTreemaView, 'change', @enableSaveButton + @insertSubView @jobProfileTreemaView _.defer => @buildPictureTreema() # Not sure why, but the Treemas don't fully build without this if you reload the page. afterInsert: -> @@ -107,7 +107,7 @@ module.exports = class SettingsView extends RootView $('#email-pane input[type="checkbox"]').on 'change', -> $(@).addClass 'changed' if me.get('anonymous') - @openModalView new AuthModalView() + @openModalView new AuthModal() @updateSavedValues() chooseTab: (category) -> @@ -222,7 +222,7 @@ module.exports = class SettingsView extends RootView jobProfile = me.get('jobProfile') ? {} updated = false - for key, val of @jobProfileView.getData() + for key, val of @jobProfileTreemaView.getData() updated = updated or not _.isEqual jobProfile[key], val jobProfile[key] = val if updated diff --git a/app/views/account/JobProfileCodeModal.coffee b/app/views/account/JobProfileCodeModal.coffee index 397de97cf..307f75847 100644 --- a/app/views/account/JobProfileCodeModal.coffee +++ b/app/views/account/JobProfileCodeModal.coffee @@ -1,7 +1,6 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/account/job_profile_code_modal' LevelSessionCodeView = require 'views/common/LevelSessionCodeView' -console.log 'template', template module.exports = class JobProfileCodeModal extends ModalView id: 'job_profile_code_modal' diff --git a/app/views/account/JobProfileTreemaView.coffee b/app/views/account/JobProfileTreemaView.coffee new file mode 100644 index 000000000..1ddde82e1 --- /dev/null +++ b/app/views/account/JobProfileTreemaView.coffee @@ -0,0 +1,131 @@ +CocoView = require 'views/kinds/CocoView' +template = require 'templates/account/job_profile' +{me} = require 'lib/auth' + +module.exports = class JobProfileTreemaView extends CocoView + id: 'job-profile-view' + template: template + + editableSettings: [ + 'lookingFor', 'active', 'name', 'city', 'country', 'skills', 'experience', 'shortDescription', 'longDescription', + 'work', 'education', 'visa', 'projects', 'links', 'jobTitle', 'photoURL' + ] + readOnlySettings: [] #['updated'] + + afterRender: -> + super() + return unless @supermodel.finished() + _.defer => @buildJobProfileTreema() # Not sure why, but the Treemas don't fully build without this if you reload the page. + + buildJobProfileTreema: -> + visibleSettings = @editableSettings.concat @readOnlySettings + data = _.pick (me.get('jobProfile') ? {}), (value, key) -> key in visibleSettings + data.name ?= (me.get('firstName') + ' ' + me.get('lastName')).trim() if me.get('firstName') + schema = _.cloneDeep me.schema().properties.jobProfile + schema.properties = _.pick schema.properties, (value, key) -> key in visibleSettings + schema.required = _.intersection schema.required, visibleSettings + for prop in @readOnlySettings + schema.properties[prop].readOnly = true + treemaOptions = + filePath: "db/user/#{me.id}" + schema: schema + data: data + aceUseWrapMode: true + callbacks: {change: @onJobProfileChanged} + nodeClasses: + 'skill': SkillTagNode + 'link-name': LinkNameNode + 'city': CityNode + 'country': CountryNode + + @jobProfileTreema = @$el.find('#job-profile-treema').treema treemaOptions + @jobProfileTreema.build() + @jobProfileTreema.open() + @updateProgress() + + onJobProfileChanged: (e) => + @hasEditedProfile = true + @trigger 'change' + @updateProgress() + + updateProgress: -> + completed = 0 + totalWeight = 0 + next = null + for metric in metrics = @getProgressMetrics() + done = metric.fn() + completed += metric.weight if done + totalWeight += metric.weight + next = metric.name unless next or done + progress = Math.round 100 * completed / totalWeight + bar = @$el.find('.profile-completion-progress .progress-bar') + bar.css 'width', "#{progress}%" + text = '' + if progress > 19 + text = "#{progress}% complete" + else if progress > 5 + text = "#{progress}%" + bar.text text + bar.parent().toggle Boolean progress + @$el.find('.progress-next-item').text(next).toggle Boolean next + + getProgressMetrics: -> + return @progressMetrics if @progressMetrics + schema = me.schema().properties.jobProfile + jobProfile = @jobProfileTreema.data + exists = (field) -> -> jobProfile[field] + modified = (field) -> -> jobProfile[field] and jobProfile[field] isnt schema.properties[field].default + listStarted = (field, subfields) -> -> jobProfile[field]?.length and _.every subfields, (subfield) -> jobProfile[field][0][subfield] + @progressMetrics = [ + {name: 'Mark yourself open to offers to show up in searches.', weight: 1, fn: modified 'active'} + {name: 'Specify your desired job title.', weight: 0, fn: exists 'jobTitle'} + {name: 'Provide your name.', weight: 1, fn: modified 'name'} + {name: 'Choose your city.', weight: 1, fn: modified 'city'} + {name: 'Pick your country.', weight: 0, fn: exists 'country'} + {name: 'List at least five skills.', weight: 2, fn: -> jobProfile.skills.length >= 5} + {name: 'Write a short description to summarize yourself at a glance.', weight: 2, fn: modified 'shortDescription'} + {name: 'Fill in your main description to sell yourself and describe the work you\'re looking for.', weight: 3, fn: modified 'longDescription'} + {name: 'List your work experience.', weight: 3, fn: listStarted 'work', ['role', 'employer']} + {name: 'Recount your educational ordeals.', weight: 3, fn: listStarted 'education', ['degree', 'school']} + {name: 'Show off up to three projects you\'ve worked on.', weight: 3, fn: listStarted 'projects', ['name']} + {name: 'Add any personal or social links.', weight: 2, fn: listStarted 'links', ['link', 'name']} + {name: 'Add an optional professional photo.', weight: 2, fn: modified 'photoURL'} + ] + + getData: -> + return {} unless me.get('jobProfile') or @hasEditedProfile + _.pick @jobProfileTreema.data, (value, key) => key in @editableSettings + +JobProfileTreemaView.commonSkills = commonSkills = ['c#', 'java', 'javascript', 'php', 'android', 'jquery', 'python', 'c++', 'html', 'mysql', 'ios', 'asp.net', 'css', 'sql', 'iphone', '.net', 'objective-c', 'ruby-on-rails', 'c', 'ruby', 'sql-server', 'ajax', 'wpf', 'linux', 'database', 'django', 'vb.net', 'windows', 'facebook', 'r', 'html5', 'multithreading', 'ruby-on-rails-3', 'wordpress', 'winforms', 'node.js', 'spring', 'osx', 'performance', 'visual-studio-2010', 'oracle', 'swing', 'algorithm', 'git', 'linq', 'apache', 'web-services', 'perl', 'wcf', 'entity-framework', 'bash', 'visual-studio', 'sql-server-2008', 'hibernate', 'actionscript-3', 'angularjs', 'matlab', 'qt', 'ipad', 'sqlite', 'cocoa-touch', 'cocoa', 'flash', 'mongodb', 'codeigniter', 'jquery-ui', 'css3', 'tsql', 'google-maps', 'silverlight', 'security', 'delphi', 'vba', 'postgresql', 'jsp', 'shell', 'internet-explorer', 'google-app-engine', 'sockets', 'validation', 'scala', 'oop', 'unit-testing', 'xaml', 'parsing', 'twitter-bootstrap', 'google-chrome', 'http', 'magento', 'email', 'android-layout', 'flex', 'rest', 'maven', 'jsf', 'listview', 'date', 'winapi', 'windows-phone-7', 'facebook-graph-api', 'unix', 'url', 'c#-4.0', 'jquery-ajax', 'svn', 'symfony2', 'table', 'cakephp', 'firefox', 'ms-access', 'java-ee', 'jquery-mobile', 'python-2.7', 'tomcat', 'zend-framework', 'opencv', 'visual-c++', 'opengl', 'spring-mvc', 'sql-server-2005', 'authentication', 'search', 'xslt', 'servlets', 'pdf', 'animation', 'math', 'batch-file', 'excel-vba', 'iis', 'mod-rewrite', 'sharepoint', 'gwt', 'powershell', 'visual-studio-2012', 'haskell', 'grails', 'ubuntu', 'networking', 'nhibernate', 'design-patterns', 'testing', 'jpa', 'visual-studio-2008', 'core-data', 'user-interface', 'audio', 'backbone.js', 'gcc', 'mobile', 'design', 'activerecord', 'extjs', 'video', 'stored-procedures', 'optimization', 'drupal', 'image-processing', 'android-intent', 'logging', 'web-applications', 'razor', 'database-design', 'azure', 'vim', 'memory-management', 'model-view-controller', 'cordova', 'c++11', 'selenium', 'ssl', 'assembly', 'soap', 'boost', 'canvas', 'google-maps-api-3', 'netbeans', 'heroku', 'jsf-2', 'encryption', 'hadoop', 'linq-to-sql', 'dll', 'xpath', 'data-binding', 'windows-phone-8', 'phonegap', 'jdbc', 'python-3.x', 'twitter', 'mvvm', 'gui', 'web', 'jquery-plugins', 'numpy', 'deployment', 'ios7', 'emacs', 'knockout.js', 'graphics', 'joomla', 'unicode', 'windows-8', 'android-fragments', 'ant', 'command-line', 'version-control', 'yii', 'github', 'amazon-web-services', 'macros', 'ember.js', 'svg', 'opengl-es', 'django-models', 'solr', 'orm', 'blackberry', 'windows-7', 'ruby-on-rails-4', 'compiler', 'tcp', 'pdo', 'architecture', 'groovy', 'nginx', 'concurrency', 'paypal', 'iis-7', 'express', 'vbscript', 'google-chrome-extension', 'memory-leaks', 'rspec', 'actionscript', 'interface', 'fonts', 'oauth', 'ssh', 'tfs', 'junit', 'struts2', 'd3.js', 'coldfusion', '.net-4.0', 'jqgrid', 'asp-classic', 'https', 'plsql', 'stl', 'sharepoint-2010', 'asp.net-web-api', 'mysqli', 'sed', 'awk', 'internet-explorer-8', 'jboss', 'charts', 'scripting', 'matplotlib', 'laravel', 'clojure', 'entity-framework-4', 'intellij-idea', 'xml-parsing', 'sqlite3', '3d', 'io', 'mfc', 'devise', 'playframework', 'youtube', 'amazon-ec2', 'localization', 'cuda', 'jenkins', 'ssis', 'safari', 'doctrine2', 'vb6', 'amazon-s3', 'dojo', 'air', 'eclipse-plugin', 'android-asynctask', 'crystal-reports', 'cocos2d-iphone', 'dns', 'highcharts', 'ruby-on-rails-3.2', 'ado.net', 'sql-server-2008-r2', 'android-emulator', 'spring-security', 'cross-browser', 'oracle11g', 'bluetooth', 'f#', 'msbuild', 'drupal-7', 'google-apps-script', 'mercurial', 'xna', 'google-analytics', 'lua', 'parallel-processing', 'internationalization', 'java-me', 'mono', 'monotouch', 'android-ndk', 'lucene', 'kendo-ui', 'linux-kernel', 'terminal', 'phpmyadmin', 'makefile', 'ffmpeg', 'applet', 'active-directory', 'coffeescript', 'pandas', 'responsive-design', 'xhtml', 'silverlight-4.0', '.net-3.5', 'jaxb', 'ruby-on-rails-3.1', 'gps', 'geolocation', 'network-programming', 'windows-services', 'laravel-4', 'ggplot2', 'rss', 'webkit', 'functional-programming', 'wsdl', 'telerik', 'maven-2', 'cron', 'mapreduce', 'websocket', 'automation', 'windows-runtime', 'django-forms', 'tkinter', 'android-widget', 'android-activity', 'rubygems', 'content-management-system', 'doctrine', 'django-templates', 'gem', 'fluent-nhibernate', 'seo', 'meteor', 'serial-port', 'glassfish', 'documentation', 'cryptography', 'ef-code-first', 'extjs4', 'x86', 'wordpress-plugin', 'go', 'wix', 'linq-to-entities', 'oracle10g', 'cocos2d', 'selenium-webdriver', 'open-source', 'jtable', 'qt4', 'smtp', 'redis', 'jvm', 'openssl', 'timezone', 'nosql', 'erlang', 'playframework-2.0', 'machine-learning', 'mocking', 'unity3d', 'thread-safety', 'android-actionbar', 'jni', 'udp', 'jasper-reports', 'zend-framework2', 'apache2', 'internet-explorer-7', 'sqlalchemy', 'neo4j', 'ldap', 'jframe', 'youtube-api', 'filesystems', 'make', 'flask', 'gdb', 'cassandra', 'sms', 'g++', 'django-admin', 'push-notification', 'statistics', 'tinymce', 'locking', 'javafx', 'firefox-addon', 'fancybox', 'windows-phone', 'log4j', 'uikit', 'prolog', 'socket.io', 'icons', 'oauth-2.0', 'refactoring', 'sencha-touch', 'elasticsearch', 'symfony1', 'google-api', 'webserver', 'wpf-controls', 'microsoft-metro', 'gtk', 'flex4', 'three.js', 'gradle', 'centos', 'angularjs-directive', 'internet-explorer-9', 'sass', 'html5-canvas', 'interface-builder', 'programming-languages', 'gmail', 'jersey', 'twitter-bootstrap-3', 'arduino', 'requirejs', 'cmake', 'web-development', 'software-engineering', 'startups', 'entrepreneurship', 'social-media-marketing', 'writing', 'marketing', 'web-design', 'graphic-design', 'game-development', 'game-design', 'photoshop', 'illustrator', 'robotics', 'aws', 'devops', 'mathematica', 'bioinformatics', 'data-vis', 'ui', 'embedded-systems', 'codecombat'] + +JobProfileTreemaView.commonLinkNames = commonLinkNames = ['GitHub', 'Facebook', 'Twitter', 'G+', 'LinkedIn', 'Personal Website', 'Blog'] + +JobProfileTreemaView.commonCountries = commonCountries = ['Afghanistan', 'Albania', 'Algeria', 'American Samoa', 'Andorra', 'Angola', 'Anguilla', 'Antarctica', 'Antigua and Barbuda', 'Argentina', 'Armenia', 'Aruba', 'Australia', 'Austria', 'Azerbaijan', 'Bahamas', 'Bahrain', 'Bangladesh', 'Barbados', 'Belarus', 'Belgium', 'Belize', 'Benin', 'Bermuda', 'Bhutan', 'Bolivia', 'Bosnia and Herzegovina', 'Botswana', 'Brazil', 'Brunei Darussalam', 'Bulgaria', 'Burkina Faso', 'Burundi', 'Cambodia', 'Cameroon', 'Canada', 'Cape Verde', 'Cayman Islands', 'Central African Republic', 'Chad', 'Chile', 'China', 'Christmas Island', 'Cocos (Keeling) Islands', 'Colombia', 'Comoros', 'Democratic Republic of the Congo (Kinshasa)', 'Congo, Republic of (Brazzaville)', 'Cook Islands', 'Costa Rica', 'Ivory Coast', 'Croatia', 'Cuba', 'Cyprus', 'Czech Republic', 'Denmark', 'Djibouti', 'Dominica', 'Dominican Republic', 'East Timor', 'Ecuador', 'Egypt', 'El Salvador', 'Equatorial Guinea', 'Eritrea', 'Estonia', 'Ethiopia', 'Falkland Islands', 'Faroe Islands', 'Fiji', 'Finland', 'France', 'French Guiana', 'French Polynesia', 'French Southern Territories', 'Gabon', 'Gambia', 'Georgia', 'Germany', 'Ghana', 'Gibraltar', 'Great Britain', 'Greece', 'Greenland', 'Grenada', 'Guadeloupe', 'Guam', 'Guatemala', 'Guinea', 'Guinea-Bissau', 'Guyana', 'Haiti', 'Holy See', 'Honduras', 'Hong Kong', 'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran', 'Iraq', 'Ireland', 'Israel', 'Italy', 'Jamaica', 'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kiribati', 'North Korea', 'South Korea', 'Kosovo', 'Kuwait', 'Kyrgyzstan', 'Lao, People\'s Democratic Republic', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia', 'Libya', 'Liechtenstein', 'Lithuania', 'Luxembourg', 'Macau', 'Macedonia, Rep. of', 'Madagascar', 'Malawi', 'Malaysia', 'Maldives', 'Mali', 'Malta', 'Marshall Islands', 'Martinique', 'Mauritania', 'Mauritius', 'Mayotte', 'Mexico', 'Micronesia, Federal States of', 'Moldova, Republic of', 'Monaco', 'Mongolia', 'Montenegro', 'Montserrat', 'Morocco', 'Mozambique', 'Myanmar, Burma', 'Namibia', 'Nauru', 'Nepal', 'Netherlands', 'Netherlands Antilles', 'New Caledonia', 'New Zealand', 'Nicaragua', 'Niger', 'Nigeria', 'Niue', 'Northern Mariana Islands', 'Norway', 'Oman', 'Pakistan', 'Palau', 'Palestinian territories', 'Panama', 'Papua New Guinea', 'Paraguay', 'Peru', 'Philippines', 'Pitcairn Island', 'Poland', 'Portugal', 'Puerto Rico', 'Qatar', 'Reunion Island', 'Romania', 'Russian Federation', 'Rwanda', 'Saint Kitts and Nevis', 'Saint Lucia', 'Saint Vincent and the Grenadines', 'Samoa', 'San Marino', 'Sao Tome and Principe', 'Saudi Arabia', 'Senegal', 'Serbia', 'Seychelles', 'Sierra Leone', 'Singapore', 'Slovakia', 'Slovenia', 'Solomon Islands', 'Somalia', 'South Africa', 'South Sudan', 'Spain', 'Sri Lanka', 'Sudan', 'Suriname', 'Swaziland', 'Sweden', 'Switzerland', 'Syria, Syrian Arab Republic', 'Taiwan', 'Tajikistan', 'Tanzania; officially the United Republic of Tanzania', 'Thailand', 'Tibet', 'Timor-Leste', 'Togo', 'Tokelau', 'Tonga', 'Trinidad and Tobago', 'Tunisia', 'Turkey', 'Turkmenistan', 'Turks and Caicos Islands', 'Tuvalu', 'Uganda', 'Ukraine', 'United Arab Emirates', 'United Kingdom', 'USA', 'Uruguay', 'Uzbekistan', 'Vanuatu', 'Vatican City State', 'Venezuela', 'Vietnam', 'Virgin Islands (British)', 'Virgin Islands (U.S.)', 'Wallis and Futuna Islands', 'Western Sahara', 'Yemen', 'Zambia', 'Zimbabwe'] + +JobProfileTreemaView.commonCities = commonCities = ['Tokyo', 'Jakarta', 'Seoul', 'Delhi', 'Shanghai', 'Manila', 'Karachi', 'New York', 'Sao Paulo', 'Mexico City', 'Cairo', 'Beijing', 'Osaka', 'Mumbai (Bombay)', 'Guangzhou', 'Moscow', 'Los Angeles', 'Calcutta', 'Dhaka', 'Buenos Aires', 'Istanbul', 'Rio de Janeiro', 'Shenzhen', 'Lagos', 'Paris', 'Nagoya', 'Lima', 'Chicago', 'Kinshasa', 'Tianjin', 'Chennai', 'Bogota', 'Bengaluru', 'London', 'Taipei', 'Ho Chi Minh City (Saigon)', 'Dongguan', 'Hyderabad', 'Chengdu', 'Lahore', 'Johannesburg', 'Tehran', 'Essen', 'Bangkok', 'Hong Kong', 'Wuhan', 'Ahmedabad', 'Chongqung', 'Baghdad', 'Hangzhou', 'Toronto', 'Kuala Lumpur', 'Santiago', 'Dallas-Fort Worth', 'Quanzhou', 'Miami', 'Shenyang', 'Belo Horizonte', 'Philadelphia', 'Nanjing', 'Madrid', 'Houston', 'Xi\'an-Xianyang', 'Milan', 'Luanda', 'Pune', 'Singapore', 'Riyadh', 'Khartoum', 'Saint Petersburg', 'Atlanta', 'Surat', 'Washington', 'Bandung', 'Surabaya', 'Yangoon', 'Alexandria', 'Guadalajara', 'Harbin', 'Boston', 'Zhengzhou', 'Qingdao', 'Abidjan', 'Barcelona', 'Monterrey', 'Ankara', 'Suzhou', 'Phoenix-Mesa', 'Salvador', 'Porto Alegre', 'Rome', 'Accra', 'Sydney', 'Recife', 'Naples', 'Detroit', 'Dalian', 'Fuzhou', 'Medellin', 'San Francisco', 'Silicon Valley', 'Portland', 'Seattle', 'Austin', 'Denver', 'Boulder'] + +autoFocus = true # Not working right now, possibly a Treema bower thing. + +class SkillTagNode extends TreemaNode.nodeMap.string + buildValueForEditing: (valEl) -> + super(valEl) + valEl.find('input').autocomplete(source: commonSkills, minLength: 1, delay: 0, autoFocus: autoFocus) + valEl + +class LinkNameNode extends TreemaNode.nodeMap.string + buildValueForEditing: (valEl) -> + super(valEl) + valEl.find('input').autocomplete(source: commonLinkNames, minLength: 0, delay: 0, autoFocus: autoFocus) + valEl + +class CityNode extends TreemaNode.nodeMap.string + buildValueForEditing: (valEl) -> + super(valEl) + valEl.find('input').autocomplete(source: commonCities, minLength: 1, delay: 0, autoFocus: autoFocus) + valEl + +class CountryNode extends TreemaNode.nodeMap.string + buildValueForEditing: (valEl) -> + super(valEl) + valEl.find('input').autocomplete(source: commonCountries, minLength: 1, delay: 0, autoFocus: autoFocus) + valEl diff --git a/app/views/account/profile_view.coffee b/app/views/account/JobProfileView.coffee similarity index 97% rename from app/views/account/profile_view.coffee rename to app/views/account/JobProfileView.coffee index 9a36039da..6b2ed8bfd 100644 --- a/app/views/account/profile_view.coffee +++ b/app/views/account/JobProfileView.coffee @@ -4,11 +4,11 @@ User = require 'models/User' LevelSession = require 'models/LevelSession' CocoCollection = require 'collections/CocoCollection' {me} = require 'lib/auth' -JobProfileContactView = require 'views/modal/job_profile_contact_modal' -JobProfileView = require 'views/account/job_profile_view' +JobProfileContactModal = require 'views/modal/JobProfileContactModal' +JobProfileTreemaView = require 'views/account/JobProfileTreemaView' UserRemark = require 'models/UserRemark' forms = require 'lib/forms' -ModelModal = require 'views/modal/model_modal' +ModelModal = require 'views/modal/ModelModal' JobProfileCodeModal = require './JobProfileCodeModal' class LevelSessionsCollection extends CocoCollection @@ -26,7 +26,7 @@ adminContacts = [ {id: '52a57252a89409700d0000d9', name: 'Ignore'} ] -module.exports = class ProfileView extends RootView +module.exports = class JobProfileView extends RootView id: 'profile-view' template: template showBackground: false @@ -317,7 +317,7 @@ module.exports = class ProfileView extends RootView initializeAutocomplete: (container) -> (container ? @$el).find('input[data-autocomplete]').each -> - $(@).autocomplete(source: JobProfileView[$(@).data('autocomplete')], minLength: parseInt($(@).data('autocomplete-min-length')), delay: 0, autoFocus: true) + $(@).autocomplete(source: JobProfileTreemaView[$(@).data('autocomplete')], minLength: parseInt($(@).data('autocomplete-min-length')), delay: 0, autoFocus: true) toggleEditing: -> @editing = not @editing @@ -374,7 +374,7 @@ module.exports = class ProfileView extends RootView null onContactCandidate: (e) -> - @openModalView new JobProfileContactView recipientID: @user.id, recipientUserName: @user.get('name') + @openModalView new JobProfileContactModal recipientID: @user.id, recipientUserName: @user.get('name') showErrors: (errors) -> section = @$el.find '.saving' diff --git a/app/views/account/unsubscribe_view.coffee b/app/views/account/UnsubscribeView.coffee similarity index 100% rename from app/views/account/unsubscribe_view.coffee rename to app/views/account/UnsubscribeView.coffee diff --git a/app/views/account/wizard_settings_view.coffee b/app/views/account/WizardSettingsView.coffee similarity index 100% rename from app/views/account/wizard_settings_view.coffee rename to app/views/account/WizardSettingsView.coffee diff --git a/app/views/account/job_profile_view.coffee b/app/views/account/job_profile_view.coffee deleted file mode 100644 index bd4472d23..000000000 --- a/app/views/account/job_profile_view.coffee +++ /dev/null @@ -1,131 +0,0 @@ -CocoView = require 'views/kinds/CocoView' -template = require 'templates/account/job_profile' -{me} = require 'lib/auth' - -module.exports = class JobProfileView extends CocoView - id: 'job-profile-view' - template: template - - editableSettings: [ - 'lookingFor', 'active', 'name', 'city', 'country', 'skills', 'experience', 'shortDescription', 'longDescription', - 'work', 'education', 'visa', 'projects', 'links', 'jobTitle', 'photoURL' - ] - readOnlySettings: [] #['updated'] - - afterRender: -> - super() - return unless @supermodel.finished() - _.defer => @buildJobProfileTreema() # Not sure why, but the Treemas don't fully build without this if you reload the page. - - buildJobProfileTreema: -> - visibleSettings = @editableSettings.concat @readOnlySettings - data = _.pick (me.get('jobProfile') ? {}), (value, key) -> key in visibleSettings - data.name ?= (me.get('firstName') + ' ' + me.get('lastName')).trim() if me.get('firstName') - schema = _.cloneDeep me.schema().properties.jobProfile - schema.properties = _.pick schema.properties, (value, key) -> key in visibleSettings - schema.required = _.intersection schema.required, visibleSettings - for prop in @readOnlySettings - schema.properties[prop].readOnly = true - treemaOptions = - filePath: "db/user/#{me.id}" - schema: schema - data: data - aceUseWrapMode: true - callbacks: {change: @onJobProfileChanged} - nodeClasses: - 'skill': SkillTagNode - 'link-name': LinkNameNode - 'city': CityNode - 'country': CountryNode - - @jobProfileTreema = @$el.find('#job-profile-treema').treema treemaOptions - @jobProfileTreema.build() - @jobProfileTreema.open() - @updateProgress() - - onJobProfileChanged: (e) => - @hasEditedProfile = true - @trigger 'change' - @updateProgress() - - updateProgress: -> - completed = 0 - totalWeight = 0 - next = null - for metric in metrics = @getProgressMetrics() - done = metric.fn() - completed += metric.weight if done - totalWeight += metric.weight - next = metric.name unless next or done - progress = Math.round 100 * completed / totalWeight - bar = @$el.find('.profile-completion-progress .progress-bar') - bar.css 'width', "#{progress}%" - text = '' - if progress > 19 - text = "#{progress}% complete" - else if progress > 5 - text = "#{progress}%" - bar.text text - bar.parent().toggle Boolean progress - @$el.find('.progress-next-item').text(next).toggle Boolean next - - getProgressMetrics: -> - return @progressMetrics if @progressMetrics - schema = me.schema().properties.jobProfile - jobProfile = @jobProfileTreema.data - exists = (field) -> -> jobProfile[field] - modified = (field) -> -> jobProfile[field] and jobProfile[field] isnt schema.properties[field].default - listStarted = (field, subfields) -> -> jobProfile[field]?.length and _.every subfields, (subfield) -> jobProfile[field][0][subfield] - @progressMetrics = [ - {name: 'Mark yourself open to offers to show up in searches.', weight: 1, fn: modified 'active'} - {name: 'Specify your desired job title.', weight: 0, fn: exists 'jobTitle'} - {name: 'Provide your name.', weight: 1, fn: modified 'name'} - {name: 'Choose your city.', weight: 1, fn: modified 'city'} - {name: 'Pick your country.', weight: 0, fn: exists 'country'} - {name: 'List at least five skills.', weight: 2, fn: -> jobProfile.skills.length >= 5} - {name: 'Write a short description to summarize yourself at a glance.', weight: 2, fn: modified 'shortDescription'} - {name: 'Fill in your main description to sell yourself and describe the work you\'re looking for.', weight: 3, fn: modified 'longDescription'} - {name: 'List your work experience.', weight: 3, fn: listStarted 'work', ['role', 'employer']} - {name: 'Recount your educational ordeals.', weight: 3, fn: listStarted 'education', ['degree', 'school']} - {name: 'Show off up to three projects you\'ve worked on.', weight: 3, fn: listStarted 'projects', ['name']} - {name: 'Add any personal or social links.', weight: 2, fn: listStarted 'links', ['link', 'name']} - {name: 'Add an optional professional photo.', weight: 2, fn: modified 'photoURL'} - ] - - getData: -> - return {} unless me.get('jobProfile') or @hasEditedProfile - _.pick @jobProfileTreema.data, (value, key) => key in @editableSettings - -JobProfileView.commonSkills = commonSkills = ['c#', 'java', 'javascript', 'php', 'android', 'jquery', 'python', 'c++', 'html', 'mysql', 'ios', 'asp.net', 'css', 'sql', 'iphone', '.net', 'objective-c', 'ruby-on-rails', 'c', 'ruby', 'sql-server', 'ajax', 'wpf', 'linux', 'database', 'django', 'vb.net', 'windows', 'facebook', 'r', 'html5', 'multithreading', 'ruby-on-rails-3', 'wordpress', 'winforms', 'node.js', 'spring', 'osx', 'performance', 'visual-studio-2010', 'oracle', 'swing', 'algorithm', 'git', 'linq', 'apache', 'web-services', 'perl', 'wcf', 'entity-framework', 'bash', 'visual-studio', 'sql-server-2008', 'hibernate', 'actionscript-3', 'angularjs', 'matlab', 'qt', 'ipad', 'sqlite', 'cocoa-touch', 'cocoa', 'flash', 'mongodb', 'codeigniter', 'jquery-ui', 'css3', 'tsql', 'google-maps', 'silverlight', 'security', 'delphi', 'vba', 'postgresql', 'jsp', 'shell', 'internet-explorer', 'google-app-engine', 'sockets', 'validation', 'scala', 'oop', 'unit-testing', 'xaml', 'parsing', 'twitter-bootstrap', 'google-chrome', 'http', 'magento', 'email', 'android-layout', 'flex', 'rest', 'maven', 'jsf', 'listview', 'date', 'winapi', 'windows-phone-7', 'facebook-graph-api', 'unix', 'url', 'c#-4.0', 'jquery-ajax', 'svn', 'symfony2', 'table', 'cakephp', 'firefox', 'ms-access', 'java-ee', 'jquery-mobile', 'python-2.7', 'tomcat', 'zend-framework', 'opencv', 'visual-c++', 'opengl', 'spring-mvc', 'sql-server-2005', 'authentication', 'search', 'xslt', 'servlets', 'pdf', 'animation', 'math', 'batch-file', 'excel-vba', 'iis', 'mod-rewrite', 'sharepoint', 'gwt', 'powershell', 'visual-studio-2012', 'haskell', 'grails', 'ubuntu', 'networking', 'nhibernate', 'design-patterns', 'testing', 'jpa', 'visual-studio-2008', 'core-data', 'user-interface', 'audio', 'backbone.js', 'gcc', 'mobile', 'design', 'activerecord', 'extjs', 'video', 'stored-procedures', 'optimization', 'drupal', 'image-processing', 'android-intent', 'logging', 'web-applications', 'razor', 'database-design', 'azure', 'vim', 'memory-management', 'model-view-controller', 'cordova', 'c++11', 'selenium', 'ssl', 'assembly', 'soap', 'boost', 'canvas', 'google-maps-api-3', 'netbeans', 'heroku', 'jsf-2', 'encryption', 'hadoop', 'linq-to-sql', 'dll', 'xpath', 'data-binding', 'windows-phone-8', 'phonegap', 'jdbc', 'python-3.x', 'twitter', 'mvvm', 'gui', 'web', 'jquery-plugins', 'numpy', 'deployment', 'ios7', 'emacs', 'knockout.js', 'graphics', 'joomla', 'unicode', 'windows-8', 'android-fragments', 'ant', 'command-line', 'version-control', 'yii', 'github', 'amazon-web-services', 'macros', 'ember.js', 'svg', 'opengl-es', 'django-models', 'solr', 'orm', 'blackberry', 'windows-7', 'ruby-on-rails-4', 'compiler', 'tcp', 'pdo', 'architecture', 'groovy', 'nginx', 'concurrency', 'paypal', 'iis-7', 'express', 'vbscript', 'google-chrome-extension', 'memory-leaks', 'rspec', 'actionscript', 'interface', 'fonts', 'oauth', 'ssh', 'tfs', 'junit', 'struts2', 'd3.js', 'coldfusion', '.net-4.0', 'jqgrid', 'asp-classic', 'https', 'plsql', 'stl', 'sharepoint-2010', 'asp.net-web-api', 'mysqli', 'sed', 'awk', 'internet-explorer-8', 'jboss', 'charts', 'scripting', 'matplotlib', 'laravel', 'clojure', 'entity-framework-4', 'intellij-idea', 'xml-parsing', 'sqlite3', '3d', 'io', 'mfc', 'devise', 'playframework', 'youtube', 'amazon-ec2', 'localization', 'cuda', 'jenkins', 'ssis', 'safari', 'doctrine2', 'vb6', 'amazon-s3', 'dojo', 'air', 'eclipse-plugin', 'android-asynctask', 'crystal-reports', 'cocos2d-iphone', 'dns', 'highcharts', 'ruby-on-rails-3.2', 'ado.net', 'sql-server-2008-r2', 'android-emulator', 'spring-security', 'cross-browser', 'oracle11g', 'bluetooth', 'f#', 'msbuild', 'drupal-7', 'google-apps-script', 'mercurial', 'xna', 'google-analytics', 'lua', 'parallel-processing', 'internationalization', 'java-me', 'mono', 'monotouch', 'android-ndk', 'lucene', 'kendo-ui', 'linux-kernel', 'terminal', 'phpmyadmin', 'makefile', 'ffmpeg', 'applet', 'active-directory', 'coffeescript', 'pandas', 'responsive-design', 'xhtml', 'silverlight-4.0', '.net-3.5', 'jaxb', 'ruby-on-rails-3.1', 'gps', 'geolocation', 'network-programming', 'windows-services', 'laravel-4', 'ggplot2', 'rss', 'webkit', 'functional-programming', 'wsdl', 'telerik', 'maven-2', 'cron', 'mapreduce', 'websocket', 'automation', 'windows-runtime', 'django-forms', 'tkinter', 'android-widget', 'android-activity', 'rubygems', 'content-management-system', 'doctrine', 'django-templates', 'gem', 'fluent-nhibernate', 'seo', 'meteor', 'serial-port', 'glassfish', 'documentation', 'cryptography', 'ef-code-first', 'extjs4', 'x86', 'wordpress-plugin', 'go', 'wix', 'linq-to-entities', 'oracle10g', 'cocos2d', 'selenium-webdriver', 'open-source', 'jtable', 'qt4', 'smtp', 'redis', 'jvm', 'openssl', 'timezone', 'nosql', 'erlang', 'playframework-2.0', 'machine-learning', 'mocking', 'unity3d', 'thread-safety', 'android-actionbar', 'jni', 'udp', 'jasper-reports', 'zend-framework2', 'apache2', 'internet-explorer-7', 'sqlalchemy', 'neo4j', 'ldap', 'jframe', 'youtube-api', 'filesystems', 'make', 'flask', 'gdb', 'cassandra', 'sms', 'g++', 'django-admin', 'push-notification', 'statistics', 'tinymce', 'locking', 'javafx', 'firefox-addon', 'fancybox', 'windows-phone', 'log4j', 'uikit', 'prolog', 'socket.io', 'icons', 'oauth-2.0', 'refactoring', 'sencha-touch', 'elasticsearch', 'symfony1', 'google-api', 'webserver', 'wpf-controls', 'microsoft-metro', 'gtk', 'flex4', 'three.js', 'gradle', 'centos', 'angularjs-directive', 'internet-explorer-9', 'sass', 'html5-canvas', 'interface-builder', 'programming-languages', 'gmail', 'jersey', 'twitter-bootstrap-3', 'arduino', 'requirejs', 'cmake', 'web-development', 'software-engineering', 'startups', 'entrepreneurship', 'social-media-marketing', 'writing', 'marketing', 'web-design', 'graphic-design', 'game-development', 'game-design', 'photoshop', 'illustrator', 'robotics', 'aws', 'devops', 'mathematica', 'bioinformatics', 'data-vis', 'ui', 'embedded-systems', 'codecombat'] - -JobProfileView.commonLinkNames = commonLinkNames = ['GitHub', 'Facebook', 'Twitter', 'G+', 'LinkedIn', 'Personal Website', 'Blog'] - -JobProfileView.commonCountries = commonCountries = ['Afghanistan', 'Albania', 'Algeria', 'American Samoa', 'Andorra', 'Angola', 'Anguilla', 'Antarctica', 'Antigua and Barbuda', 'Argentina', 'Armenia', 'Aruba', 'Australia', 'Austria', 'Azerbaijan', 'Bahamas', 'Bahrain', 'Bangladesh', 'Barbados', 'Belarus', 'Belgium', 'Belize', 'Benin', 'Bermuda', 'Bhutan', 'Bolivia', 'Bosnia and Herzegovina', 'Botswana', 'Brazil', 'Brunei Darussalam', 'Bulgaria', 'Burkina Faso', 'Burundi', 'Cambodia', 'Cameroon', 'Canada', 'Cape Verde', 'Cayman Islands', 'Central African Republic', 'Chad', 'Chile', 'China', 'Christmas Island', 'Cocos (Keeling) Islands', 'Colombia', 'Comoros', 'Democratic Republic of the Congo (Kinshasa)', 'Congo, Republic of (Brazzaville)', 'Cook Islands', 'Costa Rica', 'Ivory Coast', 'Croatia', 'Cuba', 'Cyprus', 'Czech Republic', 'Denmark', 'Djibouti', 'Dominica', 'Dominican Republic', 'East Timor', 'Ecuador', 'Egypt', 'El Salvador', 'Equatorial Guinea', 'Eritrea', 'Estonia', 'Ethiopia', 'Falkland Islands', 'Faroe Islands', 'Fiji', 'Finland', 'France', 'French Guiana', 'French Polynesia', 'French Southern Territories', 'Gabon', 'Gambia', 'Georgia', 'Germany', 'Ghana', 'Gibraltar', 'Great Britain', 'Greece', 'Greenland', 'Grenada', 'Guadeloupe', 'Guam', 'Guatemala', 'Guinea', 'Guinea-Bissau', 'Guyana', 'Haiti', 'Holy See', 'Honduras', 'Hong Kong', 'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran', 'Iraq', 'Ireland', 'Israel', 'Italy', 'Jamaica', 'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kiribati', 'North Korea', 'South Korea', 'Kosovo', 'Kuwait', 'Kyrgyzstan', 'Lao, People\'s Democratic Republic', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia', 'Libya', 'Liechtenstein', 'Lithuania', 'Luxembourg', 'Macau', 'Macedonia, Rep. of', 'Madagascar', 'Malawi', 'Malaysia', 'Maldives', 'Mali', 'Malta', 'Marshall Islands', 'Martinique', 'Mauritania', 'Mauritius', 'Mayotte', 'Mexico', 'Micronesia, Federal States of', 'Moldova, Republic of', 'Monaco', 'Mongolia', 'Montenegro', 'Montserrat', 'Morocco', 'Mozambique', 'Myanmar, Burma', 'Namibia', 'Nauru', 'Nepal', 'Netherlands', 'Netherlands Antilles', 'New Caledonia', 'New Zealand', 'Nicaragua', 'Niger', 'Nigeria', 'Niue', 'Northern Mariana Islands', 'Norway', 'Oman', 'Pakistan', 'Palau', 'Palestinian territories', 'Panama', 'Papua New Guinea', 'Paraguay', 'Peru', 'Philippines', 'Pitcairn Island', 'Poland', 'Portugal', 'Puerto Rico', 'Qatar', 'Reunion Island', 'Romania', 'Russian Federation', 'Rwanda', 'Saint Kitts and Nevis', 'Saint Lucia', 'Saint Vincent and the Grenadines', 'Samoa', 'San Marino', 'Sao Tome and Principe', 'Saudi Arabia', 'Senegal', 'Serbia', 'Seychelles', 'Sierra Leone', 'Singapore', 'Slovakia', 'Slovenia', 'Solomon Islands', 'Somalia', 'South Africa', 'South Sudan', 'Spain', 'Sri Lanka', 'Sudan', 'Suriname', 'Swaziland', 'Sweden', 'Switzerland', 'Syria, Syrian Arab Republic', 'Taiwan', 'Tajikistan', 'Tanzania; officially the United Republic of Tanzania', 'Thailand', 'Tibet', 'Timor-Leste', 'Togo', 'Tokelau', 'Tonga', 'Trinidad and Tobago', 'Tunisia', 'Turkey', 'Turkmenistan', 'Turks and Caicos Islands', 'Tuvalu', 'Uganda', 'Ukraine', 'United Arab Emirates', 'United Kingdom', 'USA', 'Uruguay', 'Uzbekistan', 'Vanuatu', 'Vatican City State', 'Venezuela', 'Vietnam', 'Virgin Islands (British)', 'Virgin Islands (U.S.)', 'Wallis and Futuna Islands', 'Western Sahara', 'Yemen', 'Zambia', 'Zimbabwe'] - -JobProfileView.commonCities = commonCities = ['Tokyo', 'Jakarta', 'Seoul', 'Delhi', 'Shanghai', 'Manila', 'Karachi', 'New York', 'Sao Paulo', 'Mexico City', 'Cairo', 'Beijing', 'Osaka', 'Mumbai (Bombay)', 'Guangzhou', 'Moscow', 'Los Angeles', 'Calcutta', 'Dhaka', 'Buenos Aires', 'Istanbul', 'Rio de Janeiro', 'Shenzhen', 'Lagos', 'Paris', 'Nagoya', 'Lima', 'Chicago', 'Kinshasa', 'Tianjin', 'Chennai', 'Bogota', 'Bengaluru', 'London', 'Taipei', 'Ho Chi Minh City (Saigon)', 'Dongguan', 'Hyderabad', 'Chengdu', 'Lahore', 'Johannesburg', 'Tehran', 'Essen', 'Bangkok', 'Hong Kong', 'Wuhan', 'Ahmedabad', 'Chongqung', 'Baghdad', 'Hangzhou', 'Toronto', 'Kuala Lumpur', 'Santiago', 'Dallas-Fort Worth', 'Quanzhou', 'Miami', 'Shenyang', 'Belo Horizonte', 'Philadelphia', 'Nanjing', 'Madrid', 'Houston', 'Xi\'an-Xianyang', 'Milan', 'Luanda', 'Pune', 'Singapore', 'Riyadh', 'Khartoum', 'Saint Petersburg', 'Atlanta', 'Surat', 'Washington', 'Bandung', 'Surabaya', 'Yangoon', 'Alexandria', 'Guadalajara', 'Harbin', 'Boston', 'Zhengzhou', 'Qingdao', 'Abidjan', 'Barcelona', 'Monterrey', 'Ankara', 'Suzhou', 'Phoenix-Mesa', 'Salvador', 'Porto Alegre', 'Rome', 'Accra', 'Sydney', 'Recife', 'Naples', 'Detroit', 'Dalian', 'Fuzhou', 'Medellin', 'San Francisco', 'Silicon Valley', 'Portland', 'Seattle', 'Austin', 'Denver', 'Boulder'] - -autoFocus = true # Not working right now, possibly a Treema bower thing. - -class SkillTagNode extends TreemaNode.nodeMap.string - buildValueForEditing: (valEl) -> - super(valEl) - valEl.find('input').autocomplete(source: commonSkills, minLength: 1, delay: 0, autoFocus: autoFocus) - valEl - -class LinkNameNode extends TreemaNode.nodeMap.string - buildValueForEditing: (valEl) -> - super(valEl) - valEl.find('input').autocomplete(source: commonLinkNames, minLength: 0, delay: 0, autoFocus: autoFocus) - valEl - -class CityNode extends TreemaNode.nodeMap.string - buildValueForEditing: (valEl) -> - super(valEl) - valEl.find('input').autocomplete(source: commonCities, minLength: 1, delay: 0, autoFocus: autoFocus) - valEl - -class CountryNode extends TreemaNode.nodeMap.string - buildValueForEditing: (valEl) -> - super(valEl) - valEl.find('input').autocomplete(source: commonCountries, minLength: 1, delay: 0, autoFocus: autoFocus) - valEl diff --git a/app/views/admin/clas_view.coffee b/app/views/admin/CLAsView.coffee similarity index 100% rename from app/views/admin/clas_view.coffee rename to app/views/admin/CLAsView.coffee diff --git a/app/views/admin/candidates_view.coffee b/app/views/admin/CandidatesView.coffee similarity index 96% rename from app/views/admin/candidates_view.coffee rename to app/views/admin/CandidatesView.coffee index c91f16efd..7d8d89038 100644 --- a/app/views/admin/candidates_view.coffee +++ b/app/views/admin/CandidatesView.coffee @@ -1,11 +1,10 @@ RootView = require 'views/kinds/RootView' template = require 'templates/admin/candidates' -app = require 'application' User = require 'models/User' UserRemark = require 'models/UserRemark' {me} = require 'lib/auth' CocoCollection = require 'collections/CocoCollection' -EmployerSignupView = require 'views/modal/employer_signup_modal' +EmployerSignupModal = require 'views/modal/EmployerSignupModal' class CandidatesCollection extends CocoCollection url: '/db/user/x/candidates' @@ -15,7 +14,7 @@ class UserRemarksCollection extends CocoCollection url: '/db/user.remark?project=contact,contactName,user' model: UserRemark -module.exports = class EmployersView extends RootView +module.exports = class CandidatesView extends RootView id: "admin-candidates-view" template: template @@ -71,7 +70,7 @@ module.exports = class EmployersView extends RootView checkForEmployerSignupHash: => if window.location.hash is "#employerSignupLoggingIn" and not ("employer" in me.get("permissions")) - @openModalView application.router.getView("modal/employer_signup","_modal") + @openModalView new EmployerSignupModal window.location.hash = "" sortTable: -> @@ -204,4 +203,4 @@ module.exports = class EmployersView extends RootView url = "/account/profile/#{id}" window.open url,"_blank" else - @openModalView new EmployerSignupView \ No newline at end of file + @openModalView new EmployerSignupModal \ No newline at end of file diff --git a/app/views/admin/employer_list_view.coffee b/app/views/admin/EmployersListView.coffee similarity index 97% rename from app/views/admin/employer_list_view.coffee rename to app/views/admin/EmployersListView.coffee index 32c08cd22..a5fcb7a45 100644 --- a/app/views/admin/employer_list_view.coffee +++ b/app/views/admin/EmployersListView.coffee @@ -1,16 +1,15 @@ RootView = require 'views/kinds/RootView' template = require 'templates/admin/employer_list' -app = require 'application' User = require 'models/User' {me} = require 'lib/auth' CocoCollection = require 'collections/CocoCollection' -ModelModal = require 'views/modal/model_modal' +ModelModal = require 'views/modal/ModelModal' class EmployersCollection extends CocoCollection url: '/db/user/x/employers' model: User -module.exports = class EmployersView extends RootView +module.exports = class EmployersListView extends RootView id: 'employers-view' template: template diff --git a/app/views/admin/files_view.coffee b/app/views/admin/FilesView.coffee similarity index 100% rename from app/views/admin/files_view.coffee rename to app/views/admin/FilesView.coffee diff --git a/app/views/admin/level_sessions_view.coffee b/app/views/admin/LevelSessionsView.coffee similarity index 100% rename from app/views/admin/level_sessions_view.coffee rename to app/views/admin/LevelSessionsView.coffee diff --git a/app/views/AdminView.coffee b/app/views/admin/MainAdminView.coffee similarity index 94% rename from app/views/AdminView.coffee rename to app/views/admin/MainAdminView.coffee index 5c23d2ab1..33bed066e 100644 --- a/app/views/AdminView.coffee +++ b/app/views/admin/MainAdminView.coffee @@ -2,7 +2,7 @@ RootView = require 'views/kinds/RootView' template = require 'templates/admin' -module.exports = class AdminView extends RootView +module.exports = class MainAdminView extends RootView id: 'admin-view' template: template diff --git a/app/views/admin/users_view.coffee b/app/views/admin/UsersView.coffee similarity index 100% rename from app/views/admin/users_view.coffee rename to app/views/admin/UsersView.coffee diff --git a/app/views/admin/base_view.coffee b/app/views/admin/base_view.coffee deleted file mode 100644 index ca58690c0..000000000 --- a/app/views/admin/base_view.coffee +++ /dev/null @@ -1,6 +0,0 @@ -RootView = require 'views/kinds/RootView' -template = require 'templates/base' - -module.exports = class BaseView extends RootView - id: 'base-view' - template: template diff --git a/app/views/contribute/ContributeClassView.coffee b/app/views/contribute/ContributeClassView.coffee index 7b403d466..178e95d00 100644 --- a/app/views/contribute/ContributeClassView.coffee +++ b/app/views/contribute/ContributeClassView.coffee @@ -1,4 +1,4 @@ -SignupModalView = require 'views/modal/signup_modal' +SignupModalView = require 'views/modal/SignupModal' RootView = require 'views/kinds/RootView' {me} = require 'lib/auth' contributorSignupAnonymousTemplate = require 'templates/contribute/contributor_signup_anonymous' diff --git a/app/views/docs/components_view.coffee b/app/views/docs/ComponentDocumentationView.coffee similarity index 87% rename from app/views/docs/components_view.coffee rename to app/views/docs/ComponentDocumentationView.coffee index eedba904e..b20385618 100644 --- a/app/views/docs/components_view.coffee +++ b/app/views/docs/ComponentDocumentationView.coffee @@ -1,4 +1,5 @@ -RootView = require 'views/kinds/RootView' +#RootView = require 'views/kinds/RootView' +CocoView = require 'views/kinds/CocoView' template = require 'templates/docs/components' CocoCollection = require 'collections/CocoCollection' LevelComponent = require 'models/LevelComponent' @@ -7,15 +8,16 @@ class ComponentDocsCollection extends CocoCollection url: '/db/level.component?project=name,description,dependencies,propertyDocumentation,code' model: LevelComponent -module.exports = class UnnamedView extends RootView +module.exports = class ComponentDocumentationView extends CocoView id: 'docs-components-view' template: template + className: 'tab-pane' constructor: (options) -> super(options) @componentDocs = new ComponentDocsCollection() @supermodel.loadCollection @componentDocs, 'components' - + onLoaded: -> console.log 'we have the components...', (c.get('name') for c in @componentDocs.models) console.log 'we have the attributes...', (c.attributes for c in @componentDocs.models) @@ -35,4 +37,4 @@ module.exports = class UnnamedView extends RootView c.language = 'javascript' else c.language = me.get('aceConfig').language - c + c \ No newline at end of file diff --git a/app/views/editor/delta.coffee b/app/views/editor/DeltaView.coffee similarity index 100% rename from app/views/editor/delta.coffee rename to app/views/editor/DeltaView.coffee diff --git a/app/views/editor/patch_modal.coffee b/app/views/editor/PatchModal.coffee similarity index 98% rename from app/views/editor/patch_modal.coffee rename to app/views/editor/PatchModal.coffee index 6737b9f00..d22dc7ce3 100644 --- a/app/views/editor/patch_modal.coffee +++ b/app/views/editor/PatchModal.coffee @@ -1,6 +1,6 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/editor/patch_modal' -DeltaView = require 'views/editor/delta' +DeltaView = require 'views/editor/DeltaView' auth = require 'lib/auth' module.exports = class PatchModal extends ModalView diff --git a/app/views/editor/patches_view.coffee b/app/views/editor/PatchesView.coffee similarity index 97% rename from app/views/editor/patches_view.coffee rename to app/views/editor/PatchesView.coffee index 751ec837c..6f5f0bdd7 100644 --- a/app/views/editor/patches_view.coffee +++ b/app/views/editor/PatchesView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/patches' PatchesCollection = require 'collections/PatchesCollection' nameLoader = require 'lib/NameLoader' -PatchModal = require './patch_modal' +PatchModal = require './PatchModal' module.exports = class PatchesView extends CocoView template: template diff --git a/app/views/editor/achievement/edit.coffee b/app/views/editor/achievement/AchievementEditView.coffee similarity index 98% rename from app/views/editor/achievement/edit.coffee rename to app/views/editor/achievement/AchievementEditView.coffee index 8f4379777..ce5da02bb 100644 --- a/app/views/editor/achievement/edit.coffee +++ b/app/views/editor/achievement/AchievementEditView.coffee @@ -1,7 +1,7 @@ RootView = require 'views/kinds/RootView' template = require 'templates/editor/achievement/edit' Achievement = require 'models/Achievement' -ConfirmModal = require 'views/modal/confirm' +ConfirmModal = require 'views/modal/ConfirmModal' module.exports = class AchievementEditView extends RootView id: 'editor-achievement-edit-view' diff --git a/app/views/editor/achievement/home.coffee b/app/views/editor/achievement/AchievementSearchView.coffee similarity index 100% rename from app/views/editor/achievement/home.coffee rename to app/views/editor/achievement/AchievementSearchView.coffee diff --git a/app/views/editor/article/edit.coffee b/app/views/editor/article/ArticleEditView.coffee similarity index 92% rename from app/views/editor/article/edit.coffee rename to app/views/editor/article/ArticleEditView.coffee index 70450103f..96d4facc7 100644 --- a/app/views/editor/article/edit.coffee +++ b/app/views/editor/article/ArticleEditView.coffee @@ -1,9 +1,9 @@ RootView = require 'views/kinds/RootView' -VersionHistoryView = require './versions_view' +VersionHistoryView = require './ArticleVersionsModal' template = require 'templates/editor/article/edit' Article = require 'models/Article' -SaveVersionModal = require 'views/modal/save_version_modal' -PatchesView = require 'views/editor/patches_view' +SaveVersionModal = require 'views/modal/SaveVersionModal' +PatchesView = require 'views/editor/PatchesView' module.exports = class ArticleEditView extends RootView id: 'editor-article-edit-view' @@ -79,7 +79,7 @@ module.exports = class ArticleEditView extends RootView @patchesView.load() openPreview: -> - @preview = window.open('/editor/article/x/preview', 'preview', 'height=800,width=600') + @preview = window.open('/editor/article/preview', 'preview', 'height=800,width=600') @preview.focus() if window.focus @preview.onload = => @pushChangesToPreview() return false diff --git a/app/views/editor/article/preview.coffee b/app/views/editor/article/ArticlePreviewView.coffee similarity index 72% rename from app/views/editor/article/preview.coffee rename to app/views/editor/article/ArticlePreviewView.coffee index 9426454bf..5b335fb2d 100644 --- a/app/views/editor/article/preview.coffee +++ b/app/views/editor/article/ArticlePreviewView.coffee @@ -1,6 +1,6 @@ RootView = require 'views/kinds/RootView' template = require 'templates/editor/article/preview' -module.exports = class PreviewView extends RootView +module.exports = class ArticlePreviewView extends RootView id: 'editor-article-preview-view' template: template diff --git a/app/views/editor/article/home.coffee b/app/views/editor/article/ArticleSearchView.coffee similarity index 89% rename from app/views/editor/article/home.coffee rename to app/views/editor/article/ArticleSearchView.coffee index 4f8fdab05..b80423011 100644 --- a/app/views/editor/article/home.coffee +++ b/app/views/editor/article/ArticleSearchView.coffee @@ -1,6 +1,6 @@ SearchView = require 'views/kinds/SearchView' -module.exports = class ThangTypeHomeView extends SearchView +module.exports = class ArticleSearchView extends SearchView id: 'editor-article-home-view' modelLabel: 'Article' model: require 'models/Article' diff --git a/app/views/editor/article/versions_view.coffee b/app/views/editor/article/ArticleVersionsModal.coffee similarity index 55% rename from app/views/editor/article/versions_view.coffee rename to app/views/editor/article/ArticleVersionsModal.coffee index 98d9f1c63..10027ad99 100644 --- a/app/views/editor/article/versions_view.coffee +++ b/app/views/editor/article/ArticleVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class ArticleVersionsView extends VersionsModalView +module.exports = class ArticleVersionsModal extends VersionsModal id: 'editor-article-versions-view' url: '/db/article/' page: 'article' diff --git a/app/views/editor/component/versions_view.coffee b/app/views/editor/component/ComponentVersionsModal.coffee similarity index 58% rename from app/views/editor/component/versions_view.coffee rename to app/views/editor/component/ComponentVersionsModal.coffee index 409dc8553..fb027826e 100755 --- a/app/views/editor/component/versions_view.coffee +++ b/app/views/editor/component/ComponentVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class ComponentVersionsView extends VersionsModalView +module.exports = class ComponentVersionsModal extends VersionsModal id: 'editor-component-versions-view' url: '/db/level.component/' page: 'component' diff --git a/app/views/editor/components/config.coffee b/app/views/editor/component/ThangComponentConfigView.coffee similarity index 93% rename from app/views/editor/components/config.coffee rename to app/views/editor/component/ThangComponentConfigView.coffee index 7fb37b3ab..8b544465e 100644 --- a/app/views/editor/components/config.coffee +++ b/app/views/editor/component/ThangComponentConfigView.coffee @@ -5,7 +5,7 @@ Level = require 'models/Level' LevelComponent = require 'models/LevelComponent' nodes = require '../level/treema_nodes' -module.exports = class ComponentConfigView extends CocoView +module.exports = class ThangComponentConfigView extends CocoView id: 'component-config-column-view' template: template className: 'column' @@ -69,4 +69,10 @@ module.exports = class ComponentConfigView extends CocoView @changed = true @callback?(@data()) + undo: -> + @editThangTreema.undo() + + redo: -> + @editThangTreema.redo() + data: -> @editThangTreema.data diff --git a/app/views/editor/components/main.coffee b/app/views/editor/component/ThangComponentEditView.coffee similarity index 81% rename from app/views/editor/components/main.coffee rename to app/views/editor/component/ThangComponentEditView.coffee index 234608a44..46b0e8f99 100644 --- a/app/views/editor/components/main.coffee +++ b/app/views/editor/component/ThangComponentEditView.coffee @@ -5,7 +5,7 @@ Level = require 'models/Level' LevelComponent = require 'models/LevelComponent' LevelSystem = require 'models/LevelSystem' ComponentsCollection = require 'collections/ComponentsCollection' -ComponentConfigView = require './config' +ComponentConfigView = require './ThangComponentConfigView' module.exports = class ThangComponentEditView extends CocoView id: 'thang-components-edit-view' @@ -39,6 +39,10 @@ module.exports = class ThangComponentEditView extends CocoView @extantComponentsTreema = @$el.find('#extant-components-column .treema').treema treemaOptions @extantComponentsTreema.build() + @$el.find('#extant-components-column .treema').droppable({ + drop: => + @onAddComponentEnterPressed @selectedRow + }) buildAddComponentTreema: -> return unless @componentCollection and @extantComponentsTreema @@ -55,7 +59,13 @@ module.exports = class ThangComponentEditView extends CocoView supermodel: @supermodel schema: {type: 'array', items: LevelComponent.schema} data: ($.extend(true, {}, c) for c in components) - callbacks: {select: @onSelectAddableComponent, enter: @onAddComponentEnterPressed} + callbacks: { + select: @onSelectAddableComponent + enter: @onAddComponentEnterPressed + dblclick: @onAddComponentDoubleClicked + mouseenter: @onAddComponentMouseEnter + mouseleave: @onAddComponentMouseLeave + } readOnly: true noSortable: true nodeClasses: @@ -65,6 +75,12 @@ module.exports = class ThangComponentEditView extends CocoView _.defer (=> @addComponentsTreema = @$el.find('#add-component-column .treema').treema treemaOptions @addComponentsTreema.build() + @$el.find('#add-component-column .treema-node').draggable({ + revert: true + start: (e) -> + # Hack to ensure dragged treema node is selected + $(@).trigger('click') unless $(@).hasClass 'treema-selected' + }) @hideLoading() ), 500 @@ -157,8 +173,6 @@ module.exports = class ThangComponentEditView extends CocoView type: 'warning' }) - currentSelection = @addComponentsTreema?.getLastSelectedTreema()?.data._id - id = node.data._id comp = _.find @componentCollection.models, id: id unless comp @@ -174,16 +188,32 @@ module.exports = class ThangComponentEditView extends CocoView majorVersion: c.get('version').major ? 0 } - return unless currentSelection - # reselect what was selected before the addComponentsTreema was rebuilt - for index, treema of @addComponentsTreema.childrenTreemas - if treema.data._id is currentSelection + # reselect newly added child treema in the extantComponentsTreema + for index, treema of @extantComponentsTreema.childrenTreemas + if treema.component.id is id treema.select() + @onSelectExtantComponent({}, [treema]) return + onAddComponentDoubleClicked: (e, treema) => + @onAddComponentEnterPressed treema + + onAddComponentMouseEnter: (e, treema) -> + treema.$el.find('.add-button').show() + + onAddComponentMouseLeave: (e, treema) -> + treema.$el.find('.add-button').hide() + return + reportChanges: -> @callback?($.extend(true, [], @extantComponentsTreema.data)) + undo: -> + if @configView is null or @configView?.editing is false then @extantComponentsTreema.undo() else @configView.undo() + + redo: -> + if @configView is null or @configView?.editing is false then @extantComponentsTreema.redo() else @configView.redo() + class ThangComponentsArrayNode extends TreemaArrayNode valueClass: 'treema-thang-components-array' editable: false @@ -230,12 +260,22 @@ class ComponentArrayNode extends TreemaArrayNode class ComponentNode extends TreemaObjectNode valueClass: 'treema-component' + addButtonTemplate: '' collection: false + build: -> + super() + @$el.find('> .treema-row').append @addButtonTemplate + addButton = @$el.find('.add-button') + addButton.hide() + addButton.click => + @callbacks.enter?(@) + @$el + buildValueForDisplay: (valEl) -> s = @data.system + '.' + @data.name @buildValueForDisplaySimply valEl, s onEnterPressed: (args...) -> super(args...) - @callbacks.enter?(@) + @callbacks.enter?(@) \ No newline at end of file diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/LevelEditView.coffee similarity index 72% rename from app/views/editor/level/edit.coffee rename to app/views/editor/level/LevelEditView.coffee index 62666f44a..a8b651192 100644 --- a/app/views/editor/level/edit.coffee +++ b/app/views/editor/level/LevelEditView.coffee @@ -6,18 +6,19 @@ World = require 'lib/world/world' DocumentFiles = require 'collections/DocumentFiles' LevelLoader = require 'lib/LevelLoader' -ThangsTabView = require './thangs_tab_view' -SettingsTabView = require './settings_tab_view' -ScriptsTabView = require './scripts_tab_view' -ComponentsTabView = require './components_tab_view' -SystemsTabView = require './systems_tab_view' -LevelSaveView = require './save_view' -LevelForkView = require './fork_view' -SaveVersionModal = require 'views/modal/save_version_modal' -PatchesView = require 'views/editor/patches_view' -VersionHistoryView = require './versions_view' +ThangsTabView = require './thangs/ThangsTabView' +SettingsTabView = require './settings/SettingsTabView' +ScriptsTabView = require './scripts/ScriptsTabView' +ComponentsTabView = require './components/ComponentsTabView' +SystemsTabView = require './systems/SystemsTabView' +SaveLevelModal = require './modals/SaveLevelModal' +LevelForkView = require './modals/ForkLevelModal' +SaveVersionModal = require 'views/modal/SaveVersionModal' +PatchesView = require 'views/editor/PatchesView' +VersionHistoryView = require './modals/LevelVersionsModal' +ComponentDocsView = require 'views/docs/ComponentDocumentationView' -module.exports = class EditorLevelView extends RootView +module.exports = class LevelEditView extends RootView id: 'editor-level-view' template: template cache: false @@ -29,8 +30,10 @@ module.exports = class EditorLevelView extends RootView 'click #commit-level-start-button': 'startCommittingLevel' 'click #fork-level-start-button': 'startForkingLevel' 'click #level-history-button': 'showVersionHistory' + 'click #undo-button': 'onUndo' + 'click #redo-button': 'onRedo' 'click #patches-tab': -> @patchesView.load() - 'click #components-tab': -> @componentsTab.refreshLevelThangsTreema @level.get('thangs') + 'click #components-tab': -> @subviews.editor_level_components_tab_view.refreshLevelThangsTreema @level.get('thangs') 'click #level-patch-button': 'startPatchingLevel' 'click #level-watch-button': 'toggleWatchLevel' 'click #pop-level-i18n-button': -> @level.populateI18N() @@ -66,11 +69,13 @@ module.exports = class EditorLevelView extends RootView return unless @supermodel.finished() @$el.find('a[data-toggle="tab"]').on 'shown.bs.tab', (e) => Backbone.Mediator.publish 'level:view-switched', e - @thangsTab = @insertSubView new ThangsTabView world: @world, supermodel: @supermodel, level: @level - @settingsTab = @insertSubView new SettingsTabView supermodel: @supermodel - @scriptsTab = @insertSubView new ScriptsTabView world: @world, supermodel: @supermodel, files: @files - @componentsTab = @insertSubView new ComponentsTabView supermodel: @supermodel - @systemsTab = @insertSubView new SystemsTabView supermodel: @supermodel + @insertSubView new ThangsTabView world: @world, supermodel: @supermodel, level: @level + @insertSubView new SettingsTabView supermodel: @supermodel + @insertSubView new ScriptsTabView world: @world, supermodel: @supermodel, files: @files + @insertSubView new ComponentsTabView supermodel: @supermodel + @insertSubView new SystemsTabView supermodel: @supermodel + @insertSubView new ComponentDocsView() + Backbone.Mediator.publish 'level-loaded', level: @level @showReadOnly() if me.get('anonymous') @patchesView = @insertSubView(new PatchesView(@level), @$el.find('.patches-view')) @@ -101,12 +106,25 @@ module.exports = class EditorLevelView extends RootView @childWindow.onPlayLevelViewLoaded = (e) => sendLevel() # still a hack @childWindow.focus() + onUndo: -> + @getCurrentView()?.undo?() + + onRedo: -> + @getCurrentView()?.redo?() + + getCurrentView: -> + tabText = _.string.underscored $('li.active')[0]?.textContent + currentView = @subviews["editor_level_#{tabText}_tab_view"] + if tabText is 'patches' then currentView = @patchesView + if tabText is 'documentation' then currentView = @subviews.docs_components_view + currentView + startPatchingLevel: (e) -> @openModalView new SaveVersionModal({model: @level}) Backbone.Mediator.publish 'level:view-switched', e startCommittingLevel: (e) -> - @openModalView new LevelSaveView level: @level, supermodel: @supermodel + @openModalView new SaveLevelModal level: @level, supermodel: @supermodel Backbone.Mediator.publish 'level:view-switched', e startForkingLevel: (e) -> diff --git a/app/views/editor/level/home.coffee b/app/views/editor/level/LevelSearchView.coffee similarity index 89% rename from app/views/editor/level/home.coffee rename to app/views/editor/level/LevelSearchView.coffee index f5db556e6..a5dfb21c7 100644 --- a/app/views/editor/level/home.coffee +++ b/app/views/editor/level/LevelSearchView.coffee @@ -1,6 +1,6 @@ SearchView = require 'views/kinds/SearchView' -module.exports = class EditorSearchView extends SearchView +module.exports = class LevelSearchView extends SearchView id: 'editor-level-home-view' modelLabel: 'Level' model: require 'models/Level' diff --git a/app/views/editor/level/components_tab_view.coffee b/app/views/editor/level/components/ComponentsTabView.coffee similarity index 97% rename from app/views/editor/level/components_tab_view.coffee rename to app/views/editor/level/components/ComponentsTabView.coffee index 03c9bb2cf..3cfb953b8 100644 --- a/app/views/editor/level/components_tab_view.coffee +++ b/app/views/editor/level/components/ComponentsTabView.coffee @@ -1,8 +1,8 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/components_tab' LevelComponent = require 'models/LevelComponent' -LevelComponentEditView = require './component/edit' -LevelComponentNewView = require './component/new' +LevelComponentEditView = require './LevelComponentEditView' +LevelComponentNewView = require './NewLevelComponentModal' class LevelComponentCollection extends Backbone.Collection url: '/db/level.component' diff --git a/app/views/editor/level/component/edit.coffee b/app/views/editor/level/components/LevelComponentEditView.coffee similarity index 94% rename from app/views/editor/level/component/edit.coffee rename to app/views/editor/level/components/LevelComponentEditView.coffee index 9e36530ba..c09600241 100644 --- a/app/views/editor/level/component/edit.coffee +++ b/app/views/editor/level/components/LevelComponentEditView.coffee @@ -1,9 +1,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/component/edit' LevelComponent = require 'models/LevelComponent' -VersionHistoryView = require 'views/editor/component/versions_view' -PatchesView = require 'views/editor/patches_view' -SaveVersionModal = require 'views/modal/save_version_modal' +ComponentVersionsModal = require 'views/editor/component/ComponentVersionsModal' +PatchesView = require 'views/editor/PatchesView' +SaveVersionModal = require 'views/modal/SaveVersionModal' module.exports = class LevelComponentEditView extends CocoView id: 'editor-level-component-edit-view' @@ -108,8 +108,8 @@ module.exports = class LevelComponentEditView extends CocoView null showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView {}, @levelComponent.id - @openModalView versionHistoryView + componentVersionsModal = new ComponentVersionsModal {}, @levelComponent.id + @openModalView componentVersionsModal Backbone.Mediator.publish 'level:view-switched', e startPatchingComponent: (e) -> diff --git a/app/views/editor/level/component/new.coffee b/app/views/editor/level/components/NewLevelComponentModal.coffee similarity index 95% rename from app/views/editor/level/component/new.coffee rename to app/views/editor/level/components/NewLevelComponentModal.coffee index 314cf2c86..c4ead45de 100644 --- a/app/views/editor/level/component/new.coffee +++ b/app/views/editor/level/components/NewLevelComponentModal.coffee @@ -4,7 +4,7 @@ LevelComponent = require 'models/LevelComponent' forms = require 'lib/forms' {me} = require 'lib/auth' -module.exports = class LevelComponentNewView extends ModalView +module.exports = class NewLevelComponentModal extends ModalView id: 'editor-level-component-new-modal' template: template instant: false diff --git a/app/views/editor/level/modal/terrain_randomize_modal.coffee b/app/views/editor/level/modal/terrain_randomize_modal.coffee deleted file mode 100644 index 34dfc4756..000000000 --- a/app/views/editor/level/modal/terrain_randomize_modal.coffee +++ /dev/null @@ -1,191 +0,0 @@ -ModalView = require 'views/kinds/ModalView' -template = require 'templates/editor/level/modal/terrain_randomize' -CocoModel = require 'models/CocoModel' - -clusters = { - 'rocks': ['Rock 1', 'Rock 2', 'Rock 3', 'Rock 4', 'Rock 5', 'Rock Cluster 1', 'Rock Cluster 2', 'Rock Cluster 3'] - 'trees': ['Tree 1', 'Tree 2', 'Tree 3', 'Tree 4'] - 'shrubs': ['Shrub 1', 'Shrub 2', 'Shrub 3'] - 'houses': ['House 1', 'House 2', 'House 3', 'House 4'] - 'animals': ['Cow', 'Horse'] - 'wood': ['Firewood 1', 'Firewood 2', 'Firewood 3', 'Barrel'] - 'farm': ['Farm'] -} - -presets = { - # 'dungeon': { - # 'type':'dungeon' - # 'borders':['Dungeon Wall'] - # 'floors':['Dungeon Floor'] - # 'decorations':[] - # } - 'grassy': { - 'type':'grassy' - 'borders':['Tree 1', 'Tree 2', 'Tree 3'] - 'floors':['Grass01', 'Grass02', 'Grass03', 'Grass04', 'Grass05'] - 'decorations': { - 'house': { - 'num':[1,2] #min-max - 'width': 20 - 'height': 20 - 'clusters': { - 'houses':[1,1] - 'trees':[1,2] - 'shrubs':[0,3] - 'rocks':[1,2] - } - } - 'farm': { - 'num':[1,2] #min-max - 'width': 20 - 'height': 20 - 'clusters': { - 'farm':[1,1] - 'shrubs':[2,3] - 'wood':[2,4] - 'animals':[2,3] - } - } - } - } -} - -sizes = { - 'small': { - 'x':80 - 'y':68 - } - 'large': { - 'x':160 - 'y':136 - } - 'floorSize': { - 'x':20 - 'y':17 - } - 'borderSize': { - 'x':4 - 'y':4 - 'thickness':3 - } -} - -module.exports = class TerrainRandomizeModal extends ModalView - id: 'terrain-randomize-modal' - template: template - thangs = [] - - events: - 'click .choose-option': 'onRandomize' - - onRevertModel: (e) -> - id = $(e.target).val() - CocoModel.backedUp[id].revert() - $(e.target).closest('tr').remove() - @reloadOnClose = true - - onRandomize: (e) -> - target = $(e.target) - presetType = target.attr 'data-preset-type' - presetSize = target.attr 'data-preset-size' - @randomizeThangs presetType, presetSize - Backbone.Mediator.publish('randomize:terrain-generated', - 'thangs': @thangs - ) - @hide() - - randomizeThangs: (presetName, presetSize) -> - preset = presets[presetName] - presetSize = sizes[presetSize] - @thangs = [] - @randomizeFloor preset, presetSize - @randomizeBorder preset, presetSize - @randomizeDecorations preset, presetSize - - randomizeFloor: (preset, presetSize) -> - for i in _.range(0, presetSize.x, sizes.floorSize.x) - for j in _.range(0, presetSize.y, sizes.floorSize.y) - @thangs.push { - 'id': @getRandomThang(preset.floors) - 'pos': { - 'x': i + sizes.floorSize.x/2 - 'y': j + sizes.floorSize.y/2 - } - } - - randomizeBorder: (preset, presetSize) -> - for i in _.range(0, presetSize.x, sizes.borderSize.x) - for j in _.range(sizes.borderSize.thickness) - @thangs.push { - 'id': @getRandomThang(preset.borders) - 'pos': { - 'x': i + _.random(-sizes.borderSize.x/2, sizes.borderSize.x/2) - 'y': 0 + _.random(-sizes.borderSize.y/2, sizes.borderSize.y) - } - } - @thangs.push { - 'id': @getRandomThang(preset.borders) - 'pos': { - 'x': i + _.random(-sizes.borderSize.x/2, sizes.borderSize.x/2) - 'y': presetSize.y + _.random(-sizes.borderSize.y, sizes.borderSize.y/2) - } - } - - for i in _.range(0, presetSize.y, sizes.borderSize.y) - for j in _.range(3) - @thangs.push { - 'id': @getRandomThang(preset.borders) - 'pos': { - 'x': 0 + _.random(-sizes.borderSize.x/2, sizes.borderSize.x) - 'y': i + _.random(-sizes.borderSize.y/2, sizes.borderSize.y/2) - } - } - @thangs.push { - 'id': @getRandomThang(preset.borders) - 'pos': { - 'x': presetSize.x + _.random(-sizes.borderSize.x, sizes.borderSize.x/2) - 'y': i + _.random(-sizes.borderSize.y/2, sizes.borderSize.y/2) - } - } - - randomizeDecorations: (preset, presetSize)-> - for name, decoration of preset.decorations - for num in _.range(_.random(decoration.num[0], decoration.num[1])) - center = - { - 'x':_.random(decoration.width, presetSize.x - decoration.width), - 'y':_.random(decoration.height, presetSize.y - decoration.height) - } - min = - { - 'x':center.x - decoration.width/2 - 'y':center.y - decoration.height/2 - } - max = - { - 'x':center.x + decoration.width/2 - 'y':center.y + decoration.height/2 - } - for cluster, range of decoration.clusters - for i in _.range(_.random(range[0], range[1])) - @thangs.push { - 'id':@getRandomThang(clusters[cluster]) - 'pos':{ - 'x':_.random(min.x, max.x) - 'y':_.random(min.y, max.y) - } - } - - - getRandomThang: (thangList) -> - return thangList[_.random(0, thangList.length-1)] - - getRenderData: -> - c = super() - models = _.values CocoModel.backedUp - models = (m for m in models when m.hasLocalChanges()) - c.models = models - c - - onHidden: -> - location.reload() if @reloadOnClose diff --git a/app/views/editor/level/fork_view.coffee b/app/views/editor/level/modals/ForkLevelModal.coffee similarity index 95% rename from app/views/editor/level/fork_view.coffee rename to app/views/editor/level/modals/ForkLevelModal.coffee index 2b3f7cfea..335ffc4a1 100644 --- a/app/views/editor/level/fork_view.coffee +++ b/app/views/editor/level/modals/ForkLevelModal.coffee @@ -3,7 +3,7 @@ template = require 'templates/editor/level/fork' forms = require 'lib/forms' Level = require 'models/Level' -module.exports = class LevelForkView extends ModalView +module.exports = class ForkLevelModal extends ModalView id: 'editor-level-fork-modal' template: template instant: false diff --git a/app/views/editor/level/versions_view.coffee b/app/views/editor/level/modals/LevelVersionsModal.coffee similarity index 55% rename from app/views/editor/level/versions_view.coffee rename to app/views/editor/level/modals/LevelVersionsModal.coffee index 38375ead8..21cb5a125 100644 --- a/app/views/editor/level/versions_view.coffee +++ b/app/views/editor/level/modals/LevelVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class LevelVersionsView extends VersionsModalView +module.exports = class LevelVersionsModal extends VersionsModal id: 'editor-level-versions-view' url: '/db/level/' page: 'level' diff --git a/app/views/editor/level/save_view.coffee b/app/views/editor/level/modals/SaveLevelModal.coffee similarity index 95% rename from app/views/editor/level/save_view.coffee rename to app/views/editor/level/modals/SaveLevelModal.coffee index 28c46e81d..2cbf62b9c 100644 --- a/app/views/editor/level/save_view.coffee +++ b/app/views/editor/level/modals/SaveLevelModal.coffee @@ -1,12 +1,12 @@ -SaveVersionModal = require 'views/modal/save_version_modal' +SaveVersionModal = require 'views/modal/SaveVersionModal' template = require 'templates/editor/level/save' forms = require 'lib/forms' LevelComponent = require 'models/LevelComponent' LevelSystem = require 'models/LevelSystem' -DeltaView = require 'views/editor/delta' -PatchModal = require 'views/editor/patch_modal' +DeltaView = require 'views/editor/DeltaView' +PatchModal = require 'views/editor/PatchModal' -module.exports = class LevelSaveView extends SaveVersionModal +module.exports = class SaveLevelModal extends SaveVersionModal template: template instant: false modalWidthPercent: 60 diff --git a/app/views/editor/level/modals/TerrainRandomizeModal.coffee b/app/views/editor/level/modals/TerrainRandomizeModal.coffee new file mode 100644 index 000000000..c9decc61c --- /dev/null +++ b/app/views/editor/level/modals/TerrainRandomizeModal.coffee @@ -0,0 +1,367 @@ +ModalView = require 'views/kinds/ModalView' +template = require 'templates/editor/level/modal/terrain_randomize' +CocoModel = require 'models/CocoModel' + +clusters = { + 'rocks': { + 'thangs': ['Rock 1', 'Rock 2', 'Rock 3', 'Rock 4', 'Rock 5', 'Rock Cluster 1', 'Rock Cluster 2', 'Rock Cluster 3'] + 'margin': 1 + } + 'trees': { + 'thangs': ['Tree 1', 'Tree 2', 'Tree 3', 'Tree 4'] + 'margin': 0 + } + 'shrubs': { + 'thangs': ['Shrub 1', 'Shrub 2', 'Shrub 3'] + 'margin': 0 + } + 'houses': { + 'thangs': ['House 1', 'House 2', 'House 3', 'House 4'] + 'margin': 4 + } + 'animals': { + 'thangs': ['Cow', 'Horse'] + 'margin': 1 + } + 'wood': { + 'thangs': ['Firewood 1', 'Firewood 2', 'Firewood 3', 'Barrel'] + 'margin': 1 + } + 'farm': { + 'thangs': ['Farm'] + 'margin': 9 + } + 'cave': { + 'thangs': ['Cave'] + 'margin': 5 + } + 'stone': { + 'thangs': ['Gargoyle', 'Rock Cluster 1', 'Rock Cluster 2', 'Rock Cluster 3'] + 'margin': 1 + } + 'doors': { + 'thangs': ['Dungeon Door'] + 'margin': -1 + } + 'grass_floor': { + 'thangs': ['Grass01', 'Grass02', 'Grass03', 'Grass04', 'Grass05'] + 'margin': -1 + } + 'dungeon_wall': { + 'thangs': ['Dungeon Wall'] + 'margin': 2 + } + 'dungeon_floor': { + 'thangs': ['Dungeon Floor'] + 'margin': -1 + } +} + +presets = { + 'dungeon': { + 'type':'dungeon' + 'borders':'dungeon_wall' + 'borderNoise':0 + 'borderSize':4 + 'floors':'dungeon_floor' + 'decorations': { + 'cave': { + 'num':[1,1] + 'width': 10 + 'height': 10 + 'clusters': { + 'cave':[1,1] + 'stone':[2,4] + } + } + 'Room': { + 'num': [1,1] + 'width': [12, 20] + 'height': [8, 16] + 'thickness': [2,2] + 'cluster': 'dungeon_wall' + } + } + } + 'grassy': { + 'type':'grassy' + 'borders':'trees' + 'borderNoise':1 + 'borderSize':0 + 'floors':'grass_floor' + 'decorations': { + 'house': { + 'num':[1,2] #min-max + 'width': 15 + 'height': 15 + 'clusters': { + 'houses':[1,1] + 'trees':[1,2] + 'shrubs':[0,3] + 'rocks':[1,2] + } + } + 'farm': { + 'num':[1,1] #min-max + 'width': 25 + 'height': 15 + 'clusters': { + 'farm':[1,1] + 'shrubs':[2,3] + 'wood':[2,4] + 'animals':[2,3] + } + } + } + } +} + +presetSizes = { + 'small': { + 'x':80 + 'y':68 + } + 'large': { + 'x':160 + 'y':136 + } +} + +thangSizes = { + 'floorSize': { + 'x':20 + 'y':17 + } + 'borderSize': { + 'x':4 + 'y':4 + 'thickness':3 + } +} + +module.exports = class TerrainRandomizeModal extends ModalView + id: 'terrain-randomize-modal' + template: template + events: + 'click .choose-option': 'onRandomize' + + onRevertModel: (e) -> + id = $(e.target).val() + CocoModel.backedUp[id].revert() + $(e.target).closest('tr').remove() + @reloadOnClose = true + + onRandomize: (e) -> + target = $(e.target) + presetType = target.attr 'data-preset-type' + presetSize = target.attr 'data-preset-size' + @randomizeThangs presetType, presetSize + Backbone.Mediator.publish('randomize:terrain-generated', + 'thangs': @thangs + ) + @hide() + + randomizeThangs: (presetName, presetSize) -> + @falseCount = 0 + preset = presets[presetName] + presetSize = presetSizes[presetSize] + @thangs = [] + @rects = [] + @randomizeFloor preset, presetSize + @randomizeBorder preset, presetSize, preset.borderNoise + @randomizeDecorations preset, presetSize + + randomizeFloor: (preset, presetSize) -> + for i in _.range(0, presetSize.x, thangSizes.floorSize.x) + for j in _.range(0, presetSize.y, thangSizes.floorSize.y) + @thangs.push { + 'id': @getRandomThang(clusters[preset.floors].thangs) + 'pos': { + 'x': i + thangSizes.floorSize.x/2 + 'y': j + thangSizes.floorSize.y/2 + } + 'margin': clusters[preset.floors].margin + } + + randomizeBorder: (preset, presetSize, noiseFactor=1) -> + for i in _.range(0, presetSize.x, thangSizes.borderSize.x) + for j in _.range(thangSizes.borderSize.thickness) + while not @addThang { + 'id': @getRandomThang(clusters[preset.borders].thangs) + 'pos': { + 'x': i + preset.borderSize/2 + noiseFactor * _.random(-thangSizes.borderSize.x/2, thangSizes.borderSize.x/2) + 'y': 0 + preset.borderSize/2 + noiseFactor * _.random(-thangSizes.borderSize.y/2, thangSizes.borderSize.y) + } + 'margin': clusters[preset.borders].margin + } + continue + while not @addThang { + 'id': @getRandomThang(clusters[preset.borders].thangs) + 'pos': { + 'x': i + preset.borderSize/2 + noiseFactor * _.random(-thangSizes.borderSize.x/2, thangSizes.borderSize.x/2) + 'y': presetSize.y - preset.borderSize/2 + noiseFactor * _.random(-thangSizes.borderSize.y, thangSizes.borderSize.y/2) + } + 'margin': clusters[preset.borders].margin + } + continue + + for i in _.range(0, presetSize.y, thangSizes.borderSize.y) + for j in _.range(3) + while not @addThang { + 'id': @getRandomThang(clusters[preset.borders].thangs) + 'pos': { + 'x': 0 + preset.borderSize/2 + noiseFactor * _.random(-thangSizes.borderSize.x/2, thangSizes.borderSize.x) + 'y': i + preset.borderSize/2 + noiseFactor * _.random(-thangSizes.borderSize.y/2, thangSizes.borderSize.y/2) + } + 'margin': clusters[preset.borders].margin + } + continue + while not @addThang { + 'id': @getRandomThang(clusters[preset.borders].thangs) + 'pos': { + 'x': presetSize.x - preset.borderSize/2 + noiseFactor * _.random(-thangSizes.borderSize.x, thangSizes.borderSize.x/2) + 'y': i + preset.borderSize/2 + noiseFactor * _.random(-thangSizes.borderSize.y/2, thangSizes.borderSize.y/2) + } + 'margin': clusters[preset.borders].margin + } + continue + + randomizeDecorations: (preset, presetSize)-> + if presetSize is presetSizes['small'] then sizeFactor = 1 else sizeFactor = 2 + for name, decoration of preset.decorations + for num in _.range(sizeFactor * _.random(decoration.num[0], decoration.num[1])) + if @['build'+name] isnt undefined + @['build'+name](preset, presetSize, decoration) + continue + while true + rect = { + 'x':_.random(decoration.width/2 + preset.borderSize/2 + thangSizes.borderSize.x, presetSize.x - decoration.width/2 - preset.borderSize/2 - thangSizes.borderSize.x), + 'y':_.random(decoration.height/2 + preset.borderSize/2 + thangSizes.borderSize.y, presetSize.y - decoration.height/2 - preset.borderSize/2 - thangSizes.borderSize.y) + 'width':decoration.width + 'height':decoration.height + } + break if @addRect rect + + for cluster, range of decoration.clusters + for i in _.range(_.random(range[0], range[1])) + while not @addThang { + 'id':@getRandomThang(clusters[cluster].thangs) + 'pos':{ + 'x':_.random(rect.x - rect.width/2, rect.x + rect.width/2) + 'y':_.random(rect.y - rect.height/2, rect.y + rect.height/2) + } + 'margin':clusters[cluster].margin + } + continue + + buildRoom: (preset, presetSize, room) -> + if presetSize is presetSizes['small'] then sizeFactor = 1 else sizeFactor = 2 + while true + rect = { + 'width':sizeFactor * (room.width[0] + preset.borderSize * _.random(0, (room.width[1] - room.width[0])/preset.borderSize)) + 'height':sizeFactor * (room.height[0] + preset.borderSize * _.random(0, (room.height[1] - room.height[0])/preset.borderSize)) + } + roomThickness = _.random(room.thickness[0], room.thickness[1]) + rect.x = _.random(rect.width/2 + preset.borderSize * (roomThickness+1), presetSize.x - rect.width/2 - preset.borderSize * (roomThickness+1)) + rect.y = _.random(rect.height/2 + preset.borderSize * (roomThickness+1), presetSize.y - rect.height/2 - preset.borderSize * (roomThickness+1)) + # Snap room walls to the wall grid. + rect.x = Math.round((rect.x - preset.borderSize / 2) / preset.borderSize) * preset.borderSize + preset.borderSize / 2 + rect.y = Math.round((rect.y - preset.borderSize / 2) / preset.borderSize) * preset.borderSize + preset.borderSize / 2 + break if @addRect { + 'x': rect.x + 'y': rect.y + 'width': rect.width + 2 * roomThickness * preset.borderSize + 'height': rect.height + 2 * roomThickness * preset.borderSize + } + + xRange = _.range(rect.x - rect.width/2 + preset.borderSize, rect.x + rect.width/2, preset.borderSize) + topDoor = _.random(1) > 0.5 + topDoorX = xRange[_.random(0, xRange.length-1)] + bottomDoor = if not topDoor then true else _.random(1) > 0.5 + bottomDoorX = xRange[_.random(0, xRange.length-1)] + + for t in _.range(0, roomThickness+1) + for i in _.range(rect.x - rect.width/2 - (t-1) * preset.borderSize, rect.x + rect.width/2 + t * preset.borderSize, preset.borderSize) + thang = { + 'id': @getRandomThang(clusters[room.cluster].thangs) + 'pos': { + 'x': i + 'y': rect.y - rect.height/2 - t * preset.borderSize + } + 'margin': clusters[room.cluster].margin + } + if i is bottomDoorX and bottomDoor + thang.id = @getRandomThang(clusters['doors'].thangs) + thang.pos.y -= preset.borderSize/3 + @addThang thang unless i is bottomDoorX and t isnt roomThickness and bottomDoor + + thang = { + 'id': @getRandomThang(clusters[room.cluster].thangs) + 'pos': { + 'x': i + 'y': rect.y + rect.height/2 + t * preset.borderSize + } + 'margin': clusters[room.cluster].margin + } + if i is topDoorX and topDoor + thang.id = @getRandomThang(clusters['doors'].thangs) + thang.pos.y -= preset.borderSize + @addThang thang unless i is topDoorX and t isnt roomThickness and topDoor + + for t in _.range(0, roomThickness) + for i in _.range(rect.y - rect.height/2 - t * preset.borderSize, rect.y + rect.height/2 + (t+1) * preset.borderSize, preset.borderSize) + @addThang { + 'id': @getRandomThang(clusters[room.cluster].thangs) + 'pos': { + 'x': rect.x - rect.width/2 - t * preset.borderSize + 'y': i + } + 'margin': clusters[room.cluster].margin + } + + @addThang { + 'id': @getRandomThang(clusters[room.cluster].thangs) + 'pos': { + 'x': rect.x + rect.width/2 + t * preset.borderSize + 'y': i + } + 'margin': clusters[room.cluster].margin + } + + addThang: (thang) -> + if @falseCount > 100 + console.log 'infinite loop', thang + @falseCount = 0 + return true + for existingThang in @thangs + if existingThang.margin is -1 or thang.margin is -1 + continue + if Math.abs(existingThang.pos.x - thang.pos.x) < thang.margin + existingThang.margin and Math.abs(existingThang.pos.y - thang.pos.y) < thang.margin + existingThang.margin + @falseCount++ + return false + @thangs.push thang + true + + addRect: (rect) -> + if @falseCount > 100 + console.log 'infinite loop', rect + @falseCount = 0 + return true + for existingRect in @rects + if Math.abs(existingRect.x - rect.x) < rect.width/2 + existingRect.width/2 and Math.abs(existingRect.y - rect.y) < rect.height/2 + existingRect.height/2 + @falseCount++ + return false + @rects.push rect + true + + getRandomThang: (thangList) -> + return thangList[_.random(0, thangList.length-1)] + + getRenderData: -> + c = super() + c.presets = presets + c.presetSizes = presetSizes + c + + onHidden: -> + location.reload() if @reloadOnClose diff --git a/app/views/editor/level/modal/world_select.coffee b/app/views/editor/level/modals/WorldSelectModal.coffee similarity index 100% rename from app/views/editor/level/modal/world_select.coffee rename to app/views/editor/level/modals/WorldSelectModal.coffee diff --git a/app/views/editor/level/scripts_tab_view.coffee b/app/views/editor/level/scripts/ScriptsTabView.coffee similarity index 78% rename from app/views/editor/level/scripts_tab_view.coffee rename to app/views/editor/level/scripts/ScriptsTabView.coffee index ae6813cbf..a53b2c383 100644 --- a/app/views/editor/level/scripts_tab_view.coffee +++ b/app/views/editor/level/scripts/ScriptsTabView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/scripts_tab' Level = require 'models/Level' Surface = require 'lib/surface/Surface' -nodes = require './treema_nodes' +nodes = require './../treema_nodes' module.exports = class ScriptsTabView extends CocoView id: 'editor-level-scripts-tab-view' @@ -39,7 +39,23 @@ module.exports = class ScriptsTabView extends CocoView onScriptsChanged: (e) => @level.set 'scripts', @scriptsTreema.data + lastAction = @scriptsTreema.trackedActions[@scriptsTreema.trackedActions.length - 1] + return unless lastAction + if lastAction.action is 'insert' and lastAction.parentPath is '/' + newScript = @scriptsTreema.get lastAction.path + if newScript.id is undefined + @scriptsTreema.set lastAction.path+'/id', 'Script-' + @scriptsTreema.data.length + @scriptTreema.refreshDisplay() + + if lastAction.action is 'delete' and lastAction.parentPath[0] is '/' + for key, treema of @scriptsTreema.childrenTreemas + key = parseInt(key) + if /Script-[0-9]*/.test treema.data.id + existingKey = parseInt(treema.data.id.substr(7)) + if existingKey isnt key+1 + treema.set 'id', 'Script-' + (key+1) + onScriptSelected: (e, selected) => selected = if selected.length > 1 then selected[0].getLastSelectedTreema() else selected[0] unless selected @@ -86,6 +102,12 @@ module.exports = class ScriptsTabView extends CocoView onScriptChanged: => @scriptsTreema.set(@selectedScriptPath, @scriptTreema.data) + undo: -> + @scriptsTreema.undo() if @scriptTreema.undo() is undefined + + redo: -> + @scriptsTreema.redo() if @scriptTreema.redo() is undefined + class ScriptNode extends TreemaObjectNode valueClass: 'treema-script' collection: false @@ -118,7 +140,14 @@ class EventPropsNode extends TreemaNode.nodeMap.string joined = '(unset)' if not joined.length @buildValueForDisplaySimply valEl, joined - buildValueForEditing: (valEl) -> @buildValueForEditingSimply(valEl, @arrayToString()) + buildValueForEditing: (valEl) -> + super(valEl) + channel = @getRoot().data.channel + channelSchema = Backbone.Mediator.channelSchemas[channel] + autocompleteValues = [] + autocompleteValues.push key for key, val of channelSchema?.properties + valEl.find('input').autocomplete(source: autocompleteValues, minLength: 0, delay: 0, autoFocus: true).autocomplete('search') + valEl saveChanges: (valEl) -> @data = (s for s in $('input', valEl).val().split('.') when s.length) diff --git a/app/views/editor/level/settings_tab_view.coffee b/app/views/editor/level/settings/SettingsTabView.coffee similarity index 93% rename from app/views/editor/level/settings_tab_view.coffee rename to app/views/editor/level/settings/SettingsTabView.coffee index 7e2056c2f..5133dd6ba 100644 --- a/app/views/editor/level/settings_tab_view.coffee +++ b/app/views/editor/level/settings/SettingsTabView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/settings_tab' Level = require 'models/Level' Surface = require 'lib/surface/Surface' -nodes = require './treema_nodes' +nodes = require './../treema_nodes' {me} = require 'lib/auth' module.exports = class SettingsTabView extends CocoView @@ -53,3 +53,9 @@ module.exports = class SettingsTabView extends CocoView for key in @editableSettings continue if @settingsTreema.data[key] is undefined @level.set key, @settingsTreema.data[key] + + undo: -> + @settingsTreema.undo() + + redo: -> + @settingsTreema.redo() diff --git a/app/views/editor/level/system/add.coffee b/app/views/editor/level/systems/AddLevelSystemModal.coffee similarity index 97% rename from app/views/editor/level/system/add.coffee rename to app/views/editor/level/systems/AddLevelSystemModal.coffee index f0c3b7490..d11071e4c 100644 --- a/app/views/editor/level/system/add.coffee +++ b/app/views/editor/level/systems/AddLevelSystemModal.coffee @@ -8,7 +8,7 @@ class LevelSystemSearchCollection extends CocoCollection url: '/db/level_system' model: LevelSystem -module.exports = class LevelSystemAddView extends ModalView +module.exports = class AddLevelSystemModal extends ModalView id: 'editor-level-system-add-modal' template: template instant: true diff --git a/app/views/editor/level/system/edit.coffee b/app/views/editor/level/systems/LevelSystemEditView.coffee similarity index 86% rename from app/views/editor/level/system/edit.coffee rename to app/views/editor/level/systems/LevelSystemEditView.coffee index de5877bda..89c52faae 100644 --- a/app/views/editor/level/system/edit.coffee +++ b/app/views/editor/level/systems/LevelSystemEditView.coffee @@ -1,9 +1,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/system/edit' LevelSystem = require 'models/LevelSystem' -VersionHistoryView = require 'views/editor/system/versions_view' -PatchesView = require 'views/editor/patches_view' -SaveVersionModal = require 'views/modal/save_version_modal' +SystemVersionsModal = require 'views/editor/level/systems/SystemVersionsModal' +PatchesView = require 'views/editor/PatchesView' +SaveVersionModal = require 'views/modal/SaveVersionModal' module.exports = class LevelSystemEditView extends CocoView id: 'editor-level-system-edit-view' @@ -101,8 +101,8 @@ module.exports = class LevelSystemEditView extends CocoView null showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView {}, @levelSystem.id - @openModalView versionHistoryView + systemVersionsModal = new SystemVersionsModal {}, @levelSystem.id + @openModalView systemVersionsModal Backbone.Mediator.publish 'level:view-switched', e startPatchingSystem: (e) -> @@ -115,6 +115,18 @@ module.exports = class LevelSystemEditView extends CocoView @levelSystem.watch(button.find('.watch').is(':visible')) button.find('> span').toggleClass('secret') + undo: -> + if @$el.find('li.active > a#system-config-schema-tab') + @configSchemaTreema.undo() + if @$el.find('li.active > a#system-settings-tab') + @systemSettingsTreema.undo() + + redo: -> + if @$el.find('li.active > a#system-config-schema-tab') + @configSchemaTreema.redo() + if @$el.find('li.active > a#system-settings-tab') + @systemSettingsTreema.redo() + destroy: -> @editor?.destroy() super() diff --git a/app/views/editor/level/system/new.coffee b/app/views/editor/level/systems/NewLevelSystemModal.coffee similarity index 95% rename from app/views/editor/level/system/new.coffee rename to app/views/editor/level/systems/NewLevelSystemModal.coffee index 86b959f01..d2f509dbf 100644 --- a/app/views/editor/level/system/new.coffee +++ b/app/views/editor/level/systems/NewLevelSystemModal.coffee @@ -4,7 +4,7 @@ LevelSystem = require 'models/LevelSystem' forms = require 'lib/forms' {me} = require 'lib/auth' -module.exports = class LevelSystemNewView extends ModalView +module.exports = class NewLevelSystemModal extends ModalView id: 'editor-level-system-new-modal' template: template instant: false diff --git a/app/views/editor/system/versions_view.coffee b/app/views/editor/level/systems/SystemVersionsModal.coffee similarity index 57% rename from app/views/editor/system/versions_view.coffee rename to app/views/editor/level/systems/SystemVersionsModal.coffee index 6c0fe3e59..75d0a4ba0 100755 --- a/app/views/editor/system/versions_view.coffee +++ b/app/views/editor/level/systems/SystemVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class SystemVersionsView extends VersionsModalView +module.exports = class SystemVersionsModal extends VersionsModal id: 'editor-system-versions-view' url: '/db/level.system/' page: 'system' diff --git a/app/views/editor/level/systems_tab_view.coffee b/app/views/editor/level/systems/SystemsTabView.coffee similarity index 91% rename from app/views/editor/level/systems_tab_view.coffee rename to app/views/editor/level/systems/SystemsTabView.coffee index 4b4988755..df5908aa7 100644 --- a/app/views/editor/level/systems_tab_view.coffee +++ b/app/views/editor/level/systems/SystemsTabView.coffee @@ -2,10 +2,10 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/systems_tab' Level = require 'models/Level' LevelSystem = require 'models/LevelSystem' -LevelSystemEditView = require './system/edit' -LevelSystemNewView = require './system/new' -LevelSystemAddView = require './system/add' -{ThangTypeNode} = require './treema_nodes' +LevelSystemEditView = require './LevelSystemEditView' +NewLevelSystemModal = require './NewLevelSystemModal' +AddLevelSystemModal = require './AddLevelSystemModal' +{ThangTypeNode} = require './../treema_nodes' module.exports = class SystemsTabView extends CocoView id: 'editor-level-systems-tab-view' @@ -49,7 +49,7 @@ module.exports = class SystemsTabView extends CocoView insertedDefaults = true systems = @getSortedByName systems treemaOptions = - # TODO: somehow get rid of the + button, or repurpose it to open the LevelSystemAddView instead + # TODO: somehow get rid of the + button, or repurpose it to open the AddLevelSystemModal instead supermodel: @supermodel schema: Level.schema.properties.systems data: systems @@ -90,11 +90,11 @@ module.exports = class SystemsTabView extends CocoView @systemsTreema.insert '/', e.system addLevelSystem: (e) -> - @openModalView new LevelSystemAddView supermodel: @supermodel, extantSystems: _.cloneDeep @systemsTreema.data + @openModalView new AddLevelSystemModal supermodel: @supermodel, extantSystems: _.cloneDeep @systemsTreema.data Backbone.Mediator.publish 'level:view-switched', e createNewLevelSystem: (e) -> - @openModalView new LevelSystemNewView supermodel: @supermodel + @openModalView new NewLevelSystemModal supermodel: @supermodel Backbone.Mediator.publish 'level:view-switched', e editLevelSystem: (e) -> @@ -125,6 +125,13 @@ module.exports = class SystemsTabView extends CocoView {original: '528114e60268d018e300001a', majorVersion: 0} # UI {original: '528114040268d018e3000011', majorVersion: 0} # Physics ] + undo: -> + return unless @levelSystemEditView + @levelSystemEditView.undo() + + redo: -> + return unless @levelSystemEditView + @levelSystemEditView.redo() class LevelSystemNode extends TreemaObjectNode valueClass: 'treema-level-system' diff --git a/app/views/editor/level/add_thangs_view.coffee b/app/views/editor/level/thangs/AddThangsView.coffee similarity index 100% rename from app/views/editor/level/add_thangs_view.coffee rename to app/views/editor/level/thangs/AddThangsView.coffee diff --git a/app/views/editor/level/thang/edit.coffee b/app/views/editor/level/thangs/LevelThangEditView.coffee similarity index 92% rename from app/views/editor/level/thang/edit.coffee rename to app/views/editor/level/thangs/LevelThangEditView.coffee index 4dd5b1549..96e2c7e1a 100644 --- a/app/views/editor/level/thang/edit.coffee +++ b/app/views/editor/level/thangs/LevelThangEditView.coffee @@ -1,6 +1,6 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/thang/edit' -ThangComponentEditView = require 'views/editor/components/main' +ThangComponentEditView = require 'views/editor/component/ThangComponentEditView' ThangType = require 'models/ThangType' module.exports = class LevelThangEditView extends CocoView @@ -92,3 +92,11 @@ module.exports = class LevelThangEditView extends CocoView onComponentsChanged: (components) => @thangData.components = components @saveThang() + + undo: -> + return unless @thangComponentEditView + @thangComponentEditView.undo() + + redo: -> + return unless @thangComponentEditView + @thangComponentEditView.redo() diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs/ThangsTabView.coffee similarity index 97% rename from app/views/editor/level/thangs_tab_view.coffee rename to app/views/editor/level/thangs/ThangsTabView.coffee index 2fa4cb64c..5f28b1279 100644 --- a/app/views/editor/level/thangs_tab_view.coffee +++ b/app/views/editor/level/thangs/ThangsTabView.coffee @@ -1,5 +1,5 @@ CocoView = require 'views/kinds/CocoView' -AddThangsView = require './add_thangs_view' +AddThangsView = require './AddThangsView' thangs_template = require 'templates/editor/level/thangs_tab' Level = require 'models/Level' ThangType = require 'models/ThangType' @@ -8,7 +8,7 @@ CocoCollection = require 'collections/CocoCollection' {isObjectID} = require 'models/CocoModel' Surface = require 'lib/surface/Surface' Thang = require 'lib/world/thang' -LevelThangEditView = require './thang/edit' +LevelThangEditView = require './LevelThangEditView' ComponentsCollection = require 'collections/ComponentsCollection' # Moving the screen while dragging thangs constants @@ -58,8 +58,8 @@ module.exports = class ThangsTabView extends CocoView 'delete, del, backspace': 'deleteSelectedExtantThang' 'left': -> @moveAddThangSelection -1 'right': -> @moveAddThangSelection 1 - 'ctrl+z': 'undoAction' - 'ctrl+shift+z': 'redoAction' + 'ctrl+z': 'undo' + 'ctrl+shift+z': 'redo' constructor: (options) -> super options @@ -116,6 +116,8 @@ module.exports = class ThangsTabView extends CocoView $(window).resize @onWindowResize @addThangsView = @insertSubView new AddThangsView world: @world, supermodel: @supermodel @buildInterface() # refactor to not have this trigger when this view re-renders? + if @thangsTreema.data.length + @$el.find('#canvas-overlay').css('display', 'none') onFilterExtantThangs: (e) -> @$el.find('#extant-thangs-filter button.active').button('toggle') @@ -233,6 +235,8 @@ module.exports = class ThangsTabView extends CocoView @addThang @addThangType, thang.pos, true @batchInsert() @selectAddThangType null + @$el.find('#canvas-overlay').css('display', 'none') + # TODO: figure out a good way to have all Surface clicks and Treema clicks just proxy in one direction, so we can maintain only one way of handling selection and deletion onExtantThangSelected: (e) -> @@ -473,11 +477,11 @@ module.exports = class ThangsTabView extends CocoView $('#add-thangs-column').toggle() @onWindowResize e - undoAction: (e) -> - @thangsTreema.undo() + undo: (e) -> + if not @editThangView then @thangsTreema.undo() else @editThangView.undo() - redoAction: (e) -> - @thangsTreema.redo() + redo: (e) -> + if not @editThangView then @thangsTreema.redo() else @editThangView.redo() class ThangsNode extends TreemaNode.nodeMap.array valueClass: 'treema-array-replacement' @@ -496,7 +500,7 @@ class ThangNode extends TreemaObjectNode s = "#{@data.thangType}" if isObjectID s unless name = ThangNode.thangNameMap[s] - thangType = _.find @settings.supermodel.getModels(ThangType), (m) -> m.get('original') is s + thangType = _.find @settings.supermodel.getModels(ThangType), (m) -> m.get('original') is s and m.get('kind') name = ThangNode.thangNameMap[s] = thangType.get 'name' ThangNode.thangKindMap[s] = thangType.get 'kind' kind = ThangNode.thangKindMap[s] diff --git a/app/views/editor/level/treema_nodes.coffee b/app/views/editor/level/treema_nodes.coffee index f06654698..92a40cdb8 100644 --- a/app/views/editor/level/treema_nodes.coffee +++ b/app/views/editor/level/treema_nodes.coffee @@ -1,4 +1,4 @@ -WorldSelectModal = require './modal/world_select' +WorldSelectModal = require './modals/WorldSelectModal' ThangType = require '/models/ThangType' makeButton = -> $('') diff --git a/app/views/editor/thang/colors_tab_view.coffee b/app/views/editor/thang/ThangTypeColorsTabView.coffee similarity index 98% rename from app/views/editor/thang/colors_tab_view.coffee rename to app/views/editor/thang/ThangTypeColorsTabView.coffee index b4a60e017..41876272e 100644 --- a/app/views/editor/thang/colors_tab_view.coffee +++ b/app/views/editor/thang/ThangTypeColorsTabView.coffee @@ -3,7 +3,7 @@ template = require 'templates/editor/thang/colors_tab' SpriteBuilder = require 'lib/sprites/SpriteBuilder' {hexToHSL} = require 'lib/utils' -module.exports = class ColorsTabView extends CocoView +module.exports = class ThangTypeColorsTabView extends CocoView id: 'editor-thang-colors-tab-view' template: template className: 'tab-pane' diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/ThangTypeEditView.coffee similarity index 96% rename from app/views/editor/thang/edit.coffee rename to app/views/editor/thang/ThangTypeEditView.coffee index b7d04b751..c9fd478bb 100644 --- a/app/views/editor/thang/edit.coffee +++ b/app/views/editor/thang/ThangTypeEditView.coffee @@ -6,11 +6,11 @@ Camera = require 'lib/surface/Camera' DocumentFiles = require 'collections/DocumentFiles' RootView = require 'views/kinds/RootView' -ThangComponentEditView = require 'views/editor/components/main' -VersionHistoryView = require './versions_view' -ColorsTabView = require './colors_tab_view' -PatchesView = require 'views/editor/patches_view' -SaveVersionModal = require 'views/modal/save_version_modal' +ThangComponentEditView = require 'views/editor/component/ThangComponentEditView' +ThangTypeVersionsModal = require './ThangTypeVersionsModal' +ThangTypeColorsTabView = require './ThangTypeColorsTabView' +PatchesView = require 'views/editor/PatchesView' +SaveVersionModal = require 'views/modal/SaveVersionModal' template = require 'templates/editor/thang/edit' CENTER = {x: 200, y: 300} @@ -73,7 +73,7 @@ module.exports = class ThangTypeEditView extends RootView @buildTreema() @initSliders() @initComponents() - @insertSubView(new ColorsTabView(@thangType)) + @insertSubView(new ThangTypeColorsTabView(@thangType)) @patchesView = @insertSubView(new PatchesView(@thangType), @$el.find('.patches-view')) @showReadOnly() if me.get('anonymous') @@ -400,8 +400,8 @@ module.exports = class ThangTypeEditView extends RootView @showingSelectedNode = false showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView thangType: @thangType, @thangTypeID - @openModalView versionHistoryView + versionHistoryModal = new ThangTypeVersionsModal thangType: @thangType, @thangTypeID + @openModalView versionHistoryModal Backbone.Mediator.publish 'level:view-switched', e openSaveModal: -> diff --git a/app/views/editor/thang/home.coffee b/app/views/editor/thang/ThangTypeSearchView.coffee similarity index 91% rename from app/views/editor/thang/home.coffee rename to app/views/editor/thang/ThangTypeSearchView.coffee index b14f1b9c4..c3b79b2bc 100644 --- a/app/views/editor/thang/home.coffee +++ b/app/views/editor/thang/ThangTypeSearchView.coffee @@ -1,6 +1,6 @@ SearchView = require 'views/kinds/SearchView' -module.exports = class ThangTypeHomeView extends SearchView +module.exports = class ThangTypeSearchView extends SearchView id: 'thang-type-home-view' modelLabel: 'Thang Type' model: require 'models/ThangType' diff --git a/app/views/editor/thang/versions_view.coffee b/app/views/editor/thang/ThangTypeVersionsModal.coffee similarity index 55% rename from app/views/editor/thang/versions_view.coffee rename to app/views/editor/thang/ThangTypeVersionsModal.coffee index 08344ce48..46bda96fc 100755 --- a/app/views/editor/thang/versions_view.coffee +++ b/app/views/editor/thang/ThangTypeVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class ComponentVersionsView extends VersionsModalView +module.exports = class ThangTypeVersionsModal extends VersionsModal id: 'editor-thang-versions-view' url: '/db/thang.type/' page: 'thang' diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee index 264e3539c..528d1d213 100644 --- a/app/views/kinds/CocoView.coffee +++ b/app/views/kinds/CocoView.coffee @@ -158,9 +158,9 @@ module.exports = class CocoView extends Backbone.View elem = $(e.target) return unless elem.data('toggle') is 'coco-modal' target = elem.data('target') - view = application.router.getView(target, '_modal') # could set up a system for loading cached modals, if told to + Modal = require 'views/'+target e.stopPropagation() - @openModalView(view) + @openModalView new Modal openModalView: (modalView, softly=false) -> return if waitingModal # can only have one waiting at once diff --git a/app/views/kinds/RootView.coffee b/app/views/kinds/RootView.coffee index 858c9fb48..f7bde789b 100644 --- a/app/views/kinds/RootView.coffee +++ b/app/views/kinds/RootView.coffee @@ -92,12 +92,12 @@ module.exports = class RootView extends CocoView logoutUser($('#login-email').val()) showWizardSettingsModal: -> - WizardSettingsModal = require('views/modal/wizard_settings_modal') + WizardSettingsModal = require('views/modal/WizardSettingsModal') subview = new WizardSettingsModal {} @openModalView subview onClickAuthbutton: -> - AuthModal = require 'views/modal/auth_modal' + AuthModal = require 'views/modal/AuthModal' @openModalView new AuthModal {} showLoading: ($el) -> @@ -152,7 +152,8 @@ module.exports = class RootView extends CocoView @saveLanguage(newLang) @render() unless newLang.split('-')[0] is 'en' - @openModalView(application.router.getView('modal/diplomat_suggestion', '_modal')) + DiplomatModal = require 'views/modal/DiplomatSuggestionModal' + @openModalView(new DiplomatModal()) saveLanguage: (newLang) -> me.set('preferredLanguage', newLang) diff --git a/app/views/modal/auth_modal.coffee b/app/views/modal/AuthModal.coffee similarity index 98% rename from app/views/modal/auth_modal.coffee rename to app/views/modal/AuthModal.coffee index ead7af8b9..ea7e4c771 100644 --- a/app/views/modal/auth_modal.coffee +++ b/app/views/modal/AuthModal.coffee @@ -5,7 +5,7 @@ forms = require 'lib/forms' User = require 'models/User' application = require 'application' -module.exports = class AuthModalView extends ModalView +module.exports = class AuthModal extends ModalView id: 'auth-modal' template: template mode: 'login' # or 'signup' diff --git a/app/views/modal/confirm.coffee b/app/views/modal/ConfirmModal.coffee similarity index 100% rename from app/views/modal/confirm.coffee rename to app/views/modal/ConfirmModal.coffee diff --git a/app/views/modal/contact_modal.coffee b/app/views/modal/ContactModal.coffee similarity index 94% rename from app/views/modal/contact_modal.coffee rename to app/views/modal/ContactModal.coffee index c8a6db460..99c47bd56 100644 --- a/app/views/modal/contact_modal.coffee +++ b/app/views/modal/ContactModal.coffee @@ -18,7 +18,7 @@ contactSchema = type: 'string' minLength: 1 -module.exports = class ContactView extends ModalView +module.exports = class ContactModal extends ModalView id: 'contact-modal' template: template closeButton: true diff --git a/app/views/modal/diplomat_suggestion_modal.coffee b/app/views/modal/DiplomatSuggestionModal.coffee similarity index 87% rename from app/views/modal/diplomat_suggestion_modal.coffee rename to app/views/modal/DiplomatSuggestionModal.coffee index c0abed5e7..e4071be20 100644 --- a/app/views/modal/diplomat_suggestion_modal.coffee +++ b/app/views/modal/DiplomatSuggestionModal.coffee @@ -3,7 +3,7 @@ template = require 'templates/modal/diplomat_suggestion' {me} = require 'lib/auth' forms = require 'lib/forms' -module.exports = class DiplomatSuggestionView extends ModalView +module.exports = class DiplomatSuggestionModal extends ModalView id: 'diplomat-suggestion-modal' template: template diff --git a/app/views/modal/employer_signup_modal.coffee b/app/views/modal/EmployerSignupModal.coffee similarity index 98% rename from app/views/modal/employer_signup_modal.coffee rename to app/views/modal/EmployerSignupModal.coffee index db766d979..65c9f1392 100644 --- a/app/views/modal/employer_signup_modal.coffee +++ b/app/views/modal/EmployerSignupModal.coffee @@ -5,7 +5,7 @@ User = require 'models/User' auth = require 'lib/auth' me = auth.me -module.exports = class EmployerSignupView extends ModalView +module.exports = class EmployerSignupModal extends ModalView id: 'employer-signup' template: template closeButton: true diff --git a/app/views/modal/job_profile_contact_modal.coffee b/app/views/modal/JobProfileContactModal.coffee similarity index 91% rename from app/views/modal/job_profile_contact_modal.coffee rename to app/views/modal/JobProfileContactModal.coffee index 0a933fe48..d8d011e63 100644 --- a/app/views/modal/job_profile_contact_modal.coffee +++ b/app/views/modal/JobProfileContactModal.coffee @@ -1,4 +1,4 @@ -ContactView = require 'views/modal/contact_modal' +ContactModal = require 'views/modal/ContactModal' template = require 'templates/modal/job_profile_contact' forms = require 'lib/forms' @@ -26,7 +26,7 @@ contactSchema = type: 'string' minLength: 1 -module.exports = class JobProfileContactView extends ContactView +module.exports = class JobProfileContactModal extends ContactModal id: 'job-profile-contact-modal' template: template diff --git a/app/views/modal/model_modal.coffee b/app/views/modal/ModelModal.coffee similarity index 100% rename from app/views/modal/model_modal.coffee rename to app/views/modal/ModelModal.coffee diff --git a/app/views/modal/recover_modal.coffee b/app/views/modal/RecoverModal.coffee similarity index 95% rename from app/views/modal/recover_modal.coffee rename to app/views/modal/RecoverModal.coffee index 5f8e9a17d..64cdd8154 100644 --- a/app/views/modal/recover_modal.coffee +++ b/app/views/modal/RecoverModal.coffee @@ -9,7 +9,7 @@ filterKeyboardEvents = (allowedEvents, func) -> return unless e.keyCode in allowedEvents or not e.keyCode return func(splat...) -module.exports = class RecoverModalView extends ModalView +module.exports = class RecoverModal extends ModalView id: 'recover-modal' template: template diff --git a/app/views/modal/revert_modal.coffee b/app/views/modal/RevertModal.coffee similarity index 100% rename from app/views/modal/revert_modal.coffee rename to app/views/modal/RevertModal.coffee diff --git a/app/views/modal/save_version_modal.coffee b/app/views/modal/SaveVersionModal.coffee similarity index 98% rename from app/views/modal/save_version_modal.coffee rename to app/views/modal/SaveVersionModal.coffee index 9edaaf859..9d682dd1c 100644 --- a/app/views/modal/save_version_modal.coffee +++ b/app/views/modal/SaveVersionModal.coffee @@ -1,6 +1,6 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/modal/save_version' -DeltaView = require 'views/editor/delta' +DeltaView = require 'views/editor/DeltaView' Patch = require 'models/Patch' forms = require 'lib/forms' diff --git a/app/views/modal/signup_modal.coffee b/app/views/modal/SignupModal.coffee similarity index 62% rename from app/views/modal/signup_modal.coffee rename to app/views/modal/SignupModal.coffee index 7c34cd6fe..93656f53a 100644 --- a/app/views/modal/signup_modal.coffee +++ b/app/views/modal/SignupModal.coffee @@ -1,4 +1,4 @@ -AuthModal = require 'views/modal/auth_modal' +AuthModal = require 'views/modal/AuthModal' module.exports = class SignupModalView extends AuthModal mode: 'signup' diff --git a/app/views/modal/versions_modal.coffee b/app/views/modal/VersionsModal.coffee similarity index 93% rename from app/views/modal/versions_modal.coffee rename to app/views/modal/VersionsModal.coffee index dfc7ec531..78eab024f 100755 --- a/app/views/modal/versions_modal.coffee +++ b/app/views/modal/VersionsModal.coffee @@ -1,8 +1,8 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/modal/versions' tableTemplate = require 'templates/kinds/table' -DeltaView = require 'views/editor/delta' -PatchModal = require 'views/editor/patch_modal' +DeltaView = require 'views/editor/DeltaView' +PatchModal = require 'views/editor/PatchModal' nameLoader = require 'lib/NameLoader' CocoCollection = require 'collections/CocoCollection' @@ -15,7 +15,7 @@ class VersionsViewCollection extends CocoCollection @url = url + levelID + '/versions' @model = model -module.exports = class VersionsModalView extends ModalView +module.exports = class VersionsModal extends ModalView template: template startsLoading: true plain: true diff --git a/app/views/modal/wizard_settings_modal.coffee b/app/views/modal/WizardSettingsModal.coffee similarity index 96% rename from app/views/modal/wizard_settings_modal.coffee rename to app/views/modal/WizardSettingsModal.coffee index d8527ee74..3e45663c0 100644 --- a/app/views/modal/wizard_settings_modal.coffee +++ b/app/views/modal/WizardSettingsModal.coffee @@ -21,7 +21,7 @@ module.exports = class WizardSettingsModal extends ModalView super options afterRender: -> - WizardSettingsView = require 'views/account/wizard_settings_view' + WizardSettingsView = require 'views/account/WizardSettingsView' view = new WizardSettingsView() @insertSubView view super() diff --git a/app/views/play/MainPlayView.coffee b/app/views/play/MainPlayView.coffee index 685887eab..c10205c8b 100644 --- a/app/views/play/MainPlayView.coffee +++ b/app/views/play/MainPlayView.coffee @@ -183,6 +183,14 @@ module.exports = class MainPlayView extends RootView description: 'Combat the armies of other Wizards in a strategic forest arena! (Fast computer required.)' levelPath: 'ladder' } + { + name: 'Sky Span (Testing)' + difficulty: 3 + id: 'sky-span' + image: '/file/db/level/526ae95c1e5cd30000000008/zone_of_danger_icon.png' + description: 'Preview version of an upgraded Dungeon Arena. Help us with hero balance before release!' + levelPath: 'ladder' + } ] playerCreated = [ diff --git a/app/views/play/spectate_view.coffee b/app/views/play/SpectateView.coffee similarity index 96% rename from app/views/play/spectate_view.coffee rename to app/views/play/SpectateView.coffee index de9cab929..4557893a8 100644 --- a/app/views/play/spectate_view.coffee +++ b/app/views/play/SpectateView.coffee @@ -20,16 +20,16 @@ Camera = require 'lib/surface/Camera' AudioPlayer = require 'lib/AudioPlayer' # subviews -LoadingView = require './level/level_loading_view' -TomeView = require './level/tome/tome_view' -ChatView = require './level/level_chat_view' -HUDView = require './level/hud_view' -ControlBarView = require './level/control_bar_view' -PlaybackView = require './level/playback_view' -GoalsView = require './level/goals_view' -GoldView = require './level/gold_view' -VictoryModal = require './level/modal/victory_modal' -InfiniteLoopModal = require './level/modal/infinite_loop_modal' +LoadingView = require './level/LevelLoadingView' +TomeView = require './level/tome/TomeView' +ChatView = require './level/LevelChatView' +HUDView = require './level/LevelHUDView' +ControlBarView = require './level/ControlBarView' +PlaybackView = require './level/LevelPlaybackView' +GoalsView = require './level/LevelGoalsView' +GoldView = require './level/LevelGoldView' +VictoryModal = require './level/modal/VictoryModal' +InfiniteLoopModal = require './level/modal/InfiniteLoopModal' PROFILE_ME = false @@ -135,9 +135,9 @@ module.exports = class SpectateLevelView extends RootView showGuide: -> @seenDocs = true - DocsModal = require './level/modal/docs_modal' + LevelGuideModal = require './level/modal/LevelGuideModal' options = {docs: @levelLoader.level.get('documentation'), supermodel: @supermodel} - @openModalView(new DocsModal(options), true) + @openModalView(new LevelGuideModal(options), true) Backbone.Mediator.subscribeOnce 'modal-closed', @onLevelLoaderLoaded, @ return true diff --git a/app/views/play/common/ladder_submission_view.coffee b/app/views/play/common/LadderSubmissionView.coffee similarity index 100% rename from app/views/play/common/ladder_submission_view.coffee rename to app/views/play/common/LadderSubmissionView.coffee diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/LadderPlayModal.coffee similarity index 100% rename from app/views/play/ladder/play_modal.coffee rename to app/views/play/ladder/LadderPlayModal.coffee diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/LadderTabView.coffee similarity index 99% rename from app/views/play/ladder/ladder_tab.coffee rename to app/views/play/ladder/LadderTabView.coffee index d0a7ff2a5..1780fa057 100644 --- a/app/views/play/ladder/ladder_tab.coffee +++ b/app/views/play/ladder/LadderTabView.coffee @@ -6,7 +6,7 @@ CocoCollection = require 'collections/CocoCollection' User = require 'models/User' LeaderboardCollection = require 'collections/LeaderboardCollection' {teamDataFromLevel} = require './utils' -ModelModal = require 'views/modal/model_modal' +ModelModal = require 'views/modal/ModelModal' HIGHEST_SCORE = 1000000 @@ -178,6 +178,7 @@ module.exports = class LadderTabView extends CocoView ctx.friends = @consolidateFriends() ctx.onFacebook = @facebookStatus is 'connected' ctx.onGPlus = application.gplusHandler.loggedIn + ctx.capitalize = _.string.capitalize ctx generateHistogram: (histogramElement, histogramData, teamName) -> diff --git a/app/views/play/ladder/ladder_view.coffee b/app/views/play/ladder/LadderView.coffee similarity index 92% rename from app/views/play/ladder/ladder_view.coffee rename to app/views/play/ladder/LadderView.coffee index 2fef77845..0e2d03e25 100644 --- a/app/views/play/ladder/ladder_view.coffee +++ b/app/views/play/ladder/LadderView.coffee @@ -6,10 +6,10 @@ CocoCollection = require 'collections/CocoCollection' {me} = require 'lib/auth' application = require 'application' -LadderTabView = require './ladder_tab' -MyMatchesTabView = require './my_matches_tab' -SimulateTabView = require './simulate_tab' -LadderPlayModal = require './play_modal' +LadderTabView = require './LadderTabView' +MyMatchesTabView = require './MyMatchesTabView' +SimulateTabView = require './SimulateTabView' +LadderPlayModal = require './LadderPlayModal' CocoClass = require 'lib/CocoClass' HIGHEST_SCORE = 1000000 @@ -92,8 +92,8 @@ module.exports = class LadderView extends RootView @openModalView modal showApologeticSignupModal: -> - SignupModal = require 'views/modal/auth_modal' - @openModalView(new SignupModal({showRequiredError: true})) + AuthModal = require 'views/modal/AuthModal' + @openModalView(new AuthModal({showRequiredError: true})) onClickedLink: (e) -> link = $(e.target).closest('a').attr('href') diff --git a/app/views/play/ladder_home.coffee b/app/views/play/ladder/MainLadderView.coffee similarity index 100% rename from app/views/play/ladder_home.coffee rename to app/views/play/ladder/MainLadderView.coffee diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/MyMatchesTabView.coffee similarity index 98% rename from app/views/play/ladder/my_matches_tab.coffee rename to app/views/play/ladder/MyMatchesTabView.coffee index b8f67e746..e0723a9ae 100644 --- a/app/views/play/ladder/my_matches_tab.coffee +++ b/app/views/play/ladder/MyMatchesTabView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' Level = require 'models/Level' LevelSession = require 'models/LevelSession' LeaderboardCollection = require 'collections/LeaderboardCollection' -LadderSubmissionView = require 'views/play/common/ladder_submission_view' +LadderSubmissionView = require 'views/play/common/LadderSubmissionView' {teamDataFromLevel} = require './utils' module.exports = class MyMatchesTabView extends CocoView diff --git a/app/views/play/ladder/simulate_tab.coffee b/app/views/play/ladder/SimulateTabView.coffee similarity index 100% rename from app/views/play/ladder/simulate_tab.coffee rename to app/views/play/ladder/SimulateTabView.coffee diff --git a/app/views/play/level/control_bar_view.coffee b/app/views/play/level/ControlBarView.coffee similarity index 91% rename from app/views/play/level/control_bar_view.coffee rename to app/views/play/level/ControlBarView.coffee index 18102be0f..15900fd53 100644 --- a/app/views/play/level/control_bar_view.coffee +++ b/app/views/play/level/ControlBarView.coffee @@ -1,9 +1,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/control_bar' -DocsModal = require './modal/docs_modal' -MultiplayerModal = require './modal/multiplayer_modal' -ReloadModal = require './modal/reload_modal' +LevelGuideModal = require './modal/LevelGuideModal' +MultiplayerModal = require './modal/MultiplayerModal' +ReloadLevelModal = require './modal/ReloadLevelModal' module.exports = class ControlBarView extends CocoView id: 'control-bar-view' @@ -76,7 +76,7 @@ module.exports = class ControlBarView extends CocoView showGuideModal: -> options = {docs: @level.get('documentation'), supermodel: @supermodel} - @openModalView(new DocsModal(options)) + @openModalView(new LevelGuideModal(options)) clearInterval @guideHighlightInterval @guideHighlightInterval = null @@ -84,4 +84,4 @@ module.exports = class ControlBarView extends CocoView @openModalView(new MultiplayerModal(session: @session, playableTeams: @playableTeams, level: @level, ladderGame: @ladderGame)) showRestartModal: -> - @openModalView(new ReloadModal()) + @openModalView(new ReloadLevelModal()) diff --git a/app/views/play/level/dialogue_animator.coffee b/app/views/play/level/DialogueAnimator.coffee similarity index 100% rename from app/views/play/level/dialogue_animator.coffee rename to app/views/play/level/DialogueAnimator.coffee diff --git a/app/views/play/level/level_chat_view.coffee b/app/views/play/level/LevelChatView.coffee similarity index 100% rename from app/views/play/level/level_chat_view.coffee rename to app/views/play/level/LevelChatView.coffee diff --git a/app/views/play/level/goals_view.coffee b/app/views/play/level/LevelGoalsView.coffee similarity index 98% rename from app/views/play/level/goals_view.coffee rename to app/views/play/level/LevelGoalsView.coffee index 1264ada34..f0388ccc1 100644 --- a/app/views/play/level/goals_view.coffee +++ b/app/views/play/level/LevelGoalsView.coffee @@ -8,7 +8,7 @@ stateIconMap = success: 'icon-ok' failure: 'icon-remove' -module.exports = class GoalsView extends CocoView +module.exports = class LevelGoalsView extends CocoView id: 'goals-view' template: template diff --git a/app/views/play/level/gold_view.coffee b/app/views/play/level/LevelGoldView.coffee similarity index 96% rename from app/views/play/level/gold_view.coffee rename to app/views/play/level/LevelGoldView.coffee index 479fe8966..414ac60b3 100644 --- a/app/views/play/level/gold_view.coffee +++ b/app/views/play/level/LevelGoldView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/gold' teamTemplate = require 'templates/play/level/team_gold' -module.exports = class GoldView extends CocoView +module.exports = class LevelGoldView extends CocoView id: 'gold-view' template: template diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/LevelHUDView.coffee similarity index 99% rename from app/views/play/level/hud_view.coffee rename to app/views/play/level/LevelHUDView.coffee index a730bedf9..975888025 100644 --- a/app/views/play/level/hud_view.coffee +++ b/app/views/play/level/LevelHUDView.coffee @@ -2,9 +2,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/hud' prop_template = require 'templates/play/level/hud_prop' action_template = require 'templates/play/level/hud_action' -DialogueAnimator = require './dialogue_animator' +DialogueAnimator = require './DialogueAnimator' -module.exports = class HUDView extends CocoView +module.exports = class LevelHUDView extends CocoView id: 'thang-hud' template: template dialogueMode: false diff --git a/app/views/play/level/level_loading_view.coffee b/app/views/play/level/LevelLoadingView.coffee similarity index 100% rename from app/views/play/level/level_loading_view.coffee rename to app/views/play/level/LevelLoadingView.coffee diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/LevelPlaybackView.coffee similarity index 98% rename from app/views/play/level/playback_view.coffee rename to app/views/play/level/LevelPlaybackView.coffee index f089e3c25..eb619ce06 100644 --- a/app/views/play/level/playback_view.coffee +++ b/app/views/play/level/LevelPlaybackView.coffee @@ -2,10 +2,10 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/playback' {me} = require 'lib/auth' -EditorConfigModal = require './modal/editor_config_modal' -KeyboardShortcutsModal = require './modal/keyboard_shortcuts_modal' +EditorConfigModal = require './modal/EditorConfigModal' +KeyboardShortcutsModal = require './modal/KeyboardShortcutsModal' -module.exports = class PlaybackView extends CocoView +module.exports = class LevelPlaybackView extends CocoView id: 'playback-view' template: template diff --git a/app/views/play/level_view.coffee b/app/views/play/level/PlayLevelView.coffee similarity index 96% rename from app/views/play/level_view.coffee rename to app/views/play/level/PlayLevelView.coffee index 010479b5f..f9de3019b 100644 --- a/app/views/play/level_view.coffee +++ b/app/views/play/level/PlayLevelView.coffee @@ -22,16 +22,16 @@ Camera = require 'lib/surface/Camera' AudioPlayer = require 'lib/AudioPlayer' # subviews -LoadingView = require './level/level_loading_view' -TomeView = require './level/tome/tome_view' -ChatView = require './level/level_chat_view' -HUDView = require './level/hud_view' -ControlBarView = require './level/control_bar_view' -PlaybackView = require './level/playback_view' -GoalsView = require './level/goals_view' -GoldView = require './level/gold_view' -VictoryModal = require './level/modal/victory_modal' -InfiniteLoopModal = require './level/modal/infinite_loop_modal' +LevelLoadingView = require './LevelLoadingView' +TomeView = require './tome/TomeView' +ChatView = require './LevelChatView' +HUDView = require './LevelHUDView' +ControlBarView = require './ControlBarView' +LevelPlaybackView = require './LevelPlaybackView' +GoalsView = require './LevelGoalsView' +GoldView = require './LevelGoldView' +VictoryModal = require './modal/VictoryModal' +InfiniteLoopModal = require './modal/InfiniteLoopModal' PROFILE_ME = false @@ -133,12 +133,12 @@ module.exports = class PlayLevelView extends RootView showGuide: -> @seenDocs = true - DocsModal = require './level/modal/docs_modal' + LevelGuideModal = require './modal/LevelGuideModal' options = docs: @levelLoader.level.get('documentation') supermodel: @supermodel firstOnly: true - @openModalView(new DocsModal(options), true) + @openModalView(new LevelGuideModal(options), true) onGuideOpened = -> @guideOpenTime = new Date() onGuideClosed = -> @@ -160,7 +160,7 @@ module.exports = class PlayLevelView extends RootView afterRender: -> super() window.onPlayLevelViewLoaded? @ # still a hack - @insertSubView @loadingView = new LoadingView {} + @insertSubView @loadingView = new LevelLoadingView {} @$el.find('#level-done-button').hide() $('body').addClass('is-playing') @@ -229,7 +229,7 @@ module.exports = class PlayLevelView extends RootView insertSubviews: -> @insertSubView @tome = new TomeView levelID: @levelID, session: @session, otherSession: @otherSession, thangs: @world.thangs, supermodel: @supermodel - @insertSubView new PlaybackView session: @session + @insertSubView new LevelPlaybackView session: @session @insertSubView new GoalsView {} @insertSubView new GoldView {} @insertSubView new HUDView {} diff --git a/app/views/play/level/thang_avatar_view.coffee b/app/views/play/level/ThangAvatarView.coffee similarity index 100% rename from app/views/play/level/thang_avatar_view.coffee rename to app/views/play/level/ThangAvatarView.coffee diff --git a/app/views/play/level/modal/editor_config_modal.coffee b/app/views/play/level/modal/EditorConfigModal.coffee similarity index 100% rename from app/views/play/level/modal/editor_config_modal.coffee rename to app/views/play/level/modal/EditorConfigModal.coffee diff --git a/app/views/play/level/modal/infinite_loop_modal.coffee b/app/views/play/level/modal/InfiniteLoopModal.coffee similarity index 100% rename from app/views/play/level/modal/infinite_loop_modal.coffee rename to app/views/play/level/modal/InfiniteLoopModal.coffee diff --git a/app/views/play/level/modal/keyboard_shortcuts_modal.coffee b/app/views/play/level/modal/KeyboardShortcutsModal.coffee similarity index 100% rename from app/views/play/level/modal/keyboard_shortcuts_modal.coffee rename to app/views/play/level/modal/KeyboardShortcutsModal.coffee diff --git a/app/views/play/level/modal/docs_modal.coffee b/app/views/play/level/modal/LevelGuideModal.coffee similarity index 96% rename from app/views/play/level/modal/docs_modal.coffee rename to app/views/play/level/modal/LevelGuideModal.coffee index a046df051..5ba7fe01a 100644 --- a/app/views/play/level/modal/docs_modal.coffee +++ b/app/views/play/level/modal/LevelGuideModal.coffee @@ -5,7 +5,7 @@ utils = require 'lib/utils' # let's implement this once we have the docs database schema set up -module.exports = class DocsModal extends ModalView +module.exports = class LevelGuideModal extends ModalView template: template id: 'docs-modal' diff --git a/app/views/play/level/modal/multiplayer_modal.coffee b/app/views/play/level/modal/MultiplayerModal.coffee similarity index 96% rename from app/views/play/level/modal/multiplayer_modal.coffee rename to app/views/play/level/modal/MultiplayerModal.coffee index 6645ca2f3..3a74f8489 100644 --- a/app/views/play/level/modal/multiplayer_modal.coffee +++ b/app/views/play/level/modal/MultiplayerModal.coffee @@ -1,7 +1,7 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/play/level/modal/multiplayer' {me} = require 'lib/auth' -LadderSubmissionView = require 'views/play/common/ladder_submission_view' +LadderSubmissionView = require 'views/play/common/LadderSubmissionView' module.exports = class MultiplayerModal extends ModalView id: 'level-multiplayer-modal' diff --git a/app/views/play/level/modal/reload_modal.coffee b/app/views/play/level/modal/ReloadLevelModal.coffee similarity index 84% rename from app/views/play/level/modal/reload_modal.coffee rename to app/views/play/level/modal/ReloadLevelModal.coffee index f7089e05c..cd3700325 100644 --- a/app/views/play/level/modal/reload_modal.coffee +++ b/app/views/play/level/modal/ReloadLevelModal.coffee @@ -3,7 +3,7 @@ template = require 'templates/play/level/modal/reload' # let's implement this once we have the docs database schema set up -module.exports = class ReloadModal extends ModalView +module.exports = class ReloadLevelModal extends ModalView id: '#reload-code-modal' template: template diff --git a/app/views/play/level/modal/victory_modal.coffee b/app/views/play/level/modal/VictoryModal.coffee similarity index 98% rename from app/views/play/level/modal/victory_modal.coffee rename to app/views/play/level/modal/VictoryModal.coffee index 03c8d72d8..172e6ad14 100644 --- a/app/views/play/level/modal/victory_modal.coffee +++ b/app/views/play/level/modal/VictoryModal.coffee @@ -1,7 +1,7 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/play/level/modal/victory' {me} = require 'lib/auth' -LadderSubmissionView = require 'views/play/common/ladder_submission_view' +LadderSubmissionView = require 'views/play/common/LadderSubmissionView' LevelFeedback = require 'models/LevelFeedback' utils = require 'lib/utils' diff --git a/app/views/play/level/tome/cast_button_view.coffee b/app/views/play/level/tome/CastButtonView.coffee similarity index 100% rename from app/views/play/level/tome/cast_button_view.coffee rename to app/views/play/level/tome/CastButtonView.coffee diff --git a/app/views/play/level/tome/doc_formatter.coffee b/app/views/play/level/tome/DocFormatter.coffee similarity index 100% rename from app/views/play/level/tome/doc_formatter.coffee rename to app/views/play/level/tome/DocFormatter.coffee diff --git a/app/views/play/level/tome/problem.coffee b/app/views/play/level/tome/Problem.coffee similarity index 96% rename from app/views/play/level/tome/problem.coffee rename to app/views/play/level/tome/Problem.coffee index 13fb7cede..5aaa1907d 100644 --- a/app/views/play/level/tome/problem.coffee +++ b/app/views/play/level/tome/Problem.coffee @@ -1,4 +1,4 @@ -ProblemAlertView = require './problem_alert_view' +ProblemAlertView = require './ProblemAlertView' Range = ace.require('ace/range').Range module.exports = class Problem diff --git a/app/views/play/level/tome/problem_alert_view.coffee b/app/views/play/level/tome/ProblemAlertView.coffee similarity index 95% rename from app/views/play/level/tome/problem_alert_view.coffee rename to app/views/play/level/tome/ProblemAlertView.coffee index 1756b2775..f90bab513 100644 --- a/app/views/play/level/tome/problem_alert_view.coffee +++ b/app/views/play/level/tome/ProblemAlertView.coffee @@ -32,6 +32,7 @@ module.exports = class ProblemAlertView extends CocoView afterRender: -> super() @$el.addClass('alert').addClass("alert-#{@problem.aetherProblem.level}").hide().fadeIn('slow') + @$el.addClass('no-hint') unless @problem.aetherProblem.hint Backbone.Mediator.publish 'play-sound', trigger: 'error_appear', volume: 1.0 onRemoveClicked: -> diff --git a/app/views/play/level/tome/spell.coffee b/app/views/play/level/tome/Spell.coffee similarity index 98% rename from app/views/play/level/tome/spell.coffee rename to app/views/play/level/tome/Spell.coffee index 72a897ee2..2f1b62d0e 100644 --- a/app/views/play/level/tome/spell.coffee +++ b/app/views/play/level/tome/Spell.coffee @@ -1,5 +1,5 @@ -SpellView = require './spell_view' -SpellListTabEntryView = require './spell_list_tab_entry_view' +SpellView = require './SpellView' +SpellListTabEntryView = require './SpellListTabEntryView' {me} = require 'lib/auth' Aether.addGlobal 'Vector', require 'lib/world/vector' diff --git a/app/views/play/level/tome/spell_debug_view.coffee b/app/views/play/level/tome/SpellDebugView.coffee similarity index 99% rename from app/views/play/level/tome/spell_debug_view.coffee rename to app/views/play/level/tome/SpellDebugView.coffee index 63e01f1b7..623e70d25 100644 --- a/app/views/play/level/tome/spell_debug_view.coffee +++ b/app/views/play/level/tome/SpellDebugView.coffee @@ -9,7 +9,7 @@ serializedClasses = Ellipse: require 'lib/world/ellipse' LineSegment: require 'lib/world/line_segment' -module.exports = class DebugView extends CocoView +module.exports = class SpellDebugView extends CocoView className: 'spell-debug-view' template: template diff --git a/app/views/play/level/tome/spell_list_entry_thangs_view.coffee b/app/views/play/level/tome/SpellListEntryThangsView.coffee similarity index 94% rename from app/views/play/level/tome/spell_list_entry_thangs_view.coffee rename to app/views/play/level/tome/SpellListEntryThangsView.coffee index eeba83590..6d730072b 100644 --- a/app/views/play/level/tome/spell_list_entry_thangs_view.coffee +++ b/app/views/play/level/tome/SpellListEntryThangsView.coffee @@ -1,5 +1,5 @@ CocoView = require 'views/kinds/CocoView' -ThangAvatarView = require 'views/play/level/thang_avatar_view' +ThangAvatarView = require 'views/play/level/ThangAvatarView' template = require 'templates/play/level/tome/spell_list_entry_thangs' module.exports = class SpellListEntryThangsView extends CocoView diff --git a/app/views/play/level/tome/spell_list_entry_view.coffee b/app/views/play/level/tome/SpellListEntryView.coffee similarity index 97% rename from app/views/play/level/tome/spell_list_entry_view.coffee rename to app/views/play/level/tome/SpellListEntryView.coffee index 05f18b23a..0ea75d5d4 100644 --- a/app/views/play/level/tome/spell_list_entry_view.coffee +++ b/app/views/play/level/tome/SpellListEntryView.coffee @@ -1,8 +1,8 @@ # TODO: This still needs a way to send problem states to its Thang CocoView = require 'views/kinds/CocoView' -ThangAvatarView = require 'views/play/level/thang_avatar_view' -SpellListEntryThangsView = require 'views/play/level/tome/spell_list_entry_thangs_view' +ThangAvatarView = require 'views/play/level/ThangAvatarView' +SpellListEntryThangsView = require 'views/play/level/tome/SpellListEntryThangsView' template = require 'templates/play/level/tome/spell_list_entry' module.exports = class SpellListEntryView extends CocoView diff --git a/app/views/play/level/tome/spell_list_tab_entry_view.coffee b/app/views/play/level/tome/SpellListTabEntryView.coffee similarity index 65% rename from app/views/play/level/tome/spell_list_tab_entry_view.coffee rename to app/views/play/level/tome/SpellListTabEntryView.coffee index 877229f54..68f946846 100644 --- a/app/views/play/level/tome/spell_list_tab_entry_view.coffee +++ b/app/views/play/level/tome/SpellListTabEntryView.coffee @@ -1,18 +1,22 @@ -SpellListEntryView = require './spell_list_entry_view' -ThangAvatarView = require 'views/play/level/thang_avatar_view' +SpellListEntryView = require './SpellListEntryView' +ThangAvatarView = require 'views/play/level/ThangAvatarView' template = require 'templates/play/level/tome/spell_list_tab_entry' LevelComponent = require 'models/LevelComponent' -DocFormatter = require './doc_formatter' +DocFormatter = require './DocFormatter' +filters = require 'lib/image_filter' module.exports = class SpellListTabEntryView extends SpellListEntryView template: template id: 'spell-list-tab-entry-view' subscriptions: + 'level-disable-controls': 'onDisableControls' + 'level-enable-controls': 'onEnableControls' 'tome:spell-loaded': 'onSpellLoaded' 'tome:spell-changed': 'onSpellChanged' 'god:new-world-created': 'onNewWorld' 'tome:spell-changed-language': 'onSpellChangedLanguage' + 'tome:fullscreen-view': 'onFullscreenClick' events: 'click .spell-list-button': 'onDropdownClick' @@ -30,6 +34,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView afterRender: -> super() @$el.addClass 'spell-tab' + @attachTransitionEventListener() onNewWorld: (e) -> @thang = e.world.thangMap[@thang.id] if @thang @@ -74,6 +79,8 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView onMouseEnterAvatar: (e) -> # Don't call super onMouseLeaveAvatar: (e) -> # Don't call super onClick: (e) -> # Don't call super + onDisableControls: (e) -> @toggleControls e, false + onEnableControls: (e) -> @toggleControls e, true onDropdownClick: (e) -> return unless @controlsEnabled @@ -88,12 +95,10 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView Backbone.Mediator.publish 'spell-beautify', spell: @spell onFullscreenClick: -> - unless $('.fullscreen-code').hasClass 'maximized' - $('#code-area').addClass 'fullscreen-editor' - $('.fullscreen-code').addClass 'maximized' - else - $('#code-area').removeClass 'fullscreen-editor' - $('.fullscreen-code').removeClass 'maximized' + $codearea = $('#code-area') + $codearea.css 'z-index', 20 unless $codearea.hasClass 'fullscreen-editor' + $('#code-area').toggleClass 'fullscreen-editor' + $('.fullscreen-code').toggleClass 'maximized' updateReloadButton: -> changed = @spell.hasChanged null, @spell.getSource() @@ -121,6 +126,33 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView return if enabled is @controlsEnabled @controlsEnabled = enabled @$el.toggleClass 'read-only', not enabled + @toggleBackground() + + toggleBackground: => + # TODO: make the palette background an actual background and do the CSS trick + # used in spell_list_entry.sass for disabling + background = @$el.find('img.spell-tab-image-hidden')[0] + if background.naturalWidth is 0 # not loaded yet + return _.delay @toggleBackground, 100 + filters.revertImage background, '.spell-list-entry-view.spell-tab' if @controlsEnabled + filters.darkenImage background, '.spell-list-entry-view.spell-tab', 0.8 unless @controlsEnabled + + attachTransitionEventListener: => + transitionListener = '' + testEl = document.createElement 'fakeelement' + transitions = + 'transition':'transitionend' + 'OTransition':'oTransitionEnd' + 'MozTransition':'transitionend' + 'WebkitTransition':'webkitTransitionEnd' + for transition, transitionEvent of transitions + unless testEl.style[transition] is undefined + transitionListener = transitionEvent + break + $codearea = $('#code-area') + $codearea.on transitionListener, => + $codearea.css 'z-index', 1 unless $codearea.hasClass 'fullscreen-editor' + destroy: -> @avatar?.destroy() diff --git a/app/views/play/level/tome/spell_list_view.coffee b/app/views/play/level/tome/SpellListView.coffee similarity index 98% rename from app/views/play/level/tome/spell_list_view.coffee rename to app/views/play/level/tome/SpellListView.coffee index 9212bd04f..febdbce12 100644 --- a/app/views/play/level/tome/spell_list_view.coffee +++ b/app/views/play/level/tome/SpellListView.coffee @@ -7,7 +7,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/spell_list' {me} = require 'lib/auth' -SpellListEntryView = require './spell_list_entry_view' +SpellListEntryView = require './SpellListEntryView' module.exports = class SpellListView extends CocoView className: 'spell-list-view' diff --git a/app/views/play/level/tome/spell_palette_entry_view.coffee b/app/views/play/level/tome/SpellPaletteEntryView.coffee similarity index 98% rename from app/views/play/level/tome/spell_palette_entry_view.coffee rename to app/views/play/level/tome/SpellPaletteEntryView.coffee index e09116876..3b7f53c71 100644 --- a/app/views/play/level/tome/spell_palette_entry_view.coffee +++ b/app/views/play/level/tome/SpellPaletteEntryView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/spell_palette_entry' {me} = require 'lib/auth' filters = require 'lib/image_filter' -DocFormatter = require './doc_formatter' +DocFormatter = require './DocFormatter' module.exports = class SpellPaletteEntryView extends CocoView tagName: 'div' # Could also try instead of
, but would need to adjust colors diff --git a/app/views/play/level/tome/spell_palette_view.coffee b/app/views/play/level/tome/SpellPaletteView.coffee similarity index 89% rename from app/views/play/level/tome/spell_palette_view.coffee rename to app/views/play/level/tome/SpellPaletteView.coffee index 89914fb3e..769cd8f92 100644 --- a/app/views/play/level/tome/spell_palette_view.coffee +++ b/app/views/play/level/tome/SpellPaletteView.coffee @@ -2,9 +2,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/spell_palette' {me} = require 'lib/auth' filters = require 'lib/image_filter' -SpellPaletteEntryView = require './spell_palette_entry_view' +SpellPaletteEntryView = require './SpellPaletteEntryView' LevelComponent = require 'models/LevelComponent' -EditorConfigModal = require '../modal/editor_config_modal' +EditorConfigModal = require '../modal/EditorConfigModal' N_ROWS = 4 @@ -84,13 +84,16 @@ module.exports = class SpellPaletteView extends CocoView snippets: 'programmableSnippets' else propStorage = - 'this': 'apiProperties' + 'this': ['apiProperties', 'apiMethods'] count = 0 propGroups = {} - for owner, storage of propStorage - props = _.reject @thang[storage] ? [], (prop) -> prop[0] is '_' # no private properties - added = propGroups[owner] = _.sortBy(props).slice() - count += added.length + for owner, storages of propStorage + storages = [storages] if _.isString storages + for storage in storages + props = _.reject @thang[storage] ? [], (prop) -> prop[0] is '_' # no private properties + added = _.sortBy(props).slice() + propGroups[owner] = (propGroups[owner] ? []).concat added + count += added.length shortenize = count > 6 tabbify = count >= 10 @@ -150,11 +153,11 @@ module.exports = class SpellPaletteView extends CocoView toggleBackground: => # TODO: make the palette background an actual background and do the CSS trick # used in spell_list_entry.sass for disabling - background = @$el.find('.code-palette-background')[0] + background = @$el.find('img.code-palette-background')[0] if background.naturalWidth is 0 # not loaded yet return _.delay @toggleBackground, 100 - filters.revertImage background if @controlsEnabled - filters.darkenImage background, 0.8 unless @controlsEnabled + filters.revertImage background, 'span.code-palette-background' if @controlsEnabled + filters.darkenImage background, 'span.code-palette-background', 0.8 unless @controlsEnabled onFrameChanged: (e) -> return unless e.selectedThang?.id is @thang.id diff --git a/app/views/play/level/tome/spell_toolbar_view.coffee b/app/views/play/level/tome/SpellToolbarView.coffee similarity index 100% rename from app/views/play/level/tome/spell_toolbar_view.coffee rename to app/views/play/level/tome/SpellToolbarView.coffee diff --git a/app/views/play/level/tome/spell_view.coffee b/app/views/play/level/tome/SpellView.coffee similarity index 98% rename from app/views/play/level/tome/spell_view.coffee rename to app/views/play/level/tome/SpellView.coffee index 46fb62e4e..ee979cc38 100644 --- a/app/views/play/level/tome/spell_view.coffee +++ b/app/views/play/level/tome/SpellView.coffee @@ -3,9 +3,9 @@ template = require 'templates/play/level/tome/spell' {me} = require 'lib/auth' filters = require 'lib/image_filter' Range = ace.require('ace/range').Range -Problem = require './problem' -SpellDebugView = require './spell_debug_view' -SpellToolbarView = require './spell_toolbar_view' +Problem = require './Problem' +SpellDebugView = require './SpellDebugView' +SpellToolbarView = require './SpellToolbarView' LevelComponent = require 'models/LevelComponent' module.exports = class SpellView extends CocoView @@ -167,6 +167,10 @@ module.exports = class SpellView extends CocoView bindKey: {win: 'Ctrl-L', mac: 'Command-L'} passEvent: true exec: -> # just prevent default ACE go-to-line alert + addCommand + name: 'open-fullscreen-editor' + bindKey: {win: 'Alt-Shift-F', mac: 'Ctrl-Shift-F'} + exec: -> Backbone.Mediator.publish 'tome:fullscreen-view' fillACE: -> @ace.setValue @spell.source @@ -630,11 +634,11 @@ module.exports = class SpellView extends CocoView toggleBackground: => # TODO: make the background an actual background and do the CSS trick # used in spell_list_entry.sass for disabling - background = @$el.find('.code-background')[0] + background = @$el.find('img.code-background')[0] if background.naturalWidth is 0 # not loaded yet return _.delay @toggleBackground, 100 - filters.revertImage background if @controlsEnabled - filters.darkenImage background, 0.8 unless @controlsEnabled + filters.revertImage background, 'span.code-background' if @controlsEnabled + filters.darkenImage background, 'span.code-background', 0.8 unless @controlsEnabled onSpellBeautify: (e) -> return unless @spellThang and (@ace.isFocused() or e.spell is @spell) diff --git a/app/views/play/level/tome/thang_list_entry_view.coffee b/app/views/play/level/tome/ThangListEntryView.coffee similarity index 98% rename from app/views/play/level/tome/thang_list_entry_view.coffee rename to app/views/play/level/tome/ThangListEntryView.coffee index 06756c898..442dbe0e9 100644 --- a/app/views/play/level/tome/thang_list_entry_view.coffee +++ b/app/views/play/level/tome/ThangListEntryView.coffee @@ -2,7 +2,7 @@ # TODO: reordering based on errors isn't working yet CocoView = require 'views/kinds/CocoView' -ThangAvatarView = require 'views/play/level/thang_avatar_view' +ThangAvatarView = require 'views/play/level/ThangAvatarView' template = require 'templates/play/level/tome/thang_list_entry' spellsPopoverTemplate = require 'templates/play/level/tome/thang_list_entry_spells' {me} = require 'lib/auth' diff --git a/app/views/play/level/tome/thang_list_view.coffee b/app/views/play/level/tome/ThangListView.coffee similarity index 98% rename from app/views/play/level/tome/thang_list_view.coffee rename to app/views/play/level/tome/ThangListView.coffee index 9f34e2977..03ab371c1 100644 --- a/app/views/play/level/tome/thang_list_view.coffee +++ b/app/views/play/level/tome/ThangListView.coffee @@ -4,7 +4,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/thang_list' {me} = require 'lib/auth' -ThangListEntryView = require './thang_list_entry_view' +ThangListEntryView = require './ThangListEntryView' module.exports = class ThangListView extends CocoView className: 'thang-list-view' diff --git a/app/views/play/level/tome/tome_view.coffee b/app/views/play/level/tome/TomeView.coffee similarity index 97% rename from app/views/play/level/tome/tome_view.coffee rename to app/views/play/level/tome/TomeView.coffee index 3ef45258c..e0335cd70 100644 --- a/app/views/play/level/tome/tome_view.coffee +++ b/app/views/play/level/tome/TomeView.coffee @@ -30,11 +30,11 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/tome' {me} = require 'lib/auth' -Spell = require './spell' -SpellListView = require './spell_list_view' -ThangListView = require './thang_list_view' -SpellPaletteView = require './spell_palette_view' -CastButtonView = require './cast_button_view' +Spell = require './Spell' +SpellListView = require './SpellListView' +ThangListView = require './ThangListView' +SpellPaletteView = require './SpellPaletteView' +CastButtonView = require './CastButtonView' window.SHIM_WORKER_PATH = '/javascripts/workers/catiline_worker_shim.js' diff --git a/bower.json b/bower.json index e979e2f49..32c815408 100644 --- a/bower.json +++ b/bower.json @@ -44,7 +44,7 @@ "bootstrap": "~3.1.1", "validated-backbone-mediator": "~0.1.3", "jquery.browser": "~0.0.6", - "zatanna": "~0.0.2", + "zatanna": "~0.0.4", "modernizr": "~2.8.3" }, "overrides": { diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee index 9dfca705b..55b45884f 100644 --- a/server/commons/Handler.coffee +++ b/server/commons/Handler.coffee @@ -13,12 +13,20 @@ FETCH_LIMIT = 200 module.exports = class Handler # subclasses should override these properties modelClass: null + privateProperties: [] editableProperties: [] postEditableProperties: [] jsonSchema: {} waterfallFunctions: [] allowedMethods: ['GET', 'POST', 'PUT', 'PATCH'] + constructor: -> + # TODO The second 'or' is for backward compatibility only is for backward compatibility only + @privateProperties = @modelClass.privateProperties or @privateProperties or [] + @editableProperties = @modelClass.editableProperties or @editableProperties or [] + @postEditableProperties = @modelClass.postEditableProperties or @postEditableProperties or [] + @jsonSchema = @modelClass.jsonSchema or @jsonSchema or {} + # subclasses should override these methods hasAccess: (req) -> true hasAccessToDocument: (req, document, method=null) -> @@ -47,7 +55,7 @@ module.exports = class Handler # sending functions sendUnauthorizedError: (res) -> errors.forbidden(res) #TODO: rename sendUnauthorizedError to sendForbiddenError - sendNotFoundError: (res) -> errors.notFound(res) + sendNotFoundError: (res, message) -> errors.notFound(res, message) sendMethodNotAllowed: (res) -> errors.badMethod(res) sendBadInputError: (res, message) -> errors.badInput(res, message) sendDatabaseError: (res, err) -> @@ -158,7 +166,7 @@ module.exports = class Handler ids = ids.split(',') if _.isString ids ids = _.uniq ids - project = {name:1, original:1} + project = {name:1, original:1, kind:1} sort = {'version.major':-1, 'version.minor':-1} makeFunc = (id) => @@ -435,3 +443,10 @@ module.exports = class Handler delete: (req, res) -> @sendMethodNotAllowed res, @allowedMethods, 'DELETE not allowed.' head: (req, res) -> @sendMethodNotAllowed res, @allowedMethods, 'HEAD not allowed.' + + # This is not a Mongoose user + projectionForUser: (req, model, ownerID) -> + return {} if 'privateProperties' not of model or req.user._id + '' is ownerID + '' or req.user.isAdmin() + projection = {} + projection[field] = 0 for field in model.privateProperties + projection diff --git a/server/levels/sessions/LevelSession.coffee b/server/levels/sessions/LevelSession.coffee index 4873e40a5..b8f0a58dc 100644 --- a/server/levels/sessions/LevelSession.coffee +++ b/server/levels/sessions/LevelSession.coffee @@ -24,4 +24,10 @@ LevelSessionSchema.pre 'save', (next) -> @set('changed', new Date()) next() +LevelSessionSchema.statics.privateProperties = ['code', 'submittedCode', 'unsubscribed'] +LevelSessionSchema.statics.editableProperties = ['multiplayer', 'players', 'code', 'codeLanguage', 'completed', 'state', + 'levelName', 'creatorName', 'levelID', 'screenshot', + 'chat', 'teamSpells', 'submitted', 'submittedCodeLanguage', 'unsubscribed', 'playtime'] +LevelSessionSchema.statics.jsonSchema = jsonschema + module.exports = LevelSession = mongoose.model('level.session', LevelSessionSchema) diff --git a/server/levels/sessions/level_session_handler.coffee b/server/levels/sessions/level_session_handler.coffee index b1179acf8..678b33e80 100644 --- a/server/levels/sessions/level_session_handler.coffee +++ b/server/levels/sessions/level_session_handler.coffee @@ -6,11 +6,6 @@ TIMEOUT = 1000 * 30 # no activity for 30 seconds means it's not active class LevelSessionHandler extends Handler modelClass: LevelSession - editableProperties: ['multiplayer', 'players', 'code', 'codeLanguage', 'completed', 'state', - 'levelName', 'creatorName', 'levelID', 'screenshot', - 'chat', 'teamSpells', 'submitted', 'submittedCodeLanguage', 'unsubscribed', 'playtime'] - privateProperties: ['code', 'submittedCode', 'unsubscribed'] - jsonSchema: require '../../../app/schemas/models/level_session' getByRelationship: (req, res, args...) -> return @getActiveSessions req, res if args.length is 2 and args[1] is 'active' diff --git a/server/plugins/plugins.coffee b/server/plugins/plugins.coffee index 2fdce3bef..7d7911ae2 100644 --- a/server/plugins/plugins.coffee +++ b/server/plugins/plugins.coffee @@ -30,6 +30,9 @@ module.exports.NamedPlugin = (schema) -> schema.add({name: String, slug: String}) schema.index({'slug': 1}, {unique: true, sparse: true, name: 'slug index'}) + schema.statics.getBySlug = (slug, done) -> + @findOne {slug: slug}, done + schema.pre('save', (next) -> if schema.uses_coco_versions v = @get('version') diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee index d35ce871a..d6aa6f3cb 100644 --- a/server/queues/scoring.coffee +++ b/server/queues/scoring.coffee @@ -124,7 +124,7 @@ module.exports.getTwoGames = (req, res) -> #if userIsAnonymous req then return errors.unauthorized(res, 'You need to be logged in to get games.') humansGameID = req.body.humansGameID ogresGameID = req.body.ogresGameID - ladderGameIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush'] + ladderGameIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush', 'sky-span'] levelID = _.sample ladderGameIDs unless ogresGameID and humansGameID #fetch random games here diff --git a/server/users/User.coffee b/server/users/User.coffee index 13f4c11fb..0372d073c 100644 --- a/server/users/User.coffee +++ b/server/users/User.coffee @@ -158,6 +158,18 @@ UserSchema.statics.hashPassword = (password) -> shasum.update(salt + password) shasum.digest('hex') +UserSchema.statics.privateProperties = [ + 'permissions', 'email', 'firstName', 'lastName', 'gender', 'facebookID', + 'gplusID', 'music', 'volume', 'aceConfig', 'employerAt', 'signedEmployerAgreement' +] +UserSchema.statics.jsonSchema = jsonschema +UserSchema.statics.editableProperties = [ + 'name', 'photoURL', 'password', 'anonymous', 'wizardColor1', 'volume', + 'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails', + 'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage', + 'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile', 'savedEmployerFilterAlerts' +] + UserSchema.plugin plugins.NamedPlugin module.exports = User = mongoose.model('User', UserSchema) diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee index 4a6e85320..a450951b0 100644 --- a/server/users/user_handler.coffee +++ b/server/users/user_handler.coffee @@ -14,37 +14,26 @@ EarnedAchievement = require '../achievements/EarnedAchievement' UserRemark = require './remarks/UserRemark' serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset'] -privateProperties = [ - 'permissions', 'email', 'firstName', 'lastName', 'gender', 'facebookID', - 'gplusID', 'music', 'volume', 'aceConfig', 'employerAt', 'signedEmployerAgreement' -] candidateProperties = [ 'jobProfile', 'jobProfileApproved', 'jobProfileNotes' ] UserHandler = class UserHandler extends Handler modelClass: User - jsonSchema: schema - editableProperties: [ - 'name', 'photoURL', 'password', 'anonymous', 'wizardColor1', 'volume', - 'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails', - 'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage', - 'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile', 'savedEmployerFilterAlerts' - ] getEditableProperties: (req, document) -> props = super req, document props.push 'permissions' unless config.isProduction props.push 'jobProfileApproved', 'jobProfileNotes','jobProfileApprovedDate' if req.user.isAdmin() # Admins naturally edit these - props.push privateProperties... if req.user.isAdmin() # Admins are mad with power + props.push @privateProperties... if req.user.isAdmin() # Admins are mad with power props - formatEntity: (req, document) -> + formatEntity: (req, document) => return null unless document? obj = document.toObject() delete obj[prop] for prop in serverProperties includePrivates = req.user and (req.user.isAdmin() or req.user._id.equals(document._id)) - delete obj[prop] for prop in privateProperties unless includePrivates + delete obj[prop] for prop in @privateProperties unless includePrivates includeCandidate = includePrivates or (obj.jobProfile?.active and req.user and ('employer' in (req.user.get('permissions') ? [])) and @employerCanViewCandidate req.user, obj) delete obj[prop] for prop in candidateProperties unless includeCandidate return obj @@ -239,31 +228,40 @@ UserHandler = class UserHandler extends Handler documents = (LevelSessionHandler.formatEntity(req, doc) for doc in documents) @sendSuccess(res, documents) - getLevelSessions: (req, res, userID) -> - query = creator: userID - isAuthorized = req.user._id+'' is userID or req.user.isAdmin() - projection = {} - if req.query.project - projection[field] = 1 for field in req.query.project.split(',') when isAuthorized or not (field in LevelSessionHandler.privateProperties) - else unless isAuthorized - projection[field] = 0 for field in LevelSessionHandler.privateProperties + IDify: (idOrSlug, done) -> + return done null, idOrSlug if Handler.isID idOrSlug + User.getBySlug idOrSlug, (err, user) -> done err, user?.get '_id' - LevelSession.find(query).select(projection).exec (err, documents) => - return @sendDatabaseError(res, err) if err - documents = (LevelSessionHandler.formatEntity(req, doc) for doc in documents) - @sendSuccess(res, documents) + getLevelSessions: (req, res, userIDOrSlug) -> + @IDify userIDOrSlug, (err, userID) => + return @sendDatabaseError res, err if err + return @sendNotFoundError res unless userID? + query = creator: userID + '' + isAuthorized = req.user._id+'' is userID or req.user.isAdmin() + projection = {} + if req.query.project + projection[field] = 1 for field in req.query.project.split(',') when isAuthorized or not (field in LevelSessionHandler.privateProperties) + else unless isAuthorized + projection[field] = 0 for field in LevelSessionHandler.privateProperties - getEarnedAchievements: (req, res, userID) -> - queryObject = {$query: {user: userID}, $orderby: {changed: -1}} - queryObject.$query.notified = false if req.query.notified is 'false' - query = EarnedAchievement.find(queryObject) - query.exec (err, documents) => - return @sendDatabaseError(res, err) if err? - cleandocs = (@formatEntity(req, doc) for doc in documents) - for doc in documents # Maybe move this logic elsewhere - doc.set('notified', true) - doc.save() - @sendSuccess(res, cleandocs) + LevelSession.find(query).select(projection).exec (err, documents) => + return @sendDatabaseError(res, err) if err + documents = (LevelSessionHandler.formatEntity(req, doc) for doc in documents) + @sendSuccess(res, documents) + + getEarnedAchievements: (req, res, userIDOrSlug) -> + @IDify userIDOrSlug, (err, userID) => + return @sendDatabaseError res, err if err + return @sendNotFoundError res unless userID? + query = user: userID + '' + query.notified = false if req.query.notified is 'false' + EarnedAchievement.find(query).sort(changed: -1).exec (err, documents) => + return @sendDatabaseError(res, err) if err? + cleandocs = (@formatEntity(req, doc) for doc in documents) + for doc in documents # TODO Ruben Maybe move this logic elsewhere + doc.set('notified', true) + doc.save() + @sendSuccess(res, cleandocs) trackActivity: (req, res, userID, activityName, increment=1) -> return @sendMethodNotAllowed res unless req.method is 'POST' diff --git a/test/app/models/Level.spec.coffee b/test/app/models/Level.spec.coffee new file mode 100644 index 000000000..db90afd8d --- /dev/null +++ b/test/app/models/Level.spec.coffee @@ -0,0 +1,52 @@ +SuperModel = require 'models/SuperModel' +Level = require 'models/Level' +ThangType = require 'models/ThangType' + +describe 'Level', -> + describe 'denormalize', -> + level = new Level({ + thangs: [ + { + "thangType": "A" + "id": "Tharin" + "components": [ + {"original": "a", "majorVersion": 0} + {"original": "b", "majorVersion": 0, "config": {i: 2}} + {"original": "c", "majorVersion": 0, "config": {i: 1, ii: 2, nest: {iii: 3}}} + # should add one more + ] + } + ] + }) + + thangType = new ThangType({ + original: 'A' + version: {major: 0, minor: 0} + components: [ + {"original": "a", "majorVersion": 0, "config": {i: 1}} + {"original": "c", "majorVersion": 0, "config": {i: 3, nest: {iv: 4}}} + {"original": "d", "majorVersion": 0, "config": {i: 1}} + ] + }) + + supermodel = new SuperModel() + supermodel.registerModel(thangType) + + result = level.denormalize(supermodel) + tharinThangComponents = result.thangs[0].components + + it 'adds default configs to thangs without any config', -> + aComp = _.find tharinThangComponents, {original:'a'} + expect(_.isEqual(aComp.config, {i:1})).toBeTruthy() + + it 'leaves alone configs for components the level thang has but the thang type does not', -> + bComp = _.find tharinThangComponents, {original:'b'} + expect(_.isEqual(bComp.config, {i:2})).toBeTruthy() + + it 'merges configs where both the level thang and thang type have one, giving priority to the level thang', -> + cComp = _.find tharinThangComponents, {original:'c'} + expect(_.isEqual(cComp.config, {i: 1, ii: 2, nest: {iii: 3, iv: 4}})).toBeTruthy() + + it 'adds components from the thang type that do not exist in the level thang', -> + dComp = _.find tharinThangComponents, {original:'d'} + expect(_.isEqual(dComp.config, {i: 1})).toBeTruthy() \ No newline at end of file diff --git a/test/app/require.spec.coffee b/test/app/require.spec.coffee new file mode 100644 index 000000000..33ebcf846 --- /dev/null +++ b/test/app/require.spec.coffee @@ -0,0 +1,9 @@ +describe 'require', -> + it 'has no modules that error when you import them', -> + modules = window.require.list() + for module in modules + try + require(module) + catch + console.error 'Could not load', module + expect(false).toBe(true) \ No newline at end of file diff --git a/test/app/vendor/lodash.spec.coffee b/test/app/vendor/lodash.spec.coffee new file mode 100644 index 000000000..cbc5b6766 --- /dev/null +++ b/test/app/vendor/lodash.spec.coffee @@ -0,0 +1,23 @@ +describe 'merge', -> + it 'combines nested objects recursively', -> + a = { i: 0, nest: { iii: 0 }} + b = { ii: 0, nest: { iv: 0 }} + res = _.merge(a, b) + expect(_.isEqual(res, { i: 0, ii: 0, nest: {iii:0, iv:0}})).toBeTruthy() + + it 'overwrites values from source to object', -> + a = { i: 0 } + b = { i: 1 } + res = _.merge(a, b) + expect(_.isEqual(res, b)).toBeTruthy() + + it 'treats arrays as atomic', -> + a = { i: 0 } + b = { i: [1,2,3] } + res = _.merge(a, b) + expect(_.isEqual(res, b)).toBeTruthy() + + a = { i: [5,4,3] } + b = { i: [1,2,3] } + res = _.merge(a, b) + expect(_.isEqual(res, b)).toBeTruthy() \ No newline at end of file diff --git a/test/app/views/editor/level/EditorLevelView.spec.coffee b/test/app/views/editor/level/EditorLevelView.spec.coffee index 47b32700f..7a9064993 100644 --- a/test/app/views/editor/level/EditorLevelView.spec.coffee +++ b/test/app/views/editor/level/EditorLevelView.spec.coffee @@ -1,11 +1,11 @@ -EditorLevelView = require 'views/editor/level/edit' +LevelEditView = require 'views/editor/level/LevelEditView' emptyLevel = {'_id': '53a0a1e2d9048dbc3a793c81', 'name': 'Emptiness', 'description': 'Tis nothing..', 'documentation': {'generalArticles': [], 'specificArticles': []}, 'scripts': [], 'thangs': [], 'systems': [], 'victory': {}, 'version': {'minor': 0, 'major': 0, 'isLatestMajor': true, 'isLatestMinor': true}, 'index': '5388f9ac9a904d0000d94f87', 'slug': 'emptiness', 'creator': '5388f9ac9a904d0000d94f87', 'original': '53a0a1e2d9048dbc3a793c81', 'watchers': ['5388f9ac9a904d0000d94f87'], '__v': 0, 'created': '2014-06-17T20:15:30.207Z', 'permissions': [{'access': 'owner', 'target': '5388f9ac9a904d0000d94f87'}]} -describe 'EditorLevelView', -> +describe 'LevelEditView', -> describe 'revert button', -> it 'opens just one modal when you click it', -> - view = new EditorLevelView({}, 'something') + view = new LevelEditView({}, 'something') request = jasmine.Ajax.requests.first() request.response {status: 200, responseText: JSON.stringify(emptyLevel)} view.render() diff --git a/test/app/views/home_view.spec.coffee b/test/app/views/home_view.spec.coffee deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/app/views/modal/AuthModalView.spec.coffee b/test/app/views/modal/AuthModal.spec.coffee similarity index 53% rename from test/app/views/modal/AuthModalView.spec.coffee rename to test/app/views/modal/AuthModal.spec.coffee index 01bd1b98e..199b265f4 100644 --- a/test/app/views/modal/AuthModalView.spec.coffee +++ b/test/app/views/modal/AuthModal.spec.coffee @@ -1,12 +1,12 @@ -AuthModalView = require 'views/modal/auth_modal' -RecoverModalView = require 'views/modal/recover_modal' +AuthModal = require 'views/modal/AuthModal' +RecoverModal = require 'views/modal/RecoverModal' -describe 'AuthModalView', -> +describe 'AuthModal', -> it 'opens the recover modal when you click the recover link', -> - m = new AuthModalView() + m = new AuthModal() m.render() spyOn(m, 'openModalView') m.$el.find('#link-to-recover').click() expect(m.openModalView.calls.count()).toEqual(1) args = m.openModalView.calls.argsFor(0) - expect(args[0] instanceof RecoverModalView).toBeTruthy() + expect(args[0] instanceof RecoverModal).toBeTruthy() diff --git a/test/app/views/play/ladder/ladder_tab.spec.coffee b/test/app/views/play/ladder/LadderTabView.coffee similarity index 91% rename from test/app/views/play/ladder/ladder_tab.spec.coffee rename to test/app/views/play/ladder/LadderTabView.coffee index 0f74b341b..e23fc26be 100644 --- a/test/app/views/play/ladder/ladder_tab.spec.coffee +++ b/test/app/views/play/ladder/LadderTabView.coffee @@ -1,4 +1,4 @@ -LadderTabView = require 'views/play/ladder/ladder_tab' +LadderTabView = require 'views/play/ladder/LadderTabView' Level = require 'models/Level' fixtures = require 'test/app/fixtures/levels' diff --git a/test/demo/views/user/JobProfileView.demo.coffee b/test/demo/views/user/JobProfileView.demo.coffee index 17ac8767b..5ab643f87 100644 --- a/test/demo/views/user/JobProfileView.demo.coffee +++ b/test/demo/views/user/JobProfileView.demo.coffee @@ -1,4 +1,4 @@ -ProfileView = require 'views/account/profile_view' +JobProfileView = require 'views/account/JobProfileView' responses = '/db/user/joe/nameToID':'512ef4805a67a8c507000001' @@ -564,7 +564,7 @@ responses = module.exports = -> me.isAdmin = -> false me.set('permissions', ['employer']) - v = new ProfileView({}, 'joe') + v = new JobProfileView({}, 'joe') for url, responseBody of responses requests = jasmine.Ajax.requests.filter(url) if not requests.length diff --git a/test/server/functional/level_session.spec.coffee b/test/server/functional/level_session.spec.coffee index ba0265cf0..eddb3407c 100644 --- a/test/server/functional/level_session.spec.coffee +++ b/test/server/functional/level_session.spec.coffee @@ -1,12 +1,64 @@ require '../common' -describe 'LevelFeedback', -> +describe '/db/level.session', -> - url = getURL('/db/level.session') + url = getURL('/db/level.session/') + session = + permissions: simplePermissions it 'get schema', (done) -> - request.get {uri: url+'/schema'}, (err, res, body) -> + request.get {uri: url+'schema'}, (err, res, body) -> expect(res.statusCode).toBe(200) body = JSON.parse(body) expect(body.type).toBeDefined() done() + + it 'clears things first', (done) -> + clearModels [LevelSession], (err) -> + expect(err).toBeNull() + done() + + # TODO Tried to mimic what happens on the site. Why is this even so hard to do. + # Right now it's even possible to create ownerless sessions through POST + xit 'allows users to create level sessions through PATCH', (done) -> + loginJoe (joe) -> + console.log url + mongoose.Types.ObjectId() + request {method: 'patch', uri: url + mongoose.Types.ObjectId(), json: session}, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe 200 + console.log body + expect(body.creator).toEqual joe.get('_id').toHexString() + done() + + # Should remove this as soon as the PATCH test case above works + it 'create a level session', (done) -> + unittest.getNormalJoe (joe) -> + session.creator = joe.get('_id').toHexString() + session = new LevelSession session + session.save (err) -> + expect(err).toBeNull() + done() + + it 'GET /db/user//level.sessions gets a user\'s level sessions', (done) -> + unittest.getNormalJoe (joe) -> + request.get {uri: getURL "/db/user/#{joe.get '_id'}/level.sessions"}, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe 200 + sessions = JSON.parse body + expect(sessions.length).toBe 1 + done() + + it 'GET /db/user//level.sessions gets a user\'s level sessions', (done) -> + unittest.getNormalJoe (joe) -> + request.get {uri: getURL "/db/user/#{joe.get 'slug'}/level.sessions"}, (err, res, body) -> + expect(err).toBeNull() + expect(res.statusCode).toBe 200 + sessions = JSON.parse body + expect(sessions.length).toBe 1 + done() + + it 'GET /db/user//level.sessions returns 404 if user not found', (done) -> + request.get {uri: getURL "/db/user/misterschtroumpf/level.sessions"}, (err, res) -> + expect(err).toBeNull() + expect(res.statusCode).toBe 404 + done() diff --git a/test/vendor/example.coffee b/test/vendor/example.coffee deleted file mode 100644 index d08284dc1..000000000 --- a/test/vendor/example.coffee +++ /dev/null @@ -1 +0,0 @@ -massivelyUsefulTestExample = 'test...'