You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2014/07/25 11:04:02 UTC
[1/3] fauxton commit: updated refs/heads/master to d68bc8e
Repository: couchdb-fauxton
Updated Branches:
refs/heads/master 893e9881d -> d68bc8e4c
restore state of couchdb in couchdb-fauxon
automatically expand ace correctly
remove unnecessary resize, improve comments
have save warning right in principle
final brush-up
Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/b340f1dd
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/b340f1dd
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/b340f1dd
Branch: refs/heads/master
Commit: b340f1dd3b04e41c4bdc28d8a4e2d9524053a6f8
Parents: 99665a1
Author: sebastianrothbucher <se...@googlemail.com>
Authored: Mon Jul 14 23:08:18 2014 +0200
Committer: sebastianrothbucher <se...@googlemail.com>
Committed: Fri Jul 18 00:26:34 2014 +0200
----------------------------------------------------------------------
app/addons/documents/assets/less/documents.less | 24 ++++
app/addons/documents/templates/code_editor.html | 2 +
.../documents/templates/string_edit_modal.html | 30 +++++
app/addons/documents/views.js | 122 ++++++++++++++++++-
app/addons/fauxton/components.js | 48 +++++++-
5 files changed, 223 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b340f1dd/app/addons/documents/assets/less/documents.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/documents.less b/app/addons/documents/assets/less/documents.less
index e62be30..0537595 100644
--- a/app/addons/documents/assets/less/documents.less
+++ b/app/addons/documents/assets/less/documents.less
@@ -152,4 +152,28 @@ button.beautify {
}
}
+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%;
+}
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b340f1dd/app/addons/documents/templates/code_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/code_editor.html b/app/addons/documents/templates/code_editor.html
index 811e111..2198079 100644
--- a/app/addons/documents/templates/code_editor.html
+++ b/app/addons/documents/templates/code_editor.html
@@ -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>
<% if (attachments) { %>
<div class="btn-group">
<button class="dropdown-toggle btn" data-bypass="true" data-toggle="dropdown">
@@ -48,6 +49,7 @@ the License.
<div id="upload-modal"> </div>
<div id="duplicate-modal"> </div>
+<div id="string-edit-modal"> </div>
</div>
<div id="editor-container" class="doc-code"><%- JSON.stringify(doc.attributes, null, " ") %></div>
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b340f1dd/app/addons/documents/templates/string_edit_modal.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/string_edit_modal.html b/app/addons/documents/templates/string_edit_modal.html
new file mode 100644
index 0000000..1177795
--- /dev/null
+++ b/app/addons/documents/templates/string_edit_modal.html
@@ -0,0 +1,30 @@
+<!--
+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.
+-->
+
+<div class="modal hide fade">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+ <h3>Edit text <span id="string-edit-header"></span></h3>
+ </div>
+ <div class="modal-body">
+ <div id="modal-error" class="hide alert alert-error"/>
+ <div id="string-editor-wrapper"><div id="string-editor-container" class="doc-code"></div></div>
+ </div>
+ <div class="modal-footer">
+ <button data-dismiss="modal" class="btn"><i class="icon fonticon-circle-x"></i> Cancel</button>
+ <button id="string-edit-save-btn" class="btn btn-success save"><i class="fonticon-circle-check"></i> Save</button>
+ </div>
+</div>
+
+
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b340f1dd/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 6ccb733..9e397af 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -247,6 +247,62 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
}
});
+ 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();
+ }
+
+ });
+
Views.Document = FauxtonAPI.View.extend({
template: "addons/documents/templates/all_docs_item",
tagName: "tr",
@@ -751,7 +807,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
"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,
@@ -765,6 +822,57 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
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({
@@ -802,6 +910,10 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
this.duplicateModal = this.setView('#duplicate-modal', new Views.DuplicateDocModal({model: this.model}));
this.duplicateModal.render();
+
+ /* initialization is automatic - and make sure ONCE */
+ this.stringEditModal = this.stringEditModal || this.setView('#string-edit-modal', new Views.StringEditModal());
+ /* this.stringEditModal.render(); */
},
upload: function (event) {
@@ -999,6 +1111,14 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
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 () {
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b340f1dd/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index 79a9320..f0dcc31 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -419,8 +419,9 @@ 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();
@@ -529,6 +530,49 @@ function(app, FauxtonAPI, ace, spin) {
isIgnorableError: function(msg) {
return _.contains(this.excludedViewErrors, msg);
+ },
+
+ configureFixedHeightEditor: function(numLines) {
+ this.editor.renderer.setVScrollBarAlwaysVisible(true);
+ this.editor.renderer.setHScrollBarAlwaysVisible(true);
+ /* customize the ace scrolling for static edit height */
+ this.editor.renderer.$autosize = function() {
+ this.$size.height = numLines * this.lineHeight;
+ this.desiredHeight = numLines * this.lineHeight;
+ this.container.style.height = this.desiredHeight + "px";
+ this.scrollBarV.setVisible(true);
+ this.scrollBarH.setVisible(true);
+ };
+ },
+
+ replaceCurrentLine: function(replacement) {
+ this.editor.getSelection().selectLine();
+ this.editor.insert(replacement);
+ this.editor.getSelection().moveCursorUp();
+ },
+
+ getLine: function(lineNum) {
+ return this.editor.session.getLine(lineNum);
+ },
+
+ getSelectionStart: function() {
+ return this.editor.getSelectionRange().start;
+ },
+
+ getSelectionEnd: function() {
+ return this.editor.getSelectionRange().end;
+ },
+
+ getRowHeight: function() {
+ return this.editor.renderer.layerConfig.lineHeight;
+ },
+
+ isRowExpanded: function(row) {
+ return !this.editor.getSession().isRowFolded(row);
+ },
+
+ documentToScreenRow: function(row) {
+ return this.editor.getSession().documentToScreenRow(row, 0);
}
});
[3/3] fauxton commit: updated refs/heads/master to d68bc8e
Posted by ga...@apache.org.
Fine tune string edit.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/d68bc8e4
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/d68bc8e4
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/d68bc8e4
Branch: refs/heads/master
Commit: d68bc8e4c6c72118f8679f82651b04216b3afae6
Parents: 12f282c
Author: sebastianrothbucher <se...@googlemail.com>
Authored: Thu Jul 24 23:00:06 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Fri Jul 25 09:55:05 2014 +0200
----------------------------------------------------------------------
app/addons/documents/views-doceditor.js | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/d68bc8e4/app/addons/documents/views-doceditor.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-doceditor.js b/app/addons/documents/views-doceditor.js
index 5514bd2..e05b8f4 100644
--- a/app/addons/documents/views-doceditor.js
+++ b/app/addons/documents/views-doceditor.js
@@ -252,8 +252,9 @@ function(app, FauxtonAPI, Components, Documents, Databases,
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");
+ /* remove the following line (along with CSS) to go back to the toolbar: take the offset top of the editor, go down as many lines as we are positioned including fold and adjust by two pixels as the button is slightly larger than a line */
+ var positionFromTop = (this.$("#editor-container").offset().top - 2 + this.editor.getRowHeight() * this.editor.documentToScreenRow(this.editor.getSelectionStart().row));
+ this.$("button.string-edit").css("top", positionFromTop + "px");
return true;
}
return false;
[2/3] fauxton commit: updated refs/heads/master to d68bc8e
Posted by ga...@apache.org.
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 <se...@googlemail.com>
Authored: Thu Jul 24 22:50:48 2014 +0200
Committer: sebastianrothbucher <se...@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();