From 58b10199348fdf9b03e1820355824e8ba56da3e7 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Tue, 15 Apr 2014 15:09:36 -0700
Subject: [PATCH 01/17] Switched listen to watch (would have been confusing
 with eye-con, and listenTo function in Backbone). Added watch button and
 patch badge to level editor.

---
 app/locale/en.coffee                     |  2 ++
 app/models/CocoModel.coffee              |  6 ++++++
 app/schemas/schemas.coffee               |  2 +-
 app/styles/base.sass                     |  5 +++++
 app/templates/editor/level/edit.jade     | 15 ++++++++++++--
 app/views/editor/level/edit.coffee       |  6 ++++++
 server/commons/Handler.coffee            | 15 ++++++++------
 test/server/functional/patch.spec.coffee | 26 ++++++++++++------------
 8 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 9cd29d8d2..5229e180c 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -15,6 +15,8 @@
     fork: "Fork"
     play: "Play"
     retry: "Retry"
+    watch: "Watch"
+    unwatch: "Unwatch"
 
   units:
     second: "second"
diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index c93708ee2..a99f48fd4 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -225,5 +225,11 @@ class CocoModel extends Backbone.Model
     @acceptedPatches ?= []
     @acceptedPatches.push patch
     @acceptedPatches = _.uniq(@acceptedPatches, false, (p) -> p.id)
+    
+  watch: (doWatch=true) ->
+    $.ajax("#{@urlRoot}/#{@id}/watch", {type:'PUT', data:{on:doWatch}})
+    
+  watching: ->
+    return me.id in @get('watchers') or []
 
 module.exports = CocoModel
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/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index ba69b27fd..873d881b4 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -27,10 +27,21 @@ block outer_content
             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
-
+              a(href="#editor-level-patches", data-toggle="tab")#patches-tab
+                span(data-i18n="resources.patches").spr Patches
+                - var patches = level.get('patches')
+                - patches = [1,2,3,3,4,5,6]
+                if patches && patches.length
+                  span.badge= patches.length
 
           ul.nav.navbar-nav.navbar-right
+            li#watch-button.btn.btn-primary.navbar-btn
+              span.watch
+                span.spr Watch
+                span.glyphicon.glyphicon-eye-open
+              span.unwatch.secret
+                span.spr Unwatch
+                span.glyphicon.glyphicon-eye-close
             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
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index e28f87247..ee704c10e 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -30,6 +30,7 @@ module.exports = class EditorLevelView extends View
     'click #history-button': 'showVersionHistory'
     'click #patches-tab': -> @patchesView.load()
     'click #commit-level-patch-button': 'startPatchingLevel'
+    'click #watch-button': 'toggleWatchLevel'
 
   constructor: (options, @levelID) ->
     super options
@@ -125,3 +126,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('#watch-button')
+    @level.watch(button.find('.watch').is(':visible'))
+    button.find('> span').toggleClass('secret')
\ No newline at end of file
diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee
index b486b79b0..a7822f9e5 100644
--- a/server/commons/Handler.coffee
+++ b/server/commons/Handler.coffee
@@ -95,7 +95,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 +105,19 @@ 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
+      console.log 'watchers?', me, watchers
+      watchers = (l for l in watchers when not l.equals(me))
+      console.log 'new watchers is', watchers, req.body.on, req.body
+      watchers.push me if req.body.on and req.body.on isnt 'false'
+      console.log 'watchers is actually now', watchers
+      document.set 'watchers', watchers
       document.save (err, document) =>
         return @sendDatabaseError(res, err) if err
         @sendSuccess(res, @formatEntity(req, document))
diff --git a/test/server/functional/patch.spec.coffee b/test/server/functional/patch.spec.coffee
index d8694baf0..4666c5353 100644
--- a/test/server/functional/patch.spec.coffee
+++ b/test/server/functional/patch.spec.coffee
@@ -53,27 +53,27 @@ describe '/db/patch', ->
       expect(body.length).toBe(1)
       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[0]).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[0]).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(1)
       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(0)
       done()
       
   it 'allows the submitter to withdraw the pull request', (done) ->

From f88e0ac0abd0024e595154568c8060b3fb833138 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Wed, 16 Apr 2014 10:42:32 -0700
Subject: [PATCH 02/17] Set up patches for components.

---
 app/models/CocoModel.coffee                    | 11 ++++++-----
 app/models/Patch.coffee                        |  5 ++++-
 app/styles/editor/level/component/edit.sass    |  7 +++++++
 app/templates/editor/level/component/edit.jade |  6 +++++-
 app/templates/editor/level/edit.jade           |  3 +--
 app/views/editor/level/component/edit.coffee   | 13 ++++++++++---
 app/views/editor/level/save_view.coffee        |  2 +-
 app/views/editor/level/thangs_tab_view.coffee  |  2 +-
 app/views/modal/save_version_modal.coffee      | 13 +++++++------
 9 files changed, 42 insertions(+), 20 deletions(-)

diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index a99f48fd4..838b30530 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -68,7 +68,8 @@ class CocoModel extends Backbone.Model
       @markToRevert()
       @clearBackup()
     @trigger "save", @
-    patch.setStatus 'accepted' for patch in @acceptedPatches or []
+    PatchModel = require 'models/Patch'
+    PatchModel.setStatus id, 'accepted' for id in @get('acceptedPatches') or []
     return super attrs, options
 
   fetch: ->
@@ -95,7 +96,6 @@ class CocoModel extends Backbone.Model
   cloneNewMinorVersion: ->
     newData = $.extend(null, {}, @attributes)
     clone = new @constructor(newData)
-    clone.acceptedPatches = @acceptedPatches
     clone
 
   cloneNewMajorVersion: ->
@@ -222,9 +222,10 @@ class CocoModel extends Backbone.Model
     deltasLib.expandDelta(delta, @_revertAttributes, @schema())
 
   addPatchToAcceptOnSave: (patch) ->
-    @acceptedPatches ?= []
-    @acceptedPatches.push patch
-    @acceptedPatches = _.uniq(@acceptedPatches, false, (p) -> p.id)
+    acceptedPatches = @get('acceptedPatches') or [] # not actually stored on the db
+    acceptedPatches.push patch.id
+    acceptedPatches = _.uniq(acceptedPatches)
+    @set 'acceptedPatches', acceptedPatches
     
   watch: (doWatch=true) ->
     $.ajax("#{@urlRoot}/#{@id}/watch", {type:'PUT', data:{on:doWatch}})
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/styles/editor/level/component/edit.sass b/app/styles/editor/level/component/edit.sass
index 5c9deda4c..2cd8e5d4f 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
     
diff --git a/app/templates/editor/level/component/edit.jade b/app/templates/editor/level/component/edit.jade
index 23c24cf6c..1a6d74d38 100644
--- a/app/templates/editor/level/component/edit.jade
+++ b/app/templates/editor/level/component/edit.jade
@@ -14,10 +14,12 @@ nav.navbar.navbar-default(role='navigation')
           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
