couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gar...@apache.org
Subject [2/3] fauxton commit: updated refs/heads/master to d68bc8e
Date Fri, 25 Jul 2014 09:04:03 GMT
upstream merge


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/12f282c4
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/12f282c4
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/12f282c4

Branch: refs/heads/master
Commit: 12f282c455e91f359a33d02668f20e429d679683
Parents: b340f1d 893e988
Author: sebastianrothbucher <sebastianrothbucher@googlemail.com>
Authored: Thu Jul 24 22:50:48 2014 +0200
Committer: sebastianrothbucher <sebastianrothbucher@googlemail.com>
Committed: Thu Jul 24 22:50:48 2014 +0200

----------------------------------------------------------------------
 Gruntfile.js                                    |   11 +-
 app/addons/activetasks/templates/tabs.html      |   11 +-
 app/addons/activetasks/views.js                 |    2 +
 app/addons/config/templates/item.html           |    8 +-
 .../documents/assets/less/advancedOptions.less  |    1 +
 app/addons/documents/assets/less/changes.less   |   31 +
 app/addons/documents/assets/less/documents.less |   87 +-
 app/addons/documents/assets/less/sidenav.less   |  147 ++
 app/addons/documents/routes.js                  |  137 +-
 .../documents/templates/all_docs_layout.html    |   12 +-
 app/addons/documents/templates/changes.html     |    4 +-
 app/addons/documents/templates/code_editor.html |    4 +-
 app/addons/documents/templates/ddoc_info.html   |    2 +-
 .../templates/delete_database_modal.html        |    4 +-
 .../documents/templates/design_doc_menu.html    |   32 +
 .../templates/design_doc_selector.html          |    3 +
 .../templates/duplicate_doc_modal.html          |    4 +-
 .../documents/templates/index_menu_item.html    |   17 +-
 app/addons/documents/templates/search.html      |   15 -
 app/addons/documents/templates/sidebar.html     |   69 +-
 .../documents/templates/upload_modal.html       |    4 +-
 app/addons/documents/templates/view_editor.html |    7 +-
 app/addons/documents/views-advancedopts.js      |  270 +++
 app/addons/documents/views-changes.js           |   84 +
 app/addons/documents/views-doceditor.js         |  535 +++++
 app/addons/documents/views-index.js             |  574 ++++++
 app/addons/documents/views-sidebar.js           |  253 +++
 app/addons/documents/views.js                   | 1587 +--------------
 app/addons/fauxton/base.js                      |   22 +-
 app/addons/fauxton/components.js                |   27 +
 app/addons/fauxton/templates/api_bar.html       |   16 +-
 app/addons/fauxton/templates/breadcrumbs.html   |    2 +-
 app/addons/fauxton/templates/menu_dropdown.html |   33 +
 app/addons/permissions/templates/section.html   |    4 +-
 app/addons/verifyinstall/base.js                |    2 +-
 app/templates/layouts/two_pane.html             |    1 -
 app/templates/layouts/with_tabs_sidebar.html    |    6 +-
 assets/fonts/FontAwesome.otf                    |  Bin 0 -> 61896 bytes
 assets/fonts/Gemfile                            |    5 +
 assets/fonts/Gemfile.lock                       |   31 +
 assets/fonts/README.md                          |   39 +
 assets/fonts/fauxtonicon.eot                    |  Bin 0 -> 16314 bytes
 assets/fonts/fauxtonicon.svg                    |  644 ++++++
 assets/fonts/fauxtonicon.ttf                    |  Bin 0 -> 16130 bytes
 assets/fonts/fauxtonicon.woff                   |  Bin 0 -> 5804 bytes
 assets/fonts/fontawesome-webfont.eot            |  Bin 0 -> 37405 bytes
 assets/fonts/fontawesome-webfont.svg            |  399 ++++
 assets/fonts/fontawesome-webfont.ttf            |  Bin 0 -> 79076 bytes
 assets/fonts/fontawesome-webfont.woff           |  Bin 0 -> 43572 bytes
 assets/fonts/fontcustom.yml                     |   51 +
 .../fonts/styleguide/fauxtonicon-preview.html   | 1868 ++++++++++++++++++
 assets/fonts/templates/icons.less               |   30 +
 assets/icons/activetasks.svg                    |    8 +
 assets/icons/arrow-box-down.svg                 |    8 +
 assets/icons/arrow-box-up.svg                   |    8 +
 assets/icons/arrow_left.svg                     |    7 +
 assets/icons/arrow_right.svg                    |    7 +
 assets/icons/arrows-cw.svg                      |    8 +
 assets/icons/article.svg                        |    8 +
 assets/icons/attention-alt.svg                  |    8 +
 assets/icons/attention-circled.svg              |    8 +
 assets/icons/block.svg                          |    8 +
 assets/icons/bookmark-ribbon-wplus.svg          |    8 +
 assets/icons/bookmark.svg                       |    8 +
 assets/icons/burger.svg                         |    8 +
 assets/icons/cancel-circled.svg                 |    8 +
 assets/icons/cancel-circled2.svg                |    8 +
 assets/icons/cancel.svg                         |    8 +
 assets/icons/circle-empty.svg                   |    8 +
 assets/icons/clipboard.svg                      |    8 +
 assets/icons/clock.svg                          |    8 +
 assets/icons/cog.svg                            |    8 +
 assets/icons/collapse.svg                       |    8 +
 assets/icons/cw.svg                             |    8 +
 assets/icons/dashboard.svg                      |    8 +
 assets/icons/database.svg                       |    8 +
 assets/icons/deselect-all.svg                   |   15 +
 assets/icons/document.svg                       |    8 +
 assets/icons/documents.svg                      |    8 +
 assets/icons/dot-circled.svg                    |    8 +
 assets/icons/down-1.svg                         |    8 +
 assets/icons/down-circled.svg                   |    8 +
 assets/icons/down-dir.svg                       |    8 +
 assets/icons/down-open.svg                      |    8 +
 assets/icons/down.svg                           |    8 +
 assets/icons/drop-down-dots.svg                 |    8 +
 assets/icons/exchange.svg                       |    8 +
 assets/icons/expand.svg                         |    8 +
 assets/icons/eye.svg                            |    8 +
 assets/icons/help-circled.svg                   |    8 +
 assets/icons/help.svg                           |    8 +
 assets/icons/info-circled.svg                   |    8 +
 assets/icons/json.svg                           |    8 +
 assets/icons/key.svg                            |    8 +
 assets/icons/left-1.svg                         |    8 +
 assets/icons/left-circled.svg                   |    8 +
 assets/icons/left-dir.svg                       |    8 +
 assets/icons/left-open.svg                      |    8 +
 assets/icons/left.svg                           |    8 +
 assets/icons/link.svg                           |    8 +
 assets/icons/list-alt.svg                       |    8 +
 assets/icons/lock.svg                           |    8 +
 assets/icons/mail-alt.svg                       |    8 +
 assets/icons/mail.svg                           |    8 +
 assets/icons/megaphone.svg                      |    8 +
 assets/icons/minus-circled.svg                  |    8 +
 assets/icons/minus-circled2.svg                 |    9 +
 assets/icons/minus-squared-alt.svg              |    8 +
 assets/icons/minus-squared.svg                  |    8 +
 assets/icons/minus.svg                          |    8 +
 assets/icons/mixer.svg                          |    8 +
 assets/icons/new-database.svg                   |    8 +
 assets/icons/ok-circled-2.svg                   |    8 +
 assets/icons/ok-circled.svg                     |    8 +
 assets/icons/ok.svg                             |    8 +
 assets/icons/paperclip.svg                      | 1364 +++++++++++++
 assets/icons/pencil.svg                         |    8 +
 assets/icons/picture.svg                        |    8 +
 assets/icons/play.svg                           |    8 +
 assets/icons/plus-circled.svg                   |    8 +
 assets/icons/plus-circled2.svg                  |   10 +
 assets/icons/plus-squared-alt.svg               |    8 +
 assets/icons/plus-squared.svg                   |    8 +
 assets/icons/plus.svg                           |    8 +
 assets/icons/popin.svg                          |    8 +
 assets/icons/popout.svg                         |    8 +
 assets/icons/profile.svg                        |    8 +
 assets/icons/replicate.svg                      |    8 +
 assets/icons/reply-all.svg                      |    8 +
 assets/icons/reply.svg                          |    8 +
 assets/icons/resize-full-reverse.svg            |    8 +
 assets/icons/resize-full.svg                    |    8 +
 assets/icons/resize-small-reverse.svg           |    8 +
 assets/icons/resize-small.svg                   |    8 +
 assets/icons/right-1.svg                        |    8 +
 assets/icons/right-circled.svg                  |    8 +
 assets/icons/right-dir.svg                      |    8 +
 assets/icons/right-open.svg                     |    8 +
 assets/icons/right.svg                          |    8 +
 assets/icons/save.svg                           |    8 +
 assets/icons/search.svg                         |    8 +
 assets/icons/select-all.svg                     |   11 +
 assets/icons/sidenav-filter-function.svg        |   10 +
 assets/icons/sidenav-info.svg                   |   15 +
 assets/icons/sidenav-list-function.svg          |   12 +
 assets/icons/sidenav-map-reduce.svg             |   13 +
 assets/icons/sidenav-search.svg                 |   17 +
 assets/icons/sidenav-show-function.svg          |   13 +
 assets/icons/sidenav-update-function.svg        |   12 +
 assets/icons/sitemap.svg                        |    8 +
 assets/icons/stats.svg                          |    8 +
 assets/icons/support.svg                        |    8 +
 assets/icons/swap-arrows.svg                    | 1318 ++++++++++++
 assets/icons/table.svg                          |    8 +
 assets/icons/trash.svg                          |    8 +
 assets/icons/up-1.svg                           |    8 +
 assets/icons/up-circled.svg                     |    8 +
 assets/icons/up-dir.svg                         |    8 +
 assets/icons/up-open.svg                        |    8 +
 assets/icons/up.svg                             |    8 +
 assets/icons/user.svg                           |    8 +
 assets/icons/users.svg                          |    8 +
 assets/icons/wrench.svg                         |    8 +
 assets/img/FontAwesome.otf                      |  Bin 61896 -> 0 bytes
 assets/img/fontawesome-webfont.eot              |  Bin 37405 -> 0 bytes
 assets/img/fontawesome-webfont.svg              |  399 ----
 assets/img/fontawesome-webfont.ttf              |  Bin 79076 -> 0 bytes
 assets/img/fontawesome-webfont.woff             |  Bin 43572 -> 0 bytes
 assets/img/fontcustom_fauxton.eot               |  Bin 7364 -> 0 bytes
 assets/img/fontcustom_fauxton.svg               |  200 --
 assets/img/fontcustom_fauxton.ttf               |  Bin 9636 -> 0 bytes
 assets/img/fontcustom_fauxton.woff              |  Bin 4816 -> 0 bytes
 assets/less/bootstrap/dropdowns.less            |   37 +-
 .../less/bootstrap/font-awesome/variables.less  |    2 +-
 assets/less/bootstrap/navs.less                 |    3 -
 assets/less/bootstrap/variables.less            |    8 +-
 assets/less/fauxton.less                        |  191 +-
 assets/less/icons.less                          |  272 ++-
 assets/less/mixins.less                         |   21 +
 assets/less/variables.less                      |    4 +-
 package.json                                    |    4 +-
 readme.md                                       |   41 +-
 tasks/couchserver.js                            |    4 +-
 183 files changed, 9388 insertions(+), 2494 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/12f282c4/app/addons/documents/assets/less/documents.less
