From 61ebc4d15bb0abd685e08f68498fd1077b16e5d1 Mon Sep 17 00:00:00 2001 From: Darredevil Date: Mon, 21 Jul 2014 03:52:34 +0300 Subject: [PATCH 01/47] Docs tab --- app/templates/editor/level/edit.jade | 5 ++++- app/views/editor/level/edit.coffee | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade index c1f372e29..e84ed276c 100644 --- a/app/templates/editor/level/edit.jade +++ b/app/templates/editor/level/edit.jade @@ -33,7 +33,8 @@ block header - var patches = level.get('patches') if patches && patches.length span.badge= patches.length - + li + a(href="#docs-component-view", data-toggle="tab", data-i18n="editor.docs-component-view") Documentation .navbar-header span.navbar-brand #{level.attributes.name} @@ -114,6 +115,8 @@ block outer_content div.tab-pane#editor-level-patches .patches-view + div.tab-pane#docs-component-view + div#error-view block footer \ No newline at end of file diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee index 62666f44a..d5321730b 100644 --- a/app/views/editor/level/edit.coffee +++ b/app/views/editor/level/edit.coffee @@ -16,6 +16,7 @@ LevelForkView = require './fork_view' SaveVersionModal = require 'views/modal/save_version_modal' PatchesView = require 'views/editor/patches_view' VersionHistoryView = require './versions_view' +ComponentDocsView = require 'views/docs/components_view' module.exports = class EditorLevelView extends RootView id: 'editor-level-view' @@ -71,6 +72,7 @@ module.exports = class EditorLevelView extends RootView @scriptsTab = @insertSubView new ScriptsTabView world: @world, supermodel: @supermodel, files: @files @componentsTab = @insertSubView new ComponentsTabView supermodel: @supermodel @systemsTab = @insertSubView new SystemsTabView supermodel: @supermodel + @componentDocsTab = @insertSubView new ComponentDocsView supermodel: @supermodel Backbone.Mediator.publish 'level-loaded', level: @level @showReadOnly() if me.get('anonymous') @patchesView = @insertSubView(new PatchesView(@level), @$el.find('.patches-view')) From 37b8790b58cdcf1fbf9e7c0265e5a184367ae51f Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Mon, 21 Jul 2014 08:02:53 -0700 Subject: [PATCH 02/47] Added task text and candidate name to task emails --- server/routes/mail.coffee | 42 +++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee index b75acfce7..b95c4cab9 100644 --- a/server/routes/mail.coffee +++ b/server/routes/mail.coffee @@ -479,26 +479,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 ### ### From ab4424c7aca3474a33b6c38f2fcddc4a6e4ab6a6 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Mon, 21 Jul 2014 08:13:09 -0700 Subject: [PATCH 03/47] Changed employer reminder to send every 14 days --- server/routes/mail.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee index b95c4cab9..81a7310ab 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}!" From 984be9980e80ccb53077e0d3ad846996c0b2f033 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Mon, 21 Jul 2014 08:32:44 -0700 Subject: [PATCH 04/47] Put minimum candidates available before employer email --- server/routes/mail.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/routes/mail.coffee b/server/routes/mail.coffee index 81a7310ab..4d905b4d1 100644 --- a/server/routes/mail.coffee +++ b/server/routes/mail.coffee @@ -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: From 6bc436aec2c4351e6bdb90b135d066cad09563f8 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Mon, 21 Jul 2014 09:44:40 -0700 Subject: [PATCH 05/47] Added saved employer filter alerts to schema --- app/schemas/models/user.coffee | 75 ++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee index 0ec4f4d61..34cedca35 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,27 @@ _.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','filterActive'] + }, { + phoneScreenFilter: phoneScreenFilter + schoolFilter: schoolFilter + locationFilter: locationFilter + roleFilter: roleFilter + seniorityFilter: seniorityFilter + visa: visa + filterActive: + title: 'Filter active' + description: 'Whether or not an employer will receive emails based on this filter' + type: 'boolean' + default: false + }) + points: {type: 'number'} activity: {type: 'object', description: 'Summary statistics about user activity', additionalProperties: c.activity} From 735a7082eeb8660fcb88a766048a7bd1b5ae2c5b Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Mon, 21 Jul 2014 10:01:49 -0700 Subject: [PATCH 06/47] Correction to filter schema --- app/schemas/models/user.coffee | 41 +++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee index 34cedca35..84c2b0f0b 100644 --- a/app/schemas/models/user.coffee +++ b/app/schemas/models/user.coffee @@ -183,12 +183,41 @@ _.extend UserSchema.properties, description: 'A saved filter set' required: ['phoneScreenFilter','schoolFilter','locationFilter','roleFilter','seniorityFilter','visa','filterActive'] }, { - phoneScreenFilter: phoneScreenFilter - schoolFilter: schoolFilter - locationFilter: locationFilter - roleFilter: roleFilter - seniorityFilter: seniorityFilter - visa: 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 filterActive: title: 'Filter active' description: 'Whether or not an employer will receive emails based on this filter' From e8ffb8980f232b52cc54578526a8b2550592bd43 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Mon, 21 Jul 2014 14:47:44 -0700 Subject: [PATCH 07/47] Removed filterActive from filter alerts --- app/schemas/models/user.coffee | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee index 84c2b0f0b..4796157f8 100644 --- a/app/schemas/models/user.coffee +++ b/app/schemas/models/user.coffee @@ -218,11 +218,6 @@ _.extend UserSchema.properties, items: type: visa.type enum: visa.enum - filterActive: - title: 'Filter active' - description: 'Whether or not an employer will receive emails based on this filter' - type: 'boolean' - default: false }) points: {type: 'number'} From f100c4ebbe0e9bbf3d335c1760f9f7e12949599f Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Mon, 21 Jul 2014 16:10:02 -0700 Subject: [PATCH 08/47] Add filter alerts to employer page --- app/schemas/models/user.coffee | 2 +- app/styles/employers.sass | 10 ++++++- app/templates/employers.jade | 10 ++++++- app/views/EmployersView.coffee | 47 ++++++++++++++++++++++++++++++-- server/users/user_handler.coffee | 2 +- 5 files changed, 64 insertions(+), 7 deletions(-) diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee index 4796157f8..47a164b5c 100644 --- a/app/schemas/models/user.coffee +++ b/app/schemas/models/user.coffee @@ -181,7 +181,7 @@ _.extend UserSchema.properties, }, c.object({ title: 'Saved filter set' description: 'A saved filter set' - required: ['phoneScreenFilter','schoolFilter','locationFilter','roleFilter','seniorityFilter','visa','filterActive'] + required: ['phoneScreenFilter','schoolFilter','locationFilter','roleFilter','seniorityFilter','visa'] }, { phoneScreenFilter: title: 'Phone screen filter values' 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/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/views/EmployersView.coffee b/app/views/EmployersView.coffee index 9bbfa1ef6..57ca3c78f 100644 --- a/app/views/EmployersView.coffee +++ b/app/views/EmployersView.coffee @@ -20,15 +20,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 +40,7 @@ module.exports = class EmployersView extends RootView afterRender: -> super() @sortTable() if @candidates.models.length + @renderSavedFilters() afterInsert: -> super() @@ -128,7 +130,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("""#{@generateFilterAlertDescription(filter)} """) + + + generateFilterAlertDescription: (filter) => + descriptionString = "" + for key in _.keys(filter).sort() + value = filter[key] + if key is "filterActive" or _.without(@defaultFilters[key],value...).length is 0 then continue + if descriptionString.length then descriptionString += ", " + descriptionString += value.join(", ") + if descriptionString.length is 0 then descriptionString = "Any new candidate" + return descriptionString + getActiveAndApprovedCandidates: => candidates = _.filter @candidates.models, (c) -> c.get('jobProfile').active return _.filter candidates, (c) -> c.get('jobProfileApproved') diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee index fbd13ec19..4a6e85320 100644 --- a/server/users/user_handler.coffee +++ b/server/users/user_handler.coffee @@ -29,7 +29,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) -> From 283108da1e0bc27b8731c725399518bee647664c Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Mon, 21 Jul 2014 16:59:42 -0700 Subject: [PATCH 09/47] Added login message for anonymous users on job profile --- app/styles/account/profile.sass | 8 +- app/templates/account/profile.jade | 980 +++++++++++++------------- app/views/account/profile_view.coffee | 3 + 3 files changed, 502 insertions(+), 489 deletions(-) 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/templates/account/profile.jade b/app/templates/account/profile.jade index 2699a3ac1..46a15da4e 100644 --- a/app/templates/account/profile.jade +++ b/app/templates/account/profile.jade @@ -1,492 +1,496 @@ 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 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]} + + .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/views/account/profile_view.coffee b/app/views/account/profile_view.coffee index ca33ba8e8..9a36039da 100644 --- a/app/views/account/profile_view.coffee +++ b/app/views/account/profile_view.coffee @@ -65,6 +65,9 @@ module.exports = class ProfileView extends RootView @authorizedWithLinkedIn = IN?.User?.isAuthorized() @render() super options + if me.get('anonymous') is true + @render() + return if User.isObjectID @userID @finishInit() else From a313c3ab27a62fed48920577edd05ebc886475d2 Mon Sep 17 00:00:00 2001 From: greyhusky Date: Tue, 22 Jul 2014 15:01:47 +0200 Subject: [PATCH 10/47] More translations Translated the "about" page and parts of "legal" page as well as some other stuff --- app/locale/de-CH.coffee | 456 ++++++++++++++++++++-------------------- 1 file changed, 228 insertions(+), 228 deletions(-) diff --git a/app/locale/de-CH.coffee b/app/locale/de-CH.coffee index d83d4959a..2ffce1674 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" From 22fabe13ea3a626cb07552af83a90995bbdabc00 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Tue, 22 Jul 2014 06:59:47 -0700 Subject: [PATCH 11/47] Increased scoring task timeout to 10 minutes Temporary increase until we can increase it only for Brawlwood --- server/queues/scoring.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee index 9f68f0cc1..d35ce871a 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() From 574252df32d963e44dc2aae0284ea3f411cfdb36 Mon Sep 17 00:00:00 2001 From: George Saines Date: Tue, 22 Jul 2014 09:11:25 -0700 Subject: [PATCH 12/47] subbing in Pavel's better tiny programming language icons --- .../images/common/code_languages/io_icon.png | Bin 4113 -> 2964 bytes .../common/code_languages/javascript_icon.png | Bin 3976 -> 2940 bytes 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 app/assets/images/common/code_languages/io_icon.png mode change 100644 => 100755 app/assets/images/common/code_languages/javascript_icon.png 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 0b6c58fe4eafcd179cb0df77a7fe4123a42c8903..14f04afc3374f31129b928c87ae1398e290e4d89 GIT binary patch delta 2941 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 F{{(R7Ih+6h From a377e6c05de148f733a00653532f0ac6b1888032 Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Tue, 22 Jul 2014 21:20:59 +0200 Subject: [PATCH 13/47] updated zatanna version --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index e979e2f49..87630ea99 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.3", "modernizr": "~2.8.3" }, "overrides": { From 5db634d6a855898ed609b0cdbc713a5ae5639b33 Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Tue, 22 Jul 2014 21:47:36 +0200 Subject: [PATCH 14/47] fullscreen on keyboard shortcut --- app/views/play/level/tome/spell_list_tab_entry_view.coffee | 1 + app/views/play/level/tome/spell_view.coffee | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/app/views/play/level/tome/spell_list_tab_entry_view.coffee b/app/views/play/level/tome/spell_list_tab_entry_view.coffee index 877229f54..7480be3cf 100644 --- a/app/views/play/level/tome/spell_list_tab_entry_view.coffee +++ b/app/views/play/level/tome/spell_list_tab_entry_view.coffee @@ -13,6 +13,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView 'tome:spell-changed': 'onSpellChanged' 'god:new-world-created': 'onNewWorld' 'tome:spell-changed-language': 'onSpellChangedLanguage' + 'tome:fullscreen-view': 'onFullscreenClick' events: 'click .spell-list-button': 'onDropdownClick' diff --git a/app/views/play/level/tome/spell_view.coffee b/app/views/play/level/tome/spell_view.coffee index 46fb62e4e..73a129ee3 100644 --- a/app/views/play/level/tome/spell_view.coffee +++ b/app/views/play/level/tome/spell_view.coffee @@ -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 From be50927fb609ae0f3627033564c30d6a1be18257 Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Wed, 23 Jul 2014 14:38:12 +0200 Subject: [PATCH 15/47] disabled editor works again --- app/lib/image_filter.coffee | 10 +++++--- app/styles/play/level/tome/problem_alert.sass | 5 ++-- .../play/level/tome/spell_list_tab_entry.jade | 2 ++ .../tome/spell_list_tab_entry_view.coffee | 23 ++++++++++++++----- .../play/level/tome/spell_palette_view.coffee | 6 ++--- app/views/play/level/tome/spell_view.coffee | 6 ++--- 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/app/lib/image_filter.coffee b/app/lib/image_filter.coffee index 11bf70d76..6f3cc50a3 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(' + img.src + ')' img.src = jqimg.data('original') 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/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/views/play/level/tome/spell_list_tab_entry_view.coffee b/app/views/play/level/tome/spell_list_tab_entry_view.coffee index 7480be3cf..8a2500667 100644 --- a/app/views/play/level/tome/spell_list_tab_entry_view.coffee +++ b/app/views/play/level/tome/spell_list_tab_entry_view.coffee @@ -3,12 +3,15 @@ ThangAvatarView = require 'views/play/level/thang_avatar_view' template = require 'templates/play/level/tome/spell_list_tab_entry' LevelComponent = require 'models/LevelComponent' DocFormatter = require './doc_formatter' +filters = require 'lib/image_filter' module.exports = class SpellListTabEntryView extends SpellListEntryView template: template id: 'spell-list-tab-entry-view' subscriptions: + 'level-disable-controls': 'onDisableControls' + 'level-enable-controls': 'onEnableControls' 'tome:spell-loaded': 'onSpellLoaded' 'tome:spell-changed': 'onSpellChanged' 'god:new-world-created': 'onNewWorld' @@ -75,6 +78,8 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView onMouseEnterAvatar: (e) -> # Don't call super onMouseLeaveAvatar: (e) -> # Don't call super onClick: (e) -> # Don't call super + onDisableControls: (e) -> @toggleControls e, false + onEnableControls: (e) -> @toggleControls e, true onDropdownClick: (e) -> return unless @controlsEnabled @@ -89,12 +94,8 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView Backbone.Mediator.publish 'spell-beautify', spell: @spell onFullscreenClick: -> - unless $('.fullscreen-code').hasClass 'maximized' - $('#code-area').addClass 'fullscreen-editor' - $('.fullscreen-code').addClass 'maximized' - else - $('#code-area').removeClass 'fullscreen-editor' - $('.fullscreen-code').removeClass 'maximized' + $('#code-area').toggleClass 'fullscreen-editor' + $('.fullscreen-code').toggleClass 'maximized' updateReloadButton: -> changed = @spell.hasChanged null, @spell.getSource() @@ -122,6 +123,16 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView return if enabled is @controlsEnabled @controlsEnabled = enabled @$el.toggleClass 'read-only', not enabled + @toggleBackground() + + toggleBackground: => + # TODO: make the palette background an actual background and do the CSS trick + # used in spell_list_entry.sass for disabling + background = @$el.find('img.spell-tab-image-hidden')[0] + if background.naturalWidth is 0 # not loaded yet + return _.delay @toggleBackground, 100 + filters.revertImage background, '.spell-list-entry-view.spell-tab' if @controlsEnabled + filters.darkenImage background, '.spell-list-entry-view.spell-tab', 0.8 unless @controlsEnabled destroy: -> @avatar?.destroy() diff --git a/app/views/play/level/tome/spell_palette_view.coffee b/app/views/play/level/tome/spell_palette_view.coffee index 89914fb3e..5641e8fb9 100644 --- a/app/views/play/level/tome/spell_palette_view.coffee +++ b/app/views/play/level/tome/spell_palette_view.coffee @@ -150,11 +150,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_view.coffee b/app/views/play/level/tome/spell_view.coffee index 73a129ee3..d5ef1c6b7 100644 --- a/app/views/play/level/tome/spell_view.coffee +++ b/app/views/play/level/tome/spell_view.coffee @@ -634,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) From 9cb704a843561d4ff0f304e8aa98dd58713dbc8a Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Wed, 23 Jul 2014 15:09:15 +0200 Subject: [PATCH 16/47] last fix for dimming the editor --- app/lib/image_filter.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/image_filter.coffee b/app/lib/image_filter.coffee index 6f3cc50a3..20a2ec9ae 100644 --- a/app/lib/image_filter.coffee +++ b/app/lib/image_filter.coffee @@ -49,5 +49,5 @@ module.exports.darkenImage = darkenImage = (img, borderImageSelector, pct=0.5) - module.exports.revertImage = revertImage = (img, borderImageSelector) -> jqimg = $(img) return unless jqimg.data('original') - $(borderImageSelector).css 'border-image-source', 'url(' + img.src + ')' + $(borderImageSelector).css 'border-image-source', 'url(' + jqimg.data('original') + ')' img.src = jqimg.data('original') From 72c1bb28b334d3e64fe183dcd7dbb670707cac1a Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Wed, 23 Jul 2014 15:26:22 +0200 Subject: [PATCH 17/47] fixed artefact --- app/styles/play/level/tome/spell.sass | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 4f6ca5335f10ab94c5b7f9db16ea416176261ad5 Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Wed, 23 Jul 2014 15:50:47 +0200 Subject: [PATCH 18/47] fixed spell palette sliding behind HUD --- app/styles/play/level.sass | 1 - .../tome/spell_list_tab_entry_view.coffee | 20 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) 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/views/play/level/tome/spell_list_tab_entry_view.coffee b/app/views/play/level/tome/spell_list_tab_entry_view.coffee index 8a2500667..84816d112 100644 --- a/app/views/play/level/tome/spell_list_tab_entry_view.coffee +++ b/app/views/play/level/tome/spell_list_tab_entry_view.coffee @@ -34,6 +34,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView afterRender: -> super() @$el.addClass 'spell-tab' + @attachTransitionEventListener() onNewWorld: (e) -> @thang = e.world.thangMap[@thang.id] if @thang @@ -94,6 +95,8 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView Backbone.Mediator.publish 'spell-beautify', spell: @spell onFullscreenClick: -> + $codearea = $('#code-area') + $codearea.css 'z-index', 20 unless $codearea.hasClass 'fullscreen-editor' $('#code-area').toggleClass 'fullscreen-editor' $('.fullscreen-code').toggleClass 'maximized' @@ -134,6 +137,23 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView filters.revertImage background, '.spell-list-entry-view.spell-tab' if @controlsEnabled filters.darkenImage background, '.spell-list-entry-view.spell-tab', 0.8 unless @controlsEnabled + attachTransitionEventListener: => + transitionListener = '' + testEl = document.createElement 'fakeelement' + transitions = + 'transition':'transitionend' + 'OTransition':'oTransitionEnd' + 'MozTransition':'transitionend' + 'WebkitTransition':'webkitTransitionEnd' + for transition, transitionEvent of transitions + unless testEl.style[transition] is undefined + transitionListener = transitionEvent + break + $codearea = $('#code-area') + $codearea.on transitionListener, => + $codearea.css 'z-index', 1 unless $codearea.hasClass 'fullscreen-editor' + + destroy: -> @avatar?.destroy() @$el.find('code').popover 'destroy' From 1c3404d03eda61018e2a98246d3fe49636888fb3 Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Wed, 23 Jul 2014 07:02:45 -0700 Subject: [PATCH 19/47] Refactored views. View file names now match view class names. Router lists routes explicitly rather than routing automagically. Hacking my way to renaming problem, spell. --- app/{lib => }/Router.coffee | 174 +++++++----------- app/application.coffee | 3 +- app/initialize.coffee | 4 +- app/templates/admin.jade | 4 +- app/templates/base.jade | 2 +- app/templates/contribute/ambassador.jade | 2 +- app/templates/contribute/archmage.jade | 2 +- app/templates/contribute/scribe.jade | 2 +- app/templates/editor.jade | 2 +- app/templates/editor/article/edit.jade | 2 +- app/templates/editor/level/edit.jade | 6 +- app/templates/editor/thang/edit.jade | 2 +- app/templates/kinds/search.jade | 2 +- app/templates/modal/auth.jade | 2 +- .../modal/employer_signup_modal.jade | 4 +- app/templates/play/ladder/ladder_tab.jade | 2 +- app/templates/play/level.jade | 2 +- app/templates/play/level/modal/victory.jade | 2 +- app/templates/play/spectate.jade | 2 +- app/templates/teachers.jade | 2 +- app/views/EmployersView.coffee | 9 +- app/views/HomeView.coffee | 1 - ...view.coffee => AccountSettingsView.coffee} | 18 +- app/views/account/JobProfileCodeModal.coffee | 1 - app/views/account/JobProfileTreemaView.coffee | 131 +++++++++++++ ...file_view.coffee => JobProfileView.coffee} | 12 +- ...ibe_view.coffee => UnsubscribeView.coffee} | 0 ..._view.coffee => WizardSettingsView.coffee} | 0 app/views/account/job_profile_view.coffee | 131 ------------- .../{clas_view.coffee => CLAsView.coffee} | 0 ...ates_view.coffee => CandidatesView.coffee} | 9 +- ...t_view.coffee => EmployersListView.coffee} | 5 +- .../{files_view.coffee => FilesView.coffee} | 0 ...s_view.coffee => LevelSessionsView.coffee} | 0 .../MainAdminView.coffee} | 2 +- .../{users_view.coffee => UsersView.coffee} | 0 app/views/admin/base_view.coffee | 6 - .../contribute/ContributeClassView.coffee | 2 +- ...ffee => ComponentDocumentationView.coffee} | 2 +- .../editor/{delta.coffee => DeltaView.coffee} | 0 .../{patch_modal.coffee => PatchModal.coffee} | 2 +- ...patches_view.coffee => PatchesView.coffee} | 2 +- ...edit.coffee => AchievementEditView.coffee} | 2 +- ...me.coffee => AchievementSearchView.coffee} | 0 .../{edit.coffee => ArticleEditView.coffee} | 8 +- ...eview.coffee => ArticlePreviewView.coffee} | 2 +- .../{home.coffee => ArticleSearchView.coffee} | 2 +- ...iew.coffee => ArticleVersionsModal.coffee} | 4 +- ...w.coffee => ComponentVersionsModal.coffee} | 4 +- .../ThangComponentConfigView.coffee} | 2 +- .../ThangComponentEditView.coffee} | 2 +- .../{edit.coffee => LevelEditView.coffee} | 24 +-- .../{home.coffee => LevelSearchView.coffee} | 2 +- .../ComponentsTabView.coffee} | 4 +- .../LevelComponentEditView.coffee} | 10 +- .../NewLevelComponentModal.coffee} | 2 +- .../ForkLevelModal.coffee} | 2 +- .../LevelVersionsModal.coffee} | 4 +- .../SaveLevelModal.coffee} | 8 +- .../TerrainRandomizeModal.coffee} | 0 .../WorldSelectModal.coffee} | 0 .../ScriptsTabView.coffee} | 2 +- .../SettingsTabView.coffee} | 2 +- .../AddLevelSystemModal.coffee} | 2 +- .../LevelSystemEditView.coffee} | 10 +- .../NewLevelSystemModal.coffee} | 2 +- .../systems/SystemVersionsModal.coffee} | 4 +- .../SystemsTabView.coffee} | 14 +- .../AddThangsView.coffee} | 0 .../LevelThangEditView.coffee} | 2 +- .../ThangsTabView.coffee} | 4 +- app/views/editor/level/treema_nodes.coffee | 2 +- ...w.coffee => ThangTypeColorsTabView.coffee} | 2 +- .../{edit.coffee => ThangTypeEditView.coffee} | 16 +- ...home.coffee => ThangTypeSearchView.coffee} | 2 +- ...w.coffee => ThangTypeVersionsModal.coffee} | 4 +- app/views/kinds/CocoView.coffee | 4 +- app/views/kinds/RootView.coffee | 7 +- .../{auth_modal.coffee => AuthModal.coffee} | 2 +- .../{confirm.coffee => ConfirmModal.coffee} | 0 ...ntact_modal.coffee => ContactModal.coffee} | 2 +- ....coffee => DiplomatSuggestionModal.coffee} | 2 +- ...odal.coffee => EmployerSignupModal.coffee} | 2 +- ...l.coffee => JobProfileContactModal.coffee} | 4 +- .../{model_modal.coffee => ModelModal.coffee} | 0 ...cover_modal.coffee => RecoverModal.coffee} | 2 +- ...revert_modal.coffee => RevertModal.coffee} | 0 ...n_modal.coffee => SaveVersionModal.coffee} | 2 +- ...signup_modal.coffee => SignupModal.coffee} | 2 +- ...ions_modal.coffee => VersionsModal.coffee} | 6 +- ...odal.coffee => WizardSettingsModal.coffee} | 2 +- ...ectate_view.coffee => SpectateView.coffee} | 20 +- ...iew.coffee => LadderSubmissionView.coffee} | 0 ...ay_modal.coffee => LadderPlayModal.coffee} | 0 ...ladder_tab.coffee => LadderTabView.coffee} | 2 +- .../{ladder_view.coffee => LadderView.coffee} | 12 +- .../MainLadderView.coffee} | 0 ...hes_tab.coffee => MyMatchesTabView.coffee} | 2 +- ...late_tab.coffee => SimulateTabView.coffee} | 0 ..._bar_view.coffee => ControlBarView.coffee} | 8 +- ...nimator.coffee => DialogueAnimator.coffee} | 0 ..._chat_view.coffee => LevelChatView.coffee} | 0 ...oals_view.coffee => LevelGoalsView.coffee} | 2 +- ...{gold_view.coffee => LevelGoldView.coffee} | 2 +- .../{hud_view.coffee => LevelHUDView.coffee} | 4 +- ...ng_view.coffee => LevelLoadingView.coffee} | 0 ...k_view.coffee => LevelPlaybackView.coffee} | 6 +- .../PlayLevelView.coffee} | 26 +-- ...tar_view.coffee => ThangAvatarView.coffee} | 0 ..._modal.coffee => EditorConfigModal.coffee} | 0 ..._modal.coffee => InfiniteLoopModal.coffee} | 0 ...l.coffee => KeyboardShortcutsModal.coffee} | 0 ...cs_modal.coffee => LevelGuideModal.coffee} | 2 +- ...r_modal.coffee => MultiplayerModal.coffee} | 2 +- ...d_modal.coffee => ReloadLevelModal.coffee} | 2 +- ...ctory_modal.coffee => VictoryModal.coffee} | 2 +- ...tton_view.coffee => CastButtonView.coffee} | 0 ...c_formatter.coffee => DocFormatter.coffee} | 0 ...rt_view.coffee => ProblemAlertView.coffee} | 0 ...ebug_view.coffee => SpellDebugView.coffee} | 2 +- ...coffee => SpellListEntryThangsView.coffee} | 2 +- ..._view.coffee => SpellListEntryView.coffee} | 4 +- ...ew.coffee => SpellListTabEntryView.coffee} | 6 +- ..._list_view.coffee => SpellListView.coffee} | 2 +- ...ew.coffee => SpellPaletteEntryView.coffee} | 2 +- ...te_view.coffee => SpellPaletteView.coffee} | 4 +- ...ar_view.coffee => SpellToolbarView.coffee} | 0 .../{spell_view.coffee => SpellView.coffee} | 6 +- ..._view.coffee => ThangListEntryView.coffee} | 2 +- ..._list_view.coffee => ThangListView.coffee} | 2 +- .../{tome_view.coffee => TomeView.coffee} | 10 +- .../tome/{problem.coffee => pproblem.coffee} | 2 +- .../tome/{spell.coffee => sspell.coffee} | 4 +- test/app/require.spec.coffee | 9 + .../editor/level/EditorLevelView.spec.coffee | 6 +- test/app/views/home_view.spec.coffee | 0 ...View.spec.coffee => AuthModal.spec.coffee} | 10 +- ...r_tab.spec.coffee => LadderTabView.coffee} | 2 +- .../views/user/JobProfileView.demo.coffee | 4 +- 139 files changed, 438 insertions(+), 476 deletions(-) rename app/{lib => }/Router.coffee (62%) rename app/views/account/{settings_view.coffee => AccountSettingsView.coffee} (94%) create mode 100644 app/views/account/JobProfileTreemaView.coffee rename app/views/account/{profile_view.coffee => JobProfileView.coffee} (97%) rename app/views/account/{unsubscribe_view.coffee => UnsubscribeView.coffee} (100%) rename app/views/account/{wizard_settings_view.coffee => WizardSettingsView.coffee} (100%) delete mode 100644 app/views/account/job_profile_view.coffee rename app/views/admin/{clas_view.coffee => CLAsView.coffee} (100%) rename app/views/admin/{candidates_view.coffee => CandidatesView.coffee} (96%) rename app/views/admin/{employer_list_view.coffee => EmployersListView.coffee} (97%) rename app/views/admin/{files_view.coffee => FilesView.coffee} (100%) rename app/views/admin/{level_sessions_view.coffee => LevelSessionsView.coffee} (100%) rename app/views/{AdminView.coffee => admin/MainAdminView.coffee} (94%) rename app/views/admin/{users_view.coffee => UsersView.coffee} (100%) delete mode 100644 app/views/admin/base_view.coffee rename app/views/docs/{components_view.coffee => ComponentDocumentationView.coffee} (95%) rename app/views/editor/{delta.coffee => DeltaView.coffee} (100%) rename app/views/editor/{patch_modal.coffee => PatchModal.coffee} (98%) rename app/views/editor/{patches_view.coffee => PatchesView.coffee} (97%) rename app/views/editor/achievement/{edit.coffee => AchievementEditView.coffee} (98%) rename app/views/editor/achievement/{home.coffee => AchievementSearchView.coffee} (100%) rename app/views/editor/article/{edit.coffee => ArticleEditView.coffee} (92%) rename app/views/editor/article/{preview.coffee => ArticlePreviewView.coffee} (72%) rename app/views/editor/article/{home.coffee => ArticleSearchView.coffee} (89%) rename app/views/editor/article/{versions_view.coffee => ArticleVersionsModal.coffee} (55%) rename app/views/editor/component/{versions_view.coffee => ComponentVersionsModal.coffee} (58%) rename app/views/editor/{components/config.coffee => component/ThangComponentConfigView.coffee} (96%) rename app/views/editor/{components/main.coffee => component/ThangComponentEditView.coffee} (99%) rename app/views/editor/level/{edit.coffee => LevelEditView.coffee} (88%) rename app/views/editor/level/{home.coffee => LevelSearchView.coffee} (89%) rename app/views/editor/level/{components_tab_view.coffee => components/ComponentsTabView.coffee} (97%) rename app/views/editor/level/{component/edit.coffee => components/LevelComponentEditView.coffee} (94%) rename app/views/editor/level/{component/new.coffee => components/NewLevelComponentModal.coffee} (95%) rename app/views/editor/level/{fork_view.coffee => modals/ForkLevelModal.coffee} (95%) rename app/views/editor/level/{versions_view.coffee => modals/LevelVersionsModal.coffee} (55%) rename app/views/editor/level/{save_view.coffee => modals/SaveLevelModal.coffee} (95%) rename app/views/editor/level/{modal/terrain_randomize_modal.coffee => modals/TerrainRandomizeModal.coffee} (100%) rename app/views/editor/level/{modal/world_select.coffee => modals/WorldSelectModal.coffee} (100%) rename app/views/editor/level/{scripts_tab_view.coffee => scripts/ScriptsTabView.coffee} (99%) rename app/views/editor/level/{settings_tab_view.coffee => settings/SettingsTabView.coffee} (98%) rename app/views/editor/level/{system/add.coffee => systems/AddLevelSystemModal.coffee} (97%) rename app/views/editor/level/{system/edit.coffee => systems/LevelSystemEditView.coffee} (93%) rename app/views/editor/level/{system/new.coffee => systems/NewLevelSystemModal.coffee} (95%) rename app/views/editor/{system/versions_view.coffee => level/systems/SystemVersionsModal.coffee} (57%) rename app/views/editor/level/{systems_tab_view.coffee => systems/SystemsTabView.coffee} (93%) rename app/views/editor/level/{add_thangs_view.coffee => thangs/AddThangsView.coffee} (100%) rename app/views/editor/level/{thang/edit.coffee => thangs/LevelThangEditView.coffee} (97%) rename app/views/editor/level/{thangs_tab_view.coffee => thangs/ThangsTabView.coffee} (99%) rename app/views/editor/thang/{colors_tab_view.coffee => ThangTypeColorsTabView.coffee} (98%) rename app/views/editor/thang/{edit.coffee => ThangTypeEditView.coffee} (96%) rename app/views/editor/thang/{home.coffee => ThangTypeSearchView.coffee} (91%) rename app/views/editor/thang/{versions_view.coffee => ThangTypeVersionsModal.coffee} (55%) rename app/views/modal/{auth_modal.coffee => AuthModal.coffee} (98%) rename app/views/modal/{confirm.coffee => ConfirmModal.coffee} (100%) rename app/views/modal/{contact_modal.coffee => ContactModal.coffee} (94%) rename app/views/modal/{diplomat_suggestion_modal.coffee => DiplomatSuggestionModal.coffee} (87%) rename app/views/modal/{employer_signup_modal.coffee => EmployerSignupModal.coffee} (98%) rename app/views/modal/{job_profile_contact_modal.coffee => JobProfileContactModal.coffee} (91%) rename app/views/modal/{model_modal.coffee => ModelModal.coffee} (100%) rename app/views/modal/{recover_modal.coffee => RecoverModal.coffee} (95%) rename app/views/modal/{revert_modal.coffee => RevertModal.coffee} (100%) rename app/views/modal/{save_version_modal.coffee => SaveVersionModal.coffee} (98%) rename app/views/modal/{signup_modal.coffee => SignupModal.coffee} (62%) rename app/views/modal/{versions_modal.coffee => VersionsModal.coffee} (93%) rename app/views/modal/{wizard_settings_modal.coffee => WizardSettingsModal.coffee} (96%) rename app/views/play/{spectate_view.coffee => SpectateView.coffee} (97%) rename app/views/play/common/{ladder_submission_view.coffee => LadderSubmissionView.coffee} (100%) rename app/views/play/ladder/{play_modal.coffee => LadderPlayModal.coffee} (100%) rename app/views/play/ladder/{ladder_tab.coffee => LadderTabView.coffee} (99%) rename app/views/play/ladder/{ladder_view.coffee => LadderView.coffee} (92%) rename app/views/play/{ladder_home.coffee => ladder/MainLadderView.coffee} (100%) rename app/views/play/ladder/{my_matches_tab.coffee => MyMatchesTabView.coffee} (98%) rename app/views/play/ladder/{simulate_tab.coffee => SimulateTabView.coffee} (100%) rename app/views/play/level/{control_bar_view.coffee => ControlBarView.coffee} (93%) rename app/views/play/level/{dialogue_animator.coffee => DialogueAnimator.coffee} (100%) rename app/views/play/level/{level_chat_view.coffee => LevelChatView.coffee} (100%) rename app/views/play/level/{goals_view.coffee => LevelGoalsView.coffee} (98%) rename app/views/play/level/{gold_view.coffee => LevelGoldView.coffee} (96%) rename app/views/play/level/{hud_view.coffee => LevelHUDView.coffee} (99%) rename app/views/play/level/{level_loading_view.coffee => LevelLoadingView.coffee} (100%) rename app/views/play/level/{playback_view.coffee => LevelPlaybackView.coffee} (98%) rename app/views/play/{level_view.coffee => level/PlayLevelView.coffee} (96%) rename app/views/play/level/{thang_avatar_view.coffee => ThangAvatarView.coffee} (100%) rename app/views/play/level/modal/{editor_config_modal.coffee => EditorConfigModal.coffee} (100%) rename app/views/play/level/modal/{infinite_loop_modal.coffee => InfiniteLoopModal.coffee} (100%) rename app/views/play/level/modal/{keyboard_shortcuts_modal.coffee => KeyboardShortcutsModal.coffee} (100%) rename app/views/play/level/modal/{docs_modal.coffee => LevelGuideModal.coffee} (96%) rename app/views/play/level/modal/{multiplayer_modal.coffee => MultiplayerModal.coffee} (96%) rename app/views/play/level/modal/{reload_modal.coffee => ReloadLevelModal.coffee} (84%) rename app/views/play/level/modal/{victory_modal.coffee => VictoryModal.coffee} (98%) rename app/views/play/level/tome/{cast_button_view.coffee => CastButtonView.coffee} (100%) rename app/views/play/level/tome/{doc_formatter.coffee => DocFormatter.coffee} (100%) rename app/views/play/level/tome/{problem_alert_view.coffee => ProblemAlertView.coffee} (100%) rename app/views/play/level/tome/{spell_debug_view.coffee => SpellDebugView.coffee} (99%) rename app/views/play/level/tome/{spell_list_entry_thangs_view.coffee => SpellListEntryThangsView.coffee} (94%) rename app/views/play/level/tome/{spell_list_entry_view.coffee => SpellListEntryView.coffee} (97%) rename app/views/play/level/tome/{spell_list_tab_entry_view.coffee => SpellListTabEntryView.coffee} (95%) rename app/views/play/level/tome/{spell_list_view.coffee => SpellListView.coffee} (98%) rename app/views/play/level/tome/{spell_palette_entry_view.coffee => SpellPaletteEntryView.coffee} (98%) rename app/views/play/level/tome/{spell_palette_view.coffee => SpellPaletteView.coffee} (98%) rename app/views/play/level/tome/{spell_toolbar_view.coffee => SpellToolbarView.coffee} (100%) rename app/views/play/level/tome/{spell_view.coffee => SpellView.coffee} (99%) rename app/views/play/level/tome/{thang_list_entry_view.coffee => ThangListEntryView.coffee} (98%) rename app/views/play/level/tome/{thang_list_view.coffee => ThangListView.coffee} (98%) rename app/views/play/level/tome/{tome_view.coffee => TomeView.coffee} (97%) rename app/views/play/level/tome/{problem.coffee => pproblem.coffee} (96%) rename app/views/play/level/tome/{spell.coffee => sspell.coffee} (98%) create mode 100644 test/app/require.spec.coffee delete mode 100644 test/app/views/home_view.spec.coffee rename test/app/views/modal/{AuthModalView.spec.coffee => AuthModal.spec.coffee} (53%) rename test/app/views/play/ladder/{ladder_tab.spec.coffee => LadderTabView.coffee} (91%) diff --git a/app/lib/Router.coffee b/app/Router.coffee similarity index 62% rename from app/lib/Router.coffee rename to app/Router.coffee index 2c3a026a3..ca6af592b 100644 --- a/app/lib/Router.coffee +++ b/app/Router.coffee @@ -6,7 +6,10 @@ NotFoundView = require('views/NotFoundView') go = (path) -> -> @routeDirectly path, arguments module.exports = class CocoRouter extends Backbone.Router - subscribe: -> + + initialize: -> + # http://nerds.airbnb.com/how-to-add-google-analytics-page-tracking-to-57536 + @bind 'route', @_trackPageView Backbone.Mediator.subscribe 'gapi-loaded', @onGPlusAPILoaded, @ Backbone.Mediator.subscribe 'router:navigate', @onNavigate, @ @@ -14,12 +17,24 @@ module.exports = class CocoRouter extends Backbone.Router '': go('HomeView') 'about': go('AboutView') - 'admin': go('AdminView') + + 'account/profile(/:userID)': go('account/JobProfileView') + 'account/settings': go('account/AccountSettingsView') + 'account/unsubscribe': go('account/UnsubscribeView') + + 'admin': go('admin/MainAdminView') + 'admin/candidates': go('admin/CandidatesView') + 'admin/clas': go('admin/CLAsView') + 'admin/employers': go('admin/EmployersListView') + 'admin/files': go('admin/FilesView') + 'admin/level-sessions': go('admin/LevelSessionsView') + 'admin/users': go('admin/UsersView') 'beta': go('HomeView') 'cla': go('CLAView') 'community': go('CommunityView') + 'contribute': go('contribute/MainContributeView') 'contribute/adventurer': go('contribute/AdventurerView') 'contribute/ambassador': go('contribute/AmbassadorView') @@ -28,71 +43,84 @@ module.exports = class CocoRouter extends Backbone.Router 'contribute/diplomat': go('contribute/DiplomatView') 'contribute/scribe': go('contribute/ScribeView') + 'db/*path': 'routeToServer' 'demo(/*subpath)': go('DemoView') + 'docs/components': go('docs/ComponentDocumentationView') 'editor': go('editor/MainEditorView') - 'employers': go('EmployersView') + + 'editor/achievement': go('editor/achievement/AchievementSearchView') + 'editor/achievement': go('editor/achievement/AchievementEditView') + 'editor/article': go('editor/article/ArticleSearchView') + 'editor/article/preview': go('editor/article/ArticlePreviewView') + 'editor/article/:articleID': go('editor/article/ArticleEditView') + 'editor/level': go('editor/level/LevelSearchView') + 'editor/level/:levelID': go('editor/level/LevelEditView') + 'editor/thang': go('editor/thang/ThangTypeSearchView') + 'editor/thang/:thangID': go('editor/thang/ThangTypeEditView') + 'employers': go('EmployersView') + + 'file/*path': 'routeToServer' + 'legal': go('LegalView') 'multiplayer': go('MultiplayerView') 'play': go('play/MainPlayView') + 'play/ladder/:levelID': go('play/ladder/LadderView') + 'play/ladder': go('play/ladder/MainLadderView') + 'play/level/:levelID': go('play/level/PlayLevelView') + 'play/spectate/:levelID': go('play/SpectateView') + 'preview': go('HomeView') 'teachers': go('TeachersView') + 'test(/*subpath)': go('TestView') + '*name': 'showNotFoundView' - # editor views tend to have the same general structure - 'editor/:model(/:slug_or_id)(/:subview)': 'editorModelView' + routeToServer: (e) -> + window.location.href = window.location.href - # Direct links - - - 'play/ladder/:levelID': go('play/ladder/ladder_view') - 'play/ladder': go('play/ladder_home') - - # db and file urls call the server directly - 'db/*path': 'routeToServer' - 'file/*path': 'routeToServer' - - # most go through here - '*name': 'general' - - home: -> @openRoute('home') - general: (name) -> - @openRoute(name) - - editorModelView: (modelName, slugOrId, subview) -> - modulePrefix = "views/editor/#{modelName}/" - suffix = subview or (if slugOrId then 'edit' else 'home') - ViewClass = @tryToLoadModule(modulePrefix + suffix) - unless ViewClass - #console.log('could not hack it', modulePrefix + suffix) - args = (a for a in arguments when a) - args.splice(0, 0, 'editor') - return @openRoute(args.join('/')) - view = new ViewClass({}, slugOrId) + routeDirectly: (path, args) -> + path = "views/#{path}" + ViewClass = @tryToLoadModule path + return @openView @notFoundView() if not ViewClass + view = new ViewClass({}, args...) # options, then any path fragment args view.render() - @openView if view then view else @notFoundView() - - cache: {} - openRoute: (route) -> - route = route.split('?')[0] - route = route.split('#')[0] - view = @getViewFromCache(route) @openView(view) + tryToLoadModule: (path) -> + try + return require(path) + catch error + if error.toString().search('Cannot find module "' + path + '" from') is -1 + throw error + + showNotFoundView: -> + @openView @notFoundView() + + notFoundView: -> + view = new NotFoundView() + view.render() + openView: (view) -> @closeCurrentView() $('#page-container').empty().append view.el window.currentView = view @activateTab() @renderLoginButtons() - window.scrollTo(0, view.scrollY) if view.scrollY? view.afterInsert() - view.didReappear() if view.fromCache + view.didReappear() + + closeCurrentView: -> + if window.currentView?.reloadOnClose + return document.location.reload() + window.currentModal?.hide?() + return unless window.currentView? + window.currentView.destroy() onGPlusAPILoaded: => @renderLoginButtons() @@ -117,71 +145,10 @@ module.exports = class CocoRouter extends Backbone.Router else console.warn 'Didn\'t have gapi.signin to render G+ login button. (DoNotTrackMe extension?)' - getViewFromCache: (route) -> - if route of @cache - @cache[route].fromCache = true - return @cache[route] - view = @getView(route) - @cache[route] = view if view?.cache - return view - - routeDirectly: (path, args) -> - if window.currentView?.reloadOnClose - return document.location.reload() - path = "views/#{path}" - ViewClass = @tryToLoadModule path - return @openView @notFoundView() if not ViewClass - view = new ViewClass({}, args...) # options, then any path fragment args - view.render() - @openView(view) - - getView: (route, suffix='_view') -> - # iteratively breaks down the url pieces looking for the view - # passing the broken off pieces as args. This way views like 'resource/14394893' - # will get passed to the resource view with arg '14394893' - pieces = _.string.words(route, '/') - split = Math.max(1, pieces.length-1) - while split > -1 - sub_route = _.string.join('/', pieces[0..split]...) - path = "views/#{sub_route}#{suffix}" - ViewClass = @tryToLoadModule(path) - break if ViewClass - split -= 1 - - return @notFoundView() if not ViewClass - args = pieces[split+1..] - view = new ViewClass({}, args...) # options, then any path fragment args - view.render() - - tryToLoadModule: (path) -> - try - return require(path) - catch error - if error.toString().search('Cannot find module "' + path + '" from') is -1 - throw error - - notFoundView: -> - view = new NotFoundView() - view.render() - - closeCurrentView: -> - window.currentModal?.hide?() - return unless window.currentView? - if window.currentView.cache - window.currentView.scrollY = window.scrollY - window.currentView.willDisappear() - else - window.currentView.destroy() - activateTab: -> base = _.string.words(document.location.pathname[1..], '/')[0] $("ul.nav li.#{base}").addClass('active') - initialize: -> - @cache = {} - # http://nerds.airbnb.com/how-to-add-google-analytics-page-tracking-to-57536 - @bind 'route', @_trackPageView - _trackPageView: -> window.tracker?.trackPageView() @@ -196,6 +163,3 @@ module.exports = class CocoRouter extends Backbone.Router @openView view else @openView e.view - - routeToServer: (e) -> - window.location.href = window.location.href diff --git a/app/application.coffee b/app/application.coffee index 8d71a3249..4eb829c88 100644 --- a/app/application.coffee +++ b/app/application.coffee @@ -35,7 +35,7 @@ preload = (arrayOfImages) -> $('')[0].src = @ Application = initialize: -> - Router = require('lib/Router') + Router = require('Router') @tracker = new Tracker() @facebookHandler = new FacebookHandler() @gplusHandler = new GPlusHandler() @@ -53,7 +53,6 @@ Application = initialize: -> #resPostPath: '/languages/add/__lng__/__ns__' }, (t) => @router = new Router() - @router.subscribe() onIdleChanged = (to) => => Backbone.Mediator.publish 'application:idle-changed', idle: @userIsIdle = to @idleTracker = new Idle onAway: onIdleChanged true diff --git a/app/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/templates/admin.jade b/app/templates/admin.jade index 5d583f703..79061e10d 100644 --- a/app/templates/admin.jade +++ b/app/templates/admin.jade @@ -22,9 +22,9 @@ block content li a(href="/admin/users", data-i18n="admin.av_entities_users_url") Users li - a(href="/admin/level_sessions", data-i18n="admin.av_entities_active_instances_url") Active Instances + a(href="/admin/level-sessions", data-i18n="admin.av_entities_active_instances_url") Active Instances li - a(href="/admin/employer_list", data-i18n="admin.av_entities_employer_list_url") Employer List + a(href="/admin/employers", data-i18n="admin.av_entities_employer_list_url") Employer List li a(href="/admin/candidates") Candidate List diff --git a/app/templates/base.jade b/app/templates/base.jade index 6c18d420c..d8bc8996f 100644 --- a/app/templates/base.jade +++ b/app/templates/base.jade @@ -67,7 +67,7 @@ body a(href='/contribute', title='Contribute', tabindex=-1, data-i18n="nav.contribute") Contribute a(href='/legal', title='Legal', tabindex=-1, data-i18n="nav.legal") Legal a(href='/about', title='About', tabindex=-1, data-i18n="nav.about") About - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Contact a(href='/editor', data-i18n="nav.editor") Editor a(href='http://blog.codecombat.com/', data-i18n="nav.blog") Blog a(href='http://discourse.codecombat.com/', data-i18n="nav.forum") Forum diff --git a/app/templates/contribute/ambassador.jade b/app/templates/contribute/ambassador.jade index 2d1f65564..d7be893da 100644 --- a/app/templates/contribute/ambassador.jade +++ b/app/templates/contribute/ambassador.jade @@ -31,7 +31,7 @@ block content h4(data-i18n="contribute.how_to_join") How to Join p - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.contact_us_url") + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="contribute.contact_us_url") | Contact us span , span(data-i18n="contribute.ambassador_join_desc") diff --git a/app/templates/contribute/archmage.jade b/app/templates/contribute/archmage.jade index ae982472e..0d00200c7 100644 --- a/app/templates/contribute/archmage.jade +++ b/app/templates/contribute/archmage.jade @@ -48,7 +48,7 @@ block content span(data-i18n="contribute.join_desc_2") | to get started, and check the box below to mark yourself as a brave Archmage and get the latest news by email. | Want to chat about what to do or how to get more deeply involved? - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.join_url_email") + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="contribute.join_url_email") | Email us span(data-i18n="contribute.join_desc_3") | , or find us in our diff --git a/app/templates/contribute/scribe.jade b/app/templates/contribute/scribe.jade index 92155143c..a4aae2b81 100644 --- a/app/templates/contribute/scribe.jade +++ b/app/templates/contribute/scribe.jade @@ -37,7 +37,7 @@ block content h4(data-i18n="contribute.how_to_join") How To Join p - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.contact_us_url") + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="contribute.contact_us_url") | Contact us span , span(data-i18n="contribute.scribe_join_description") diff --git a/app/templates/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/edit.jade b/app/templates/editor/level/edit.jade index c1f372e29..924949af8 100644 --- a/app/templates/editor/level/edit.jade +++ b/app/templates/editor/level/edit.jade @@ -78,9 +78,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 +96,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 diff --git a/app/templates/editor/thang/edit.jade b/app/templates/editor/thang/edit.jade index b1924f439..df7972622 100644 --- a/app/templates/editor/thang/edit.jade +++ b/app/templates/editor/thang/edit.jade @@ -14,7 +14,7 @@ block content button.btn.btn-secondary#history-button(data-i18n="general.version_history") Version History button.btn.btn-primary#save-button(data-i18n="common.save", disabled=authorized === true ? undefined : "true") Save - button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true") Revert + button.btn.btn-primary#revert-button(data-toggle="coco-modal", data-target="modal/RevertModal", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true") Revert h3 Edit Thang Type: "#{thangType.attributes.name}" diff --git a/app/templates/kinds/search.jade b/app/templates/kinds/search.jade index 59a9c880c..0e522d272 100644 --- a/app/templates/kinds/search.jade +++ b/app/templates/kinds/search.jade @@ -10,7 +10,7 @@ block content | #{currentEditor} if me.get('anonymous') - a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="modal/auth", role="button", data-i18n="#{currentNewSignup}") Log in to Create a New Content + a.btn.btn-primary.open-modal-button(data-toggle="coco-modal", data-target="modal/AuthModal", role="button", data-i18n="#{currentNewSignup}") Log in to Create a New Content else a.btn.btn-primary.open-modal-button(href='#new-model-modal', role="button", data-toggle="modal", data-i18n="#{currentNew}") Create a New Something input#search(data-i18n="[placeholder]#{currentSearch}") diff --git a/app/templates/modal/auth.jade b/app/templates/modal/auth.jade index 80444f4c1..0bb8f6b49 100644 --- a/app/templates/modal/auth.jade +++ b/app/templates/modal/auth.jade @@ -74,4 +74,4 @@ block modal-footer div.network-login .gplus-login-button#gplus-login-button div#recover-account-wrapper - a(data-toggle="coco-modal", data-target="modal/recover", data-i18n="login.recover")#link-to-recover recover account + a(data-toggle="coco-modal", data-target="modal/RecoverModal", data-i18n="login.recover")#link-to-recover recover account diff --git a/app/templates/modal/employer_signup_modal.jade b/app/templates/modal/employer_signup_modal.jade index 8d0429137..0c17755da 100644 --- a/app/templates/modal/employer_signup_modal.jade +++ b/app/templates/modal/employer_signup_modal.jade @@ -23,7 +23,7 @@ block modal-body-content br br | Already have a CodeCombat account? - a.login-link(data-toggle="coco-modal", data-target="modal/auth") Log in to continue! + a.login-link(data-toggle="coco-modal", data-target="modal/AuthModal") Log in to continue! else if !userIsAuthorized .modal-footer.linkedin p Please sign into your LinkedIn account to verify your identity. @@ -50,7 +50,7 @@ block modal-footer if userIsAnonymous if userIsAuthorized .modal-footer.linkedin - a.login-link(data-toggle="coco-modal", data-target="modal/auth") Please log in to continue. + a.login-link(data-toggle="coco-modal", data-target="modal/AuthModal") Please log in to continue. else if !userIsAnonymous && !userIsAuthorized .modal-footer.linkedin else if userIsAuthorized && !userHasSignedContract diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade index 515397e1f..bce03bf95 100644 --- a/app/templates/play/ladder/ladder_tab.jade +++ b/app/templates/play/ladder/ladder_tab.jade @@ -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/spectate.jade b/app/templates/play/spectate.jade index ee9408d4c..720cd4b30 100644 --- a/app/templates/play/spectate.jade +++ b/app/templates/play/spectate.jade @@ -13,4 +13,4 @@ .footer .content p(class='footer-link-text') - a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Contact \ No newline at end of file + a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Contact \ No newline at end of file diff --git a/app/templates/teachers.jade b/app/templates/teachers.jade index 651de1205..529e3e50d 100644 --- a/app/templates/teachers.jade +++ b/app/templates/teachers.jade @@ -24,7 +24,7 @@ block content p More questions? Get in touch! Feature requests? We'd love to hear them! CodeCombat is new and needs to hear from you to learn what teachers would love to have in their classrooms of programming wizards-to-be. h3 - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact") Contact Us + a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal") Contact Us .span5 diff --git a/app/views/EmployersView.coffee b/app/views/EmployersView.coffee index 57ca3c78f..b7699e428 100644 --- a/app/views/EmployersView.coffee +++ b/app/views/EmployersView.coffee @@ -1,11 +1,10 @@ RootView = require 'views/kinds/RootView' template = require 'templates/employers' -app = require 'application' User = require 'models/User' UserRemark = require 'models/UserRemark' {me} = require 'lib/auth' CocoCollection = require 'collections/CocoCollection' -EmployerSignupView = require 'views/modal/employer_signup_modal' +EmployerSignupModal = require 'views/modal/EmployerSignupModal' class CandidatesCollection extends CocoCollection url: '/db/user/x/candidates' @@ -75,7 +74,7 @@ module.exports = class EmployersView extends RootView @applyFilters() openSignupModal: -> - @openModalView new EmployerSignupView + @openModalView new EmployerSignupModal handleSelectAllChange: (e) -> checkedState = e.currentTarget.checked $('#filters :input').each -> @@ -222,7 +221,7 @@ module.exports = class EmployersView extends RootView checkForEmployerSignupHash: => if window.location.hash is '#employerSignupLoggingIn' and not ('employer' in me.get('permissions')) and not me.isAdmin() - @openModalView application.router.getView('modal/employer_signup', '_modal') + @openModalView new EmployerSignupModal window.location.hash = '' sortTable: -> @@ -356,4 +355,4 @@ module.exports = class EmployersView extends RootView url = "/account/profile/#{id}" window.open url, '_blank' else - @openModalView new EmployerSignupView + @openModalView new EmployerSignupModal diff --git a/app/views/HomeView.coffee b/app/views/HomeView.coffee index 05e9f78f0..4323f5ea0 100644 --- a/app/views/HomeView.coffee +++ b/app/views/HomeView.coffee @@ -4,7 +4,6 @@ WizardSprite = require 'lib/surface/WizardSprite' ThangType = require 'models/ThangType' Simulator = require 'lib/simulator/Simulator' {me} = require '/lib/auth' -application = require 'application' module.exports = class HomeView extends RootView id: 'home-view' diff --git a/app/views/account/settings_view.coffee b/app/views/account/AccountSettingsView.coffee similarity index 94% rename from app/views/account/settings_view.coffee rename to app/views/account/AccountSettingsView.coffee index 39a335488..7dabe37fa 100644 --- a/app/views/account/settings_view.coffee +++ b/app/views/account/AccountSettingsView.coffee @@ -3,12 +3,12 @@ template = require 'templates/account/settings' {me} = require 'lib/auth' forms = require 'lib/forms' User = require 'models/User' -AuthModalView = require 'views/modal/auth_modal' +AuthModal = require 'views/modal/AuthModal' -WizardSettingsView = require './wizard_settings_view' -JobProfileView = require './job_profile_view' +WizardSettingsView = require './WizardSettingsView' +JobProfileTreemaView = require './JobProfileTreemaView' -module.exports = class SettingsView extends RootView +module.exports = class AccountSettingsView extends RootView id: 'account-settings-view' template: template changedFields: [] # DOM input fields @@ -97,9 +97,9 @@ module.exports = class SettingsView extends RootView @listenTo wizardSettingsView, 'change', @enableSaveButton @insertSubView wizardSettingsView - @jobProfileView = new JobProfileView() - @listenTo @jobProfileView, 'change', @enableSaveButton - @insertSubView @jobProfileView + @jobProfileTreemaView = new JobProfileTreemaView() + @listenTo @jobProfileTreemaView, 'change', @enableSaveButton + @insertSubView @jobProfileTreemaView _.defer => @buildPictureTreema() # Not sure why, but the Treemas don't fully build without this if you reload the page. afterInsert: -> @@ -107,7 +107,7 @@ module.exports = class SettingsView extends RootView $('#email-pane input[type="checkbox"]').on 'change', -> $(@).addClass 'changed' if me.get('anonymous') - @openModalView new AuthModalView() + @openModalView new AuthModal() @updateSavedValues() chooseTab: (category) -> @@ -222,7 +222,7 @@ module.exports = class SettingsView extends RootView jobProfile = me.get('jobProfile') ? {} updated = false - for key, val of @jobProfileView.getData() + for key, val of @jobProfileTreemaView.getData() updated = updated or not _.isEqual jobProfile[key], val jobProfile[key] = val if updated diff --git a/app/views/account/JobProfileCodeModal.coffee b/app/views/account/JobProfileCodeModal.coffee index 397de97cf..307f75847 100644 --- a/app/views/account/JobProfileCodeModal.coffee +++ b/app/views/account/JobProfileCodeModal.coffee @@ -1,7 +1,6 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/account/job_profile_code_modal' LevelSessionCodeView = require 'views/common/LevelSessionCodeView' -console.log 'template', template module.exports = class JobProfileCodeModal extends ModalView id: 'job_profile_code_modal' diff --git a/app/views/account/JobProfileTreemaView.coffee b/app/views/account/JobProfileTreemaView.coffee new file mode 100644 index 000000000..1ddde82e1 --- /dev/null +++ b/app/views/account/JobProfileTreemaView.coffee @@ -0,0 +1,131 @@ +CocoView = require 'views/kinds/CocoView' +template = require 'templates/account/job_profile' +{me} = require 'lib/auth' + +module.exports = class JobProfileTreemaView extends CocoView + id: 'job-profile-view' + template: template + + editableSettings: [ + 'lookingFor', 'active', 'name', 'city', 'country', 'skills', 'experience', 'shortDescription', 'longDescription', + 'work', 'education', 'visa', 'projects', 'links', 'jobTitle', 'photoURL' + ] + readOnlySettings: [] #['updated'] + + afterRender: -> + super() + return unless @supermodel.finished() + _.defer => @buildJobProfileTreema() # Not sure why, but the Treemas don't fully build without this if you reload the page. + + buildJobProfileTreema: -> + visibleSettings = @editableSettings.concat @readOnlySettings + data = _.pick (me.get('jobProfile') ? {}), (value, key) -> key in visibleSettings + data.name ?= (me.get('firstName') + ' ' + me.get('lastName')).trim() if me.get('firstName') + schema = _.cloneDeep me.schema().properties.jobProfile + schema.properties = _.pick schema.properties, (value, key) -> key in visibleSettings + schema.required = _.intersection schema.required, visibleSettings + for prop in @readOnlySettings + schema.properties[prop].readOnly = true + treemaOptions = + filePath: "db/user/#{me.id}" + schema: schema + data: data + aceUseWrapMode: true + callbacks: {change: @onJobProfileChanged} + nodeClasses: + 'skill': SkillTagNode + 'link-name': LinkNameNode + 'city': CityNode + 'country': CountryNode + + @jobProfileTreema = @$el.find('#job-profile-treema').treema treemaOptions + @jobProfileTreema.build() + @jobProfileTreema.open() + @updateProgress() + + onJobProfileChanged: (e) => + @hasEditedProfile = true + @trigger 'change' + @updateProgress() + + updateProgress: -> + completed = 0 + totalWeight = 0 + next = null + for metric in metrics = @getProgressMetrics() + done = metric.fn() + completed += metric.weight if done + totalWeight += metric.weight + next = metric.name unless next or done + progress = Math.round 100 * completed / totalWeight + bar = @$el.find('.profile-completion-progress .progress-bar') + bar.css 'width', "#{progress}%" + text = '' + if progress > 19 + text = "#{progress}% complete" + else if progress > 5 + text = "#{progress}%" + bar.text text + bar.parent().toggle Boolean progress + @$el.find('.progress-next-item').text(next).toggle Boolean next + + getProgressMetrics: -> + return @progressMetrics if @progressMetrics + schema = me.schema().properties.jobProfile + jobProfile = @jobProfileTreema.data + exists = (field) -> -> jobProfile[field] + modified = (field) -> -> jobProfile[field] and jobProfile[field] isnt schema.properties[field].default + listStarted = (field, subfields) -> -> jobProfile[field]?.length and _.every subfields, (subfield) -> jobProfile[field][0][subfield] + @progressMetrics = [ + {name: 'Mark yourself open to offers to show up in searches.', weight: 1, fn: modified 'active'} + {name: 'Specify your desired job title.', weight: 0, fn: exists 'jobTitle'} + {name: 'Provide your name.', weight: 1, fn: modified 'name'} + {name: 'Choose your city.', weight: 1, fn: modified 'city'} + {name: 'Pick your country.', weight: 0, fn: exists 'country'} + {name: 'List at least five skills.', weight: 2, fn: -> jobProfile.skills.length >= 5} + {name: 'Write a short description to summarize yourself at a glance.', weight: 2, fn: modified 'shortDescription'} + {name: 'Fill in your main description to sell yourself and describe the work you\'re looking for.', weight: 3, fn: modified 'longDescription'} + {name: 'List your work experience.', weight: 3, fn: listStarted 'work', ['role', 'employer']} + {name: 'Recount your educational ordeals.', weight: 3, fn: listStarted 'education', ['degree', 'school']} + {name: 'Show off up to three projects you\'ve worked on.', weight: 3, fn: listStarted 'projects', ['name']} + {name: 'Add any personal or social links.', weight: 2, fn: listStarted 'links', ['link', 'name']} + {name: 'Add an optional professional photo.', weight: 2, fn: modified 'photoURL'} + ] + + getData: -> + return {} unless me.get('jobProfile') or @hasEditedProfile + _.pick @jobProfileTreema.data, (value, key) => key in @editableSettings + +JobProfileTreemaView.commonSkills = commonSkills = ['c#', 'java', 'javascript', 'php', 'android', 'jquery', 'python', 'c++', 'html', 'mysql', 'ios', 'asp.net', 'css', 'sql', 'iphone', '.net', 'objective-c', 'ruby-on-rails', 'c', 'ruby', 'sql-server', 'ajax', 'wpf', 'linux', 'database', 'django', 'vb.net', 'windows', 'facebook', 'r', 'html5', 'multithreading', 'ruby-on-rails-3', 'wordpress', 'winforms', 'node.js', 'spring', 'osx', 'performance', 'visual-studio-2010', 'oracle', 'swing', 'algorithm', 'git', 'linq', 'apache', 'web-services', 'perl', 'wcf', 'entity-framework', 'bash', 'visual-studio', 'sql-server-2008', 'hibernate', 'actionscript-3', 'angularjs', 'matlab', 'qt', 'ipad', 'sqlite', 'cocoa-touch', 'cocoa', 'flash', 'mongodb', 'codeigniter', 'jquery-ui', 'css3', 'tsql', 'google-maps', 'silverlight', 'security', 'delphi', 'vba', 'postgresql', 'jsp', 'shell', 'internet-explorer', 'google-app-engine', 'sockets', 'validation', 'scala', 'oop', 'unit-testing', 'xaml', 'parsing', 'twitter-bootstrap', 'google-chrome', 'http', 'magento', 'email', 'android-layout', 'flex', 'rest', 'maven', 'jsf', 'listview', 'date', 'winapi', 'windows-phone-7', 'facebook-graph-api', 'unix', 'url', 'c#-4.0', 'jquery-ajax', 'svn', 'symfony2', 'table', 'cakephp', 'firefox', 'ms-access', 'java-ee', 'jquery-mobile', 'python-2.7', 'tomcat', 'zend-framework', 'opencv', 'visual-c++', 'opengl', 'spring-mvc', 'sql-server-2005', 'authentication', 'search', 'xslt', 'servlets', 'pdf', 'animation', 'math', 'batch-file', 'excel-vba', 'iis', 'mod-rewrite', 'sharepoint', 'gwt', 'powershell', 'visual-studio-2012', 'haskell', 'grails', 'ubuntu', 'networking', 'nhibernate', 'design-patterns', 'testing', 'jpa', 'visual-studio-2008', 'core-data', 'user-interface', 'audio', 'backbone.js', 'gcc', 'mobile', 'design', 'activerecord', 'extjs', 'video', 'stored-procedures', 'optimization', 'drupal', 'image-processing', 'android-intent', 'logging', 'web-applications', 'razor', 'database-design', 'azure', 'vim', 'memory-management', 'model-view-controller', 'cordova', 'c++11', 'selenium', 'ssl', 'assembly', 'soap', 'boost', 'canvas', 'google-maps-api-3', 'netbeans', 'heroku', 'jsf-2', 'encryption', 'hadoop', 'linq-to-sql', 'dll', 'xpath', 'data-binding', 'windows-phone-8', 'phonegap', 'jdbc', 'python-3.x', 'twitter', 'mvvm', 'gui', 'web', 'jquery-plugins', 'numpy', 'deployment', 'ios7', 'emacs', 'knockout.js', 'graphics', 'joomla', 'unicode', 'windows-8', 'android-fragments', 'ant', 'command-line', 'version-control', 'yii', 'github', 'amazon-web-services', 'macros', 'ember.js', 'svg', 'opengl-es', 'django-models', 'solr', 'orm', 'blackberry', 'windows-7', 'ruby-on-rails-4', 'compiler', 'tcp', 'pdo', 'architecture', 'groovy', 'nginx', 'concurrency', 'paypal', 'iis-7', 'express', 'vbscript', 'google-chrome-extension', 'memory-leaks', 'rspec', 'actionscript', 'interface', 'fonts', 'oauth', 'ssh', 'tfs', 'junit', 'struts2', 'd3.js', 'coldfusion', '.net-4.0', 'jqgrid', 'asp-classic', 'https', 'plsql', 'stl', 'sharepoint-2010', 'asp.net-web-api', 'mysqli', 'sed', 'awk', 'internet-explorer-8', 'jboss', 'charts', 'scripting', 'matplotlib', 'laravel', 'clojure', 'entity-framework-4', 'intellij-idea', 'xml-parsing', 'sqlite3', '3d', 'io', 'mfc', 'devise', 'playframework', 'youtube', 'amazon-ec2', 'localization', 'cuda', 'jenkins', 'ssis', 'safari', 'doctrine2', 'vb6', 'amazon-s3', 'dojo', 'air', 'eclipse-plugin', 'android-asynctask', 'crystal-reports', 'cocos2d-iphone', 'dns', 'highcharts', 'ruby-on-rails-3.2', 'ado.net', 'sql-server-2008-r2', 'android-emulator', 'spring-security', 'cross-browser', 'oracle11g', 'bluetooth', 'f#', 'msbuild', 'drupal-7', 'google-apps-script', 'mercurial', 'xna', 'google-analytics', 'lua', 'parallel-processing', 'internationalization', 'java-me', 'mono', 'monotouch', 'android-ndk', 'lucene', 'kendo-ui', 'linux-kernel', 'terminal', 'phpmyadmin', 'makefile', 'ffmpeg', 'applet', 'active-directory', 'coffeescript', 'pandas', 'responsive-design', 'xhtml', 'silverlight-4.0', '.net-3.5', 'jaxb', 'ruby-on-rails-3.1', 'gps', 'geolocation', 'network-programming', 'windows-services', 'laravel-4', 'ggplot2', 'rss', 'webkit', 'functional-programming', 'wsdl', 'telerik', 'maven-2', 'cron', 'mapreduce', 'websocket', 'automation', 'windows-runtime', 'django-forms', 'tkinter', 'android-widget', 'android-activity', 'rubygems', 'content-management-system', 'doctrine', 'django-templates', 'gem', 'fluent-nhibernate', 'seo', 'meteor', 'serial-port', 'glassfish', 'documentation', 'cryptography', 'ef-code-first', 'extjs4', 'x86', 'wordpress-plugin', 'go', 'wix', 'linq-to-entities', 'oracle10g', 'cocos2d', 'selenium-webdriver', 'open-source', 'jtable', 'qt4', 'smtp', 'redis', 'jvm', 'openssl', 'timezone', 'nosql', 'erlang', 'playframework-2.0', 'machine-learning', 'mocking', 'unity3d', 'thread-safety', 'android-actionbar', 'jni', 'udp', 'jasper-reports', 'zend-framework2', 'apache2', 'internet-explorer-7', 'sqlalchemy', 'neo4j', 'ldap', 'jframe', 'youtube-api', 'filesystems', 'make', 'flask', 'gdb', 'cassandra', 'sms', 'g++', 'django-admin', 'push-notification', 'statistics', 'tinymce', 'locking', 'javafx', 'firefox-addon', 'fancybox', 'windows-phone', 'log4j', 'uikit', 'prolog', 'socket.io', 'icons', 'oauth-2.0', 'refactoring', 'sencha-touch', 'elasticsearch', 'symfony1', 'google-api', 'webserver', 'wpf-controls', 'microsoft-metro', 'gtk', 'flex4', 'three.js', 'gradle', 'centos', 'angularjs-directive', 'internet-explorer-9', 'sass', 'html5-canvas', 'interface-builder', 'programming-languages', 'gmail', 'jersey', 'twitter-bootstrap-3', 'arduino', 'requirejs', 'cmake', 'web-development', 'software-engineering', 'startups', 'entrepreneurship', 'social-media-marketing', 'writing', 'marketing', 'web-design', 'graphic-design', 'game-development', 'game-design', 'photoshop', 'illustrator', 'robotics', 'aws', 'devops', 'mathematica', 'bioinformatics', 'data-vis', 'ui', 'embedded-systems', 'codecombat'] + +JobProfileTreemaView.commonLinkNames = commonLinkNames = ['GitHub', 'Facebook', 'Twitter', 'G+', 'LinkedIn', 'Personal Website', 'Blog'] + +JobProfileTreemaView.commonCountries = commonCountries = ['Afghanistan', 'Albania', 'Algeria', 'American Samoa', 'Andorra', 'Angola', 'Anguilla', 'Antarctica', 'Antigua and Barbuda', 'Argentina', 'Armenia', 'Aruba', 'Australia', 'Austria', 'Azerbaijan', 'Bahamas', 'Bahrain', 'Bangladesh', 'Barbados', 'Belarus', 'Belgium', 'Belize', 'Benin', 'Bermuda', 'Bhutan', 'Bolivia', 'Bosnia and Herzegovina', 'Botswana', 'Brazil', 'Brunei Darussalam', 'Bulgaria', 'Burkina Faso', 'Burundi', 'Cambodia', 'Cameroon', 'Canada', 'Cape Verde', 'Cayman Islands', 'Central African Republic', 'Chad', 'Chile', 'China', 'Christmas Island', 'Cocos (Keeling) Islands', 'Colombia', 'Comoros', 'Democratic Republic of the Congo (Kinshasa)', 'Congo, Republic of (Brazzaville)', 'Cook Islands', 'Costa Rica', 'Ivory Coast', 'Croatia', 'Cuba', 'Cyprus', 'Czech Republic', 'Denmark', 'Djibouti', 'Dominica', 'Dominican Republic', 'East Timor', 'Ecuador', 'Egypt', 'El Salvador', 'Equatorial Guinea', 'Eritrea', 'Estonia', 'Ethiopia', 'Falkland Islands', 'Faroe Islands', 'Fiji', 'Finland', 'France', 'French Guiana', 'French Polynesia', 'French Southern Territories', 'Gabon', 'Gambia', 'Georgia', 'Germany', 'Ghana', 'Gibraltar', 'Great Britain', 'Greece', 'Greenland', 'Grenada', 'Guadeloupe', 'Guam', 'Guatemala', 'Guinea', 'Guinea-Bissau', 'Guyana', 'Haiti', 'Holy See', 'Honduras', 'Hong Kong', 'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran', 'Iraq', 'Ireland', 'Israel', 'Italy', 'Jamaica', 'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kiribati', 'North Korea', 'South Korea', 'Kosovo', 'Kuwait', 'Kyrgyzstan', 'Lao, People\'s Democratic Republic', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia', 'Libya', 'Liechtenstein', 'Lithuania', 'Luxembourg', 'Macau', 'Macedonia, Rep. of', 'Madagascar', 'Malawi', 'Malaysia', 'Maldives', 'Mali', 'Malta', 'Marshall Islands', 'Martinique', 'Mauritania', 'Mauritius', 'Mayotte', 'Mexico', 'Micronesia, Federal States of', 'Moldova, Republic of', 'Monaco', 'Mongolia', 'Montenegro', 'Montserrat', 'Morocco', 'Mozambique', 'Myanmar, Burma', 'Namibia', 'Nauru', 'Nepal', 'Netherlands', 'Netherlands Antilles', 'New Caledonia', 'New Zealand', 'Nicaragua', 'Niger', 'Nigeria', 'Niue', 'Northern Mariana Islands', 'Norway', 'Oman', 'Pakistan', 'Palau', 'Palestinian territories', 'Panama', 'Papua New Guinea', 'Paraguay', 'Peru', 'Philippines', 'Pitcairn Island', 'Poland', 'Portugal', 'Puerto Rico', 'Qatar', 'Reunion Island', 'Romania', 'Russian Federation', 'Rwanda', 'Saint Kitts and Nevis', 'Saint Lucia', 'Saint Vincent and the Grenadines', 'Samoa', 'San Marino', 'Sao Tome and Principe', 'Saudi Arabia', 'Senegal', 'Serbia', 'Seychelles', 'Sierra Leone', 'Singapore', 'Slovakia', 'Slovenia', 'Solomon Islands', 'Somalia', 'South Africa', 'South Sudan', 'Spain', 'Sri Lanka', 'Sudan', 'Suriname', 'Swaziland', 'Sweden', 'Switzerland', 'Syria, Syrian Arab Republic', 'Taiwan', 'Tajikistan', 'Tanzania; officially the United Republic of Tanzania', 'Thailand', 'Tibet', 'Timor-Leste', 'Togo', 'Tokelau', 'Tonga', 'Trinidad and Tobago', 'Tunisia', 'Turkey', 'Turkmenistan', 'Turks and Caicos Islands', 'Tuvalu', 'Uganda', 'Ukraine', 'United Arab Emirates', 'United Kingdom', 'USA', 'Uruguay', 'Uzbekistan', 'Vanuatu', 'Vatican City State', 'Venezuela', 'Vietnam', 'Virgin Islands (British)', 'Virgin Islands (U.S.)', 'Wallis and Futuna Islands', 'Western Sahara', 'Yemen', 'Zambia', 'Zimbabwe'] + +JobProfileTreemaView.commonCities = commonCities = ['Tokyo', 'Jakarta', 'Seoul', 'Delhi', 'Shanghai', 'Manila', 'Karachi', 'New York', 'Sao Paulo', 'Mexico City', 'Cairo', 'Beijing', 'Osaka', 'Mumbai (Bombay)', 'Guangzhou', 'Moscow', 'Los Angeles', 'Calcutta', 'Dhaka', 'Buenos Aires', 'Istanbul', 'Rio de Janeiro', 'Shenzhen', 'Lagos', 'Paris', 'Nagoya', 'Lima', 'Chicago', 'Kinshasa', 'Tianjin', 'Chennai', 'Bogota', 'Bengaluru', 'London', 'Taipei', 'Ho Chi Minh City (Saigon)', 'Dongguan', 'Hyderabad', 'Chengdu', 'Lahore', 'Johannesburg', 'Tehran', 'Essen', 'Bangkok', 'Hong Kong', 'Wuhan', 'Ahmedabad', 'Chongqung', 'Baghdad', 'Hangzhou', 'Toronto', 'Kuala Lumpur', 'Santiago', 'Dallas-Fort Worth', 'Quanzhou', 'Miami', 'Shenyang', 'Belo Horizonte', 'Philadelphia', 'Nanjing', 'Madrid', 'Houston', 'Xi\'an-Xianyang', 'Milan', 'Luanda', 'Pune', 'Singapore', 'Riyadh', 'Khartoum', 'Saint Petersburg', 'Atlanta', 'Surat', 'Washington', 'Bandung', 'Surabaya', 'Yangoon', 'Alexandria', 'Guadalajara', 'Harbin', 'Boston', 'Zhengzhou', 'Qingdao', 'Abidjan', 'Barcelona', 'Monterrey', 'Ankara', 'Suzhou', 'Phoenix-Mesa', 'Salvador', 'Porto Alegre', 'Rome', 'Accra', 'Sydney', 'Recife', 'Naples', 'Detroit', 'Dalian', 'Fuzhou', 'Medellin', 'San Francisco', 'Silicon Valley', 'Portland', 'Seattle', 'Austin', 'Denver', 'Boulder'] + +autoFocus = true # Not working right now, possibly a Treema bower thing. + +class SkillTagNode extends TreemaNode.nodeMap.string + buildValueForEditing: (valEl) -> + super(valEl) + valEl.find('input').autocomplete(source: commonSkills, minLength: 1, delay: 0, autoFocus: autoFocus) + valEl + +class LinkNameNode extends TreemaNode.nodeMap.string + buildValueForEditing: (valEl) -> + super(valEl) + valEl.find('input').autocomplete(source: commonLinkNames, minLength: 0, delay: 0, autoFocus: autoFocus) + valEl + +class CityNode extends TreemaNode.nodeMap.string + buildValueForEditing: (valEl) -> + super(valEl) + valEl.find('input').autocomplete(source: commonCities, minLength: 1, delay: 0, autoFocus: autoFocus) + valEl + +class CountryNode extends TreemaNode.nodeMap.string + buildValueForEditing: (valEl) -> + super(valEl) + valEl.find('input').autocomplete(source: commonCountries, minLength: 1, delay: 0, autoFocus: autoFocus) + valEl diff --git a/app/views/account/profile_view.coffee b/app/views/account/JobProfileView.coffee similarity index 97% rename from app/views/account/profile_view.coffee rename to app/views/account/JobProfileView.coffee index 9a36039da..6b2ed8bfd 100644 --- a/app/views/account/profile_view.coffee +++ b/app/views/account/JobProfileView.coffee @@ -4,11 +4,11 @@ User = require 'models/User' LevelSession = require 'models/LevelSession' CocoCollection = require 'collections/CocoCollection' {me} = require 'lib/auth' -JobProfileContactView = require 'views/modal/job_profile_contact_modal' -JobProfileView = require 'views/account/job_profile_view' +JobProfileContactModal = require 'views/modal/JobProfileContactModal' +JobProfileTreemaView = require 'views/account/JobProfileTreemaView' UserRemark = require 'models/UserRemark' forms = require 'lib/forms' -ModelModal = require 'views/modal/model_modal' +ModelModal = require 'views/modal/ModelModal' JobProfileCodeModal = require './JobProfileCodeModal' class LevelSessionsCollection extends CocoCollection @@ -26,7 +26,7 @@ adminContacts = [ {id: '52a57252a89409700d0000d9', name: 'Ignore'} ] -module.exports = class ProfileView extends RootView +module.exports = class JobProfileView extends RootView id: 'profile-view' template: template showBackground: false @@ -317,7 +317,7 @@ module.exports = class ProfileView extends RootView initializeAutocomplete: (container) -> (container ? @$el).find('input[data-autocomplete]').each -> - $(@).autocomplete(source: JobProfileView[$(@).data('autocomplete')], minLength: parseInt($(@).data('autocomplete-min-length')), delay: 0, autoFocus: true) + $(@).autocomplete(source: JobProfileTreemaView[$(@).data('autocomplete')], minLength: parseInt($(@).data('autocomplete-min-length')), delay: 0, autoFocus: true) toggleEditing: -> @editing = not @editing @@ -374,7 +374,7 @@ module.exports = class ProfileView extends RootView null onContactCandidate: (e) -> - @openModalView new JobProfileContactView recipientID: @user.id, recipientUserName: @user.get('name') + @openModalView new JobProfileContactModal recipientID: @user.id, recipientUserName: @user.get('name') showErrors: (errors) -> section = @$el.find '.saving' diff --git a/app/views/account/unsubscribe_view.coffee b/app/views/account/UnsubscribeView.coffee similarity index 100% rename from app/views/account/unsubscribe_view.coffee rename to app/views/account/UnsubscribeView.coffee diff --git a/app/views/account/wizard_settings_view.coffee b/app/views/account/WizardSettingsView.coffee similarity index 100% rename from app/views/account/wizard_settings_view.coffee rename to app/views/account/WizardSettingsView.coffee diff --git a/app/views/account/job_profile_view.coffee b/app/views/account/job_profile_view.coffee deleted file mode 100644 index bd4472d23..000000000 --- a/app/views/account/job_profile_view.coffee +++ /dev/null @@ -1,131 +0,0 @@ -CocoView = require 'views/kinds/CocoView' -template = require 'templates/account/job_profile' -{me} = require 'lib/auth' - -module.exports = class JobProfileView extends CocoView - id: 'job-profile-view' - template: template - - editableSettings: [ - 'lookingFor', 'active', 'name', 'city', 'country', 'skills', 'experience', 'shortDescription', 'longDescription', - 'work', 'education', 'visa', 'projects', 'links', 'jobTitle', 'photoURL' - ] - readOnlySettings: [] #['updated'] - - afterRender: -> - super() - return unless @supermodel.finished() - _.defer => @buildJobProfileTreema() # Not sure why, but the Treemas don't fully build without this if you reload the page. - - buildJobProfileTreema: -> - visibleSettings = @editableSettings.concat @readOnlySettings - data = _.pick (me.get('jobProfile') ? {}), (value, key) -> key in visibleSettings - data.name ?= (me.get('firstName') + ' ' + me.get('lastName')).trim() if me.get('firstName') - schema = _.cloneDeep me.schema().properties.jobProfile - schema.properties = _.pick schema.properties, (value, key) -> key in visibleSettings - schema.required = _.intersection schema.required, visibleSettings - for prop in @readOnlySettings - schema.properties[prop].readOnly = true - treemaOptions = - filePath: "db/user/#{me.id}" - schema: schema - data: data - aceUseWrapMode: true - callbacks: {change: @onJobProfileChanged} - nodeClasses: - 'skill': SkillTagNode - 'link-name': LinkNameNode - 'city': CityNode - 'country': CountryNode - - @jobProfileTreema = @$el.find('#job-profile-treema').treema treemaOptions - @jobProfileTreema.build() - @jobProfileTreema.open() - @updateProgress() - - onJobProfileChanged: (e) => - @hasEditedProfile = true - @trigger 'change' - @updateProgress() - - updateProgress: -> - completed = 0 - totalWeight = 0 - next = null - for metric in metrics = @getProgressMetrics() - done = metric.fn() - completed += metric.weight if done - totalWeight += metric.weight - next = metric.name unless next or done - progress = Math.round 100 * completed / totalWeight - bar = @$el.find('.profile-completion-progress .progress-bar') - bar.css 'width', "#{progress}%" - text = '' - if progress > 19 - text = "#{progress}% complete" - else if progress > 5 - text = "#{progress}%" - bar.text text - bar.parent().toggle Boolean progress - @$el.find('.progress-next-item').text(next).toggle Boolean next - - getProgressMetrics: -> - return @progressMetrics if @progressMetrics - schema = me.schema().properties.jobProfile - jobProfile = @jobProfileTreema.data - exists = (field) -> -> jobProfile[field] - modified = (field) -> -> jobProfile[field] and jobProfile[field] isnt schema.properties[field].default - listStarted = (field, subfields) -> -> jobProfile[field]?.length and _.every subfields, (subfield) -> jobProfile[field][0][subfield] - @progressMetrics = [ - {name: 'Mark yourself open to offers to show up in searches.', weight: 1, fn: modified 'active'} - {name: 'Specify your desired job title.', weight: 0, fn: exists 'jobTitle'} - {name: 'Provide your name.', weight: 1, fn: modified 'name'} - {name: 'Choose your city.', weight: 1, fn: modified 'city'} - {name: 'Pick your country.', weight: 0, fn: exists 'country'} - {name: 'List at least five skills.', weight: 2, fn: -> jobProfile.skills.length >= 5} - {name: 'Write a short description to summarize yourself at a glance.', weight: 2, fn: modified 'shortDescription'} - {name: 'Fill in your main description to sell yourself and describe the work you\'re looking for.', weight: 3, fn: modified 'longDescription'} - {name: 'List your work experience.', weight: 3, fn: listStarted 'work', ['role', 'employer']} - {name: 'Recount your educational ordeals.', weight: 3, fn: listStarted 'education', ['degree', 'school']} - {name: 'Show off up to three projects you\'ve worked on.', weight: 3, fn: listStarted 'projects', ['name']} - {name: 'Add any personal or social links.', weight: 2, fn: listStarted 'links', ['link', 'name']} - {name: 'Add an optional professional photo.', weight: 2, fn: modified 'photoURL'} - ] - - getData: -> - return {} unless me.get('jobProfile') or @hasEditedProfile - _.pick @jobProfileTreema.data, (value, key) => key in @editableSettings - -JobProfileView.commonSkills = commonSkills = ['c#', 'java', 'javascript', 'php', 'android', 'jquery', 'python', 'c++', 'html', 'mysql', 'ios', 'asp.net', 'css', 'sql', 'iphone', '.net', 'objective-c', 'ruby-on-rails', 'c', 'ruby', 'sql-server', 'ajax', 'wpf', 'linux', 'database', 'django', 'vb.net', 'windows', 'facebook', 'r', 'html5', 'multithreading', 'ruby-on-rails-3', 'wordpress', 'winforms', 'node.js', 'spring', 'osx', 'performance', 'visual-studio-2010', 'oracle', 'swing', 'algorithm', 'git', 'linq', 'apache', 'web-services', 'perl', 'wcf', 'entity-framework', 'bash', 'visual-studio', 'sql-server-2008', 'hibernate', 'actionscript-3', 'angularjs', 'matlab', 'qt', 'ipad', 'sqlite', 'cocoa-touch', 'cocoa', 'flash', 'mongodb', 'codeigniter', 'jquery-ui', 'css3', 'tsql', 'google-maps', 'silverlight', 'security', 'delphi', 'vba', 'postgresql', 'jsp', 'shell', 'internet-explorer', 'google-app-engine', 'sockets', 'validation', 'scala', 'oop', 'unit-testing', 'xaml', 'parsing', 'twitter-bootstrap', 'google-chrome', 'http', 'magento', 'email', 'android-layout', 'flex', 'rest', 'maven', 'jsf', 'listview', 'date', 'winapi', 'windows-phone-7', 'facebook-graph-api', 'unix', 'url', 'c#-4.0', 'jquery-ajax', 'svn', 'symfony2', 'table', 'cakephp', 'firefox', 'ms-access', 'java-ee', 'jquery-mobile', 'python-2.7', 'tomcat', 'zend-framework', 'opencv', 'visual-c++', 'opengl', 'spring-mvc', 'sql-server-2005', 'authentication', 'search', 'xslt', 'servlets', 'pdf', 'animation', 'math', 'batch-file', 'excel-vba', 'iis', 'mod-rewrite', 'sharepoint', 'gwt', 'powershell', 'visual-studio-2012', 'haskell', 'grails', 'ubuntu', 'networking', 'nhibernate', 'design-patterns', 'testing', 'jpa', 'visual-studio-2008', 'core-data', 'user-interface', 'audio', 'backbone.js', 'gcc', 'mobile', 'design', 'activerecord', 'extjs', 'video', 'stored-procedures', 'optimization', 'drupal', 'image-processing', 'android-intent', 'logging', 'web-applications', 'razor', 'database-design', 'azure', 'vim', 'memory-management', 'model-view-controller', 'cordova', 'c++11', 'selenium', 'ssl', 'assembly', 'soap', 'boost', 'canvas', 'google-maps-api-3', 'netbeans', 'heroku', 'jsf-2', 'encryption', 'hadoop', 'linq-to-sql', 'dll', 'xpath', 'data-binding', 'windows-phone-8', 'phonegap', 'jdbc', 'python-3.x', 'twitter', 'mvvm', 'gui', 'web', 'jquery-plugins', 'numpy', 'deployment', 'ios7', 'emacs', 'knockout.js', 'graphics', 'joomla', 'unicode', 'windows-8', 'android-fragments', 'ant', 'command-line', 'version-control', 'yii', 'github', 'amazon-web-services', 'macros', 'ember.js', 'svg', 'opengl-es', 'django-models', 'solr', 'orm', 'blackberry', 'windows-7', 'ruby-on-rails-4', 'compiler', 'tcp', 'pdo', 'architecture', 'groovy', 'nginx', 'concurrency', 'paypal', 'iis-7', 'express', 'vbscript', 'google-chrome-extension', 'memory-leaks', 'rspec', 'actionscript', 'interface', 'fonts', 'oauth', 'ssh', 'tfs', 'junit', 'struts2', 'd3.js', 'coldfusion', '.net-4.0', 'jqgrid', 'asp-classic', 'https', 'plsql', 'stl', 'sharepoint-2010', 'asp.net-web-api', 'mysqli', 'sed', 'awk', 'internet-explorer-8', 'jboss', 'charts', 'scripting', 'matplotlib', 'laravel', 'clojure', 'entity-framework-4', 'intellij-idea', 'xml-parsing', 'sqlite3', '3d', 'io', 'mfc', 'devise', 'playframework', 'youtube', 'amazon-ec2', 'localization', 'cuda', 'jenkins', 'ssis', 'safari', 'doctrine2', 'vb6', 'amazon-s3', 'dojo', 'air', 'eclipse-plugin', 'android-asynctask', 'crystal-reports', 'cocos2d-iphone', 'dns', 'highcharts', 'ruby-on-rails-3.2', 'ado.net', 'sql-server-2008-r2', 'android-emulator', 'spring-security', 'cross-browser', 'oracle11g', 'bluetooth', 'f#', 'msbuild', 'drupal-7', 'google-apps-script', 'mercurial', 'xna', 'google-analytics', 'lua', 'parallel-processing', 'internationalization', 'java-me', 'mono', 'monotouch', 'android-ndk', 'lucene', 'kendo-ui', 'linux-kernel', 'terminal', 'phpmyadmin', 'makefile', 'ffmpeg', 'applet', 'active-directory', 'coffeescript', 'pandas', 'responsive-design', 'xhtml', 'silverlight-4.0', '.net-3.5', 'jaxb', 'ruby-on-rails-3.1', 'gps', 'geolocation', 'network-programming', 'windows-services', 'laravel-4', 'ggplot2', 'rss', 'webkit', 'functional-programming', 'wsdl', 'telerik', 'maven-2', 'cron', 'mapreduce', 'websocket', 'automation', 'windows-runtime', 'django-forms', 'tkinter', 'android-widget', 'android-activity', 'rubygems', 'content-management-system', 'doctrine', 'django-templates', 'gem', 'fluent-nhibernate', 'seo', 'meteor', 'serial-port', 'glassfish', 'documentation', 'cryptography', 'ef-code-first', 'extjs4', 'x86', 'wordpress-plugin', 'go', 'wix', 'linq-to-entities', 'oracle10g', 'cocos2d', 'selenium-webdriver', 'open-source', 'jtable', 'qt4', 'smtp', 'redis', 'jvm', 'openssl', 'timezone', 'nosql', 'erlang', 'playframework-2.0', 'machine-learning', 'mocking', 'unity3d', 'thread-safety', 'android-actionbar', 'jni', 'udp', 'jasper-reports', 'zend-framework2', 'apache2', 'internet-explorer-7', 'sqlalchemy', 'neo4j', 'ldap', 'jframe', 'youtube-api', 'filesystems', 'make', 'flask', 'gdb', 'cassandra', 'sms', 'g++', 'django-admin', 'push-notification', 'statistics', 'tinymce', 'locking', 'javafx', 'firefox-addon', 'fancybox', 'windows-phone', 'log4j', 'uikit', 'prolog', 'socket.io', 'icons', 'oauth-2.0', 'refactoring', 'sencha-touch', 'elasticsearch', 'symfony1', 'google-api', 'webserver', 'wpf-controls', 'microsoft-metro', 'gtk', 'flex4', 'three.js', 'gradle', 'centos', 'angularjs-directive', 'internet-explorer-9', 'sass', 'html5-canvas', 'interface-builder', 'programming-languages', 'gmail', 'jersey', 'twitter-bootstrap-3', 'arduino', 'requirejs', 'cmake', 'web-development', 'software-engineering', 'startups', 'entrepreneurship', 'social-media-marketing', 'writing', 'marketing', 'web-design', 'graphic-design', 'game-development', 'game-design', 'photoshop', 'illustrator', 'robotics', 'aws', 'devops', 'mathematica', 'bioinformatics', 'data-vis', 'ui', 'embedded-systems', 'codecombat'] - -JobProfileView.commonLinkNames = commonLinkNames = ['GitHub', 'Facebook', 'Twitter', 'G+', 'LinkedIn', 'Personal Website', 'Blog'] - -JobProfileView.commonCountries = commonCountries = ['Afghanistan', 'Albania', 'Algeria', 'American Samoa', 'Andorra', 'Angola', 'Anguilla', 'Antarctica', 'Antigua and Barbuda', 'Argentina', 'Armenia', 'Aruba', 'Australia', 'Austria', 'Azerbaijan', 'Bahamas', 'Bahrain', 'Bangladesh', 'Barbados', 'Belarus', 'Belgium', 'Belize', 'Benin', 'Bermuda', 'Bhutan', 'Bolivia', 'Bosnia and Herzegovina', 'Botswana', 'Brazil', 'Brunei Darussalam', 'Bulgaria', 'Burkina Faso', 'Burundi', 'Cambodia', 'Cameroon', 'Canada', 'Cape Verde', 'Cayman Islands', 'Central African Republic', 'Chad', 'Chile', 'China', 'Christmas Island', 'Cocos (Keeling) Islands', 'Colombia', 'Comoros', 'Democratic Republic of the Congo (Kinshasa)', 'Congo, Republic of (Brazzaville)', 'Cook Islands', 'Costa Rica', 'Ivory Coast', 'Croatia', 'Cuba', 'Cyprus', 'Czech Republic', 'Denmark', 'Djibouti', 'Dominica', 'Dominican Republic', 'East Timor', 'Ecuador', 'Egypt', 'El Salvador', 'Equatorial Guinea', 'Eritrea', 'Estonia', 'Ethiopia', 'Falkland Islands', 'Faroe Islands', 'Fiji', 'Finland', 'France', 'French Guiana', 'French Polynesia', 'French Southern Territories', 'Gabon', 'Gambia', 'Georgia', 'Germany', 'Ghana', 'Gibraltar', 'Great Britain', 'Greece', 'Greenland', 'Grenada', 'Guadeloupe', 'Guam', 'Guatemala', 'Guinea', 'Guinea-Bissau', 'Guyana', 'Haiti', 'Holy See', 'Honduras', 'Hong Kong', 'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran', 'Iraq', 'Ireland', 'Israel', 'Italy', 'Jamaica', 'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kiribati', 'North Korea', 'South Korea', 'Kosovo', 'Kuwait', 'Kyrgyzstan', 'Lao, People\'s Democratic Republic', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia', 'Libya', 'Liechtenstein', 'Lithuania', 'Luxembourg', 'Macau', 'Macedonia, Rep. of', 'Madagascar', 'Malawi', 'Malaysia', 'Maldives', 'Mali', 'Malta', 'Marshall Islands', 'Martinique', 'Mauritania', 'Mauritius', 'Mayotte', 'Mexico', 'Micronesia, Federal States of', 'Moldova, Republic of', 'Monaco', 'Mongolia', 'Montenegro', 'Montserrat', 'Morocco', 'Mozambique', 'Myanmar, Burma', 'Namibia', 'Nauru', 'Nepal', 'Netherlands', 'Netherlands Antilles', 'New Caledonia', 'New Zealand', 'Nicaragua', 'Niger', 'Nigeria', 'Niue', 'Northern Mariana Islands', 'Norway', 'Oman', 'Pakistan', 'Palau', 'Palestinian territories', 'Panama', 'Papua New Guinea', 'Paraguay', 'Peru', 'Philippines', 'Pitcairn Island', 'Poland', 'Portugal', 'Puerto Rico', 'Qatar', 'Reunion Island', 'Romania', 'Russian Federation', 'Rwanda', 'Saint Kitts and Nevis', 'Saint Lucia', 'Saint Vincent and the Grenadines', 'Samoa', 'San Marino', 'Sao Tome and Principe', 'Saudi Arabia', 'Senegal', 'Serbia', 'Seychelles', 'Sierra Leone', 'Singapore', 'Slovakia', 'Slovenia', 'Solomon Islands', 'Somalia', 'South Africa', 'South Sudan', 'Spain', 'Sri Lanka', 'Sudan', 'Suriname', 'Swaziland', 'Sweden', 'Switzerland', 'Syria, Syrian Arab Republic', 'Taiwan', 'Tajikistan', 'Tanzania; officially the United Republic of Tanzania', 'Thailand', 'Tibet', 'Timor-Leste', 'Togo', 'Tokelau', 'Tonga', 'Trinidad and Tobago', 'Tunisia', 'Turkey', 'Turkmenistan', 'Turks and Caicos Islands', 'Tuvalu', 'Uganda', 'Ukraine', 'United Arab Emirates', 'United Kingdom', 'USA', 'Uruguay', 'Uzbekistan', 'Vanuatu', 'Vatican City State', 'Venezuela', 'Vietnam', 'Virgin Islands (British)', 'Virgin Islands (U.S.)', 'Wallis and Futuna Islands', 'Western Sahara', 'Yemen', 'Zambia', 'Zimbabwe'] - -JobProfileView.commonCities = commonCities = ['Tokyo', 'Jakarta', 'Seoul', 'Delhi', 'Shanghai', 'Manila', 'Karachi', 'New York', 'Sao Paulo', 'Mexico City', 'Cairo', 'Beijing', 'Osaka', 'Mumbai (Bombay)', 'Guangzhou', 'Moscow', 'Los Angeles', 'Calcutta', 'Dhaka', 'Buenos Aires', 'Istanbul', 'Rio de Janeiro', 'Shenzhen', 'Lagos', 'Paris', 'Nagoya', 'Lima', 'Chicago', 'Kinshasa', 'Tianjin', 'Chennai', 'Bogota', 'Bengaluru', 'London', 'Taipei', 'Ho Chi Minh City (Saigon)', 'Dongguan', 'Hyderabad', 'Chengdu', 'Lahore', 'Johannesburg', 'Tehran', 'Essen', 'Bangkok', 'Hong Kong', 'Wuhan', 'Ahmedabad', 'Chongqung', 'Baghdad', 'Hangzhou', 'Toronto', 'Kuala Lumpur', 'Santiago', 'Dallas-Fort Worth', 'Quanzhou', 'Miami', 'Shenyang', 'Belo Horizonte', 'Philadelphia', 'Nanjing', 'Madrid', 'Houston', 'Xi\'an-Xianyang', 'Milan', 'Luanda', 'Pune', 'Singapore', 'Riyadh', 'Khartoum', 'Saint Petersburg', 'Atlanta', 'Surat', 'Washington', 'Bandung', 'Surabaya', 'Yangoon', 'Alexandria', 'Guadalajara', 'Harbin', 'Boston', 'Zhengzhou', 'Qingdao', 'Abidjan', 'Barcelona', 'Monterrey', 'Ankara', 'Suzhou', 'Phoenix-Mesa', 'Salvador', 'Porto Alegre', 'Rome', 'Accra', 'Sydney', 'Recife', 'Naples', 'Detroit', 'Dalian', 'Fuzhou', 'Medellin', 'San Francisco', 'Silicon Valley', 'Portland', 'Seattle', 'Austin', 'Denver', 'Boulder'] - -autoFocus = true # Not working right now, possibly a Treema bower thing. - -class SkillTagNode extends TreemaNode.nodeMap.string - buildValueForEditing: (valEl) -> - super(valEl) - valEl.find('input').autocomplete(source: commonSkills, minLength: 1, delay: 0, autoFocus: autoFocus) - valEl - -class LinkNameNode extends TreemaNode.nodeMap.string - buildValueForEditing: (valEl) -> - super(valEl) - valEl.find('input').autocomplete(source: commonLinkNames, minLength: 0, delay: 0, autoFocus: autoFocus) - valEl - -class CityNode extends TreemaNode.nodeMap.string - buildValueForEditing: (valEl) -> - super(valEl) - valEl.find('input').autocomplete(source: commonCities, minLength: 1, delay: 0, autoFocus: autoFocus) - valEl - -class CountryNode extends TreemaNode.nodeMap.string - buildValueForEditing: (valEl) -> - super(valEl) - valEl.find('input').autocomplete(source: commonCountries, minLength: 1, delay: 0, autoFocus: autoFocus) - valEl diff --git a/app/views/admin/clas_view.coffee b/app/views/admin/CLAsView.coffee similarity index 100% rename from app/views/admin/clas_view.coffee rename to app/views/admin/CLAsView.coffee diff --git a/app/views/admin/candidates_view.coffee b/app/views/admin/CandidatesView.coffee similarity index 96% rename from app/views/admin/candidates_view.coffee rename to app/views/admin/CandidatesView.coffee index c91f16efd..7d8d89038 100644 --- a/app/views/admin/candidates_view.coffee +++ b/app/views/admin/CandidatesView.coffee @@ -1,11 +1,10 @@ RootView = require 'views/kinds/RootView' template = require 'templates/admin/candidates' -app = require 'application' User = require 'models/User' UserRemark = require 'models/UserRemark' {me} = require 'lib/auth' CocoCollection = require 'collections/CocoCollection' -EmployerSignupView = require 'views/modal/employer_signup_modal' +EmployerSignupModal = require 'views/modal/EmployerSignupModal' class CandidatesCollection extends CocoCollection url: '/db/user/x/candidates' @@ -15,7 +14,7 @@ class UserRemarksCollection extends CocoCollection url: '/db/user.remark?project=contact,contactName,user' model: UserRemark -module.exports = class EmployersView extends RootView +module.exports = class CandidatesView extends RootView id: "admin-candidates-view" template: template @@ -71,7 +70,7 @@ module.exports = class EmployersView extends RootView checkForEmployerSignupHash: => if window.location.hash is "#employerSignupLoggingIn" and not ("employer" in me.get("permissions")) - @openModalView application.router.getView("modal/employer_signup","_modal") + @openModalView new EmployerSignupModal window.location.hash = "" sortTable: -> @@ -204,4 +203,4 @@ module.exports = class EmployersView extends RootView url = "/account/profile/#{id}" window.open url,"_blank" else - @openModalView new EmployerSignupView \ No newline at end of file + @openModalView new EmployerSignupModal \ No newline at end of file diff --git a/app/views/admin/employer_list_view.coffee b/app/views/admin/EmployersListView.coffee similarity index 97% rename from app/views/admin/employer_list_view.coffee rename to app/views/admin/EmployersListView.coffee index 32c08cd22..a5fcb7a45 100644 --- a/app/views/admin/employer_list_view.coffee +++ b/app/views/admin/EmployersListView.coffee @@ -1,16 +1,15 @@ RootView = require 'views/kinds/RootView' template = require 'templates/admin/employer_list' -app = require 'application' User = require 'models/User' {me} = require 'lib/auth' CocoCollection = require 'collections/CocoCollection' -ModelModal = require 'views/modal/model_modal' +ModelModal = require 'views/modal/ModelModal' class EmployersCollection extends CocoCollection url: '/db/user/x/employers' model: User -module.exports = class EmployersView extends RootView +module.exports = class EmployersListView extends RootView id: 'employers-view' template: template diff --git a/app/views/admin/files_view.coffee b/app/views/admin/FilesView.coffee similarity index 100% rename from app/views/admin/files_view.coffee rename to app/views/admin/FilesView.coffee diff --git a/app/views/admin/level_sessions_view.coffee b/app/views/admin/LevelSessionsView.coffee similarity index 100% rename from app/views/admin/level_sessions_view.coffee rename to app/views/admin/LevelSessionsView.coffee diff --git a/app/views/AdminView.coffee b/app/views/admin/MainAdminView.coffee similarity index 94% rename from app/views/AdminView.coffee rename to app/views/admin/MainAdminView.coffee index 5c23d2ab1..33bed066e 100644 --- a/app/views/AdminView.coffee +++ b/app/views/admin/MainAdminView.coffee @@ -2,7 +2,7 @@ RootView = require 'views/kinds/RootView' template = require 'templates/admin' -module.exports = class AdminView extends RootView +module.exports = class MainAdminView extends RootView id: 'admin-view' template: template diff --git a/app/views/admin/users_view.coffee b/app/views/admin/UsersView.coffee similarity index 100% rename from app/views/admin/users_view.coffee rename to app/views/admin/UsersView.coffee diff --git a/app/views/admin/base_view.coffee b/app/views/admin/base_view.coffee deleted file mode 100644 index ca58690c0..000000000 --- a/app/views/admin/base_view.coffee +++ /dev/null @@ -1,6 +0,0 @@ -RootView = require 'views/kinds/RootView' -template = require 'templates/base' - -module.exports = class BaseView extends RootView - id: 'base-view' - template: template diff --git a/app/views/contribute/ContributeClassView.coffee b/app/views/contribute/ContributeClassView.coffee index 7b403d466..178e95d00 100644 --- a/app/views/contribute/ContributeClassView.coffee +++ b/app/views/contribute/ContributeClassView.coffee @@ -1,4 +1,4 @@ -SignupModalView = require 'views/modal/signup_modal' +SignupModalView = require 'views/modal/SignupModal' RootView = require 'views/kinds/RootView' {me} = require 'lib/auth' contributorSignupAnonymousTemplate = require 'templates/contribute/contributor_signup_anonymous' diff --git a/app/views/docs/components_view.coffee b/app/views/docs/ComponentDocumentationView.coffee similarity index 95% rename from app/views/docs/components_view.coffee rename to app/views/docs/ComponentDocumentationView.coffee index eedba904e..630f73262 100644 --- a/app/views/docs/components_view.coffee +++ b/app/views/docs/ComponentDocumentationView.coffee @@ -7,7 +7,7 @@ class ComponentDocsCollection extends CocoCollection url: '/db/level.component?project=name,description,dependencies,propertyDocumentation,code' model: LevelComponent -module.exports = class UnnamedView extends RootView +module.exports = class ComponentDocumentationView extends RootView id: 'docs-components-view' template: template diff --git a/app/views/editor/delta.coffee b/app/views/editor/DeltaView.coffee similarity index 100% rename from app/views/editor/delta.coffee rename to app/views/editor/DeltaView.coffee diff --git a/app/views/editor/patch_modal.coffee b/app/views/editor/PatchModal.coffee similarity index 98% rename from app/views/editor/patch_modal.coffee rename to app/views/editor/PatchModal.coffee index 6737b9f00..d22dc7ce3 100644 --- a/app/views/editor/patch_modal.coffee +++ b/app/views/editor/PatchModal.coffee @@ -1,6 +1,6 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/editor/patch_modal' -DeltaView = require 'views/editor/delta' +DeltaView = require 'views/editor/DeltaView' auth = require 'lib/auth' module.exports = class PatchModal extends ModalView diff --git a/app/views/editor/patches_view.coffee b/app/views/editor/PatchesView.coffee similarity index 97% rename from app/views/editor/patches_view.coffee rename to app/views/editor/PatchesView.coffee index 751ec837c..6f5f0bdd7 100644 --- a/app/views/editor/patches_view.coffee +++ b/app/views/editor/PatchesView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/patches' PatchesCollection = require 'collections/PatchesCollection' nameLoader = require 'lib/NameLoader' -PatchModal = require './patch_modal' +PatchModal = require './PatchModal' module.exports = class PatchesView extends CocoView template: template diff --git a/app/views/editor/achievement/edit.coffee b/app/views/editor/achievement/AchievementEditView.coffee similarity index 98% rename from app/views/editor/achievement/edit.coffee rename to app/views/editor/achievement/AchievementEditView.coffee index 8f4379777..ce5da02bb 100644 --- a/app/views/editor/achievement/edit.coffee +++ b/app/views/editor/achievement/AchievementEditView.coffee @@ -1,7 +1,7 @@ RootView = require 'views/kinds/RootView' template = require 'templates/editor/achievement/edit' Achievement = require 'models/Achievement' -ConfirmModal = require 'views/modal/confirm' +ConfirmModal = require 'views/modal/ConfirmModal' module.exports = class AchievementEditView extends RootView id: 'editor-achievement-edit-view' diff --git a/app/views/editor/achievement/home.coffee b/app/views/editor/achievement/AchievementSearchView.coffee similarity index 100% rename from app/views/editor/achievement/home.coffee rename to app/views/editor/achievement/AchievementSearchView.coffee diff --git a/app/views/editor/article/edit.coffee b/app/views/editor/article/ArticleEditView.coffee similarity index 92% rename from app/views/editor/article/edit.coffee rename to app/views/editor/article/ArticleEditView.coffee index 70450103f..96d4facc7 100644 --- a/app/views/editor/article/edit.coffee +++ b/app/views/editor/article/ArticleEditView.coffee @@ -1,9 +1,9 @@ RootView = require 'views/kinds/RootView' -VersionHistoryView = require './versions_view' +VersionHistoryView = require './ArticleVersionsModal' template = require 'templates/editor/article/edit' Article = require 'models/Article' -SaveVersionModal = require 'views/modal/save_version_modal' -PatchesView = require 'views/editor/patches_view' +SaveVersionModal = require 'views/modal/SaveVersionModal' +PatchesView = require 'views/editor/PatchesView' module.exports = class ArticleEditView extends RootView id: 'editor-article-edit-view' @@ -79,7 +79,7 @@ module.exports = class ArticleEditView extends RootView @patchesView.load() openPreview: -> - @preview = window.open('/editor/article/x/preview', 'preview', 'height=800,width=600') + @preview = window.open('/editor/article/preview', 'preview', 'height=800,width=600') @preview.focus() if window.focus @preview.onload = => @pushChangesToPreview() return false diff --git a/app/views/editor/article/preview.coffee b/app/views/editor/article/ArticlePreviewView.coffee similarity index 72% rename from app/views/editor/article/preview.coffee rename to app/views/editor/article/ArticlePreviewView.coffee index 9426454bf..5b335fb2d 100644 --- a/app/views/editor/article/preview.coffee +++ b/app/views/editor/article/ArticlePreviewView.coffee @@ -1,6 +1,6 @@ RootView = require 'views/kinds/RootView' template = require 'templates/editor/article/preview' -module.exports = class PreviewView extends RootView +module.exports = class ArticlePreviewView extends RootView id: 'editor-article-preview-view' template: template diff --git a/app/views/editor/article/home.coffee b/app/views/editor/article/ArticleSearchView.coffee similarity index 89% rename from app/views/editor/article/home.coffee rename to app/views/editor/article/ArticleSearchView.coffee index 4f8fdab05..b80423011 100644 --- a/app/views/editor/article/home.coffee +++ b/app/views/editor/article/ArticleSearchView.coffee @@ -1,6 +1,6 @@ SearchView = require 'views/kinds/SearchView' -module.exports = class ThangTypeHomeView extends SearchView +module.exports = class ArticleSearchView extends SearchView id: 'editor-article-home-view' modelLabel: 'Article' model: require 'models/Article' diff --git a/app/views/editor/article/versions_view.coffee b/app/views/editor/article/ArticleVersionsModal.coffee similarity index 55% rename from app/views/editor/article/versions_view.coffee rename to app/views/editor/article/ArticleVersionsModal.coffee index 98d9f1c63..10027ad99 100644 --- a/app/views/editor/article/versions_view.coffee +++ b/app/views/editor/article/ArticleVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class ArticleVersionsView extends VersionsModalView +module.exports = class ArticleVersionsModal extends VersionsModal id: 'editor-article-versions-view' url: '/db/article/' page: 'article' diff --git a/app/views/editor/component/versions_view.coffee b/app/views/editor/component/ComponentVersionsModal.coffee similarity index 58% rename from app/views/editor/component/versions_view.coffee rename to app/views/editor/component/ComponentVersionsModal.coffee index 409dc8553..fb027826e 100755 --- a/app/views/editor/component/versions_view.coffee +++ b/app/views/editor/component/ComponentVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class ComponentVersionsView extends VersionsModalView +module.exports = class ComponentVersionsModal extends VersionsModal id: 'editor-component-versions-view' url: '/db/level.component/' page: 'component' diff --git a/app/views/editor/components/config.coffee b/app/views/editor/component/ThangComponentConfigView.coffee similarity index 96% rename from app/views/editor/components/config.coffee rename to app/views/editor/component/ThangComponentConfigView.coffee index 7fb37b3ab..b14f4d211 100644 --- a/app/views/editor/components/config.coffee +++ b/app/views/editor/component/ThangComponentConfigView.coffee @@ -5,7 +5,7 @@ Level = require 'models/Level' LevelComponent = require 'models/LevelComponent' nodes = require '../level/treema_nodes' -module.exports = class ComponentConfigView extends CocoView +module.exports = class ThangComponentConfigView extends CocoView id: 'component-config-column-view' template: template className: 'column' diff --git a/app/views/editor/components/main.coffee b/app/views/editor/component/ThangComponentEditView.coffee similarity index 99% rename from app/views/editor/components/main.coffee rename to app/views/editor/component/ThangComponentEditView.coffee index 234608a44..3a4434710 100644 --- a/app/views/editor/components/main.coffee +++ b/app/views/editor/component/ThangComponentEditView.coffee @@ -5,7 +5,7 @@ Level = require 'models/Level' LevelComponent = require 'models/LevelComponent' LevelSystem = require 'models/LevelSystem' ComponentsCollection = require 'collections/ComponentsCollection' -ComponentConfigView = require './config' +ComponentConfigView = require './ThangComponentConfigView' module.exports = class ThangComponentEditView extends CocoView id: 'thang-components-edit-view' diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/LevelEditView.coffee similarity index 88% rename from app/views/editor/level/edit.coffee rename to app/views/editor/level/LevelEditView.coffee index 62666f44a..60ca1c010 100644 --- a/app/views/editor/level/edit.coffee +++ b/app/views/editor/level/LevelEditView.coffee @@ -6,18 +6,18 @@ World = require 'lib/world/world' DocumentFiles = require 'collections/DocumentFiles' LevelLoader = require 'lib/LevelLoader' -ThangsTabView = require './thangs_tab_view' -SettingsTabView = require './settings_tab_view' -ScriptsTabView = require './scripts_tab_view' -ComponentsTabView = require './components_tab_view' -SystemsTabView = require './systems_tab_view' -LevelSaveView = require './save_view' -LevelForkView = require './fork_view' -SaveVersionModal = require 'views/modal/save_version_modal' -PatchesView = require 'views/editor/patches_view' -VersionHistoryView = require './versions_view' +ThangsTabView = require './thangs/ThangsTabView' +SettingsTabView = require './settings/SettingsTabView' +ScriptsTabView = require './scripts/ScriptsTabView' +ComponentsTabView = require './components/ComponentsTabView' +SystemsTabView = require './systems/SystemsTabView' +SaveLevelModal = require './modals/SaveLevelModal' +LevelForkView = require './modals/ForkLevelModal' +SaveVersionModal = require 'views/modal/SaveVersionModal' +PatchesView = require 'views/editor/PatchesView' +VersionHistoryView = require './modals/LevelVersionsModal' -module.exports = class EditorLevelView extends RootView +module.exports = class LevelEditView extends RootView id: 'editor-level-view' template: template cache: false @@ -106,7 +106,7 @@ module.exports = class EditorLevelView extends RootView Backbone.Mediator.publish 'level:view-switched', e startCommittingLevel: (e) -> - @openModalView new LevelSaveView level: @level, supermodel: @supermodel + @openModalView new SaveLevelModal level: @level, supermodel: @supermodel Backbone.Mediator.publish 'level:view-switched', e startForkingLevel: (e) -> diff --git a/app/views/editor/level/home.coffee b/app/views/editor/level/LevelSearchView.coffee similarity index 89% rename from app/views/editor/level/home.coffee rename to app/views/editor/level/LevelSearchView.coffee index f5db556e6..a5dfb21c7 100644 --- a/app/views/editor/level/home.coffee +++ b/app/views/editor/level/LevelSearchView.coffee @@ -1,6 +1,6 @@ SearchView = require 'views/kinds/SearchView' -module.exports = class EditorSearchView extends SearchView +module.exports = class LevelSearchView extends SearchView id: 'editor-level-home-view' modelLabel: 'Level' model: require 'models/Level' diff --git a/app/views/editor/level/components_tab_view.coffee b/app/views/editor/level/components/ComponentsTabView.coffee similarity index 97% rename from app/views/editor/level/components_tab_view.coffee rename to app/views/editor/level/components/ComponentsTabView.coffee index 03c9bb2cf..3cfb953b8 100644 --- a/app/views/editor/level/components_tab_view.coffee +++ b/app/views/editor/level/components/ComponentsTabView.coffee @@ -1,8 +1,8 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/components_tab' LevelComponent = require 'models/LevelComponent' -LevelComponentEditView = require './component/edit' -LevelComponentNewView = require './component/new' +LevelComponentEditView = require './LevelComponentEditView' +LevelComponentNewView = require './NewLevelComponentModal' class LevelComponentCollection extends Backbone.Collection url: '/db/level.component' diff --git a/app/views/editor/level/component/edit.coffee b/app/views/editor/level/components/LevelComponentEditView.coffee similarity index 94% rename from app/views/editor/level/component/edit.coffee rename to app/views/editor/level/components/LevelComponentEditView.coffee index 9e36530ba..c09600241 100644 --- a/app/views/editor/level/component/edit.coffee +++ b/app/views/editor/level/components/LevelComponentEditView.coffee @@ -1,9 +1,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/component/edit' LevelComponent = require 'models/LevelComponent' -VersionHistoryView = require 'views/editor/component/versions_view' -PatchesView = require 'views/editor/patches_view' -SaveVersionModal = require 'views/modal/save_version_modal' +ComponentVersionsModal = require 'views/editor/component/ComponentVersionsModal' +PatchesView = require 'views/editor/PatchesView' +SaveVersionModal = require 'views/modal/SaveVersionModal' module.exports = class LevelComponentEditView extends CocoView id: 'editor-level-component-edit-view' @@ -108,8 +108,8 @@ module.exports = class LevelComponentEditView extends CocoView null showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView {}, @levelComponent.id - @openModalView versionHistoryView + componentVersionsModal = new ComponentVersionsModal {}, @levelComponent.id + @openModalView componentVersionsModal Backbone.Mediator.publish 'level:view-switched', e startPatchingComponent: (e) -> diff --git a/app/views/editor/level/component/new.coffee b/app/views/editor/level/components/NewLevelComponentModal.coffee similarity index 95% rename from app/views/editor/level/component/new.coffee rename to app/views/editor/level/components/NewLevelComponentModal.coffee index 314cf2c86..c4ead45de 100644 --- a/app/views/editor/level/component/new.coffee +++ b/app/views/editor/level/components/NewLevelComponentModal.coffee @@ -4,7 +4,7 @@ LevelComponent = require 'models/LevelComponent' forms = require 'lib/forms' {me} = require 'lib/auth' -module.exports = class LevelComponentNewView extends ModalView +module.exports = class NewLevelComponentModal extends ModalView id: 'editor-level-component-new-modal' template: template instant: false diff --git a/app/views/editor/level/fork_view.coffee b/app/views/editor/level/modals/ForkLevelModal.coffee similarity index 95% rename from app/views/editor/level/fork_view.coffee rename to app/views/editor/level/modals/ForkLevelModal.coffee index 2b3f7cfea..335ffc4a1 100644 --- a/app/views/editor/level/fork_view.coffee +++ b/app/views/editor/level/modals/ForkLevelModal.coffee @@ -3,7 +3,7 @@ template = require 'templates/editor/level/fork' forms = require 'lib/forms' Level = require 'models/Level' -module.exports = class LevelForkView extends ModalView +module.exports = class ForkLevelModal extends ModalView id: 'editor-level-fork-modal' template: template instant: false diff --git a/app/views/editor/level/versions_view.coffee b/app/views/editor/level/modals/LevelVersionsModal.coffee similarity index 55% rename from app/views/editor/level/versions_view.coffee rename to app/views/editor/level/modals/LevelVersionsModal.coffee index 38375ead8..21cb5a125 100644 --- a/app/views/editor/level/versions_view.coffee +++ b/app/views/editor/level/modals/LevelVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class LevelVersionsView extends VersionsModalView +module.exports = class LevelVersionsModal extends VersionsModal id: 'editor-level-versions-view' url: '/db/level/' page: 'level' diff --git a/app/views/editor/level/save_view.coffee b/app/views/editor/level/modals/SaveLevelModal.coffee similarity index 95% rename from app/views/editor/level/save_view.coffee rename to app/views/editor/level/modals/SaveLevelModal.coffee index 28c46e81d..2cbf62b9c 100644 --- a/app/views/editor/level/save_view.coffee +++ b/app/views/editor/level/modals/SaveLevelModal.coffee @@ -1,12 +1,12 @@ -SaveVersionModal = require 'views/modal/save_version_modal' +SaveVersionModal = require 'views/modal/SaveVersionModal' template = require 'templates/editor/level/save' forms = require 'lib/forms' LevelComponent = require 'models/LevelComponent' LevelSystem = require 'models/LevelSystem' -DeltaView = require 'views/editor/delta' -PatchModal = require 'views/editor/patch_modal' +DeltaView = require 'views/editor/DeltaView' +PatchModal = require 'views/editor/PatchModal' -module.exports = class LevelSaveView extends SaveVersionModal +module.exports = class SaveLevelModal extends SaveVersionModal template: template instant: false modalWidthPercent: 60 diff --git a/app/views/editor/level/modal/terrain_randomize_modal.coffee b/app/views/editor/level/modals/TerrainRandomizeModal.coffee similarity index 100% rename from app/views/editor/level/modal/terrain_randomize_modal.coffee rename to app/views/editor/level/modals/TerrainRandomizeModal.coffee diff --git a/app/views/editor/level/modal/world_select.coffee b/app/views/editor/level/modals/WorldSelectModal.coffee similarity index 100% rename from app/views/editor/level/modal/world_select.coffee rename to app/views/editor/level/modals/WorldSelectModal.coffee diff --git a/app/views/editor/level/scripts_tab_view.coffee b/app/views/editor/level/scripts/ScriptsTabView.coffee similarity index 99% rename from app/views/editor/level/scripts_tab_view.coffee rename to app/views/editor/level/scripts/ScriptsTabView.coffee index ae6813cbf..d221876ee 100644 --- a/app/views/editor/level/scripts_tab_view.coffee +++ b/app/views/editor/level/scripts/ScriptsTabView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/scripts_tab' Level = require 'models/Level' Surface = require 'lib/surface/Surface' -nodes = require './treema_nodes' +nodes = require './../treema_nodes' module.exports = class ScriptsTabView extends CocoView id: 'editor-level-scripts-tab-view' diff --git a/app/views/editor/level/settings_tab_view.coffee b/app/views/editor/level/settings/SettingsTabView.coffee similarity index 98% rename from app/views/editor/level/settings_tab_view.coffee rename to app/views/editor/level/settings/SettingsTabView.coffee index 7e2056c2f..ba436ef23 100644 --- a/app/views/editor/level/settings_tab_view.coffee +++ b/app/views/editor/level/settings/SettingsTabView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/settings_tab' Level = require 'models/Level' Surface = require 'lib/surface/Surface' -nodes = require './treema_nodes' +nodes = require './../treema_nodes' {me} = require 'lib/auth' module.exports = class SettingsTabView extends CocoView diff --git a/app/views/editor/level/system/add.coffee b/app/views/editor/level/systems/AddLevelSystemModal.coffee similarity index 97% rename from app/views/editor/level/system/add.coffee rename to app/views/editor/level/systems/AddLevelSystemModal.coffee index f0c3b7490..d11071e4c 100644 --- a/app/views/editor/level/system/add.coffee +++ b/app/views/editor/level/systems/AddLevelSystemModal.coffee @@ -8,7 +8,7 @@ class LevelSystemSearchCollection extends CocoCollection url: '/db/level_system' model: LevelSystem -module.exports = class LevelSystemAddView extends ModalView +module.exports = class AddLevelSystemModal extends ModalView id: 'editor-level-system-add-modal' template: template instant: true diff --git a/app/views/editor/level/system/edit.coffee b/app/views/editor/level/systems/LevelSystemEditView.coffee similarity index 93% rename from app/views/editor/level/system/edit.coffee rename to app/views/editor/level/systems/LevelSystemEditView.coffee index de5877bda..b1bcf8f67 100644 --- a/app/views/editor/level/system/edit.coffee +++ b/app/views/editor/level/systems/LevelSystemEditView.coffee @@ -1,9 +1,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/system/edit' LevelSystem = require 'models/LevelSystem' -VersionHistoryView = require 'views/editor/system/versions_view' -PatchesView = require 'views/editor/patches_view' -SaveVersionModal = require 'views/modal/save_version_modal' +SystemVersionsModal = require 'views/editor/level/systems/SystemVersionsModal' +PatchesView = require 'views/editor/PatchesView' +SaveVersionModal = require 'views/modal/SaveVersionModal' module.exports = class LevelSystemEditView extends CocoView id: 'editor-level-system-edit-view' @@ -101,8 +101,8 @@ module.exports = class LevelSystemEditView extends CocoView null showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView {}, @levelSystem.id - @openModalView versionHistoryView + systemVersionsModal = new SystemVersionsModal {}, @levelSystem.id + @openModalView systemVersionsModal Backbone.Mediator.publish 'level:view-switched', e startPatchingSystem: (e) -> diff --git a/app/views/editor/level/system/new.coffee b/app/views/editor/level/systems/NewLevelSystemModal.coffee similarity index 95% rename from app/views/editor/level/system/new.coffee rename to app/views/editor/level/systems/NewLevelSystemModal.coffee index 86b959f01..d2f509dbf 100644 --- a/app/views/editor/level/system/new.coffee +++ b/app/views/editor/level/systems/NewLevelSystemModal.coffee @@ -4,7 +4,7 @@ LevelSystem = require 'models/LevelSystem' forms = require 'lib/forms' {me} = require 'lib/auth' -module.exports = class LevelSystemNewView extends ModalView +module.exports = class NewLevelSystemModal extends ModalView id: 'editor-level-system-new-modal' template: template instant: false diff --git a/app/views/editor/system/versions_view.coffee b/app/views/editor/level/systems/SystemVersionsModal.coffee similarity index 57% rename from app/views/editor/system/versions_view.coffee rename to app/views/editor/level/systems/SystemVersionsModal.coffee index 6c0fe3e59..75d0a4ba0 100755 --- a/app/views/editor/system/versions_view.coffee +++ b/app/views/editor/level/systems/SystemVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class SystemVersionsView extends VersionsModalView +module.exports = class SystemVersionsModal extends VersionsModal id: 'editor-system-versions-view' url: '/db/level.system/' page: 'system' diff --git a/app/views/editor/level/systems_tab_view.coffee b/app/views/editor/level/systems/SystemsTabView.coffee similarity index 93% rename from app/views/editor/level/systems_tab_view.coffee rename to app/views/editor/level/systems/SystemsTabView.coffee index 4b4988755..89fa16bf1 100644 --- a/app/views/editor/level/systems_tab_view.coffee +++ b/app/views/editor/level/systems/SystemsTabView.coffee @@ -2,10 +2,10 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/systems_tab' Level = require 'models/Level' LevelSystem = require 'models/LevelSystem' -LevelSystemEditView = require './system/edit' -LevelSystemNewView = require './system/new' -LevelSystemAddView = require './system/add' -{ThangTypeNode} = require './treema_nodes' +LevelSystemEditView = require './LevelSystemEditView' +NewLevelSystemModal = require './NewLevelSystemModal' +AddLevelSystemModal = require './AddLevelSystemModal' +{ThangTypeNode} = require './../treema_nodes' module.exports = class SystemsTabView extends CocoView id: 'editor-level-systems-tab-view' @@ -49,7 +49,7 @@ module.exports = class SystemsTabView extends CocoView insertedDefaults = true systems = @getSortedByName systems treemaOptions = - # TODO: somehow get rid of the + button, or repurpose it to open the LevelSystemAddView instead + # TODO: somehow get rid of the + button, or repurpose it to open the AddLevelSystemModal instead supermodel: @supermodel schema: Level.schema.properties.systems data: systems @@ -90,11 +90,11 @@ module.exports = class SystemsTabView extends CocoView @systemsTreema.insert '/', e.system addLevelSystem: (e) -> - @openModalView new LevelSystemAddView supermodel: @supermodel, extantSystems: _.cloneDeep @systemsTreema.data + @openModalView new AddLevelSystemModal supermodel: @supermodel, extantSystems: _.cloneDeep @systemsTreema.data Backbone.Mediator.publish 'level:view-switched', e createNewLevelSystem: (e) -> - @openModalView new LevelSystemNewView supermodel: @supermodel + @openModalView new NewLevelSystemModal supermodel: @supermodel Backbone.Mediator.publish 'level:view-switched', e editLevelSystem: (e) -> diff --git a/app/views/editor/level/add_thangs_view.coffee b/app/views/editor/level/thangs/AddThangsView.coffee similarity index 100% rename from app/views/editor/level/add_thangs_view.coffee rename to app/views/editor/level/thangs/AddThangsView.coffee diff --git a/app/views/editor/level/thang/edit.coffee b/app/views/editor/level/thangs/LevelThangEditView.coffee similarity index 97% rename from app/views/editor/level/thang/edit.coffee rename to app/views/editor/level/thangs/LevelThangEditView.coffee index 4dd5b1549..f5a2a4387 100644 --- a/app/views/editor/level/thang/edit.coffee +++ b/app/views/editor/level/thangs/LevelThangEditView.coffee @@ -1,6 +1,6 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/editor/level/thang/edit' -ThangComponentEditView = require 'views/editor/components/main' +ThangComponentEditView = require 'views/editor/component/ThangComponentEditView' ThangType = require 'models/ThangType' module.exports = class LevelThangEditView extends CocoView diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs/ThangsTabView.coffee similarity index 99% rename from app/views/editor/level/thangs_tab_view.coffee rename to app/views/editor/level/thangs/ThangsTabView.coffee index 2fa4cb64c..7861c2539 100644 --- a/app/views/editor/level/thangs_tab_view.coffee +++ b/app/views/editor/level/thangs/ThangsTabView.coffee @@ -1,5 +1,5 @@ CocoView = require 'views/kinds/CocoView' -AddThangsView = require './add_thangs_view' +AddThangsView = require './AddThangsView' thangs_template = require 'templates/editor/level/thangs_tab' Level = require 'models/Level' ThangType = require 'models/ThangType' @@ -8,7 +8,7 @@ CocoCollection = require 'collections/CocoCollection' {isObjectID} = require 'models/CocoModel' Surface = require 'lib/surface/Surface' Thang = require 'lib/world/thang' -LevelThangEditView = require './thang/edit' +LevelThangEditView = require './LevelThangEditView' ComponentsCollection = require 'collections/ComponentsCollection' # Moving the screen while dragging thangs constants diff --git a/app/views/editor/level/treema_nodes.coffee b/app/views/editor/level/treema_nodes.coffee index f06654698..92a40cdb8 100644 --- a/app/views/editor/level/treema_nodes.coffee +++ b/app/views/editor/level/treema_nodes.coffee @@ -1,4 +1,4 @@ -WorldSelectModal = require './modal/world_select' +WorldSelectModal = require './modals/WorldSelectModal' ThangType = require '/models/ThangType' makeButton = -> $('') diff --git a/app/views/editor/thang/colors_tab_view.coffee b/app/views/editor/thang/ThangTypeColorsTabView.coffee similarity index 98% rename from app/views/editor/thang/colors_tab_view.coffee rename to app/views/editor/thang/ThangTypeColorsTabView.coffee index b4a60e017..41876272e 100644 --- a/app/views/editor/thang/colors_tab_view.coffee +++ b/app/views/editor/thang/ThangTypeColorsTabView.coffee @@ -3,7 +3,7 @@ template = require 'templates/editor/thang/colors_tab' SpriteBuilder = require 'lib/sprites/SpriteBuilder' {hexToHSL} = require 'lib/utils' -module.exports = class ColorsTabView extends CocoView +module.exports = class ThangTypeColorsTabView extends CocoView id: 'editor-thang-colors-tab-view' template: template className: 'tab-pane' diff --git a/app/views/editor/thang/edit.coffee b/app/views/editor/thang/ThangTypeEditView.coffee similarity index 96% rename from app/views/editor/thang/edit.coffee rename to app/views/editor/thang/ThangTypeEditView.coffee index b7d04b751..c9fd478bb 100644 --- a/app/views/editor/thang/edit.coffee +++ b/app/views/editor/thang/ThangTypeEditView.coffee @@ -6,11 +6,11 @@ Camera = require 'lib/surface/Camera' DocumentFiles = require 'collections/DocumentFiles' RootView = require 'views/kinds/RootView' -ThangComponentEditView = require 'views/editor/components/main' -VersionHistoryView = require './versions_view' -ColorsTabView = require './colors_tab_view' -PatchesView = require 'views/editor/patches_view' -SaveVersionModal = require 'views/modal/save_version_modal' +ThangComponentEditView = require 'views/editor/component/ThangComponentEditView' +ThangTypeVersionsModal = require './ThangTypeVersionsModal' +ThangTypeColorsTabView = require './ThangTypeColorsTabView' +PatchesView = require 'views/editor/PatchesView' +SaveVersionModal = require 'views/modal/SaveVersionModal' template = require 'templates/editor/thang/edit' CENTER = {x: 200, y: 300} @@ -73,7 +73,7 @@ module.exports = class ThangTypeEditView extends RootView @buildTreema() @initSliders() @initComponents() - @insertSubView(new ColorsTabView(@thangType)) + @insertSubView(new ThangTypeColorsTabView(@thangType)) @patchesView = @insertSubView(new PatchesView(@thangType), @$el.find('.patches-view')) @showReadOnly() if me.get('anonymous') @@ -400,8 +400,8 @@ module.exports = class ThangTypeEditView extends RootView @showingSelectedNode = false showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView thangType: @thangType, @thangTypeID - @openModalView versionHistoryView + versionHistoryModal = new ThangTypeVersionsModal thangType: @thangType, @thangTypeID + @openModalView versionHistoryModal Backbone.Mediator.publish 'level:view-switched', e openSaveModal: -> diff --git a/app/views/editor/thang/home.coffee b/app/views/editor/thang/ThangTypeSearchView.coffee similarity index 91% rename from app/views/editor/thang/home.coffee rename to app/views/editor/thang/ThangTypeSearchView.coffee index b14f1b9c4..c3b79b2bc 100644 --- a/app/views/editor/thang/home.coffee +++ b/app/views/editor/thang/ThangTypeSearchView.coffee @@ -1,6 +1,6 @@ SearchView = require 'views/kinds/SearchView' -module.exports = class ThangTypeHomeView extends SearchView +module.exports = class ThangTypeSearchView extends SearchView id: 'thang-type-home-view' modelLabel: 'Thang Type' model: require 'models/ThangType' diff --git a/app/views/editor/thang/versions_view.coffee b/app/views/editor/thang/ThangTypeVersionsModal.coffee similarity index 55% rename from app/views/editor/thang/versions_view.coffee rename to app/views/editor/thang/ThangTypeVersionsModal.coffee index 08344ce48..46bda96fc 100755 --- a/app/views/editor/thang/versions_view.coffee +++ b/app/views/editor/thang/ThangTypeVersionsModal.coffee @@ -1,6 +1,6 @@ -VersionsModalView = require 'views/modal/versions_modal' +VersionsModal = require 'views/modal/VersionsModal' -module.exports = class ComponentVersionsView extends VersionsModalView +module.exports = class ThangTypeVersionsModal extends VersionsModal id: 'editor-thang-versions-view' url: '/db/thang.type/' page: 'thang' diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee index 264e3539c..528d1d213 100644 --- a/app/views/kinds/CocoView.coffee +++ b/app/views/kinds/CocoView.coffee @@ -158,9 +158,9 @@ module.exports = class CocoView extends Backbone.View elem = $(e.target) return unless elem.data('toggle') is 'coco-modal' target = elem.data('target') - view = application.router.getView(target, '_modal') # could set up a system for loading cached modals, if told to + Modal = require 'views/'+target e.stopPropagation() - @openModalView(view) + @openModalView new Modal openModalView: (modalView, softly=false) -> return if waitingModal # can only have one waiting at once diff --git a/app/views/kinds/RootView.coffee b/app/views/kinds/RootView.coffee index 858c9fb48..f7bde789b 100644 --- a/app/views/kinds/RootView.coffee +++ b/app/views/kinds/RootView.coffee @@ -92,12 +92,12 @@ module.exports = class RootView extends CocoView logoutUser($('#login-email').val()) showWizardSettingsModal: -> - WizardSettingsModal = require('views/modal/wizard_settings_modal') + WizardSettingsModal = require('views/modal/WizardSettingsModal') subview = new WizardSettingsModal {} @openModalView subview onClickAuthbutton: -> - AuthModal = require 'views/modal/auth_modal' + AuthModal = require 'views/modal/AuthModal' @openModalView new AuthModal {} showLoading: ($el) -> @@ -152,7 +152,8 @@ module.exports = class RootView extends CocoView @saveLanguage(newLang) @render() unless newLang.split('-')[0] is 'en' - @openModalView(application.router.getView('modal/diplomat_suggestion', '_modal')) + DiplomatModal = require 'views/modal/DiplomatSuggestionModal' + @openModalView(new DiplomatModal()) saveLanguage: (newLang) -> me.set('preferredLanguage', newLang) diff --git a/app/views/modal/auth_modal.coffee b/app/views/modal/AuthModal.coffee similarity index 98% rename from app/views/modal/auth_modal.coffee rename to app/views/modal/AuthModal.coffee index ead7af8b9..ea7e4c771 100644 --- a/app/views/modal/auth_modal.coffee +++ b/app/views/modal/AuthModal.coffee @@ -5,7 +5,7 @@ forms = require 'lib/forms' User = require 'models/User' application = require 'application' -module.exports = class AuthModalView extends ModalView +module.exports = class AuthModal extends ModalView id: 'auth-modal' template: template mode: 'login' # or 'signup' diff --git a/app/views/modal/confirm.coffee b/app/views/modal/ConfirmModal.coffee similarity index 100% rename from app/views/modal/confirm.coffee rename to app/views/modal/ConfirmModal.coffee diff --git a/app/views/modal/contact_modal.coffee b/app/views/modal/ContactModal.coffee similarity index 94% rename from app/views/modal/contact_modal.coffee rename to app/views/modal/ContactModal.coffee index c8a6db460..99c47bd56 100644 --- a/app/views/modal/contact_modal.coffee +++ b/app/views/modal/ContactModal.coffee @@ -18,7 +18,7 @@ contactSchema = type: 'string' minLength: 1 -module.exports = class ContactView extends ModalView +module.exports = class ContactModal extends ModalView id: 'contact-modal' template: template closeButton: true diff --git a/app/views/modal/diplomat_suggestion_modal.coffee b/app/views/modal/DiplomatSuggestionModal.coffee similarity index 87% rename from app/views/modal/diplomat_suggestion_modal.coffee rename to app/views/modal/DiplomatSuggestionModal.coffee index c0abed5e7..e4071be20 100644 --- a/app/views/modal/diplomat_suggestion_modal.coffee +++ b/app/views/modal/DiplomatSuggestionModal.coffee @@ -3,7 +3,7 @@ template = require 'templates/modal/diplomat_suggestion' {me} = require 'lib/auth' forms = require 'lib/forms' -module.exports = class DiplomatSuggestionView extends ModalView +module.exports = class DiplomatSuggestionModal extends ModalView id: 'diplomat-suggestion-modal' template: template diff --git a/app/views/modal/employer_signup_modal.coffee b/app/views/modal/EmployerSignupModal.coffee similarity index 98% rename from app/views/modal/employer_signup_modal.coffee rename to app/views/modal/EmployerSignupModal.coffee index db766d979..65c9f1392 100644 --- a/app/views/modal/employer_signup_modal.coffee +++ b/app/views/modal/EmployerSignupModal.coffee @@ -5,7 +5,7 @@ User = require 'models/User' auth = require 'lib/auth' me = auth.me -module.exports = class EmployerSignupView extends ModalView +module.exports = class EmployerSignupModal extends ModalView id: 'employer-signup' template: template closeButton: true diff --git a/app/views/modal/job_profile_contact_modal.coffee b/app/views/modal/JobProfileContactModal.coffee similarity index 91% rename from app/views/modal/job_profile_contact_modal.coffee rename to app/views/modal/JobProfileContactModal.coffee index 0a933fe48..d8d011e63 100644 --- a/app/views/modal/job_profile_contact_modal.coffee +++ b/app/views/modal/JobProfileContactModal.coffee @@ -1,4 +1,4 @@ -ContactView = require 'views/modal/contact_modal' +ContactModal = require 'views/modal/ContactModal' template = require 'templates/modal/job_profile_contact' forms = require 'lib/forms' @@ -26,7 +26,7 @@ contactSchema = type: 'string' minLength: 1 -module.exports = class JobProfileContactView extends ContactView +module.exports = class JobProfileContactModal extends ContactModal id: 'job-profile-contact-modal' template: template diff --git a/app/views/modal/model_modal.coffee b/app/views/modal/ModelModal.coffee similarity index 100% rename from app/views/modal/model_modal.coffee rename to app/views/modal/ModelModal.coffee diff --git a/app/views/modal/recover_modal.coffee b/app/views/modal/RecoverModal.coffee similarity index 95% rename from app/views/modal/recover_modal.coffee rename to app/views/modal/RecoverModal.coffee index 5f8e9a17d..64cdd8154 100644 --- a/app/views/modal/recover_modal.coffee +++ b/app/views/modal/RecoverModal.coffee @@ -9,7 +9,7 @@ filterKeyboardEvents = (allowedEvents, func) -> return unless e.keyCode in allowedEvents or not e.keyCode return func(splat...) -module.exports = class RecoverModalView extends ModalView +module.exports = class RecoverModal extends ModalView id: 'recover-modal' template: template diff --git a/app/views/modal/revert_modal.coffee b/app/views/modal/RevertModal.coffee similarity index 100% rename from app/views/modal/revert_modal.coffee rename to app/views/modal/RevertModal.coffee diff --git a/app/views/modal/save_version_modal.coffee b/app/views/modal/SaveVersionModal.coffee similarity index 98% rename from app/views/modal/save_version_modal.coffee rename to app/views/modal/SaveVersionModal.coffee index 9edaaf859..9d682dd1c 100644 --- a/app/views/modal/save_version_modal.coffee +++ b/app/views/modal/SaveVersionModal.coffee @@ -1,6 +1,6 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/modal/save_version' -DeltaView = require 'views/editor/delta' +DeltaView = require 'views/editor/DeltaView' Patch = require 'models/Patch' forms = require 'lib/forms' diff --git a/app/views/modal/signup_modal.coffee b/app/views/modal/SignupModal.coffee similarity index 62% rename from app/views/modal/signup_modal.coffee rename to app/views/modal/SignupModal.coffee index 7c34cd6fe..93656f53a 100644 --- a/app/views/modal/signup_modal.coffee +++ b/app/views/modal/SignupModal.coffee @@ -1,4 +1,4 @@ -AuthModal = require 'views/modal/auth_modal' +AuthModal = require 'views/modal/AuthModal' module.exports = class SignupModalView extends AuthModal mode: 'signup' diff --git a/app/views/modal/versions_modal.coffee b/app/views/modal/VersionsModal.coffee similarity index 93% rename from app/views/modal/versions_modal.coffee rename to app/views/modal/VersionsModal.coffee index dfc7ec531..78eab024f 100755 --- a/app/views/modal/versions_modal.coffee +++ b/app/views/modal/VersionsModal.coffee @@ -1,8 +1,8 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/modal/versions' tableTemplate = require 'templates/kinds/table' -DeltaView = require 'views/editor/delta' -PatchModal = require 'views/editor/patch_modal' +DeltaView = require 'views/editor/DeltaView' +PatchModal = require 'views/editor/PatchModal' nameLoader = require 'lib/NameLoader' CocoCollection = require 'collections/CocoCollection' @@ -15,7 +15,7 @@ class VersionsViewCollection extends CocoCollection @url = url + levelID + '/versions' @model = model -module.exports = class VersionsModalView extends ModalView +module.exports = class VersionsModal extends ModalView template: template startsLoading: true plain: true diff --git a/app/views/modal/wizard_settings_modal.coffee b/app/views/modal/WizardSettingsModal.coffee similarity index 96% rename from app/views/modal/wizard_settings_modal.coffee rename to app/views/modal/WizardSettingsModal.coffee index d8527ee74..3e45663c0 100644 --- a/app/views/modal/wizard_settings_modal.coffee +++ b/app/views/modal/WizardSettingsModal.coffee @@ -21,7 +21,7 @@ module.exports = class WizardSettingsModal extends ModalView super options afterRender: -> - WizardSettingsView = require 'views/account/wizard_settings_view' + WizardSettingsView = require 'views/account/WizardSettingsView' view = new WizardSettingsView() @insertSubView view super() diff --git a/app/views/play/spectate_view.coffee b/app/views/play/SpectateView.coffee similarity index 97% rename from app/views/play/spectate_view.coffee rename to app/views/play/SpectateView.coffee index de9cab929..d7e843106 100644 --- a/app/views/play/spectate_view.coffee +++ b/app/views/play/SpectateView.coffee @@ -20,16 +20,16 @@ Camera = require 'lib/surface/Camera' AudioPlayer = require 'lib/AudioPlayer' # subviews -LoadingView = require './level/level_loading_view' -TomeView = require './level/tome/tome_view' -ChatView = require './level/level_chat_view' -HUDView = require './level/hud_view' -ControlBarView = require './level/control_bar_view' -PlaybackView = require './level/playback_view' -GoalsView = require './level/goals_view' -GoldView = require './level/gold_view' -VictoryModal = require './level/modal/victory_modal' -InfiniteLoopModal = require './level/modal/infinite_loop_modal' +LoadingView = require './level/LevelLoadingView' +TomeView = require './level/tome/TomeView' +ChatView = require './level/LevelChatView' +HUDView = require './level/LevelHUDView' +ControlBarView = require './level/ControlBarView' +PlaybackView = require './level/LevelPlaybackView' +GoalsView = require './level/LevelGoalsView' +GoldView = require './level/LevelGoldView' +VictoryModal = require './level/modal/VictoryModal' +InfiniteLoopModal = require './level/modal/InfiniteLoopModal' PROFILE_ME = false diff --git a/app/views/play/common/ladder_submission_view.coffee b/app/views/play/common/LadderSubmissionView.coffee similarity index 100% rename from app/views/play/common/ladder_submission_view.coffee rename to app/views/play/common/LadderSubmissionView.coffee diff --git a/app/views/play/ladder/play_modal.coffee b/app/views/play/ladder/LadderPlayModal.coffee similarity index 100% rename from app/views/play/ladder/play_modal.coffee rename to app/views/play/ladder/LadderPlayModal.coffee diff --git a/app/views/play/ladder/ladder_tab.coffee b/app/views/play/ladder/LadderTabView.coffee similarity index 99% rename from app/views/play/ladder/ladder_tab.coffee rename to app/views/play/ladder/LadderTabView.coffee index d0a7ff2a5..e049b2c26 100644 --- a/app/views/play/ladder/ladder_tab.coffee +++ b/app/views/play/ladder/LadderTabView.coffee @@ -6,7 +6,7 @@ CocoCollection = require 'collections/CocoCollection' User = require 'models/User' LeaderboardCollection = require 'collections/LeaderboardCollection' {teamDataFromLevel} = require './utils' -ModelModal = require 'views/modal/model_modal' +ModelModal = require 'views/modal/ModelModal' HIGHEST_SCORE = 1000000 diff --git a/app/views/play/ladder/ladder_view.coffee b/app/views/play/ladder/LadderView.coffee similarity index 92% rename from app/views/play/ladder/ladder_view.coffee rename to app/views/play/ladder/LadderView.coffee index 2fef77845..0e2d03e25 100644 --- a/app/views/play/ladder/ladder_view.coffee +++ b/app/views/play/ladder/LadderView.coffee @@ -6,10 +6,10 @@ CocoCollection = require 'collections/CocoCollection' {me} = require 'lib/auth' application = require 'application' -LadderTabView = require './ladder_tab' -MyMatchesTabView = require './my_matches_tab' -SimulateTabView = require './simulate_tab' -LadderPlayModal = require './play_modal' +LadderTabView = require './LadderTabView' +MyMatchesTabView = require './MyMatchesTabView' +SimulateTabView = require './SimulateTabView' +LadderPlayModal = require './LadderPlayModal' CocoClass = require 'lib/CocoClass' HIGHEST_SCORE = 1000000 @@ -92,8 +92,8 @@ module.exports = class LadderView extends RootView @openModalView modal showApologeticSignupModal: -> - SignupModal = require 'views/modal/auth_modal' - @openModalView(new SignupModal({showRequiredError: true})) + AuthModal = require 'views/modal/AuthModal' + @openModalView(new AuthModal({showRequiredError: true})) onClickedLink: (e) -> link = $(e.target).closest('a').attr('href') diff --git a/app/views/play/ladder_home.coffee b/app/views/play/ladder/MainLadderView.coffee similarity index 100% rename from app/views/play/ladder_home.coffee rename to app/views/play/ladder/MainLadderView.coffee diff --git a/app/views/play/ladder/my_matches_tab.coffee b/app/views/play/ladder/MyMatchesTabView.coffee similarity index 98% rename from app/views/play/ladder/my_matches_tab.coffee rename to app/views/play/ladder/MyMatchesTabView.coffee index b8f67e746..e0723a9ae 100644 --- a/app/views/play/ladder/my_matches_tab.coffee +++ b/app/views/play/ladder/MyMatchesTabView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' Level = require 'models/Level' LevelSession = require 'models/LevelSession' LeaderboardCollection = require 'collections/LeaderboardCollection' -LadderSubmissionView = require 'views/play/common/ladder_submission_view' +LadderSubmissionView = require 'views/play/common/LadderSubmissionView' {teamDataFromLevel} = require './utils' module.exports = class MyMatchesTabView extends CocoView diff --git a/app/views/play/ladder/simulate_tab.coffee b/app/views/play/ladder/SimulateTabView.coffee similarity index 100% rename from app/views/play/ladder/simulate_tab.coffee rename to app/views/play/ladder/SimulateTabView.coffee diff --git a/app/views/play/level/control_bar_view.coffee b/app/views/play/level/ControlBarView.coffee similarity index 93% rename from app/views/play/level/control_bar_view.coffee rename to app/views/play/level/ControlBarView.coffee index 18102be0f..fcfdccd3d 100644 --- a/app/views/play/level/control_bar_view.coffee +++ b/app/views/play/level/ControlBarView.coffee @@ -1,9 +1,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/control_bar' -DocsModal = require './modal/docs_modal' -MultiplayerModal = require './modal/multiplayer_modal' -ReloadModal = require './modal/reload_modal' +DocsModal = require './modal/LevelGuideModal' +MultiplayerModal = require './modal/MultiplayerModal' +ReloadLevelModal = require './modal/ReloadLevelModal' module.exports = class ControlBarView extends CocoView id: 'control-bar-view' @@ -84,4 +84,4 @@ module.exports = class ControlBarView extends CocoView @openModalView(new MultiplayerModal(session: @session, playableTeams: @playableTeams, level: @level, ladderGame: @ladderGame)) showRestartModal: -> - @openModalView(new ReloadModal()) + @openModalView(new ReloadLevelModal()) diff --git a/app/views/play/level/dialogue_animator.coffee b/app/views/play/level/DialogueAnimator.coffee similarity index 100% rename from app/views/play/level/dialogue_animator.coffee rename to app/views/play/level/DialogueAnimator.coffee diff --git a/app/views/play/level/level_chat_view.coffee b/app/views/play/level/LevelChatView.coffee similarity index 100% rename from app/views/play/level/level_chat_view.coffee rename to app/views/play/level/LevelChatView.coffee diff --git a/app/views/play/level/goals_view.coffee b/app/views/play/level/LevelGoalsView.coffee similarity index 98% rename from app/views/play/level/goals_view.coffee rename to app/views/play/level/LevelGoalsView.coffee index 1264ada34..f0388ccc1 100644 --- a/app/views/play/level/goals_view.coffee +++ b/app/views/play/level/LevelGoalsView.coffee @@ -8,7 +8,7 @@ stateIconMap = success: 'icon-ok' failure: 'icon-remove' -module.exports = class GoalsView extends CocoView +module.exports = class LevelGoalsView extends CocoView id: 'goals-view' template: template diff --git a/app/views/play/level/gold_view.coffee b/app/views/play/level/LevelGoldView.coffee similarity index 96% rename from app/views/play/level/gold_view.coffee rename to app/views/play/level/LevelGoldView.coffee index 479fe8966..414ac60b3 100644 --- a/app/views/play/level/gold_view.coffee +++ b/app/views/play/level/LevelGoldView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/gold' teamTemplate = require 'templates/play/level/team_gold' -module.exports = class GoldView extends CocoView +module.exports = class LevelGoldView extends CocoView id: 'gold-view' template: template diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/LevelHUDView.coffee similarity index 99% rename from app/views/play/level/hud_view.coffee rename to app/views/play/level/LevelHUDView.coffee index a730bedf9..975888025 100644 --- a/app/views/play/level/hud_view.coffee +++ b/app/views/play/level/LevelHUDView.coffee @@ -2,9 +2,9 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/hud' prop_template = require 'templates/play/level/hud_prop' action_template = require 'templates/play/level/hud_action' -DialogueAnimator = require './dialogue_animator' +DialogueAnimator = require './DialogueAnimator' -module.exports = class HUDView extends CocoView +module.exports = class LevelHUDView extends CocoView id: 'thang-hud' template: template dialogueMode: false diff --git a/app/views/play/level/level_loading_view.coffee b/app/views/play/level/LevelLoadingView.coffee similarity index 100% rename from app/views/play/level/level_loading_view.coffee rename to app/views/play/level/LevelLoadingView.coffee diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/LevelPlaybackView.coffee similarity index 98% rename from app/views/play/level/playback_view.coffee rename to app/views/play/level/LevelPlaybackView.coffee index f089e3c25..eb619ce06 100644 --- a/app/views/play/level/playback_view.coffee +++ b/app/views/play/level/LevelPlaybackView.coffee @@ -2,10 +2,10 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/playback' {me} = require 'lib/auth' -EditorConfigModal = require './modal/editor_config_modal' -KeyboardShortcutsModal = require './modal/keyboard_shortcuts_modal' +EditorConfigModal = require './modal/EditorConfigModal' +KeyboardShortcutsModal = require './modal/KeyboardShortcutsModal' -module.exports = class PlaybackView extends CocoView +module.exports = class LevelPlaybackView extends CocoView id: 'playback-view' template: template diff --git a/app/views/play/level_view.coffee b/app/views/play/level/PlayLevelView.coffee similarity index 96% rename from app/views/play/level_view.coffee rename to app/views/play/level/PlayLevelView.coffee index 010479b5f..ec4ab8411 100644 --- a/app/views/play/level_view.coffee +++ b/app/views/play/level/PlayLevelView.coffee @@ -22,16 +22,16 @@ Camera = require 'lib/surface/Camera' AudioPlayer = require 'lib/AudioPlayer' # subviews -LoadingView = require './level/level_loading_view' -TomeView = require './level/tome/tome_view' -ChatView = require './level/level_chat_view' -HUDView = require './level/hud_view' -ControlBarView = require './level/control_bar_view' -PlaybackView = require './level/playback_view' -GoalsView = require './level/goals_view' -GoldView = require './level/gold_view' -VictoryModal = require './level/modal/victory_modal' -InfiniteLoopModal = require './level/modal/infinite_loop_modal' +LevelLoadingView = require './LevelLoadingView' +TomeView = require './tome/TomeView' +ChatView = require './LevelChatView' +HUDView = require './LevelHUDView' +ControlBarView = require './ControlBarView' +LevelPlaybackView = require './LevelPlaybackView' +GoalsView = require './LevelGoalsView' +GoldView = require './LevelGoldView' +VictoryModal = require './modal/VictoryModal' +InfiniteLoopModal = require './modal/InfiniteLoopModal' PROFILE_ME = false @@ -133,7 +133,7 @@ module.exports = class PlayLevelView extends RootView showGuide: -> @seenDocs = true - DocsModal = require './level/modal/docs_modal' + DocsModal = require './modal/docs_modal' options = docs: @levelLoader.level.get('documentation') supermodel: @supermodel @@ -160,7 +160,7 @@ module.exports = class PlayLevelView extends RootView afterRender: -> super() window.onPlayLevelViewLoaded? @ # still a hack - @insertSubView @loadingView = new LoadingView {} + @insertSubView @loadingView = new LevelLoadingView {} @$el.find('#level-done-button').hide() $('body').addClass('is-playing') @@ -229,7 +229,7 @@ module.exports = class PlayLevelView extends RootView insertSubviews: -> @insertSubView @tome = new TomeView levelID: @levelID, session: @session, otherSession: @otherSession, thangs: @world.thangs, supermodel: @supermodel - @insertSubView new PlaybackView session: @session + @insertSubView new LevelPlaybackView session: @session @insertSubView new GoalsView {} @insertSubView new GoldView {} @insertSubView new HUDView {} diff --git a/app/views/play/level/thang_avatar_view.coffee b/app/views/play/level/ThangAvatarView.coffee similarity index 100% rename from app/views/play/level/thang_avatar_view.coffee rename to app/views/play/level/ThangAvatarView.coffee diff --git a/app/views/play/level/modal/editor_config_modal.coffee b/app/views/play/level/modal/EditorConfigModal.coffee similarity index 100% rename from app/views/play/level/modal/editor_config_modal.coffee rename to app/views/play/level/modal/EditorConfigModal.coffee diff --git a/app/views/play/level/modal/infinite_loop_modal.coffee b/app/views/play/level/modal/InfiniteLoopModal.coffee similarity index 100% rename from app/views/play/level/modal/infinite_loop_modal.coffee rename to app/views/play/level/modal/InfiniteLoopModal.coffee diff --git a/app/views/play/level/modal/keyboard_shortcuts_modal.coffee b/app/views/play/level/modal/KeyboardShortcutsModal.coffee similarity index 100% rename from app/views/play/level/modal/keyboard_shortcuts_modal.coffee rename to app/views/play/level/modal/KeyboardShortcutsModal.coffee diff --git a/app/views/play/level/modal/docs_modal.coffee b/app/views/play/level/modal/LevelGuideModal.coffee similarity index 96% rename from app/views/play/level/modal/docs_modal.coffee rename to app/views/play/level/modal/LevelGuideModal.coffee index a046df051..5ba7fe01a 100644 --- a/app/views/play/level/modal/docs_modal.coffee +++ b/app/views/play/level/modal/LevelGuideModal.coffee @@ -5,7 +5,7 @@ utils = require 'lib/utils' # let's implement this once we have the docs database schema set up -module.exports = class DocsModal extends ModalView +module.exports = class LevelGuideModal extends ModalView template: template id: 'docs-modal' diff --git a/app/views/play/level/modal/multiplayer_modal.coffee b/app/views/play/level/modal/MultiplayerModal.coffee similarity index 96% rename from app/views/play/level/modal/multiplayer_modal.coffee rename to app/views/play/level/modal/MultiplayerModal.coffee index 6645ca2f3..3a74f8489 100644 --- a/app/views/play/level/modal/multiplayer_modal.coffee +++ b/app/views/play/level/modal/MultiplayerModal.coffee @@ -1,7 +1,7 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/play/level/modal/multiplayer' {me} = require 'lib/auth' -LadderSubmissionView = require 'views/play/common/ladder_submission_view' +LadderSubmissionView = require 'views/play/common/LadderSubmissionView' module.exports = class MultiplayerModal extends ModalView id: 'level-multiplayer-modal' diff --git a/app/views/play/level/modal/reload_modal.coffee b/app/views/play/level/modal/ReloadLevelModal.coffee similarity index 84% rename from app/views/play/level/modal/reload_modal.coffee rename to app/views/play/level/modal/ReloadLevelModal.coffee index f7089e05c..cd3700325 100644 --- a/app/views/play/level/modal/reload_modal.coffee +++ b/app/views/play/level/modal/ReloadLevelModal.coffee @@ -3,7 +3,7 @@ template = require 'templates/play/level/modal/reload' # let's implement this once we have the docs database schema set up -module.exports = class ReloadModal extends ModalView +module.exports = class ReloadLevelModal extends ModalView id: '#reload-code-modal' template: template diff --git a/app/views/play/level/modal/victory_modal.coffee b/app/views/play/level/modal/VictoryModal.coffee similarity index 98% rename from app/views/play/level/modal/victory_modal.coffee rename to app/views/play/level/modal/VictoryModal.coffee index 03c8d72d8..172e6ad14 100644 --- a/app/views/play/level/modal/victory_modal.coffee +++ b/app/views/play/level/modal/VictoryModal.coffee @@ -1,7 +1,7 @@ ModalView = require 'views/kinds/ModalView' template = require 'templates/play/level/modal/victory' {me} = require 'lib/auth' -LadderSubmissionView = require 'views/play/common/ladder_submission_view' +LadderSubmissionView = require 'views/play/common/LadderSubmissionView' LevelFeedback = require 'models/LevelFeedback' utils = require 'lib/utils' diff --git a/app/views/play/level/tome/cast_button_view.coffee b/app/views/play/level/tome/CastButtonView.coffee similarity index 100% rename from app/views/play/level/tome/cast_button_view.coffee rename to app/views/play/level/tome/CastButtonView.coffee diff --git a/app/views/play/level/tome/doc_formatter.coffee b/app/views/play/level/tome/DocFormatter.coffee similarity index 100% rename from app/views/play/level/tome/doc_formatter.coffee rename to app/views/play/level/tome/DocFormatter.coffee diff --git a/app/views/play/level/tome/problem_alert_view.coffee b/app/views/play/level/tome/ProblemAlertView.coffee similarity index 100% rename from app/views/play/level/tome/problem_alert_view.coffee rename to app/views/play/level/tome/ProblemAlertView.coffee diff --git a/app/views/play/level/tome/spell_debug_view.coffee b/app/views/play/level/tome/SpellDebugView.coffee similarity index 99% rename from app/views/play/level/tome/spell_debug_view.coffee rename to app/views/play/level/tome/SpellDebugView.coffee index 63e01f1b7..623e70d25 100644 --- a/app/views/play/level/tome/spell_debug_view.coffee +++ b/app/views/play/level/tome/SpellDebugView.coffee @@ -9,7 +9,7 @@ serializedClasses = Ellipse: require 'lib/world/ellipse' LineSegment: require 'lib/world/line_segment' -module.exports = class DebugView extends CocoView +module.exports = class SpellDebugView extends CocoView className: 'spell-debug-view' template: template diff --git a/app/views/play/level/tome/spell_list_entry_thangs_view.coffee b/app/views/play/level/tome/SpellListEntryThangsView.coffee similarity index 94% rename from app/views/play/level/tome/spell_list_entry_thangs_view.coffee rename to app/views/play/level/tome/SpellListEntryThangsView.coffee index eeba83590..6d730072b 100644 --- a/app/views/play/level/tome/spell_list_entry_thangs_view.coffee +++ b/app/views/play/level/tome/SpellListEntryThangsView.coffee @@ -1,5 +1,5 @@ CocoView = require 'views/kinds/CocoView' -ThangAvatarView = require 'views/play/level/thang_avatar_view' +ThangAvatarView = require 'views/play/level/ThangAvatarView' template = require 'templates/play/level/tome/spell_list_entry_thangs' module.exports = class SpellListEntryThangsView extends CocoView diff --git a/app/views/play/level/tome/spell_list_entry_view.coffee b/app/views/play/level/tome/SpellListEntryView.coffee similarity index 97% rename from app/views/play/level/tome/spell_list_entry_view.coffee rename to app/views/play/level/tome/SpellListEntryView.coffee index 05f18b23a..0ea75d5d4 100644 --- a/app/views/play/level/tome/spell_list_entry_view.coffee +++ b/app/views/play/level/tome/SpellListEntryView.coffee @@ -1,8 +1,8 @@ # TODO: This still needs a way to send problem states to its Thang CocoView = require 'views/kinds/CocoView' -ThangAvatarView = require 'views/play/level/thang_avatar_view' -SpellListEntryThangsView = require 'views/play/level/tome/spell_list_entry_thangs_view' +ThangAvatarView = require 'views/play/level/ThangAvatarView' +SpellListEntryThangsView = require 'views/play/level/tome/SpellListEntryThangsView' template = require 'templates/play/level/tome/spell_list_entry' module.exports = class SpellListEntryView extends CocoView diff --git a/app/views/play/level/tome/spell_list_tab_entry_view.coffee b/app/views/play/level/tome/SpellListTabEntryView.coffee similarity index 95% rename from app/views/play/level/tome/spell_list_tab_entry_view.coffee rename to app/views/play/level/tome/SpellListTabEntryView.coffee index 877229f54..ccd5f6716 100644 --- a/app/views/play/level/tome/spell_list_tab_entry_view.coffee +++ b/app/views/play/level/tome/SpellListTabEntryView.coffee @@ -1,8 +1,8 @@ -SpellListEntryView = require './spell_list_entry_view' -ThangAvatarView = require 'views/play/level/thang_avatar_view' +SpellListEntryView = require './SpellListEntryView' +ThangAvatarView = require 'views/play/level/ThangAvatarView' template = require 'templates/play/level/tome/spell_list_tab_entry' LevelComponent = require 'models/LevelComponent' -DocFormatter = require './doc_formatter' +DocFormatter = require './DocFormatter' module.exports = class SpellListTabEntryView extends SpellListEntryView template: template diff --git a/app/views/play/level/tome/spell_list_view.coffee b/app/views/play/level/tome/SpellListView.coffee similarity index 98% rename from app/views/play/level/tome/spell_list_view.coffee rename to app/views/play/level/tome/SpellListView.coffee index 9212bd04f..febdbce12 100644 --- a/app/views/play/level/tome/spell_list_view.coffee +++ b/app/views/play/level/tome/SpellListView.coffee @@ -7,7 +7,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/spell_list' {me} = require 'lib/auth' -SpellListEntryView = require './spell_list_entry_view' +SpellListEntryView = require './SpellListEntryView' module.exports = class SpellListView extends CocoView className: 'spell-list-view' diff --git a/app/views/play/level/tome/spell_palette_entry_view.coffee b/app/views/play/level/tome/SpellPaletteEntryView.coffee similarity index 98% rename from app/views/play/level/tome/spell_palette_entry_view.coffee rename to app/views/play/level/tome/SpellPaletteEntryView.coffee index e09116876..3b7f53c71 100644 --- a/app/views/play/level/tome/spell_palette_entry_view.coffee +++ b/app/views/play/level/tome/SpellPaletteEntryView.coffee @@ -2,7 +2,7 @@ CocoView = require 'views/kinds/CocoView' template = require 'templates/play/level/tome/spell_palette_entry' {me} = require 'lib/auth' filters = require 'lib/image_filter' -DocFormatter = require './doc_formatter' +DocFormatter = require './DocFormatter' module.exports = class SpellPaletteEntryView extends CocoView tagName: 'div' # Could also try instead of
, but would need to adjust colors diff --git a/app/views/play/level/tome/spell_palette_view.coffee b/app/views/play/level/tome/SpellPaletteView.coffee similarity index 98% rename from app/views/play/level/tome/spell_palette_view.coffee rename to app/views/play/level/tome/SpellPaletteView.coffee index 89914fb3e..15bcbf8c5 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 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 99% rename from app/views/play/level/tome/spell_view.coffee rename to app/views/play/level/tome/SpellView.coffee index 46fb62e4e..585d184f1 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 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/play/level/tome/problem.coffee b/app/views/play/level/tome/pproblem.coffee similarity index 96% rename from app/views/play/level/tome/problem.coffee rename to app/views/play/level/tome/pproblem.coffee index 13fb7cede..5aaa1907d 100644 --- a/app/views/play/level/tome/problem.coffee +++ b/app/views/play/level/tome/pproblem.coffee @@ -1,4 +1,4 @@ -ProblemAlertView = require './problem_alert_view' +ProblemAlertView = require './ProblemAlertView' Range = ace.require('ace/range').Range module.exports = class Problem diff --git a/app/views/play/level/tome/spell.coffee b/app/views/play/level/tome/sspell.coffee similarity index 98% rename from app/views/play/level/tome/spell.coffee rename to app/views/play/level/tome/sspell.coffee index 72a897ee2..2f1b62d0e 100644 --- a/app/views/play/level/tome/spell.coffee +++ b/app/views/play/level/tome/sspell.coffee @@ -1,5 +1,5 @@ -SpellView = require './spell_view' -SpellListTabEntryView = require './spell_list_tab_entry_view' +SpellView = require './SpellView' +SpellListTabEntryView = require './SpellListTabEntryView' {me} = require 'lib/auth' Aether.addGlobal 'Vector', require 'lib/world/vector' diff --git a/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 From 65375aa5fcc54120cda072fde9dc0e0a71e695a8 Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Wed, 23 Jul 2014 07:09:05 -0700 Subject: [PATCH 20/47] Renamed problem and spell to their new, capitalized names. --- app/views/play/level/tome/{pproblem.coffee => Problem.coffee} | 0 app/views/play/level/tome/{sspell.coffee => Spell.coffee} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename app/views/play/level/tome/{pproblem.coffee => Problem.coffee} (100%) rename app/views/play/level/tome/{sspell.coffee => Spell.coffee} (100%) diff --git a/app/views/play/level/tome/pproblem.coffee b/app/views/play/level/tome/Problem.coffee similarity index 100% rename from app/views/play/level/tome/pproblem.coffee rename to app/views/play/level/tome/Problem.coffee diff --git a/app/views/play/level/tome/sspell.coffee b/app/views/play/level/tome/Spell.coffee similarity index 100% rename from app/views/play/level/tome/sspell.coffee rename to app/views/play/level/tome/Spell.coffee From 5279b01483dab5874ce7807b6abbff1450bb183a Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Wed, 23 Jul 2014 17:39:16 +0200 Subject: [PATCH 21/47] fixed showing pinned popover --- app/styles/play/level/tome/tome.sass | 8 ++++++++ 1 file changed, 8 insertions(+) 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 From 5477a5b84af11cfea6b95cfafc4f21200360a447 Mon Sep 17 00:00:00 2001 From: Dominik Kundel Date: Wed, 23 Jul 2014 17:52:15 +0200 Subject: [PATCH 22/47] fixed broken build from #1380 --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 87630ea99..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.3", + "zatanna": "~0.0.4", "modernizr": "~2.8.3" }, "overrides": { From 26ac94367e79bc28cfdf6d82d946715b1b18ca1a Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Wed, 23 Jul 2014 08:59:42 -0700 Subject: [PATCH 23/47] Fixed #1372. Minor fixes. --- app/lib/surface/CocoSprite.coffee | 2 +- app/templates/play/ladder/ladder_tab.jade | 4 ++-- app/views/play/level/tome/SpellPaletteView.coffee | 13 ++++++++----- server/queues/scoring.coffee | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) 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/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade index bce03bf95..df72b69af 100644 --- a/app/templates/play/ladder/ladder_tab.jade +++ b/app/templates/play/ladder/ladder_tab.jade @@ -26,7 +26,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 !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 diff --git a/app/views/play/level/tome/SpellPaletteView.coffee b/app/views/play/level/tome/SpellPaletteView.coffee index 15bcbf8c5..e239ee4d0 100644 --- a/app/views/play/level/tome/SpellPaletteView.coffee +++ b/app/views/play/level/tome/SpellPaletteView.coffee @@ -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 diff --git a/server/queues/scoring.coffee b/server/queues/scoring.coffee index d35ce871a..d6aa6f3cb 100644 --- a/server/queues/scoring.coffee +++ b/server/queues/scoring.coffee @@ -124,7 +124,7 @@ module.exports.getTwoGames = (req, res) -> #if userIsAnonymous req then return errors.unauthorized(res, 'You need to be logged in to get games.') humansGameID = req.body.humansGameID ogresGameID = req.body.ogresGameID - ladderGameIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush'] + ladderGameIDs = ['greed', 'criss-cross', 'brawlwood', 'dungeon-arena', 'gold-rush', 'sky-span'] levelID = _.sample ladderGameIDs unless ogresGameID and humansGameID #fetch random games here From 7910c5d9cc0ec1af57136bcd40f27f85587c6622 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Wed, 23 Jul 2014 15:10:51 -0700 Subject: [PATCH 24/47] Implement #1370 --- app/templates/play/ladder/ladder_tab.jade | 2 +- app/views/play/ladder/LadderTabView.coffee | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/templates/play/ladder/ladder_tab.jade b/app/templates/play/ladder/ladder_tab.jade index df72b69af..2c74735eb 100644 --- a/app/templates/play/ladder/ladder_tab.jade +++ b/app/templates/play/ladder/ladder_tab.jade @@ -21,7 +21,7 @@ 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" diff --git a/app/views/play/ladder/LadderTabView.coffee b/app/views/play/ladder/LadderTabView.coffee index e049b2c26..1780fa057 100644 --- a/app/views/play/ladder/LadderTabView.coffee +++ b/app/views/play/ladder/LadderTabView.coffee @@ -178,6 +178,7 @@ module.exports = class LadderTabView extends CocoView ctx.friends = @consolidateFriends() ctx.onFacebook = @facebookStatus is 'connected' ctx.onGPlus = application.gplusHandler.loggedIn + ctx.capitalize = _.string.capitalize ctx generateHistogram: (histogramElement, histogramData, teamName) -> From be28f3e6a0b0aa42ff6813416e7ba776b327ce56 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Wed, 23 Jul 2014 15:23:53 -0700 Subject: [PATCH 25/47] Uncommented some commented translated lines --- app/locale/de-CH.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/locale/de-CH.coffee b/app/locale/de-CH.coffee index 2ffce1674..770f088a0 100644 --- a/app/locale/de-CH.coffee +++ b/app/locale/de-CH.coffee @@ -100,12 +100,12 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge for_beginners: "Für Afänger" multiplayer: "Multiplayer" for_developers: "Für Entwickler" -# 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." + 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: "D Sproch für Game Scripts." -# io_blurb: "Eifach aber undurchsichtig." + lua_blurb: "D Sproch für Game Scripts." + io_blurb: "Eifach aber undurchsichtig." play: choose_your_level: "Wähl dis Level us" From 2120657e5b71d8c9f7844beee9da247d64c4b7f8 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Thu, 24 Jul 2014 10:16:43 -0700 Subject: [PATCH 26/47] Add login link to profile login prompt --- app/templates/account/profile.jade | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/templates/account/profile.jade b/app/templates/account/profile.jade index 46a15da4e..fde78ef60 100644 --- a/app/templates/account/profile.jade +++ b/app/templates/account/profile.jade @@ -3,7 +3,10 @@ extends /templates/base block content if !allowedToEditJobProfile && me.get('anonymous') == true div(class="job-profile-container") - h1#login-message Please login to view this profile. + h1#login-message + |Please + a.auth-button login + | to view this profile. else if allowedToEditJobProfile .profile-control-bar From d773c301fba90823d3e32ba37b0a96153aab3315 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Thu, 24 Jul 2014 10:47:27 -0700 Subject: [PATCH 27/47] Add message if no player code in profile --- app/templates/account/profile.jade | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/templates/account/profile.jade b/app/templates/account/profile.jade index fde78ef60..37ff7ef85 100644 --- a/app/templates/account/profile.jade +++ b/app/templates/account/profile.jade @@ -194,7 +194,9 @@ block content span.spl - #{session.team} if session.codeLanguage != 'javascript' span.spl - #{{coffeescript: 'CoffeeScript', python: 'Python', lua: 'Lua', io: 'Io', clojure: 'Clojure'}[session.codeLanguage]} - + if !editing && !sessions.length + h3(data-i18n="account_profile.player_code") Player Code + p This player hasn't submitted code to our more recent tournaments. .middle-column.full-height-column .sub-column #name-container.editable-section From f78c48c8933fe24d6b2c91022927100e7e749e50 Mon Sep 17 00:00:00 2001 From: Darredevil Date: Fri, 25 Jul 2014 01:26:34 +0300 Subject: [PATCH 28/47] Docs tab v2 --- app/templates/docs/components.jade | 2 +- app/templates/editor/level/edit.jade | 4 ++-- app/views/docs/components_view.coffee | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) 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/level/edit.jade b/app/templates/editor/level/edit.jade index e84ed276c..7189d31c5 100644 --- a/app/templates/editor/level/edit.jade +++ b/app/templates/editor/level/edit.jade @@ -34,7 +34,7 @@ block header if patches && patches.length span.badge= patches.length li - a(href="#docs-component-view", data-toggle="tab", data-i18n="editor.docs-component-view") Documentation + a(href="#docs-components-view", data-toggle="tab", data-i18n="editor.level_tab_docs") Documentation .navbar-header span.navbar-brand #{level.attributes.name} @@ -115,7 +115,7 @@ block outer_content div.tab-pane#editor-level-patches .patches-view - div.tab-pane#docs-component-view + div.tab-pane#docs-components-view div#error-view diff --git a/app/views/docs/components_view.coffee b/app/views/docs/components_view.coffee index eedba904e..dc10d91ae 100644 --- a/app/views/docs/components_view.coffee +++ b/app/views/docs/components_view.coffee @@ -1,8 +1,12 @@ -RootView = require 'views/kinds/RootView' +#RootView = require 'views/kinds/RootView' +CocoView = require 'views/kinds/RootView' template = require 'templates/docs/components' CocoCollection = require 'collections/CocoCollection' LevelComponent = require 'models/LevelComponent' +class UnnamedView extends CocoView + className: 'tab-pane' + class ComponentDocsCollection extends CocoCollection url: '/db/level.component?project=name,description,dependencies,propertyDocumentation,code' model: LevelComponent From 86cf344f28a4b913edb56bb2de1d961d53577a7a Mon Sep 17 00:00:00 2001 From: Jayant Jain Date: Fri, 25 Jul 2014 17:50:02 +0530 Subject: [PATCH 29/47] Adds preset images to preview the generated terrain --- .../pages/editor/level/preset_grassy_large.jpg | Bin 0 -> 75982 bytes .../pages/editor/level/preset_grassy_small.jpg | Bin 0 -> 69809 bytes .../editor/level/modal/terrain_randomize.sass | 2 +- .../editor/level/modal/terrain_randomize.jade | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 app/assets/images/pages/editor/level/preset_grassy_large.jpg create mode 100644 app/assets/images/pages/editor/level/preset_grassy_small.jpg 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 0000000000000000000000000000000000000000..53c8bc2a7612da68e0ca2c20e0c667dee2b9cb0a GIT binary patch literal 75982 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
UMYvr1l4(*O4YS|*k_$VAqU~0yl+)6&t7(|eA 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 F|Jg>6ndJZg literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ed93569449aaafe65f06a884f5b4e4c2faf155bd GIT binary patch literal 69809 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 +a;xiqDm?l+K-T^)=Mk>n4Boi%%mZEjMo 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
  • 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