+        li
+          a(href="#component-patches" data-toggle="tab" data-i18n="resources.patches")#component-patches-tab Patches
       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
+        li.btn.btn-primary.navbar-btn#patch-component-button Patch
 
 .tab-content
   .tab-pane.active#component-code
@@ -26,3 +28,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/edit.jade b/app/templates/editor/level/edit.jade
index 873d881b4..297d000f8 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -30,7 +30,6 @@ block outer_content
               a(href="#editor-level-patches", data-toggle="tab")#patches-tab
                 span(data-i18n="resources.patches").spr Patches
                 - var patches = level.get('patches')
-                - patches = [1,2,3,3,4,5,6]
                 if patches && patches.length
                   span.badge= patches.length
 
@@ -42,7 +41,7 @@ block outer_content
               span.unwatch.secret
                 span.spr Unwatch
                 span.glyphicon.glyphicon-eye-close
-            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
+            li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=anonymous ? "true": undefined).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
diff --git a/app/views/editor/level/component/edit.coffee b/app/views/editor/level/component/edit.coffee
index 3f91f1467..caf2340e5 100644
--- a/app/views/editor/level/component/edit.coffee
+++ b/app/views/editor/level/component/edit.coffee
@@ -2,6 +2,8 @@ View = require 'views/kinds/CocoView'
 VersionHistoryView = require 'views/editor/component/versions_view'
 template = require 'templates/editor/level/component/edit'
 LevelComponent = require 'models/LevelComponent'
+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"
@@ -12,6 +14,8 @@ module.exports = class LevelComponentEditView extends View
     '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 #patch-component-button': 'startPatchingComponent'
 
   constructor: (options) ->
     super options
@@ -21,6 +25,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 +33,7 @@ module.exports = class LevelComponentEditView extends View
     @buildSettingsTreema()
     @buildConfigSchemaTreema()
     @buildCodeEditor()
+    @patchesView = @insertSubView(new PatchesView(@levelComponent), @$el.find('.patches-view'))
 
   buildSettingsTreema: ->
     data = _.pick @levelComponent.attributes, (value, key) => key in @editableSettings
@@ -40,7 +46,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 +63,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()
@@ -73,7 +77,6 @@ module.exports = class LevelComponentEditView extends View
     editorEl = @$el.find '#component-code-editor'
     editorEl.text @levelComponent.get('code')
     @editor = ace.edit(editorEl[0])
-    @editor.setReadOnly(not me.isAdmin())
     session = @editor.getSession()
     session.setMode 'ace/mode/coffee'
     session.setTabSize 2
@@ -97,4 +100,8 @@ module.exports = class LevelComponentEditView extends View
   showVersionHistory: (e) ->
     versionHistoryView = new VersionHistoryView component:@levelComponent, @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
\ No newline at end of file
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/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee
index 5c5ca8dbd..3e0ed6583 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 (not e) or $(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/modal/save_version_modal.coffee b/app/views/modal/save_version_modal.coffee
index fda6b3951..d06aef707 100644
--- a/app/views/modal/save_version_modal.coffee
+++ b/app/views/modal/save_version_modal.coffee
@@ -27,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: ->

From 02a7381fa9bb71c7fcf230166aa1f5b9bb018117 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Wed, 16 Apr 2014 11:02:40 -0700
Subject: [PATCH 03/17] Fixed the watch buttons for levels and components.

---
 app/models/CocoModel.coffee                   |   3 +-
 .../editor/level/component/edit.jade          |   7 +
 app/templates/editor/level/edit.jade          | 156 +++++++++---------
 app/views/editor/level/component/edit.coffee  |  18 +-
 app/views/editor/level/edit.coffee            |   1 +
 server/commons/Handler.coffee                 |   3 -
 6 files changed, 105 insertions(+), 83 deletions(-)

diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index 838b30530..6ccfae775 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -229,8 +229,9 @@ class CocoModel extends Backbone.Model
     
   watch: (doWatch=true) ->
     $.ajax("#{@urlRoot}/#{@id}/watch", {type:'PUT', data:{on:doWatch}})
+    @watching = -> doWatch
     
   watching: ->
-    return me.id in @get('watchers') or []
+    return me.id in (@get('watchers') or [])
 
 module.exports = CocoModel
diff --git a/app/templates/editor/level/component/edit.jade b/app/templates/editor/level/component/edit.jade
index 1a6d74d38..843ef6b15 100644
--- a/app/templates/editor/level/component/edit.jade
+++ b/app/templates/editor/level/component/edit.jade
@@ -20,6 +20,13 @@ nav.navbar.navbar-default(role='navigation')
         li(data-i18n="general.version_history").btn.btn-primary.navbar-btn#history-button Version History
         li(data-i18n="editor.level_component_btn_new").btn.btn-primary.navbar-btn#create-new-component-button Create New Component
         li.btn.btn-primary.navbar-btn#patch-component-button Patch
+        li#watch-component-button.btn.btn-primary.navbar-btn
+          span.watch
+            span.spr Watch
+            span.glyphicon.glyphicon-eye-open
+          span.unwatch.secret
+            span.spr Unwatch
+            span.glyphicon.glyphicon-eye-close
 
 .tab-content
   .tab-pane.active#component-code
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index 297d000f8..ff7ecf3e8 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -2,82 +2,90 @@ extends /templates/base
 
 block outer_content
   .outer-content
-
-    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
+    
+    if level.loading
+      nav.navbar.navbar-default(role='navigation')#level-editor-top-nav
+        .container-fluid
+          ul.nav.navbar-nav
             li
-              a(href="#editor-level-scripts-tab-view", data-toggle="tab", data-i18n="editor.level_tab_scripts") Scripts
+              a(href="/editor/level", data-i18n="editor.back") Back
+    
+    else
+      nav.navbar.navbar-default(role='navigation')#level-editor-top-nav
+        .container-fluid
+          ul.nav.navbar-nav
             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
-
-          ul.nav.navbar-nav.navbar-right
-            li#watch-button.btn.btn-primary.navbar-btn
-              span.watch
-                span.spr Watch
-                span.glyphicon.glyphicon-eye-open
-              span.unwatch.secret
-                span.spr Unwatch
-                span.glyphicon.glyphicon-eye-close
-            li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=anonymous ? "true": undefined).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", 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")#patches-tab
+                  span(data-i18n="resources.patches").spr Patches
+                  - var patches = level.get('patches')
+                  if patches && patches.length
+                    span.badge= patches.length
+  
+            ul.nav.navbar-nav.navbar-right
+              li#watch-button.btn.btn-primary.navbar-btn
+                span.watch
+                  span.spr Watch
+                  span.glyphicon.glyphicon-eye-open
+                span.unwatch.secret
+                  span.spr Unwatch
+                  span.glyphicon.glyphicon-eye-close
+              li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=anonymous ? "true": undefined).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
   
     div.tab-content#level-editor-tabs
       div.tab-pane.active#editor-level-thangs-tab-view
