You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by de...@apache.org on 2014/07/23 21:00:18 UTC
[1/2] Changed how these files are named so it's easier to read in the
addon folders
Repository: couchdb-fauxton
Updated Branches:
refs/heads/master f978779e9 -> 893e9881d
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views-index.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-index.js b/app/addons/documents/views-index.js
new file mode 100644
index 0000000..d0ed8ed
--- /dev/null
+++ b/app/addons/documents/views-index.js
@@ -0,0 +1,574 @@
+// 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",
+ "addons/pouchdb/base",
+ //views
+ "addons/documents/views-advancedopts",
+ // Libs
+ "addons/fauxton/resizeColumns",
+
+ // Plugins
+ "plugins/beautify",
+ "plugins/prettify"
+],
+
+function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
+ QueryOptions, resizeColumns, beautify, prettify) {
+
+ var Views = {};
+
+ Views.ViewEditor = FauxtonAPI.View.extend({
+ template: "addons/documents/templates/view_editor",
+ builtinReduces: ['_sum', '_count', '_stats'],
+
+ events: {
+ "click button.save": "saveView",
+ "click button.delete": "deleteView",
+ "change select#reduce-function-selector": "updateReduce",
+ "click button.preview": "previewView",
+ "click #db-views-tabs-nav": 'toggleIndexNav',
+ "click .beautify_map": "beautifyCode",
+ "click .beautify_reduce": "beautifyCode",
+ "click #query-options-wrapper": 'toggleIndexNav'
+ },
+
+ langTemplates: {
+ "javascript": {
+ map: "function(doc) {\n emit(doc._id, 1);\n}",
+ reduce: "function(keys, values, rereduce){\n if (rereduce){\n return sum(values);\n } else {\n return values.length;\n }\n}"
+ }
+ },
+
+ defaultLang: "javascript",
+
+ initialize: function(options) {
+ this.newView = options.newView || false;
+ this.ddocs = options.ddocs;
+ this.params = options.params;
+ this.database = options.database;
+ this.currentDdoc = options.currentddoc;
+ if (this.newView) {
+ this.viewName = 'newView';
+ } else {
+ this.ddocID = options.ddocInfo.id;
+ this.viewName = options.viewName;
+ this.ddocInfo = new Documents.DdocInfo({_id: this.ddocID},{database: this.database});
+ }
+
+ this.showIndex = false;
+ _.bindAll(this);
+ },
+
+ establish: function () {
+ if (this.ddocInfo) {
+ return this.ddocInfo.fetch();
+ }
+ },
+
+ updateValues: function() {
+ var notification;
+ if (this.model.changedAttributes()) {
+ notification = FauxtonAPI.addNotification({
+ msg: "Document saved successfully.",
+ type: "success",
+ clear: true
+ });
+ this.editor.setValue(this.model.prettyJSON());
+ }
+ },
+
+ updateReduce: function(event) {
+ var $ele = $("#reduce-function-selector");
+ var $reduceContainer = $(".control-group.reduce-function");
+ if ($ele.val() == "CUSTOM") {
+ this.createReduceEditor();
+ this.reduceEditor.setValue(this.langTemplates.javascript.reduce);
+ $reduceContainer.show();
+ } else {
+ $reduceContainer.hide();
+ }
+ },
+
+ deleteView: function (event) {
+ event.preventDefault();
+
+ if (this.newView) { return alert('Cannot delete a new view.'); }
+ if (!confirm('Are you sure you want to delete this view?')) {return;}
+
+ var that = this,
+ promise,
+ viewName = this.$('#index-name').val(),
+ ddocName = this.$('#ddoc :selected').val(),
+ ddoc = this.getCurrentDesignDoc();
+
+ ddoc.removeDdocView(viewName);
+
+ if (ddoc.hasViews()) {
+ promise = ddoc.save();
+ } else {
+ promise = ddoc.destroy();
+ }
+
+ promise.then(function () {
+ FauxtonAPI.navigate('/database/' + that.database.safeID() + '/_all_docs?limit=' + Databases.DocLimit);
+ FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
+ });
+ },
+
+ saveView: function(event) {
+ var json, notification,
+ that = this;
+
+ if (event) { event.preventDefault();}
+
+ $('#dashboard-content').scrollTop(0); //scroll up
+
+ if (this.hasValidCode() && this.$('#new-ddoc:visible').val() !=="") {
+ var mapVal = this.mapEditor.getValue(),
+ reduceVal = this.reduceVal(),
+ viewName = this.$('#index-name').val(),
+ ddoc = this.getCurrentDesignDoc(),
+ ddocName = ddoc.id,
+ viewNameChange = false;
+
+ if (this.viewName !== viewName) {
+ ddoc.removeDdocView(this.viewName);
+ this.viewName = viewName;
+ viewNameChange = true;
+ }
+
+ notification = FauxtonAPI.addNotification({
+ msg: "Saving document.",
+ selector: "#define-view .errors-container",
+ clear: true
+ });
+
+ ddoc.setDdocView(viewName, mapVal, reduceVal);
+
+ ddoc.save().then(function () {
+ that.ddocs.add(ddoc);
+
+ that.mapEditor.editSaved();
+ that.reduceEditor && that.reduceEditor.editSaved();
+
+
+ FauxtonAPI.addNotification({
+ msg: "View has been saved.",
+ type: "success",
+ selector: "#define-view .errors-container",
+ clear: true
+ });
+
+ if (that.newView || viewNameChange) {
+ var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName);
+
+ FauxtonAPI.navigate(fragment, {trigger: false});
+ that.newView = false;
+ that.ddocID = ddoc.safeID();
+ that.viewName = viewName;
+ that.ddocInfo = ddoc;
+ that.showIndex = true;
+ that.render();
+ FauxtonAPI.triggerRouteEvent('reloadDesignDocs', {
+ selectedTab: app.utils.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.utils.removeSpecialCharacters(viewName)
+ });
+ }
+
+ if (that.reduceFunStr !== reduceVal) {
+ that.reduceFunStr = reduceVal;
+ that.advancedOptions.renderOnUpdatehasReduce(that.hasReduce());
+ }
+
+ FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: ddocName, view: viewName});
+
+ }, function(xhr) {
+ var responseText = JSON.parse(xhr.responseText).reason;
+ notification = FauxtonAPI.addNotification({
+ msg: "Save failed: " + responseText,
+ type: "error",
+ clear: true
+ });
+ });
+ } else {
+ var errormessage = (this.$('#new-ddoc:visible').val() ==="")?"Enter a design doc name":"Please fix the Javascript errors and try again.";
+ notification = FauxtonAPI.addNotification({
+ msg: errormessage,
+ type: "error",
+ selector: "#define-view .errors-container",
+ clear: true
+ });
+ }
+ },
+
+ updateView: function(event, paramInfo) {
+ event.preventDefault();
+
+ if (this.newView) { return alert('Please save this new view before querying it.'); }
+
+ var errorParams = paramInfo.errorParams,
+ params = paramInfo.params;
+
+ if (_.any(errorParams)) {
+ _.map(errorParams, function(param) {
+
+ // TODO: Where to add this error?
+ // bootstrap wants the error on a control-group div, but we're not using that
+ //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
+ return FauxtonAPI.addNotification({
+ msg: "JSON Parse Error on field: "+param.name,
+ type: "error",
+ selector: ".advanced-options .errors-container",
+ clear: true
+ });
+ });
+ FauxtonAPI.addNotification({
+ msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
+ type: "warning",
+ selector: ".advanced-options .errors-container",
+ clear: true
+ });
+
+ return false;
+ }
+
+ var fragment = window.location.hash.replace(/\?.*$/, '');
+ if (!_.isEmpty(params)) {
+ fragment = fragment + '?' + $.param(params);
+ }
+
+ FauxtonAPI.navigate(fragment, {trigger: false});
+ FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: this.ddocID, view: this.viewName});
+ },
+
+
+ previewView: function(event, paramsInfo) {
+ event.preventDefault();
+ var that = this,
+ mapVal = this.mapVal(),
+ reduceVal = this.reduceVal(),
+ paramsArr = [];
+
+ if (paramsInfo && paramsInfo.params) {
+ paramsArr = paramsInfo.params;
+ }
+
+ var params = _.reduce(paramsArr, function (params, param) {
+ params[param.name] = param.value;
+ return params;
+ }, {reduce: false});
+
+ FauxtonAPI.addNotification({
+ msg: "<strong>Warning!</strong> Preview executes the Map/Reduce functions in your browser, and may behave differently from CouchDB.",
+ type: "warning",
+ selector: ".advanced-options .errors-container",
+ fade: true,
+ escape: false // beware of possible XSS when the message changes
+ });
+
+ var promise = FauxtonAPI.Deferred();
+
+ if (!this.database.allDocs || this.database.allDocs.params.include_docs !== true) {
+ this.database.buildAllDocs({limit: Databases.DocLimit.toString(), include_docs: true});
+ promise = this.database.allDocs.fetch();
+ } else {
+ promise.resolve();
+ }
+
+ promise.then(function () {
+ params.docs = that.database.allDocs.map(function (model) { return model.get('doc');});
+ var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
+ queryPromise.then(function (results) {
+ FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});
+ });
+ });
+ },
+
+ getCurrentDesignDoc: function () {
+ return this.designDocSelector.getCurrentDesignDoc();
+ },
+
+ isCustomReduceEnabled: function() {
+ return $("#reduce-function-selector").val() == "CUSTOM";
+ },
+
+ mapVal: function () {
+ if (this.mapEditor) {
+ return this.mapEditor.getValue();
+ }
+
+ return this.$('#map-function').text();
+ },
+
+ reduceVal: function() {
+ var reduceOption = this.$('#reduce-function-selector :selected').val(),
+ reduceVal = "";
+
+ if (reduceOption === 'CUSTOM') {
+ if (!this.reduceEditor) { this.createReduceEditor(); }
+ reduceVal = this.reduceEditor.getValue();
+ } else if ( reduceOption !== 'NONE') {
+ reduceVal = reduceOption;
+ }
+
+ return reduceVal;
+ },
+
+
+ hasValidCode: function() {
+ return _.every(["mapEditor", "reduceEditor"], function(editorName) {
+ var editor = this[editorName];
+ if (editorName === "reduceEditor" && ! this.isCustomReduceEnabled()) {
+ return true;
+ }
+ return editor.hadValidCode();
+ }, this);
+ },
+
+ toggleIndexNav: function (event) {
+ $('#dashboard-content').scrollTop(0); //scroll up
+
+ var $targetId = this.$(event.target).attr('id'),
+ $previousTab = this.$(this.$('li.active a').attr('href')),
+ $targetTab = this.$(this.$(event.target).attr('href'));
+
+ if ($targetTab.attr('id') !== $previousTab.attr('id')) {
+ $previousTab.removeAttr('style');
+ }
+
+ if ($targetId === 'index-nav') {
+ if (this.newView) { return; }
+ var that = this;
+ $('#dashboard-content').scrollTop(0); //scroll up
+ $targetTab.toggle('slow', function(){
+ that.showEditors();
+ });
+ } else {
+ $targetTab.toggle('slow');
+ }
+ },
+
+ serialize: function() {
+ return {
+ ddocs: this.ddocs,
+ ddoc: this.model,
+ ddocName: this.model.id,
+ viewName: this.viewName,
+ reduceFunStr: this.reduceFunStr,
+ isCustomReduce: this.hasCustomReduce(),
+ newView: this.newView,
+ langTemplates: this.langTemplates.javascript
+ };
+ },
+
+ hasCustomReduce: function() {
+ return this.reduceFunStr && ! _.contains(this.builtinReduces, this.reduceFunStr);
+ },
+
+ hasReduce: function () {
+ return this.reduceFunStr || false;
+ },
+
+ createReduceEditor: function () {
+ if (this.reduceEditor) {
+ this.reduceEditor.remove();
+ }
+
+ this.reduceEditor = new Components.Editor({
+ editorId: "reduce-function",
+ mode: "javascript",
+ couchJSHINT: true
+ });
+ this.reduceEditor.render();
+
+ if (this.reduceEditor.getLines() === 1){
+ this.$('.beautify_reduce').removeClass("hide");
+ $('.beautify-tooltip').tooltip();
+ }
+ },
+ beforeRender: function () {
+
+ if (this.newView) {
+ this.reduceFunStr = '';
+ if (this.ddocs.length === 0) {
+ this.model = new Documents.Doc(null, {database: this.database});
+ } else {
+ this.model = this.ddocs.first().dDocModel();
+ }
+ this.ddocID = this.model.id;
+ } else {
+ var ddocDecode = decodeURIComponent(this.ddocID);
+ this.model = this.ddocs.get(this.ddocID).dDocModel();
+ this.reduceFunStr = this.model.viewHasReduce(this.viewName);
+ }
+
+ var viewFilters = FauxtonAPI.getExtensions('sidebar:viewFilters'),
+ filteredModels = this.ddocs.models,
+ designDocs = this.ddocs.clone();
+
+ if (!_.isEmpty(viewFilters)) {
+ _.each(viewFilters, function (filter) {
+ filteredModels = _.filter(filteredModels, filter);
+ });
+ designDocs.reset(filteredModels, {silent: true});
+ }
+
+ this.designDocSelector = this.setView('.design-doc-group', new Views.DesignDocSelector({
+ collection: designDocs,
+ ddocName: this.currentDdoc || this.model.id,
+ database: this.database
+ }));
+
+ if (!this.newView) {
+ this.eventer = _.extend({}, Backbone.Events);
+
+ this.advancedOptions = this.insertView('#query', new QueryOptions.AdvancedOptions({
+ updateViewFn: this.updateView,
+ previewFn: this.previewView,
+ database: this.database,
+ viewName: this.viewName,
+ ddocName: this.model.id,
+ hasReduce: this.hasReduce(),
+ eventer: this.eventer,
+ showStale: true
+ }));
+ }
+
+ },
+
+ afterRender: function() {
+
+ if (this.params && !this.newView) {
+ this.advancedOptions.updateFromParams(this.params);
+ }
+
+ this.designDocSelector.updateDesignDoc();
+ if (this.newView || this.showIndex) {
+ this.showEditors();
+ this.showIndex = false;
+ } else {
+ this.$('#index').hide();
+ this.$('#index-nav').parent().removeClass('active');
+ }
+
+ },
+
+ showEditors: function () {
+ this.mapEditor = new Components.Editor({
+ editorId: "map-function",
+ mode: "javascript",
+ couchJSHINT: true
+ });
+ this.mapEditor.render();
+
+ if (this.hasCustomReduce()) {
+ this.createReduceEditor();
+ } else {
+ $(".control-group.reduce-function").hide();
+ }
+
+ if (this.newView) {
+ this.mapEditor.setValue(this.langTemplates[this.defaultLang].map);
+ //Use a built in view by default
+ //this.reduceEditor.setValue(this.langTemplates[this.defaultLang].reduce);
+ }
+
+ this.mapEditor.editSaved();
+ this.reduceEditor && this.reduceEditor.editSaved();
+
+ if (this.mapEditor.getLines() === 1){
+ this.$('.beautify_map').removeClass("hide");
+ $('.beautify-tooltip').tooltip();
+ }
+ },
+ beautifyCode: function(e){
+ e.preventDefault();
+ var targetEditor = $(e.currentTarget).hasClass('beautify_reduce')?this.reduceEditor:this.mapEditor;
+ var beautifiedCode = beautify(targetEditor.getValue());
+ targetEditor.setValue(beautifiedCode);
+ },
+ cleanup: function () {
+ this.mapEditor && this.mapEditor.remove();
+ this.reduceEditor && this.reduceEditor.remove();
+ }
+ });
+
+ Views.DesignDocSelector = FauxtonAPI.View.extend({
+ template: "addons/documents/templates/design_doc_selector",
+
+ events: {
+ "change select#ddoc": "updateDesignDoc"
+ },
+
+ initialize: function (options) {
+ this.ddocName = options.ddocName;
+ this.database = options.database;
+ this.listenTo(this.collection, 'add', this.ddocAdded);
+ this.DocModel = options.DocModel || Documents.Doc;
+ },
+
+ ddocAdded: function (ddoc) {
+ this.ddocName = ddoc.id;
+ this.render();
+ },
+
+ serialize: function () {
+ return {
+ ddocName: this.ddocName,
+ ddocs: this.collection
+ };
+ },
+
+ updateDesignDoc: function () {
+ if (this.newDesignDoc()) {
+ this.$('#new-ddoc-section').show();
+ } else {
+ this.$('#new-ddoc-section').hide();
+ }
+ },
+
+ newDesignDoc: function () {
+
+ return this.$('#ddoc').val() === 'new-doc';
+ },
+
+ newDocValidation: function(){
+ return this.newDesignDoc() && this.$('#new-ddoc').val()==="";
+ },
+ getCurrentDesignDoc: function () {
+ if (this.newDesignDoc()) {
+ var doc = {
+ _id: '_design/' + this.$('#new-ddoc').val(),
+ views: {},
+ language: "javascript"
+ };
+ var ddoc = new this.DocModel(doc, {database: this.database});
+ //this.collection.add(ddoc);
+ return ddoc;
+ } else if ( !this.newDesignDoc() ) {
+ var ddocName = this.$('#ddoc').val();
+ return this.collection.find(function (ddoc) {
+ return ddoc.id === ddocName;
+ }).dDocModel();
+ }
+ }
+ });
+
+ return Views;
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views-sidebar.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-sidebar.js b/app/addons/documents/views-sidebar.js
new file mode 100644
index 0000000..e3cc629
--- /dev/null
+++ b/app/addons/documents/views-sidebar.js
@@ -0,0 +1,253 @@
+// 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"
+],
+
+function(app, FauxtonAPI, Components, Documents, Databases) {
+ var Views = {};
+
+ Views.Sidebar = FauxtonAPI.View.extend({
+ template: "addons/documents/templates/sidebar",
+ className: "sidenav",
+ tagName: "nav",
+ events: {
+ "click button#delete-database": "showDeleteDatabaseModal"
+ },
+
+ initialize: function(options) {
+ this.database = options.database;
+ if (options.ddocInfo) {
+ this.ddocID = options.ddocInfo.id;
+ this.currView = options.ddocInfo.currView;
+ }
+ },
+ showDeleteDatabaseModal: function(event){
+ this.deleteDBModal.showModal();
+ },
+
+ serialize: function() {
+ var docLinks = FauxtonAPI.getExtensions('docLinks'),
+ newLinks = FauxtonAPI.getExtensions('sidebar:newLinks'),
+ addLinks = FauxtonAPI.getExtensions('sidebar:links'),
+ extensionList = FauxtonAPI.getExtensions('sidebar:list');
+ return {
+ changes_url: '#' + this.database.url('changes'),
+ permissions_url: '#' + this.database.url('app') + '/permissions',
+ db_url: '#' + this.database.url('index'),
+ database: this.collection.database,
+ database_url: '#' + this.database.url('app'),
+ docLinks: docLinks,
+ addLinks: addLinks,
+ newLinks: newLinks,
+ extensionList: extensionList > 0
+ };
+ },
+
+
+ beforeRender: function(manage) {
+ this.deleteDBModal = this.setView(
+ '#delete-db-modal',
+ new Views.DeleteDBModal({database: this.database})
+ );
+
+ var database = this.collection.database,
+ newurl = "#" + database.url('app') + '/new';
+
+ var newLinks = [{
+ title: 'Add new',
+ links: [{
+ title: 'New Doc',
+ url: newurl,
+ icon: 'fonticon-plus-circled'
+ },{
+ title: 'New Design Doc',
+ url: newurl,
+ icon: 'fonticon-plus-circled'
+ }]
+ }];
+
+ this.insertView("#new-all-docs-button", new Components.MenuDropDown({
+ links: newLinks,
+ }));
+
+ this.insertView("#new-design-docs-button", new Components.MenuDropDown({
+ links: newLinks,
+ }));
+
+ this.collection.each(function(design) {
+ if (design.has('doc')){
+ this.insertView(new Views.DdocSidenav({
+ model: design,
+ collection: this.collection
+ }));
+ }
+ },this);
+ },
+
+ afterRender: function () {
+ if (this.selectedTab) {
+ this.setSelectedTab(this.selectedTab);
+ }
+ },
+
+ setSelectedTab: function (selectedTab) {
+ this.selectedTab = selectedTab;
+ var $selectedTab = this.$('#' + selectedTab);
+
+ this.$('li').removeClass('active');
+ $selectedTab.parent().addClass('active');
+
+ if ($selectedTab.parents(".accordion-body").length !== 0){
+ $selectedTab
+ .parents(".accordion-body")
+ .addClass("in")
+ .parents(".nav-header")
+ .find(">.js-collapse-toggle").addClass("down");
+
+ this.$('.js-toggle-' + $selectedTab.data('ddoctype')).addClass("down");
+ }
+ }
+ });
+
+ Views.DdocSidenav = FauxtonAPI.View.extend({
+ tagName: "ul",
+ className: "nav nav-list",
+ template: "addons/documents/templates/design_doc_menu",
+ events: {
+ "click .js-collapse-toggle": "toggleArrow"
+ },
+
+ toggleArrow: function(e){
+ this.$(e.currentTarget).toggleClass("down");
+ },
+ buildIndexList: function(collection, selector, ddocType){
+ var design = this.model.id.replace(/^_design\//,"");
+
+ this.insertView(".accordion-body", new Views.IndexItem({
+ selector: selector,
+ ddoc: design,
+ collection: collection[selector],
+ ddocType: ddocType,
+ database: this.model.collection.database.id
+ }));
+ },
+
+ serialize: function(){
+ var ddocName = this.model.id.replace(/^_design\//,"");
+ return{
+ database: this.collection.database,
+ designDoc: ddocName,
+ ddoc_clean: app.utils.removeSpecialCharacters(ddocName),
+ ddoc_encoded: app.utils.safeURLName(ddocName),
+ database_encoded: app.utils.safeURLName(this.model.collection.database.id),
+ };
+ },
+
+ getSidebarLinks: function () {
+ var ddocName = this.model.id.replace(/^_design\//,""),
+ docSafe = app.utils.safeURLName(ddocName),
+ database = this.collection.database;
+
+ return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
+
+ menuLinks.push({
+ title: link.title,
+ url: "#" + database.url('app') + "/" + link.url + "/" + docSafe,
+ icon: 'fonticon-plus-circled'
+ });
+
+ return menuLinks;
+ }, [{
+ title: 'Secondary View',
+ url: "#" + database.url('app') + "/new_view/" + docSafe,
+ icon: 'fonticon-plus-circled'
+ }]);
+
+ },
+
+ renderIndexLists: function () {
+ var ddocDocs = this.model.get("doc"),
+ sidebarListTypes = FauxtonAPI.getExtensions('sidebar:list');
+
+ if (!ddocDocs){ return; }
+
+ this.buildIndexList(ddocDocs, "views", "view");
+ _.each(sidebarListTypes, function (type) {
+ this.buildIndexList(ddocDocs, type);
+ },this);
+
+ },
+
+ beforeRender: function(manage) {
+ var sideBarMenuLinks = [];
+
+ sideBarMenuLinks.push({
+ title: 'Add new',
+ links: this.getSidebarLinks()
+ });
+
+ this.renderIndexLists();
+ this.insertView(".new-button", new Components.MenuDropDown({
+ links: sideBarMenuLinks,
+ }));
+ }
+ });
+
+ Views.IndexItem = FauxtonAPI.View.extend({
+ template: "addons/documents/templates/index_menu_item",
+ tagName: 'li',
+
+ initialize: function(options){
+ this.index = options.index;
+ this.ddoc = options.ddoc;
+ this.database = options.database;
+ this.selected = !! options.selected;
+ this.selector = options.selector;
+ this.ddocType = options.ddocType || this.selector;
+ this.icons = {
+ "view": "fonticon-sidenav-map-reduce",
+ "indexes": "fonticon-sidenav-search"
+ };
+
+ },
+
+ serialize: function() {
+ return {
+ icon: this.icons[this.ddocType],
+ ddocType: this.ddocType,
+ index: this.index,
+ ddoc: this.ddoc,
+ database: this.database,
+ selected: this.selected,
+ collection: this.collection
+ };
+ },
+
+ afterRender: function() {
+ if (this.selected) {
+ $(".sidenav ul.nav-list li").removeClass("active");
+ this.$el.addClass("active");
+ }
+ }
+ });
+
+ return Views;
+});
+
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 66305ec..b68df87 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -19,8 +19,8 @@ define([
"addons/databases/resources",
//Views
- "addons/documents/sidebarviews",
- "addons/documents/queryoptionviews",
+ "addons/documents/views-sidebar",
+ "addons/documents/views-advancedopts",
// Libs
"addons/fauxton/resizeColumns",
//plugins
[2/2] fauxton commit: updated refs/heads/master to 893e988
Posted by de...@apache.org.
Changed how these files are named so it's easier to read in the addon folders
Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/893e9881
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/893e9881
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/893e9881
Branch: refs/heads/master
Commit: 893e9881d789f3b8c621bd6148130e1327cde638
Parents: f978779
Author: deathbearbrown <de...@gmail.com>
Authored: Wed Jul 23 14:41:23 2014 -0400
Committer: deathbearbrown <de...@gmail.com>
Committed: Wed Jul 23 14:41:23 2014 -0400
----------------------------------------------------------------------
app/addons/documents/changesviews.js | 84 ----
app/addons/documents/doceditorviews.js | 416 -----------------
app/addons/documents/indexviews.js | 574 ------------------------
app/addons/documents/queryoptionviews.js | 270 -----------
app/addons/documents/routes.js | 6 +-
app/addons/documents/sidebarviews.js | 253 -----------
app/addons/documents/views-advancedopts.js | 270 +++++++++++
app/addons/documents/views-changes.js | 84 ++++
app/addons/documents/views-doceditor.js | 416 +++++++++++++++++
app/addons/documents/views-index.js | 574 ++++++++++++++++++++++++
app/addons/documents/views-sidebar.js | 253 +++++++++++
app/addons/documents/views.js | 4 +-
12 files changed, 1602 insertions(+), 1602 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/changesviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/changesviews.js b/app/addons/documents/changesviews.js
deleted file mode 100644
index 2f91c21..0000000
--- a/app/addons/documents/changesviews.js
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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",
- // Libs
- "addons/fauxton/resizeColumns",
-
- // Plugins
- "plugins/prettify",
- // this should never be global available:
- // https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/security.md
- "plugins/zeroclipboard/ZeroClipboard"
-],
-
-function(app, FauxtonAPI, resizeColumns, prettify, ZeroClipboard) {
-
- var Views = {};
-
- Views.Changes = FauxtonAPI.View.extend({
- template: "addons/documents/templates/changes",
-
- initialize: function () {
- this.listenTo( this.model.changes, 'sync', this.render);
- this.listenTo( this.model.changes, 'cachesync', this.render);
- },
-
- events: {
- "click button.js-toggle-json": "toggleJson"
- },
-
- toggleJson: function(event) {
- event.preventDefault();
-
- var $button = this.$(event.target),
- $container = $button.closest('.change-box').find(".js-json-container");
-
- if (!$container.is(":visible")) {
- $button
- .text("Close JSON")
- .addClass("btn-secondary")
- .removeClass("btn-primary");
- } else {
- $button.text("View JSON")
- .addClass("btn-primary")
- .removeClass("btn-secondary");
- }
-
- $container.slideToggle();
- },
-
- establish: function() {
- return [ this.model.changes.fetchOnce({prefill: true})];
- },
-
- serialize: function () {
- return {
- changes: this.model.changes.toJSON(),
- database: this.model
- };
- },
-
- afterRender: function(){
- prettyPrint();
- ZeroClipboard.config({ moviePath: "/assets/js/plugins/zeroclipboard/ZeroClipboard.swf" });
- var client = new ZeroClipboard(this.$(".js-copy"));
- }
- });
-
-
-
- return Views;
-});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/doceditorviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/doceditorviews.js b/app/addons/documents/doceditorviews.js
deleted file mode 100644
index add8d8c..0000000
--- a/app/addons/documents/doceditorviews.js
+++ /dev/null
@@ -1,416 +0,0 @@
-// 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');
- }
- });
-
-
-
- /* 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"
- },
-
- disableLoader: true,
-
- initialize: function (options) {
- this.database = options.database;
- _.bindAll(this);
- },
-
- goback: function(){
- FauxtonAPI.navigate(this.database.url("index") + "?limit=100");
- },
-
- 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}));
- 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
- });
- });
- },
-
- cleanup: function () {
- if (this.editor) this.editor.remove();
- }
- });
-
- return Views;
-});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/indexviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/indexviews.js b/app/addons/documents/indexviews.js
deleted file mode 100644
index df8c10d..0000000
--- a/app/addons/documents/indexviews.js
+++ /dev/null
@@ -1,574 +0,0 @@
-// 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",
- "addons/pouchdb/base",
- //views
- "addons/documents/queryoptionviews",
- // Libs
- "addons/fauxton/resizeColumns",
-
- // Plugins
- "plugins/beautify",
- "plugins/prettify"
-],
-
-function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
- QueryOptions, resizeColumns, beautify, prettify) {
-
- var Views = {};
-
- Views.ViewEditor = FauxtonAPI.View.extend({
- template: "addons/documents/templates/view_editor",
- builtinReduces: ['_sum', '_count', '_stats'],
-
- events: {
- "click button.save": "saveView",
- "click button.delete": "deleteView",
- "change select#reduce-function-selector": "updateReduce",
- "click button.preview": "previewView",
- "click #db-views-tabs-nav": 'toggleIndexNav',
- "click .beautify_map": "beautifyCode",
- "click .beautify_reduce": "beautifyCode",
- "click #query-options-wrapper": 'toggleIndexNav'
- },
-
- langTemplates: {
- "javascript": {
- map: "function(doc) {\n emit(doc._id, 1);\n}",
- reduce: "function(keys, values, rereduce){\n if (rereduce){\n return sum(values);\n } else {\n return values.length;\n }\n}"
- }
- },
-
- defaultLang: "javascript",
-
- initialize: function(options) {
- this.newView = options.newView || false;
- this.ddocs = options.ddocs;
- this.params = options.params;
- this.database = options.database;
- this.currentDdoc = options.currentddoc;
- if (this.newView) {
- this.viewName = 'newView';
- } else {
- this.ddocID = options.ddocInfo.id;
- this.viewName = options.viewName;
- this.ddocInfo = new Documents.DdocInfo({_id: this.ddocID},{database: this.database});
- }
-
- this.showIndex = false;
- _.bindAll(this);
- },
-
- establish: function () {
- if (this.ddocInfo) {
- return this.ddocInfo.fetch();
- }
- },
-
- updateValues: function() {
- var notification;
- if (this.model.changedAttributes()) {
- notification = FauxtonAPI.addNotification({
- msg: "Document saved successfully.",
- type: "success",
- clear: true
- });
- this.editor.setValue(this.model.prettyJSON());
- }
- },
-
- updateReduce: function(event) {
- var $ele = $("#reduce-function-selector");
- var $reduceContainer = $(".control-group.reduce-function");
- if ($ele.val() == "CUSTOM") {
- this.createReduceEditor();
- this.reduceEditor.setValue(this.langTemplates.javascript.reduce);
- $reduceContainer.show();
- } else {
- $reduceContainer.hide();
- }
- },
-
- deleteView: function (event) {
- event.preventDefault();
-
- if (this.newView) { return alert('Cannot delete a new view.'); }
- if (!confirm('Are you sure you want to delete this view?')) {return;}
-
- var that = this,
- promise,
- viewName = this.$('#index-name').val(),
- ddocName = this.$('#ddoc :selected').val(),
- ddoc = this.getCurrentDesignDoc();
-
- ddoc.removeDdocView(viewName);
-
- if (ddoc.hasViews()) {
- promise = ddoc.save();
- } else {
- promise = ddoc.destroy();
- }
-
- promise.then(function () {
- FauxtonAPI.navigate('/database/' + that.database.safeID() + '/_all_docs?limit=' + Databases.DocLimit);
- FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
- });
- },
-
- saveView: function(event) {
- var json, notification,
- that = this;
-
- if (event) { event.preventDefault();}
-
- $('#dashboard-content').scrollTop(0); //scroll up
-
- if (this.hasValidCode() && this.$('#new-ddoc:visible').val() !=="") {
- var mapVal = this.mapEditor.getValue(),
- reduceVal = this.reduceVal(),
- viewName = this.$('#index-name').val(),
- ddoc = this.getCurrentDesignDoc(),
- ddocName = ddoc.id,
- viewNameChange = false;
-
- if (this.viewName !== viewName) {
- ddoc.removeDdocView(this.viewName);
- this.viewName = viewName;
- viewNameChange = true;
- }
-
- notification = FauxtonAPI.addNotification({
- msg: "Saving document.",
- selector: "#define-view .errors-container",
- clear: true
- });
-
- ddoc.setDdocView(viewName, mapVal, reduceVal);
-
- ddoc.save().then(function () {
- that.ddocs.add(ddoc);
-
- that.mapEditor.editSaved();
- that.reduceEditor && that.reduceEditor.editSaved();
-
-
- FauxtonAPI.addNotification({
- msg: "View has been saved.",
- type: "success",
- selector: "#define-view .errors-container",
- clear: true
- });
-
- if (that.newView || viewNameChange) {
- var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName);
-
- FauxtonAPI.navigate(fragment, {trigger: false});
- that.newView = false;
- that.ddocID = ddoc.safeID();
- that.viewName = viewName;
- that.ddocInfo = ddoc;
- that.showIndex = true;
- that.render();
- FauxtonAPI.triggerRouteEvent('reloadDesignDocs', {
- selectedTab: app.utils.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.utils.removeSpecialCharacters(viewName)
- });
- }
-
- if (that.reduceFunStr !== reduceVal) {
- that.reduceFunStr = reduceVal;
- that.advancedOptions.renderOnUpdatehasReduce(that.hasReduce());
- }
-
- FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: ddocName, view: viewName});
-
- }, function(xhr) {
- var responseText = JSON.parse(xhr.responseText).reason;
- notification = FauxtonAPI.addNotification({
- msg: "Save failed: " + responseText,
- type: "error",
- clear: true
- });
- });
- } else {
- var errormessage = (this.$('#new-ddoc:visible').val() ==="")?"Enter a design doc name":"Please fix the Javascript errors and try again.";
- notification = FauxtonAPI.addNotification({
- msg: errormessage,
- type: "error",
- selector: "#define-view .errors-container",
- clear: true
- });
- }
- },
-
- updateView: function(event, paramInfo) {
- event.preventDefault();
-
- if (this.newView) { return alert('Please save this new view before querying it.'); }
-
- var errorParams = paramInfo.errorParams,
- params = paramInfo.params;
-
- if (_.any(errorParams)) {
- _.map(errorParams, function(param) {
-
- // TODO: Where to add this error?
- // bootstrap wants the error on a control-group div, but we're not using that
- //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
- return FauxtonAPI.addNotification({
- msg: "JSON Parse Error on field: "+param.name,
- type: "error",
- selector: ".advanced-options .errors-container",
- clear: true
- });
- });
- FauxtonAPI.addNotification({
- msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
- type: "warning",
- selector: ".advanced-options .errors-container",
- clear: true
- });
-
- return false;
- }
-
- var fragment = window.location.hash.replace(/\?.*$/, '');
- if (!_.isEmpty(params)) {
- fragment = fragment + '?' + $.param(params);
- }
-
- FauxtonAPI.navigate(fragment, {trigger: false});
- FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: this.ddocID, view: this.viewName});
- },
-
-
- previewView: function(event, paramsInfo) {
- event.preventDefault();
- var that = this,
- mapVal = this.mapVal(),
- reduceVal = this.reduceVal(),
- paramsArr = [];
-
- if (paramsInfo && paramsInfo.params) {
- paramsArr = paramsInfo.params;
- }
-
- var params = _.reduce(paramsArr, function (params, param) {
- params[param.name] = param.value;
- return params;
- }, {reduce: false});
-
- FauxtonAPI.addNotification({
- msg: "<strong>Warning!</strong> Preview executes the Map/Reduce functions in your browser, and may behave differently from CouchDB.",
- type: "warning",
- selector: ".advanced-options .errors-container",
- fade: true,
- escape: false // beware of possible XSS when the message changes
- });
-
- var promise = FauxtonAPI.Deferred();
-
- if (!this.database.allDocs || this.database.allDocs.params.include_docs !== true) {
- this.database.buildAllDocs({limit: Databases.DocLimit.toString(), include_docs: true});
- promise = this.database.allDocs.fetch();
- } else {
- promise.resolve();
- }
-
- promise.then(function () {
- params.docs = that.database.allDocs.map(function (model) { return model.get('doc');});
- var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
- queryPromise.then(function (results) {
- FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});
- });
- });
- },
-
- getCurrentDesignDoc: function () {
- return this.designDocSelector.getCurrentDesignDoc();
- },
-
- isCustomReduceEnabled: function() {
- return $("#reduce-function-selector").val() == "CUSTOM";
- },
-
- mapVal: function () {
- if (this.mapEditor) {
- return this.mapEditor.getValue();
- }
-
- return this.$('#map-function').text();
- },
-
- reduceVal: function() {
- var reduceOption = this.$('#reduce-function-selector :selected').val(),
- reduceVal = "";
-
- if (reduceOption === 'CUSTOM') {
- if (!this.reduceEditor) { this.createReduceEditor(); }
- reduceVal = this.reduceEditor.getValue();
- } else if ( reduceOption !== 'NONE') {
- reduceVal = reduceOption;
- }
-
- return reduceVal;
- },
-
-
- hasValidCode: function() {
- return _.every(["mapEditor", "reduceEditor"], function(editorName) {
- var editor = this[editorName];
- if (editorName === "reduceEditor" && ! this.isCustomReduceEnabled()) {
- return true;
- }
- return editor.hadValidCode();
- }, this);
- },
-
- toggleIndexNav: function (event) {
- $('#dashboard-content').scrollTop(0); //scroll up
-
- var $targetId = this.$(event.target).attr('id'),
- $previousTab = this.$(this.$('li.active a').attr('href')),
- $targetTab = this.$(this.$(event.target).attr('href'));
-
- if ($targetTab.attr('id') !== $previousTab.attr('id')) {
- $previousTab.removeAttr('style');
- }
-
- if ($targetId === 'index-nav') {
- if (this.newView) { return; }
- var that = this;
- $('#dashboard-content').scrollTop(0); //scroll up
- $targetTab.toggle('slow', function(){
- that.showEditors();
- });
- } else {
- $targetTab.toggle('slow');
- }
- },
-
- serialize: function() {
- return {
- ddocs: this.ddocs,
- ddoc: this.model,
- ddocName: this.model.id,
- viewName: this.viewName,
- reduceFunStr: this.reduceFunStr,
- isCustomReduce: this.hasCustomReduce(),
- newView: this.newView,
- langTemplates: this.langTemplates.javascript
- };
- },
-
- hasCustomReduce: function() {
- return this.reduceFunStr && ! _.contains(this.builtinReduces, this.reduceFunStr);
- },
-
- hasReduce: function () {
- return this.reduceFunStr || false;
- },
-
- createReduceEditor: function () {
- if (this.reduceEditor) {
- this.reduceEditor.remove();
- }
-
- this.reduceEditor = new Components.Editor({
- editorId: "reduce-function",
- mode: "javascript",
- couchJSHINT: true
- });
- this.reduceEditor.render();
-
- if (this.reduceEditor.getLines() === 1){
- this.$('.beautify_reduce').removeClass("hide");
- $('.beautify-tooltip').tooltip();
- }
- },
- beforeRender: function () {
-
- if (this.newView) {
- this.reduceFunStr = '';
- if (this.ddocs.length === 0) {
- this.model = new Documents.Doc(null, {database: this.database});
- } else {
- this.model = this.ddocs.first().dDocModel();
- }
- this.ddocID = this.model.id;
- } else {
- var ddocDecode = decodeURIComponent(this.ddocID);
- this.model = this.ddocs.get(this.ddocID).dDocModel();
- this.reduceFunStr = this.model.viewHasReduce(this.viewName);
- }
-
- var viewFilters = FauxtonAPI.getExtensions('sidebar:viewFilters'),
- filteredModels = this.ddocs.models,
- designDocs = this.ddocs.clone();
-
- if (!_.isEmpty(viewFilters)) {
- _.each(viewFilters, function (filter) {
- filteredModels = _.filter(filteredModels, filter);
- });
- designDocs.reset(filteredModels, {silent: true});
- }
-
- this.designDocSelector = this.setView('.design-doc-group', new Views.DesignDocSelector({
- collection: designDocs,
- ddocName: this.currentDdoc || this.model.id,
- database: this.database
- }));
-
- if (!this.newView) {
- this.eventer = _.extend({}, Backbone.Events);
-
- this.advancedOptions = this.insertView('#query', new QueryOptions.AdvancedOptions({
- updateViewFn: this.updateView,
- previewFn: this.previewView,
- database: this.database,
- viewName: this.viewName,
- ddocName: this.model.id,
- hasReduce: this.hasReduce(),
- eventer: this.eventer,
- showStale: true
- }));
- }
-
- },
-
- afterRender: function() {
-
- if (this.params && !this.newView) {
- this.advancedOptions.updateFromParams(this.params);
- }
-
- this.designDocSelector.updateDesignDoc();
- if (this.newView || this.showIndex) {
- this.showEditors();
- this.showIndex = false;
- } else {
- this.$('#index').hide();
- this.$('#index-nav').parent().removeClass('active');
- }
-
- },
-
- showEditors: function () {
- this.mapEditor = new Components.Editor({
- editorId: "map-function",
- mode: "javascript",
- couchJSHINT: true
- });
- this.mapEditor.render();
-
- if (this.hasCustomReduce()) {
- this.createReduceEditor();
- } else {
- $(".control-group.reduce-function").hide();
- }
-
- if (this.newView) {
- this.mapEditor.setValue(this.langTemplates[this.defaultLang].map);
- //Use a built in view by default
- //this.reduceEditor.setValue(this.langTemplates[this.defaultLang].reduce);
- }
-
- this.mapEditor.editSaved();
- this.reduceEditor && this.reduceEditor.editSaved();
-
- if (this.mapEditor.getLines() === 1){
- this.$('.beautify_map').removeClass("hide");
- $('.beautify-tooltip').tooltip();
- }
- },
- beautifyCode: function(e){
- e.preventDefault();
- var targetEditor = $(e.currentTarget).hasClass('beautify_reduce')?this.reduceEditor:this.mapEditor;
- var beautifiedCode = beautify(targetEditor.getValue());
- targetEditor.setValue(beautifiedCode);
- },
- cleanup: function () {
- this.mapEditor && this.mapEditor.remove();
- this.reduceEditor && this.reduceEditor.remove();
- }
- });
-
- Views.DesignDocSelector = FauxtonAPI.View.extend({
- template: "addons/documents/templates/design_doc_selector",
-
- events: {
- "change select#ddoc": "updateDesignDoc"
- },
-
- initialize: function (options) {
- this.ddocName = options.ddocName;
- this.database = options.database;
- this.listenTo(this.collection, 'add', this.ddocAdded);
- this.DocModel = options.DocModel || Documents.Doc;
- },
-
- ddocAdded: function (ddoc) {
- this.ddocName = ddoc.id;
- this.render();
- },
-
- serialize: function () {
- return {
- ddocName: this.ddocName,
- ddocs: this.collection
- };
- },
-
- updateDesignDoc: function () {
- if (this.newDesignDoc()) {
- this.$('#new-ddoc-section').show();
- } else {
- this.$('#new-ddoc-section').hide();
- }
- },
-
- newDesignDoc: function () {
-
- return this.$('#ddoc').val() === 'new-doc';
- },
-
- newDocValidation: function(){
- return this.newDesignDoc() && this.$('#new-ddoc').val()==="";
- },
- getCurrentDesignDoc: function () {
- if (this.newDesignDoc()) {
- var doc = {
- _id: '_design/' + this.$('#new-ddoc').val(),
- views: {},
- language: "javascript"
- };
- var ddoc = new this.DocModel(doc, {database: this.database});
- //this.collection.add(ddoc);
- return ddoc;
- } else if ( !this.newDesignDoc() ) {
- var ddocName = this.$('#ddoc').val();
- return this.collection.find(function (ddoc) {
- return ddoc.id === ddocName;
- }).dDocModel();
- }
- }
- });
-
- return Views;
-});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/queryoptionviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/queryoptionviews.js b/app/addons/documents/queryoptionviews.js
deleted file mode 100644
index b2e1af5..0000000
--- a/app/addons/documents/queryoptionviews.js
+++ /dev/null
@@ -1,270 +0,0 @@
-// 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",
- // Libs
- "addons/fauxton/resizeColumns",
-],
-
-function(app, FauxtonAPI, resizeColumns ) {
-
- var Views = {};
-
- Views.AdvancedOptions = FauxtonAPI.View.extend({
- template: "addons/documents/templates/advanced_options",
- className: "advanced-options well",
-
- initialize: function (options) {
- this.database = options.database;
- this.ddocName = options.ddocName;
- this.viewName = options.viewName;
- this.updateViewFn = options.updateViewFn;
- this.previewFn = options.previewFn;
- this.showStale = _.isUndefined(options.showStale) ? false : options.showStale;
- this.hasReduce = _.isUndefined(options.hasReduce) ? true : options.hasReduce;
- },
-
- events: {
- "change form.js-view-query-update input": "updateFilters",
- "change form.js-view-query-update select": "updateFilters",
- "submit form.js-view-query-update": "updateView",
- "click .toggle-btns > label": "toggleQuery"
- },
-
- toggleQuery: function(e){
- e.preventDefault();
-
- if (this.$(e.currentTarget).hasClass("active")){
- this.$('.js-query-keys-wrapper').addClass("hide");
- this.$(".toggle-btns > label").removeClass('active');
- this.$('.js-query-keys-wrapper').find("input,textarea").attr("disabled","true");
- } else {
- this.$('.js-query-keys-wrapper').removeClass("hide");
- var showFunctionName =this.$(e.currentTarget).attr("for");
- //highlight current
- this.$(".toggle-btns > label").removeClass('active');
- this.$(e.currentTarget).addClass("active");
- this.$("[id^='js-show']").hide();
- //show section & disable what needs to be disabled
- this[showFunctionName]();
- }
- },
-
- showKeys: function(){
- this.$("#js-showKeys, .js-disabled-message").show();
- this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').attr("disabled","true");
- this.$('[name="keys"]').removeAttr("disabled");
- },
-
- showStartEnd: function(){
- this.$("#js-showStartEnd").show();
- this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').removeAttr("disabled");
- this.$('.js-disabled-message').hide();
- this.$('[name="keys"]').attr("disabled","true");
- },
-
- beforeRender: function () {
- if (this.viewName && this.ddocName) {
- var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton');
- _.each(buttonViews, function (view) {
- this.insertView('#button-options', view);
- view.update(this.database, this.ddocName, this.viewName);
- }, this);
- }
- },
-
- renderOnUpdatehasReduce: function (hasReduce) {
- this.hasReduce = hasReduce;
- this.render();
- },
-
- parseJSON: function (value) {
- try {
- return JSON.parse(value);
- } catch(e) {
- return undefined;
- }
- },
-
- validateKeys: function(param){
- var errorMsg = false,
- parsedValue = this.parseJSON(param.value);
-
- if (_.isUndefined(parsedValue)) {
- errorMsg = "Keys must be valid json.";
- } else if (!_.isArray(parsedValue)) {
- errorMsg = "Keys values must be in an array. E.g [1,2,3]";
- }
-
- if (errorMsg) {
- this.$('.js-keys-error').empty();
- FauxtonAPI.addNotification({
- type: "error",
- msg: errorMsg,
- clear: false,
- selector: '.advanced-options .errors-container'
- });
- return false;
- }
-
- return true;
- },
- validateFields: function(params){
- var errors = false;
- //so ghetto. Spaghetti code.
- for (var i= 0; i <params.length; i++){
- if (params[i].name === "skip"){
- if (!(/^\d+$/).test(params[i].value)){
- FauxtonAPI.addNotification({
- msg: "Numbers only for skip",
- type: "warn",
- selector: ".advanced-options .errors-container",
- clear: true
- });
- errors = true;
- }
- }
- }
- return errors;
- },
- queryParams: function () {
- var $form = this.$(".js-view-query-update"),
- keysParam = false;
-
- var params = _.reduce($form.serializeArray(), function(params, param) {
- if (!param.value) { return params; }
- if (param.name === "limit" && param.value === 'None') { return params; }
- if (param.name === "keys") { keysParam = param; }
- params.push(param);
- return params;
- }, []);
-
-
- if (keysParam && !this.validateKeys(keysParam)) { return false; }
-
- if (params && this.validateFields(params)){ return false; }
-
- // Validate *key* params to ensure they're valid JSON
- var keyParams = ["keys","startkey","endkey"];
- var errorParams = _.filter(params, function(param) {
- if (_.contains(keyParams, param.name) && _.isUndefined(this.parseJSON(param.value))) {
- return true;
- }
-
- return false;
- }, this);
-
- return {params: params, errorParams: errorParams};
- },
-
- updateView: function (event) {
- event.preventDefault();
- var params = this.queryParams();
- if (!params) { return;}
- this.updateViewFn(event, params);
- },
-
- updateFilters: function(event) {
- event.preventDefault();
- var $ele = $(event.currentTarget);
- var name = $ele.attr('name');
- this.updateFiltersFor(name, $ele);
- },
-
- updateFiltersFor: function(name, $ele) {
- var $form = $ele.parents("form.js-view-query-update:first");
- switch (name) {
- // Reduce constraints
- // - Can't include_docs for reduce=true
- // - can't include group_level for reduce=false
- case "reduce":
- if ($ele.prop('checked') === true) {
- if ($form.find("input[name=include_docs]").prop("checked") === true) {
- $form.find("input[name=include_docs]").prop("checked", false);
- var notification = FauxtonAPI.addNotification({
- msg: "include_docs has been disabled as you cannot include docs on a reduced view",
- type: "warn",
- selector: ".advanced-options .errors-container",
- clear: true
- });
- }
- $form.find("input[name=include_docs]").prop("disabled", true);
- $form.find("select[name=group_level]").prop("disabled", false);
- } else {
- $form.find("select[name=group_level]").val("999").prop("disabled", true);
- $form.find("input[name=include_docs]").prop("disabled", false);
- }
- break;
- case "skip":
- if (!(/^\d+$/).test($ele.val())){
- FauxtonAPI.addNotification({
- msg: "Numbers only for skip",
- type: "warn",
- selector: ".advanced-options .errors-container",
- clear: true
- });
- }
- break;
- case "include_docs":
- break;
- }
- },
-
- updateFromParams: function (params) {
- var $form = this.$el.find("form.js-view-query-update");
- _.each(params, function(val, key) {
- var $ele;
- switch (key) {
- case "limit":
- case "descending":
- case "group_level":
- if (!val) { return; }
- $form.find("select[name='"+key+"']").val(val);
- break;
- case "include_docs":
- case "stale":
- case "inclusive_end":
- $form.find("input[name='"+key+"']").prop('checked', true);
- break;
- case "reduce":
- $ele = $form.find("input[name='"+key+"']");
- if (val == "true") {
- $ele.prop('checked', true);
- }
- this.updateFiltersFor(key, $ele);
- break;
- case "key":
- case "keys":
- $form.find("textarea[name='"+key+"']").val(val);
- break;
- default:
- $form.find("input[name='"+key+"']").val(val);
- break;
- }
- }, this);
- },
-
- serialize: function () {
- return {
- hasReduce: this.hasReduce,
- showPreview: false,
- showStale: this.showStale
- };
- }
- });
-
-
- return Views;
-
-});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
index 2140e04..9c266be 100644
--- a/app/addons/documents/routes.js
+++ b/app/addons/documents/routes.js
@@ -18,9 +18,9 @@ define([
// Modules
//views
"addons/documents/views",
- "addons/documents/changesviews",
- "addons/documents/indexviews",
- "addons/documents/doceditorviews",
+ "addons/documents/views-changes",
+ "addons/documents/views-index",
+ "addons/documents/views-doceditor",
"addons/databases/base",
"addons/documents/resources"
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/sidebarviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/sidebarviews.js b/app/addons/documents/sidebarviews.js
deleted file mode 100644
index e3cc629..0000000
--- a/app/addons/documents/sidebarviews.js
+++ /dev/null
@@ -1,253 +0,0 @@
-// 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"
-],
-
-function(app, FauxtonAPI, Components, Documents, Databases) {
- var Views = {};
-
- Views.Sidebar = FauxtonAPI.View.extend({
- template: "addons/documents/templates/sidebar",
- className: "sidenav",
- tagName: "nav",
- events: {
- "click button#delete-database": "showDeleteDatabaseModal"
- },
-
- initialize: function(options) {
- this.database = options.database;
- if (options.ddocInfo) {
- this.ddocID = options.ddocInfo.id;
- this.currView = options.ddocInfo.currView;
- }
- },
- showDeleteDatabaseModal: function(event){
- this.deleteDBModal.showModal();
- },
-
- serialize: function() {
- var docLinks = FauxtonAPI.getExtensions('docLinks'),
- newLinks = FauxtonAPI.getExtensions('sidebar:newLinks'),
- addLinks = FauxtonAPI.getExtensions('sidebar:links'),
- extensionList = FauxtonAPI.getExtensions('sidebar:list');
- return {
- changes_url: '#' + this.database.url('changes'),
- permissions_url: '#' + this.database.url('app') + '/permissions',
- db_url: '#' + this.database.url('index'),
- database: this.collection.database,
- database_url: '#' + this.database.url('app'),
- docLinks: docLinks,
- addLinks: addLinks,
- newLinks: newLinks,
- extensionList: extensionList > 0
- };
- },
-
-
- beforeRender: function(manage) {
- this.deleteDBModal = this.setView(
- '#delete-db-modal',
- new Views.DeleteDBModal({database: this.database})
- );
-
- var database = this.collection.database,
- newurl = "#" + database.url('app') + '/new';
-
- var newLinks = [{
- title: 'Add new',
- links: [{
- title: 'New Doc',
- url: newurl,
- icon: 'fonticon-plus-circled'
- },{
- title: 'New Design Doc',
- url: newurl,
- icon: 'fonticon-plus-circled'
- }]
- }];
-
- this.insertView("#new-all-docs-button", new Components.MenuDropDown({
- links: newLinks,
- }));
-
- this.insertView("#new-design-docs-button", new Components.MenuDropDown({
- links: newLinks,
- }));
-
- this.collection.each(function(design) {
- if (design.has('doc')){
- this.insertView(new Views.DdocSidenav({
- model: design,
- collection: this.collection
- }));
- }
- },this);
- },
-
- afterRender: function () {
- if (this.selectedTab) {
- this.setSelectedTab(this.selectedTab);
- }
- },
-
- setSelectedTab: function (selectedTab) {
- this.selectedTab = selectedTab;
- var $selectedTab = this.$('#' + selectedTab);
-
- this.$('li').removeClass('active');
- $selectedTab.parent().addClass('active');
-
- if ($selectedTab.parents(".accordion-body").length !== 0){
- $selectedTab
- .parents(".accordion-body")
- .addClass("in")
- .parents(".nav-header")
- .find(">.js-collapse-toggle").addClass("down");
-
- this.$('.js-toggle-' + $selectedTab.data('ddoctype')).addClass("down");
- }
- }
- });
-
- Views.DdocSidenav = FauxtonAPI.View.extend({
- tagName: "ul",
- className: "nav nav-list",
- template: "addons/documents/templates/design_doc_menu",
- events: {
- "click .js-collapse-toggle": "toggleArrow"
- },
-
- toggleArrow: function(e){
- this.$(e.currentTarget).toggleClass("down");
- },
- buildIndexList: function(collection, selector, ddocType){
- var design = this.model.id.replace(/^_design\//,"");
-
- this.insertView(".accordion-body", new Views.IndexItem({
- selector: selector,
- ddoc: design,
- collection: collection[selector],
- ddocType: ddocType,
- database: this.model.collection.database.id
- }));
- },
-
- serialize: function(){
- var ddocName = this.model.id.replace(/^_design\//,"");
- return{
- database: this.collection.database,
- designDoc: ddocName,
- ddoc_clean: app.utils.removeSpecialCharacters(ddocName),
- ddoc_encoded: app.utils.safeURLName(ddocName),
- database_encoded: app.utils.safeURLName(this.model.collection.database.id),
- };
- },
-
- getSidebarLinks: function () {
- var ddocName = this.model.id.replace(/^_design\//,""),
- docSafe = app.utils.safeURLName(ddocName),
- database = this.collection.database;
-
- return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
-
- menuLinks.push({
- title: link.title,
- url: "#" + database.url('app') + "/" + link.url + "/" + docSafe,
- icon: 'fonticon-plus-circled'
- });
-
- return menuLinks;
- }, [{
- title: 'Secondary View',
- url: "#" + database.url('app') + "/new_view/" + docSafe,
- icon: 'fonticon-plus-circled'
- }]);
-
- },
-
- renderIndexLists: function () {
- var ddocDocs = this.model.get("doc"),
- sidebarListTypes = FauxtonAPI.getExtensions('sidebar:list');
-
- if (!ddocDocs){ return; }
-
- this.buildIndexList(ddocDocs, "views", "view");
- _.each(sidebarListTypes, function (type) {
- this.buildIndexList(ddocDocs, type);
- },this);
-
- },
-
- beforeRender: function(manage) {
- var sideBarMenuLinks = [];
-
- sideBarMenuLinks.push({
- title: 'Add new',
- links: this.getSidebarLinks()
- });
-
- this.renderIndexLists();
- this.insertView(".new-button", new Components.MenuDropDown({
- links: sideBarMenuLinks,
- }));
- }
- });
-
- Views.IndexItem = FauxtonAPI.View.extend({
- template: "addons/documents/templates/index_menu_item",
- tagName: 'li',
-
- initialize: function(options){
- this.index = options.index;
- this.ddoc = options.ddoc;
- this.database = options.database;
- this.selected = !! options.selected;
- this.selector = options.selector;
- this.ddocType = options.ddocType || this.selector;
- this.icons = {
- "view": "fonticon-sidenav-map-reduce",
- "indexes": "fonticon-sidenav-search"
- };
-
- },
-
- serialize: function() {
- return {
- icon: this.icons[this.ddocType],
- ddocType: this.ddocType,
- index: this.index,
- ddoc: this.ddoc,
- database: this.database,
- selected: this.selected,
- collection: this.collection
- };
- },
-
- afterRender: function() {
- if (this.selected) {
- $(".sidenav ul.nav-list li").removeClass("active");
- this.$el.addClass("active");
- }
- }
- });
-
- return Views;
-});
-
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views-advancedopts.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-advancedopts.js b/app/addons/documents/views-advancedopts.js
new file mode 100644
index 0000000..b2e1af5
--- /dev/null
+++ b/app/addons/documents/views-advancedopts.js
@@ -0,0 +1,270 @@
+// 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",
+ // Libs
+ "addons/fauxton/resizeColumns",
+],
+
+function(app, FauxtonAPI, resizeColumns ) {
+
+ var Views = {};
+
+ Views.AdvancedOptions = FauxtonAPI.View.extend({
+ template: "addons/documents/templates/advanced_options",
+ className: "advanced-options well",
+
+ initialize: function (options) {
+ this.database = options.database;
+ this.ddocName = options.ddocName;
+ this.viewName = options.viewName;
+ this.updateViewFn = options.updateViewFn;
+ this.previewFn = options.previewFn;
+ this.showStale = _.isUndefined(options.showStale) ? false : options.showStale;
+ this.hasReduce = _.isUndefined(options.hasReduce) ? true : options.hasReduce;
+ },
+
+ events: {
+ "change form.js-view-query-update input": "updateFilters",
+ "change form.js-view-query-update select": "updateFilters",
+ "submit form.js-view-query-update": "updateView",
+ "click .toggle-btns > label": "toggleQuery"
+ },
+
+ toggleQuery: function(e){
+ e.preventDefault();
+
+ if (this.$(e.currentTarget).hasClass("active")){
+ this.$('.js-query-keys-wrapper').addClass("hide");
+ this.$(".toggle-btns > label").removeClass('active');
+ this.$('.js-query-keys-wrapper').find("input,textarea").attr("disabled","true");
+ } else {
+ this.$('.js-query-keys-wrapper').removeClass("hide");
+ var showFunctionName =this.$(e.currentTarget).attr("for");
+ //highlight current
+ this.$(".toggle-btns > label").removeClass('active');
+ this.$(e.currentTarget).addClass("active");
+ this.$("[id^='js-show']").hide();
+ //show section & disable what needs to be disabled
+ this[showFunctionName]();
+ }
+ },
+
+ showKeys: function(){
+ this.$("#js-showKeys, .js-disabled-message").show();
+ this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').attr("disabled","true");
+ this.$('[name="keys"]').removeAttr("disabled");
+ },
+
+ showStartEnd: function(){
+ this.$("#js-showStartEnd").show();
+ this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').removeAttr("disabled");
+ this.$('.js-disabled-message').hide();
+ this.$('[name="keys"]').attr("disabled","true");
+ },
+
+ beforeRender: function () {
+ if (this.viewName && this.ddocName) {
+ var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton');
+ _.each(buttonViews, function (view) {
+ this.insertView('#button-options', view);
+ view.update(this.database, this.ddocName, this.viewName);
+ }, this);
+ }
+ },
+
+ renderOnUpdatehasReduce: function (hasReduce) {
+ this.hasReduce = hasReduce;
+ this.render();
+ },
+
+ parseJSON: function (value) {
+ try {
+ return JSON.parse(value);
+ } catch(e) {
+ return undefined;
+ }
+ },
+
+ validateKeys: function(param){
+ var errorMsg = false,
+ parsedValue = this.parseJSON(param.value);
+
+ if (_.isUndefined(parsedValue)) {
+ errorMsg = "Keys must be valid json.";
+ } else if (!_.isArray(parsedValue)) {
+ errorMsg = "Keys values must be in an array. E.g [1,2,3]";
+ }
+
+ if (errorMsg) {
+ this.$('.js-keys-error').empty();
+ FauxtonAPI.addNotification({
+ type: "error",
+ msg: errorMsg,
+ clear: false,
+ selector: '.advanced-options .errors-container'
+ });
+ return false;
+ }
+
+ return true;
+ },
+ validateFields: function(params){
+ var errors = false;
+ //so ghetto. Spaghetti code.
+ for (var i= 0; i <params.length; i++){
+ if (params[i].name === "skip"){
+ if (!(/^\d+$/).test(params[i].value)){
+ FauxtonAPI.addNotification({
+ msg: "Numbers only for skip",
+ type: "warn",
+ selector: ".advanced-options .errors-container",
+ clear: true
+ });
+ errors = true;
+ }
+ }
+ }
+ return errors;
+ },
+ queryParams: function () {
+ var $form = this.$(".js-view-query-update"),
+ keysParam = false;
+
+ var params = _.reduce($form.serializeArray(), function(params, param) {
+ if (!param.value) { return params; }
+ if (param.name === "limit" && param.value === 'None') { return params; }
+ if (param.name === "keys") { keysParam = param; }
+ params.push(param);
+ return params;
+ }, []);
+
+
+ if (keysParam && !this.validateKeys(keysParam)) { return false; }
+
+ if (params && this.validateFields(params)){ return false; }
+
+ // Validate *key* params to ensure they're valid JSON
+ var keyParams = ["keys","startkey","endkey"];
+ var errorParams = _.filter(params, function(param) {
+ if (_.contains(keyParams, param.name) && _.isUndefined(this.parseJSON(param.value))) {
+ return true;
+ }
+
+ return false;
+ }, this);
+
+ return {params: params, errorParams: errorParams};
+ },
+
+ updateView: function (event) {
+ event.preventDefault();
+ var params = this.queryParams();
+ if (!params) { return;}
+ this.updateViewFn(event, params);
+ },
+
+ updateFilters: function(event) {
+ event.preventDefault();
+ var $ele = $(event.currentTarget);
+ var name = $ele.attr('name');
+ this.updateFiltersFor(name, $ele);
+ },
+
+ updateFiltersFor: function(name, $ele) {
+ var $form = $ele.parents("form.js-view-query-update:first");
+ switch (name) {
+ // Reduce constraints
+ // - Can't include_docs for reduce=true
+ // - can't include group_level for reduce=false
+ case "reduce":
+ if ($ele.prop('checked') === true) {
+ if ($form.find("input[name=include_docs]").prop("checked") === true) {
+ $form.find("input[name=include_docs]").prop("checked", false);
+ var notification = FauxtonAPI.addNotification({
+ msg: "include_docs has been disabled as you cannot include docs on a reduced view",
+ type: "warn",
+ selector: ".advanced-options .errors-container",
+ clear: true
+ });
+ }
+ $form.find("input[name=include_docs]").prop("disabled", true);
+ $form.find("select[name=group_level]").prop("disabled", false);
+ } else {
+ $form.find("select[name=group_level]").val("999").prop("disabled", true);
+ $form.find("input[name=include_docs]").prop("disabled", false);
+ }
+ break;
+ case "skip":
+ if (!(/^\d+$/).test($ele.val())){
+ FauxtonAPI.addNotification({
+ msg: "Numbers only for skip",
+ type: "warn",
+ selector: ".advanced-options .errors-container",
+ clear: true
+ });
+ }
+ break;
+ case "include_docs":
+ break;
+ }
+ },
+
+ updateFromParams: function (params) {
+ var $form = this.$el.find("form.js-view-query-update");
+ _.each(params, function(val, key) {
+ var $ele;
+ switch (key) {
+ case "limit":
+ case "descending":
+ case "group_level":
+ if (!val) { return; }
+ $form.find("select[name='"+key+"']").val(val);
+ break;
+ case "include_docs":
+ case "stale":
+ case "inclusive_end":
+ $form.find("input[name='"+key+"']").prop('checked', true);
+ break;
+ case "reduce":
+ $ele = $form.find("input[name='"+key+"']");
+ if (val == "true") {
+ $ele.prop('checked', true);
+ }
+ this.updateFiltersFor(key, $ele);
+ break;
+ case "key":
+ case "keys":
+ $form.find("textarea[name='"+key+"']").val(val);
+ break;
+ default:
+ $form.find("input[name='"+key+"']").val(val);
+ break;
+ }
+ }, this);
+ },
+
+ serialize: function () {
+ return {
+ hasReduce: this.hasReduce,
+ showPreview: false,
+ showStale: this.showStale
+ };
+ }
+ });
+
+
+ return Views;
+
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views-changes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-changes.js b/app/addons/documents/views-changes.js
new file mode 100644
index 0000000..2f91c21
--- /dev/null
+++ b/app/addons/documents/views-changes.js
@@ -0,0 +1,84 @@
+// 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",
+ // Libs
+ "addons/fauxton/resizeColumns",
+
+ // Plugins
+ "plugins/prettify",
+ // this should never be global available:
+ // https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/security.md
+ "plugins/zeroclipboard/ZeroClipboard"
+],
+
+function(app, FauxtonAPI, resizeColumns, prettify, ZeroClipboard) {
+
+ var Views = {};
+
+ Views.Changes = FauxtonAPI.View.extend({
+ template: "addons/documents/templates/changes",
+
+ initialize: function () {
+ this.listenTo( this.model.changes, 'sync', this.render);
+ this.listenTo( this.model.changes, 'cachesync', this.render);
+ },
+
+ events: {
+ "click button.js-toggle-json": "toggleJson"
+ },
+
+ toggleJson: function(event) {
+ event.preventDefault();
+
+ var $button = this.$(event.target),
+ $container = $button.closest('.change-box').find(".js-json-container");
+
+ if (!$container.is(":visible")) {
+ $button
+ .text("Close JSON")
+ .addClass("btn-secondary")
+ .removeClass("btn-primary");
+ } else {
+ $button.text("View JSON")
+ .addClass("btn-primary")
+ .removeClass("btn-secondary");
+ }
+
+ $container.slideToggle();
+ },
+
+ establish: function() {
+ return [ this.model.changes.fetchOnce({prefill: true})];
+ },
+
+ serialize: function () {
+ return {
+ changes: this.model.changes.toJSON(),
+ database: this.model
+ };
+ },
+
+ afterRender: function(){
+ prettyPrint();
+ ZeroClipboard.config({ moviePath: "/assets/js/plugins/zeroclipboard/ZeroClipboard.swf" });
+ var client = new ZeroClipboard(this.$(".js-copy"));
+ }
+ });
+
+
+
+ return Views;
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views-doceditor.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-doceditor.js b/app/addons/documents/views-doceditor.js
new file mode 100644
index 0000000..add8d8c
--- /dev/null
+++ b/app/addons/documents/views-doceditor.js
@@ -0,0 +1,416 @@
+// 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');
+ }
+ });
+
+
+
+ /* 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"
+ },
+
+ disableLoader: true,
+
+ initialize: function (options) {
+ this.database = options.database;
+ _.bindAll(this);
+ },
+
+ goback: function(){
+ FauxtonAPI.navigate(this.database.url("index") + "?limit=100");
+ },
+
+ 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}));
+ 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
+ });
+ });
+ },
+
+ cleanup: function () {
+ if (this.editor) this.editor.remove();
+ }
+ });
+
+ return Views;
+});