http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/documents/views-index.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/views-index.js b/app/addons/documents/views-index.js deleted file mode 100644 index d0ed8ed..0000000 --- a/app/addons/documents/views-index.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/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/113615ff/app/addons/documents/views-sidebar.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/views-sidebar.js b/app/addons/documents/views-sidebar.js index 9f8c0ee..1d746ce 100644 --- a/app/addons/documents/views-sidebar.js +++ b/app/addons/documents/views-sidebar.js @@ -151,8 +151,13 @@ function(app, FauxtonAPI, Components, Documents, Databases) { toggleArrow: function(e){ this.$(e.currentTarget).toggleClass("down"); }, + buildIndexList: function(collection, selector, ddocType){ + buildIndexList: function(collection, indexType){ buildIndexList: function(collection, info){ var design = this.model.id.replace(/^_design\//,""); + var selector = indexType.selector; + var ddocType = indexType.ddocType; + var icon = indexType.icon; this.insertView(".accordion-body", new Views.IndexItem({ selector: info.selector, @@ -176,14 +181,14 @@ function(app, FauxtonAPI, Components, Documents, Databases) { getSidebarLinks: function () { var ddocName = this.model.id.replace(/^_design\//,""), - docSafe = app.utils.safeURLName(ddocName), + 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, + url: "#" + database.url('app')+ "/" + link.url + "/" + docSafe, icon: 'fonticon-plus-circled' }); @@ -228,6 +233,7 @@ function(app, FauxtonAPI, Components, Documents, Databases) { } }); + //Sidebar Index Item Views.IndexItem = FauxtonAPI.View.extend({ template: "addons/documents/templates/index_menu_item", tagName: 'li', @@ -248,7 +254,7 @@ function(app, FauxtonAPI, Components, Documents, Databases) { serialize: function() { return { - icon: this.icons[this.ddocType], + icon: this.icons[this.ddocType], ddocType: this.selector, name: this.name, index: this.index, @@ -258,7 +264,6 @@ function(app, FauxtonAPI, Components, Documents, Databases) { collection: this.collection }; }, - afterRender: function() { if (this.selected) { $(".sidenav ul.nav-list li").removeClass("active"); @@ -267,6 +272,8 @@ function(app, FauxtonAPI, Components, Documents, Databases) { } }); + + return Views; }); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/documents/views.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js index 7085bd8..16a853a 100644 --- a/app/addons/documents/views.js +++ b/app/addons/documents/views.js @@ -38,6 +38,163 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, }); } + //Header for alldocs with search, Query options,& api bar + Views.RightAllDocsHeader = FauxtonAPI.View.extend({ + className: "header-right", + template: "addons/documents/templates/header_alldocs", + events: { + 'select .selectAllDocs': 'selectAllDocs' + }, + initialize: function(options){ + //adding the database to the object + this.database = options.database; + }, + selectAllDocs: function(){ + //trigger event to select all in other view + }, + updateApiUrl: function(api){ + //this will update the api bar when the route changes + //you can find the method that updates it in components.js Components.ApiBar() + this.apiBar && this.apiBar.update(api); + }, + serialize: function() { + //basically if you want something in a template, You can define it here + return { + database: this.database.get('id') + }; + }, + beforeRender:function(){ + //insert DB search dropdown + + //insert top create level dropdown with gear icon + + //search docs + this.setView("#header-search", new Views.JumpToDoc({ + database: this.database, + collection: this.database.allDocs + })); + + //insert queryoptions + //that file is included in require() above and the argument is QueryOptions + // and it wants all these params: + /* Sooooo I searched this file for where Advanced options was originally inserted to see what the hell + is happening. and it's in AllDocsLayout. So I'm going to move some of those functions over here + + These are required: + this.database = options.database; + this.updateViewFn = options.updateViewFn; + this.previewFn = options.previewFn; + + these are booleans: + this.showStale = _.isUndefined(options.showStale) ? false : options.showStale; + this.hasReduce = _.isUndefined(options.hasReduce) ? true : options.hasReduce; + + these you only need for view indexes, not all docs because they are about + specific views and design docs (ddocs, also views live inside a ddoc): + this.viewName = options.viewName; + this.ddocName = options.ddocName; + */ + this.setView("#query-options", new QueryOptions.AdvancedOptions({ + updateViewFn: this.updateAllDocs, + previewFn: this.previewView, + database: this.database, + hasReduce: false, + showPreview: false, + })); + + //Moved the apibar view into the components file so you can include it in your views + this.apiBar = this.insertView("#header-api-bar", new Components.ApiBar({})); + + }, + //moved from alldocs layout + updateAllDocs: function (event, paramInfo) { + event.preventDefault(); + + 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', {allDocs: true}); + }, + previewView: function (event) { + event.preventDefault(); + } + }); + + + //header that shows up when a doc is selected + // when a Doc is selected, trigger a routeEvent to render this + // the routeEvent will determine which header to show (??) + Views.DocEditHeader = FauxtonAPI.View.extend({ + template: "addons/documents/templates/header_doc_edit", + events: { + 'select .selectAllDocs': 'selectAllDocs' + }, + initialize: function(options){ + + }, + selectAllDocs: function(){ + //trigger event to select all in other view + }, + afterRender:function(){ + //insert DB search dropdown + + //insert top create level dropdown with gear icon + } + }); + + Views.DocsHeader = FauxtonAPI.View.extend({ + template: "addons/documents/templates/header_selecteddoc", + events: { + 'select .selectAllDocs': 'selectAllDocs' + }, + initialize: function(options){ + + }, + selectAllDocs: function(){ + //trigger event to select all in other view + }, + afterRender:function(){ + //insert DB search dropdown + + //insert top create level dropdown with gear icon + + //search docs + + //insert queryoptions + + } + }); + Views.DeleteDBModal = Components.ModalView.extend({ template: "addons/documents/templates/delete_database_modal", @@ -83,11 +240,10 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, Views.Document = FauxtonAPI.View.extend({ template: "addons/documents/templates/all_docs_item", - tagName: "tr", - className: "all-docs-item", - + className: "all-docs-item doc-row", initialize: function (options) { this.checked = options.checked; + this.expanded = options.expanded; }, events: { @@ -103,6 +259,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, serialize: function() { return { + expanded: this.expanded, + docID: this.model.get('_id'), doc: this.model, checked: this.checked }; @@ -148,27 +306,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, } }); - Views.Row = FauxtonAPI.View.extend({ - template: "addons/documents/templates/index_row_docular", - tagName: "tr", - - events: { - "click button.delete": "destroy" - }, - - destroy: function (event) { - event.preventDefault(); - - window.alert('Cannot delete a document generated from a view.'); - }, - - serialize: function() { - return { - doc: this.model, - url: this.model.url('app') - }; - } - }); Views.AllDocsNumber = FauxtonAPI.View.extend({ @@ -232,88 +369,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, }); - Views.AllDocsLayout = FauxtonAPI.View.extend({ - template: "addons/documents/templates/all_docs_layout", - - initialize: function (options) { - this.database = options.database; - this.params = options.params; - }, - - events: { - 'click #toggle-query': "toggleQuery" - }, - - toggleQuery: function (event) { - $('#dashboard-content').scrollTop(0); - this.$('#query').toggle('slow'); - }, - - beforeRender: function () { - this.advancedOptions = this.insertView('#query', new QueryOptions.AdvancedOptions({ - updateViewFn: this.updateAllDocs, - previewFn: this.previewView, - hasReduce: false, - showPreview: false, - database: this.database, - })); - - this.toolsView = this.setView(".js-search", new Views.JumpToDoc({ - database: this.database, - collection: this.database.allDocs - })); - }, - - afterRender: function () { - if (this.params) { - this.advancedOptions.updateFromParams(this.params); - } - }, - - updateAllDocs: function (event, paramInfo) { - event.preventDefault(); - - 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', {allDocs: true}); - }, - - previewView: function (event) { - event.preventDefault(); - } - - }); // TODO: Rename to reflect that this is a list of rows or documents Views.AllDocsList = FauxtonAPI.View.extend({ @@ -378,12 +433,12 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, }, toggleDocument: function (event) { - var $row = this.$(event.target).closest('tr'), + var $row = this.$(event.target).closest('.doc-row'), docId = $row.attr('data-id'), rev = this.collection.get(docId).get('_rev'), data = {_id: docId, _rev: rev, _deleted: true}; - if (!$row.hasClass('js-to-delete'))Â { + if (!$row.hasClass('js-to-delete')) { this.bulkDeleteDocsCollection.add(data); } else { this.bulkDeleteDocsCollection.remove(this.bulkDeleteDocsCollection.get(docId)); @@ -535,8 +590,9 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, if (this.bulkDeleteDocsCollection) { isChecked = this.bulkDeleteDocsCollection.get(doc.id); } - this.rows[doc.id] = this.insertView("table.all-docs tbody", new this.nestedView({ + this.rows[doc.id] = this.insertView("#doc-list", new this.nestedView({ model: doc, + expanded: this.expandDocs, checked: isChecked })); }, this); @@ -569,8 +625,11 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, } this.toggleTrash(); + this.setPaginationWidth(); + }, + setPaginationWidth: function(){ + this.$('#documents-pagination').css('width', this.$el.outerWidth()); }, - perPage: function () { return this.allDocsNumber.perPage(); } http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/fauxton/base.js ---------------------------------------------------------------------- diff --git a/app/addons/fauxton/base.js b/app/addons/fauxton/base.js index 8b88d36..68ee7cd 100644 --- a/app/addons/fauxton/base.js +++ b/app/addons/fauxton/base.js @@ -14,11 +14,10 @@ define([ "app", "api", "addons/fauxton/resizeColumns", - "addons/fauxton/components", - "plugins/zeroclipboard/ZeroClipboard" + "addons/fauxton/components" ], -function(app, FauxtonAPI, resizeColumns, Components, ZeroClipboard) { +function(app, FauxtonAPI, resizeColumns, Components) { var Fauxton = FauxtonAPI.addon(); FauxtonAPI.addNotification = function (options) { @@ -51,7 +50,7 @@ function(app, FauxtonAPI, resizeColumns, Components, ZeroClipboard) { Fauxton.initialize = function () { // app.footer = new Fauxton.Footer({el: "#footer-content"}), app.navBar = new Fauxton.NavBar(); - app.apiBar = new Fauxton.ApiBar(); + app.apiBar = new Components.ApiBar(); FauxtonAPI.when.apply(null, app.navBar.establish()).done(function() { FauxtonAPI.masterLayout.setView("#primary-navbar", app.navBar, true); @@ -77,7 +76,7 @@ function(app, FauxtonAPI, resizeColumns, Components, ZeroClipboard) { var crumbs = routeObject.get('crumbs'); if (crumbs.length) { - FauxtonAPI.masterLayout.setView('#breadcrumbs', new Fauxton.Breadcrumbs({ + FauxtonAPI.masterLayout.setView('#breadcrumbs', new Components.Breadcrumbs({ crumbs: crumbs }), true).render(); } @@ -93,20 +92,7 @@ function(app, FauxtonAPI, resizeColumns, Components, ZeroClipboard) { }); }; - Fauxton.Breadcrumbs = FauxtonAPI.View.extend({ - template: "addons/fauxton/templates/breadcrumbs", - serialize: function() { - var crumbs = _.clone(this.crumbs); - return { - crumbs: crumbs - }; - }, - - initialize: function(options) { - this.crumbs = options.crumbs; - } - }); Fauxton.VersionInfo = Backbone.Model.extend({ url: function () { @@ -259,64 +245,6 @@ function(app, FauxtonAPI, resizeColumns, Components, ZeroClipboard) { // TODO: ADD ACTIVE CLASS }); - Fauxton.ApiBar = FauxtonAPI.View.extend({ - template: "addons/fauxton/templates/api_bar", - endpoint: '_all_docs', - - documentation: 'docs', - - events: { - "click .api-url-btn" : "toggleAPIbar" - }, - - toggleAPIbar: function(e){ - var $currentTarget = $(e.currentTarget).find('span'); - if ($currentTarget.hasClass("fonticon-plus")){ - $currentTarget.removeClass("fonticon-plus").addClass("fonticon-minus"); - }else{ - $currentTarget.removeClass("fonticon-minus").addClass("fonticon-plus"); - } - $('.api-navbar').toggle(); - }, - - serialize: function() { - return { - endpoint: this.endpoint, - documentation: this.documentation - }; - }, - - hide: function(){ - this.$el.addClass('hide'); - }, - show: function(){ - this.$el.removeClass('hide'); - }, - update: function(endpoint) { - this.show(); - this.endpoint = endpoint[0]; - this.documentation = endpoint[1]; - this.render(); - }, - afterRender: function(){ - var client = new Components.Clipboard({ - $el: this.$('.copy-url') - }); - - client.on("load", function(e){ - var $apiInput = $('#api-navbar input'); - var copyURLTimer; - client.on("mouseup", function(e){ - $apiInput.css("background-color","#aaa"); - window.clearTimeout(copyURLTimer); - copyURLTimer = setInterval(function () { - $apiInput.css("background-color","#fff"); - }, 200); - }); - }); - } - - }); Fauxton.Notification = FauxtonAPI.View.extend({ fadeTimer: 5000, http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/fauxton/components.js ---------------------------------------------------------------------- diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js index c863ba7..9540252 100644 --- a/app/addons/fauxton/components.js +++ b/app/addons/fauxton/components.js @@ -34,7 +34,124 @@ define([ function(app, FauxtonAPI, ace, spin, ZeroClipboard) { var Components = FauxtonAPI.addon(); + + //setting up the left header with the backbutton used in Views and All docs + Components.LeftHeader = FauxtonAPI.View.extend({ + className: "header-left", + template: "addons/fauxton/templates/header_left", + initialize:function(options){ + this.dropdownMenuLinks = options.dropdownMenu; + this.crumbs = options.crumbs || []; + }, + updateCrumbs: function(crumbs){ + this.breadcrumbs && this.breadcrumbs.update(crumbs); + }, + updateDropdown: function(menuLinks){ + this.dropdown && this.dropdown.update(menuLinks); + }, + beforeRender: function(){ + this.setUpCrumbs(); + this.setUpDropDownMenu(); + }, + setUpCrumbs: function(){ + this.breadcrumbs = this.insertView("#header-breadcrumbs", new Components.Breadcrumbs({ + crumbs: this.crumbs + })); + }, + setUpDropDownMenu: function(){ + if (this.dropdownMenuLinks){ + this.dropdown = this.insertView("#header-dropdown-menu", new Components.MenuDropDown({ + icon: 'fonticon-cog', + links: this.dropdownMenuLinks, + })); + } + } + }); + + + Components.Breadcrumbs = FauxtonAPI.View.extend({ + className: "breadcrumb pull-left", + tagName: "ul", + template: "addons/fauxton/templates/breadcrumbs", + serialize: function() { + var crumbs = _.clone(this.crumbs); + return { + crumbs: crumbs + }; + }, + update: function(crumbs) { + this.crumbs = crumbs; + this.render(); + }, + initialize: function(options) { + this.crumbs = options.crumbs; + } + }); + + Components.ApiBar = FauxtonAPI.View.extend({ + template: "addons/fauxton/templates/api_bar", + events: { + "click .api-url-btn" : "toggleAPIbar" + }, + + initialize: function(options){ + var _options = options || {}; + this.endpoint = _options.endpoint || '_all_docs'; + this.documentation = _options.documentation || 'docs'; + }, + + toggleAPIbar: function(e){ + var $currentTarget = $(e.currentTarget).find('span'); + if ($currentTarget.hasClass("fonticon-plus")){ + $currentTarget.removeClass("fonticon-plus").addClass("fonticon-minus"); + }else{ + $currentTarget.removeClass("fonticon-minus").addClass("fonticon-plus"); + } + $('.api-navbar').toggle(); + }, + + serialize: function() { + return { + endpoint: this.endpoint, + documentation: this.documentation + }; + }, + + hide: function(){ + this.$el.addClass('hide'); + }, + show: function(){ + this.$el.removeClass('hide'); + }, + update: function(endpoint) { + this.show(); + this.endpoint = endpoint[0]; + this.documentation = endpoint[1]; + this.render(); + }, + afterRender: function(){ + ZeroClipboard.config({ moviePath: "/assets/js/plugins/zeroclipboard/ZeroClipboard.swf" }); + var client = new ZeroClipboard(this.$(".copy-url")); + client.on("load", function(e){ + var $apiInput = $('#api-navbar input'); + var copyURLTimer; + client.on("mouseup", function(e){ + $apiInput.css("background-color","#aaa"); + window.clearTimeout(copyURLTimer); + copyURLTimer = setInterval(function () { + $apiInput.css("background-color","#fff"); + }, 200); + }); + }); + } + + }); + + + + Components.Pagination = FauxtonAPI.View.extend({ + className: "pagination pagination-centered", template: "addons/fauxton/templates/pagination", initialize: function(options) { @@ -57,6 +174,7 @@ function(app, FauxtonAPI, ace, spin, ZeroClipboard) { }); Components.IndexPagination = FauxtonAPI.View.extend({ + className: "pagination pagination-centered", template: "addons/fauxton/templates/index_pagination", events: { "click a": 'scrollTo', @@ -453,7 +571,7 @@ function(app, FauxtonAPI, ace, spin, ZeroClipboard) { if (this.mode != "plain") { this.editor.getSession().setMode("ace/mode/" + this.mode); } - + this.editor.setShowPrintMargin(false); this.addCommands(); @@ -624,11 +742,16 @@ function(app, FauxtonAPI, ace, spin, ZeroClipboard) { className: "dropdown", initialize: function(options){ this.links = options.links; + this.icon = options.icon || "fonticon-plus-circled2"; + }, + update: function(links){ + this.links = links; + this.render(); }, serialize: function(){ - var sidebarItem = FauxtonAPI.getExtensions('sidebar:links'); return { - links: this.links + links: this.links, + icon: this.icon }; } }); @@ -656,7 +779,7 @@ function(app, FauxtonAPI, ace, spin, ZeroClipboard) { //need to make this into a backbone view... var routeObjectSpinner; FauxtonAPI.RouteObject.on('beforeEstablish', function (routeObject) { - if (!routeObject.disableLoader){ + if (!routeObject.disableLoader){ var opts = { lines: 16, // The number of lines to draw length: 8, // The length of each line @@ -702,7 +825,7 @@ function(app, FauxtonAPI, ace, spin, ZeroClipboard) { FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) { removeRouteObjectSpinner(); - if (!view.disableLoader){ + if (!view.disableLoader){ var opts = { lines: 16, // The number of lines to draw length: 8, // The length of each line http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/fauxton/resizeColumns.js ---------------------------------------------------------------------- diff --git a/app/addons/fauxton/resizeColumns.js b/app/addons/fauxton/resizeColumns.js index b3d8841..98555a9 100644 --- a/app/addons/fauxton/resizeColumns.js +++ b/app/addons/fauxton/resizeColumns.js @@ -32,7 +32,8 @@ function(FauxtonAPI) { var primaryNavWidth = $('body').hasClass('closeMenu') ? 64 : 220; return primaryNavWidth; }, - getPanelWidth: function(){ + + getSinglePanelWidth: function(){ var sidebarWidth = $('#sidebar-content').length > 0 ? $('#sidebar-content').outerWidth() : 0, borders = parseInt($('#dashboard').css('border-left-width'), 10) + parseInt($('#dashboard-content').css('border-left-width'), 10) + @@ -40,6 +41,16 @@ function(FauxtonAPI) { return (this.getPrimaryNavWidth() + sidebarWidth + borders); }, + + getTwoPanelWidth: function(){ + var borders = parseInt($('#dashboard').css('border-left-width'), 10) + + parseInt($('#right-content').css('border-left-width'), 10) + + parseInt($('#left-content').css('border-right-width'), 10)+ + parseInt($('#left-content').css('border-left-width'), 10) + + parseInt($('#right-content').css('border-right-width'), 10); + return (this.getPrimaryNavWidth()+ borders); + }, + initialize: function(){ // $(window).off('resize'); var that = this; @@ -49,33 +60,63 @@ function(FauxtonAPI) { FauxtonAPI.utils.initWindowResize(); this.onResizeHandler(); }, + updateOptions:function(options){ this.options = {}; this.options = options; }, + turnOff:function(){ FauxtonAPI.utils.removeWindowResize("animation"); }, + cleanupCallback: function(){ this.callback = null; }, + + singlePanelResize: function(){ + var combinedWidth = window.innerWidth - this.getSinglePanelWidth(), + smallWidthConstraint = ($('#sidebar-content').length > 0)? 470:800, + panelWidth; + + if (combinedWidth > smallWidthConstraint) { + panelWidth = combinedWidth; + } else if (combinedWidth < smallWidthConstraint){ + panelWidth = smallWidthConstraint; + } + return panelWidth; + }, + + getPanelWidth: function(){ + var panelWidth; + if ($('#dashboard').hasClass('two-pane')){ + panelWidth = (window.innerWidth - this.getTwoPanelWidth())/2; + } else { + panelWidth = this.singlePanelResize(); + } + return panelWidth; + }, + + setPosition: function(panelWidth){ + var primary = this.getPrimaryNavWidth(); + $('#right-content').css('left',panelWidth+primary+4); + }, + onResizeHandler: function (){ //if there is an override, do that instead if (this.options.onResizeHandler){ this.options.onResizeHandler(); } else { - var combinedWidth = window.innerWidth - this.getPanelWidth(), - smallWidthConstraint = ($('#sidebar-content').length > 0)? 470:800, - panelWidth; - - if (combinedWidth > smallWidthConstraint) { - panelWidth = window.innerWidth - this.getPanelWidth(); - } else if (combinedWidth < smallWidthConstraint){ - panelWidth = smallWidthConstraint; - } + /* + Just so we all are aware: + This entire file and the html of the layouts is bonkers + crazy. I hate what horrible things happened in this file. + It will change soon with a layout overhaul. + */ + var panelWidth = this.getPanelWidth(); + this.setPosition(panelWidth); $('.window-resizeable').innerWidth(panelWidth); - } //if there is a callback, run that if(this.options.callback) { http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/fauxton/templates/breadcrumbs.html ---------------------------------------------------------------------- diff --git a/app/addons/fauxton/templates/breadcrumbs.html b/app/addons/fauxton/templates/breadcrumbs.html index 52ea884..ca073c3 100644 --- a/app/addons/fauxton/templates/breadcrumbs.html +++ b/app/addons/fauxton/templates/breadcrumbs.html @@ -12,13 +12,10 @@ License for the specific language governing permissions and limitations under the License. --> -<ul class="breadcrumb pull-left"> <% _.each(_.initial(crumbs), function(crumb) { %> <li> - <a href="#<%- crumb.link %>"><%- crumb.name %></a> - <span class="divider fonticon fonticon-right-open"> </span> + <a href="#<%- crumb.link %>" class="fonticon <%- crumb.className %>"><%- crumb.name %></a> </li> <% }); %> <% var last = _.last(crumbs) || {name: ''} %> <li class="active"><%- last.name %></li> -</ul> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/fauxton/templates/header_left.html ---------------------------------------------------------------------- diff --git a/app/addons/fauxton/templates/header_left.html b/app/addons/fauxton/templates/header_left.html new file mode 100644 index 0000000..13bea60 --- /dev/null +++ b/app/addons/fauxton/templates/header_left.html @@ -0,0 +1,17 @@ +<!-- +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. +--> +<!--back arrow--> +<div id="header-breadcrumbs"></div> + <!-- Menu gear--> +<div id="header-dropdown-menu"></div> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/fauxton/templates/index_pagination.html ---------------------------------------------------------------------- diff --git a/app/addons/fauxton/templates/index_pagination.html b/app/addons/fauxton/templates/index_pagination.html index f445377..594f6fc 100644 --- a/app/addons/fauxton/templates/index_pagination.html +++ b/app/addons/fauxton/templates/index_pagination.html @@ -12,13 +12,11 @@ License for the specific language governing permissions and limitations under the License. --> -<div class="pagination pagination-centered"> - <ul> - <li <% if (!canShowPreviousfn()) {%> class="disabled" <% } %>> - <a id="previous" href="#"> Previous </a> - </li> - <li <% if (!canShowNextfn()) {%> class="disabled" <% } %>> - <a id="next" href="#"> Next </a></li> - </ul> -</div> +<ul> + <li <% if (!canShowPreviousfn()) {%> class="disabled" <% } %>> + <a id="previous" href="#"> Previous </a> + </li> + <li <% if (!canShowNextfn()) {%> class="disabled" <% } %>> + <a id="next" href="#"> Next </a></li> +</ul> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/fauxton/templates/menu_dropdown.html ---------------------------------------------------------------------- diff --git a/app/addons/fauxton/templates/menu_dropdown.html b/app/addons/fauxton/templates/menu_dropdown.html index ddef343..d1e96af 100644 --- a/app/addons/fauxton/templates/menu_dropdown.html +++ b/app/addons/fauxton/templates/menu_dropdown.html @@ -12,7 +12,7 @@ License for the specific language governing permissions and limitations under the License. --> -<a class="dropdown-toggle icon fonticon-plus-circled2" data-toggle="dropdown" href="#" data-bypass="true"></a> +<a class="dropdown-toggle icon <%=icon%>" data-toggle="dropdown" href="#" data-bypass="true"></a> <ul class="dropdown-menu arrow" role="menu" aria-labelledby="dLabel"> <% _.each(links, function (linkSection) { %> <% if (linkSection.title) { %> @@ -20,9 +20,9 @@ the License. <% } %> <% _.each(linkSection.links, function (link) { %> <li> - <a + <a <% if (link.icon) { %> - class="icon <%- link.icon %>" + class="icon <%- link.icon %>" <% } %> href="<%- link.url %>"> <%- link.title %> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/fauxton/templates/pagination.html ---------------------------------------------------------------------- diff --git a/app/addons/fauxton/templates/pagination.html b/app/addons/fauxton/templates/pagination.html index 0674c22..614fd06 100644 --- a/app/addons/fauxton/templates/pagination.html +++ b/app/addons/fauxton/templates/pagination.html @@ -11,8 +11,6 @@ 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="pagination pagination-centered"> <ul> <% if (page > 1) { %> <li> <a href="<%- urlFun(page-1) %>">«</a></li> @@ -28,4 +26,3 @@ the License. <li class="disabled"> <a href="<%- urlFun(page) %>">»</a></li> <% } %> </ul> -</div> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/assets/less/doc-item.less ---------------------------------------------------------------------- diff --git a/app/addons/indexes/assets/less/doc-item.less b/app/addons/indexes/assets/less/doc-item.less new file mode 100644 index 0000000..a04883a --- /dev/null +++ b/app/addons/indexes/assets/less/doc-item.less @@ -0,0 +1,83 @@ +// 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. +.view table td div.doc-menu-item div.dropdown{ + display: block; +} + +#doc-list{ + margin-top: 30px; + div.doc-row { + margin-bottom:20px; + div.select { + width: 10%; + float: left; + vertical-align: top; + } + .doc-item { + float:left; + width:90%; + vertical-align: top; + position: relative; + .border-radius(5px 5px 5px 5px); + .box-shadow(3px 4px 0 rgba(0, 0, 0, 0.3)); + border: 1px solid #000; + header { + font-weight: bold; + position: relative; + padding: 20px; + background-color: #777; + color: #3a2c2b; + border-bottom: 1px solid #000; + .header-id-number{ + color: #fff; + margin-left: 10px; + } + } + + .doc-data{ + pre.prettyprint{ + } + } + + &:hover{ + .btn-group{ + display:block; + } + } + //temporary + .btn-group{ + position:absolute; + top:10px; + right:10px; + display:none; + } + + .doc-menu { + position:absolute; + right: 0px; + top: 0px; + .doc-menu-item{ + a { + text-decoration: none; + } + .dropdown-menu { + left:auto; + right: 0px; + } + display: inline-block; + width: 30px; + height: 30px; + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/assets/less/index-form.less ---------------------------------------------------------------------- diff --git a/app/addons/indexes/assets/less/index-form.less b/app/addons/indexes/assets/less/index-form.less new file mode 100644 index 0000000..c07163b --- /dev/null +++ b/app/addons/indexes/assets/less/index-form.less @@ -0,0 +1,64 @@ +// 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. +.index-form{ + .control-group { + padding:15px 25px; + border-bottom: 1px solid #D9D9D9; + border-top: 1px solid #fff; + margin: 0 0 0 1px; + > input[type=text]{ + width: 100%; + .border-radius(5px 5px 5px 5px); + } + } + .js-editor { + border: 1px solid #ccc; + .border-radius(5px 5px 5px 5px); + } +} +.input-prepend { + margin-left:0; +} +.new-ddoc { + .select-wrapper { + .border-radius(5px 0 0 5px); + margin-left:0; + overflow: hidden; + border: 1px solid #d0cdc6; + position: relative; + select { + border: 0; + color: #000; + background: transparent; + font-size: 14px; + padding: 5px 10px; + -webkit-appearance: none; + -moz-appearance: window; + height: 44px; + } + i { + position: absolute; + right: 20px; + top: 16px; + display: block; + color: #000; + width: 0; + height: 0; + border-style: solid; + border-width: 10px 7.5px 0 7.5px; + border-color: #000000 transparent transparent transparent; + } + } + input[type=text]{ + .border-radius(0px 5px 5px 0); + } +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/assets/less/indexes.less ---------------------------------------------------------------------- diff --git a/app/addons/indexes/assets/less/indexes.less b/app/addons/indexes/assets/less/indexes.less new file mode 100644 index 0000000..5795cce --- /dev/null +++ b/app/addons/indexes/assets/less/indexes.less @@ -0,0 +1,17 @@ +// 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. +@import "../../../../../assets/less/variables.less"; +@import "../../../../../assets/less/bootstrap/variables.less"; +@import "../../../../../assets/less/bootstrap/mixins.less"; +@import "new-index-placeholder.less"; +@import "index-form.less"; +@import "doc-item.less"; http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/assets/less/new-index-placeholder.less ---------------------------------------------------------------------- diff --git a/app/addons/indexes/assets/less/new-index-placeholder.less b/app/addons/indexes/assets/less/new-index-placeholder.less new file mode 100644 index 0000000..ade1d3a --- /dev/null +++ b/app/addons/indexes/assets/less/new-index-placeholder.less @@ -0,0 +1,25 @@ +// 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. +.watermark-logo { + background: transparent url('../img/couchWatermark.png') no-repeat 50% 50%; + min-height: 400px; + padding-top: 60%; + text-align: center; + h3 { + border-bottom: 1px solid #ccc; + padding-bottom:10px; + margin-bottom:20px; + } + .preview { + margin: 0 10px; + } +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/base.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/base.js b/app/addons/indexes/base.js new file mode 100644 index 0000000..6365c61 --- /dev/null +++ b/app/addons/indexes/base.js @@ -0,0 +1,74 @@ +// 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. + + +/* View Indexes */ +define([ + "app", + "api", + "addons/indexes/routes" +], +function(app, FauxtonAPI, Routes) { + Routes.initialize = function() { + + /* + Example of an extension: + An extension is just like an event that may or may not have listener in another view. + In this case the listener is in the documents addon in the sidebar. + + If there are is a view that you want rendered in another route, this is the way to do it. + + Each Secondary index is going to trigger this event with the views it's passing. + The views will be rendered and have links to the routes defined in this addon. Then it's just business as usual. + + FauxtonAPI.registerExtension('sidebar:list', new Views.IndexMenu({})); + FauxtonAPI.registerExtension('sidebar:links',{ + title: "New View", + url: "new_view" + }); + + + */ + //Show in the sidebar + FauxtonAPI.registerExtension('sidebar:list', { + selector:'views', + ddocType:'view', + icon: "fonticon-sidenav-map-reduce" + }); + FauxtonAPI.registerExtension('sidebar:list', { + selector:'list', + icon: "fonticon-sidenav-list-function" + }); + FauxtonAPI.registerExtension('sidebar:list', { + selector:'show', + icon: "fonticon-sidenav-show-function" + }); + + + /* show in the add new menu dropdown */ + FauxtonAPI.registerExtension('sidebar:links', { + title: "Secondary View", + url: "new_view" + }); + FauxtonAPI.registerExtension('sidebar:links', { + title: "List Function", + url: "new_list" + }); + + FauxtonAPI.registerExtension('sidebar:links', { + url: 'new_show', + title: 'Show Index' + }); + + }; + return Routes; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/index-components.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/index-components.js b/app/addons/indexes/index-components.js new file mode 100644 index 0000000..1ec34e2 --- /dev/null +++ b/app/addons/indexes/index-components.js @@ -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. + + +/* + Index components includes any common, generic, and reusable code for creating secondary indexes + View functions, List functions, Show Functions, and Filter functions, as well as anything created by + couchdb affiliates. +*/ + +define([ + "app", + "api" +], + +function(app, FauxtonAPI) { + var Components = {}; + + + return Components; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/resources.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/resources.js b/app/addons/indexes/resources.js new file mode 100644 index 0000000..626d984 --- /dev/null +++ b/app/addons/indexes/resources.js @@ -0,0 +1,285 @@ +// 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", + "cloudant.pagingcollection" +], + +function(app, FauxtonAPI, PagingCollection) { + var Resources = {}; + + + Resources.QueryParams = (function () { + var _eachParams = function (params, action) { + // clone to avoid in-place modification + var result = _.clone(params); + + _.each(['startkey', 'endkey', 'key'], function (key) { + if (_.has(result, key)) { + result[key] = action(result[key]); + } + }); + + return result; + }; + + return { + parse: function (params) { + return _eachParams(params, JSON.parse); + }, + + stringify: function (params) { + return _eachParams(params, JSON.stringify); + } + }; + })(); + + Resources.ViewRow = FauxtonAPI.Model.extend({ + // this is a hack so that backbone.collections doesn't group + // these by id and reduce the number of items returned. + idAttribute: "_id", + + docType: function() { + if (!this.id) return "reduction"; + + return this.id.match(/^_design/) ? "design doc" : "doc"; + }, + documentation: function(){ + return "docs"; + }, + url: function(context) { + return this.collection.database.url(context) + "/" + this.safeID(); + }, + + isEditable: function() { + return this.docType() != "reduction"; + }, + safeID: function() { + var id = this.id || this.get("id"); + + return app.utils.safeURLName(id); + }, + + prettyJSON: function() { + //var data = this.get("doc") ? this.get("doc") : this; + return JSON.stringify(this, null, " "); + } + }); + + + Resources.PouchIndexCollection = PagingCollection.extend({ + model: Resources.ViewRow, + documentation: function(){ + return "docs"; + }, + initialize: function(_models, options) { + this.database = options.database; + this.rows = options.rows; + this.view = options.view; + this.design = options.design.replace('_design/',''); + this.params = _.extend({limit: 20, reduce: false}, options.params); + + this.idxType = "_view"; + }, + + url: function () { + return ''; + }, + + simple: function () { + var docs = this.map(function (item) { + return { + _id: item.id, + key: item.get('key'), + value: item.get('value') + }; + }); + + return new Resources.PouchIndexCollection(docs, { + database: this.database, + params: this.params, + view: this.view, + design: this.design, + rows: this.rows + }); + + }, + + fetch: function() { + var deferred = FauxtonAPI.Deferred(); + this.reset(this.rows, {silent: true}); + + this.viewMeta = { + total_rows: this.rows.length, + offset: 0, + update_seq: false + }; + + deferred.resolve(); + return deferred; + }, + + totalRows: function() { + return this.viewMeta.total_rows || "unknown"; + }, + + updateSeq: function() { + return this.viewMeta.update_seq || false; + }, + + buildAllDocs: function(){ + this.fetch(); + }, + + allDocs: function(){ + return this.models; + } + }); + + + Resources.IndexCollection = PagingCollection.extend({ + model: Resources.ViewRow, + documentation: function(){ + return "docs"; + }, + initialize: function(_models, options) { + this.database = options.database; + this.params = _.extend({limit: 20, reduce: false}, options.params); + + this.idxType = "_view"; + this.view = options.view; + this.design = options.design.replace('_design/',''); + this.perPageLimit = options.perPageLimit || 20; + + if (!this.params.limit) { + this.params.limit = this.perPageLimit; + } + }, + + urlRef: function(context, params) { + var query = ""; + + if (params) { + if (!_.isEmpty(params)) { + query = "?" + $.param(params); + } else { + query = ''; + } + } else if (this.params) { + var parsedParam = Resources.QueryParams.stringify(this.params); + query = "?" + $.param(parsedParam); + } + + var startOfUrl = app.host; + if (context === 'app') { + startOfUrl = 'database'; + } else if (context === "apiurl"){ + startOfUrl = window.location.origin; + } + var design = app.utils.safeURLName(this.design), + view = app.utils.safeURLName(this.view); + + var url = [startOfUrl, this.database.safeID(), "_design", design, this.idxType, view]; + return url.join("/") + query; + }, + + url: function () { + return this.urlRef.apply(this, arguments); + }, + + totalRows: function() { + if (this.params.reduce) { return "unknown_reduce";} + + return this.viewMeta.total_rows || "unknown"; + }, + + updateSeq: function() { + return this.viewMeta.update_seq || false; + }, + + simple: function () { + var docs = this.map(function (item) { + return { + _id: item.id, + key: item.get('key'), + value: item.get('value') + }; + }); + + return new Resources.IndexCollection(docs, { + database: this.database, + params: this.params, + view: this.view, + design: this.design + }); + }, + + parse: function(resp) { + var rows = resp.rows; + this.endTime = new Date().getTime(); + this.requestDuration = (this.endTime - this.startTime); + + return PagingCollection.prototype.parse.apply(this, arguments); + }, + + buildAllDocs: function(){ + this.fetch(); + }, + + // We implement our own fetch to store the starttime so we that + // we can get the request duration + fetch: function () { + this.startTime = new Date().getTime(); + return PagingCollection.prototype.fetch.call(this); + }, + + allDocs: function(){ + return this.models; + }, + + // This is taken from futon.browse.js $.timeString + requestDurationInString: function () { + var ms, sec, min, h, timeString, milliseconds = this.requestDuration; + + sec = Math.floor(milliseconds / 1000.0); + min = Math.floor(sec / 60.0); + sec = (sec % 60.0).toString(); + if (sec.length < 2) { + sec = "0" + sec; + } + + h = (Math.floor(min / 60.0)).toString(); + if (h.length < 2) { + h = "0" + h; + } + + min = (min % 60.0).toString(); + if (min.length < 2) { + min = "0" + min; + } + + timeString = h + ":" + min + ":" + sec; + + ms = (milliseconds % 1000.0).toString(); + while (ms.length < 3) { + ms = "0" + ms; + } + timeString += "." + ms; + + return timeString; + } + + }); + + return Resources; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/routes-core.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/routes-core.js b/app/addons/indexes/routes-core.js new file mode 100644 index 0000000..354afb0 --- /dev/null +++ b/app/addons/indexes/routes-core.js @@ -0,0 +1,129 @@ +// 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/databases/base", + "addons/indexes/views", + "addons/documents/views", + "addons/indexes/resources" +], + +function (app, FauxtonAPI, Databases, Views, Documents, Resources) { + + var CoreIndexRouteObj = FauxtonAPI.RouteObject.extend({ + layout: "two_pane", + + initialize: function (route, masterLayout, options) { + this.databaseName = options[0]; + + this.data = { + database: new Databases.Model({id:this.databaseName}) + }; + + this.data.designDocs = new Documents.AllDocs(null, { + database: this.data.database, + paging: { + pageSize: 500 + }, + params: { + startkey: '_design', + endkey: '_design1', + include_docs: true, + limit: 500 + } + }); + }, + + events: { + "route:updatePreviewDocs": "updateAllDocsFromPreview" + }, + + ddocInfo: function (designDoc, designDocs, view) { + return { + id: "_design/" + designDoc, + currView: view, + designDocs: designDocs + }; + }, + + createParams: function (options) { + var urlParams = app.getParams(options); + var params = Documents.QueryParams.parse(urlParams); + + return { + urlParams: urlParams, + docParams: _.extend(params, {limit: this.getDocPerPageLimit(params, 20)}) + }; + }, + + getDocPerPageLimit: function (urlParams, perPage) { + var storedPerPage = perPage; + + if (window.localStorage) { + storedPerPage = window.localStorage.getItem('fauxton:perpage'); + + if (!storedPerPage) { + this.setDocPerPageLimit(perPage); + storedPerPage = perPage; + } else { + storedPerPage = parseInt(storedPerPage, 10); + } + } + + if (!urlParams.limit || urlParams.limit > storedPerPage) { + return parseInt(storedPerPage, 10); + } else { + return parseInt(urlParams.limit, 10); + } + }, + + establish: function () { + return this.data.designDocs.fetch({reset: true}); + }, + + createViewDocumentsView: function (options) { + return this.setView("#right-content", new Documents.Views.AllDocsList({ + database: options.database, + collection: options.indexedDocs, + nestedView: Views.Row, + viewList: true, + ddocInfo: this.ddocInfo(options.designDoc, options.designDocs, options.view), + docParams: options.docParams, + params: options.urlParams + })); + }, + + updateAllDocsFromPreview: function (event) { + var view = event.view, + rows = event.rows, + ddoc = event.ddoc; + + this.data.indexedDocs = new Documents.PouchIndexCollection(null, { + database: this.data.database, + design: ddoc, + view: view, + rows: rows + }); + + this.documentsView = this.setView("#right-content", new Documents.Views.AllDocsList({ + database: this.data.database, + collection: this.data.indexedDocs, + nestedView: Views.Row, + viewList: true + })); + } + }); + + return CoreIndexRouteObj; + +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/routes-list.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/routes-list.js b/app/addons/indexes/routes-list.js new file mode 100644 index 0000000..437cef6 --- /dev/null +++ b/app/addons/indexes/routes-list.js @@ -0,0 +1,108 @@ +// 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/databases/base", + "addons/indexes/views", + "addons/documents/views", + "addons/indexes/resources", + "addons/indexes/routes-core", + "addons/fauxton/components" +], + +function (app, FauxtonAPI, Databases, Views, Documents, Resources, RouteCore, Components) { + + var ListIndexes = RouteCore.extend({ + routes: { + "database/:database/_design/:ddoc/_lists/:fn": { + route: "tempFn", + roles: ['_admin'] + }, + "database/:database/new_list": "newListsEditor", + "database/:database/new_list/:designDoc": "newListsEditor" + }, + + apiUrl: function() { + //TODO: Hook up proper API urls + return ''; + }, + + newListsEditor: function (database, designDoc) { + var params = app.getParams(); + + /* -------------------------------------------------- + Insert View Editor for new list + ----------------------------------------------------*/ + this.setView("#left-content", new Views.ListEditor({ + model: this.data.database, + currentddoc: designDoc ? "_design/"+designDoc : "", + ddocs: this.data.designDocs, + params: params, + database: this.data.database, + newView: true + })); + /* -------------------------------------------------- + Insert Preview Screen View + ----------------------------------------------------*/ + this.setView("#right-content", new Views.PreviewScreen({})); + + /* -------------------------------------------------- + Set up & Insert breadcrumb header + ----------------------------------------------------*/ + var crumbs = [ + {"name": "", "className": "fonticon-left-open", "link": Databases.databaseUrl(this.data.database)}, + {"name": "Create a List Index", "link": Databases.databaseUrl(this.data.database)} + ]; + this.leftheader = this.setView("#breadcrumbs", new Components.LeftHeader({ + crumbs: crumbs + })); + }, + tempFn: function(databaseName, ddoc, view){ + /* -------------------------------------------------- + Set up breadcrumb header + ----------------------------------------------------*/ + var crumbs = [ + {"name": "", "className": "fonticon-left-open", "link": Databases.databaseUrl(this.data.database)}, + {"name": view, "link": Databases.databaseUrl(this.data.database)} + ]; + + var dropdown = [{ + links: [{ + title: 'Duplicate Index', + icon: 'fonticon-documents' + },{ + title: 'Delete', + icon: 'fonticon-trash' + }] + }]; + + this.leftheader = this.setView("#breadcrumbs", new Components.LeftHeader({ + crumbs: crumbs, + dropdownMenu: dropdown + })); + + + /* -------------------------------------------------- + Insert List Editor + ----------------------------------------------------*/ + this.setView("#left-content", new Views.ListEditor({})); + + /* -------------------------------------------------- + Insert Preview Screen View + ----------------------------------------------------*/ + this.setView("#right-content", new Views.PreviewScreen({})); + } + }); + + return ListIndexes; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/routes-show.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/routes-show.js b/app/addons/indexes/routes-show.js new file mode 100644 index 0000000..73f52d1 --- /dev/null +++ b/app/addons/indexes/routes-show.js @@ -0,0 +1,103 @@ +// 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/databases/base", + "addons/indexes/views", + "addons/documents/views", + "addons/indexes/resources", + "addons/indexes/routes-core", + "addons/fauxton/components" +], + +function (app, FauxtonAPI, Databases, Views, Documents, Resources, RouteCore, Components) { + + var ShowIndexes = RouteCore.extend({ + routes: { + "database/:database/_design/:ddoc/_show/:fn": { + route: "tempFn", + roles: ['_admin'] + }, + "database/:database/new_show": "newShowEditor", + "database/:database/new_show/:designDoc": "newShowEditor" + }, + + newShowEditor: function (database, designDoc) { + var params = app.getParams(); + /* -------------------------------------------------- + Insert View Editor for new view + ----------------------------------------------------*/ + this.setView("#left-content", new Views.ShowEditor({ + model: this.data.database, + currentddoc: designDoc ? "_design/"+designDoc : "", + ddocs: this.data.designDocs, + params: params, + database: this.data.database, + newView: true + })); + + /* -------------------------------------------------- + Insert Preview Screen View + ----------------------------------------------------*/ + this.setView("#right-content", new Views.PreviewScreen({})); + + /* -------------------------------------------------- + Set up & Insert breadcrumb header + ----------------------------------------------------*/ + var crumbs = [ + {"name": "", "className": "fonticon-left-open", "link": Databases.databaseUrl(this.data.database)}, + {"name": "Create a Show Index", "link": Databases.databaseUrl(this.data.database)} + ]; + this.leftheader = this.setView("#breadcrumbs", new Components.LeftHeader({ + crumbs: crumbs + })); + }, + tempFn: function(databaseName, ddoc, view){ + /* -------------------------------------------------- + Set up breadcrumb header + ----------------------------------------------------*/ + var crumbs = [ + {"name": "", "className": "fonticon-left-open", "link": Databases.databaseUrl(this.data.database)}, + {"name": view, "link": Databases.databaseUrl(this.data.database)} + ]; + + var dropdown = [{ + links: [{ + title: 'Duplicate Index', + icon: 'fonticon-documents' + },{ + title: 'Delete', + icon: 'fonticon-trash' + }] + }]; + + this.leftheader = this.setView("#breadcrumbs", new Components.LeftHeader({ + crumbs: crumbs, + dropdownMenu: dropdown + })); + + + /* -------------------------------------------------- + Insert Show Editor + ----------------------------------------------------*/ + this.setView("#left-content", new Views.ListEditor({})); + + /* -------------------------------------------------- + Insert Preview Screen View + ----------------------------------------------------*/ + this.setView("#right-content", new Views.PreviewScreen({})); + } + }); + + return ShowIndexes; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/app/addons/indexes/routes-viewindexes.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/routes-viewindexes.js b/app/addons/indexes/routes-viewindexes.js new file mode 100644 index 0000000..7330d04 --- /dev/null +++ b/app/addons/indexes/routes-viewindexes.js @@ -0,0 +1,156 @@ +// 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/databases/base", + "addons/indexes/views", + "addons/documents/views", + "addons/indexes/resources", + "addons/indexes/routes-core", + "addons/fauxton/components" +], + +function (app, FauxtonAPI, Databases, Views, Documents, Resources, RouteCore, Components) { + + var ViewIndexes = RouteCore.extend({ + routes: { + "database/:database/_design/:ddoc/_view/:view": { + route: "viewFn", + roles: ['_admin'] + }, + "database/:database/new_view": "newViewEditor", + "database/:database/new_view/:designDoc": "newViewEditor" + }, + + newViewEditor: function (database, designDoc) { + var params = app.getParams(); + /* -------------------------------------------------- + remove right header + ----------------------------------------------------*/ + this.rightheader && this.rightheader.remove(); + + /* -------------------------------------------------- + Insert Preview Screen View + ----------------------------------------------------*/ + this.setView("#right-content", new Views.PreviewScreen({})); + + /* -------------------------------------------------- + Insert View Editor for new view + ----------------------------------------------------*/ + this.viewEditor = this.setView("#left-content", new Views.ViewEditor({ + model: this.data.database, + currentddoc: designDoc ? "_design/"+designDoc : "", + ddocs: this.data.designDocs, + params: params, + database: this.data.database, + newView: true + })); + + /* -------------------------------------------------- + Set up & Insert breadcrumb header + ----------------------------------------------------*/ + var crumbs = [ + {"name": "", "className": "fonticon-left-open", "link": Databases.databaseUrl(this.data.database)}, + {"name": "Create a View Index", "link": Databases.databaseUrl(this.data.database)} + ]; + this.leftheader = this.setView("#breadcrumbs", new Components.LeftHeader({ + crumbs: crumbs + })); + + }, + + viewFn: function (databaseName, ddoc, view) { + var params = this.createParams(), + urlParams = params.urlParams, + docParams = params.docParams, + decodeDdoc = decodeURIComponent(ddoc); + view = view.replace(/\?.*$/,''); + + /* -------------------------------------------------- + Set up breadcrumb header + ----------------------------------------------------*/ + var crumbs = [ + {"name": "", "className": "fonticon-left-open", "link": Databases.databaseUrl(this.data.database)}, + {"name": view, "link": Databases.databaseUrl(this.data.database)} + ]; + + var dropdown = [{ + links: [{ + title: 'Duplicate Index', + icon: 'fonticon-documents' + },{ + title: 'Delete', + icon: 'fonticon-trash' + }] + }]; + + this.leftheader = this.setView("#breadcrumbs", new Components.LeftHeader({ + crumbs: crumbs, + dropdownMenu: dropdown + })); + + /* -------------------------------------------------- + Set up Index Collection + ----------------------------------------------------*/ + this.data.indexedDocs = new Resources.IndexCollection(null, { + database: this.data.database, + design: decodeDdoc, + view: view, + params: docParams, + paging: { + pageSize: this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10)) + } + }); + + + /* -------------------------------------------------- + Set up right header + ----------------------------------------------------*/ + + this.rightheader = this.setView("#api-navbar", new Views.RightHeader({ + database: this.data.database, + model: this.data.database, + endpoint: this.data.indexedDocs.urlRef("apiurl", urlParams), + documentation: "docs" + })); + + /* -------------------------------------------------- + Insert View Editor + ----------------------------------------------------*/ + this.viewEditor = this.setView("#left-content", new Views.ViewEditor({ + model: this.data.database, + ddocs: this.data.designDocs, + viewName: view, + params: urlParams, + newView: false, + database: this.data.database, + ddocInfo: this.ddocInfo(decodeDdoc, this.data.designDocs, view) + })); + + /* -------------------------------------------------- + Insert Docs returned from view + ----------------------------------------------------*/ + this.documentsView = this.createViewDocumentsView({ + designDoc: decodeDdoc, + docParams: docParams, + urlParams: urlParams, + database: this.data.database, + indexedDocs: this.data.indexedDocs, + designDocs: this.data.designDocs, + view: view + }); + } + }); + + return ViewIndexes; +});