diff --git a/app/views/editor/level/component/edit.coffee b/app/views/editor/level/component/edit.coffee
index caf2340e5..fa2f3609f 100644
--- a/app/views/editor/level/component/edit.coffee
+++ b/app/views/editor/level/component/edit.coffee
@@ -16,6 +16,7 @@ module.exports = class LevelComponentEditView extends View
     'click .nav a': (e) -> $(e.target).tab('show')
     'click #component-patches-tab': -> @patchesView.load()
     'click #patch-component-button': 'startPatchingComponent'
+    'click #watch-component-button': 'toggleWatchComponent'
 
   constructor: (options) ->
     super options
@@ -34,6 +35,7 @@ module.exports = class LevelComponentEditView extends View
     @buildConfigSchemaTreema()
     @buildCodeEditor()
     @patchesView = @insertSubView(new PatchesView(@levelComponent), @$el.find('.patches-view'))
+    @$el.find('#watch-component-button').find('> span').toggleClass('secret') if @levelComponent.watching()
 
   buildSettingsTreema: ->
     data = _.pick @levelComponent.attributes, (value, key) => key in @editableSettings
@@ -93,10 +95,6 @@ module.exports = class LevelComponentEditView extends View
     Backbone.Mediator.publish 'level-component-editing-ended', levelComponent: @levelComponent
     null
 
-  destroy: ->
-    @editor?.destroy()
-    super()
-
   showVersionHistory: (e) ->
     versionHistoryView = new VersionHistoryView component:@levelComponent, @levelComponent.id
     @openModalView versionHistoryView
@@ -104,4 +102,14 @@ module.exports = class LevelComponentEditView extends View
     
   startPatchingComponent: (e) ->
     @openModalView new SaveVersionModal({model:@levelComponent})
-    Backbone.Mediator.publish 'level:view-switched', e
\ No newline at end of file
+    Backbone.Mediator.publish 'level:view-switched', e
+
+  toggleWatchComponent: ->
+    button = @$el.find('#watch-component-button')
+    @levelComponent.watch(button.find('.watch').is(':visible'))
+    button.find('> span').toggleClass('secret')
+
+  destroy: ->
+    @editor?.destroy()
+    super()
+
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index a97f59be6..26808a742 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -94,6 +94,7 @@ 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'))
+    @$el.find('#watch-button').find('> span').toggleClass('secret') if @level.watching()
 
   onPlayLevel: (e) ->
     sendLevel = =>
diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee
index a7822f9e5..99c28e71c 100644
--- a/server/commons/Handler.coffee
+++ b/server/commons/Handler.coffee
@@ -112,11 +112,8 @@ module.exports = class Handler
       return @sendNotFoundError(res) unless document?
       watchers = document.get('watchers') or []
       me = req.user.get('_id')
-      console.log 'watchers?', me, watchers
       watchers = (l for l in watchers when not l.equals(me))
-      console.log 'new watchers is', watchers, req.body.on, req.body
       watchers.push me if req.body.on and req.body.on isnt 'false'
-      console.log 'watchers is actually now', watchers
       document.set 'watchers', watchers
       document.save (err, document) =>
         return @sendDatabaseError(res, err) if err

From 8859405e182bb6b34d07085945b7abd42e97b2a4 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 11:02:00 -0700
Subject: [PATCH 04/17] Reworked the nav bars in the level editor.

---
 app/locale/en.coffee                          |   1 +
 app/styles/editor/level/component/edit.sass   |   7 +-
 app/styles/editor/level/components_tab.sass   |   8 +-
 app/styles/editor/level/edit.sass             |  46 ++++--
 app/styles/editor/level/system/edit.sass      |   5 +-
 app/styles/editor/level/systems_tab.sass      |   6 +-
 .../editor/level/component/edit.jade          |  68 +++++----
 .../editor/level/components_tab.jade          |   2 +-
 app/templates/editor/level/edit.jade          | 144 +++++++++---------
 app/templates/editor/level/system/edit.jade   |  51 ++++---
 .../editor/level/components_tab_view.coffee   |   1 +
 .../editor/level/systems_tab_view.coffee      |   1 +
 12 files changed, 198 insertions(+), 142 deletions(-)

diff --git a/app/locale/en.coffee b/app/locale/en.coffee
index 335d9887f..83bb2e67f 100644
--- a/app/locale/en.coffee
+++ b/app/locale/en.coffee
@@ -17,6 +17,7 @@
     retry: "Retry"
     watch: "Watch"
     unwatch: "Unwatch"
+    submit_patch: "Submit Patch"
 
   units:
     second: "second"
diff --git a/app/styles/editor/level/component/edit.sass b/app/styles/editor/level/component/edit.sass
index 2cd8e5d4f..beca326ff 100644
--- a/app/styles/editor/level/component/edit.sass
+++ b/app/styles/editor/level/component/edit.sass
@@ -14,9 +14,6 @@
     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
+    border-top: none
\ 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..339b199c2 100644
--- a/app/styles/editor/level/edit.sass
+++ b/app/styles/editor/level/edit.sass
@@ -4,7 +4,7 @@
   
   #top-nav
     display: none
-
+    
   position: absolute
   top: 0px
   left: 0px
@@ -12,17 +12,45 @@
   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
+    &: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
 
   .outer-content
     background-color: $BG
@@ -47,7 +75,7 @@
     position: absolute
     left: 20px
     right: 20px
-    top: 66px
+    top: 46px
     bottom: 20px
     
   .treema-root
diff --git a/app/styles/editor/level/system/edit.sass b/app/styles/editor/level/system/edit.sass
index e86dc5a46..e648e3e64 100644
--- a/app/styles/editor/level/system/edit.sass
+++ b/app/styles/editor/level/system/edit.sass
@@ -7,9 +7,6 @@
     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
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/templates/editor/level/component/edit.jade b/app/templates/editor/level/component/edit.jade
index 843ef6b15..74d90e625 100644
--- a/app/templates/editor/level/component/edit.jade
+++ b/app/templates/editor/level/component/edit.jade
@@ -1,32 +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
-        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
-        li
-          a(href="#component-patches" data-toggle="tab" data-i18n="resources.patches")#component-patches-tab Patches
-      ul.nav.navbar-nav.navbar-left
-        li(data-i18n="general.version_history").btn.btn-primary.navbar-btn#history-button Version History
-        li(data-i18n="editor.level_component_btn_new").btn.btn-primary.navbar-btn#create-new-component-button Create New Component
-        li.btn.btn-primary.navbar-btn#patch-component-button Patch
-        li#watch-component-button.btn.btn-primary.navbar-btn
-          span.watch
-            span.spr Watch
-            span.glyphicon.glyphicon-eye-open
-          span.unwatch.secret
-            span.spr Unwatch
-            span.glyphicon.glyphicon-eye-close
+  ul.nav.navbar-nav.nav-tabs
+    li.active
+      a(href="#component-code" data-toggle="tab" data-i18n="general.code") Code
+    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
+    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#watch-component-button
+          a
+            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#history-button
+          a(data-i18n="general.version_history") Version History
 
 .tab-content
   .tab-pane.active#component-code
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 ff7ecf3e8..5c21fb45e 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -3,90 +3,88 @@ extends /templates/base
 block outer_content
   .outer-content
     
