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:25:13 UTC
[64/64] [abbrv] fauxton commit: updated refs/heads/secondary-indexes
to ef01e24
Ripping out views into it's own addon
Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/ef01e241
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/ef01e241
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/ef01e241
Branch: refs/heads/secondary-indexes
Commit: ef01e241b449d4679b933d7972e0742bf49ea2d5
Parents: fe48dc9
Author: deathbearbrown <de...@gmail.com>
Authored: Tue Jul 22 16:40:06 2014 -0400
Committer: deathbearbrown <de...@gmail.com>
Committed: Wed Jul 23 15:23:56 2014 -0400
----------------------------------------------------------------------
app/addons/documents/routes.js | 102 +---
.../templates/design_doc_selector.html | 38 --
app/addons/documents/templates/view_editor.html | 91 ---
app/addons/documents/views-index.js | 574 -------------------
app/addons/indexes/index-components.js | 2 +
app/addons/indexes/routes-filter.js | 47 ++
app/addons/indexes/routes-list.js | 47 ++
app/addons/indexes/routes-show.js | 47 ++
app/addons/indexes/routes-viewindexes.js | 204 +++++++
app/addons/indexes/routes.js | 24 +-
.../indexes/templates/design_doc_selector.html | 38 ++
app/addons/indexes/templates/view_editor.html | 70 +++
app/addons/indexes/views.js | 559 +++++++++++++++++-
settings.json.default | 1 +
14 files changed, 1021 insertions(+), 823 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
index 9c266be..449e50e 100644
--- a/app/addons/documents/routes.js
+++ b/app/addons/documents/routes.js
@@ -19,14 +19,13 @@ define([
//views
"addons/documents/views",
"addons/documents/views-changes",
- "addons/documents/views-index",
"addons/documents/views-doceditor",
"addons/databases/base",
"addons/documents/resources"
],
-function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resources) {
+function(app, FauxtonAPI, Documents, Changes, DocEditor, Databases, Resources) {
var DocEditorRouteObject = FauxtonAPI.RouteObject.extend({
layout: "one_pane",
@@ -133,28 +132,10 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
route: "allDocs",
roles: ["_reader","_writer","_admin"]
},
- "database/:database/_design/:ddoc/_view/:view": {
- route: "viewFn",
- roles: ['_admin']
- },
- "database/:database/_design/:ddoc/_lists/:fn": {
- route: "tempFn",
- roles: ['_admin']
- },
- "database/:database/_design/:ddoc/_filters/:fn": {
- route: "tempFn",
- roles: ['_admin']
- },
- "database/:database/_design/:ddoc/_show/:fn": {
- route: "tempFn",
- roles: ['_admin']
- },
"database/:database/_design/:ddoc/metadata": {
route: "designDocMetadata",
roles: ['_admin']
},
- "database/:database/new_view": "newViewEditor",
- "database/:database/new_view/:designDoc": "newViewEditor",
"database/:database/_changes(:params)": "changes"
},
@@ -213,15 +194,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
this.apiUrl = [designDocInfo.url('apiurl'), designDocInfo.documentation() ];
},
- tempFn: function(databaseName, ddoc, fn){
- this.setView("#dashboard-upper-content", new Documents.Views.temp({}));
- this.crumbs = function () {
- return [
- {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
- ];
- };
-
- },
establish: function () {
return this.data.designDocs.fetch({reset: true});
@@ -286,56 +258,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
this.apiUrl = [this.data.database.allDocs.urlRef("apiurl", urlParams), this.data.database.allDocs.documentation() ];
},
- viewFn: function (databaseName, ddoc, view) {
- var params = this.createParams(),
- urlParams = params.urlParams,
- docParams = params.docParams,
- decodeDdoc = decodeURIComponent(ddoc);
-
- view = view.replace(/\?.*$/,'');
-
- this.data.indexedDocs = new Documents.IndexCollection(null, {
- database: this.data.database,
- design: decodeDdoc,
- view: view,
- params: docParams,
- paging: {
- pageSize: this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10))
- }
- });
-
- this.viewEditor = this.setView("#dashboard-upper-content", new Index.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)
- }));
-
- this.toolsView && this.toolsView.remove();
-
- this.documentsView = this.createViewDocumentsView({
- designDoc: decodeDdoc,
- docParams: docParams,
- urlParams: urlParams,
- database: this.data.database,
- indexedDocs: this.data.indexedDocs,
- designDocs: this.data.designDocs,
- view: view
- });
-
- this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + '_' + app.utils.removeSpecialCharacters(view));
-
- this.crumbs = function () {
- return [
- {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
- ];
- };
-
- this.apiUrl = [this.data.indexedDocs.urlRef("apiurl", urlParams), "docs"];
- },
ddocInfo: function (designDoc, designDocs, view) {
return {
@@ -358,28 +280,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou
}));
},
- newViewEditor: function (database, designDoc) {
- var params = app.getParams();
-
- this.toolsView && this.toolsView.remove();
- this.documentsView && this.documentsView.remove();
-
- this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditor({
- currentddoc: "_design/"+designDoc || "",
- ddocs: this.data.designDocs,
- params: params,
- database: this.data.database,
- newView: true
- }));
-
- this.sidebar.setSelectedTab('new-view');
- this.crumbs = function () {
- return [
- {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
- ];
- };
- },
-
updateAllDocsFromView: function (event) {
var view = event.view,
params = this.createParams(),
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/app/addons/documents/templates/design_doc_selector.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/design_doc_selector.html b/app/addons/documents/templates/design_doc_selector.html
deleted file mode 100644
index 828b5a5..0000000
--- a/app/addons/documents/templates/design_doc_selector.html
+++ /dev/null
@@ -1,38 +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.
--->
-<div class="span3">
- <label for="ddoc">Save to Design Document <a class="help-link" href="<%-getDocUrl('design_doc')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
- <select id="ddoc">
- <optgroup label="Select a document">
- <option value="new-doc">New document</option>
-
- <% ddocs.each(function(ddoc) { %>
- <%= ddoc.id %>
- <%= ddocName %>
- <% if (ddoc.id === ddocName) { %>
- <option selected="selected" value="<%- ddoc.id %>"><%- ddoc.id %></option>
- <% } else { %>
- <option value="<%- ddoc.id %>"><%- ddoc.id %></option>
- <% } %>
- <% }); %>
- </optgroup>
- </select>
-</div>
-
-<div id="new-ddoc-section" class="span5" style="display:none">
- <label class="control-label" for="new-ddoc"> _design/ </label>
- <div class="controls">
- <input type="text" id="new-ddoc" placeholder="newDesignDoc" />
- </div>
-</div>
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/app/addons/documents/templates/view_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/view_editor.html b/app/addons/documents/templates/view_editor.html
deleted file mode 100644
index e6fbbc1..0000000
--- a/app/addons/documents/templates/view_editor.html
+++ /dev/null
@@ -1,91 +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.
--->
-<div class="dashboard-upper-menu">
- <ul class="nav nav-tabs" id="db-views-tabs-nav">
- <li class="active"> <a data-bypass="true" id="index-nav" data-toggle="tab" href="#index">
- <i class="fonticon-wrench fonticon"></i>
- <% if (newView) { %>Create Index <% } else { %>Edit Index <% } %></a></li>
- <% if (!newView) { %>
- <li><a data-bypass="true" id="query-nav" href="#query" data-toggle="tab">
- <i class="fonticon-plus fonticon"></i> Query Options</a>
- </li>
- <% } %>
- </ul>
-</div>
- <div class="all-docs-list errors-container"></div>
- <div class="tab-content">
- <div id="query-options-wrapper"></div>
- <div class="tab-pane active" id="index">
- <div id="define-view" class="ddoc-alert well">
- <div class="errors-container"></div>
- <form class="form-horizontal view-query-save">
-
- <div class="control-group design-doc-group">
- </div>
-
- <div class="control-group">
- <label for="index-name">Index name <a class="help-link" href="<%-getDocUrl('view_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
- <input type="text" id="index-name" value="<%- viewName %>" placeholder="Index name" />
- </div>
-
-
- <div class="control-group">
- <label for="map-function">Map function <a class="help-link" href="<%-getDocUrl('map_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
- <% if (newView) { %>
- <div class="js-editor" id="map-function"><%= langTemplates.map %></div>
- <% } else { %>
- <div class="js-editor" id="map-function"><%- ddoc.get('views')[viewName].map %></div>
- <button class="beautify beautify_map btn btn-primary btn-large hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
- <% } %>
- </div>
-
-
- <div class="control-group">
- <label for="reduce-function-selector">Reduce (optional) <a class="help-link" href="<%-getDocUrl('reduce_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-
- <select id="reduce-function-selector">
- <option value="" <%- !reduceFunStr ? 'selected="selected"' : '' %>>None</option>
- <% _.each(["_sum", "_count", "_stats"], function(reduce) { %>
- <option value="<%- reduce %>" <% if (reduce == reduceFunStr) { %>selected<% } %>><%= reduce %></option>
- <% }) %>
- <option value="CUSTOM" <% if (isCustomReduce) { %>selected<% } %>>Custom Reduce function</option>
- </select>
- </div>
-
- <div class="control-group reduce-function">
- <label for="reduce-function">Custom Reduce function</label>
- <% if (newView) { %>
- <div class="js-editor" id="reduce-function"><%- langTemplates.reduce %></div>
- <% } else { %>
- <div class="js-editor" id="reduce-function"><%- ddoc.get('views')[viewName].reduce %></div>
- <button class="beautify beautify_reduce btn btn-primary btn-large hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
- <% } %>
- </div>
-
- <div class="control-group">
- <button class="btn btn-success save"><i class="icon fonticon-ok-circled"></i> Save & Build Index</button>
- <% if (!newView) { %>
- <button class="btn btn-danger delete"><i class="icon fonticon-cancel-circled"></i> Delete</button>
- <% } %>
- </div>
- <div class="clearfix"></div>
- </form>
- </div>
- </div>
- <div class="tab-pane" id="metadata">
- <div id="ddoc-info" class="well"> </div>
- </div>
- <div class="tab-pane" id="query">
- </div>
- </div>
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/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/ef01e241/app/addons/indexes/index-components.js
----------------------------------------------------------------------
diff --git a/app/addons/indexes/index-components.js b/app/addons/indexes/index-components.js
index ffb22a0..1ec34e2 100644
--- a/app/addons/indexes/index-components.js
+++ b/app/addons/indexes/index-components.js
@@ -23,6 +23,8 @@ define([
],
function(app, FauxtonAPI) {
+ var Components = {};
+ return Components;
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/app/addons/indexes/routes-filter.js
----------------------------------------------------------------------
diff --git a/app/addons/indexes/routes-filter.js b/app/addons/indexes/routes-filter.js
new file mode 100644
index 0000000..492b014
--- /dev/null
+++ b/app/addons/indexes/routes-filter.js
@@ -0,0 +1,47 @@
+// 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 FilterIndexes = FauxtonAPI.RouteObject.extend({
+ layout: "two_pane",
+ routes: {
+ "database/:database/_design/:ddoc/_filters/:fn": {
+ route: "tempFn",
+ roles: ['_admin']
+ },
+ "database/:database/new_filter": "newFilterEditor",
+ "database/:database/new_filter/:designDoc": "newFilterEditor"
+ },
+ newFilterEditor: function(){
+ return false;
+ },
+ tempFn: function(databaseName, ddoc, fn){
+ this.setView("#dashboard-upper-content", new Documents.Views.temp({}));
+ this.crumbs = function () {
+ return [
+ {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
+ ];
+ };
+ }
+ });
+
+ return FilterIndexes;
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/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..10141b7
--- /dev/null
+++ b/app/addons/indexes/routes-list.js
@@ -0,0 +1,47 @@
+// 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 ListIndexes = FauxtonAPI.RouteObject.extend({
+ layout: "two_pane",
+ routes: {
+ "database/:database/_design/:ddoc/_lists/:fn": {
+ route: "tempFn",
+ roles: ['_admin']
+ },
+ "database/:database/new_lists": "newListsEditor",
+ "database/:database/new_lists/:designDoc": "newListsEditor"
+ },
+ newListsEditor: function(){
+ return false;
+ },
+ tempFn: function(databaseName, ddoc, fn){
+ this.setView("#dashboard-upper-content", new Documents.Views.temp({}));
+ this.crumbs = function () {
+ return [
+ {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
+ ];
+ };
+ }
+ });
+
+ return ListIndexes;
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/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..1861fd1
--- /dev/null
+++ b/app/addons/indexes/routes-show.js
@@ -0,0 +1,47 @@
+// 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 ShowIndexes = FauxtonAPI.RouteObject.extend({
+ layout: "two_pane",
+ routes: {
+ "database/:database/_design/:ddoc/_show/:fn": {
+ route: "tempFn",
+ roles: ['_admin']
+ },
+ "database/:database/new_show": "newShowEditor",
+ "database/:database/new_show/:designDoc": "newShowEditor"
+ },
+ newShowEditor: function(){
+ return false;
+ },
+ tempFn: function(databaseName, ddoc, fn){
+ this.setView("#dashboard-upper-content", new Documents.Views.temp({}));
+ this.crumbs = function () {
+ return [
+ {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
+ ];
+ };
+ }
+ });
+
+ return ShowIndexes;
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/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..9577cbb
--- /dev/null
+++ b/app/addons/indexes/routes-viewindexes.js
@@ -0,0 +1,204 @@
+// 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 ViewIndexes = FauxtonAPI.RouteObject.extend({
+ layout: "two_pane",
+ routes: {
+ "database/:database/_design/:ddoc/_view/:view": {
+ route: "viewFn",
+ roles: ['_admin']
+ },
+ "database/:database/new_view": "newViewEditor",
+ "database/:database/new_view/:designDoc": "newViewEditor"
+ },
+ 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
+ }
+ });
+ },
+
+
+ createViewDocumentsView: function (options) {
+ return this.setView("#right-content", new Documents.Views.AllDocsList({
+ database: options.database,
+ collection: options.indexedDocs,
+ nestedView: Documents.Views.Row,
+ viewList: true,
+ ddocInfo: this.ddocInfo(options.designDoc, options.designDocs, options.view),
+ docParams: options.docParams,
+ params: options.urlParams
+ }));
+ },
+
+ 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});
+ },
+
+ 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("#dashboard-lower-content", new Documents.Views.AllDocsList({
+ // database: this.data.database,
+ // collection: this.data.indexedDocs,
+ // nestedView: Documents.Views.Row,
+ // viewList: true
+ // }));
+ },
+
+ newViewEditor: function (database, designDoc) {
+ var params = app.getParams();
+
+ this.toolsView && this.toolsView.remove();
+ this.documentsView && this.documentsView.remove();
+
+ this.viewEditor = this.setView("#left-content", new Views.ViewEditor({
+ currentddoc: "_design/"+designDoc || "",
+ ddocs: this.data.designDocs,
+ params: params,
+ database: this.data.database,
+ newView: true
+ }));
+
+ this.sidebar.setSelectedTab('new-view');
+ this.crumbs = function () {
+ return [
+ {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
+ ];
+ };
+ },
+
+ viewFn: function (databaseName, ddoc, view) {
+ var params = this.createParams(),
+ urlParams = params.urlParams,
+ docParams = params.docParams,
+ decodeDdoc = decodeURIComponent(ddoc);
+
+ view = view.replace(/\?.*$/,'');
+
+ this.data.indexedDocs = new Documents.IndexCollection(null, {
+ database: this.data.database,
+ design: decodeDdoc,
+ view: view,
+ params: docParams,
+ paging: {
+ pageSize: this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10))
+ }
+ });
+
+ 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)
+ }));
+
+ this.toolsView && this.toolsView.remove();
+
+ this.documentsView = this.createViewDocumentsView({
+ designDoc: decodeDdoc,
+ docParams: docParams,
+ urlParams: urlParams,
+ database: this.data.database,
+ indexedDocs: this.data.indexedDocs,
+ designDocs: this.data.designDocs,
+ view: view
+ });
+
+
+ this.crumbs = function () {
+ return [
+ {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
+ ];
+ };
+
+ this.apiUrl = [this.data.indexedDocs.urlRef("apiurl", urlParams), "docs"];
+ }
+ });
+
+ return ViewIndexes;
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/app/addons/indexes/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/indexes/routes.js b/app/addons/indexes/routes.js
index 4c7515d..52771d6 100644
--- a/app/addons/indexes/routes.js
+++ b/app/addons/indexes/routes.js
@@ -12,22 +12,14 @@
define([
"app",
"api",
- "addons/indexes/resources",
- "addons/indexes/views"
+ "addons/indexes/views",
+ "addons/indexes/routes-viewindexes",
+ "addons/indexes/routes-filter",
+ "addons/indexes/routes-show",
+ "addons/indexes/routes-list",
],
-function (app, FauxtonAPI, Resources, Views) {
-
- var ViewIndexes = FauxtonAPI.RouteObject.extend({});
-
- var FilterIndexes = FauxtonAPI.RouteObject.extend({});
-
- var ShowIndexes = FauxtonAPI.RouteObject.extend({});
-
- var ListIndexes = FauxtonAPI.RouteObject.extend({});
-
-
- Resources.RouteObjects = [ViewIndexes, FilterIndexes, ShowIndexes, ListIndexes];
-
- return Resources;
+function (app, FauxtonAPI, Views, ViewIndex, Filter, Show, List) {
+ Views.RouteObjects = [ViewIndex, Filter, Show, List];
+ return Views;
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/app/addons/indexes/templates/design_doc_selector.html
----------------------------------------------------------------------
diff --git a/app/addons/indexes/templates/design_doc_selector.html b/app/addons/indexes/templates/design_doc_selector.html
new file mode 100644
index 0000000..828b5a5
--- /dev/null
+++ b/app/addons/indexes/templates/design_doc_selector.html
@@ -0,0 +1,38 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<div class="span3">
+ <label for="ddoc">Save to Design Document <a class="help-link" href="<%-getDocUrl('design_doc')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+ <select id="ddoc">
+ <optgroup label="Select a document">
+ <option value="new-doc">New document</option>
+
+ <% ddocs.each(function(ddoc) { %>
+ <%= ddoc.id %>
+ <%= ddocName %>
+ <% if (ddoc.id === ddocName) { %>
+ <option selected="selected" value="<%- ddoc.id %>"><%- ddoc.id %></option>
+ <% } else { %>
+ <option value="<%- ddoc.id %>"><%- ddoc.id %></option>
+ <% } %>
+ <% }); %>
+ </optgroup>
+ </select>
+</div>
+
+<div id="new-ddoc-section" class="span5" style="display:none">
+ <label class="control-label" for="new-ddoc"> _design/ </label>
+ <div class="controls">
+ <input type="text" id="new-ddoc" placeholder="newDesignDoc" />
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/app/addons/indexes/templates/view_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/indexes/templates/view_editor.html b/app/addons/indexes/templates/view_editor.html
new file mode 100644
index 0000000..afc7454
--- /dev/null
+++ b/app/addons/indexes/templates/view_editor.html
@@ -0,0 +1,70 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<div class="all-docs-list errors-container"></div>
+<div id="define-view" class="ddoc-alert well">
+ <div class="errors-container"></div>
+ <form class="form-horizontal view-query-save">
+
+ <div class="control-group design-doc-group">
+ </div>
+
+ <div class="control-group">
+ <label for="index-name">Index name <a class="help-link" href="<%-getDocUrl('view_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+ <input type="text" id="index-name" value="<%- viewName %>" placeholder="Index name" />
+ </div>
+
+
+ <div class="control-group">
+ <label for="map-function">Map function <a class="help-link" href="<%-getDocUrl('map_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+ <% if (newView) { %>
+ <div class="js-editor" id="map-function"><%= langTemplates.map %></div>
+ <% } else { %>
+ <div class="js-editor" id="map-function"><%- ddoc.get('views')[viewName].map %></div>
+ <button class="beautify beautify_map btn btn-primary btn-large hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
+ <% } %>
+ </div>
+
+
+ <div class="control-group">
+ <label for="reduce-function-selector">Reduce (optional) <a class="help-link" href="<%-getDocUrl('reduce_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+
+ <select id="reduce-function-selector">
+ <option value="" <%- !reduceFunStr ? 'selected="selected"' : '' %>>None</option>
+ <% _.each(["_sum", "_count", "_stats"], function(reduce) { %>
+ <option value="<%- reduce %>" <% if (reduce == reduceFunStr) { %>selected<% } %>><%= reduce %></option>
+ <% }) %>
+ <option value="CUSTOM" <% if (isCustomReduce) { %>selected<% } %>>Custom Reduce function</option>
+ </select>
+ </div>
+
+ <div class="control-group reduce-function">
+ <label for="reduce-function">Custom Reduce function</label>
+ <% if (newView) { %>
+ <div class="js-editor" id="reduce-function"><%- langTemplates.reduce %></div>
+ <% } else { %>
+ <div class="js-editor" id="reduce-function"><%- ddoc.get('views')[viewName].reduce %></div>
+ <button class="beautify beautify_reduce btn btn-primary btn-large hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
+ <% } %>
+ </div>
+
+ <div class="control-group">
+ <button class="btn btn-success save"><i class="icon fonticon-ok-circled"></i> Save & Build Index</button>
+ <% if (!newView) { %>
+ <button class="btn btn-danger delete"><i class="icon fonticon-cancel-circled"></i> Delete</button>
+ <% } %>
+ </div>
+ <div class="clearfix"></div>
+ </form>
+</div>
+
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ef01e241/app/addons/indexes/views.js
----------------------------------------------------------------------
diff --git a/app/addons/indexes/views.js b/app/addons/indexes/views.js
index e8383cf..42a9066 100644
--- a/app/addons/indexes/views.js
+++ b/app/addons/indexes/views.js
@@ -9,13 +9,566 @@
// 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"
+ "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) {
+function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
+ QueryOptions, resizeColumns, beautify, prettify) {
+
var Views = {};
+ Views.ViewEditor = FauxtonAPI.View.extend({
+ template: "addons/indexes/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/indexes/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/ef01e241/settings.json.default
----------------------------------------------------------------------
diff --git a/settings.json.default b/settings.json.default
index bc5a617..d278368 100644
--- a/settings.json.default
+++ b/settings.json.default
@@ -3,6 +3,7 @@
{ "name": "fauxton" },
{ "name": "databases" },
{ "name": "documents" },
+ { "name": "indexes" },
{ "name": "pouchdb" },
{ "name": "activetasks" },
{ "name": "config" },