diff --git a/app/lib/Router.coffee b/app/Router.coffee similarity index 63% rename from app/lib/Router.coffee rename to app/Router.coffee index 42690cb62..0b0755653 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,25 @@ module.exports = class CocoRouter extends Backbone.Router '': go('HomeView') 'about': go('AboutView') - 'admin': go('AdminView') + + 'account': go('account/MainAccountView') + 'account/settings': go('account/AccountSettingsView') + 'account/unsubscribe': go('account/UnsubscribeView') + #'account/payment' + + '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,80 +44,89 @@ 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') - - # editor views tend to have the same general structure - 'editor/:model(/:slug_or_id)(/:subview)': 'editorModelView' - 'user/:slugOrID': go('user/MainUserView') 'user/:slugOrID/stats': go('user/AchievementsView') 'user/:slugOrID/profile': go('user/JobProfileView') #'user/:slugOrID/code': go('user/CodeView') - 'account': go('account/MainAccountView') - 'account/settings': go('account/AccountSettingsView') - #'account/payment' + '*name': 'showNotFoundView' - # Direct links + routeToServer: (e) -> + window.location.href = window.location.href - - '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() @@ -126,71 +151,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() @@ -205,6 +169,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 b0f4c5ba0..7d471acd3 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() @@ -57,7 +57,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/common/code_languages/io_icon.png b/app/assets/images/common/code_languages/io_icon.png old mode 100644 new mode 100755 index 0b6c58fe4..14f04afc3 Binary files a/app/assets/images/common/code_languages/io_icon.png and b/app/assets/images/common/code_languages/io_icon.png differ diff --git a/app/assets/images/common/code_languages/javascript_icon.png b/app/assets/images/common/code_languages/javascript_icon.png old mode 100644 new mode 100755 index 4580f350b..085dbe523 Binary files a/app/assets/images/common/code_languages/javascript_icon.png and b/app/assets/images/common/code_languages/javascript_icon.png differ 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..8185ef358 100644 --- a/app/initialize.coffee +++ b/app/initialize.coffee @@ -35,8 +35,6 @@ init = -> 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) -> @@ -93,3 +91,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() \ No newline at end of file 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..509b735e0 100644 --- a/app/lib/surface/CocoSprite.coffee +++ b/app/lib/surface/CocoSprite.coffee @@ -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/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/schemas/models/user.coffee b/app/schemas/models/user.coffee index 11c9a32bc..4f2d3beed 100644 --- a/app/schemas/models/user.coffee +++ b/app/schemas/models/user.coffee @@ -6,6 +6,33 @@ UserSchema = c.object c.extendNamedProperties UserSchema # let's have the name be the first property +#Put the various filters in variables for reusability +phoneScreenFilter = + title: 'Phone screened' + type: 'boolean' + description: 'Whether the candidate has been phone screened.' +schoolFilter = + title: 'School' + type: 'string' + enum: ['Top School', 'Other'] +locationFilter = + title: 'Location' + type: 'string' + enum: ['Bay Area', 'New York', 'Other US', 'International'] +roleFilter = + title: 'Role' + type: 'string' + enum: ['Web Developer', 'Software Developer', 'Mobile Developer'] +seniorityFilter = + title: 'Seniority' + type: 'string' + enum: ['College Student', 'Recent Grad', 'Junior', 'Senior'] +visa = c.shortString + title: 'US Work Status' + description: 'Are you authorized to work in the US, or do you need visa sponsorship? (If you live in Canada or Australia, mark authorized.)' + enum: ['Authorized to work in the US', 'Need visa sponsorship'] + default: 'Authorized to work in the US' + _.extend UserSchema.properties, email: c.shortString({title: 'Email', format: 'email'}) firstName: c.shortString({title: 'First Name'}) @@ -87,7 +114,7 @@ _.extend UserSchema.properties, experience: {type: 'integer', title: 'Years of Experience', minimum: 0, description: 'How many years of professional experience (getting paid) developing software do you have?'} shortDescription: {type: 'string', maxLength: 140, title: 'Short Description', description: 'Who are you, and what are you looking for? 140 characters max.', default: 'Programmer seeking to build great software.'} longDescription: {type: 'string', maxLength: 600, title: 'Description', description: '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.', format: 'markdown', default: '* I write great code.\n* You need great code?\n* Great!'} - visa: c.shortString {title: 'US Work Status', description: 'Are you authorized to work in the US, or do you need visa sponsorship? (If you live in Canada or Australia, mark authorized.)', enum: ['Authorized to work in the US', 'Need visa sponsorship'], default: 'Authorized to work in the US'} + visa: visa work: c.array {title: 'Work Experience', description: 'List your relevant work experience, most recent first.'}, c.object {title: 'Job', description: 'Some work experience you had.', required: ['employer', 'role', 'duration']}, employer: c.shortString {title: 'Employer', description: 'Name of your employer.'} @@ -131,26 +158,11 @@ _.extend UserSchema.properties, workHistory: c.array {title: 'Work history', description: 'One or two places the candidate has worked', type: 'array'}, title: 'Workplace' type: 'string' - phoneScreenFilter: - title: 'Phone screened' - type: 'boolean' - description: 'Whether the candidate has been phone screened.' - schoolFilter: - title: 'School' - type: 'string' - enum: ['Top School', 'Other'] - locationFilter: - title: 'Location' - type: 'string' - enum: ['Bay Area', 'New York', 'Other US', 'International'] - roleFilter: - title: 'Role' - type: 'string' - enum: ['Web Developer', 'Software Developer', 'Mobile Developer'] - seniorityFilter: - title: 'Seniority' - type: 'string' - enum: ['College Student', 'Recent Grad', 'Junior', 'Senior'] + phoneScreenFilter: phoneScreenFilter + schoolFilter: schoolFilter + locationFilter: locationFilter + roleFilter: roleFilter + seniorityFilter: seniorityFilter featured: title: 'Featured' type: 'boolean' @@ -163,6 +175,51 @@ _.extend UserSchema.properties, linkedinID: c.shortString {title: 'LinkedInID', description: 'The user\'s LinkedIn ID when they signed the contract.'} date: c.date {title: 'Date signed employer agreement'} data: c.object {description: 'Cached LinkedIn data slurped from profile.', additionalProperties: true} + savedEmployerFilterAlerts: c.array { + title: 'Saved Employer Filter Alerts' + description: 'Employers can get emailed alerts whenever there are new candidates matching their filters' + }, c.object({ + title: 'Saved filter set' + description: 'A saved filter set' + required: ['phoneScreenFilter','schoolFilter','locationFilter','roleFilter','seniorityFilter','visa'] + }, { + phoneScreenFilter: + title: 'Phone screen filter values' + type: 'array' + items: + type: 'boolean' + schoolFilter: + title: 'School filter values' + type: 'array' + items: + type: schoolFilter.type + enum: schoolFilter.enum + locationFilter: + title: 'Location filter values' + type: 'array' + items: + type: locationFilter.type + enum: locationFilter.enum + roleFilter: + title: 'Role filter values' + type: 'array' + items: + type: roleFilter.type + enum: roleFilter.enum + seniorityFilter: + title: 'Seniority filter values' + type: 'array' + items: + type: roleFilter.type + enum: seniorityFilter.enum + visa: + title: 'Visa filter values' + type: 'array' + items: + type: visa.type + enum: visa.enum + }) + points: {type: 'number'} activity: {type: 'object', description: 'Summary statistics about user activity', additionalProperties: c.activity} stats: c.object {additionalProperties: false}, diff --git a/app/styles/account/profile.sass b/app/styles/account/profile.sass index a661ea611..5b5d83fc9 100644 --- a/app/styles/account/profile.sass +++ b/app/styles/account/profile.sass @@ -2,7 +2,13 @@ #profile-view $sideBackground: rgb(220, 220, 220) - + #login-message + h1, h2, h3, h4 + font-family: Arial, Helvetica, sans-serif + color: #333333 + width: 100% + text-align: center + margin-top: 200px .profile-control-bar background-color: $sideBackground width: 100% 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..ac5509f64 100644 --- a/app/styles/editor/level/thangs_tab.sass +++ b/app/styles/editor/level/thangs_tab.sass @@ -151,6 +151,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 +210,21 @@ $mobile: 1050px #canvas-wrapper width: 100% position: relative + + #canvas-overlay + 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/employers.sass b/app/styles/employers.sass index 32c1d1de3..bc0fb4d21 100644 --- a/app/styles/employers.sass +++ b/app/styles/employers.sass @@ -63,7 +63,15 @@ cursor: pointer input margin-right: 5px - + #saved-filter-table + display: none + width: 100% + tbody + tr:nth-child(even) + background-color: #CBCBCB + margin-bottom: 20px + .deletion-row + text-align: center .get-started-button vertical-align: text-bottom margin-left: 10px 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..4d503ba0f 100644 --- a/app/styles/play/level/tome/problem_alert.sass +++ b/app/styles/play/level/tome/problem_alert.sass @@ -8,7 +8,7 @@ right: 10px background: transparent border: 0 - padding: 18px 35px 18px 14px + padding: 7px 20px text-shadow: none color: white word-wrap: break-word @@ -46,7 +46,8 @@ 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) diff --git a/app/styles/play/level/tome/spell.sass b/app/styles/play/level/tome/spell.sass index 291403dc0..e01f63a0e 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 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 2699a3ac1..37ff7ef85 100644 --- a/app/templates/account/profile.jade +++ b/app/templates/account/profile.jade @@ -1,492 +1,501 @@ extends /templates/base block content - if allowedToEditJobProfile - .profile-control-bar - if editing - .progress.profile-completion-progress - .progress-bar.progress-bar-success(style="width: #{100 * progress}%") - .progress-text - a.btn(href="/account/settings") - i.icon-cog - span(data-i18n="account_profile.settings") Settings - if editing - button.btn.btn-success#toggle-editing - i.icon-ok - span(data-i18n="account_profile.done_editing") Done Editing - else - button.btn#toggle-editing - i.icon-cog - span(data-i18n="account_profile.edit_profile") Edit Profile - if linkedInAuthorized && editing - button.btn.btn-success#importLinkedIn - i.icon-arrow-down - span Import LinkedIn - else if editing - button.btn.linked-in-button - script(type="in/Login" id="linkedInAuthButton" data-onAuth="contractCallback") - if profile && profile.active - button.btn.btn-success#toggle-job-profile-active - i.icon-eye-open - span(data-i18n="account_profile.active") Looking for interview offers now - else - button.btn#toggle-job-profile-active - i.icon-eye-close - span(data-i18n="account_profile.inactive") Not looking for offers right now - if profile && (profile.active || me.isAdmin()) - if profileApproved - button.btn.btn-success#toggle-job-profile-approved(disabled=!me.isAdmin()) - i.icon-eye-open - span(data-i18n='account_profile.featured') Featured - else if me.isAdmin() - button.btn#toggle-job-profile-approved - i.icon-eye-close - span(data-i18n='account_profile.not_featured') Not Featured - if me.isAdmin() && !myProfile - button.btn#enter-espionage-mode 007 - if me.isAdmin() - button.btn#open-model-modal Raw - - if profile && allowedToViewJobProfile - div(class="job-profile-container" + (editing ? " editable-profile" : "")) - .job-profile-row - .left-column.full-height-column - .sub-column - #profile-photo-container.editable-section(title="Click to change your photo") - .editable-icon.glyphicon.glyphicon-pencil - img.profile-photo(src=user.getPhotoURL(240, true)) - .profile-caption= profile.jobTitle || 'Software Developer' - - #links-container.editable-section - .editable-display(title="Click to add social and personal links") - .editable-icon.glyphicon.glyphicon-pencil - if profileLinks && profileLinks.length - ul.links.editable-thinner - each link in profileLinks - if link.link && link.name - li(title=profile.name + " on " + link.name, class=link.icon ? "has-icon" : "") - a(href=link.link) - if link.icon - img(src=link.icon.url, alt=link.icon.name) - else - button.btn.btn-large.btn-inverse.flat-button= link.name - else if editing - h3.edit-label(data-i18n="account_profile.add_links") Add some links - ul.links - li.has-icon - a(href='http://example.com') - img(src='/images/pages/account/profile/icon_github.png', alt='GitHub') - li.has-icon - a(href='http://example.com') - img(src='/images/pages/account/profile/icon_facebook.png', alt='Facebook') - li.has-icon - a(href='http://example.com') - img(src='/images/pages/account/profile/icon_twitter.png', alt='Twitter') - li.has-icon - a(href='http://example.com/') - img(src='/images/pages/account/profile/icon_linkedin.png', alt='LinkedIn') - button.btn.btn-large.btn-inverse.flat-button.edit-example-button(data-i18n="account_profile.example_blog") Blog - button.btn.btn-large.btn-inverse.flat-button.edit-example-button(data-i18n="account_profile.example_personal_site") Personal Site - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - h3(data-i18n="account_profile.links_header") Personal Links - p.help-block(data-i18n="account_profile.links_blurb") Link any other sites or profiles you want to highlight, like your GitHub, your LinkedIn, or your blog. - .editable-array(data-property='links') - for link, index in (profile.links || []).concat({}) - .array-item.link-container.well.well-sm - .form-group - label.control-label(data-i18n="account_profile.links_name") Link Name - input.form-control(type='link-name', maxlength='30', data-schemaformat='link-name', name="root[links][#{index}][name]", value=link.name, data-autocomplete="commonLinkNames", data-autocomplete-min-length=0) - if !index - p.help-block - span(data-i18n="account_profile.links_name_help") What are you linking to? - | Ex.: 'Personal Website', 'GitHub' - .form-group - label.control-label(data-i18n="account_profile.links_link") Link URL - input.form-control(type='url', pattern='^(ht|f)tp(s?)://[0-9a-zA-Z]([-.w]*[0-9a-zA-Z])*(:(0-9)*)*(/?)([a-zA-Z0-9-.?,\'/\+&%$#_=]*)?$', data-schemaformat='url', name="root[links][#{index}][link]", value=link.link) - if !index - p.help-block Ex.: "https://github.com/nwinter" - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - .editable-section#basic-info-container - - var editableDefaults = editing && profile.city == jobProfileSchema.properties.city.default - div(class="editable-display" + (editableDefaults ? " edit-example-text" : ""), title="Click to edit your basic info") - .editable-icon.glyphicon.glyphicon-pencil - if editableDefaults - h3.edit-label(data-i18n="account_profile.basics_header") Update basic info - div= profile.city + ', ' + profile.country - div= profile.visa - div - span(data-i18n="account_profile.looking_for") Looking for: - | #{profile.lookingFor} - div - span(data-i18n="account_profile.last_updated") Last updated: - | #{moment(profile.updated).fromNow()} - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - .form-group - label.control-label(data-i18n="account_profile.basics_active") Open to Offers - select.form-control(name='root[active]') - option(value='1', selected=profile.active, data-i18n="account_profile.active") Looking for interview offers now - option(value='', selected=!profile.active, data-i18n="account_profile.inactive") Not looking for offers right now - p.help-block(data-i18n="account_profile.basics_active_help") Want interview offers right now? - .form-group - label.control-label(data-i18n="account_profile.basics_job_title") Desired Job Title - input.form-control(type='text', maxlength='50', name='root[jobTitle]', value=profile.jobTitle) - p.help-block - span(data-i18n="account_profile.basics_job_title_help") What role are you looking for? - | Ex.: "Full Stack Engineer", "Front-End Developer", "iOS Developer" - .form-group - label.control-label(data-i18n="account_profile.basics_city") City - input.form-control(type='city', maxlength='100', data-schemaformat='city', name='root[city]', value=profile.city, data-autocomplete="commonCities", data-autocomplete-min-length=1) - p.help-block - span(data-i18n="account_profile.basics_city_help") City you want to work in (or live in now). - | Ex.: "San Francisco", "Lubbock, TX" - .form-group - label.control-label(data-i18n="account_profile.basics_country") Country - input.form-control(type='country', maxlength='100', data-schemaformat='country', name='root[country]', value=profile.country, data-autocomplete="commonCountries", data-autocomplete-min-length=1) - p.help-block - span(data-i18n="account_profile.basics_country_help") Country you want to work in (or live in now). - | Ex.: "USA", "France" - .form-group - label.control-label(data-i18n="account_profile.basics_visa") US Work Status - select.form-control(name='root[visa]') - option(value='Authorized to work in the US', selected=profile.visa == 'Authorized to work in the US') Authorized to work in the US - option(value='Need visa sponsorship', selected=profile.visa == 'Need visa sponsorship') Need visa sponsorship - p.help-block(data-i18n="account_profile.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.) - .form-group - label.control-label(data-i18n="account_profile.basics_looking_for") Looking For - select.form-control(name='root[lookingFor]') - option(value='Full-time', selected=profile.lookingFor == "Full-time", data-i18n="account_profile.basics_looking_for_full_time") Full-time - option(value='Part-time', selected=profile.lookingFor == "Part-time", data-i18n="account_profile.basics_looking_for_part_time") Part-time - option(value='Remote', selected=profile.lookingFor == "Remote", data-i18n="account_profile.basics_looking_for_remote") Remote - option(value='Contracting', selected=profile.lookingFor == "Contracting", data-i18n="account_profile.basics_looking_for_contracting") Contracting - option(value='Internship', selected=profile.lookingFor == "Internship", data-i18n="account_profile.basics_looking_for_internship") Internship - p.help-block(data-i18n="account_profile.basics_looking_for_help") What kind of developer position do you want? - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - if !editing && !myProfile - button#contact-candidate.btn.btn-large.btn-inverse.flat-button - span(data-i18n="account_profile.contact") Contact - | #{profile.name.split(' ')[0]} - if me.isAdmin() - select#admin-contact.form-control - for contact in adminContacts - option(value=contact.id, selected=remark && remark.get('contact') == contact.id)= contact.name - - if !editing && sessions.length - h3(data-i18n="account_profile.player_code") Player Code - ul.sessions - each session in sessions - li - a.session-link(data-session-id=session._id) - span= session.levelName - if session.team - span.spl - #{session.team} - if session.codeLanguage != 'javascript' - span.spl - #{{coffeescript: 'CoffeeScript', python: 'Python', lua: 'Lua', io: 'Io', clojure: 'Clojure'}[session.codeLanguage]} - - .middle-column.full-height-column - .sub-column - #name-container.editable-section - .editable-display(title="Click to fill in your name") - .editable-icon.glyphicon.glyphicon-pencil - if editing && !profile.name - h3.edit-label(data-i18n="account_profile.name_header") Fill in your name - else if profile.name - h3= profile.name + (me.isAdmin() ? ' (' + user.get('name') + ')' : '') - else - h3 - span(data-i18n="account_profile.name_anonymous") Anonymous Developer - if me.isAdmin() - span (#{user.get('name')}) - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - .form-group - label.control-label(data-i18n="general.name") Name - input.form-control(type='text', maxlength='100', name='root[name]', value=profile.name) - p.help-block(data-i18n="account_profile.name_help") Name you want employers to see, like 'Nick Winter'. - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - - #short-description-container.editable-section - .editable-display(title="Click to write your tagline") - .editable-icon.glyphicon.glyphicon-pencil - if editing && (!profile.shortDescription || profile.shortDescription == jobProfileSchema.properties.shortDescription.default) - h3.edit-label(data-i18n="account_profile.short_description_header") Write a short description of yourself - p.edit-example-text(data-i18n="account_profile.short_description_blurb") Add a tagline to help an employer quickly learn more about you. - - else if profile.shortDescription - p.editable-thinner= profile.shortDescription - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - .form-group - label.control-label(data-i18n="account_profile.short_description") Tagline - textarea.form-control(rows=3, maxlength='140', name='root[shortDescription]')= profile.shortDescription - p.help-block(data-i18n="account_profile.short_description_help") Who are you, and what are you looking for? 140 characters max. - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - - #skills-container.editable-section - .editable-display.editable-thinner(title="Click to tag your programming skills") - .editable-icon.glyphicon.glyphicon-pencil - if editing && (!profile.skills || !profile.skills.length || (profile.skills.length == 1 && profile.skills[0] == 'javascript')) - h3.edit-label Tag your programming skills - each skill in ["python", "coffeescript", "node", "ios", "objective-c", "javascript", "app-engine", "mongodb", "web dev", "django", "backbone"] - code.edit-example-tag= skill - span - else - each skill in profile.skills - code= skill - span - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - h3(data-i18n="account_profile.skills_header") Skills - p.help-block - span(data-i18n="account_profile.skills_help") Tag relevant developer skills in order of proficiency. - | Ex.: "objective-c", "mongodb", "rails", "android", "javascript" - .editable-array(data-property='skills') - for skill, index in (profile.skills || []).concat('') - .array-item.skill-array-item - input.form-control(type='skill', maxlength='20', pattern='.{1,}', data-schemaformat='skill', name="root[skills][#{index}]", value=skill, data-autocomplete="commonSkills", data-autocomplete-min-length=1) - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - - #long-description-container.editable-section - .editable-display(title="Click to start writing your longer description") - .editable-icon.glyphicon.glyphicon-pencil - - var modified = profile.longDescription && profile.longDescription != jobProfileSchema.properties.longDescription.default - if editing && !modified - h3.edit-label(data-i18n="account_profile.long_description_header") Describe your desired position - p.edit-example-text(data-i18n="account_profile.long_description_blurb") Tell employers how awesome you are and what role you want. - else if modified - div.long-description.editable-thinner!= marked(profile.longDescription) - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - .form-group - label.control-label(data-i18n="account_profile.long_description") Self Description - textarea.form-control(rows=20, maxlength='600', data-schemaformat='markdown', name='root[longDescription]')= profile.longDescription - p.help-block(data-i18n="account_profile.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. - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - #work-container.editable-section - .editable-display(title="Click to add work experience") - .editable-icon.glyphicon.glyphicon-pencil - if profile.work && profile.work.length - h3.experience-header - img.header-icon(src="/images/pages/account/profile/work.png", alt="") - span(data-i18n="account_profile.work_experience") Work Experience - | - #{profile.experience} - | - span(data-i18n=profile.experience == 1 ? "units.year" : "units.years") - each job in profile.work - if job.role && job.employer - div.experience-entry - div.duration.pull-right= job.duration - | #{job.role} at #{job.employer} - .clearfix - if job.description - div!= marked(job.description) - else if editing - h3.experience-header.edit-label(data-i18n="account_profile.work_header") Chronicle your work history - - div.experience-entry.edit-example-text - div.duration.pull-right June, 2012 - present - | UX Designer at Hooli - .clearfix - div Revolutionized CSS, refactored flattening, and designed all the things. - - div.experience-entry.edit-example-text - div.duration.pull-right 1999 - 2012 - | Software Engineer at Initrode - .clearfix - div Built a P2P streaming TPS report fulfillment system. - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - h3(data-i18n="account_profile.work_experience") Work Experience - .form-group - label.control-label(data-i18n="account_profile.work_years") Years of Experience - input.form-control(type='text', name='root[experience]', value=profile.experience) - p.help-block(data-i18n="account_profile.work_years_help") How many years of professional experience (getting paid) developing software do you have? - p(data-i18n="account_profile.work_blurb") List your relevant work experience, most recent first. - .editable-array(data-property='work') - for job, index in (profile.work || []).concat({}) - .array-item.well.well-sm - .form-group - label.control-label(data-i18n="account_profile.work_employer") Employer - input.form-control(type='text', maxlength='100', name="root[work][#{index}][employer]", value=job.employer) - p.help-block(data-i18n="account_profile.work_employer_help") Name of your employer. - .form-group - label.control-label(data-i18n="account_profile.work_role") Job Title - input.form-control(type='text', maxlength='100', name="root[work][#{index}][role]", value=job.role) - p.help-block(data-i18n="account_profile.work_role_help") What was your job title or role? - .form-group - label.control-label(data-i18n="account_profile.work_duration") Duration - input.form-control(type='text', maxlength='100', name="root[work][#{index}][duration]", value=job.duration) - p.help-block - span(data-i18n="account_profile.work_duration_help") When did you hold this gig? - | Ex.: "Feb 2013 - present". - .form-group - label.control-label(data-i18n="account_profile.work_description") Description - textarea.form-control(rows=3, maxlength='140', name="root[work][#{index}][description]")= job.description - p.help-block(data-i18n="account_profile.work_description_help") What did you do there? (140 chars; optional) - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - - #education-container.editable-section - .editable-display(title="Click to add academic experience") - .editable-icon.glyphicon.glyphicon-pencil - if profile.education && profile.education.length - h3.experience-header - img.header-icon(src="/images/pages/account/profile/education.png", alt="") - span(data-i18n="account_profile.education") Education - each school in profile.education - if school.degree && school.school - div.experience-entry - div.duration.pull-right= school.duration - | #{school.degree} at #{school.school} - .clearfix - if school.description - div!= marked(school.description) - else if editing - h3.experience-header.edit-label(data-i18n="account_profile.education_header") Recount your academic ordeals - - div.experience-entry.edit-example-text - div.duration.pull-right 1995 - 1997 - | Ph.D. Janitorial Science at MIT - .clearfix - div Anonymously solved problems in algebraic graph theory. Swept floors. - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - h3(data-i18n="accont_profile.education") Education - p(data-i18n="account_profile.education_blurb") List your academic ordeals. - .editable-array(data-property='education') - for school, index in (profile.education || []).concat({}) - .array-item.well.well-sm - .form-group - label.control-label(data-i18n="account_profile.education_school") School - input.form-control(type='text', maxlength='100', name="root[education][#{index}][school]", value=school.school) - p.help-block(data-i18n="account_profile.education_school_help") Name of your school. - .form-group - label.control-label(data-i18n="account_profile.education_degree") Degree - input.form-control(type='text', maxlength='100', name="root[education][#{index}][degree]", value=school.degree) - p.help-block - span(data-i18n="account_profile.education_degree_help") What was your degree and field of study? - | Ex.: "Ph.D. Human-Computer Interaction (incomplete)" - .form-group - label.control-label(data-i18n="account_profile.education_duration") Dates - input.form-control(type='text', maxlength='100', name="root[education][#{index}][duration]", value=school.duration) - p.help-block - span(data-i18n="account_profile.education_duration_help") When? - | Ex.: "Aug 2004 - May 2008". - .form-group - label.control-label(data-i18n="account_profile.education_description") Description - textarea.form-control(rows=3, maxlength='140', name="root[education][#{index}][description]")= school.description - p.help-block(data-i18n="account_profile.education_description_help") Highlight anything about this educational experience. (140 chars; optional) - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - - if user.get('jobProfileNotes') || me.isAdmin() - div(class="our-notes-section" + (editing ? " deemphasized" : "")) - h3.experience-header(data-i18n="account_profile.our_notes") CodeCombat's Notes - - var notes = user.get('jobProfileNotes') || ''; - if me.isAdmin() - textarea#job-profile-notes!= notes - button.btn.btn-primary#save-notes-button(data-i18n="common.save") Save - else - div!= marked(notes) - - if me.isAdmin() - h3(data-i18n="account_profile.remarks") Remarks - #remark-treema - - .right-column.full-height-column - .sub-column - #projects-container.editable-section - .editable-display(title="Click to add your projects") - .editable-icon.glyphicon.glyphicon-pencil - if profile.projects && profile.projects.length - h3(data-i18n="account_profile.projects") Projects - ul.projects - each project in profile.projects - if project.name - li - if project.link && project.link.length && project.link != 'http://example.com' - a(href=project.link) - if project.picture - .project-image(style="background-image: url('/file/" + project.picture + "')") - p= project.name - div!= marked(project.description) - else if editing - h3.edit-label(data-i18n="account_profile.projects_header") Add 3 projects - ul.projects - li.edit-example-text - .project-image(style="background-image: url('/images/pages/account/profile/sample_project.png')") - p Cog.js - div JS microlibrary to animate fixie bike cogs on ecommerce sites that sell bike hardware. - li.edit-example-text - .project-image(style="background-image: url('/images/pages/account/profile/sample_project.png')") - p Combjoy - div Ember.js project that schedules hair stylists to ride in Ubers with you to comb your hair on your way to work. - li.edit-example-text - .project-image(style="background-image: url('/images/pages/account/profile/sample_project.png')") - p Bass Drop - div Insert a few lines of JS into your site and get a "Drop the bass!" button for your website. Plays techno. - - form.editable-form - .editable-icon.glyphicon.glyphicon-remove - h3(data-i18n="account_profile.projects_header_2") Projects (Top 3) - p(data-i18n="account_profile.projects_blurb") Highlight your projects to amaze employers. - for index in [0, 1, 2] - - var project = (profile.projects || [])[index] || {}; - .array-item.well.well-sm - .form-group - label.control-label(data-i18n="account_profile.projects_name") Project Name - input.form-control(type='text', maxlength='100', name="root[projects][#{index}][name]", value=project.name) - p.help-block(data-i18n="account_profile.projects_name_help") What was the project called? - .form-group - label.control-label(data-i18n="account_profile.projects_description") Description - textarea.form-control(rows=6, maxlength='400', data-schemaformat='markdown', name="root[projects][#{index}][description]")= project.description - p.help-block(data-i18n="account_profile.projects_description_help") Briefly describe the project. - .form-group - label.control-label(data-i18n="account_profile.projects_picture") Picture - .project-image(style="background-image: url('" + (src=project.picture ? "/file/" + project.picture : "/images/pages/account/profile/sample_project.png") + "')") - input(type="hidden", name="root[projects][#{index}][picture]", value=project.picture) - p.help-block(data-i18n="account_profile.projects_picture_help") Upload a 230x115px or larger image showing off the project. - .form-group - label.control-label(data-i18n="account_profile.projects_link") Link - input.form-control(type='url', pattern='^(ht|f)tp(s?)://[0-9a-zA-Z]([-.w]*[0-9a-zA-Z])*(:(0-9)*)*(/?)([a-zA-Z0-9-.?,\'/\+&%$#_=]*)?$', data-schemaformat='url', name="root[projects][#{index}][link]", value=project.link) - p.help-block(data-i18n="account_profile.projects_link_help") Link to the project. - button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save - - else if allowedToViewJobProfile - .public-profile-container - h2(data-i18n="common.loading") Loading... - - else if user - .public-profile-container - h2 - span(data-i18n="account_profile.profile_for_prefix") Profile for - span= user.get('name') || "Anonymous Wizard" - span(data-i18n="account_profile.profile_for_suffix") - - img.profile-photo(src=user.getPhotoURL(256)) - - p To see a private user profile, you may need to log in. - + if !allowedToEditJobProfile && me.get('anonymous') == true + div(class="job-profile-container") + h1#login-message + |Please + a.auth-button login + | to view this profile. else - .public-profile-container - h2 - span(data-i18n="account_profile.profile_for_prefix") Profile for - span= userID - span(data-i18n="account_profile.profile_for_suffix") - | - span(data-i18n="loading_error.not_found") + if allowedToEditJobProfile + .profile-control-bar + if editing + .progress.profile-completion-progress + .progress-bar.progress-bar-success(style="width: #{100 * progress}%") + .progress-text + a.btn(href="/account/settings") + i.icon-cog + span(data-i18n="account_profile.settings") Settings + if editing + button.btn.btn-success#toggle-editing + i.icon-ok + span(data-i18n="account_profile.done_editing") Done Editing + else + button.btn#toggle-editing + i.icon-cog + span(data-i18n="account_profile.edit_profile") Edit Profile + if linkedInAuthorized && editing + button.btn.btn-success#importLinkedIn + i.icon-arrow-down + span Import LinkedIn + else if editing + button.btn.linked-in-button + script(type="in/Login" id="linkedInAuthButton" data-onAuth="contractCallback") + if profile && profile.active + button.btn.btn-success#toggle-job-profile-active + i.icon-eye-open + span(data-i18n="account_profile.active") Looking for interview offers now + else + button.btn#toggle-job-profile-active + i.icon-eye-close + span(data-i18n="account_profile.inactive") Not looking for offers right now + if profile && (profile.active || me.isAdmin()) + if profileApproved + button.btn.btn-success#toggle-job-profile-approved(disabled=!me.isAdmin()) + i.icon-eye-open + span(data-i18n='account_profile.featured') Featured + else if me.isAdmin() + button.btn#toggle-job-profile-approved + i.icon-eye-close + span(data-i18n='account_profile.not_featured') Not Featured + if me.isAdmin() && !myProfile + button.btn#enter-espionage-mode 007 + if me.isAdmin() + button.btn#open-model-modal Raw + + if profile && allowedToViewJobProfile + div(class="job-profile-container" + (editing ? " editable-profile" : "")) + .job-profile-row + .left-column.full-height-column + .sub-column + #profile-photo-container.editable-section(title="Click to change your photo") + .editable-icon.glyphicon.glyphicon-pencil + img.profile-photo(src=user.getPhotoURL(240, true)) + .profile-caption= profile.jobTitle || 'Software Developer' + + #links-container.editable-section + .editable-display(title="Click to add social and personal links") + .editable-icon.glyphicon.glyphicon-pencil + if profileLinks && profileLinks.length + ul.links.editable-thinner + each link in profileLinks + if link.link && link.name + li(title=profile.name + " on " + link.name, class=link.icon ? "has-icon" : "") + a(href=link.link) + if link.icon + img(src=link.icon.url, alt=link.icon.name) + else + button.btn.btn-large.btn-inverse.flat-button= link.name + else if editing + h3.edit-label(data-i18n="account_profile.add_links") Add some links + ul.links + li.has-icon + a(href='http://example.com') + img(src='/images/pages/account/profile/icon_github.png', alt='GitHub') + li.has-icon + a(href='http://example.com') + img(src='/images/pages/account/profile/icon_facebook.png', alt='Facebook') + li.has-icon + a(href='http://example.com') + img(src='/images/pages/account/profile/icon_twitter.png', alt='Twitter') + li.has-icon + a(href='http://example.com/') + img(src='/images/pages/account/profile/icon_linkedin.png', alt='LinkedIn') + button.btn.btn-large.btn-inverse.flat-button.edit-example-button(data-i18n="account_profile.example_blog") Blog + button.btn.btn-large.btn-inverse.flat-button.edit-example-button(data-i18n="account_profile.example_personal_site") Personal Site + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + h3(data-i18n="account_profile.links_header") Personal Links + p.help-block(data-i18n="account_profile.links_blurb") Link any other sites or profiles you want to highlight, like your GitHub, your LinkedIn, or your blog. + .editable-array(data-property='links') + for link, index in (profile.links || []).concat({}) + .array-item.link-container.well.well-sm + .form-group + label.control-label(data-i18n="account_profile.links_name") Link Name + input.form-control(type='link-name', maxlength='30', data-schemaformat='link-name', name="root[links][#{index}][name]", value=link.name, data-autocomplete="commonLinkNames", data-autocomplete-min-length=0) + if !index + p.help-block + span(data-i18n="account_profile.links_name_help") What are you linking to? + | Ex.: 'Personal Website', 'GitHub' + .form-group + label.control-label(data-i18n="account_profile.links_link") Link URL + input.form-control(type='url', pattern='^(ht|f)tp(s?)://[0-9a-zA-Z]([-.w]*[0-9a-zA-Z])*(:(0-9)*)*(/?)([a-zA-Z0-9-.?,\'/\+&%$#_=]*)?$', data-schemaformat='url', name="root[links][#{index}][link]", value=link.link) + if !index + p.help-block Ex.: "https://github.com/nwinter" + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + .editable-section#basic-info-container + - var editableDefaults = editing && profile.city == jobProfileSchema.properties.city.default + div(class="editable-display" + (editableDefaults ? " edit-example-text" : ""), title="Click to edit your basic info") + .editable-icon.glyphicon.glyphicon-pencil + if editableDefaults + h3.edit-label(data-i18n="account_profile.basics_header") Update basic info + div= profile.city + ', ' + profile.country + div= profile.visa + div + span(data-i18n="account_profile.looking_for") Looking for: + | #{profile.lookingFor} + div + span(data-i18n="account_profile.last_updated") Last updated: + | #{moment(profile.updated).fromNow()} + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + .form-group + label.control-label(data-i18n="account_profile.basics_active") Open to Offers + select.form-control(name='root[active]') + option(value='1', selected=profile.active, data-i18n="account_profile.active") Looking for interview offers now + option(value='', selected=!profile.active, data-i18n="account_profile.inactive") Not looking for offers right now + p.help-block(data-i18n="account_profile.basics_active_help") Want interview offers right now? + .form-group + label.control-label(data-i18n="account_profile.basics_job_title") Desired Job Title + input.form-control(type='text', maxlength='50', name='root[jobTitle]', value=profile.jobTitle) + p.help-block + span(data-i18n="account_profile.basics_job_title_help") What role are you looking for? + | Ex.: "Full Stack Engineer", "Front-End Developer", "iOS Developer" + .form-group + label.control-label(data-i18n="account_profile.basics_city") City + input.form-control(type='city', maxlength='100', data-schemaformat='city', name='root[city]', value=profile.city, data-autocomplete="commonCities", data-autocomplete-min-length=1) + p.help-block + span(data-i18n="account_profile.basics_city_help") City you want to work in (or live in now). + | Ex.: "San Francisco", "Lubbock, TX" + .form-group + label.control-label(data-i18n="account_profile.basics_country") Country + input.form-control(type='country', maxlength='100', data-schemaformat='country', name='root[country]', value=profile.country, data-autocomplete="commonCountries", data-autocomplete-min-length=1) + p.help-block + span(data-i18n="account_profile.basics_country_help") Country you want to work in (or live in now). + | Ex.: "USA", "France" + .form-group + label.control-label(data-i18n="account_profile.basics_visa") US Work Status + select.form-control(name='root[visa]') + option(value='Authorized to work in the US', selected=profile.visa == 'Authorized to work in the US') Authorized to work in the US + option(value='Need visa sponsorship', selected=profile.visa == 'Need visa sponsorship') Need visa sponsorship + p.help-block(data-i18n="account_profile.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.) + .form-group + label.control-label(data-i18n="account_profile.basics_looking_for") Looking For + select.form-control(name='root[lookingFor]') + option(value='Full-time', selected=profile.lookingFor == "Full-time", data-i18n="account_profile.basics_looking_for_full_time") Full-time + option(value='Part-time', selected=profile.lookingFor == "Part-time", data-i18n="account_profile.basics_looking_for_part_time") Part-time + option(value='Remote', selected=profile.lookingFor == "Remote", data-i18n="account_profile.basics_looking_for_remote") Remote + option(value='Contracting', selected=profile.lookingFor == "Contracting", data-i18n="account_profile.basics_looking_for_contracting") Contracting + option(value='Internship', selected=profile.lookingFor == "Internship", data-i18n="account_profile.basics_looking_for_internship") Internship + p.help-block(data-i18n="account_profile.basics_looking_for_help") What kind of developer position do you want? + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + if !editing && !myProfile + button#contact-candidate.btn.btn-large.btn-inverse.flat-button + span(data-i18n="account_profile.contact") Contact + | #{profile.name.split(' ')[0]} + if me.isAdmin() + select#admin-contact.form-control + for contact in adminContacts + option(value=contact.id, selected=remark && remark.get('contact') == contact.id)= contact.name + + if !editing && sessions.length + h3(data-i18n="account_profile.player_code") Player Code + ul.sessions + each session in sessions + li + a.session-link(data-session-id=session._id) + span= session.levelName + if session.team + 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 + .editable-display(title="Click to fill in your name") + .editable-icon.glyphicon.glyphicon-pencil + if editing && !profile.name + h3.edit-label(data-i18n="account_profile.name_header") Fill in your name + else if profile.name + h3= profile.name + (me.isAdmin() ? ' (' + user.get('name') + ')' : '') + else + h3 + span(data-i18n="account_profile.name_anonymous") Anonymous Developer + if me.isAdmin() + span (#{user.get('name')}) + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + .form-group + label.control-label(data-i18n="general.name") Name + input.form-control(type='text', maxlength='100', name='root[name]', value=profile.name) + p.help-block(data-i18n="account_profile.name_help") Name you want employers to see, like 'Nick Winter'. + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + + #short-description-container.editable-section + .editable-display(title="Click to write your tagline") + .editable-icon.glyphicon.glyphicon-pencil + if editing && (!profile.shortDescription || profile.shortDescription == jobProfileSchema.properties.shortDescription.default) + h3.edit-label(data-i18n="account_profile.short_description_header") Write a short description of yourself + p.edit-example-text(data-i18n="account_profile.short_description_blurb") Add a tagline to help an employer quickly learn more about you. + + else if profile.shortDescription + p.editable-thinner= profile.shortDescription + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + .form-group + label.control-label(data-i18n="account_profile.short_description") Tagline + textarea.form-control(rows=3, maxlength='140', name='root[shortDescription]')= profile.shortDescription + p.help-block(data-i18n="account_profile.short_description_help") Who are you, and what are you looking for? 140 characters max. + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + + #skills-container.editable-section + .editable-display.editable-thinner(title="Click to tag your programming skills") + .editable-icon.glyphicon.glyphicon-pencil + if editing && (!profile.skills || !profile.skills.length || (profile.skills.length == 1 && profile.skills[0] == 'javascript')) + h3.edit-label Tag your programming skills + each skill in ["python", "coffeescript", "node", "ios", "objective-c", "javascript", "app-engine", "mongodb", "web dev", "django", "backbone"] + code.edit-example-tag= skill + span + else + each skill in profile.skills + code= skill + span + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + h3(data-i18n="account_profile.skills_header") Skills + p.help-block + span(data-i18n="account_profile.skills_help") Tag relevant developer skills in order of proficiency. + | Ex.: "objective-c", "mongodb", "rails", "android", "javascript" + .editable-array(data-property='skills') + for skill, index in (profile.skills || []).concat('') + .array-item.skill-array-item + input.form-control(type='skill', maxlength='20', pattern='.{1,}', data-schemaformat='skill', name="root[skills][#{index}]", value=skill, data-autocomplete="commonSkills", data-autocomplete-min-length=1) + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + + #long-description-container.editable-section + .editable-display(title="Click to start writing your longer description") + .editable-icon.glyphicon.glyphicon-pencil + - var modified = profile.longDescription && profile.longDescription != jobProfileSchema.properties.longDescription.default + if editing && !modified + h3.edit-label(data-i18n="account_profile.long_description_header") Describe your desired position + p.edit-example-text(data-i18n="account_profile.long_description_blurb") Tell employers how awesome you are and what role you want. + else if modified + div.long-description.editable-thinner!= marked(profile.longDescription) + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + .form-group + label.control-label(data-i18n="account_profile.long_description") Self Description + textarea.form-control(rows=20, maxlength='600', data-schemaformat='markdown', name='root[longDescription]')= profile.longDescription + p.help-block(data-i18n="account_profile.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. + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + #work-container.editable-section + .editable-display(title="Click to add work experience") + .editable-icon.glyphicon.glyphicon-pencil + if profile.work && profile.work.length + h3.experience-header + img.header-icon(src="/images/pages/account/profile/work.png", alt="") + span(data-i18n="account_profile.work_experience") Work Experience + | - #{profile.experience} + | + span(data-i18n=profile.experience == 1 ? "units.year" : "units.years") + each job in profile.work + if job.role && job.employer + div.experience-entry + div.duration.pull-right= job.duration + | #{job.role} at #{job.employer} + .clearfix + if job.description + div!= marked(job.description) + else if editing + h3.experience-header.edit-label(data-i18n="account_profile.work_header") Chronicle your work history + + div.experience-entry.edit-example-text + div.duration.pull-right June, 2012 - present + | UX Designer at Hooli + .clearfix + div Revolutionized CSS, refactored flattening, and designed all the things. + + div.experience-entry.edit-example-text + div.duration.pull-right 1999 - 2012 + | Software Engineer at Initrode + .clearfix + div Built a P2P streaming TPS report fulfillment system. + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + h3(data-i18n="account_profile.work_experience") Work Experience + .form-group + label.control-label(data-i18n="account_profile.work_years") Years of Experience + input.form-control(type='text', name='root[experience]', value=profile.experience) + p.help-block(data-i18n="account_profile.work_years_help") How many years of professional experience (getting paid) developing software do you have? + p(data-i18n="account_profile.work_blurb") List your relevant work experience, most recent first. + .editable-array(data-property='work') + for job, index in (profile.work || []).concat({}) + .array-item.well.well-sm + .form-group + label.control-label(data-i18n="account_profile.work_employer") Employer + input.form-control(type='text', maxlength='100', name="root[work][#{index}][employer]", value=job.employer) + p.help-block(data-i18n="account_profile.work_employer_help") Name of your employer. + .form-group + label.control-label(data-i18n="account_profile.work_role") Job Title + input.form-control(type='text', maxlength='100', name="root[work][#{index}][role]", value=job.role) + p.help-block(data-i18n="account_profile.work_role_help") What was your job title or role? + .form-group + label.control-label(data-i18n="account_profile.work_duration") Duration + input.form-control(type='text', maxlength='100', name="root[work][#{index}][duration]", value=job.duration) + p.help-block + span(data-i18n="account_profile.work_duration_help") When did you hold this gig? + | Ex.: "Feb 2013 - present". + .form-group + label.control-label(data-i18n="account_profile.work_description") Description + textarea.form-control(rows=3, maxlength='140', name="root[work][#{index}][description]")= job.description + p.help-block(data-i18n="account_profile.work_description_help") What did you do there? (140 chars; optional) + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + + #education-container.editable-section + .editable-display(title="Click to add academic experience") + .editable-icon.glyphicon.glyphicon-pencil + if profile.education && profile.education.length + h3.experience-header + img.header-icon(src="/images/pages/account/profile/education.png", alt="") + span(data-i18n="account_profile.education") Education + each school in profile.education + if school.degree && school.school + div.experience-entry + div.duration.pull-right= school.duration + | #{school.degree} at #{school.school} + .clearfix + if school.description + div!= marked(school.description) + else if editing + h3.experience-header.edit-label(data-i18n="account_profile.education_header") Recount your academic ordeals + + div.experience-entry.edit-example-text + div.duration.pull-right 1995 - 1997 + | Ph.D. Janitorial Science at MIT + .clearfix + div Anonymously solved problems in algebraic graph theory. Swept floors. + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + h3(data-i18n="accont_profile.education") Education + p(data-i18n="account_profile.education_blurb") List your academic ordeals. + .editable-array(data-property='education') + for school, index in (profile.education || []).concat({}) + .array-item.well.well-sm + .form-group + label.control-label(data-i18n="account_profile.education_school") School + input.form-control(type='text', maxlength='100', name="root[education][#{index}][school]", value=school.school) + p.help-block(data-i18n="account_profile.education_school_help") Name of your school. + .form-group + label.control-label(data-i18n="account_profile.education_degree") Degree + input.form-control(type='text', maxlength='100', name="root[education][#{index}][degree]", value=school.degree) + p.help-block + span(data-i18n="account_profile.education_degree_help") What was your degree and field of study? + | Ex.: "Ph.D. Human-Computer Interaction (incomplete)" + .form-group + label.control-label(data-i18n="account_profile.education_duration") Dates + input.form-control(type='text', maxlength='100', name="root[education][#{index}][duration]", value=school.duration) + p.help-block + span(data-i18n="account_profile.education_duration_help") When? + | Ex.: "Aug 2004 - May 2008". + .form-group + label.control-label(data-i18n="account_profile.education_description") Description + textarea.form-control(rows=3, maxlength='140', name="root[education][#{index}][description]")= school.description + p.help-block(data-i18n="account_profile.education_description_help") Highlight anything about this educational experience. (140 chars; optional) + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + + if user.get('jobProfileNotes') || me.isAdmin() + div(class="our-notes-section" + (editing ? " deemphasized" : "")) + h3.experience-header(data-i18n="account_profile.our_notes") CodeCombat's Notes + - var notes = user.get('jobProfileNotes') || ''; + if me.isAdmin() + textarea#job-profile-notes!= notes + button.btn.btn-primary#save-notes-button(data-i18n="common.save") Save + else + div!= marked(notes) + + if me.isAdmin() + h3(data-i18n="account_profile.remarks") Remarks + #remark-treema + + .right-column.full-height-column + .sub-column + #projects-container.editable-section + .editable-display(title="Click to add your projects") + .editable-icon.glyphicon.glyphicon-pencil + if profile.projects && profile.projects.length + h3(data-i18n="account_profile.projects") Projects + ul.projects + each project in profile.projects + if project.name + li + if project.link && project.link.length && project.link != 'http://example.com' + a(href=project.link) + if project.picture + .project-image(style="background-image: url('/file/" + project.picture + "')") + p= project.name + div!= marked(project.description) + else if editing + h3.edit-label(data-i18n="account_profile.projects_header") Add 3 projects + ul.projects + li.edit-example-text + .project-image(style="background-image: url('/images/pages/account/profile/sample_project.png')") + p Cog.js + div JS microlibrary to animate fixie bike cogs on ecommerce sites that sell bike hardware. + li.edit-example-text + .project-image(style="background-image: url('/images/pages/account/profile/sample_project.png')") + p Combjoy + div Ember.js project that schedules hair stylists to ride in Ubers with you to comb your hair on your way to work. + li.edit-example-text + .project-image(style="background-image: url('/images/pages/account/profile/sample_project.png')") + p Bass Drop + div Insert a few lines of JS into your site and get a "Drop the bass!" button for your website. Plays techno. + + form.editable-form + .editable-icon.glyphicon.glyphicon-remove + h3(data-i18n="account_profile.projects_header_2") Projects (Top 3) + p(data-i18n="account_profile.projects_blurb") Highlight your projects to amaze employers. + for index in [0, 1, 2] + - var project = (profile.projects || [])[index] || {}; + .array-item.well.well-sm + .form-group + label.control-label(data-i18n="account_profile.projects_name") Project Name + input.form-control(type='text', maxlength='100', name="root[projects][#{index}][name]", value=project.name) + p.help-block(data-i18n="account_profile.projects_name_help") What was the project called? + .form-group + label.control-label(data-i18n="account_profile.projects_description") Description + textarea.form-control(rows=6, maxlength='400', data-schemaformat='markdown', name="root[projects][#{index}][description]")= project.description + p.help-block(data-i18n="account_profile.projects_description_help") Briefly describe the project. + .form-group + label.control-label(data-i18n="account_profile.projects_picture") Picture + .project-image(style="background-image: url('" + (src=project.picture ? "/file/" + project.picture : "/images/pages/account/profile/sample_project.png") + "')") + input(type="hidden", name="root[projects][#{index}][picture]", value=project.picture) + p.help-block(data-i18n="account_profile.projects_picture_help") Upload a 230x115px or larger image showing off the project. + .form-group + label.control-label(data-i18n="account_profile.projects_link") Link + input.form-control(type='url', pattern='^(ht|f)tp(s?)://[0-9a-zA-Z]([-.w]*[0-9a-zA-Z])*(:(0-9)*)*(/?)([a-zA-Z0-9-.?,\'/\+&%$#_=]*)?$', data-schemaformat='url', name="root[projects][#{index}][link]", value=project.link) + p.help-block(data-i18n="account_profile.projects_link_help") Link to the project. + button.btn.btn-success.btn-block.save-section(data-i18n="common.save") Save + + else if allowedToViewJobProfile + .public-profile-container + h2(data-i18n="common.loading") Loading... + + else if user + .public-profile-container + h2 + span(data-i18n="account_profile.profile_for_prefix") Profile for + span= user.get('name') || "Anonymous Wizard" + span(data-i18n="account_profile.profile_for_suffix") + + img.profile-photo(src=user.getPhotoURL(256)) + + p To see a private user profile, you may need to log in. + + else + .public-profile-container + h2 + span(data-i18n="account_profile.profile_for_prefix") Profile for + span= userID + span(data-i18n="account_profile.profile_for_suffix") + | + span(data-i18n="loading_error.not_found") 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 d810526c9..e47222734 100644 --- a/app/templates/base.jade +++ b/app/templates/base.jade @@ -85,7 +85,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..54eb93f7e 100644 --- a/app/templates/editor/level/thangs_tab.jade +++ b/app/templates/editor/level/thangs_tab.jade @@ -23,6 +23,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/employers.jade b/app/templates/employers.jade index cc07bc618..bb689fa0d 100644 --- a/app/templates/employers.jade +++ b/app/templates/employers.jade @@ -90,7 +90,15 @@ block content p#results | #{numberOfCandidates} span(data-i18n="employers.results") results - //button.btn#create-alert-button Create Alert + h4#filter-alerts-heading Filter Email Alerts + p Get an email whenever a candidate meeting certain criteria enters the system. + table#saved-filter-table + thead + tr + th Filters + th Remove + tbody + button.btn#create-alert-button Create Alert with Current Filters #candidates-column(class=fullProfiles ? "full-profiles col-md-9" : "teaser-profiles col-md-12") if candidates.length 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 9bbfa1ef6..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' @@ -20,15 +19,16 @@ module.exports = class EmployersView extends RootView template: template events: - 'click tbody tr': 'onCandidateClicked' + 'click #candidate-table': 'onCandidateClicked' 'click #logout-link': 'logoutAccount' 'change #filters input': 'onFilterChanged' - 'click #filter-button': 'applyFilters' 'change #select_all_checkbox': 'handleSelectAllChange' 'click .get-started-button': 'openSignupModal' 'click .navbar-brand': 'restoreBodyColor' 'click #login-link': 'onClickAuthbutton' 'click #filter-link': 'swapFolderIcon' + 'click #create-alert-button': 'createFilterAlert' + 'click .deletion-col': 'deleteFilterAlert' constructor: (options) -> super options @@ -39,6 +39,7 @@ module.exports = class EmployersView extends RootView afterRender: -> super() @sortTable() if @candidates.models.length + @renderSavedFilters() afterInsert: -> super() @@ -73,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 -> @@ -128,7 +129,46 @@ module.exports = class EmployersView extends RootView return (_.filter candidates, (c) -> c.get('jobProfile').curated?[filterName] is filterValue).length else return Math.floor(Math.random() * 500) - + createFilterAlert: -> + currentFilterSet = _.cloneDeep @filters + currentSavedFilters = _.cloneDeep me.get('savedEmployerFilterAlerts') ? [] + currentSavedFilters.push currentFilterSet + @patchEmployerFilterAlerts currentSavedFilters, @renderSavedFilters + + deleteFilterAlert: (e) -> + index = $(e.target).closest('tbody tr').data('filter-index') + currentSavedFilters = me.get('savedEmployerFilterAlerts') + currentSavedFilters.splice(index,1) + @patchEmployerFilterAlerts currentSavedFilters, @renderSavedFilters + + patchEmployerFilterAlerts: (newFilters, cb) -> + me.set('savedEmployerFilterAlerts',newFilters) + unless me.isValid() + alert("There was an error setting the filter(me.isValid() returned false.) Reverting! Please notify team@codecombat.com.") + me.set 'savedEmployerFilterAlerts', me.previous('savedEmployerFilterAlerts') + else + triggerErrorAlert = -> alert("There was an error saving your filter alert! Please notify team@codecombat.com.") + res = me.save {"savedEmployerFilterAlerts": newFilters}, {patch: true, success: cb, error: triggerErrorAlert} + + renderSavedFilters: => + savedFilters = me.get('savedEmployerFilterAlerts') + unless savedFilters?.length then return $("#saved-filter-table").hide() + $("#saved-filter-table").show() + $("#saved-filter-table").find("tbody tr").remove() + for filter, index in savedFilters + $("#saved-filter-table tbody").append("""
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/app/views/user/JobProfileCodeModal.coffee b/app/views/user/JobProfileCodeModal.coffee
index 397de97cf..307f75847 100644
--- a/app/views/user/JobProfileCodeModal.coffee
+++ b/app/views/user/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/user/JobProfileView.coffee b/app/views/user/JobProfileView.coffee
index 488e8c397..47451d590 100644
--- a/app/views/user/JobProfileView.coffee
+++ b/app/views/user/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 UserView
+module.exports = class JobProfileView extends UserView
id: 'profile-view'
template: template
showBackground: false
@@ -70,7 +70,6 @@ module.exports = class ProfileView extends UserView
super()
finishInit: ->
- console.debug 'finishing that init'
return unless @userID
@uploadFilePath = "db/user/#{@userID}"
@highlightedContainers = []
@@ -79,7 +78,6 @@ module.exports = class ProfileView extends UserView
$.post "/db/user/#{@userID}/track/viewed_by_employer" unless me.isAdmin()
@sessions = @supermodel.loadCollection(new LevelSessionsCollection(@userID), 'candidate_sessions').model
if me.isAdmin()
- console.debug 'fetching that remark'
# Mimicking how the VictoryModal fetches LevelFeedback
@remark = new UserRemark()
@remark.setURL "/db/user/#{@userID}/remark"
@@ -277,7 +275,6 @@ module.exports = class ProfileView extends UserView
_.delay ->
justSavedSection.removeClass 'just-saved', duration: 1500, easing: 'easeOutQuad'
, 500
- console.debug @user
if me.isAdmin() and @user
visibleSettings = ['history', 'tasks']
data = _.pick (@remark.attributes), (value, key) -> key in visibleSettings
@@ -306,7 +303,7 @@ module.exports = class ProfileView extends UserView
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
@@ -363,7 +360,7 @@ module.exports = class ProfileView extends UserView
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/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 898e2dd4b..e6f29b30f 100644
--- a/server/commons/Handler.coffee
+++ b/server/commons/Handler.coffee
@@ -48,7 +48,7 @@ module.exports = class Handler
# sending functions
sendUnauthorizedError: (res) -> errors.forbidden(res) #TODO: rename sendUnauthorizedError to sendForbiddenError
sendForbiddenError: (res) -> errors.forbidden(res)
- 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) ->
diff --git a/server/plugins/plugins.coffee b/server/plugins/plugins.coffee
index 3aa5bcecf..238bcce3d 100644
--- a/server/plugins/plugins.coffee
+++ b/server/plugins/plugins.coffee
@@ -31,6 +31,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 9f68f0cc1..d6aa6f3cb 100644
--- a/server/queues/scoring.coffee
+++ b/server/queues/scoring.coffee
@@ -13,7 +13,7 @@ TaskLog = require './task/ScoringTask'
bayes = new (require 'bayesian-battle')()
scoringTaskQueue = undefined
-scoringTaskTimeoutInSeconds = 240
+scoringTaskTimeoutInSeconds = 600
module.exports.setup = (app) -> connectToScoringQueue()
@@ -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/routes/mail.coffee b/server/routes/mail.coffee
index b75acfce7..4d905b4d1 100644
--- a/server/routes/mail.coffee
+++ b/server/routes/mail.coffee
@@ -361,7 +361,7 @@ employersEmailedDigestMoreThanWeekAgoFilter = (employer, cb) ->
"user": employer._id
"mailTask": @mailTaskName
"sent":
- $gt: new Date(@currentTime.getTime() - 7 * 24 * 60 * 60 * 1000)
+ $gt: new Date(@currentTime.getTime() - 14 * 24 * 60 * 60 * 1000)
MailSent.find(findParameters).lean().exec (err, sentMail) ->
if err?
log.error "Error finding mail sent for task #{@mailTaskName} and employer #employer._id}!"
@@ -384,6 +384,8 @@ sendEmployerNewCandidatesAvailableEmail = (employer, cb) ->
]
User.count countParameters, (err, numberOfCandidatesSinceLogin) =>
if err? then return cb err
+ if numberOfCandidatesSinceLogin < 4
+ return cb null
context =
email_id: "tem_CCcHKr95Nvu5bT7c7iHCtm"
recipient:
@@ -479,26 +481,30 @@ sendUserRemarkTaskEmail = (task, cb) ->
mailTaskName = @mailTaskName
User.findOne("_id":task.contact).select("email").lean().exec (err, contact) ->
if err? then return cb err
- context =
- email_id: "tem_aryDjyw6JmEmbKtCMTSwAM"
- recipient:
- address: contact.email
- email_data:
- candidate_link: "http://codecombat.com/account/profile/#{task.user}"
- due_date: task.date
- log.info "Sending recruitment task reminder to #{contact.email}"
- newSentMail =
- mailTask: mailTaskName
- user: task.contact
- "metadata":
- remarkID: task.remarkID
- taskAction: task.action
- date: task.date
- MailSent.create newSentMail, (err) ->
+ User.findOne("_id":task.user).select("jobProfile.name").lean().exec (err, user) ->
if err? then return cb err
- sendwithus.api.send context, (err, result) ->
- log.error "Error sending #{mailTaskName} to #{contact.email}: #{err} with result #{result}" if err
- cb null
+ context =
+ email_id: "tem_aryDjyw6JmEmbKtCMTSwAM"
+ recipient:
+ address: contact.email
+ email_data:
+ task_text: task.action
+ candidate_name: user.jobProfile?.name ? "(Name not listed in job profile)"
+ candidate_link: "http://codecombat.com/account/profile/#{task.user}"
+ due_date: task.date
+ log.info "Sending recruitment task reminder to #{contact.email}"
+ newSentMail =
+ mailTask: mailTaskName
+ user: task.contact
+ "metadata":
+ remarkID: task.remarkID
+ taskAction: task.action
+ date: task.date
+ MailSent.create newSentMail, (err) ->
+ if err? then return cb err
+ sendwithus.api.send context, (err, result) ->
+ log.error "Error sending #{mailTaskName} to #{contact.email}: #{err} with result #{result}" if err
+ cb null
### New Recruit Leaderboard Email ###
###
diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee
index dfc1de92f..de3484641 100644
--- a/server/users/user_handler.coffee
+++ b/server/users/user_handler.coffee
@@ -30,7 +30,7 @@ UserHandler = class UserHandler extends Handler
'name', 'photoURL', 'password', 'anonymous', 'wizardColor1', 'volume',
'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails',
'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage',
- 'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile'
+ 'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile', 'savedEmployerFilterAlerts'
]
getEditableProperties: (req, document) ->
@@ -241,33 +241,42 @@ 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
- sort = {}
- sort.changed = req.query.order if req.query.order
+ 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).sort(sort).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
+ sort = {}
+ sort.changed = req.query.order if req.query.order
- 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).sort(sort).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)
getRecentlyPlayed: (req, res, userID) ->
twoWeeksAgo = moment().subtract('days', 14).toDate()
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/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()