-    if level.loading
+    if false
       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
+              a(href="/editor/level")
+                span.glyphicon-home.glyphicon
     
     else
       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")#patches-tab
-                  span(data-i18n="resources.patches").spr Patches
-                  - var patches = level.get('patches')
-                  if patches && patches.length
-                    span.badge= patches.length
-  
-            ul.nav.navbar-nav.navbar-right
-              li#watch-button.btn.btn-primary.navbar-btn
-                span.watch
-                  span.spr Watch
-                  span.glyphicon.glyphicon-eye-open
-                span.unwatch.secret
-                  span.spr Unwatch
-                  span.glyphicon.glyphicon-eye-close
-              li(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert", disabled=anonymous ? "true": undefined).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.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
+              a
+                span.glyphicon-floppy-disk.glyphicon
+          else
+            li
+              a
+                span.glyphicon-floppy-disk.glyphicon
+          
+          li(title="⌃↩ or ⌘↩: Play preview of current level")
+            a
+              span.glyphicon-play.glyphicon
+          li.dropdown
+            a(data-toggle='dropdown')
+              span.glyphicon-chevron-down.glyphicon
             ul.dropdown-menu
-              li
-                span(data-i18n="editor.level_some_options").dropdown-menu-header Some Options?
+              li.dropdown-header Actions
+              li#watch-button
+                a
+                  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#history-button
+                a(href='#', data-i18n="general.version_history") Version History
+              li.divider
+              li.dropdown-header Help
               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='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
+
     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..d1aed8a93 100644
--- a/app/templates/editor/level/system/edit.jade
+++ b/app/templates/editor/level/system/edit.jade
@@ -1,21 +1,38 @@
 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
-        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
+
+  ul.nav.navbar-nav.nav-tabs
+    li.active
+      a(href="#system-code" data-toggle="tab") Code
+    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.dropdown
+      a(data-toggle='dropdown')
+        span.glyphicon-chevron-down.glyphicon
+      ul.dropdown-menu
+        li.dropdown-header Actions
+        li#watch-component-button
+          a
+            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-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
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/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

From 8a2b762446d7747caa8c235fc9d50171df0b7d94 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 11:12:09 -0700
Subject: [PATCH 05/17] Fixed a bug where opening a modal by data attributes
 would sometimes open it multiple times.

---
 app/views/kinds/CocoView.coffee | 1 +
 1 file changed, 1 insertion(+)

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.

From 4c1143f026ead682daa6592538195ef5c6298641 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 11:22:33 -0700
Subject: [PATCH 06/17] Tweaked the versions history modal.

---
 app/templates/modal/versions.jade     | 2 +-
 app/views/modal/versions_modal.coffee | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

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/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: ""

From 6057bd94b93ca827e9c918269a44d5443fea5d09 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 11:27:20 -0700
Subject: [PATCH 07/17] Refactored how the editor sets up its special nav
 through base.jade.

---
 app/styles/editor/level/edit.sass    |  16 +--
 app/templates/editor/level/edit.jade | 156 +++++++++++++--------------
 2 files changed, 86 insertions(+), 86 deletions(-)

diff --git a/app/styles/editor/level/edit.sass b/app/styles/editor/level/edit.sass
index 339b199c2..a4f27c597 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
@@ -55,7 +55,7 @@
   .outer-content
     background-color: $BG
     position: absolute
-    top: 0
+    top: 35px
     bottom: 0
     left: 0
     right: 0
@@ -73,10 +73,10 @@
 
   #level-editor-tabs
     position: absolute
-    left: 20px
-    right: 20px
-    top: 46px
-    bottom: 20px
+    left: 15px
+    right: 15px
+    top: 15px
+    bottom: 15px
     
   .treema-root
     background-color: white
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index 5c21fb45e..ea902d695 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -1,90 +1,90 @@
 extends /templates/base
 
-block outer_content
-  .outer-content
-    
-    if false
-      nav.navbar.navbar-default(role='navigation')#level-editor-top-nav
-        .container-fluid
-          ul.nav.navbar-nav
-            li
-              a(href="/editor/level")
-                span.glyphicon-home.glyphicon
-    
-    else
-      nav.navbar.navbar-default(role='navigation')#level-editor-top-nav
+block header
+  if false
+    nav.navbar.navbar-default(role='navigation')#level-editor-top-nav
+      .container-fluid
         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}
+  
+  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
-              a
-                span.glyphicon-floppy-disk.glyphicon
-          else
-            li
-              a
-                span.glyphicon-floppy-disk.glyphicon
-          
-          li(title="⌃↩ or ⌘↩: Play preview of current level")
+      ul.nav.navbar-nav.navbar-right
+        if authorized
+          li
             a
-              span.glyphicon-play.glyphicon
-          li.dropdown
-            a(data-toggle='dropdown')
-              span.glyphicon-chevron-down.glyphicon
-            ul.dropdown-menu
-              li.dropdown-header Actions
-              li#watch-button
-                a
-                  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#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
+              span.glyphicon-floppy-disk.glyphicon
+        else
+          li
+            a
+              span.glyphicon-floppy-disk.glyphicon
+        
+        li(title="⌃↩ or ⌘↩: Play preview of current level")
+          a
+            span.glyphicon-play.glyphicon
+        li.dropdown
+          a(data-toggle='dropdown')
+            span.glyphicon-chevron-down.glyphicon
+          ul.dropdown-menu
+            li.dropdown-header Actions
+            li#watch-button
+              a
+                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#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
         

From 8f4535853b81b5b02f314e20365e103bf74ed2b7 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 11:29:12 -0700
Subject: [PATCH 08/17] Fixed the component history button.

---
 app/templates/editor/level/component/edit.jade | 2 +-
 app/templates/editor/level/edit.jade           | 2 +-
 app/views/editor/level/component/edit.coffee   | 2 +-
 app/views/editor/level/edit.coffee             | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/app/templates/editor/level/component/edit.jade b/app/templates/editor/level/component/edit.jade
index 74d90e625..655ac818f 100644
--- a/app/templates/editor/level/component/edit.jade
+++ b/app/templates/editor/level/component/edit.jade
@@ -37,7 +37,7 @@ nav.navbar.navbar-default(role='navigation')
         li.divider
         li.dropdown-header Info
   