----------------------------------------------------------------------
diff --cc app/addons/documents/assets/less/documents.less
index 0537595,c466e53..13bd4fc
--- a/app/addons/documents/assets/less/documents.less
+++ b/app/addons/documents/assets/less/documents.less
@@@ -119,6 -100,6 +100,31 @@@ button.beautify 
      font-size: 16px;
  }
  
++button.string-edit {
++  position: absolute;
++  padding: 0;
++  z-index: 1000;
++  width: 16px;
++  left: 22px;
++}
++
++button.string-edit[disabled] {
++  display: none;
++}
++
++#string-edit-modal {
++  div.modal {
++    overflow-x: visible;
++    width: initial;
++    min-width: 560px;
++  }
++}
++
++#string-editor-wrapper {
++  height: 500px;
++  width: 100%;
++}
++
  #keys-input {
    width: 100%;
  }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/12f282c4/app/addons/documents/templates/code_editor.html
----------------------------------------------------------------------
diff --cc app/addons/documents/templates/code_editor.html
index 2198079,4a14a9e..76d37ef
--- a/app/addons/documents/templates/code_editor.html
+++ b/app/addons/documents/templates/code_editor.html
@@@ -22,7 -22,6 +22,7 @@@ the License
    </div>
  
    <div class="span7">
