Repository: couchdb-fauxton Updated Branches: refs/heads/continue-secondary-index [created] 16049ba5b
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/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/113615ff/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..7d58116 --- /dev/null +++ b/app/addons/indexes/templates/design_doc_selector.html @@ -0,0 +1,36 @@ +<!-- +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. +--> +<label for="ddoc">Save to Design Document <a class="help-link" data-bypass="true" href="<%-getDocUrl('design_doc')%>" target="_blank"><i class="icon-question-sign"></i></a></label> +<div class="row-fluid new-ddoc"> + <div class="select-wrapper span5"> + <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> + <i></i> + </div> + + <input type="text" id="new-ddoc" class="span7" style="display:none" placeholder="Enter a design doc name" /> +</div> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/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..38634b5 --- /dev/null +++ b/app/addons/indexes/templates/header_right.html @@ -0,0 +1,22 @@ +<!-- +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. +--> + <!-- Select toggle--> + <div id="header-select-all"> + <span class="toggle-select-menu icon fonticon-ok-circled">Select</span> + </div> + <!-- Query Options--> + <div id="header-query-options"></div> + <!--right margin for api bar--> + <div id="header-api-bar"></div> + http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/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/113615ff/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/113615ff/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..a7de45b --- /dev/null +++ b/app/addons/indexes/templates/preview_screen.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. +--> + +<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/113615ff/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/113615ff/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/113615ff/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..bfe209e --- /dev/null +++ b/app/addons/indexes/views.js @@ -0,0 +1,701 @@ +// 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 = {}; + + +//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; + this.api = options.api; + this.endpoint = options.endpoint; + this.documentation = options.documentation; + this.eventer = _.extend({}, Backbone.Events); + }, + updateApiUrl: function(api){ + //this will update the api bar when the route changes + //you can find the method that updates it in components.js Components.ApiBar() + this.apiBar && this.apiBar.update(api); + }, + beforeRender: function(){ + + this.apiBar = this.insertView("#header-api-bar", new Components.ApiBar({ + endpoint: this.endpoint, + documentation: this.documentation + })); + + this.advancedOptions = this.insertView('#header-query-options', 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 + })); + }, + hasReduce: function(){ + + }, + updateView: function(event, paramInfo) { + event.preventDefault(); + + var errorParams = paramInfo.errorParams, + params = paramInfo.params; + + if (_.any(errorParams)) { + _.map(errorParams, function(param) { + + // TODO: Where to add this error? + // bootstrap wants the error on a control-group div, but we're not using that + //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error'); + return FauxtonAPI.addNotification({ + msg: "JSON Parse Error on field: "+param.name, + type: "error", + selector: ".advanced-options .errors-container", + clear: true + }); + }); + FauxtonAPI.addNotification({ + msg: "Make sure that strings are properly quoted and any other values are valid JSON structures", + type: "warning", + selector: ".advanced-options .errors-container", + clear: true + }); + + return false; + } + + var fragment = window.location.hash.replace(/\?.*$/, ''); + if (!_.isEmpty(params)) { + fragment = fragment + '?' + $.param(params); + } + + FauxtonAPI.navigate(fragment, {trigger: false}); + FauxtonAPI.triggerRouteEvent('updateAllDocs', {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}); + }); + }); + } + }); + + + + + 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}); + }, + + 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/113615ff/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/113615ff/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/113615ff/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/113615ff/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/113615ff/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 http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/assets/index.underscore ---------------------------------------------------------------------- diff --git a/assets/index.underscore b/assets/index.underscore index 396cce3..6a887b5 100644 --- a/assets/index.underscore +++ b/assets/index.underscore @@ -35,10 +35,6 @@ <div role="main" id="main"> <div id="global-notifications" class="container errors-container"></div> <div id="app-container"></div> - - <footer> - <div id="footer-content"></div> - </footer> </div> <!-- Application source. --> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/assets/less/fauxton.less ---------------------------------------------------------------------- diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less index 93afce6..29ef04f 100644 --- a/assets/less/fauxton.less +++ b/assets/less/fauxton.less @@ -22,7 +22,10 @@ @import "bootstrap/mixins.less"; @import "prettyprint.less"; @import "icons.less"; - +@import "templates.less"; +@import "headers.less"; +@import "formstyles.less"; +@import "pagination.less"; /** * HTML-wide overrides **/ @@ -56,28 +59,7 @@ a:hover { color: @red; } -input[type=text], -input[type=password] { - .border-radius(0); - padding: 12px; - border: 1px solid #ccc; - height: auto; - font-size: 16px; - margin-top: 0; -} - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; - padding: 0; -} -input[type="file"], -input[type="checkbox"], -input[type="radio"], -select { - margin: 0 0 1em 0; -} /* bootstrap overrides */ @@ -166,109 +148,7 @@ tbody { background-color: #F7F7F7; } -/*form elements and buttons*/ -.btn-group { - > .btn + .dropdown-toggle, - > .btn:first-child, - > .btn:last-child, - > .dropdown-toggle { - .border-radius(0); - background-image: none; - text-shadow: none; - } -} - -.btn { - .box-shadow(none); - .border-radius(@baseBorderRadius); - background-image: none; - text-shadow: none; - background-repeat: no-repeat; - padding: 10px; - margin-top: 0px; - .icon { - margin-right: 0.2em; - } - &.btn-small { - padding: 5px 10px; - .icon { - margin-right: 0; - font-size: inherit; - } - } - &.btn-mini { - padding: 3px 8px; - .icon { - margin-right: 0; - font-size: inherit; - } - } -} -.btn-primary { - background: @redButton; -} - -.btn-primary a:visited { - color: #fff; -} - -.form-actions { - background: none; - border: none; -} - -.input-append, -.input-prepend { - .add-on { - font-size: 18px; - padding: 14px 5px 30px; - } - .btn .icon { - font-size: 21.5px; - margin-right: 0; - } -} - -.row-fluid .input-append [class*="span"], -.input-prepend input[class*="span"] { - width: auto; -} - -.form-inline { - input[type=password], - input[type=text] { - width: auto; - } -} -.checkbox { - label { - display: inline-block; - padding-left:25px; - } -} - -label { - margin-right: 15px; - padding-left:0; - display: block; - cursor: pointer; - position: relative; - font-size: 14px; - &.inline { - display: inline-block; - } -} -.help-block { - font-size: 12px; -} - -a.help-link:hover { - text-decoration: none; -} -input[type=text].error { - border: red 1px solid; -} /** * Fauxton-specific Bootstrap additions @@ -297,462 +177,9 @@ table.databases { } } -/* ajax loader */ -.loader { - background: url('../img/loader.gif') center center no-repeat; - min-height: 100px; -} -#app-container.loader{ - min-height: 400px; - > *{ - display: none; - } -} - -#global-notifications { - position: fixed; - top: 0px; - display: block; - z-index: 100000; - left: @navWidth; - .closeMenu & { - left: @collapsedNavWidth; - } - width: 100%; -} - -#app-container{ - padding: 0; - height: 100%; - width: 100%; - position: absolute; - top: 0; - left: 0; - > .row-fluid { - height: 100%; - } -} - -/* Fixed side navigation */ -#primary-navbar { - height: 100%; - position: fixed; - width: @navWidth; - top: 0; - bottom: 0; - background-color: @primaryNav; - overflow-y: scroll; - .js-version { - color: #fff; - font-size: 10px; - padding-left: 10px; - } - .closeMenu & { - .js-version { - display: none; - } - } - #footer-links{ - position: absolute; - bottom: 0; - width: 100%; - } - #user-create-admin{ - font-size: 12px - } - .navbar { - .burger{ - .transition(all @transitionSpeed @transitionEaseType); - padding: 22px 0 0 18px; - position: fixed; - z-index: 100; - width: 64px; - top: 0; - background-color: @primaryNav; - width: @navWidth; - div{ - .transition(all @transitionSpeed @transitionEaseType); - height: 4px; - width: 24px; - .border-radius(2); - background-color: @navBG; - margin: 2px 0px; - } - &:hover div{ - background-color: @orange; - } - } - .bottom-container { - height: 110px; - position: fixed; - bottom: 0; - width: 220px; - background: #3a2c2b; - .brand { - .box-sizing(content-box); - .hide-text; - .customTransition(left, 1s, 0.805, 0.005, 0.165, 0.985); - margin: 10px 0 0 0; - width: 200px; - height: 40px; - padding: 10px; - float: none; - background: #3a2c2b; - .icon { - .box-sizing(content-box); - background: url(../img/couchdb-site.png) no-repeat 0 0; - display: block; - height: 100%; - width: 100%; - } - .closeMenu & { - .icon { - background: url(../img/minilogo.png) no-repeat 0 0; - } - width: 45px; - } - } - #footer-nav-links { - li { - a { - font-size: 12px; - color: @red; - padding: 12px; - text-shadow: none; - } - &.active, &:hover{ - a { - text-decoration: underline; - } - } - } - } - } - nav { - margin-top: 64px; - .nav{ - margin: 0; - li{ - .transition(all @transitionSpeed @transitionEaseType); - padding: 0; - font-size: 16px; - letter-spacing: 1px; - line-height: 23px; - width: @navWidth; - font-weight: normal; - font-family: helvetica; - .box-sizing(border-box); - background-color: @navBG; - border-bottom: 1px solid @primaryNav; - min-height: 48px; - &.active, &:hover{ - a{ - .box-shadow(none); - } - background-color: @red; - } - &:hover .fonticon:before{ - color: @white; - } - &.active .fonticon:before, - &:hover .fonticon:before, - { - text-shadow: @boxShadow; - color: @NavIconActive; - } - a{ - padding: 12px 25px 12px 60px; - background-color: transparent; - color: #fff; - text-shadow: @textShadowOff; - &.closeMenu{ - color: transparent; - } - .fonticon { - position: relative; - &:before { - position: absolute; - top: -5px; - left: -41px; - font-size: 24px; - color: @NavIcon; - text-shadow: @boxShadowOff; - } - } - .closeMenu &{ - color: transparent; - } - } - } - } - ul#footer-nav-links{ - li{ - background-color: @primaryNav; - border-top: 1px solid @red; - border-bottom: none; - font-size: 12px; - padding: 12px; - min-height: 44px; - &.active, &:hover{ - background-color: @linkRed; - border-top: 1px solid @red; - a{ - color: white; - } - } - a{ - color: @red; - } - } - - } - ul#bottom-nav-links{ - margin-top: 0; - padding-bottom: 70px; - li{ - min-height: 55px; - background-color: @bottomNav; - &.active{ - background-color:@linkRed; - } - &:hover{ - background-color: @navBGHover; - } - a{ - &.fonticon { - position: relative; - &:before { - top: -5px; - left: -40px; - font-size: 22px; - } - } - } - } - } - } - } -} - - -#dashboard { - .box-shadow(-6px 0 rgba(0, 0, 0, 0.1)); - border-left: 1px solid #999; - position: absolute; - left: @navWidth; - margin-left: 0; - padding-left: 0; - padding-right: 0; - background-color: @sidebarBG; - min-width: 600px; - height: 100%; - .closeMenu &{ - left: @collapsedNavWidth; - } - &.one-pane{ - min-width: 800px; - margin-top: 0; - overflow-x: hidden; - } -} - -/*dashboard content can be in multiple templates*/ - -#dashboard-content{ - &.row-fluid, - &.window-resizeable{ - /*remove gutter without rewriting variable*/ - margin-left: 0px; - } - padding: 20px; - .with-sidebar &{ - border-left: 1px solid #999; - border-right: 1px solid #999; - width: auto; - .box-shadow(-6px 0 rgba(0, 0, 0, 0.1)); - padding: 0px; - bottom: 0px; - top: 60px; - position: fixed; - overflow-x: hidden; - overflow-y: auto; - left: @sidebarWidth+@navWidth; - right: 0; - .box-sizing(border-box); - .closeMenu & { - left: @sidebarWidth+@collapsedNavWidth; - } - } - > div.inner { - display: block; - } -} - -.with-sidebar.content-area { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; -} - -// .closeMenu .with-sidebar.content-area { -// left: 0; -// } -/*tools*/ - -.row-fluid.content-area{ - background-color: @background; -} - - -.fixed-header{ - background-color: @breadcrumbBG; - position: fixed; - top: 0; - right: 0; - left: @navWidth; - .closeMenu & { - left: @collapsedNavWidth; - } - border-bottom: 5px solid @breadcrumbBorder; - .box-shadow(0 4px 6px -2px #808080); - z-index: 100; - .one-pane & { - position: relative; - border: none; - .box-shadow(none); - left: auto; - } -} - -#breadcrumbs { - .breadcrumb { - margin: 15px 20px; - margin-bottom: 0; - background-color: transparent; - padding: 0; - li { - .divider { - font-size: 12px; - color: @breadcrumbArrow; - } - &:first-child { - font-size: 30px; - } - color: @breadcrumbText; - font-size: 18px; - text-shadow: none; - &.active{ - color: #333; - } - a{ - color: @breadcrumbText; - } - } - } -} - - -/*SIDEBAR TEMPLATE STYLES*/ -.topmenu-defaults { - height: 70px; - padding: 12px 10px 0; - .box-sizing(border-box); -} - -.dashboard-upper-menu{ - right: 0; - left: @sidebarWidth+@navWidth; - position: fixed; - z-index: 11; - display: block; - .topmenu-defaults; - background-color: #CBCBCB; - .closeMenu & { - left: @sidebarWidth+@collapsedNavWidth; - } -} - -#dashboard-lower-content{ - padding: 20px; - background-color: #F1F1F1; -} - -#dashboard-upper-content{ - .tab-content { - padding-top: 70px; - } - .well{ - padding: 20px; - .border-radius(0); - .box-shadow(none); - } -} - -.sidenav { - padding: 0; - header { - width: @sidebarWidth; - border-bottom: 1px solid #d3d7db; - } - .nav-list{ - .divider { - border: none; - } - > li > a:hover, - > li > a:focus{ - background-color: @darkRed; - color: #fff; - } - li.active > a { - color: @darkRed; - } - > li > a{ - color: @linkRed; - padding: 10px 13px 10px 24px; - border-bottom: 1px solid #d3d7db; - span{ - margin-right: 8px; - width: 14px; - display: inline-block; - text-align: center; - } - } - a{ - display: block; - padding: 10px 5px 5px 15px; - color: @subListGray; - .divider { - background: none; - color: #ccc; - padding: 0 2px; - } - } - .nav-header{ - padding: 0px; - text-shadow: none; - color: #333333; - & > span:hover { - color: @red; - } - } - } -} -#sidebar-content { - position: absolute; - top: 60px; - width: @sidebarWidth; - left: 0; - background-color: @secondarySidebar; - > div.inner { - display: block; - } -} -/*ONE PANEL TEMPLATE ONLY STYLES AKA _all_dbs */ .result-tools{ border-bottom: 1px solid #999999; @@ -808,76 +235,7 @@ table.databases { } } -.custom-inputs{ - - input[type=radio], - input[type=checkbox] { - display: none; - } - - .checkbox label:before { - border-radius: 3px; - } - - .controls > .radio:first-child, .controls > .checkbox:first-child { - padding-top: 15px; - } - - .radio.inline, .checkbox.inline { - display: inline-block; - padding-top: 15px; - margin-bottom: 12px; - vertical-align: middle; - } - - input[type=checkbox]:checked + label:before { - /*content: "\2713"; */ - content: "\00d7"; - text-shadow: 1px 1px 1px rgba(0, 0, 0, .2); - font-size: 16px; - background-color: @red; - color: white; - text-align: center; - line-height: 15px; - } - - label:before { - content: ""; - display: inline-block; - - width: 16px; - height: 16px; - - margin-right: 10px; - position: absolute; - left: 0; - bottom: 1px; - background-color: #aaa; - box-shadow: inset 0px 2px 3px 0px rgba(0, 0, 0, .3), 0px 1px 0px 0px rgba(255, 255, 255, .8); - } - - .radio label:before { - border-radius: 8px; - } - - input[type=radio]:checked + label:before { - content: "\2022"; - color: #f3f3f3; - font-size: 30px; - text-align: center; - line-height: 18px; - } - - label.drop-down{ - &:before{ - display: none; - } - } -} -form.view-query-update, form.view-query-save { - max-width: 100%; -} /*documents and databases */ .view.show{ @@ -890,11 +248,6 @@ div.spinner { top: 50%; } -#api-navbar{ - position: relative; - padding-right: 5px; -} - .api-url-btn { margin-top: 5px; margin-bottom: 5px; @@ -990,39 +343,4 @@ div.spinner { } } -div.add-dropdown { - position: absolute; - top: 2px; - right: 0px; - .dropdown-menu{ - left: -110px; - padding-bottom: 0; - width: 148px; - min-width: 0; - top: 38px; - .box-shadow(@boxShadow); - &.arrow:before{ - right: 4px; - } - a { - background-color: #202326; - color: rgba(255, 255, 255, 0.8); - &:hover{ - background-color: @red; - color: white; - } - } - li a { - padding: 10px 15px 10px 12px; - } - } - .dropdown-toggle{ - border-top: none !important; - text-decoration: none; - } - > a { - border-bottom: none; - text-decoration: none; - font-size: 16px; - } -} + http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/assets/less/formstyles.less ---------------------------------------------------------------------- diff --git a/assets/less/formstyles.less b/assets/less/formstyles.less new file mode 100644 index 0000000..4645664 --- /dev/null +++ b/assets/less/formstyles.less @@ -0,0 +1,247 @@ +/* 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 "variables.less"; + +input[type=text], +input[type=password] { + .border-radius(0); + padding: 12px; + border: 1px solid #ccc; + height: auto; + font-size: 16px; + margin-top: 0; +} + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} + +input[type="file"], +input[type="checkbox"], +input[type="radio"], +select { + margin: 0 0 1em 0; +} + +/*form elements and buttons*/ +.btn-group { + > .btn + .dropdown-toggle, + > .btn:first-child, + > .btn:last-child, + > .dropdown-toggle { + .border-radius(0); + background-image: none; + text-shadow: none; + } +} + +.btn { + .box-shadow(none); + .border-radius(@baseBorderRadius); + background-image: none; + text-shadow: none; + background-repeat: no-repeat; + padding: 10px; + margin-top: 0px; + .icon { + margin-right: 0.2em; + } + &.btn-small { + padding: 5px 10px; + .icon { + margin-right: 0; + font-size: inherit; + } + } + &.btn-mini { + padding: 3px 8px; + .icon { + margin-right: 0; + font-size: inherit; + } + } +} +.btn-primary { + background: @redButton; +} + +.btn-primary a:visited { + color: #fff; +} + +.form-actions { + background: none; + border: none; +} + +.input-append, +.input-prepend { + .add-on { + font-size: 18px; + padding: 14px 5px 30px; + } + .btn .icon { + font-size: 21.5px; + margin-right: 0; + } +} + +.row-fluid .input-append [class*="span"], +.input-prepend input[class*="span"] { + width: auto; +} + +.form-inline { + input[type=password], + input[type=text] { + width: auto; + } +} +.checkbox { + label { + display: inline-block; + padding-left:25px; + } +} + +label { + margin-right: 15px; + padding-left:0; + display: block; + cursor: pointer; + position: relative; + font-size: 14px; + &.inline { + display: inline-block; + } +} +.help-block { + font-size: 12px; +} + +a.help-link:hover { + text-decoration: none; +} + +input[type=text].error { + border: red 1px solid; +} + +form.view-query-update, form.view-query-save { + max-width: 100%; +} +.custom-inputs{ + + input[type=radio], + input[type=checkbox] { + display: none; + } + + .checkbox label:before { + border-radius: 3px; + } + + .controls > .radio:first-child, .controls > .checkbox:first-child { + padding-top: 15px; + } + + .radio.inline, .checkbox.inline { + display: inline-block; + padding-top: 15px; + margin-bottom: 12px; + vertical-align: middle; + } + + input[type=checkbox]:checked + label:before { + /*content: "\2713"; */ + content: "\00d7"; + text-shadow: 1px 1px 1px rgba(0, 0, 0, .2); + font-size: 16px; + background-color: @red; + color: white; + text-align: center; + line-height: 15px; + } + + label:before { + content: ""; + display: inline-block; + + width: 16px; + height: 16px; + + margin-right: 10px; + position: absolute; + left: 0; + bottom: 1px; + background-color: #aaa; + box-shadow: inset 0px 2px 3px 0px rgba(0, 0, 0, .3), 0px 1px 0px 0px rgba(255, 255, 255, .8); + } + + .radio label:before { + border-radius: 8px; + } + + input[type=radio]:checked + label:before { + content: "\2022"; + color: #f3f3f3; + font-size: 30px; + text-align: center; + line-height: 18px; + } + + label.drop-down{ + &:before{ + display: none; + } + } +} + +div.add-dropdown { + position: absolute; + top: 2px; + right: 0px; + .dropdown-menu{ + left: -110px; + padding-bottom: 0; + width: 148px; + min-width: 0; + top: 38px; + .box-shadow(@boxShadow); + &.arrow:before{ + right: 4px; + } + a { + background-color: #202326; + color: rgba(255, 255, 255, 0.8); + &:hover{ + background-color: @red; + color: white; + } + } + li a { + padding: 10px 15px 10px 12px; + } + } + .dropdown-toggle{ + border-top: none !important; + text-decoration: none; + } + > a { + border-bottom: none; + text-decoration: none; + font-size: 16px; + } +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/assets/less/headers.less ---------------------------------------------------------------------- diff --git a/assets/less/headers.less b/assets/less/headers.less new file mode 100644 index 0000000..e073ad7 --- /dev/null +++ b/assets/less/headers.less @@ -0,0 +1,128 @@ +/* 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. + */ +.fixed-header{ + height: 60px; + background-color: @breadcrumbBG; + position: fixed; + top: 0; + right: 0; + left: @navWidth; + .closeMenu & { + left: @collapsedNavWidth; + } + z-index: 100; + .two-pane & { + border: none; + } + .two-pane &, + .with-sidebar & { + #api-navbar{ + > div { + .bottom-shadow-border; + height: 60px; + } + .left-shadow-border; + } + #breadcrumbs{ + .bottom-shadow-border; + } + } + .one-pane & { + #breadcrumbs{ + width: 90%; + } + position: relative; + border: none; + .box-shadow(none); + left: auto; + } + /* these styles are for the new header*/ + > div { + display:inline-block; + vertical-align: top; + } +} + +#api-navbar{ + height: 60px; + position: relative; + /* these styles are for the new header*/ + .right-header{ + } +} + +#breadcrumbs { + height: 60px; + &.sidebar{ + width: @sidebarWidth - 4; + } + /* these styles are for the new header*/ + .header-left{ + > div{ + display:inline-block; + } + } + .breadcrumb { + margin-bottom: 0; + background-color: transparent; + padding: 0; + li { + padding:15px 10px; + height: 60px; + vertical-align: top; + &:first-child { + font-size: 30px; + .with-sidebar &, + .two-pane & { + padding:20px 10px; + font-size: 19px; + border-right: 1px solid #ccc; + } + } + color: @breadcrumbText; + font-size: 18px; + text-shadow: none; + &.active{ + color: #333; + } + a{ + text-decoration: none; + color: @breadcrumbText; + } + } + } +} + +.header-left{ + position: relative; + #header-dropdown-menu { + position: absolute; + right: 0; + top: 0; + a { + text-decoration: none; + } + .dropdown { + border-left: 1px solid #ccc; + padding: 20px; + } + .dropdown-menu { + left: -105px; + top: 56px; + } + } +} + + + + http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/assets/less/mixins.less ---------------------------------------------------------------------- diff --git a/assets/less/mixins.less b/assets/less/mixins.less index 63eda35..9c47456 100644 --- a/assets/less/mixins.less +++ b/assets/less/mixins.less @@ -1,3 +1,15 @@ +/* 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. + */ .translate-origin(@x, @y) { -webkit-transform-origin: @x @y; -moz-transform-origin: @x @y; @@ -7,15 +19,15 @@ } .customTransition(@prop, @delay, @a, @b, @c, @d){ --webkit-transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); - -moz-transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); - -ms-transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); - -o-transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); +-webkit-transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); + -moz-transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); + -ms-transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); + -o-transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); transition: @prop, @delay cubic-bezier(@a, @b, @c, @d); /* custom */ --webkit-transition-timing-function: cubic-bezier(@a, @b, @c, @d); - -moz-transition-timing-function: cubic-bezier(@a, @b, @c, @d); - -ms-transition-timing-function: cubic-bezier(@a, @b, @c, @d); - -o-transition-timing-function: cubic-bezier(@a, @b, @c, @d); +-webkit-transition-timing-function: cubic-bezier(@a, @b, @c, @d); + -moz-transition-timing-function: cubic-bezier(@a, @b, @c, @d); + -ms-transition-timing-function: cubic-bezier(@a, @b, @c, @d); + -o-transition-timing-function: cubic-bezier(@a, @b, @c, @d); transition-timing-function: cubic-bezier(@a, @b, @c, @d); /* custom */ } http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/assets/less/pagination.less ---------------------------------------------------------------------- diff --git a/assets/less/pagination.less b/assets/less/pagination.less new file mode 100644 index 0000000..07e13b3 --- /dev/null +++ b/assets/less/pagination.less @@ -0,0 +1,21 @@ +/* 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. + */ +#documents-pagination { + position:fixed; + background-color:#fff; + bottom:0; + border-top:1px solid #ccc; + .pagination{ + margin: 15px 0 10px; + } +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/assets/less/templates.less ---------------------------------------------------------------------- diff --git a/assets/less/templates.less b/assets/less/templates.less new file mode 100644 index 0000000..062cd32 --- /dev/null +++ b/assets/less/templates.less @@ -0,0 +1,490 @@ +/* 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 "variables.less"; + +/* ajax loader */ +.loader { + background: url('../img/loader.gif') center center no-repeat; + min-height: 100px; +} + +#global-notifications { + position: fixed; + top: 0px; + display: block; + z-index: 100000; + left: @navWidth; + .closeMenu & { + left: @collapsedNavWidth; + } + width: 100%; +} + +/*container where the layout is injected*/ +#app-container{ + padding: 0; + height: 100%; + width: 100%; + position: absolute; + top: 0; + left: 0; + > .row-fluid { + height: 100%; + } + &.loader{ + min-height: 400px; + > *{ + display: none; + } + } +} + +/* Fixed side navigation */ +#primary-navbar { + /* hack for the scrollbar that shines through from the sidebar */ + -webkit-transform: translate3d(0, 0, 0); + height: 100%; + position: fixed; + width: @navWidth; + top: 0; + bottom: 0; + background-color: @primaryNav; + overflow-y: scroll; + .version { + color: #fff; + font-size: 10px; + padding-left: 10px; + } + #footer-links{ + position: absolute; + bottom: 0; + width: 100%; + } + #user-create-admin{ + font-size: 12px + } + .navbar { + .burger{ + .transition(all @transitionSpeed @transitionEaseType); + padding: 22px 0 0 18px; + position: fixed; + top: 0; + z-index: 100; + background-color: @primaryNav; + width: @navWidth; + div{ + .transition(all @transitionSpeed @transitionEaseType); + height: 4px; + width: 24px; + .border-radius(2); + background-color: @navBG; + margin: 2px 0px; + } + &:hover div{ + background-color: @orange; + } + } + .bottom-container { + height: 110px; + position: fixed; + bottom: 0; + width: 220px; + background: #3a2c2b; + .brand { + .box-sizing(content-box); + .hide-text; + .customTransition(left, 1s, 0.805, 0.005, 0.165, 0.985); + margin: 10px 0 0 0; + width: 200px; + height: 40px; + padding: 10px; + float: none; + background: #3a2c2b; + .icon { + .box-sizing(content-box); + background: url(../img/couchdb-site.png) no-repeat 0 0; + display: block; + height: 100%; + width: 100%; + } + .closeMenu & { + .icon { + background: url(../img/minilogo.png) no-repeat 0 0; + } + width: 45px; + } + } + #footer-nav-links { + li { + a { + font-size: 12px; + color: @red; + padding: 12px; + text-shadow: none; + } + &.active, &:hover{ + a { + text-decoration: underline; + } + } + } + } + } + nav { + margin-top: 64px; + .nav{ + margin: 0; + li{ + .transition(all @transitionSpeed @transitionEaseType); + padding: 0; + font-size: 16px; + letter-spacing: 1px; + line-height: 23px; + width: @navWidth; + font-weight: normal; + font-family: helvetica; + .box-sizing(border-box); + background-color: @navBG; + border-bottom: 1px solid @primaryNav; + min-height: 48px; + &.active, &:hover{ + a{ + .box-shadow(none); + } + background-color: @red; + } + &:hover .fonticon:before{ + color: @white; + } + &.active .fonticon:before, + &:hover .fonticon:before, + { + text-shadow: @boxShadow; + color: @NavIconActive; + } + a{ + padding: 12px 25px 12px 60px; + background-color: transparent; + color: #fff; + text-shadow: @textShadowOff; + &.closeMenu{ + color: transparent; + } + .fonticon { + position: relative; + &:before { + position: absolute; + top: -5px; + left: -41px; + font-size: 24px; + color: @NavIcon; + text-shadow: @boxShadowOff; + } + } + .closeMenu &{ + color: transparent; + } + } + } + } + ul#footer-nav-links{ + li{ + background-color: @primaryNav; + border-top: 1px solid @red; + border-bottom: none; + font-size: 12px; + padding: 12px; + min-height: 44px; + &.active, &:hover{ + background-color: @linkRed; + border-top: 1px solid @red; + a{ + color: white; + } + } + a{ + color: @red; + } + } + + } + ul#bottom-nav-links{ + margin-top: 0; + padding-bottom: 70px; + li{ + min-height: 55px; + background-color: @bottomNav; + &.active{ + background-color:@linkRed; + } + &:hover{ + background-color: @navBGHover; + } + a{ + &.fonticon { + position: relative; + &:before { + top: -5px; + left: -40px; + font-size: 22px; + } + } + } + } + } + } + } +} + + +/* +--------------------------------------------------- + REUSEABLE SHADOW BORDER +--------------------------------------------------- +*/ + +.left-shadow-border{ + border-left: 1px solid #999; + .box-shadow(-6px 0 rgba(0, 0, 0, 0.1)); +} + +.bottom-shadow-border{ + border-bottom: 1px solid #999; + .box-shadow(0px 6px 0 0 rgba(0, 0, 0, 0.1)); +} + +/* + + FIXED HEADER, DASHBOARD & BREADCRUMBS: + + one_pane.html + two_pane.html + with_sidebar.html + with_tabs.html + with_tabs_sidebar.html +*/ +#dashboard { + .left-shadow-border; + position: absolute; + left: @navWidth; + margin-left: 0; + padding-left: 0; + padding-right: 0; + background-color: @sidebarBG; + min-width: 600px; + height: 100%; + .closeMenu &{ + left: @collapsedNavWidth; + } + &.one-pane{ + min-width: 800px; + margin-top: 0; + overflow-x: hidden; + } + &.two-pane{ + margin-top: 0; + overflow-x: hidden; + } +} + + + +/* SIDEBAR-CONTENT & DASHBOARD-CONTENT LAYOUTS: + with_sidebar.html + with_tabs_sidebar.html +*/ + +#sidebar-content { + position: absolute; + top: 60px; + width: @sidebarWidth; + left: 0; + background-color: @secondarySidebar; + > div.inner { + display: block; + } +} + +.topmenu-defaults { + height: 70px; + padding: 12px 10px 0; + .box-sizing(border-box); +} + +/* USED IN TEMPLATE: with_tabs_sidebar.html */ +.dashboard-upper-menu{ + right: 0; + left: @sidebarWidth+@navWidth; + position: fixed; + z-index: 11; + display: block; + .topmenu-defaults; + background-color: #CBCBCB; + .closeMenu & { + left: @sidebarWidth+@collapsedNavWidth; + } +} + +#dashboard-lower-content{ + background-color: #F1F1F1; + .view { + padding: 20px; + } +} + +#dashboard-upper-content{ + .tab-content { + padding-top: 70px; + } + .well{ + padding: 20px; + .border-radius(0); + .box-shadow(none); + } +} + +#dashboard-content{ + &.row-fluid, + &.window-resizeable{ + /*remove gutter without rewriting variable*/ + margin-left: 0px; + } + padding: 20px; + .with-sidebar &{ + .left-shadow-border; + border-right: 1px solid #999; + width: auto; + padding: 0px; + bottom: 0px; + top: 60px; + position: fixed; + overflow-x: hidden; + overflow-y: auto; + left: @sidebarWidth+@navWidth; + right: 0; + .box-sizing(border-box); + .closeMenu & { + left: @sidebarWidth+@collapsedNavWidth; + } + } + > div.inner { + display: block; + } +} + +/* + Sidenav: + USED IN DOCUMENT ADDON & EXTERNAL ADDONS +*/ +.sidenav { + padding: 0; + header { + width: @sidebarWidth; + border-bottom: 1px solid #d3d7db; + } + .nav-list{ + .divider { + border: none; + } + > li > a:hover, + > li > a:focus{ + background-color: @darkRed; + color: #fff; + } + li.active > a { + color: @darkRed; + } + > li > a{ + color: @linkRed; + padding: 10px 13px 10px 24px; + border-bottom: 1px solid #d3d7db; + span{ + margin-right: 8px; + width: 14px; + display: inline-block; + text-align: center; + } + } + a{ + display: block; + padding: 10px 5px 5px 15px; + color: @subListGray; + .divider { + background: none; + color: #ccc; + padding: 0 2px; + } + } + .nav-header{ + padding: 0px; + text-shadow: none; + color: #333333; + & > span:hover { + color: @red; + } + } + } +} + +.row-fluid.content-area{ + background-color: @background; +} + + +/* + #left-content & #right-content from template: + two_pane.html +*/ +#left-content, +#right-content{ + .two-pane &{ + padding: 0px; + bottom: 0px; + top: 60px; + margin-left:0; + position: fixed; + overflow-x: hidden; + overflow-y: auto; + .box-sizing(border-box); + } +} + +#left-content{ + .two-pane &{ + left: @navWidth; + .closeMenu & { + left: @collapsedNavWidth; + } + } +} +#right-content{ + .two-pane &{ + .view { + padding: 0 20px; + } + border-left: 1px solid #999; + .box-shadow(-6px 0 rgba(0, 0, 0, 0.1)); + } +} + + +.with-sidebar.content-area, +.two-pane.content-area { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + + http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/113615ff/settings.json.default ---------------------------------------------------------------------- diff --git a/settings.json.default b/settings.json.default index bc5a617..d278368 100644 --- a/settings.json.default +++ b/settings.json.default @@ -3,6 +3,7 @@ { "name": "fauxton" }, { "name": "databases" }, { "name": "documents" }, + { "name": "indexes" }, { "name": "pouchdb" }, { "name": "activetasks" }, { "name": "config" },