-        li#history-button
+        li#component-history-button
           a(data-i18n="general.version_history") Version History
 
 .tab-content
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index ea902d695..20898abf6 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -70,7 +70,7 @@ block header
               a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert
             li.divider
             li.dropdown-header Info
-            li#history-button
+            li#level-history-button
               a(href='#', data-i18n="general.version_history") Version History
             li.divider
             li.dropdown-header Help
diff --git a/app/views/editor/level/component/edit.coffee b/app/views/editor/level/component/edit.coffee
index fa2f3609f..7fc326b88 100644
--- a/app/views/editor/level/component/edit.coffee
+++ b/app/views/editor/level/component/edit.coffee
@@ -12,7 +12,7 @@ module.exports = class LevelComponentEditView extends View
 
   events:
     'click #done-editing-component-button': 'endEditing'
-    'click #history-button': 'showVersionHistory'
+    'click #component-history-button': 'showVersionHistory'
     'click .nav a': (e) -> $(e.target).tab('show')
     'click #component-patches-tab': -> @patchesView.load()
     'click #patch-component-button': 'startPatchingComponent'
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index 26808a742..fdc4727aa 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -27,7 +27,7 @@ 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 #watch-button': 'toggleWatchLevel'

From 7bc9bb53282b52d241661e482aa5c61066cb4463 Mon Sep 17 00:00:00 2001
From: dpen2000 <davidpendray@gmail.com>
Date: Thu, 17 Apr 2014 14:32:35 -0400
Subject: [PATCH 09/17] Fix javascript error occuring when e is null/undefined

---
 app/views/editor/level/thangs_tab_view.coffee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/views/editor/level/thangs_tab_view.coffee b/app/views/editor/level/thangs_tab_view.coffee
index 5c5ca8dbd..b11c616db 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')

From 9eff958dcb728c7404b1ac64904f19db06a5f32c Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 11:35:09 -0700
Subject: [PATCH 10/17] Fixed the level and component watch buttons.

---
 app/templates/editor/level/component/edit.jade | 4 ++--
 app/templates/editor/level/edit.jade           | 6 +++---
 app/templates/editor/level/system/edit.jade    | 2 +-
 app/views/editor/level/component/edit.coffee   | 6 +++---
 app/views/editor/level/edit.coffee             | 6 +++---
 5 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/app/templates/editor/level/component/edit.jade b/app/templates/editor/level/component/edit.jade
index 655ac818f..d5ec68c93 100644
--- a/app/templates/editor/level/component/edit.jade
+++ b/app/templates/editor/level/component/edit.jade
@@ -19,8 +19,8 @@ nav.navbar.navbar-default(role='navigation')
 
       ul.dropdown-menu
         li.dropdown-header Actions
-        li#watch-component-button
-          a
+        li
+          a#component-watch-button
             span.watch
               span.glyphicon.glyphicon-eye-open
               span.spl Watch
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index 20898abf6..ecfebecf9 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -1,7 +1,7 @@
 extends /templates/base
 
 block header
-  if false
+  if level.loading
     nav.navbar.navbar-default(role='navigation')#level-editor-top-nav
       .container-fluid
         ul.nav.navbar-nav
@@ -55,8 +55,8 @@ block header
             span.glyphicon-chevron-down.glyphicon
           ul.dropdown-menu
             li.dropdown-header Actions
-            li#watch-button
-              a
+            li
+              a#level-watch-button
                 span.watch
                   span.glyphicon.glyphicon-eye-open
                   span.spl Watch
diff --git a/app/templates/editor/level/system/edit.jade b/app/templates/editor/level/system/edit.jade
index d1aed8a93..ad4bc1e62 100644
--- a/app/templates/editor/level/system/edit.jade
+++ b/app/templates/editor/level/system/edit.jade
@@ -14,7 +14,7 @@ nav.navbar.navbar-default(role='navigation')
         span.glyphicon-chevron-down.glyphicon
       ul.dropdown-menu
         li.dropdown-header Actions
-        li#watch-component-button
+        li#component-watch-button
           a
             span.watch
               span.glyphicon.glyphicon-eye-open
diff --git a/app/views/editor/level/component/edit.coffee b/app/views/editor/level/component/edit.coffee
index 7fc326b88..1b842942a 100644
--- a/app/views/editor/level/component/edit.coffee
+++ b/app/views/editor/level/component/edit.coffee
@@ -16,7 +16,7 @@ module.exports = class LevelComponentEditView extends View
     'click .nav a': (e) -> $(e.target).tab('show')
     'click #component-patches-tab': -> @patchesView.load()
     'click #patch-component-button': 'startPatchingComponent'
-    'click #watch-component-button': 'toggleWatchComponent'
+    'click #component-watch-button': 'toggleWatchComponent'
 
   constructor: (options) ->
     super options
@@ -35,7 +35,7 @@ module.exports = class LevelComponentEditView extends View
     @buildConfigSchemaTreema()
     @buildCodeEditor()
     @patchesView = @insertSubView(new PatchesView(@levelComponent), @$el.find('.patches-view'))
-    @$el.find('#watch-component-button').find('> span').toggleClass('secret') if @levelComponent.watching()
+    @$el.find('#component-watch-button').find('> span').toggleClass('secret') if @levelComponent.watching()
 
   buildSettingsTreema: ->
     data = _.pick @levelComponent.attributes, (value, key) => key in @editableSettings
@@ -105,7 +105,7 @@ module.exports = class LevelComponentEditView extends View
     Backbone.Mediator.publish 'level:view-switched', e
 
   toggleWatchComponent: ->
-    button = @$el.find('#watch-component-button')
+    button = @$el.find('#component-watch-button')
     @levelComponent.watch(button.find('.watch').is(':visible'))
     button.find('> span').toggleClass('secret')
 
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index fdc4727aa..9ba419b47 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -30,7 +30,7 @@ module.exports = class EditorLevelView extends View
     'click #level-history-button': 'showVersionHistory'
     'click #patches-tab': -> @patchesView.load()
     'click #commit-level-patch-button': 'startPatchingLevel'
-    'click #watch-button': 'toggleWatchLevel'
+    'click #level-watch-button': 'toggleWatchLevel'
 
   constructor: (options, @levelID) ->
     super options
@@ -94,7 +94,7 @@ 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'))
-    @$el.find('#watch-button').find('> span').toggleClass('secret') if @level.watching()
+    @$el.find('#level-watch-button').find('> span').toggleClass('secret') if @level.watching()
 
   onPlayLevel: (e) ->
     sendLevel = =>
@@ -128,6 +128,6 @@ module.exports = class EditorLevelView extends View
     Backbone.Mediator.publish 'level:view-switched', e
 
   toggleWatchLevel: ->