-     <button class="btn string-edit" title="Edit line" disabled="true"><i class="icon
icon-edit"></i></button>
++    <button class="btn string-edit" title="Edit line" disabled="true"><i class="icon
icon-edit"></i></button>  
      <% if (attachments) { %>
      <div class="btn-group">
        <button class="dropdown-toggle btn" data-bypass="true" data-toggle="dropdown">

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/12f282c4/app/addons/documents/views-doceditor.js
----------------------------------------------------------------------
diff --cc app/addons/documents/views-doceditor.js
index 0000000,add8d8c..5514bd2
mode 000000,100644..100644
--- a/app/addons/documents/views-doceditor.js
+++ b/app/addons/documents/views-doceditor.js
@@@ -1,0 -1,416 +1,535 @@@
+ // Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ // use this file except in compliance with the License. You may obtain a copy of
+ // the License at
+ //
+ //   http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Unless required by applicable law or agreed to in writing, software
+ // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ // License for the specific language governing permissions and limitations under
+ // the License.
+ 
+ define([
+        "app",
+ 
+        "api",
+        "addons/fauxton/components",
+ 
+        "addons/documents/resources",
+        "addons/databases/resources",
+ 
+        // Libs
+        "addons/fauxton/resizeColumns",
+ 
+        // Plugins
+        "plugins/prettify"
+ ],
+ 
+ function(app, FauxtonAPI, Components, Documents, Databases,
+          resizeColumns, prettify) {
+ 
+   var Views = {};
+ 
+   /* Attachments upload modal */
+ 
+   Views.UploadModal = Components.ModalView.extend({
+     template: "addons/documents/templates/upload_modal",
+ 
+     events: {
+       "click #upload-btn": "uploadFile"
+     },
+ 
+     uploadFile: function (event) {
+       event.preventDefault();
+ 
+       var docRev = this.model.get('_rev'),
+           that = this,
+           $form = this.$('#file-upload');
+ 
+       if (!docRev) {
+         return this.set_error_msg('The document needs to be saved before adding an attachment.');
+       }
+ 
+       if ($('input[type="file"]')[0].files.length === 0) {
+         return this.set_error_msg('Selected a file to be uploaded.');
+       }
+ 
+       this.$('#_rev').val(docRev);
+ 
+       $form.ajaxSubmit({
+         url: this.model.url(),
+         type: 'POST',
+         beforeSend: this.beforeSend,
+         uploadProgress: this.uploadProgress,
+         success: this.success,
+         error: function (resp) {
+           console.log('ERR on upload', resp);
+           return that.set_error_msg('Could not upload document: ' + JSON.parse(resp.responseText).reason);
+         }
+       });
+     },
+ 
+     success: function (resp) {
+       var hideModal = this.hideModal,
+           $form = this.$('#file-upload');
+ 
+       FauxtonAPI.triggerRouteEvent('reRenderDoc');
+       //slight delay to make this transistion a little more fluid and less jumpy
+       setTimeout(function () {
+         $form.clearForm();
+         hideModal();
+         $('.modal-backdrop').remove();
+       }, 1000);
+     },
+ 
+     uploadProgress: function(event, position, total, percentComplete) {
+       this.$('.bar').css({width: percentComplete + '%'});
+     },
+ 
+     beforeSend: function () {
+       this.$('.progress').removeClass('hide');
+     },
+ 
+     _showModal: function () {
+       this.$('.bar').css({width: '0%'});
+       this.$('.progress').addClass('hide');
+     }
+   });
+ 
++  Views.StringEditModal = Components.ModalView.extend({
++    template: "addons/documents/templates/string_edit_modal",
++
++    initialize: function () {
++      _.bindAll(this);
++    },
++
++    events: {
++      "click #string-edit-save-btn":"saveString"
++    },
++  
++    saveString: function (event) {
++      event.preventDefault();
++      var newStr = this.subEditor.getValue();
++      this.subEditor.editSaved();
++      this.editor.replaceCurrentLine(this.indent + this.hashKey + JSON.stringify(newStr)
+ this.comma + "\n");
++      this.hideModal();
++    },
++
++    _showModal: function () {
++      this.$('.bar').css({width: '0%'});
++      this.$('.progress').addClass('hide');
++      this.clear_error_msg();
++    }, 
++
++    openWin: function(editor, indent, hashKey, jsonString, comma) {
++      this.editor = editor;
++      this.indent = indent;
++      this.hashKey = hashKey;      
++      this.$('#string-edit-header').text(hashKey);
++      this.subEditor.setValue(JSON.parse(jsonString));
++      /* make sure we don't have save warnings w/out change */
++      this.subEditor.editSaved();
++      this.comma = comma;
++      this.showModal();
++    },
++
++    afterRender: function() {
++      /* make sure we init only ONCE */
++      if (!this.subEditor) {
++        this.subEditor = new Components.Editor({
++          editorId: "string-editor-container",
++          mode: "plain"
++        });
++        this.subEditor.render();
++        /* optimize by disabling auto sizing (35 is the lines fitting into the pop-up) */
++        this.subEditor.configureFixedHeightEditor(35);
++      }
++    },
++
++    cleanup: function () {
++      if (this.subEditor) this.subEditor.remove();
++    }
++
++  });
+ 
+ 
+   /* Doc Duplication modal */
+   Views.DuplicateDocModal = Components.ModalView.extend({
+     template: "addons/documents/templates/duplicate_doc_modal",
+ 
+     initialize: function () {
+       _.bindAll(this);
+     },
+ 
+     events: {
+       "click #duplicate-btn":"duplicate",
+       "submit #doc-duplicate": "duplicate"
+ 
+     },
+ 
+     duplicate: function (event) {
+       event.preventDefault();
+       var newId = this.$('#dup-id').val(),
+           isDDoc = newId.match(/^_design\//),
+           removeDDocID = newId.replace(/^_design\//,""),
+           encodedID = isDDoc? "_design/"+ app.utils.safeURLName(removeDDocID):app.utils.safeURLName(newId);
+ 
+       this.hideModal();
+       FauxtonAPI.triggerRouteEvent('duplicateDoc', encodedID);
+     },
+ 
+     _showModal: function () {
+       this.$('.bar').css({width: '0%'});
+       this.$('.progress').addClass('hide');
+       this.clear_error_msg();
+       this.$('.modal').modal();
+       // hack to get modal visible
+       $('.modal-backdrop').css('z-index',1025);
+     },
+ 
+     showModal: function () {
+       var showModal = this._showModal,
+           setDefaultIdValue = this.setDefaultIdValue,
+           uuid = new FauxtonAPI.UUID();
+ 
+       uuid.fetch().then(function () {
+         setDefaultIdValue(uuid.next());
+         showModal();
+       });
+     },
+ 
+     setDefaultIdValue: function (id) {
+       this.$('#dup-id').val(id);
+     }
+   });
+ 
+   /* Document editor*/
+    Views.CodeEditor = FauxtonAPI.View.extend({
+     template: "addons/documents/templates/code_editor",
+     events: {
+       "click button.save-doc": "saveDoc",
+       "click button.delete": "destroy",
+       "click button.duplicate": "duplicate",
+       "click button.upload": "upload",
 -      "click button.cancel-button": "goback"
++      "click button.cancel-button": "goback",
++      "click button.string-edit": "stringEditing"
+     },
+ 
+     disableLoader: true,
+ 
+     initialize: function (options) {
+       this.database = options.database;
+       _.bindAll(this);
+     },
+ 
+     goback: function(){
+       FauxtonAPI.navigate(this.database.url("index") + "?limit=100");
+     },
+ 
++    determineStringEditMatch: function(event) {
++      var selStart = this.editor.getSelectionStart().row;
++      var selEnd = this.editor.getSelectionEnd().row;
++      /* one JS(ON) string can't span more than one line - we edit one string, so ensure
we don't select several lines */
++      if (selStart >=0 && selEnd >= 0 && selStart === selEnd &&
this.editor.isRowExpanded(selStart)) {    
++        var editLine = this.editor.getLine(selStart);
++	var editMatch = editLine.match(/^([ \t]*)("[a-zA-Z0-9_]*": )?(".*",?[ \t]*)$/);
++	if (editMatch) {
++          return editMatch;
++	} else {
++          return null;
++	}
++      } else {
++        return null;
++      }
++    }, 
++
++    showHideEditDocString: function (event) {
++      this.$("button.string-edit").attr("disabled", "true");
++      if (!this.hasValidCode()) {
++        return false;
++      }
++      var editMatch = this.determineStringEditMatch(event);
++      if (editMatch) {
++        this.$("button.string-edit").removeAttr("disabled");
++	/* remove the following line (along with CSS) to go back to the toolbar */
++        this.$("button.string-edit").css("top", (this.$("#editor-container")[0].offsetTop
- 2 + this.editor.getRowHeight() * this.editor.documentToScreenRow(this.editor.getSelectionStart().row))
+ "px");
++        return true;
++      }
++      return false;
++    },
++
++    stringEditing: function(event) {
++      event.preventDefault();   
++      if (!this.hasValidCode()) {
++        return;
++      }
++      var editMatch = this.determineStringEditMatch(event);
++      if (editMatch) {
++        var indent = editMatch[1] || "",
++              hashKey = editMatch[2] || "",
++              editText = editMatch[3],
++              comma = "";
++        if (editText.substring(editText.length - 1) === ",") {
++          editText = editText.substring(0, editText.length - 1); 
++          comma = ",";
++        }
++        this.stringEditModal.openWin(this.editor, indent, hashKey, editText, comma);
++      }
++    },
++
+     destroy: function(event) {
+       if (this.model.isNewDoc()) {
+         FauxtonAPI.addNotification({
+           msg: 'This document has not been saved yet.',
+           type: 'warning',
+           clear:  true
+         });
+         return;
+       }
+ 
+       if (!window.confirm("Are you sure you want to delete this doc?")) {
+         return false;
+       }
+ 
+       var database = this.model.database;
+ 
+       this.model.destroy().then(function(resp) {
+         FauxtonAPI.addNotification({
+           msg: "Succesfully deleted your doc",
+           clear:  true
+         });
+         FauxtonAPI.navigate(database.url("index"));
+       }, function(resp) {
+         FauxtonAPI.addNotification({
+           msg: "Failed to delete your doc!",
+           type: "error",
+           clear:  true
+         });
+       });
+     },
+ 
+     beforeRender: function () {
+       this.uploadModal = this.setView('#upload-modal', new Views.UploadModal({model: this.model}));
+       this.uploadModal.render();
+ 
+       this.duplicateModal = this.setView('#duplicate-modal', new Views.DuplicateDocModal({model:
this.model}));
++
++      /* initialization is automatic - and make sure ONCE */
++      this.stringEditModal = this.stringEditModal || this.setView('#string-edit-modal',
new Views.StringEditModal());
++      /* this.stringEditModal.render(); */
+       this.duplicateModal.render();
+     },
+ 
+     upload: function (event) {
+       event.preventDefault();
+       if (this.model.isNewDoc()) {
+         FauxtonAPI.addNotification({
+           msg: 'Please save the document before uploading an attachment.',
+           type: 'warning',
+           clear:  true
+         });
+         return;
+       }
+       this.uploadModal.showModal();
+     },
+ 
+     duplicate: function(event) {
+       if (this.model.isNewDoc()) {
+         FauxtonAPI.addNotification({
+           msg: 'Please save the document before duplicating it.',
+           type: 'warning',
+           clear:  true
+         });
+         return;
+       }
+       event.preventDefault();
+       this.duplicateModal.showModal();
+     },
+ 
+     updateValues: function() {
+       if (this.model.changedAttributes()) {
+         FauxtonAPI.addNotification({
+           msg: "Document saved successfully.",
+           type: "success",
+           clear: true
+         });
+         this.editor.setValue(this.model.prettyJSON());
+       }
+     },
+ 
+     establish: function() {
+       var promise = this.model.fetch(),
+           databaseId = this.database.safeID(),
+           deferred = $.Deferred(),
+           that = this;
+ 
+       promise.then(function () {
+         deferred.resolve();
+       }, function (xhr, reason, msg) {
+         if (xhr.status === 404) {
+           FauxtonAPI.addNotification({
+             msg: 'The document does not exist',
+             type: 'error',
+             clear: true
+           });
+           that.goback();
+         }
+         deferred.reject();
+      });
+ 
+       return deferred;
+     },
+ 
+     saveDoc: function(event) {
+       var json,
+       that = this,
+       editor = this.editor,
+       validDoc = this.getDocFromEditor();
+ 
+       if (validDoc) {
+         this.getDocFromEditor();
+ 
+         FauxtonAPI.addNotification({msg: "Saving document."});
+ 
+         this.model.save().then(function () {
+           editor.editSaved();
+           FauxtonAPI.navigate('/database/' + that.database.safeID() + '/' + that.model.id);
+         }).fail(function(xhr) {
+           var responseText = JSON.parse(xhr.responseText).reason;
+           FauxtonAPI.addNotification({
+             msg: "Save failed: " + responseText,
+             type: "error",
+             fade: false,
+             clear: true,
+             selector: "#doc .errors-container"
+           });
+         });
+       } else if(this.model.validationError && this.model.validationError === 'Cannot
change a documents id.') {
+           FauxtonAPI.addNotification({
+             msg: "Cannot save: " + 'Cannot change a documents _id, try Duplicate doc instead!',
+             type: "error",
+             selector: "#doc .errors-container",
+             clear:  true
+           });
+         delete this.model.validationError;
+       } else {
+         FauxtonAPI.addNotification({
+           msg: "Please fix the JSON errors and try again.",
+           type: "error",
+           selector: "#doc .errors-container",
+           clear:  true
+         });
+       }
+     },
+ 
+     getDocFromEditor: function () {
+       var json;
+ 
+       if (!this.hasValidCode()) {
+         return false;
+       }
+ 
+       json = JSON.parse(this.editor.getValue());
+ 
+       this.model.clear().set(json, {validate: true});
+       if (this.model.validationError) {
+         return false;
+       }
+ 
+       return this.model;
+     },
+ 
+     hasValidCode: function() {
+       var errors = this.editor.getAnnotations();
+       return errors.length === 0;
+     },
+ 
+     serialize: function() {
+       return {
+         doc: this.model,
+         attachments: this.getAttachments()
+       };
+     },
+ 
+     getAttachments: function () {
+       var attachments = this.model.get('_attachments');
+ 
+       if (!attachments) { return false; }
+ 
+       return _.map(attachments, function (att, key) {
+         return {
+           fileName: key,
+           size: att.length,
+           contentType: att.content_type,
+           url: this.model.url() + '/' + app.utils.safeURLName(key)
+         };
+       }, this);
+     },
+ 
+     afterRender: function() {
+       var saveDoc = this.saveDoc,
+           editor,
+           model;
+ 
+       this.editor = new Components.Editor({
+         editorId: "editor-container",
+         forceMissingId: true,
+         commands: [{
+           name: 'save',
+           bindKey: {win: 'Ctrl-S',  mac: 'Ctrl-S'},
+           exec: function(editor) {
+             saveDoc();
+           },
+           readOnly: true // false if this command should not apply in readOnly mode
+         }]
+       });
+       this.editor.render();
+ 
+       editor = this.editor;
+       model = this.model;
+ 
+       this.listenTo(this.model, "sync", this.updateValues);
+       this.listenTo(editor.editor, "change", function (event) {
+         var changedDoc;
+         try {
+           changedDoc = JSON.parse(editor.getValue());
+         } catch(exception) {
+           //not complete doc. Cannot work with it
+           return;
+         }
+ 
+         var keyChecked = ["_id"];
+         if (model.get("_rev")) { keyChecked.push("_rev");}
+ 
+         //check the changedDoc has all the required standard keys
+         if (_.isEmpty(_.difference(keyChecked, _.keys(changedDoc)))) { return; }
+ 
+         editor.setReadOnly(true);
+         setTimeout(function () { editor.setReadOnly(false);}, 400);
+         // use extend so that _id stays at the top of the object with displaying the doc
+         changedDoc = _.extend({_id: model.id, _rev: model.get("_rev")}, changedDoc);
+         editor.setValue(JSON.stringify(changedDoc, null, "  "));
+         FauxtonAPI.addNotification({
+           type: "error",
+           msg: "Cannot remove a documents Id or Revision.",
+           clear:  true
+         });
+       });
++
++      var that = this;
++      this.listenTo(editor.editor, "changeSelection", function (event) {
++        that.showHideEditDocString(event);
++      });
++      this.listenTo(editor.editor.session, "changeBackMarker", function (event) {
++        that.showHideEditDocString(event);
++      });
+     },
+ 
+     cleanup: function () {
+       if (this.editor) this.editor.remove();
+     }
+   });
+ 
+   return Views;
+ });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/12f282c4/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --cc app/addons/fauxton/components.js
index f0dcc31,85f7b34..fc0f500
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@@ -419,9 -419,8 +419,11 @@@ function(app, FauxtonAPI, ace, spin) 
        this.setHeightToLineCount();
  
        this.editor.setTheme("ace/theme/" + this.theme);
+ 
 -      this.editor.getSession().setMode("ace/mode/" + this.mode);
 +      if (this.mode != "plain") {
 +        this.editor.getSession().setMode("ace/mode/" + this.mode);
 +      }
++      
        this.editor.setShowPrintMargin(false);
        this.addCommands();
  


Mime
View raw message