Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D82F0171FC for ; Thu, 16 Oct 2014 10:03:09 +0000 (UTC) Received: (qmail 41079 invoked by uid 500); 16 Oct 2014 10:03:09 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 41029 invoked by uid 500); 16 Oct 2014 10:03:09 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 41020 invoked by uid 99); 16 Oct 2014 10:03:09 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 16 Oct 2014 10:03:09 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 5D5EA98FE0C; Thu, 16 Oct 2014 10:03:09 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: robertkowalski@apache.org To: commits@couchdb.apache.org Date: Thu, 16 Oct 2014 10:03:11 -0000 Message-Id: <06cabdaa13534f1884b54b7071b53c8e@git.apache.org> In-Reply-To: <77fa3fb8469244478064fed5b0b59e02@git.apache.org> References: <77fa3fb8469244478064fed5b0b59e02@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [4/4] fauxton commit: updated refs/heads/master to 332c7b5 New Query Options tray added This is a cherry-picked branch the clears up the old PR: https://github.com/apache/couchdb-fauxton/pull/78 For comments regarding this PR, see the original PR. For scope and discussion of the fix, see the Jira ticket: https://issues.apache.org/jira/browse/COUCHDB-2347 Closes COUCHDB-2347 Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/332c7b53 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/332c7b53 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/332c7b53 Branch: refs/heads/master Commit: 332c7b5350a928e35006e821f1f8bf9b6b748c12 Parents: 5976c65 Author: Benjamin Keen Authored: Fri Oct 3 10:38:33 2014 -0700 Committer: Robert Kowalski Committed: Thu Oct 16 11:59:30 2014 +0200 ---------------------------------------------------------------------- app/addons/compaction/base.js | 3 +- .../documents/assets/less/advancedOptions.less | 1 - app/addons/documents/assets/less/changes.less | 3 - app/addons/documents/assets/less/documents.less | 122 ++--- .../documents/assets/less/queryOptions.less | 161 ++++++ app/addons/documents/resources.js | 1 - app/addons/documents/routes-documents.js | 106 ++-- .../documents/templates/advanced_options.html | 157 ------ .../documents/templates/all_docs_layout.html | 11 +- .../documents/templates/all_docs_list.html | 4 +- app/addons/documents/templates/ddoc_info.html | 2 +- .../documents/templates/header_alldocs.html | 5 +- .../documents/templates/query_options.html | 38 ++ .../query_options_additional_params.html | 61 +++ .../templates/query_options_key_search.html | 50 ++ .../templates/query_options_main_fields.html | 55 ++ app/addons/documents/templates/view_editor.html | 7 +- .../documents/tests/views-advancedoptsSpec.js | 6 +- app/addons/documents/views-advancedopts.js | 270 ---------- app/addons/documents/views-index.js | 90 ++-- app/addons/documents/views-queryoptions.js | 519 +++++++++++++++++++ app/addons/documents/views.js | 239 +++------ app/addons/fauxton/base.js | 3 +- app/addons/fauxton/components.js | 6 +- app/addons/fauxton/templates/api_bar.html | 2 +- app/core/routeObject.js | 7 +- app/core/router.js | 3 +- app/core/utils.js | 10 + assets/fonts/fauxtonicon.eot | Bin 17640 -> 18290 bytes assets/fonts/fauxtonicon.svg | 259 +++++---- assets/fonts/fauxtonicon.ttf | Bin 17452 -> 18100 bytes assets/fonts/fauxtonicon.woff | Bin 10000 -> 10368 bytes .../fonts/styleguide/fauxtonicon-preview.html | 441 ++++++++-------- assets/icons/gears.svg | 8 + assets/less/bootstrap/forms.less | 2 +- assets/less/fauxton.less | 27 +- assets/less/formstyles.less | 38 +- assets/less/icons.less | 214 ++++---- 38 files changed, 1688 insertions(+), 1243 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/compaction/base.js ---------------------------------------------------------------------- diff --git a/app/addons/compaction/base.js b/app/addons/compaction/base.js index de0f124..f80c42e 100644 --- a/app/addons/compaction/base.js +++ b/app/addons/compaction/base.js @@ -17,6 +17,7 @@ define([ ], function(app, FauxtonAPI, Compaction) { + Compaction.initialize = function() { FauxtonAPI.registerExtension('docLinks', { title: "Compact & Clean", @@ -24,7 +25,7 @@ function(app, FauxtonAPI, Compaction) { icon: "icon-cogs" }); - FauxtonAPI.registerExtension('advancedOptions:ViewButton', new Compaction.CompactView({})); + FauxtonAPI.registerExtension('ViewEditor:ButtonRow', new Compaction.CompactView({})); }; return Compaction; http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/assets/less/advancedOptions.less ---------------------------------------------------------------------- diff --git a/app/addons/documents/assets/less/advancedOptions.less b/app/addons/documents/assets/less/advancedOptions.less deleted file mode 100644 index 2e29d38..0000000 --- a/app/addons/documents/assets/less/advancedOptions.less +++ /dev/null @@ -1 +0,0 @@ -/*for advanced options css*/ http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/assets/less/changes.less ---------------------------------------------------------------------- diff --git a/app/addons/documents/assets/less/changes.less b/app/addons/documents/assets/less/changes.less index 96e6d19..ebba21d 100644 --- a/app/addons/documents/assets/less/changes.less +++ b/app/addons/documents/assets/less/changes.less @@ -7,9 +7,6 @@ right: 15px; } -.changes-view { - padding-top: 70px; -} .change-wrapper { margin-top: 20px; http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/assets/less/documents.less ---------------------------------------------------------------------- diff --git a/app/addons/documents/assets/less/documents.less b/app/addons/documents/assets/less/documents.less index 2b29744..8e730b5 100644 --- a/app/addons/documents/assets/less/documents.less +++ b/app/addons/documents/assets/less/documents.less @@ -10,31 +10,31 @@ // License for the specific language governing permissions and limitations under // the License. /*ALL DOCS TABLE*/ - @import "../../../../../assets/less/variables.less"; @import "../../../../../assets/less/bootstrap/variables.less"; @import "../../../../../assets/less/bootstrap/mixins.less"; -@import "advancedOptions.less"; +@import "queryOptions.less"; @import "changes.less"; @import "sidenav.less"; tr.all-docs-item { border: none; background: transparent; - .btn-group { - position: absolute; - right: 0; - top: 6px; - } + .btn-group { + position: absolute; + right: 0; + top: 6px; + } } + button.beautify { margin-top: 20px; } .toggle-btns { - label{ - margin-right: 0; - } + label { + margin-right: 0; + } } #per-page { @@ -43,65 +43,66 @@ button.beautify { #select-per-page { margin-top: 10px; } - } - -#query div.controls-group.well{ - height: 180px; - margin-right: 17px; +#query div.controls-group.well { + height: 180px; + margin-right: 17px; } /** used in all_docs_list.html **/ .view { - table td div { - position: relative; - } + table td div { + position: relative; + } - table td div div { - display: none; - line-height: 1; - position: absolute; - right: 4px; - top: 4px; - } + table td div div { + display: none; + line-height: 1; + position: absolute; + right: 4px; + top: 4px; + } - table td div:hover div a.edits { - padding-left: 16px; - padding-right: 16px; - } + table td div:hover div a.edits { + padding-left: 16px; + padding-right: 16px; + } - table td div:hover div { - display: block; - } + table td div:hover div { + display: block; + } } /** used in view_editor.html **/ -.design-doc-group{ - .span3 { margin: 0;} - #new-ddoc-section { - margin-top: 10px; - label{ width: 100px} - .controls{ - margin-left: 100px; - } +.design-doc-group { + .span3 { + margin: 0; + } + #new-ddoc-section { + margin-top: 10px; + label { + width: 100px } + .controls { + margin-left: 100px; + } + } } - -#map-function, #reduce-function{ - width: 100%; - font-size: 16px; +#map-function, #reduce-function { + width: 100%; + font-size: 16px; } #doc-actions { - height: 42px; + height: 42px; } #editor-container { - width: 1316px; - height: 688px; - font-size: 16px; + width: 1316px; + height: 688px; + font-size: 16px; } button.string-edit { @@ -137,21 +138,20 @@ button.string-edit[disabled] { display: inline-block; } - .change-sequence { word-wrap: break-word; } - -#dashboard-upper-content{ - .js-query-keys-wrapper{ +#dashboard-upper-content { + .js-query-keys-wrapper { padding-top: 0; } - /** used in advanced-options.html**/ + + /** used in query-options.html**/ .custom-inputs { - .row-fluid{ + .row-fluid { padding-top: 20px; - .radio, .checkbox{ + .radio, .checkbox { padding-left: 0; } .checkbox.inline, @@ -163,12 +163,14 @@ button.string-edit[disabled] { } } -.nav-list{ +.nav-list { border-top: none; } +.end-of-results { + margin-bottom: 30px; - - - - + .muted { + margin-bottom: 0px; + } +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/assets/less/queryOptions.less ---------------------------------------------------------------------- diff --git a/app/addons/documents/assets/less/queryOptions.less b/app/addons/documents/assets/less/queryOptions.less new file mode 100644 index 0000000..f326c5e --- /dev/null +++ b/app/addons/documents/assets/less/queryOptions.less @@ -0,0 +1,161 @@ +// 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-tray:before { + right: 140px; +} + +#query-options-tray { + width: 490px; + + .query-group:first-child { + margin-top: 0px; + padding-top: 0px; + } + + .icon-question-sign { + margin-left: 3px; + font-size: 17.5px; + } + + .query-group { + padding: 20px; + border-bottom: 1px solid #555; + } + + .query-group:last-child { + border-bottom: none; + } + .controls-group { + margin: 0; + } + .controls-group:last-child { + margin: 0; + } + form { + overflow: scroll; + margin-bottom: 0; + .dropdown.inline { + display: inline-block; + } + + input[type="text"], + textarea { + .border-radius(5px); + background-color: #666; + padding: 8px; + border: none; + color: #eee; + font-size: 13px; + } + .input-small { + width: 70px; + margin-left: 5px; + } + .checkbox { + padding: 0; + margin: 0; + } + .btn-success { + .border-radius(5px); + } + .btn-cancel, .btn-cancel:active { + background: none; + border: none; + box-shadow: none; + color: @red; + line-height: 1em; + } + select { + margin-top: -4px; + margin-bottom: 0px; + } + .include-end-key-row { + line-height: 20px; + margin-left: 8px; + } + } + + .toggle-btns { + .btn { + padding: 5px 12px 5px; + background: #727A82; + color: #fff; + font-size: 12px; + border: none; + } + .btn.active { + background: #fff; + color: #E33F3B; + box-shadow: 2px 2px 0px rgba(0, 0, 0, 0.25) inset, 2px 2px 2px rgba(0, 0, 0, 0.15); + } + label:first-child { + .border-radius(5px 0 0 5px); + } + label:last-child { + .border-radius(0 5px 5px 0); + margin-left: 1px; + } + } + + label { + margin-right: 0; + font-size: 13px; + + /* + due to: https://code.google.com/p/chromium/issues/detail?id=411065 - that bug causes the checkbox state not to + update when the user clicks on labels quickly. It can be removed once the fix is in Chrome stable + */ + -webkit-user-select: none; + } + label.disabled { + color: #777777; + } + div.controls-group.well{ + height: 156px; + background: none; + border: none; + padding: 10px 0; + } + .row-fluid.fieldsets { + .inline { + width: 32%; + } + .inline:nth-child(3) { + text-align: right; + width: 34%; + } + } + .row-fluid.fieldsets { + margin-bottom: 5px; + :last-child { + margin-bottom: 2px; + } + } + + #skipRows { + margin-left: 5px; + } + .add-on { + height: 28px; + } + .hide { + display: none; + } + + .icon-question-sign:hover { + color: @red; + } + .additionalParams { + margin-bottom: 2px; + } +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/resources.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js index ef119ac..651ca37 100644 --- a/app/addons/documents/resources.js +++ b/app/addons/documents/resources.js @@ -249,7 +249,6 @@ function(app, FauxtonAPI, PagingCollection) { var ddoc = this.id.replace(/^_design\//,""); return "_design/"+app.utils.safeURLName(ddoc); } - }); Documents.ViewRow = FauxtonAPI.Model.extend({ http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/routes-documents.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js index d3f693f..37ec482 100644 --- a/app/addons/documents/routes-documents.js +++ b/app/addons/documents/routes-documents.js @@ -12,7 +12,6 @@ define([ "app", - "api", // Modules @@ -85,16 +84,16 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou "route:paginate": "paginate", "route:perPageChange": "perPageChange", "route:changesFilterAdd": "addFilter", - "route:changesFilterRemove": "removeFilter" + "route:changesFilterRemove": "removeFilter", + "route:updateQueryOptions": "updateQueryOptions", + "route:resetQueryOptions": "resetQueryOptions" }, overrideBreadcrumbs: true, initialize: function (route, masterLayout, options) { this.databaseName = options[0]; - this.database = new Databases.Model({id:this.databaseName}); - this.designDocs = new Documents.AllDocs(null, { database: this.database, paging: { @@ -123,12 +122,12 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou })); }, - setUpDropdown: function(){ + setUpDropdown: function() { var defaultMenuLinks = [{ links: [{ title: 'Replicate Database', icon: 'fonticon-replicate', - url: '#/replication/'+this.databaseName + url: '#/replication/' + this.databaseName },{ title: 'Delete', icon: 'fonticon-trash', @@ -159,37 +158,33 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou }]; return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) { - menuLinks.push({ title: link.title, url: newurlPrefix + "/" + link.url, icon: 'fonticon-plus-circled' }); - return menuLinks; - }, menuLinks); - + }, menuLinks); }, designDocMetadata: function(database, ddoc){ this.toolsView && this.toolsView.remove(); this.viewEditor && this.viewEditor.remove(); - var designDocInfo = new Resources.DdocInfo({_id: "_design/"+ddoc},{database: this.database }); - + var designDocInfo = new Resources.DdocInfo({ _id: "_design/" + ddoc }, { database: this.database }); this.setView("#dashboard-lower-content", new Documents.Views.DdocInfo({ ddocName: ddoc, model: designDocInfo })); this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc)+"_metadata"); + this.leftheader.updateCrumbs(crumbs.allDocs(this.database)); + this.rightHeader.hideQueryOptions(); - - this.leftheader.updateCrumbs(crumbs.allDocs(this.database)); - + // problem line again this.apiUrl = [designDocInfo.url('apiurl'), designDocInfo.documentation() ]; - }, + tempFn: function(databaseName, ddoc, fn){ this.setView("#dashboard-upper-content", new Documents.Views.temp({})); this.crumbs = function () { @@ -197,7 +192,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou {"name": this.database.id, "link": Databases.databaseUrl(this.database)}, ]; }; - }, establish: function () { @@ -215,10 +209,10 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou }, /* - * docParams are the options collection uses to fetch from the server - * urlParams are what are shown in the url and to the user - * They are not the same when paginating - */ + * docParams are the options collection uses to fetch from the server + * urlParams are what are shown in the url and to the user + * They are not the same when paginating + */ allDocs: function(databaseName, options) { var params = this.createParams(options), urlParams = params.urlParams, @@ -232,23 +226,15 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.leftheader.updateCrumbs(crumbs.allDocs(this.database)); this.database.buildAllDocs(docParams); - if (docParams.startkey && docParams.startkey.indexOf('_design') > -1) { - this.sidebar.setSelectedTab('design-docs'); + if (docParams.startkey && docParams.startkey.indexOf("_design") > -1) { + this.sidebar.setSelectedTab("design-docs"); } else { - this.sidebar.setSelectedTab('all-docs'); + this.sidebar.setSelectedTab("all-docs"); } this.viewEditor && this.viewEditor.remove(); - this.database.allDocs.paging.pageSize = this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10)); - this.viewEditor = this.setView("#dashboard-upper-content", new Documents.Views.AllDocsLayout({ - database: this.database, - collection: this.database.allDocs, - params: urlParams, - docParams: docParams - })); - this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({ database: this.database, collection: this.database.allDocs, @@ -261,20 +247,23 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou return [this.database.allDocs.urlRef("apiurl", urlParams), this.database.allDocs.documentation()]; }; + // update the rightHeader with the latest & greatest info + this.rightHeader.resetQueryOptions({ queryParams: urlParams }); + this.rightHeader.showQueryOptions(); }, - viewFn: function (databaseName, ddoc, view) { + viewFn: function (databaseName, ddoc, viewName) { var params = this.createParams(), urlParams = params.urlParams, docParams = params.docParams, decodeDdoc = decodeURIComponent(ddoc); - view = view.replace(/\?.*$/,''); + viewName = viewName.replace(/\?.*$/,''); this.indexedDocs = new Documents.IndexCollection(null, { database: this.database, design: decodeDdoc, - view: view, + view: viewName, params: docParams, paging: { pageSize: this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10)) @@ -284,11 +273,11 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditor({ model: this.database, ddocs: this.designDocs, - viewName: view, + viewName: viewName, params: urlParams, newView: false, database: this.database, - ddocInfo: this.ddocInfo(decodeDdoc, this.designDocs, view) + ddocInfo: this.ddocInfo(decodeDdoc, this.designDocs, viewName) })); this.toolsView && this.toolsView.remove(); @@ -300,14 +289,23 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou database: this.database, indexedDocs: this.indexedDocs, designDocs: this.designDocs, - view: view + view: viewName }); - this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + '_' + app.utils.removeSpecialCharacters(view)); + this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + '_' + app.utils.removeSpecialCharacters(viewName)); this.apiUrl = function() { return [this.indexedDocs.urlRef("apiurl", urlParams), "docs"]; }; + + this.rightHeader.showQueryOptions(); + this.rightHeader.resetQueryOptions({ + queryParams: urlParams, + showStale: true, + hasReduce: true, + viewName: viewName, + ddocName: ddoc + }); }, ddocInfo: function (designDoc, designDocs, view) { @@ -319,7 +317,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou }, createViewDocumentsView: function (options) { - return this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({ database: options.database, collection: options.indexedDocs, @@ -338,19 +335,22 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.documentsView && this.documentsView.remove(); this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditor({ - currentddoc: "_design/"+designDoc || "", + currentddoc: "_design/" + designDoc || "", ddocs: this.designDocs, params: params, database: this.database, newView: true })); - this.sidebar.setSelectedTab('new-view'); + this.sidebar.setSelectedTab("new-view"); + this.rightHeader.hideQueryOptions(); // clear out anything that was in the lower section this.removeView("#dashboard-lower-content"); - //this.rightHeader.updateApiUrl([this.indexedDocs.urlRef("apiurl", urlParams), "docs"]); + // TODO +// var apiUrl = this.database.url("app") + "/new_view/" + designDoc; +// this.rightHeader.updateApiUrl([apiUrl, "docs"]); }, updateAllDocsFromView: function (event) { @@ -370,7 +370,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.database.buildAllDocs(docParams); collection = this.database.allDocs; collection.paging.pageSize = pageSize; - } else { collection = this.indexedDocs = new Documents.IndexCollection(null, { database: this.database, @@ -399,7 +398,11 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.documentsView.setParams(docParams, urlParams); this.documentsView.forceRender(); - this.apiUrl = [collection.urlRef("apiurl", urlParams), "docs"]; + // this has been commented out because it causes the header bar to disappear after a search (i.e the "Query + // Options" link disappears). This issue is being addressed in a separate ticket (not sure about the Jira ID) +// this.apiUrl = function() { +// return [this.indexedDocs.urlRef("apiurl", urlParams), "docs"]; +// }; }, perPageChange: function (perPage) { @@ -473,13 +476,12 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.viewEditor && this.viewEditor.remove(); this.sidebar.setSelectedTab('changes'); - this.leftheader.updateCrumbs(crumbs.changes(this.database)); + this.rightHeader.showQueryOptions(); this.apiUrl = function () { return [this.database.url("changes-apiurl"), this.database.documentation()]; }; - }, addFilter: function (filter) { @@ -490,10 +492,16 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou removeFilter: function (filter) { this.changesView.filters.splice(this.changesView.filters.indexOf(filter), 1); this.changesView.render(); - } + }, + resetQueryOptions: function(options) { + this.rightHeader.resetQueryOptions(options); + }, + + updateQueryOptions: function(options) { + this.rightHeader.updateQueryOptions(options); + } }); return DocumentsRouteObject; }); - http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/advanced_options.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/advanced_options.html b/app/addons/documents/templates/advanced_options.html deleted file mode 100644 index c986d4e..0000000 --- a/app/addons/documents/templates/advanced_options.html +++ /dev/null @@ -1,157 +0,0 @@ - -
-
- - - -
- - -
- -
-
-
- - -
-
-
-
-
-
- - -
-
- - -
- - -
-
- -
- -
-
- - - -
- -
-
- -
-
- -
-
-
-
- -
-
- -
-
-
- <% if (showStale) { %> -
-
- - -
-
- <% } %> -
-
- - -
-
- -
- <% if (hasReduce) { %> -
-
-
- - -
-
-
- -
-
- <% } %> -
- -
-
- -
-
-
- - http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/all_docs_layout.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/all_docs_layout.html b/app/addons/documents/templates/all_docs_layout.html index e2c2479..8db91ed 100644 --- a/app/addons/documents/templates/all_docs_layout.html +++ b/app/addons/documents/templates/all_docs_layout.html @@ -11,15 +11,6 @@ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - -
-
-
+
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/all_docs_list.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/all_docs_list.html b/app/addons/documents/templates/all_docs_list.html index 8db7bbe..c77fc05 100644 --- a/app/addons/documents/templates/all_docs_list.html +++ b/app/addons/documents/templates/all_docs_list.html @@ -33,9 +33,9 @@ the License. <% if (endOfResults) { %> -
+

- End of results - edit query + End of results - edit query

<% } %> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/ddoc_info.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/ddoc_info.html b/app/addons/documents/templates/ddoc_info.html index e9b1b6e..5c180ec 100644 --- a/app/addons/documents/templates/ddoc_info.html +++ b/app/addons/documents/templates/ddoc_info.html @@ -58,4 +58,4 @@ the License.
- + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/header_alldocs.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/header_alldocs.html b/app/addons/documents/templates/header_alldocs.html index b353d89..a4da0fb 100644 --- a/app/addons/documents/templates/header_alldocs.html +++ b/app/addons/documents/templates/header_alldocs.html @@ -13,13 +13,12 @@ the License. --> -
- + http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/query_options.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/query_options.html b/app/addons/documents/templates/query_options.html new file mode 100644 index 0000000..8126457 --- /dev/null +++ b/app/addons/documents/templates/query_options.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. +*/ %> + + + Query Options + + +
+
+ +
+ +
+ +
+
+ + Cancel +
+
+ +
+
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/query_options_additional_params.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/query_options_additional_params.html b/app/addons/documents/templates/query_options_additional_params.html new file mode 100644 index 0000000..3784315 --- /dev/null +++ b/app/addons/documents/templates/query_options_additional_params.html @@ -0,0 +1,61 @@ +<% /* +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. +*/ %> + + +
Additional Parameters
+ +
+ + <% if (showStale) { %> +
+ + +
+ <% } %> + +
+ + +
+ + +
+ +
+
+ + +
+ + +
\ No newline at end of file http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/query_options_key_search.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/query_options_key_search.html b/app/addons/documents/templates/query_options_key_search.html new file mode 100644 index 0000000..b288b4d --- /dev/null +++ b/app/addons/documents/templates/query_options_key_search.html @@ -0,0 +1,50 @@ +<% /* +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. +*/ %> + +
Keys
+ + +
+ + +
+ +
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+ + +
+ + +
+
+
+
+
+ http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/templates/query_options_main_fields.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/query_options_main_fields.html b/app/addons/documents/templates/query_options_main_fields.html new file mode 100644 index 0000000..48b5d3c --- /dev/null +++ b/app/addons/documents/templates/query_options_main_fields.html @@ -0,0 +1,55 @@ +<% /* +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 + + + + + +
+ +
+
+
+ + +
+ + <% if (hasReduce) { %> +
+ + +
+ + + <% } %> +
+
\ No newline at end of file http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/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 index 769deed..d22c734 100644 --- a/app/addons/documents/templates/view_editor.html +++ b/app/addons/documents/templates/view_editor.html @@ -15,12 +15,8 @@ the License.
@@ -78,6 +74,7 @@ the License. <% if (!newView) { %> <% } %> +
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/tests/views-advancedoptsSpec.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/tests/views-advancedoptsSpec.js b/app/addons/documents/tests/views-advancedoptsSpec.js index 3f9373b..fe9bbe5 100644 --- a/app/addons/documents/tests/views-advancedoptsSpec.js +++ b/app/addons/documents/tests/views-advancedoptsSpec.js @@ -10,14 +10,14 @@ // License for the specific language governing permissions and limitations under // the License. define([ - 'addons/documents/views-advancedopts', - 'testUtils' + 'addons/documents/views-queryoptions', + 'testUtils' ], function (Views, testUtils) { var assert = testUtils.assert, ViewSandbox = testUtils.ViewSandbox, viewSandbox; - describe('Documents AdvancedOptions', function () { + describe('Documents QueryOptions', function () { var view; beforeEach(function () { viewSandbox = new ViewSandbox(); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/views-advancedopts.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/views-advancedopts.js b/app/addons/documents/views-advancedopts.js deleted file mode 100644 index b2e1af5..0000000 --- a/app/addons/documents/views-advancedopts.js +++ /dev/null @@ -1,270 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -define([ - "app", - "api", - // Libs - "addons/fauxton/resizeColumns", -], - -function(app, FauxtonAPI, resizeColumns ) { - - var Views = {}; - - Views.AdvancedOptions = FauxtonAPI.View.extend({ - template: "addons/documents/templates/advanced_options", - className: "advanced-options well", - - initialize: function (options) { - this.database = options.database; - this.ddocName = options.ddocName; - this.viewName = options.viewName; - this.updateViewFn = options.updateViewFn; - this.previewFn = options.previewFn; - this.showStale = _.isUndefined(options.showStale) ? false : options.showStale; - this.hasReduce = _.isUndefined(options.hasReduce) ? true : options.hasReduce; - }, - - events: { - "change form.js-view-query-update input": "updateFilters", - "change form.js-view-query-update select": "updateFilters", - "submit form.js-view-query-update": "updateView", - "click .toggle-btns > label": "toggleQuery" - }, - - toggleQuery: function(e){ - e.preventDefault(); - - if (this.$(e.currentTarget).hasClass("active")){ - this.$('.js-query-keys-wrapper').addClass("hide"); - this.$(".toggle-btns > label").removeClass('active'); - this.$('.js-query-keys-wrapper').find("input,textarea").attr("disabled","true"); - } else { - this.$('.js-query-keys-wrapper').removeClass("hide"); - var showFunctionName =this.$(e.currentTarget).attr("for"); - //highlight current - this.$(".toggle-btns > label").removeClass('active'); - this.$(e.currentTarget).addClass("active"); - this.$("[id^='js-show']").hide(); - //show section & disable what needs to be disabled - this[showFunctionName](); - } - }, - - showKeys: function(){ - this.$("#js-showKeys, .js-disabled-message").show(); - this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').attr("disabled","true"); - this.$('[name="keys"]').removeAttr("disabled"); - }, - - showStartEnd: function(){ - this.$("#js-showStartEnd").show(); - this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').removeAttr("disabled"); - this.$('.js-disabled-message').hide(); - this.$('[name="keys"]').attr("disabled","true"); - }, - - beforeRender: function () { - if (this.viewName && this.ddocName) { - var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton'); - _.each(buttonViews, function (view) { - this.insertView('#button-options', view); - view.update(this.database, this.ddocName, this.viewName); - }, this); - } - }, - - renderOnUpdatehasReduce: function (hasReduce) { - this.hasReduce = hasReduce; - this.render(); - }, - - parseJSON: function (value) { - try { - return JSON.parse(value); - } catch(e) { - return undefined; - } - }, - - validateKeys: function(param){ - var errorMsg = false, - parsedValue = this.parseJSON(param.value); - - if (_.isUndefined(parsedValue)) { - errorMsg = "Keys must be valid json."; - } else if (!_.isArray(parsedValue)) { - errorMsg = "Keys values must be in an array. E.g [1,2,3]"; - } - - if (errorMsg) { - this.$('.js-keys-error').empty(); - FauxtonAPI.addNotification({ - type: "error", - msg: errorMsg, - clear: false, - selector: '.advanced-options .errors-container' - }); - return false; - } - - return true; - }, - validateFields: function(params){ - var errors = false; - //so ghetto. Spaghetti code. - for (var i= 0; i Warning! Preview executes the Map/Reduce functions in your browser, and may behave differently from CouchDB.", type: "warning", - selector: ".advanced-options .errors-container", + selector: ".query-options .errors-container", fade: true, escape: false // beware of possible XSS when the message changes }); @@ -311,7 +319,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, if (this.mapEditor) { return this.mapEditor.getValue(); } - return this.$('#map-function').text(); }, @@ -401,8 +408,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, $('.beautify-tooltip').tooltip(); } }, - beforeRender: function () { + beforeRender: function () { if (this.newView) { this.reduceFunStr = ''; if (this.ddocs.length === 0) { @@ -427,7 +434,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, }); designDocs.reset(filteredModels, {silent: true}); } - + if (!this.designDocSelector) { this.designDocSelector = this.setView('.design-doc-group', new Views.DesignDocSelector({ collection: designDocs, @@ -436,27 +443,25 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, })); } + // if this isn't a new View, add in whatever extensions have been associated with this location 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 - })); + var buttonViews = FauxtonAPI.getExtensions('ViewEditor:ButtonRow'); + _.each(buttonViews, function (view) { + this.insertView("#viewBtnExtensions", view); + view.update(this.database, this.ddocInfo.safeID(), this.viewName); + }, this); } - }, afterRender: function() { - - if (this.params && !this.newView) { - this.advancedOptions.updateFromParams(this.params); + if (this.params && !this.newView && hasRenderedOnce) { + FauxtonAPI.triggerRouteEvent('resetQueryOptions', { + queryParams: this.params, + hasReduce: this.hasReduce(), + showStale: true, + viewName: this.viewName, + ddocName: this.ddocInfo.get('name') + }); } this.designDocSelector.updateDesignDoc(); @@ -468,6 +473,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, this.$('#index-nav').parent().removeClass('active'); } + // note that this View has been rendered + hasRenderedOnce = true; }, showEditors: function () { @@ -550,6 +557,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, newDocValidation: function(){ return this.newDesignDoc() && this.$('#new-ddoc').val()===""; }, + getCurrentDesignDoc: function () { if (this.newDesignDoc()) { var doc = { http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/332c7b53/app/addons/documents/views-queryoptions.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/views-queryoptions.js b/app/addons/documents/views-queryoptions.js new file mode 100644 index 0000000..5bea495 --- /dev/null +++ b/app/addons/documents/views-queryoptions.js @@ -0,0 +1,519 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +define([ + "app", + "api", + + // libs + "addons/fauxton/resizeColumns" +], + + function (app, FauxtonAPI) { + + // our default settings for the Query Options tray + var defaultOptions = { + showStale: false, + hasReduce: false, + viewName: null, + ddocName: null, + + // all the possible query search params. Ultimately these should probably be moved higher-up (route object?), + // because they also apply to the actual search results. Seems better to place them there, then use them in + // both places + queryParams: { + include_docs: "false", + keys: "", + limit: "", + descending: "false", + skip: "", + update_seq: "false", + startkey: "", + endkey: "", + inclusive_end: "true", + reduce: "false", + stale: "", + group_level: "999" + } + }; + + + var Views = {}; + + // our main View. This is the only View exposed externally + Views.QueryOptionsTray = FauxtonAPI.View.extend({ + template: "addons/documents/templates/query_options", + className: "query-options", + + initialize: function (options) { + + // overlays whatever custom options were passed with defaultOptions above, so this.options + // always contains all options. [This does a deep copy: we never overwrite defaultOptions!] + this.options = $.extend(true, {}, defaultOptions, options); + + // add any general events relating to the Query Options tray + this.addEvents(); + + // add the sub-views + this.mainFieldsView = this.setView("#query-options-main-fields", new MainFieldsView(this.options)); + this.keySearchFieldsView = this.setView("#query-options-key-search", new KeySearchFieldsView(this.options)); + this.additionalParamsView = this.setView("#query-options-additional-params", new AdditionalParamsView(this.options)); + }, + + addEvents: function () { + FauxtonAPI.Events.on('QueryOptions:closeTray', this.closeTray, this); + FauxtonAPI.Events.on('QueryOptions:openTray', this.toggleQueryOptionsTray, this); + + // if the user just clicked outside the tray, close it [TODO be nice to generalize for all trays] + var trayIsVisible = this.trayIsVisible; + var closeTray = this.closeTray; + + $("body").on("click.queryOptions", function (e) { + if (!trayIsVisible()) { return; } + if ($(e.target).closest("#query-options-tray").length === 0) { + closeTray(); + } + }); + + $(window).on("resize", this.onResize); + }, + + afterRender: function () { + this.onResize(); + }, + + cleanup: function () { + FauxtonAPI.Events.unbind("QueryOptions:closeTray"); + FauxtonAPI.Events.unbind("QueryOptions:openTray"); + $(window).off("resize", this.onResize); + }, + + events: { + "click #toggle-query": "toggleQueryOptionsTray", // hide/show the Query Options tray + "submit form.js-view-query-update": "onSubmit", // submits the form + "click .btn-cancel": "onCancel" // closes the tray (doesn't reset the fields) + }, + + toggleQueryOptionsTray: function () { + if (!this.trayIsVisible()) { + $("#query-options-tray").velocity("transition.slideDownIn", 250); // TODO constant + FauxtonAPI.Events.trigger("APIbar:closeTray"); + } + }, + + // returns all applicable query parameters for the Query Options tray + getQueryParams: function () { + var mainFieldParams = this.mainFieldsView.getParams(); + var keySearchParams = this.keySearchFieldsView.getParams(); + var additionalParams = this.additionalParamsView.getParams(); + + // assumption: there aren't conflicting keys + return _.extend({}, mainFieldParams, keySearchParams, additionalParams); + }, + + onSubmit: function (e) { + e.preventDefault(); + + // validate the user-inputted fields. If anything is invalid, the sub-view will display the appropriate + // errors to the user + if (!this.keySearchFieldsView.hasValidInputs() || !this.additionalParamsView.hasValidInputs()) { + return; + } + + this.closeTray(); + + // this may be empty. That's ok! Perhaps the user just did a search with params, then removed them & wants the default + var params = this.getQueryParams(); + + // all looks good! Close the tray and publish the message + var url = app.utils.replaceQueryParams(params); + FauxtonAPI.navigate(url, { trigger: false }); + + if (this.options.viewName !== null && this.options.ddocName !== null) { + FauxtonAPI.triggerRouteEvent('updateAllDocs', { ddoc: this.options.ddocName, view: this.options.viewName }); + } else { + FauxtonAPI.triggerRouteEvent("updateAllDocs", { allDocs: true }); + } + }, + + onCancel: function () { + this.closeTray(); + }, + + // if the screen is so small there isn't space for the full tray height we manually shrink the height to allow scrolling. + // Technically this should handle width as well, but we won't bother because there are way bigger issues with a screen + // with such a small width! + onResize: function () { + var $tray = $("#query-options-tray"); + var heightFromTop = parseInt($tray.css("top"), 10); + var windowHeight = $(window).height(); + + // we apply the max-height to the form rather than the entire tray to allow the little up arrow to appear normally + $tray.find("form").css("max-height", windowHeight - heightFromTop); + }, + + /* + * Updates specific query options, leaving any that have been set already intact. + */ + updateQueryOptions: function (options) { + this.options = $.extend(this.options, options); + this.updateSubViews(); + }, + + /* + * Reset the query options back to the defaults, then apply whatever new options are needed. + */ + resetQueryOptions: function (options) { + this.options = $.extend(true, {}, defaultOptions, options); + this.updateSubViews(); + }, + + // helper + updateSubViews: function () { + this.mainFieldsView.update(this.options); + this.keySearchFieldsView.update(this.options); + this.additionalParamsView.update(this.options); + }, + + trayIsVisible: function () { + return $("#query-options-tray").is(":visible"); + }, + + closeTray: function () { + $("#query-options-tray").velocity("reverse", 250, function () { // TODO constant + $("#query-options-tray").hide(); + }); + } + }); + + + // ------ "private" Views ------ + + var MainFieldsView = FauxtonAPI.View.extend({ + template: "addons/documents/templates/query_options_main_fields", + events: { + "change #qoReduce": "onToggleReduceCheckbox" + }, + + initialize: function (options) { + this.queryParams = options.queryParams; + this.showStale = options.showStale; + this.hasReduce = options.hasReduce; + }, + + update: function (options) { + this.queryParams = options.queryParams; + this.showStale = options.showStale; + this.hasReduce = options.hasReduce; + + // if the View hasn't already rendered we can rely on afterRender() to pre-fill the fields + if (this.hasRendered) { + this.render(); + } + }, + + afterRender: function () { + $("#qoIncludeDocs").prop("checked", this.queryParams.include_docs === "true"); + this.updateReduceSettings(this.queryParams.reduce === "true"); + }, + + /* + * The "Reduce" option comes with baggage: + * - we can't include_docs for reduce = true + * - can't include group_level for reduce = false + */ + onToggleReduceCheckbox: function (e) { + e.preventDefault(); + var isChecked = $(e.currentTarget).prop("checked"); + this.updateReduceSettings(isChecked); + }, + + + // helper function to hide/show, disable/enable fields based on whether "Reduce" is an option and whether + // it's checked + updateReduceSettings: function (isChecked) { + $("#qoReduce").prop("checked", isChecked); + + var $qoIncludeDocs = $("#qoIncludeDocs"), + $qoIncludeDocsLabel = $("#qoIncludeDocsLabel"), + $qoGroupLevelGroup = $("#qoGroupLevelGroup"); + + if (this.hasReduce) { + $("#qoGroupLevel").val(this.queryParams.group_level); + + if (isChecked) { + $qoIncludeDocs.prop({ "checked": false, "disabled": true }); + $qoIncludeDocsLabel.addClass("disabled"); + $qoGroupLevelGroup.removeClass("hide"); + } else { + $qoIncludeDocs.prop("disabled", false); + $qoIncludeDocsLabel.removeClass("disabled"); + $qoGroupLevelGroup.addClass("hide"); + } + } else { + $qoIncludeDocs.prop("disabled", false); + $qoIncludeDocsLabel.removeClass("disabled"); + $qoGroupLevelGroup.addClass("hide"); + } + }, + + getParams: function () { + var params = {}; + this.$("input:checked,select").each(function () { + + // this ensures that only settings that differ from the defaults are passed along. If we didn't do this, + // the query string would be loaded up with all possible vals for each search (which would work, but would be ugly) + if (this.value !== defaultOptions.queryParams[this.name]) { + params[this.name] = this.value; + } + }); + return params; + }, + + serialize: function () { + return { + hasReduce: this.hasReduce, + showStale: this.showStale + }; + } + }); + + + var KeySearchFieldsView = FauxtonAPI.View.extend({ + template: "addons/documents/templates/query_options_key_search", + events: { + "click .toggle-btns > label": "toggleKeysSection" + }, + + initialize: function (options) { + this.queryParams = options.queryParams; + this.hasReduce = options.hasReduce; + }, + + update: function (options) { + this.queryParams = options.queryParams; + this.hasReduce = options.hasReduce; + + if (this.hasRendered) { + this.render(); + } + }, + + // prefill the form fields + afterRender: function () { + if (this.queryParams.keys) { + this.$(".toggle-btns > label[data-action=showByKeys]").addClass("active"); + this.$(".js-query-keys-wrapper").removeClass("hide"); + this.showByKeysSection(); + $("#keys-input").val(this.queryParams.keys); + } else { + + // if the startKey, endKey or inclusive_end differs from the defaults, show the section. Meh, this sucks... + if (defaultOptions.queryParams.startkey !== this.queryParams.startkey || + defaultOptions.queryParams.endkey !== this.queryParams.endkey || + defaultOptions.queryParams.inclusive_end !== this.queryParams.inclusive_end) { + this.$(".toggle-btns > label[data-action=showBetweenKeys]").addClass("active"); + this.$(".js-keys-section").addClass("hide"); + this.$(".js-query-keys-wrapper").removeClass("hide"); + this.showBetweenKeysSection(); + + $("#startkey").prop("disabled", false).val(this.queryParams.startkey); + $("#endkey").prop("disabled", false).val(this.queryParams.endkey); + $("#qoIncludeEndKeyInResults").prop("checked", this.queryParams.inclusive_end === "true"); + } + } + }, + + toggleKeysSection: function (e) { + e.preventDefault(); + + var $clickedEl = $(e.currentTarget); + var $keyFieldsWrapper = this.$(".js-query-keys-wrapper"); + + if ($clickedEl.hasClass("active")){ + $clickedEl.removeClass("active"); + $keyFieldsWrapper.addClass("hide"); + } else { + this.$(".toggle-btns > label").removeClass("active"); + this.$(".js-keys-section").hide(); + + $clickedEl.addClass("active"); + $keyFieldsWrapper.removeClass("hide"); + + // show section and disable what needs to be disabled + var action = $clickedEl.data("action"); + if (action === "showByKeys") { + this.showByKeysSection(); + } else { + this.showBetweenKeysSection(); + } + } + }, + + showByKeysSection: function () { + this.$("#js-showKeys, .js-disabled-message").show(); + this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').prop("disabled", true); + this.$('[name="keys"]').removeAttr("disabled"); + }, + + showBetweenKeysSection: function (){ + this.$("#js-showStartEnd").show(); + this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').removeAttr("disabled"); + this.$('.js-disabled-message').hide(); + this.$('[name="keys"]').prop("disabled", true); + }, + + // this assumes that hasValidInputs has been called. Otherwise the returned param data may be invalid + getParams: function () { + var params = {}; + var selectedKeysSection = this.getSelectedKeysSection(); + + // basically the gist of this is that it only actually returns *relevant* key-value pairs. Defaults + // aren't included because they'd clutter up the URL + if (selectedKeysSection === "showByKeys") { + var keys = $.trim($("#keys-input").val()); + if (keys !== "") { + params.keys = keys; + } + } else if (selectedKeysSection === "showBetweenKeys") { + var startKey = $.trim($("#startkey").val()); + if (startKey !== defaultOptions.queryParams.startkey) { + params.startkey = startKey; + } + var endKey = $.trim($("#endkey").val()); + if (endKey !== defaultOptions.queryParams.endkey) { + params.endkey = endKey; + } + var includeEndKeyVal = $("#qoIncludeEndKeyInResults").is(":checked"); + params.inclusive_end = (includeEndKeyVal) ? "true" : "false"; + } + return params; + }, + + /* + * Checks to see that the user-inputted values are valid. If not, it displays a message to the user. + * @returns {boolean} true if all valid; false otherwise + */ + hasValidInputs: function () { + var selectedKeysSection = this.getSelectedKeysSection(), + errorMsg = null; + + if (selectedKeysSection === "showByKeys") { + var keys = this.parseJSON($("#keys-input").val()); + if (_.isUndefined(keys) || !_.isArray(keys)) { + errorMsg = "Keys values must be in an array, e.g [1,2,3]"; + } + } else { + var startKey = $.trim($("#startkey").val()), + endKey = $.trim($("#endkey").val()); + + if (startKey !== "" && _.isUndefined(this.parseJSON(startKey))) { + errorMsg = "JSON Parse Error on the Start Key field"; + } else if (endKey !== "" && _.isUndefined(this.parseJSON(endKey))) { + errorMsg = "JSON Parse Error on the End Key field"; + } + } + + if (errorMsg !== null) { + this.$(".js-keys-error").empty(); + + FauxtonAPI.addNotification({ + type: "error", + msg: errorMsg, + clear: false, + selector: ".query-options .errors-container" + }); + return false; + } + + return true; + }, + + parseJSON: function (value) { + try { + return JSON.parse(value); + } catch(e) { + return undefined; + } + }, + + getSelectedKeysSection: function () { + return this.$(".toggle-btns > label.active").data("action"); + } + }); + + + var AdditionalParamsView = FauxtonAPI.View.extend({ + template: "addons/documents/templates/query_options_additional_params", + + initialize: function (options) { + this.queryParams = options.queryParams; + this.showStale = options.showStale; + }, + + update: function (options) { + this.queryParams = options.queryParams; + this.showStale = options.showStale; + if (this.hasRendered) { + this.render(); + } + }, + + afterRender: function () { + $("#qoUpdateSeq").prop("checked", this.queryParams.update_seq === "true"); + $("#qoDescending").prop("checked", this.queryParams.descending === "true"); + $("#qoLimit").val(this.queryParams.limit); + $("#qoSkip").val(this.queryParams.skip); + $("#qoStale").prop("checked", this.queryParams.stale === "ok"); + }, + + getParams: function () { + var params = {}; + this.$("input,select").each(function () { + if ($(this).is(":checkbox")) { + if (this.checked) { + params[this.name] = this.value; + } + } else { + var val = $.trim(this.value); + if (val !== "") { + params[this.name] = this.value; + } + } + }); + return params; + }, + + hasValidInputs: function () { + var allValid = true; + var skipVal = $("#qoSkip").val(); + if (skipVal !== "" && /\D/.test(skipVal)) { + FauxtonAPI.addNotification({ + msg: "Please only enter numbers only for the Skip field.", + type: "error", + selector: ".query-options .errors-container", + clear: true + }); + allValid = false; + } + return allValid; + }, + + serialize: function () { + return { + showStale: this.showStale + }; + } + }); + + return Views; + });