-    button = @$el.find('#watch-button')
+    button = @$el.find('#level-watch-button')
     @level.watch(button.find('.watch').is(':visible'))
     button.find('> span').toggleClass('secret')

From b5406b01494246dda047f741d0164127729f459c Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 13:24:17 -0700
Subject: [PATCH 11/17] Set up the rest of the component/system buttons and nav
 bars.

---
 app/templates/editor/level/system/edit.jade  | 10 ++++++---
 app/views/editor/level/component/edit.coffee |  6 ++---
 app/views/editor/level/system/edit.coffee    | 23 ++++++++++++++++++++
 app/views/editor/system/versions_view.coffee |  9 ++++++++
 4 files changed, 42 insertions(+), 6 deletions(-)
 create mode 100755 app/views/editor/system/versions_view.coffee

diff --git a/app/templates/editor/level/system/edit.jade b/app/templates/editor/level/system/edit.jade
index ad4bc1e62..cc35a29b5 100644
--- a/app/templates/editor/level/system/edit.jade
+++ b/app/templates/editor/level/system/edit.jade
@@ -7,6 +7,8 @@ nav.navbar.navbar-default(role='navigation')
       a(href="#system-config-schema" data-toggle="tab") Config Schema
     li
       a(href="#system-settings" data-toggle="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
@@ -14,15 +16,15 @@ nav.navbar.navbar-default(role='navigation')
         span.glyphicon-chevron-down.glyphicon
       ul.dropdown-menu
         li.dropdown-header Actions
-        li#component-watch-button
-          a
+        li
+          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-component-button
+        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
@@ -41,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/views/editor/level/component/edit.coffee b/app/views/editor/level/component/edit.coffee
index 1b842942a..ba8c01d48 100644
--- a/app/views/editor/level/component/edit.coffee
+++ b/app/views/editor/level/component/edit.coffee
@@ -1,7 +1,7 @@
 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'
 
@@ -12,9 +12,9 @@ module.exports = class LevelComponentEditView extends View
 
   events:
     'click #done-editing-component-button': 'endEditing'
-    'click #component-history-button': 'showVersionHistory'
     'click .nav a': (e) -> $(e.target).tab('show')
     'click #component-patches-tab': -> @patchesView.load()
+    'click #component-history-button': 'showVersionHistory'
     'click #patch-component-button': 'startPatchingComponent'
     'click #component-watch-button': 'toggleWatchComponent'
 
@@ -96,7 +96,7 @@ module.exports = class LevelComponentEditView extends View
     null
 
   showVersionHistory: (e) ->
-    versionHistoryView = new VersionHistoryView component:@levelComponent, @levelComponent.id
+    versionHistoryView = new VersionHistoryView {}, @levelComponent.id
     @openModalView versionHistoryView
     Backbone.Mediator.publish 'level:view-switched', e
     
diff --git a/app/views/editor/level/system/edit.coffee b/app/views/editor/level/system/edit.coffee
index 338ede1e5..365910d38 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,10 @@ 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-history-button': 'showVersionHistory'
+    'click #patch-system-button': 'startPatchingSystem'
+    'click #system-watch-button': 'toggleWatchSystem'
 
   constructor: (options) ->
     super options
@@ -26,6 +33,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
@@ -88,6 +96,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/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

From 781a8ec913139892ff227b43b6ae238a37540311 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 13:37:08 -0700
Subject: [PATCH 12/17] Fixed the play and save buttons.

---
 app/styles/editor/level/edit.sass    | 4 ++--
 app/templates/editor/level/edit.jade | 6 +++---
 app/views/editor/level/edit.coffee   | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/app/styles/editor/level/edit.sass b/app/styles/editor/level/edit.sass
index a4f27c597..3e747368f 100644
--- a/app/styles/editor/level/edit.sass
+++ b/app/styles/editor/level/edit.sass
@@ -20,6 +20,7 @@
   // custom navbar height rules
   .navbar-nav > li > a
     padding: 7px 8px 8px
+    cursor: pointer
     &:hover
       background-color: lighten($NAVBG, 10%)
   .navbar
@@ -80,5 +81,4 @@
     
   .treema-root
     background-color: white
-    border-radius: 4px
-    
+    border-radius: 4px
\ No newline at end of file
diff --git a/app/templates/editor/level/edit.jade b/app/templates/editor/level/edit.jade
index ecfebecf9..6b010912d 100644
--- a/app/templates/editor/level/edit.jade
+++ b/app/templates/editor/level/edit.jade
@@ -39,15 +39,15 @@ block header
 
       ul.nav.navbar-nav.navbar-right
         if authorized
-          li
+          li#commit-level-start-button
             a
               span.glyphicon-floppy-disk.glyphicon
         else
-          li
+          li#level-patch-button
             a
               span.glyphicon-floppy-disk.glyphicon
         
-        li(title="⌃↩ or ⌘↩: Play preview of current level")
+        li(title="⌃↩ or ⌘↩: Play preview of current level")#play-button
           a
             span.glyphicon-play.glyphicon
         li.dropdown
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index 9ba419b47..9a83172ac 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -29,7 +29,7 @@ module.exports = class EditorLevelView extends View
     'click #fork-level-start-button': 'startForkingLevel'
     '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'
 
   constructor: (options, @levelID) ->

From cdaf2ebfaf01719a30adab337a3403846584e9ea Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 14:23:33 -0700
Subject: [PATCH 13/17] Set up the tabs and views in the level editor to reload
 so that when patches are applied, their changes are visible.

---
 app/styles/editor/level/component/edit.sass    | 9 ++++++++-
 app/styles/editor/level/system/edit.sass       | 7 +++++++
 app/styles/editor/patches.sass                 | 2 +-
 app/templates/editor/level/component/edit.jade | 6 +++---
 app/templates/editor/level/system/edit.jade    | 6 +++---
 app/templates/editor/patch_modal.jade          | 1 +
 app/views/editor/level/component/edit.coffee   | 8 ++++++--
 app/views/editor/level/edit.coffee             | 8 ++++++++
 app/views/editor/level/system/edit.coffee      | 8 ++++++--
 app/views/editor/patch_modal.coffee            | 9 +++++++--
 app/views/editor/patches_view.coffee           | 3 ++-
 app/views/modal/save_version_modal.coffee      | 1 +
 12 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/app/styles/editor/level/component/edit.sass b/app/styles/editor/level/component/edit.sass
index beca326ff..7a78534ed 100644
--- a/app/styles/editor/level/component/edit.sass
+++ b/app/styles/editor/level/component/edit.sass
@@ -16,4 +16,11 @@
     bottom: 0
     top: 35px
     border: 2px solid black
-    border-top: none
\ No newline at end of file
+    border-top: none
+    
+  .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/system/edit.sass b/app/styles/editor/level/system/edit.sass
index e648e3e64..567ff5b27 100644
--- a/app/styles/editor/level/system/edit.sass
+++ b/app/styles/editor/level/system/edit.sass
@@ -10,3 +10,10 @@
     top: 35px
     border: 2px solid black
     border-top: none
+
+  .inner-editor
+    position: absolute
+    left: 0
+    right: 0
+    bottom: 0
+    top: 0px
\ No newline at end of file
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 d5ec68c93..7228ff914 100644
--- a/app/templates/editor/level/component/edit.jade
+++ b/app/templates/editor/level/component/edit.jade
@@ -1,11 +1,11 @@
 nav.navbar.navbar-default(role='navigation')
   ul.nav.navbar-nav.nav-tabs
     li.active
-      a(href="#component-code" data-toggle="tab" data-i18n="general.code") Code
+      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") Config Schema
+      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") Settings
+      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
 
diff --git a/app/templates/editor/level/system/edit.jade b/app/templates/editor/level/system/edit.jade
index cc35a29b5..267993ea5 100644
--- a/app/templates/editor/level/system/edit.jade
+++ b/app/templates/editor/level/system/edit.jade
@@ -2,11 +2,11 @@ nav.navbar.navbar-default(role='navigation')
 
   ul.nav.navbar-nav.nav-tabs
     li.active
-      a(href="#system-code" data-toggle="tab") Code
+      a(href="#system-code" data-toggle="tab")#system-code-tab Code
     li
-      a(href="#system-config-schema" data-toggle="tab") Config Schema
+      a(href="#system-config-schema" data-toggle="tab")#system-config-schema-tab Config Schema
     li
-      a(href="#system-settings" data-toggle="tab") Settings
+      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
 
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/views/editor/level/component/edit.coffee b/app/views/editor/level/component/edit.coffee
index ba8c01d48..74c23b567 100644
--- a/app/views/editor/level/component/edit.coffee
+++ b/app/views/editor/level/component/edit.coffee
@@ -14,6 +14,9 @@ module.exports = class LevelComponentEditView extends View
     'click #done-editing-component-button': 'endEditing'
     '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'
@@ -76,8 +79,9 @@ 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])
     session = @editor.getSession()
     session.setMode 'ace/mode/coffee'
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index 9a83172ac..f0f15828b 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -31,7 +31,14 @@ module.exports = class EditorLevelView extends View
     'click #patches-tab': -> @patchesView.load()
     'click #level-patch-button': 'startPatchingLevel'
     'click #level-watch-button': 'toggleWatchLevel'
