diff options
author | suelockwood <deathbear@apache.org> | 2014-03-06 11:37:17 -0500 |
---|---|---|
committer | suelockwood <deathbear@apache.org> | 2014-03-06 16:31:56 -0500 |
commit | 6e93561273b249275bb391b2f43a96e5733db21b (patch) | |
tree | 10006ab9b4c157297fcda56c57b27c43589befe9 | |
parent | b63ff1b50b7bde0c8f1f95988d076dda63f41fed (diff) | |
download | couchdb-2128-autocomplete-section-name.tar.gz |
Added Autocomplete for config sections2128-autocomplete-section-name
Form Validation
Check for existing config
Pulled Views out of resources and into their own file
updated makefile with the new views.js
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/fauxton/app/addons/config/assets/less/config.less | 2 | ||||
-rw-r--r-- | src/fauxton/app/addons/config/resources.js | 107 | ||||
-rw-r--r-- | src/fauxton/app/addons/config/routes.js | 10 | ||||
-rw-r--r-- | src/fauxton/app/addons/config/templates/dashboard.html | 29 | ||||
-rw-r--r-- | src/fauxton/app/addons/config/templates/modal.html | 33 | ||||
-rw-r--r-- | src/fauxton/app/addons/config/views.js | 201 | ||||
-rw-r--r-- | src/fauxton/app/addons/fauxton/components.js | 53 |
8 files changed, 278 insertions, 158 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 59aa6bfb9..df64e9c72 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -69,6 +69,7 @@ FAUXTON_FILES = \ fauxton/app/addons/config/base.js \ fauxton/app/addons/config/resources.js \ fauxton/app/addons/config/routes.js \ + fauxton/app/addons/config/views.js \ fauxton/app/addons/config/templates/dashboard.html \ fauxton/app/addons/config/templates/item.html \ fauxton/app/addons/contribute/base.js \ diff --git a/src/fauxton/app/addons/config/assets/less/config.less b/src/fauxton/app/addons/config/assets/less/config.less index 88bbc6641..c16b45a95 100644 --- a/src/fauxton/app/addons/config/assets/less/config.less +++ b/src/fauxton/app/addons/config/assets/less/config.less @@ -26,7 +26,7 @@ } } -#add-section-modal { +#add-section-modal .modal { width: 400px; } diff --git a/src/fauxton/app/addons/config/resources.js b/src/fauxton/app/addons/config/resources.js index 227e80dbe..4ee46c587 100644 --- a/src/fauxton/app/addons/config/resources.js +++ b/src/fauxton/app/addons/config/resources.js @@ -12,12 +12,15 @@ define([ "app", - "api" + "api", + ], function (app, FauxtonAPI) { var Config = FauxtonAPI.addon(); + var Events = {}; + Config.Events = _.extend(Events, Backbone.Events); Config.Model = Backbone.Model.extend({}); Config.OptionModel = Backbone.Model.extend({ @@ -75,107 +78,7 @@ function (app, FauxtonAPI) { } }); - Config.ViewItem = FauxtonAPI.View.extend({ - tagName: "tr", - className: "config-item", - template: "addons/config/templates/item", - - events: { - "click .edit-button": "editValue", - "click #delete-value": "deleteValue", - "click #cancel-value": "cancelEdit", - "click #save-value": "saveValue" - }, - - deleteValue: function (event) { - var result = confirm("Are you sure you want to delete this configuration value?"); - - if (!result) { return; } - - this.model.destroy(); - this.remove(); - }, - - editValue: function (event) { - this.$("#show-value").hide(); - this.$("#edit-value-form").show(); - }, - - saveValue: function (event) { - this.model.save({value: this.$(".value-input").val()}); - this.render(); - }, - - cancelEdit: function (event) { - this.$("#edit-value-form").hide(); - this.$("#show-value").show(); - }, - - serialize: function () { - return {option: this.model.toJSON()}; - } - - }); - - Config.View = FauxtonAPI.View.extend({ - template: "addons/config/templates/dashboard", - - events: { - "click #add-section": "addSection", - "submit #add-section-form": "submitForm" - }, - - submitForm: function (event) { - event.preventDefault(); - var option = new Config.OptionModel({ - section: this.$('input[name="section"]').val(), - name: this.$('input[name="name"]').val(), - value: this.$('input[name="value"]').val() - }); - - option.save(); - - var section = this.collection.find(function (section) { - return section.get("section") === option.get("section"); - }); - - if (section) { - section.get("options").push(option.attributes); - } else { - this.collection.add({ - section: option.get("section"), - options: [option.attributes] - }); - } - - this.$("#add-section-modal").modal('hide'); - this.render(); - }, - - addSection: function (event) { - event.preventDefault(); - this.$("#add-section-modal").modal({show:true}); - }, - - beforeRender: function() { - this.collection.each(function(config) { - _.each(config.get("options"), function (option, index) { - this.insertView("table.config tbody", new Config.ViewItem({ - model: new Config.OptionModel({ - section: config.get("section"), - name: option.name, - value: option.value, - index: index - }) - })); - }, this); - }, this); - }, - - establish: function() { - return [this.collection.fetch()]; - } - }); + return Config; }); diff --git a/src/fauxton/app/addons/config/routes.js b/src/fauxton/app/addons/config/routes.js index 6af81572f..cb3f28728 100644 --- a/src/fauxton/app/addons/config/routes.js +++ b/src/fauxton/app/addons/config/routes.js @@ -12,14 +12,12 @@ define([ "app", - "api", - - // Modules - "addons/config/resources" + "addons/config/resources", + "addons/config/views" ], -function(app, FauxtonAPI, Config) { +function(app, FauxtonAPI, Config, View) { var ConfigRouteObject = FauxtonAPI.RouteObject.extend({ layout: "one_pane", @@ -45,7 +43,7 @@ function(app, FauxtonAPI, Config) { }, config: function () { - this.setView("#dashboard-content", new Config.View({collection: this.configs})); + this.setView("#dashboard-content", new View.Table({collection: this.configs})); }, establish: function () { diff --git a/src/fauxton/app/addons/config/templates/dashboard.html b/src/fauxton/app/addons/config/templates/dashboard.html index b7dbc55f4..e56999576 100644 --- a/src/fauxton/app/addons/config/templates/dashboard.html +++ b/src/fauxton/app/addons/config/templates/dashboard.html @@ -13,10 +13,10 @@ the License. --> <div class="row"> - <button id="add-section" href="#" class="btn btn-primary pull-right"> - <i class="icon icon-plus icon-white"> </i> - Add Section - </button> + <button id="add-section" href="#" class="btn btn-primary pull-right"> + <i class="icon icon-plus icon-white"> </i> + Add Section + </button> </div> <table class="config table table-striped table-bordered"> <thead> @@ -28,23 +28,4 @@ the License. <tbody> </tbody> </table> -<div id="add-section-modal" class="modal hide fade"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> - <h3>Create Config Option</h3> - </div> - <div class="modal-body"> - <form id="add-section-form" class="form well"> - <label>Section</label> - <input type="text" name="section" placeholder="Section"> - <span class="help-block">Enter an existing section name to add to it.</span> - <input type="text" name="name" placeholder="Name"> - <br/> - <input type="text" name="value" placeholder="Value"> - <div class="modal-footer"> - <button type="button" class="btn" data-dismiss="modal">Cancel</button> - <button type="submit" class="btn btn-primary"> Save </button> - </div> - </form> - </div> -</div> +<div id="add-section-modal"></div> diff --git a/src/fauxton/app/addons/config/templates/modal.html b/src/fauxton/app/addons/config/templates/modal.html new file mode 100644 index 000000000..2ba53ca3c --- /dev/null +++ b/src/fauxton/app/addons/config/templates/modal.html @@ -0,0 +1,33 @@ + <!-- +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="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h3>Create Config Option</h3> +</div> +<div class="modal-body"> + <div class="form-error-config"></div> + <form id="add-section-form" class="form well"> + <label>Section</label> + <input type="text" name="section" placeholder="Section" > + <span class="help-block">Enter an existing section name to add to it.</span> + <input type="text" name="name" placeholder="Name"> + <br/> + <input type="text" name="value" placeholder="Value"> + <div class="modal-footer"> + <button type="button" class="btn" data-dismiss="modal">Cancel</button> + <button type="submit" class="btn btn-primary"> Save </button> + </div> + </form> +</div> diff --git a/src/fauxton/app/addons/config/views.js b/src/fauxton/app/addons/config/views.js new file mode 100644 index 000000000..bb6b228d0 --- /dev/null +++ b/src/fauxton/app/addons/config/views.js @@ -0,0 +1,201 @@ +// 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/config/resources", + "addons/fauxton/components" + +], +function(app, FauxtonAPI, Config, Components) { + var Views ={}; + + + Views.ViewItem = FauxtonAPI.View.extend({ + tagName: "tr", + className: "config-item", + template: "addons/config/templates/item", + + events: { + "click .edit-button": "editValue", + "click #delete-value": "deleteValue", + "click #cancel-value": "cancelEdit", + "click #save-value": "saveValue" + }, + + deleteValue: function (event) { + var result = confirm("Are you sure you want to delete this configuration value?"); + + if (!result) { return; } + + this.model.destroy(); + this.remove(); + }, + + editValue: function (event) { + this.$("#show-value").hide(); + this.$("#edit-value-form").show(); + }, + + saveValue: function (event) { + this.model.save({value: this.$(".value-input").val()}); + this.render(); + }, + + cancelEdit: function (event) { + this.$("#edit-value-form").hide(); + this.$("#show-value").show(); + }, + + serialize: function () { + return {option: this.model.toJSON()}; + } + + }); + + Views.Table = FauxtonAPI.View.extend({ + template: "addons/config/templates/dashboard", + + events: { + "click #add-section": "addSection" + }, + + initialize: function(){ + Config.Events.on("newSection", this.render); + }, + + addSection: function (event) { + event.preventDefault(); + this.modal.show(); + }, + + beforeRender: function() { + this.modal = this.insertView("#add-section-modal", new Views.Modal({ + collection: this.collection + })); + this.modal.render(); + + this.collection.each(function(config) { + _.each(config.get("options"), function (option, index) { + this.insertView("table.config tbody", new Views.ViewItem({ + model: new Config.OptionModel({ + section: config.get("section"), + name: option.name, + value: option.value, + index: index + }) + })); + }, this); + }, this); + }, + + establish: function() { + return [this.collection.fetch()]; + } + }); + + Views.Modal = FauxtonAPI.View.extend({ + className: "modal hide fade", + template: "addons/config/templates/modal", + events: { + "submit #add-section-form": "validate" + }, + initialize: function(){ + this.sourceArray = _.map(this.collection.toJSON(), function(item, key){ + return item.section; + }); + }, + afterRender: function(){ + this.sectionTypeAhead = new Components.Typeahead({ + source: this.sourceArray, + el: 'input[name="section"]' + }); + this.sectionTypeAhead.render(); + }, + submitForm: function (event) { + var option = new Config.OptionModel({ + section: this.$('input[name="section"]').val(), + name: this.$('input[name="name"]').val(), + value: this.$('input[name="value"]').val() + }); + + option.save(); + + var section = this.collection.find(function (section) { + return section.get("section") === option.get("section"); + }); + + if (section) { + section.get("options").push(option.attributes); + } else { + this.collection.add({ + section: option.get("section"), + options: [option.attributes] + }); + } + + this.hide(); + Config.Events.trigger("newSection"); + + }, + isNew: function(collection){ + var sectionName = this.$('input[name="section"]').val(), + name = this.$('input[name="name"]').val(); + var section = _.findWhere(collection.toJSON(), {"section":sectionName}); + var options = _.findWhere(section.options, {name: name}); + + return options; + }, + isSection: function(){ + var section = this.$('input[name="section"]').val(); + return _.find(this.sourceArray, function(item){ return item === section; }); + }, + validate: function (event){ + event.preventDefault(); + var section = this.$('input[name="section"]').val(), + name = this.$('input[name="name"]').val(), + value = this.$('input[name="value"]').val(), + collection = this.collection; + + if(!this.isSection()){ + this.errorMessage("You need to use an existing section."); + } else if (!name) { + this.errorMessage("Add a name."); + } else if (!value) { + this.errorMessage("Add a value"); + } else if (this.isNew(collection)){ + this.errorMessage("Must have a unique name"); + } else { + this.submitForm(); + } + }, + errorMessage: function(msg){ + this.error = FauxtonAPI.addNotification({ + msg: msg, + type: "error", + clear: true, + selector: ".form-error-config" + }); + }, + show: function(){ + $(this.el).modal({show:true}); + }, + hide: function(){ + $(this.el).modal('hide'); + } + + }); + + return Views; + +}); diff --git a/src/fauxton/app/addons/fauxton/components.js b/src/fauxton/app/addons/fauxton/components.js index 7dcf2d7d0..5177db49e 100644 --- a/src/fauxton/app/addons/fauxton/components.js +++ b/src/fauxton/app/addons/fauxton/components.js @@ -210,32 +210,7 @@ function(app, FauxtonAPI, ace, spin) { }); - //TODO allow more of the typeahead options. - //Current this just does what we need but we - //need to support the other typeahead options. - Components.Typeahead = FauxtonAPI.View.extend({ - - initialize: function (options) { - this.source = options.source; - _.bindAll(this); - }, - afterRender: function () { - var onUpdate = this.onUpdate; - - this.$el.typeahead({ - source: this.source, - updater: function (item) { - if (onUpdate) { - onUpdate(item); - } - - return item; - } - }); - } - - }); Components.ModalView = FauxtonAPI.View.extend({ @@ -279,6 +254,34 @@ function(app, FauxtonAPI, ace, spin) { } }); + //TODO allow more of the typeahead options. + //Current this just does what we need but we + //need to support the other typeahead options. + Components.Typeahead = FauxtonAPI.View.extend({ + + initialize: function (options) { + this.source = options.source; + this.onUpdate = options.onUpdate; + _.bindAll(this); + }, + + afterRender: function () { + var onUpdate = this.onUpdate; + + this.$el.typeahead({ + source: this.source, + updater: function (item) { + if (onUpdate) { + onUpdate(item); + } + + return item; + } + }); + } + + }); + Components.DbSearchTypeahead = Components.Typeahead.extend({ initialize: function (options) { this.dbLimit = options.dbLimit || 30; |