http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/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/28333566/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/28333566/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/28333566/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/28333566/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/28333566/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/28333566/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..6336771 --- /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: 80%; + 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/28333566/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/28333566/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/28333566/app/addons/indexes/less/indexes.less ---------------------------------------------------------------------- diff --git a/app/addons/indexes/less/indexes.less b/app/addons/indexes/less/indexes.less new file mode 100644 index 0000000..d526ee9 --- /dev/null +++ b/app/addons/indexes/less/indexes.less @@ -0,0 +1,13 @@ +// 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 "new-index-placeholder.less"; http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/addons/indexes/less/new-index-placeholder.less ---------------------------------------------------------------------- diff --git a/app/addons/indexes/less/new-index-placeholder.less b/app/addons/indexes/less/new-index-placeholder.less new file mode 100644 index 0000000..3f5db0e --- /dev/null +++ b/app/addons/indexes/less/new-index-placeholder.less @@ -0,0 +1,3 @@ +.watermark-logo { + background: transparent url(../img/couchWatermark.png') no-repeat 0 0; +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/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/28333566/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/28333566/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..1245c24 --- /dev/null +++ b/app/addons/indexes/routes-list.js @@ -0,0 +1,71 @@ +// 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" +], + +function (app, FauxtonAPI, Databases, Views, Documents, Resources, RouteCore) { + + 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(); + + 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 + })); + + this.setView("#right-content", new Views.PreviewScreen({})); + this.crumbs = function () { + return [ + {"name": "Create List Index", "link": Databases.databaseUrl(this.data.database)}, + ]; + }; + }, + tempFn: function(databaseName, ddoc, fn){ + this.setView("#left-content", new Views.ListEditor({})); + + this.setView("#right-content", new Views.PreviewScreen({})); + 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/28333566/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..10a3a56 --- /dev/null +++ b/app/addons/indexes/routes-show.js @@ -0,0 +1,72 @@ +// 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" +], + +function (app, FauxtonAPI, Databases, Views, Documents, Resources, RouteCore) { + + 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(); + + 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 + })); + + this.setView("#right-content", new Views.PreviewScreen({})); + this.crumbs = function () { + return [ + {"name": "Create Show Index", "link": Databases.databaseUrl(this.data.database)}, + ]; + }; + }, + + apiUrl: function() { + //TODO: Hook up proper API urls + return ''; + }, + + tempFn: function(databaseName, ddoc, fn){ + this.setView("#left-content", new Views.ShowEditor({})); + + this.setView("#right-content", new Views.PreviewScreen({})); + 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/28333566/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..de53981 --- /dev/null +++ b/app/addons/indexes/routes-viewindexes.js @@ -0,0 +1,107 @@ +// 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" +], + +function (app, FauxtonAPI, Databases, Views, Documents, Resources, RouteCore) { + + 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(); + this.rightheader && this.rightheader.remove(); + + this.setView("#right-content", new Views.PreviewScreen({})); + + 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 + })); + + this.leftheader = this.setView("#breadcrumbs", new Views.LeftHeader({ + title:"Create a View Index", + database: 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.leftheader = this.setView("#breadcrumbs", new Views.LeftHeader({ + title: view, + database: this.data.database + })); + + this.rightheader = this.setView("#api-bar", new Views.RightHeader({ + database: this.data.database + })); + + 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)) + } + }); + + 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.documentsView = this.createViewDocumentsView({ + designDoc: decodeDdoc, + docParams: docParams, + urlParams: urlParams, + database: this.data.database, + indexedDocs: this.data.indexedDocs, + designDocs: this.data.designDocs, + view: view + }); + + this.apiUrl = [this.data.indexedDocs.urlRef("apiurl", urlParams), "docs"]; + } + }); + + return ViewIndexes; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/addons/indexes/routes.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/routes.js b/app/addons/indexes/routes.js new file mode 100644 index 0000000..90c9aac --- /dev/null +++ b/app/addons/indexes/routes.js @@ -0,0 +1,24 @@ +// 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/indexes/views", + "addons/indexes/routes-viewindexes", + "addons/indexes/routes-show", + "addons/indexes/routes-list", +], + +function (app, FauxtonAPI, Views, ViewIndex, Show, List) { + Views.RouteObjects = [ViewIndex, Show, List]; + return Views; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/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..98abc46 --- /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> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/addons/indexes/templates/header_left.html ---------------------------------------------------------------------- diff --git a/app/addons/indexes/templates/header_left.html b/app/addons/indexes/templates/header_left.html new file mode 100644 index 0000000..13bea60 --- /dev/null +++ b/app/addons/indexes/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/28333566/app/addons/indexes/templates/header_right.html ---------------------------------------------------------------------- diff --git a/app/addons/indexes/templates/header_right.html b/app/addons/indexes/templates/header_right.html new file mode 100644 index 0000000..90828d2 --- /dev/null +++ b/app/addons/indexes/templates/header_right.html @@ -0,0 +1,18 @@ +<!-- +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. +--> + + <!-- Query Options--> + <!--right margin for api bar--> + <div id="header-api-bar"></div> + http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/addons/indexes/templates/index_header.html ---------------------------------------------------------------------- diff --git a/app/addons/indexes/templates/index_header.html b/app/addons/indexes/templates/index_header.html new file mode 100644 index 0000000..ac8ac56 --- /dev/null +++ b/app/addons/indexes/templates/index_header.html @@ -0,0 +1,28 @@ +<!-- +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="header-left"> +<!--back arrow--> + +<!--title--> + +<!-- Menu gear--> + +</div> + + +<div class="header-right"> + <!-- Query Options--> + <!--right margin for api bar--> +</div> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/addons/indexes/templates/index_row_docular.html ---------------------------------------------------------------------- diff --git a/app/addons/indexes/templates/index_row_docular.html b/app/addons/indexes/templates/index_row_docular.html new file mode 100644 index 0000000..ba88d06 --- /dev/null +++ b/app/addons/indexes/templates/index_row_docular.html @@ -0,0 +1,35 @@ +<!-- +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. +--> +<% if (doc.isEditable()) { %> + <div class="select"><input type="checkbox"></div> +<% } %> + +<div class="doc-item"> + <header> + _id <span class="header-id-number">"<%=docID%>"</span> + + <div class="doc-menu"> + <a href="#<%= url %>" class="doc-menu-item icon fonticon-pencil"></a> + <% if (doc.isEditable()) { %> + <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button> + <% } %> + + <div id="view-doc-menu" class="doc-menu-item"></div> + </div> + </header> + <div class="doc-data"> + <pre class="prettyprint"><%- doc.prettyJSON() %></pre> + </div> +</div> +<div class="clearfix"></div> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/addons/indexes/templates/list_editor.html ---------------------------------------------------------------------- diff --git a/app/addons/indexes/templates/list_editor.html b/app/addons/indexes/templates/list_editor.html new file mode 100644 index 0000000..8644909 --- /dev/null +++ b/app/addons/indexes/templates/list_editor.html @@ -0,0 +1,18 @@ +<!-- +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. +--> + +<form> + <label> A FORM</label> + +</form> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/addons/indexes/templates/preview_screen.html ---------------------------------------------------------------------- diff --git a/app/addons/indexes/templates/preview_screen.html b/app/addons/indexes/templates/preview_screen.html new file mode 100644 index 0000000..1fcf6d9 --- /dev/null +++ b/app/addons/indexes/templates/preview_screen.html @@ -0,0 +1,16 @@ +<!-- +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. +--> + +<h3>No Index Created Yet!</h3> +<p> Run <a href="#/preview" class="btn btn-success save"> Preview</a> To query result</p> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/addons/indexes/templates/show_editor.html ---------------------------------------------------------------------- diff --git a/app/addons/indexes/templates/show_editor.html b/app/addons/indexes/templates/show_editor.html new file mode 100644 index 0000000..9afa2bf --- /dev/null +++ b/app/addons/indexes/templates/show_editor.html @@ -0,0 +1,41 @@ +<!-- +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 index-form"> + <div class="errors-container"></div> + <form class="form-horizontal view-query-save"> + <div class="control-group"> + <p>Views are the primary tool used for querying and reporting on CouchDB databases.</p> + </div> + + <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"> + <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/28333566/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..f33d3f9 --- /dev/null +++ b/app/addons/indexes/templates/view_editor.html @@ -0,0 +1,80 @@ +<!-- +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 index-form"> + <div class="errors-container"></div> + <form class="form-horizontal view-query-save"> + <div class="control-group"> + <p>Views are the primary tool used for querying and reporting on CouchDB databases.</p> + </div> + + + <div class="control-group"> + <label for="index-name">Database name</label> + <p><%- database %></p> + </div> + + + <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/28333566/app/addons/indexes/views.js ---------------------------------------------------------------------- diff --git a/app/addons/indexes/views.js b/app/addons/indexes/views.js new file mode 100644 index 0000000..80e6a40 --- /dev/null +++ b/app/addons/indexes/views.js @@ -0,0 +1,712 @@ +// 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 = {}; + +//left header + Views.LeftHeader = FauxtonAPI.View.extend({ + className: "header-left", + template: "addons/indexes/templates/header_left", + initialize:function(options){ + this.database = options.database; + this.title = options.title; + }, + beforeRender: function(){ + var crumbs = [ + {"name": "", "className": "fonticon-left-open", "link": Databases.databaseUrl(this.database)}, + {"name": this.title, "link": Databases.databaseUrl(this.database)} + ]; + this.insertView("#header-breadcrumbs", new Components.Breadcrumbs({ + crumbs: crumbs + })); + this.dropDownMenu(); + }, + dropDownMenu: function(){ + var newLinks = [{ + links: [{ + title: 'Table', + icon: 'fonticon-table' + },{ + title: 'JSON', + icon: 'fonticon-json' + }] + }]; + + this.insertView("#header-dropdown-menu", new Components.MenuDropDown({ + icon: 'fonticon-cog', + links: newLinks, + })); + } + }); + +//right header + Views.RightHeader = FauxtonAPI.View.extend({ + className: "header-right", + template: "addons/indexes/templates/header_right", + initialize:function(options){ + this.database = options.database; + this.title = options.title; + }, + beforeRender: function(){ + this.insertView(".header-api-bar", new Components.ApiBar({})); + } + }); + + + + + Views.PreviewScreen = FauxtonAPI.View.extend({ + template: "addons/indexes/templates/preview_screen", + className: "watermark-logo" + }); + + + Views.Row = FauxtonAPI.View.extend({ + template: "addons/indexes/templates/index_row_docular", + className: "doc-row", + events: { + "click button.delete": "destroy" + }, + + destroy: function (event) { + event.preventDefault(); + + window.alert('Cannot delete a document generated from a view.'); + }, + + beforeRender: function(){ + var newLinks = [{ + links: [{ + title: 'Table', + icon: 'fonticon-table' + },{ + title: 'JSON', + icon: 'fonticon-json' + }] + }]; + + this.insertView("#view-doc-menu", new Components.MenuDropDown({ + icon: 'fonticon-drop-down-dots', + links: newLinks, + })); + }, + + serialize: function() { + return { + docID: this.model.get('id'), + doc: this.model, + url: this.model.url('app') + }; + } + }); + + +/* + + INDEX EDITORS____________________________________ + +*/ + + //Index view CORE extend this + Views.IndexCore = FauxtonAPI.View.extend({ + 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 ? 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(); + } + }, + serialize: function() { + return { + database: this.database.get('id'), + ddocs: this.ddocs, + ddoc: this.model, + ddocName: this.model.id, + viewName: this.viewName, + newView: this.newView, + langTemplates: this.langTemplates.javascript + }; + } + }); + + Views.ShowEditor = Views.IndexCore.extend({ + template: "addons/indexes/templates/show_editor", + langTemplates: { + "javascript": { + map: "function(doc) {\n emit(doc._id, 1);\n}", + } + }, + defaultLang: "javascript" + }); + + Views.ListEditor = Views.IndexCore.extend({ + template: "addons/indexes/templates/list_editor", + langTemplates: { + "javascript": { + map: "function(doc) {\n emit(doc._id, 1);\n}", + } + }, + defaultLang: "javascript" + }); + + + + + 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" + }, + + 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 + //check if the code is valid & the inputs are filled out + 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; + this.viewNameChange = false; + + + if (this.viewName !== viewName) { + ddoc.removeDdocView(this.viewName); + this.viewName = viewName; + this.viewNameChange = true; + } + + notification = FauxtonAPI.addNotification({ + msg: "Saving document.", + selector: "#define-view .errors-container", + clear: true + }); + + ddoc.setDdocView(viewName, mapVal, reduceVal); + + ddoc.save().then(function () { + //on success + that.afterSave(ddoc, viewName, ddocName); + }, + function(xhr) { + //on failure + var responseText = JSON.parse(xhr.responseText).reason; + notification = FauxtonAPI.addNotification({ + msg: "Save failed: " + responseText, + type: "error", + clear: true + }); + }); + } else { + //if nothing is filled out give an error message + 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 + }); + } + }, + + afterSave: function(ddoc, viewName, ddocName){ + var reduceVal = this.reduceVal(); + //add ddoc to the collection + this.ddocs.add(ddoc); + + //trigger the EditSaved function on the map editor & reduce editor + this.mapEditor.editSaved(); + this.reduceEditor && this.reduceEditor.editSaved(); + + + //show a notification + FauxtonAPI.addNotification({ + msg: "View has been saved.", + type: "success", + selector: "#define-view .errors-container", + clear: true + }); + + + //if it's new or the name changed (aka created a new doc) + if (this.newView || this.viewNameChange) { + var fragment = '/database/' + this.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName); + + FauxtonAPI.navigate(fragment, {trigger: false}); + this.newView = false; + this.ddocID = ddoc.safeID(); + this.viewName = viewName; + this.ddocInfo = ddoc; + this.showIndex = true; + this.render(); + FauxtonAPI.triggerRouteEvent('reloadDesignDocs', { + selectedTab: app.utils.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.utils.removeSpecialCharacters(viewName) + }); + } + + // TODO:// this should change to a trigger because we shouldn't define advanced options in this view + if (this.reduceFunStr !== reduceVal) { + this.reduceFunStr = reduceVal; + // this.advancedOptions.renderOnUpdatehasReduce(this.hasReduce()); + } + + // Route Event will reload the right content + FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: ddocName, view: viewName}); + }, + + 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); + }, + + + serialize: function() { + return { + database: this.database.get('id'), + 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 + })); + + }, + + afterRender: function() { + //TODO: have this happen on a trigger once we move advanced options to the header + // if (this.params && !this.newView) { + // this.advancedOptions.updateFromParams(this.params); + // } + + this.designDocSelector.updateDesignDoc(); + this.showEditors(); + this.showIndex = false; + + }, + + 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').show(); + } else { + this.$('#new-ddoc').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/28333566/app/templates/layouts/two_pane.html ---------------------------------------------------------------------- diff --git a/app/templates/layouts/two_pane.html b/app/templates/layouts/two_pane.html index 031ad12..0174a5a 100644 --- a/app/templates/layouts/two_pane.html +++ b/app/templates/layouts/two_pane.html @@ -12,18 +12,16 @@ License for the specific language governing permissions and limitations under the License. --> - <div id="primary-navbar"></div> -<div id="dashboard" class="container-fluid"> - <div class="fixed-header"> - <div id="breadcrumbs"></div> - <div id="api-navbar"></div> - </div> +<div id="dashboard" class="container-fluid two-pane"> + <header class="fixed-header row-fluid"> + <div id="breadcrumbs" class="window-resizeable"></div> + <div id="api-navbar" class="window-resizeable"></div> + </header> - <div class="row-fluid content-area"> - <div id="left-content" class="span6"></div> - <div id="right-content" class="span6"></div> + <div class="content-area two-pane"> + <div id="left-content" class="span6 window-resizeable"></div> + <div id="right-content" class="span6 window-resizeable"></div> </div> </div> - http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/templates/layouts/with_sidebar.html ---------------------------------------------------------------------- diff --git a/app/templates/layouts/with_sidebar.html b/app/templates/layouts/with_sidebar.html index 4eba634..7fc64db 100644 --- a/app/templates/layouts/with_sidebar.html +++ b/app/templates/layouts/with_sidebar.html @@ -14,10 +14,10 @@ the License. <div id="primary-navbar"></div> -<div id="dashboard" class="container-fluid"> - <header class="fixed-header"> - <div id="breadcrumbs"></div> - <div id="api-navbar"></div> +<div id="dashboard" class="container-fluid with-sidebar"> + <header class="fixed-header row-fluid"> + <div id="breadcrumbs" class="sidebar"></div> + <div id="api-navbar" class="window-resizeable"></div> </header> <div class="with-sidebar content-area"> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/templates/layouts/with_tabs.html ---------------------------------------------------------------------- diff --git a/app/templates/layouts/with_tabs.html b/app/templates/layouts/with_tabs.html index fc372ff..074385f 100644 --- a/app/templates/layouts/with_tabs.html +++ b/app/templates/layouts/with_tabs.html @@ -15,10 +15,11 @@ the License. <div id="primary-navbar"></div> <div id="dashboard" class="container-fluid"> - <div class="fixed-header"> - <div id="breadcrumbs"></div> - <div id="api-navbar"></div> - </div> + <header class="fixed-header row-fluid"> + <div id="breadcrumbs" class="sidebar"></div> + <div id="api-navbar" class="window-resizeable"></div> + </header> + <div class="row-fluid content-area"> <div id="tabs" class="row-fluid"></div> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/app/templates/layouts/with_tabs_sidebar.html ---------------------------------------------------------------------- diff --git a/app/templates/layouts/with_tabs_sidebar.html b/app/templates/layouts/with_tabs_sidebar.html index a0ed03d..de4bdee 100644 --- a/app/templates/layouts/with_tabs_sidebar.html +++ b/app/templates/layouts/with_tabs_sidebar.html @@ -13,17 +13,14 @@ the License. --> <div id="primary-navbar"></div> -<div id="dashboard" class="container-fluid"> +<div id="dashboard" class="container-fluid with-sidebar"> - <header class="fixed-header"> - <div id="breadcrumbs"></div> - <div id="api-navbar"></div> + <header class="fixed-header row-fluid"> + <div id="breadcrumbs" class="sidebar"></div> + <div id="api-navbar" class="window-resizeable"></div> </header> <div class="with-sidebar content-area"> - - <div id="tabs" class="row-fluid"></div> - <aside id="sidebar-content" class="sidebar"></aside> <section id="dashboard-content" class="list pull-right window-resizeable"> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/28333566/assets/img/couchWatermark.png ---------------------------------------------------------------------- diff --git a/assets/img/couchWatermark.png b/assets/img/couchWatermark.png new file mode 100644 index 0000000..cab9ce4 Binary files /dev/null and b/assets/img/couchWatermark.png differ