+    
+  subscriptions:
+    'refresh-level-editor': 'rerenderAllViews'
 
+  rerenderAllViews: ->
+    for view in [@thangsTab, @settingsTab, @scriptsTab, @componentsTab, @systemsTab, @patchesView]
+      view.render()
+    
   constructor: (options, @levelID) ->
     super options
     @listenToOnce(@supermodel, 'loaded-all', @onAllLoaded)
@@ -94,6 +101,7 @@ 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', -> location.reload()
     @$el.find('#level-watch-button').find('> span').toggleClass('secret') if @level.watching()
 
   onPlayLevel: (e) ->
diff --git a/app/views/editor/level/system/edit.coffee b/app/views/editor/level/system/edit.coffee
index 365910d38..a7699b316 100644
--- a/app/views/editor/level/system/edit.coffee
+++ b/app/views/editor/level/system/edit.coffee
@@ -14,6 +14,9 @@ module.exports = class LevelSystemEditView extends View
     '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'
@@ -76,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()
diff --git a/app/views/editor/patch_modal.coffee b/app/views/editor/patch_modal.coffee
index 19f3ebfe6..88a5bec86 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'))
@@ -49,6 +53,7 @@ module.exports = class PatchModal extends ModalView
     delta = @deltaView.getApplicableDelta()
     @targetModel.applyDelta(delta)
     @targetModel.addPatchToAcceptOnSave(@patch)
+    @trigger 'accepted-patch'
     @hide()
     
   rejectPatch: ->
diff --git a/app/views/editor/patches_view.coffee b/app/views/editor/patches_view.coffee
index f8dd4fa15..ce9512caf 100644
--- a/app/views/editor/patches_view.coffee
+++ b/app/views/editor/patches_view.coffee
@@ -53,4 +53,5 @@ 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'
\ No newline at end of file
diff --git a/app/views/modal/save_version_modal.coffee b/app/views/modal/save_version_modal.coffee
index 13dbecda5..22fba1216 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'

From 7ccaa8c843dd8b013d481f03b5a7e63273735ce2 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 14:39:52 -0700
Subject: [PATCH 14/17] Fixed a bug, colored a badge.

---
 app/styles/editor/level/edit.sass | 3 +++
 app/views/editor/delta.coffee     | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/app/styles/editor/level/edit.sass b/app/styles/editor/level/edit.sass
index 3e747368f..7d2b5b962 100644
--- a/app/styles/editor/level/edit.sass
+++ b/app/styles/editor/level/edit.sass
@@ -52,6 +52,9 @@
     cursor: pointer
     &:hover
       background-color: #d3d3d3
+      
+  .badge
+    background-color: green
 
   .outer-content
     background-color: $BG
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: ->

From 21e8d7b26f132fa45a451dda13b4401fcaac974f Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 15:44:19 -0700
Subject: [PATCH 15/17] Fixed patches denormalization.

---
 app/models/CocoModel.coffee          |  8 --------
 app/views/editor/level/edit.coffee   |  2 +-
 app/views/editor/patch_modal.coffee  |  2 +-
 app/views/editor/patches_view.coffee | 11 +++++++++--
 app/views/kinds/ModalView.coffee     |  2 ++
 server/patches/Patch.coffee          |  3 ++-
 6 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index 6ccfae775..a4c031869 100644
--- a/app/models/CocoModel.coffee
+++ b/app/models/CocoModel.coffee
@@ -68,8 +68,6 @@ class CocoModel extends Backbone.Model
       @markToRevert()
       @clearBackup()
     @trigger "save", @
-    PatchModel = require 'models/Patch'
-    PatchModel.setStatus id, 'accepted' for id in @get('acceptedPatches') or []
     return super attrs, options
 
   fetch: ->
@@ -221,12 +219,6 @@ class CocoModel extends Backbone.Model
     delta = @getDelta()
     deltasLib.expandDelta(delta, @_revertAttributes, @schema())
 
-  addPatchToAcceptOnSave: (patch) ->
-    acceptedPatches = @get('acceptedPatches') or [] # not actually stored on the db
-    acceptedPatches.push patch.id
-    acceptedPatches = _.uniq(acceptedPatches)
-    @set 'acceptedPatches', acceptedPatches
-    
   watch: (doWatch=true) ->
     $.ajax("#{@urlRoot}/#{@id}/watch", {type:'PUT', data:{on:doWatch}})
     @watching = -> doWatch
