diff --git a/app/locale/en.coffee b/app/locale/en.coffee index 41f9f15b6..4696d8dae 100644 --- a/app/locale/en.coffee +++ b/app/locale/en.coffee @@ -15,6 +15,9 @@ fork: "Fork" play: "Play" retry: "Retry" + watch: "Watch" + unwatch: "Unwatch" + submit_patch: "Submit Patch" units: second: "second" diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee index c93708ee2..b33177a3a 100644 --- a/app/models/CocoModel.coffee +++ b/app/models/CocoModel.coffee @@ -60,6 +60,7 @@ class CocoModel extends Backbone.Model return result.errors unless result.valid save: (attrs, options) -> + @set 'editPath', document.location.pathname options ?= {} success = options.success options.success = (resp) => @@ -68,7 +69,6 @@ class CocoModel extends Backbone.Model @markToRevert() @clearBackup() @trigger "save", @ - patch.setStatus 'accepted' for patch in @acceptedPatches or [] return super attrs, options fetch: -> @@ -95,7 +95,6 @@ class CocoModel extends Backbone.Model cloneNewMinorVersion: -> newData = $.extend(null, {}, @attributes) clone = new @constructor(newData) - clone.acceptedPatches = @acceptedPatches clone cloneNewMajorVersion: -> @@ -221,9 +220,11 @@ class CocoModel extends Backbone.Model delta = @getDelta() deltasLib.expandDelta(delta, @_revertAttributes, @schema()) - addPatchToAcceptOnSave: (patch) -> - @acceptedPatches ?= [] - @acceptedPatches.push patch - @acceptedPatches = _.uniq(@acceptedPatches, false, (p) -> p.id) + watch: (doWatch=true) -> + $.ajax("#{@urlRoot}/#{@id}/watch", {type:'PUT', data:{on:doWatch}}) + @watching = -> doWatch + + watching: -> + return me.id in (@get('watchers') or []) module.exports = CocoModel diff --git a/app/models/Patch.coffee b/app/models/Patch.coffee index 68b62eca9..c505c93c0 100644 --- a/app/models/Patch.coffee +++ b/app/models/Patch.coffee @@ -5,4 +5,7 @@ module.exports = class PatchModel extends CocoModel urlRoot: "/db/patch" setStatus: (status) -> - $.ajax("/db/patch/#{@id}/status", {type:"PUT", data: {status:status}}) \ No newline at end of file + PatchModel.setStatus @id, status + + @setStatus: (id, status) -> + $.ajax("/db/patch/#{id}/status", {type:"PUT", data: {status:status}}) \ No newline at end of file diff --git a/app/schemas/schemas.coffee b/app/schemas/schemas.coffee index 2d7ae0603..9c20c9ba2 100644 --- a/app/schemas/schemas.coffee +++ b/app/schemas/schemas.coffee @@ -63,7 +63,7 @@ patchableProps = -> status: { enum: ['pending', 'accepted', 'rejected', 'cancelled']} }) allowPatches: { type: 'boolean' } - listeners: me.array({title:'Listeners'}, + watchers: me.array({title:'Watchers'}, me.objectId(links: [{rel: 'extra', href: "/db/user/{($)}"}])) me.extendPatchableProperties = (schema) -> diff --git a/app/styles/base.sass b/app/styles/base.sass index 0425ba2d6..afa9fbcc9 100644 --- a/app/styles/base.sass +++ b/app/styles/base.sass @@ -265,3 +265,8 @@ body[lang='ja'] font-family: 'Glyphicons Halflings' src: url("/fonts/glyphicons-halflings-regular.eot") src: url("/fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("/fonts/glyphicons-halflings-regular.woff") format("woff"), url("/fonts/glyphicons-halflings-regular.ttf") format("truetype"), url("/fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular") format("svg") + +.spr:after + content: " " +.spl:before + content: " " \ No newline at end of file diff --git a/app/styles/editor/level/component/edit.sass b/app/styles/editor/level/component/edit.sass index 5c9deda4c..7a78534ed 100644 --- a/app/styles/editor/level/component/edit.sass +++ b/app/styles/editor/level/component/edit.sass @@ -1,4 +1,11 @@ #editor-level-component-edit-view + nav + margin-bottom: 0 + + #component-patches + padding: 0 10px 10px + background: white + .navbar-text float: left @@ -7,9 +14,13 @@ left: 0 right: 0 bottom: 0 - top: 50px + top: 35px border: 2px solid black border-top: none - .active > a, .active > a:hover, .active > a:focus - background-color: white !important \ No newline at end of file + .inner-editor + position: absolute + left: 0 + right: 0 + bottom: 0 + top: 0px \ No newline at end of file diff --git a/app/styles/editor/level/components_tab.sass b/app/styles/editor/level/components_tab.sass index b8a029a5b..c70a5f4d6 100644 --- a/app/styles/editor/level/components_tab.sass +++ b/app/styles/editor/level/components_tab.sass @@ -1,4 +1,6 @@ #editor-level-components-tab-view + h3 + margin-top: 0 .components-container position: absolute @@ -7,7 +9,7 @@ .treema-root position: absolute - top: 50px + top: 35px bottom: 0 width: 250px overflow: scroll @@ -25,13 +27,13 @@ .treema-root position: absolute - top: 50px + top: 35px right: 0 left: 0px bottom: 0 overflow: scroll - #create-new-component-button + #create-new-component-button-no-select position: absolute top: 0 right: 0 diff --git a/app/styles/editor/level/edit.sass b/app/styles/editor/level/edit.sass index f1cfc2303..7d2b5b962 100644 --- a/app/styles/editor/level/edit.sass +++ b/app/styles/editor/level/edit.sass @@ -1,10 +1,10 @@ #editor-level-view + &, #level-editor-top-nav + min-width: 1024px + a font-family: helvetica, arial, sans serif - #top-nav - display: none - position: absolute top: 0px left: 0px @@ -12,22 +12,54 @@ bottom: 0px $BG: rgba(228, 207, 140, 1.0) + $NAVBG: #2f261d li.navbar-btn margin-right: 5px - #level-editor-top-nav - .nav-tabs - border-bottom: 0 !important - .active > a, .active > a:hover, .active > a:focus - background-color: $BG !important - border-color: darken($BG, 50%) - border-bottom: 0 + // custom navbar height rules + .navbar-nav > li > a + padding: 7px 8px 8px + cursor: pointer + &:hover + background-color: lighten($NAVBG, 10%) + .navbar + min-height: 0px + border-radius: 0 + .navbar-right // not sure why bootstrap puts a big negative margin in, but this overrides it + margin-right: 10px + + // custom navbar styling + .navbar-brand + padding-top: 7px + padding-bottom: 7px + color: lighten(gold, 30%) + .navbar-header + border-left: 2px solid lighten($NAVBG, 20%) + border-right: 2px solid lighten($NAVBG, 20%) + background: lighten($NAVBG, 10%) + margin-left: 20px + .nav-tabs + margin-left: 5px + border-bottom: 0 !important + .active > a, .active > a:hover, .active > a:focus + background-color: $BG !important + border-color: darken($BG, 50%) + border-bottom: 0 + a + padding: 7px 5px !important + .dropdown-menu a + cursor: pointer + &:hover + background-color: #d3d3d3 + + .badge + background-color: green .outer-content background-color: $BG position: absolute - top: 0 + top: 35px bottom: 0 left: 0 right: 0 @@ -45,12 +77,11 @@ #level-editor-tabs position: absolute - left: 20px - right: 20px - top: 66px - bottom: 20px + left: 15px + right: 15px + top: 15px + bottom: 15px .treema-root background-color: white - border-radius: 4px - + border-radius: 4px \ No newline at end of file diff --git a/app/styles/editor/level/system/edit.sass b/app/styles/editor/level/system/edit.sass index e86dc5a46..567ff5b27 100644 --- a/app/styles/editor/level/system/edit.sass +++ b/app/styles/editor/level/system/edit.sass @@ -7,9 +7,13 @@ left: 0 right: 0 bottom: 0 - top: 50px + top: 35px border: 2px solid black border-top: none - - .active > a, .active > a:hover, .active > a:focus - background-color: white !important \ No newline at end of file + + .inner-editor + position: absolute + left: 0 + right: 0 + bottom: 0 + top: 0px \ No newline at end of file diff --git a/app/styles/editor/level/systems_tab.sass b/app/styles/editor/level/systems_tab.sass index 88585504d..0d1aa6b33 100644 --- a/app/styles/editor/level/systems_tab.sass +++ b/app/styles/editor/level/systems_tab.sass @@ -1,4 +1,6 @@ #editor-level-systems-tab-view + h3 + margin-top: 0 .systems-container position: absolute @@ -7,7 +9,7 @@ .treema-root position: absolute - top: 50px + top: 35px bottom: 0 width: 250px overflow: scroll @@ -30,7 +32,7 @@ .treema-root position: absolute - top: 50px + top: 35px right: 0 left: 0px bottom: 0 diff --git a/app/styles/editor/patches.sass b/app/styles/editor/patches.sass index 87c22728e..110370137 100644 --- a/app/styles/editor/patches.sass +++ b/app/styles/editor/patches.sass @@ -1,3 +1,3 @@ .patches-view .status-buttons - margin: 10px 0 + margin-bottom: 10px diff --git a/app/templates/editor/level/component/edit.jade b/app/templates/editor/level/component/edit.jade index 23c24cf6c..7228ff914 100644 --- a/app/templates/editor/level/component/edit.jade +++ b/app/templates/editor/level/component/edit.jade @@ -1,23 +1,44 @@ nav.navbar.navbar-default(role='navigation') - .container-fluid - .navbar-header - span.navbar-brand - span(data-i18n="editor.level_component_edit_title") - | Edit Component - span : - | "#{editTitle}" - .collapse.navbar-collapse - ul.nav.navbar-nav.nav-tabs - li.active - a(href="#component-code" data-toggle="tab" data-i18n="general.code") Code + ul.nav.navbar-nav.nav-tabs + li.active + a(href="#component-code" data-toggle="tab" data-i18n="general.code")#component-code-tab Code + li + a(href="#component-config-schema" data-toggle="tab" data-i18n="editor.level_component_config_schema")#component-config-schema-tab Config Schema + li + a(href="#component-settings" data-toggle="tab" data-i18n="editor.level_component_settings")#component-settings-tab Settings + li + a(href="#component-patches" data-toggle="tab" data-i18n="resources.patches")#component-patches-tab Patches + + .navbar-header + span.navbar-brand= editTitle + + ul.nav.navbar-nav.navbar-right + li.dropdown + a(data-toggle='dropdown') + span.glyphicon-chevron-down.glyphicon + + ul.dropdown-menu + li.dropdown-header Actions li - a(href="#component-config-schema" data-toggle="tab" data-i18n="editor.level_component_config_schema") Config Schema - li - a(href="#component-settings" data-toggle="tab" data-i18n="editor.level_component_settings") Settings - ul.nav.navbar-nav.navbar-left - li(data-i18n="general.version_history").btn.btn-primary.navbar-btn#history-button Version History - ul.nav.navbar-nav.navbar-right - li(data-i18n="editor.level_component_btn_new").btn.btn-primary.navbar-btn#create-new-component-button Create New Component + a#component-watch-button + span.watch + span.glyphicon.glyphicon-eye-open + span.spl Watch + span.unwatch.secret + span.glyphicon.glyphicon-eye-close + span.spl Unwatch + + li#patch-component-button + a(data-i18n="common.submit_patch") Submit Patch + + li#create-new-component-button + a(data-i18n="editor.level_component_btn_new") Create New Component + + li.divider + li.dropdown-header Info + + li#component-history-button + a(data-i18n="general.version_history") Version History .tab-content .tab-pane.active#component-code @@ -26,3 +47,5 @@ nav.navbar.navbar-default(role='navigation') #config-schema-treema .tab-pane#component-settings #edit-component-treema + .tab-pane#component-patches + .patches-view \ No newline at end of file diff --git a/app/templates/editor/level/components_tab.jade b/app/templates/editor/level/components_tab.jade index e97f47aa4..9cd86545e 100644 --- a/app/templates/editor/level/components_tab.jade +++ b/app/templates/editor/level/components_tab.jade @@ -4,6 +4,6 @@ .edit-component-container if me.isAdmin() - button(data-i18n="editor.level_component_btn_new").btn.btn-primary#create-new-component-button Create New Component + button(data-i18n="editor.level_component_btn_new").btn.btn-primary#create-new-component-button-no-select Create New Component #editor-level-component-edit-view diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade index ba69b27fd..6b010912d 100644 --- a/app/templates/editor/level/edit.jade +++ b/app/templates/editor/level/edit.jade @@ -1,74 +1,90 @@ extends /templates/base -block outer_content - .outer-content - +block header + if level.loading nav.navbar.navbar-default(role='navigation')#level-editor-top-nav .container-fluid ul.nav.navbar-nav li - a(href="/editor/level", data-i18n="editor.back") Back - .navbar-header - span.navbar-brand - span(data-i18n="editor.level_title") Level Editor - span : - span.level-title #{level.attributes.name} - .collapse.navbar-collapse - ul.nav.navbar-nav.nav-tabs - - li.active - a(href="#editor-level-thangs-tab-view", data-toggle="tab", data-i18n="editor.level_tab_thangs") Thangs - li - a(href="#editor-level-scripts-tab-view", data-toggle="tab", data-i18n="editor.level_tab_scripts") Scripts - li - a(href="#editor-level-settings-tab-view", data-toggle="tab", data-i18n="editor.level_tab_settings") Settings - li - a(href="#editor-level-components-tab-view", data-toggle="tab", data-i18n="editor.level_tab_components") Components - li - a(href="#editor-level-systems-tab-view", data-toggle="tab", data-i18n="editor.level_tab_systems") Systems - li - a(href="#editor-level-patches", data-toggle="tab", data-i18n="resources.patches")#patches-tab Patches - - - ul.nav.navbar-nav.navbar-right - li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=authorized === true ? undefined : "true").btn.btn-primary.navbar-btn#revert-button Revert - if authorized - li(data-i18n="common.save").btn.btn-primary.navbar-btn#commit-level-start-button Save - else - li(data-i18n="common.patch").btn.btn-primary.navbar-btn#commit-level-patch-button Patch - li(data-i18n="common.fork", disabled=anonymous ? "true": undefined).btn.btn-primary.navbar-btn#fork-level-start-button Fork - li(title="⌃↩ or ⌘↩: Play preview of current level", data-i18n="common.play")#play-button.btn.btn-inverse.banner.navbar-btn Play! - - li.divider - - li.dropdown - a.dropdown-toggle(href='#', data-toggle='dropdown', data-i18n="editor.more") - | More - b.caret - ul.dropdown-menu - li#history-button - a(href='#', data-i18n="general.version_history") Version History - li - a(href='https://github.com/codecombat/codecombat/wiki/Artisan-Home', data-i18n="editor.wiki") Wiki - li - a(href='http://www.hipchat.com/g3plnOKqa', data-i18n="editor.live_chat") Live Chat - li - a(href='http://discourse.codecombat.com/category/artisan', data-i18n="nav.forum") Forum - li - a(data-toggle="coco-modal", data-target="modal/contact", data-i18n="nav.contact") Email - - - - ul.dropdown-menu - li - span(data-i18n="editor.level_some_options").dropdown-menu-header Some Options? - li.divider - li - a(data-delay="1000", href="#", data-i18n="common.delay_1_sec") 1 second - a(data-delay="3000", href="#", data-i18n="common.delay_3_sec") 3 seconds - a(data-delay="5000", href="#", data-i18n="common.delay_5_sec") 5 seconds - a(data-delay="90019001", href="#", data-i18n="common.manual") Manual + a(href="/editor/level") + span.glyphicon-home.glyphicon + else + nav.navbar.navbar-default(role='navigation')#level-editor-top-nav + ul.nav.navbar-nav + li + a(href="/editor/level") + span.glyphicon-home.glyphicon + ul.nav.navbar-nav.nav-tabs + + li.active + a(href="#editor-level-thangs-tab-view", data-toggle="tab", data-i18n="editor.level_tab_thangs") Thangs + li + a(href="#editor-level-scripts-tab-view", data-toggle="tab", data-i18n="editor.level_tab_scripts") Scripts + li + a(href="#editor-level-settings-tab-view", data-toggle="tab", data-i18n="editor.level_tab_settings") Settings + li + a(href="#editor-level-components-tab-view", data-toggle="tab", data-i18n="editor.level_tab_components") Components + li + a(href="#editor-level-systems-tab-view", data-toggle="tab", data-i18n="editor.level_tab_systems") Systems + li + a(href="#editor-level-patches", data-toggle="tab")#patches-tab + span(data-i18n="resources.patches").spr Patches + - var patches = level.get('patches') + if patches && patches.length + span.badge= patches.length + + .navbar-header + span.navbar-brand #{level.attributes.name} + + ul.nav.navbar-nav.navbar-right + if authorized + li#commit-level-start-button + a + span.glyphicon-floppy-disk.glyphicon + else + li#level-patch-button + a + span.glyphicon-floppy-disk.glyphicon + + li(title="⌃↩ or ⌘↩: Play preview of current level")#play-button + a + span.glyphicon-play.glyphicon + li.dropdown + a(data-toggle='dropdown') + span.glyphicon-chevron-down.glyphicon + ul.dropdown-menu + li.dropdown-header Actions + li + a#level-watch-button + span.watch + span.glyphicon.glyphicon-eye-open + span.spl Watch + span.unwatch.secret + span.glyphicon.glyphicon-eye-close + span.spl Unwatch + + 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 + li.divider + li.dropdown-header Info + li#level-history-button + a(href='#', data-i18n="general.version_history") Version History + li.divider + li.dropdown-header Help + li + a(href='https://github.com/codecombat/codecombat/wiki/Artisan-Home', data-i18n="editor.wiki", target="_blank") Wiki + li + a(href='http://www.hipchat.com/g3plnOKqa', data-i18n="editor.live_chat", target="_blank") Live Chat + 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 + +block outer_content + .outer-content div.tab-content#level-editor-tabs div.tab-pane.active#editor-level-thangs-tab-view diff --git a/app/templates/editor/level/system/edit.jade b/app/templates/editor/level/system/edit.jade index db20287b6..267993ea5 100644 --- a/app/templates/editor/level/system/edit.jade +++ b/app/templates/editor/level/system/edit.jade @@ -1,21 +1,40 @@ nav.navbar.navbar-default(role='navigation') - .container-fluid - .navbar-header - span.navbar-brand - span(data-i18n="editor.level_system_edit_title") - | Edit System - span : - | "#{editTitle}" - .collapse.navbar-collapse - ul.nav.navbar-nav.nav-tabs - li.active - a(href="#system-code" data-toggle="tab") Code + + ul.nav.navbar-nav.nav-tabs + li.active + a(href="#system-code" data-toggle="tab")#system-code-tab Code + li + a(href="#system-config-schema" data-toggle="tab")#system-config-schema-tab Config Schema + li + a(href="#system-settings" data-toggle="tab")#system-settings-tab Settings + li + a(href="#system-patches" data-toggle="tab" data-i18n="resources.patches")#system-patches-tab Patches + + ul.nav.navbar-nav.navbar-right + li.dropdown + a(data-toggle='dropdown') + span.glyphicon-chevron-down.glyphicon + ul.dropdown-menu + li.dropdown-header Actions li - a(href="#system-config-schema" data-toggle="tab") Config Schema - li - a(href="#system-settings" data-toggle="tab") Settings - ul.nav.navbar-nav.navbar-right - li(data-i18n="editor.level_system_btn_new").btn.btn-primary.navbar-btn#create-new-system-button Create New System + a#system-watch-button + span.watch + span.glyphicon.glyphicon-eye-open + span.spl Watch + span.unwatch.secret + span.glyphicon.glyphicon-eye-close + span.spl Unwatch + li#patch-system-button + a(data-i18n="common.submit_patch") Submit Patch + li#create-new-system + a(data-i18n="editor.level_system_btn_new") Create New System + li.divider + li.dropdown-header Info + li#system-history-button + a(data-i18n="general.version_history") Version History + + .navbar-header + span.navbar-brand= editTitle .tab-content .tab-pane.active#system-code @@ -24,3 +43,5 @@ nav.navbar.navbar-default(role='navigation') #config-schema-treema .tab-pane#system-settings #edit-system-treema + .tab-pane#system-patches + .patches-view \ No newline at end of file diff --git a/app/templates/editor/patch_modal.jade b/app/templates/editor/patch_modal.jade index 68fed43f7..4d46d8cb5 100644 --- a/app/templates/editor/patch_modal.jade +++ b/app/templates/editor/patch_modal.jade @@ -6,6 +6,7 @@ block modal-header-content block modal-body-content .modal-body + p= patch.get('commitMessage') .changes-stub diff --git a/app/templates/modal/versions.jade b/app/templates/modal/versions.jade index bd5b099eb..af78e7fcd 100755 --- a/app/templates/modal/versions.jade +++ b/app/templates/modal/versions.jade @@ -8,7 +8,7 @@ block modal-header-content block modal-body-content if dataList - table.table + table.table.table-condensed tr th(data-i18n="general.name") Name th(data-i18n="general.version") Version diff --git a/app/views/editor/delta.coffee b/app/views/editor/delta.coffee index 09c0981a6..b79b1cda5 100644 --- a/app/views/editor/delta.coffee +++ b/app/views/editor/delta.coffee @@ -21,12 +21,12 @@ module.exports = class DeltaView extends CocoView if @headModel @headDeltas = @headModel.getExpandedDelta() @conflicts = deltasLib.getConflicts(@headDeltas, @expandedDeltas) - DeltaView.deltaCounter += @expandedDeltas.length getRenderData: -> c = super() c.deltas = @expandedDeltas c.counter = DeltaView.deltaCounter + DeltaView.deltaCounter += @expandedDeltas.length c afterRender: -> diff --git a/app/views/editor/level/component/edit.coffee b/app/views/editor/level/component/edit.coffee index 3f91f1467..74c23b567 100644 --- a/app/views/editor/level/component/edit.coffee +++ b/app/views/editor/level/component/edit.coffee @@ -1,7 +1,9 @@ View = require 'views/kinds/CocoView' -VersionHistoryView = require 'views/editor/component/versions_view' 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' module.exports = class LevelComponentEditView extends View id: "editor-level-component-edit-view" @@ -10,8 +12,14 @@ module.exports = class LevelComponentEditView extends View events: 'click #done-editing-component-button': 'endEditing' - 'click #history-button': 'showVersionHistory' 'click .nav a': (e) -> $(e.target).tab('show') + 'click #component-patches-tab': -> @patchesView.load() + 'click #component-code-tab': 'buildCodeEditor' + 'click #component-config-schema-tab': 'buildConfigSchemaTreema' + 'click #component-settings-tab': 'buildSettingsTreema' + 'click #component-history-button': 'showVersionHistory' + 'click #patch-component-button': 'startPatchingComponent' + 'click #component-watch-button': 'toggleWatchComponent' constructor: (options) -> super options @@ -21,6 +29,7 @@ module.exports = class LevelComponentEditView extends View getRenderData: (context={}) -> context = super(context) context.editTitle = "#{@levelComponent.get('system')}.#{@levelComponent.get('name')}" + context.component = @levelComponent context afterRender: -> @@ -28,6 +37,8 @@ module.exports = class LevelComponentEditView extends View @buildSettingsTreema() @buildConfigSchemaTreema() @buildCodeEditor() + @patchesView = @insertSubView(new PatchesView(@levelComponent), @$el.find('.patches-view')) + @$el.find('#component-watch-button').find('> span').toggleClass('secret') if @levelComponent.watching() buildSettingsTreema: -> data = _.pick @levelComponent.attributes, (value, key) => key in @editableSettings @@ -40,7 +51,6 @@ module.exports = class LevelComponentEditView extends View schema: schema data: data callbacks: {change: @onComponentSettingsEdited} - treemaOptions.readOnly = true unless me.isAdmin() @componentSettingsTreema = @$el.find('#edit-component-treema').treema treemaOptions @componentSettingsTreema.build() @componentSettingsTreema.open() @@ -58,7 +68,6 @@ module.exports = class LevelComponentEditView extends View schema: LevelComponent.schema.properties.configSchema data: @levelComponent.get 'configSchema' callbacks: {change: @onConfigSchemaEdited} - treemaOptions.readOnly = true unless me.isAdmin() @configSchemaTreema = @$el.find('#config-schema-treema').treema treemaOptions @configSchemaTreema.build() @configSchemaTreema.open() @@ -70,10 +79,10 @@ module.exports = class LevelComponentEditView extends View Backbone.Mediator.publish 'level-component-edited', levelComponent: @levelComponent buildCodeEditor: -> - editorEl = @$el.find '#component-code-editor' - editorEl.text @levelComponent.get('code') + @editor?.destroy() + editorEl = $('<div></div>').text(@levelComponent.get('code')).addClass('inner-editor') + @$el.find('#component-code-editor').empty().append(editorEl) @editor = ace.edit(editorEl[0]) - @editor.setReadOnly(not me.isAdmin()) session = @editor.getSession() session.setMode 'ace/mode/coffee' session.setTabSize 2 @@ -90,11 +99,21 @@ module.exports = class LevelComponentEditView extends View Backbone.Mediator.publish 'level-component-editing-ended', levelComponent: @levelComponent null + showVersionHistory: (e) -> + versionHistoryView = new VersionHistoryView {}, @levelComponent.id + @openModalView versionHistoryView + Backbone.Mediator.publish 'level:view-switched', e + + startPatchingComponent: (e) -> + @openModalView new SaveVersionModal({model:@levelComponent}) + Backbone.Mediator.publish 'level:view-switched', e + + toggleWatchComponent: -> + button = @$el.find('#component-watch-button') + @levelComponent.watch(button.find('.watch').is(':visible')) + button.find('> span').toggleClass('secret') + destroy: -> @editor?.destroy() super() - showVersionHistory: (e) -> - versionHistoryView = new VersionHistoryView component:@levelComponent, @levelComponent.id - @openModalView versionHistoryView - Backbone.Mediator.publish 'level:view-switched', e \ No newline at end of file diff --git a/app/views/editor/level/components_tab_view.coffee b/app/views/editor/level/components_tab_view.coffee index 823bebed1..0a6ab8518 100644 --- a/app/views/editor/level/components_tab_view.coffee +++ b/app/views/editor/level/components_tab_view.coffee @@ -21,6 +21,7 @@ module.exports = class ComponentsTabView extends View events: 'click #create-new-component-button': 'createNewLevelComponent' + 'click #create-new-component-button-no-select': 'createNewLevelComponent' onLevelThangsChanged: (e) -> thangsData = e.thangsData diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee index dd319e01f..88d50be62 100644 --- a/app/views/editor/level/edit.coffee +++ b/app/views/editor/level/edit.coffee @@ -27,10 +27,18 @@ module.exports = class EditorLevelView extends View 'click #play-button': 'onPlayLevel' 'click #commit-level-start-button': 'startCommittingLevel' 'click #fork-level-start-button': 'startForkingLevel' - 'click #history-button': 'showVersionHistory' + 'click #level-history-button': 'showVersionHistory' 'click #patches-tab': -> @patchesView.load() - 'click #commit-level-patch-button': 'startPatchingLevel' + 'click #level-patch-button': 'startPatchingLevel' + 'click #level-watch-button': 'toggleWatchLevel' + + subscriptions: + 'refresh-level-editor': 'rerenderAllViews' + rerenderAllViews: -> + for view in [@thangsTab, @settingsTab, @scriptsTab, @componentsTab, @systemsTab, @patchesView] + view.render() + constructor: (options, @levelID) -> super options @listenToOnce(@supermodel, 'loaded-all', @onAllLoaded) @@ -93,6 +101,8 @@ module.exports = class EditorLevelView extends View Backbone.Mediator.publish 'level-loaded', level: @level @showReadOnly() if me.get('anonymous') @patchesView = @insertSubView(new PatchesView(@level), @$el.find('.patches-view')) + @listenTo @patchesView, 'accepted-patch', -> setTimeout "location.reload()", 400 + @$el.find('#level-watch-button').find('> span').toggleClass('secret') if @level.watching() onPlayLevel: (e) -> sendLevel = => @@ -124,3 +134,8 @@ module.exports = class EditorLevelView extends View versionHistoryView = new VersionHistoryView level:@level, @levelID @openModalView versionHistoryView Backbone.Mediator.publish 'level:view-switched', e + + toggleWatchLevel: -> + button = @$el.find('#level-watch-button') + @level.watch(button.find('.watch').is(':visible')) + button.find('> span').toggleClass('secret') diff --git a/app/views/editor/level/save_view.coffee b/app/views/editor/level/save_view.coffee index f47b07657..86ba7e96b 100644 --- a/app/views/editor/level/save_view.coffee +++ b/app/views/editor/level/save_view.coffee @@ -30,7 +30,7 @@ module.exports = class LevelSaveView extends SaveVersionModal context afterRender: -> - super() + super(false) changeEls = @$el.find('.changes-stub') models = if @lastContext.levelNeedsSave then [@level] else [] models = models.concat @lastContext.modifiedComponents diff --git a/app/views/editor/level/system/edit.coffee b/app/views/editor/level/system/edit.coffee index 338ede1e5..a7699b316 100644 --- a/app/views/editor/level/system/edit.coffee +++ b/app/views/editor/level/system/edit.coffee @@ -1,6 +1,9 @@ View = 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' module.exports = class LevelSystemEditView extends View id: "editor-level-system-edit-view" @@ -10,6 +13,13 @@ module.exports = class LevelSystemEditView extends View events: 'click #done-editing-system-button': 'endEditing' 'click .nav a': (e) -> $(e.target).tab('show') + 'click #system-patches-tab': -> @patchesView.load() + 'click #system-code-tab': 'buildCodeEditor' + 'click #system-config-schema-tab': 'buildConfigSchemaTreema' + 'click #system-settings-tab': 'buildSettingsTreema' + 'click #system-history-button': 'showVersionHistory' + 'click #patch-system-button': 'startPatchingSystem' + 'click #system-watch-button': 'toggleWatchSystem' constructor: (options) -> super options @@ -26,6 +36,7 @@ module.exports = class LevelSystemEditView extends View @buildSettingsTreema() @buildConfigSchemaTreema() @buildCodeEditor() + @patchesView = @insertSubView(new PatchesView(@levelSystem), @$el.find('.patches-view')) buildSettingsTreema: -> data = _.pick @levelSystem.attributes, (value, key) => key in @editableSettings @@ -68,8 +79,9 @@ module.exports = class LevelSystemEditView extends View Backbone.Mediator.publish 'level-system-edited', levelSystem: @levelSystem buildCodeEditor: -> - editorEl = @$el.find '#system-code-editor' - editorEl.text @levelSystem.get('code') + @editor?.destroy() + editorEl = $('<div></div>').text(@levelSystem.get('code')).addClass('inner-editor') + @$el.find('#system-code-editor').empty().append(editorEl) @editor = ace.edit(editorEl[0]) @editor.setReadOnly(not me.isAdmin()) session = @editor.getSession() @@ -88,6 +100,21 @@ module.exports = class LevelSystemEditView extends View Backbone.Mediator.publish 'level-system-editing-ended', levelSystem: @levelSystem null + showVersionHistory: (e) -> + versionHistoryView = new VersionHistoryView {}, @levelSystem.id + @openModalView versionHistoryView + Backbone.Mediator.publish 'level:view-switched', e + + startPatchingSystem: (e) -> + @openModalView new SaveVersionModal({model:@levelSystem}) + Backbone.Mediator.publish 'level:view-switched', e + + toggleWatchSystem: -> + console.log 'toggle watch system?' + button = @$el.find('#system-watch-button') + @levelSystem.watch(button.find('.watch').is(':visible')) + button.find('> span').toggleClass('secret') + destroy: -> @editor?.destroy() super() diff --git a/app/views/editor/level/systems_tab_view.coffee b/app/views/editor/level/systems_tab_view.coffee index eb4747b0e..e3f4fa626 100644 --- a/app/views/editor/level/systems_tab_view.coffee +++ b/app/views/editor/level/systems_tab_view.coffee @@ -23,6 +23,7 @@ module.exports = class SystemsTabView extends View events: 'click #add-system-button': 'addLevelSystem' 'click #create-new-system-button': 'createNewLevelSystem' + 'click #create-new-system': 'createNewLevelSystem' constructor: (options) -> super options diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee index b4ddc0e0f..d19a93eab 100644 --- a/app/views/editor/level/thangs_tab_view.coffee +++ b/app/views/editor/level/thangs_tab_view.coffee @@ -255,7 +255,7 @@ module.exports = class ThangsTabView extends View # @thangsTreema.deselectAll() selectAddThang: (e) => - return unless $(e.target).closest('.editor-level-thangs-tab-view').length + return unless e? and $(e.target).closest('.editor-level-thangs-tab-view').length if e then target = $(e.target) else target = @$el.find('.add-thangs-palette') # pretend to click on background if no event return true if target.attr('id') is 'surface' target = target.closest('.add-thang-palette-icon') diff --git a/app/views/editor/patch_modal.coffee b/app/views/editor/patch_modal.coffee index 19f3ebfe6..f5dc339cf 100644 --- a/app/views/editor/patch_modal.coffee +++ b/app/views/editor/patch_modal.coffee @@ -7,6 +7,7 @@ module.exports = class PatchModal extends ModalView id: "patch-modal" template: template plain: true + modalWidthPercent: 60 events: 'click #withdraw-button': 'withdrawPatch' @@ -30,12 +31,15 @@ module.exports = class PatchModal extends ModalView c.isPatchCreator = @patch.get('creator') is auth.me.id c.isPatchRecipient = @targetModel.hasWriteAccess() c.status = @patch.get 'status' + c.patch = @patch c afterRender: -> return if @originalSource.loading - headModel = @originalSource.clone(false) - headModel.set(@targetModel.attributes) + headModel = null + if @targetModel.hasWriteAccess() + headModel = @originalSource.clone(false) + headModel.set(@targetModel.attributes) pendingModel = @originalSource.clone(false) pendingModel.applyDelta(@patch.get('delta')) @@ -48,7 +52,8 @@ module.exports = class PatchModal extends ModalView acceptPatch: -> delta = @deltaView.getApplicableDelta() @targetModel.applyDelta(delta) - @targetModel.addPatchToAcceptOnSave(@patch) + @patch.setStatus('accepted') + @trigger 'accepted-patch' @hide() rejectPatch: -> diff --git a/app/views/editor/patches_view.coffee b/app/views/editor/patches_view.coffee index f8dd4fa15..8887b44bb 100644 --- a/app/views/editor/patches_view.coffee +++ b/app/views/editor/patches_view.coffee @@ -44,8 +44,11 @@ module.exports = class PatchesView extends CocoView @$el.find(".#{@status}").addClass 'active' onStatusButtonsChanged: (e) -> - @loaded = false @status = $(e.target).val() + @reloadPatches() + + reloadPatches: -> + @loaded = false @initPatches() @load() @render() @@ -53,4 +56,9 @@ module.exports = class PatchesView extends CocoView openPatchModal: (e) -> patch = _.find @patches.models, {id:$(e.target).data('patch-id')} modal = new PatchModal(patch, @model) - @openModalView(modal) \ No newline at end of file + @openModalView(modal) + @listenTo modal, 'accepted-patch', -> @trigger 'accepted-patch' + @listenTo modal, 'hide', -> + f = => @reloadPatches() + setTimeout(f, 400) + @stopListening modal \ No newline at end of file diff --git a/app/views/editor/system/versions_view.coffee b/app/views/editor/system/versions_view.coffee new file mode 100755 index 000000000..562d134ad --- /dev/null +++ b/app/views/editor/system/versions_view.coffee @@ -0,0 +1,9 @@ +VersionsModalView = require 'views/modal/versions_modal' + +module.exports = class SystemVersionsView extends VersionsModalView + id: "editor-system-versions-view" + url: "/db/level.system/" + page: "system" + + constructor: (options, @ID) -> + super options, ID, require 'models/LevelSystem' \ No newline at end of file diff --git a/app/views/kinds/CocoView.coffee b/app/views/kinds/CocoView.coffee index b368f51ab..5e9275ca3 100644 --- a/app/views/kinds/CocoView.coffee +++ b/app/views/kinds/CocoView.coffee @@ -207,6 +207,7 @@ class CocoView extends Backbone.View # Modals toggleModal: (e) -> + return if visibleModal if $(e.currentTarget).prop('target') is '_blank' return true # special handler for opening modals that are dynamically loaded, rather than static in the page. It works (or should work) like Bootstrap's modals, except use coco-modal for the data-toggle value. diff --git a/app/views/kinds/ModalView.coffee b/app/views/kinds/ModalView.coffee index 2bf6ee8db..26a32081a 100644 --- a/app/views/kinds/ModalView.coffee +++ b/app/views/kinds/ModalView.coffee @@ -45,9 +45,11 @@ module.exports = class ModalView extends CocoView super($el) hide: -> + @trigger 'hide' @$el.removeClass('fade').modal "hide" onHidden: -> + @trigger 'hidden' destroy: -> @hide() unless @hidden diff --git a/app/views/modal/save_version_modal.coffee b/app/views/modal/save_version_modal.coffee index 6533a741f..d95fc4166 100644 --- a/app/views/modal/save_version_modal.coffee +++ b/app/views/modal/save_version_modal.coffee @@ -8,6 +8,7 @@ module.exports = class SaveVersionModal extends ModalView id: 'save-version-modal' template: template plain: true + modalWidthPercent: 60 events: 'click #save-version-button': 'onClickSaveButton' @@ -26,15 +27,16 @@ module.exports = class SaveVersionModal extends ModalView c.hasChanges = @model.hasLocalChanges() c - afterRender: -> + afterRender: (insertDeltaView=true) -> super() @$el.find(if me.get('signedCLA') then '#accept-cla-wrapper' else '#save-version-button').hide() changeEl = @$el.find('.changes-stub') - try - deltaView = new DeltaView({model:@model}) - @insertSubView(deltaView, changeEl) - catch e - console.error "Couldn't create delta view:", e + if insertDeltaView + try + deltaView = new DeltaView({model:@model}) + @insertSubView(deltaView, changeEl) + catch e + console.error "Couldn't create delta view:", e @$el.find('.commit-message input').attr('placeholder', $.i18n.t('general.commit_msg')) onClickSaveButton: -> @@ -54,6 +56,7 @@ module.exports = class SaveVersionModal extends ModalView } errors = patch.validate() forms.applyErrorsToForm(@$el, errors) if errors + patch.set 'editPath', document.location.pathname res = patch.save() return unless res @enableModalInProgress(@$el) diff --git a/app/views/modal/versions_modal.coffee b/app/views/modal/versions_modal.coffee index 97aeafb33..6bf511396 100755 --- a/app/views/modal/versions_modal.coffee +++ b/app/views/modal/versions_modal.coffee @@ -13,6 +13,8 @@ class VersionsViewCollection extends Backbone.Collection module.exports = class VersionsModalView extends ModalView template: template startsLoading: true + plain: true + modalWidthPercent: 80 # needs to be overwritten by child id: "" diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee index b486b79b0..aed496fd8 100644 --- a/server/commons/Handler.coffee +++ b/server/commons/Handler.coffee @@ -4,6 +4,8 @@ Grid = require 'gridfs-stream' errors = require './errors' log = require 'winston' Patch = require '../patches/Patch' +User = require '../users/User' +sendwithus = require '../sendwithus' PROJECT = {original:1, name:1, version:1, description: 1, slug:1, kind: 1} FETCH_LIMIT = 200 @@ -95,7 +97,7 @@ module.exports = class Handler # this handler should be overwritten by subclasses if @modelClass.schema.is_patchable return @getPatchesFor(req, res, args[0]) if req.route.method is 'get' and args[1] is 'patches' - return @setListening(req, res, args[0]) if req.route.method is 'put' and args[1] is 'listen' + return @setWatching(req, res, args[0]) if req.route.method is 'put' and args[1] is 'watch' return @sendNotFoundError(res) getPatchesFor: (req, res, id) -> @@ -105,16 +107,16 @@ module.exports = class Handler patches = (patch.toObject() for patch in patches) @sendSuccess(res, patches) - setListening: (req, res, id) -> + setWatching: (req, res, id) -> @getDocumentForIdOrSlug id, (err, document) => return @sendUnauthorizedError(res) unless @hasAccessToDocument(req, document, 'get') return @sendDatabaseError(res, err) if err return @sendNotFoundError(res) unless document? - listeners = document.get('listeners') or [] + watchers = document.get('watchers') or [] me = req.user.get('_id') - listeners = (l for l in listeners when not l.equals(me)) - listeners.push me if req.body.on - document.set 'listeners', listeners + watchers = (l for l in watchers when not l.equals(me)) + watchers.push me if req.body.on and req.body.on isnt 'false' + document.set 'watchers', watchers document.save (err, document) => return @sendDatabaseError(res, err) if err @sendSuccess(res, @formatEntity(req, document)) @@ -233,6 +235,9 @@ module.exports = class Handler return @sendBadInputError(res, err.errors) if err?.valid is false return @sendDatabaseError(res, err) if err @sendSuccess(res, @formatEntity(req, document)) + @onPostSuccess(req, document) + + onPostSuccess: (req, doc) -> ### TODO: think about pulling some common stuff out of postFirstVersion/postNewVersion @@ -248,7 +253,6 @@ module.exports = class Handler document.set('original', document._id) document.set('creator', req.user._id) @saveChangesToDocument req, document, (err) => - console.log 'saved new version', document.toObject() return @sendBadInputError(res, err.errors) if err?.valid is false return @sendDatabaseError(res, err) if err @sendSuccess(res, @formatEntity(req, document)) @@ -291,6 +295,7 @@ module.exports = class Handler newDocument.save (err) => return @sendDatabaseError(res, err) if err @sendSuccess(res, @formatEntity(req, newDocument)) + @notifyWatchersOfChange(req.user, newDocument, req.body.editPath) if @modelClass.schema.is_patchable if major? parentDocument.makeNewMinorVersion(updatedObject, major, done) @@ -298,8 +303,31 @@ module.exports = class Handler else parentDocument.makeNewMajorVersion(updatedObject, done) + notifyWatchersOfChange: (editor, changedDocument, editPath) -> + watchers = changedDocument.get('watchers') or [] + watchers = (w for w in watchers when not w.equals(editor.get('_id'))) + return unless watchers.length + User.find({_id:{$in:watchers}}).select({email:1, name:1}).exec (err, watchers) => + for watcher in watchers + @notifyWatcherOfChange editor, watcher, changedDocument, editPath + + notifyWatcherOfChange: (editor, watcher, changedDocument, editPath) -> + context = + email_id: sendwithus.templates.change_made_notify_watcher + recipient: + address: watcher.get('email') + name: watcher.get('name') + email_data: + doc_name: changedDocument.get('name') or '???' + submitter_name: editor.get('name') or '???' + doc_link: if editPath then "http://codecombat.com#{editPath}" else null + commit_message: changedDocument.get('commitMessage') + sendwithus.api.send context, (err, result) -> + makeNewInstance: (req) -> - new @modelClass({}) + model = new @modelClass({}) + model.set 'watchers', [req.user.get('_id')] if @modelClass.schema.is_patchable + model validateDocumentInput: (input) -> tv4 = require('tv4').tv4 diff --git a/server/patches/Patch.coffee b/server/patches/Patch.coffee index df621f2a4..3e12638cf 100644 --- a/server/patches/Patch.coffee +++ b/server/patches/Patch.coffee @@ -39,8 +39,10 @@ PatchSchema.pre 'save', (next) -> target.original = targetID patches = document.get('patches') or [] + patches = _.clone patches patches.push @_id - document.set 'patches', patches + document.set 'patches', patches, {strict: false} + @targetLoaded = document document.save (err) -> next(err) module.exports = mongoose.model('patch', PatchSchema) diff --git a/server/patches/patch_handler.coffee b/server/patches/patch_handler.coffee index 12a68ed9a..4e134d73d 100644 --- a/server/patches/patch_handler.coffee +++ b/server/patches/patch_handler.coffee @@ -1,8 +1,11 @@ Patch = require('./Patch') +User = require '../users/User' Handler = require('../commons/Handler') schema = require '../../app/schemas/models/patch' {handlers} = require '../commons/mapping' mongoose = require('mongoose') +log = require 'winston' +sendwithus = require '../sendwithus' PatchHandler = class PatchHandler extends Handler modelClass: Patch @@ -50,6 +53,29 @@ PatchHandler = class PatchHandler extends Handler patch.update {$set:{status:newStatus}}, {}, -> target.update {$pull:{patches:patch.get('_id')}}, {}, -> @sendSuccess(res, null) + + onPostSuccess: (req, doc) -> + log.error "Error sending patch created: could not find the loaded target on the patch object." unless doc.targetLoaded + return unless doc.targetLoaded + watchers = doc.targetLoaded.get('watchers') or [] + watchers = (w for w in watchers when not w.equals(editor.get('_id'))) + return unless watchers?.length + User.find({_id:{$in:watchers}}).select({email:1, name:1}).exec (err, watchers) => + for watcher in watchers + @sendPatchCreatedEmail req.user, watcher, doc, doc.targetLoaded, req.body.editPath + sendPatchCreatedEmail: (patchCreator, watcher, patch, target, editPath) -> +# return if watcher._id is patchCreator._id + context = + email_id: sendwithus.templates.patch_created + recipient: + address: watcher.get('email') + name: watcher.get('name') + email_data: + doc_name: target.get('name') or '???' + submitter_name: patchCreator.get('name') or '???' + doc_link: "http://codecombat.com#{editPath}" + commit_message: patch.get('commitMessage') + sendwithus.api.send context, (err, result) -> module.exports = new PatchHandler() diff --git a/server/sendwithus.coffee b/server/sendwithus.coffee index bda58d896..04d8205c3 100644 --- a/server/sendwithus.coffee +++ b/server/sendwithus.coffee @@ -14,3 +14,5 @@ if config.unittest module.exports.templates = welcome_email: 'utnGaBHuSU4Hmsi7qrAypU' ladder_update_email: 'JzaZxf39A4cKMxpPZUfWy4' + patch_created: 'tem_xhxuNosLALsizTNojBjNcL' + change_made_notify_watcher: 'tem_7KVkfmv9SZETb25dtHbUtG' diff --git a/test/server/common.coffee b/test/server/common.coffee index e68c27b72..80aa6e47e 100644 --- a/test/server/common.coffee +++ b/test/server/common.coffee @@ -64,13 +64,13 @@ GLOBAL.unittest = {} unittest.users = unittest.users or {} unittest.getNormalJoe = (done, force) -> - unittest.getUser('normal@jo.com', 'food', done, force) + unittest.getUser('Joe', 'normal@jo.com', 'food', done, force) unittest.getOtherSam = (done, force) -> - unittest.getUser('other@sam.com', 'beer', done, force) + unittest.getUser('Sam', 'other@sam.com', 'beer', done, force) unittest.getAdmin = (done, force) -> - unittest.getUser('admin@afc.com', '80yqxpb38j', done, force) + unittest.getUser('Admin', 'admin@afc.com', '80yqxpb38j', done, force) -unittest.getUser = (email, password, done, force) -> +unittest.getUser = (name, email, password, done, force) -> # Creates the user if it doesn't already exist. return done(unittest.users[email]) if unittest.users[email] and not force @@ -81,6 +81,7 @@ unittest.getUser = (email, password, done, force) -> throw err if err User.findOne({email:email}).exec((err, user) -> user.set('permissions', if password is '80yqxpb38j' then [ 'admin' ] else []) + user.set('name', name) user.save (err) -> wrapUpGetUser(email, user, done) ) @@ -88,7 +89,6 @@ unittest.getUser = (email, password, done, force) -> form = req.form() form.append('email', email) form.append('password', password) - wrapUpGetUser = (email, user, done) -> unittest.users[email] = user diff --git a/test/server/functional/patch.spec.coffee b/test/server/functional/patch.spec.coffee index d8694baf0..9d0f4265d 100644 --- a/test/server/functional/patch.spec.coffee +++ b/test/server/functional/patch.spec.coffee @@ -16,13 +16,14 @@ describe '/db/patch', -> patch = commitMessage: 'Accept this patch!' delta: {name:['test']} + editPath: '/who/knows/yes' target: id:null collection: 'article' it 'creates an Article to patch', (done) -> loginAdmin -> - request.post {uri:articleURL, json:patch}, (err, res, body) -> + request.post {uri:articleURL, json:article}, (err, res, body) -> articles[0] = body patch.target.id = articles[0]._id done() @@ -51,29 +52,29 @@ describe '/db/patch', -> body = JSON.parse(body) expect(res.statusCode).toBe(200) expect(body.length).toBe(1) - done() + done() - it 'allows you to set yourself as listening', (done) -> - listeningURL = getURL("/db/article/#{articles[0]._id}/listen") - request.put {uri: listeningURL, json: {on:true}}, (err, res, body) -> - expect(body.listeners[0]).toBeDefined() + it 'allows you to set yourself as watching', (done) -> + watchingURL = getURL("/db/article/#{articles[0]._id}/watch") + request.put {uri: watchingURL, json: {on:true}}, (err, res, body) -> + expect(body.watchers[1]).toBeDefined() done() - it 'added the listener to the target document', (done) -> + it 'added the watcher to the target document', (done) -> Article.findOne({}).exec (err, article) -> - expect(article.toObject().listeners[0]).toBeDefined() + expect(article.toObject().watchers[1]).toBeDefined() done() - it 'does not add duplicate listeners', (done) -> - listeningURL = getURL("/db/article/#{articles[0]._id}/listen") - request.put {uri: listeningURL, json: {on:true}}, (err, res, body) -> - expect(body.listeners.length).toBe(1) + it 'does not add duplicate watchers', (done) -> + watchingURL = getURL("/db/article/#{articles[0]._id}/watch") + request.put {uri: watchingURL, json: {on:true}}, (err, res, body) -> + expect(body.watchers.length).toBe(2) done() it 'allows removing yourself', (done) -> - listeningURL = getURL("/db/article/#{articles[0]._id}/listen") - request.put {uri: listeningURL, json: {on:false}}, (err, res, body) -> - expect(body.listeners.length).toBe(0) + watchingURL = getURL("/db/article/#{articles[0]._id}/watch") + request.put {uri: watchingURL, json: {on:false}}, (err, res, body) -> + expect(body.watchers.length).toBe(1) done() it 'allows the submitter to withdraw the pull request', (done) -> diff --git a/test/server/functional/user.spec.coffee b/test/server/functional/user.spec.coffee index 29e1360a9..0ee2ff364 100644 --- a/test/server/functional/user.spec.coffee +++ b/test/server/functional/user.spec.coffee @@ -112,7 +112,7 @@ ghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghlfarghlarghl unittest.getNormalJoe (joe) -> req = request.put getURL(urlUser), (err, res) -> expect(res.statusCode).toBe(200) - unittest.getUser('New@email.com', 'null', (joe) -> + unittest.getUser('Wilhelm', 'New@email.com', 'null', (joe) -> expect(joe.get('name')).toBe('Wilhelm') expect(joe.get('emailLower')).toBe('new@email.com') expect(joe.get('email')).toBe('New@email.com')