diff --git a/app/views/editor/level/edit.coffee b/app/views/editor/level/edit.coffee
index f0f15828b..88d50be62 100644
--- a/app/views/editor/level/edit.coffee
+++ b/app/views/editor/level/edit.coffee
@@ -101,7 +101,7 @@ 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', -> location.reload()
+    @listenTo @patchesView, 'accepted-patch', -> setTimeout "location.reload()", 400
     @$el.find('#level-watch-button').find('> span').toggleClass('secret') if @level.watching()
 
   onPlayLevel: (e) ->
diff --git a/app/views/editor/patch_modal.coffee b/app/views/editor/patch_modal.coffee
index 88a5bec86..f5dc339cf 100644
--- a/app/views/editor/patch_modal.coffee
+++ b/app/views/editor/patch_modal.coffee
@@ -52,7 +52,7 @@ module.exports = class PatchModal extends ModalView
   acceptPatch: ->
     delta = @deltaView.getApplicableDelta()
     @targetModel.applyDelta(delta)
-    @targetModel.addPatchToAcceptOnSave(@patch)
+    @patch.setStatus('accepted')
     @trigger 'accepted-patch'
     @hide()
     
diff --git a/app/views/editor/patches_view.coffee b/app/views/editor/patches_view.coffee
index ce9512caf..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()
@@ -54,4 +57,8 @@ module.exports = class PatchesView extends CocoView
     patch = _.find @patches.models, {id:$(e.target).data('patch-id')}
     modal = new PatchModal(patch, @model)
     @openModalView(modal)
-    @listenTo modal, 'accepted-patch', -> @trigger 'accepted-patch'
\ No newline at end of file
+    @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/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/server/patches/Patch.coffee b/server/patches/Patch.coffee
index df621f2a4..47b6aefa9 100644
--- a/server/patches/Patch.coffee
+++ b/server/patches/Patch.coffee
@@ -39,8 +39,9 @@ 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}
     document.save (err) -> next(err)
 
 module.exports = mongoose.model('patch', PatchSchema)

From ed0c7e1412a402a2fd743d34523f28484df6fd07 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 17:09:01 -0700
Subject: [PATCH 16/17] Creators of documents are automatically added as
 watchers. Added a patch creation email for watchers.

---
 app/views/modal/save_version_modal.coffee |  1 +
 server/commons/Handler.coffee             |  8 ++++++--
 server/patches/Patch.coffee               |  1 +
 server/patches/patch_handler.coffee       | 25 +++++++++++++++++++++++
 server/sendwithus.coffee                  |  1 +
 test/server/common.coffee                 | 10 ++++-----
 test/server/functional/patch.spec.coffee  | 11 +++++-----
 test/server/functional/user.spec.coffee   |  2 +-
 8 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/app/views/modal/save_version_modal.coffee b/app/views/modal/save_version_modal.coffee
index 22fba1216..d95fc4166 100644
--- a/app/views/modal/save_version_modal.coffee
+++ b/app/views/modal/save_version_modal.coffee
@@ -56,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/server/commons/Handler.coffee b/server/commons/Handler.coffee
index 99c28e71c..4ce1c6b93 100644
--- a/server/commons/Handler.coffee
+++ b/server/commons/Handler.coffee
@@ -233,6 +233,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 +251,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))
@@ -299,7 +301,9 @@ module.exports = class Handler
         parentDocument.makeNewMajorVersion(updatedObject, done)
 
   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 47b6aefa9..3e12638cf 100644
--- a/server/patches/Patch.coffee
+++ b/server/patches/Patch.coffee
@@ -42,6 +42,7 @@ PatchSchema.pre 'save', (next) ->
     patches = _.clone patches
     patches.push @_id
     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..6262936f6 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,28 @@ 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')
+    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..41fbd4062 100644
--- a/server/sendwithus.coffee
+++ b/server/sendwithus.coffee
@@ -14,3 +14,4 @@ if config.unittest
 module.exports.templates =
   welcome_email: 'utnGaBHuSU4Hmsi7qrAypU'
   ladder_update_email: 'JzaZxf39A4cKMxpPZUfWy4'
+  patch_created: 'tem_xhxuNosLALsizTNojBjNcL'
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 4666c5353..9f35cb37d 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()
@@ -56,24 +57,24 @@ describe '/db/patch', ->
   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[0]).toBeDefined()
+      expect(body.watchers[1]).toBeDefined()
       done()
 
   it 'added the watcher to the target document', (done) ->
     Article.findOne({}).exec (err, article) ->
-      expect(article.toObject().watchers[0]).toBeDefined()
+      expect(article.toObject().watchers[1]).toBeDefined()
       done()
 
   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(1)
+      expect(body.watchers.length).toBe(2)
       done()
       
   it 'allows removing yourself', (done) ->
     watchingURL = getURL("/db/article/#{articles[0]._id}/watch")
     request.put {uri: watchingURL, json: {on:false}}, (err, res, body) ->
-      expect(body.watchers.length).toBe(0)
+      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')

From 8adca4a1dae1913d9a2047b3a58085679a1b4418 Mon Sep 17 00:00:00 2001
From: Scott Erickson <sderickson@gmail.com>
Date: Thu, 17 Apr 2014 17:30:55 -0700
Subject: [PATCH 17/17] Added a transactional email for when changes are made,
 to notify watchers.

---
 app/models/CocoModel.coffee              |  1 +
 server/commons/Handler.coffee            | 24 ++++++++++++++++++++++++
 server/patches/patch_handler.coffee      |  3 ++-
 server/sendwithus.coffee                 |  1 +
 test/server/functional/patch.spec.coffee |  2 +-
 5 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee
index a4c031869..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) =>
diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee
index 4ce1c6b93..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
@@ -293,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)
@@ -300,6 +303,27 @@ 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) ->
     model = new @modelClass({})
     model.set 'watchers', [req.user.get('_id')] if @modelClass.schema.is_patchable
diff --git a/server/patches/patch_handler.coffee b/server/patches/patch_handler.coffee
index 6262936f6..4e134d73d 100644
--- a/server/patches/patch_handler.coffee
+++ b/server/patches/patch_handler.coffee
@@ -57,7 +57,8 @@ PatchHandler = class PatchHandler extends Handler
   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')
+    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
diff --git a/server/sendwithus.coffee b/server/sendwithus.coffee
index 41fbd4062..04d8205c3 100644
--- a/server/sendwithus.coffee
+++ b/server/sendwithus.coffee
@@ -15,3 +15,4 @@ 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/functional/patch.spec.coffee b/test/server/functional/patch.spec.coffee
index 9f35cb37d..9d0f4265d 100644
--- a/test/server/functional/patch.spec.coffee
+++ b/test/server/functional/patch.spec.coffee
@@ -52,7 +52,7 @@ 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 watching', (done) ->
     watchingURL = getURL("/db/article/#{articles[0]._id}/watch")