improve workflow for adding application
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/b0412050 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/b0412050 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/b0412050 Branch: refs/heads/0.5.0 Commit: b04120503127954b83caf77dc99dfcaaf927ca1b Parents: 73881a0 Author: Alex Heneveld <[email protected]> Authored: Mon Nov 19 14:54:05 2012 +0000 Committer: Alex Heneveld <[email protected]> Committed: Tue Nov 27 15:46:47 2012 -0800 ---------------------------------------------------------------------- .../src/main/webapp/assets/css/prettybrook.css | 12 +- .../assets/js/view/application-add-wizard.js | 405 ++++++++++++++++++ .../assets/js/view/application-explorer.js | 6 +- .../src/main/webapp/assets/js/view/home.js | 6 +- .../main/webapp/assets/js/view/modal-wizard.js | 410 ------------------- .../tpl/app-add-wizard/create-config-entry.html | 8 + .../tpl/app-add-wizard/create-entity-entry.html | 44 ++ .../assets/tpl/app-add-wizard/create.html | 62 +++ .../app-add-wizard/deploy-location-option.html | 3 + .../tpl/app-add-wizard/deploy-location-row.html | 6 + .../assets/tpl/app-add-wizard/deploy.html | 28 ++ .../assets/tpl/app-add-wizard/modal-wizard.html | 13 + .../assets/tpl/app-add-wizard/preview.html | 10 + .../webapp/assets/tpl/home/modal-wizard.html | 13 - .../assets/tpl/home/step1-location-option.html | 3 - .../assets/tpl/home/step1-location-row.html | 6 - .../src/main/webapp/assets/tpl/home/step1.html | 28 -- .../assets/tpl/home/step2-config-entry.html | 6 - .../assets/tpl/home/step2-entity-entry.html | 44 -- .../src/main/webapp/assets/tpl/home/step2.html | 64 --- .../src/main/webapp/assets/tpl/home/step3.html | 10 - .../specs/view/application-add-wizard-spec.js | 194 +++++++++ .../javascript/specs/view/modal-wizard-spec.js | 194 --------- 23 files changed, 785 insertions(+), 790 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/css/prettybrook.css ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/css/prettybrook.css b/usage/jsgui/src/main/webapp/assets/css/prettybrook.css index 73a1433..6a4a7b2 100644 --- a/usage/jsgui/src/main/webapp/assets/css/prettybrook.css +++ b/usage/jsgui/src/main/webapp/assets/css/prettybrook.css @@ -491,26 +491,26 @@ div.for-empty-table { -moz-border-radius: 4px; border-radius: 4px; } -.step2-entity-config input { +.app-add-wizard-create-entity-config input { margin-bottom: 0px; } -.step2-entity-label-newline { +.app-add-wizard-create-entity-label-newline { padding-left: 2px; padding-bottom: 3px; } -.step2-entity-label { +.app-add-wizard-create-entity-label { width: 4em; float: left; padding-top: 3px; } -.step2-entity-input { +.app-add-wizard-create-entity-input { width: 300px; } -.step2-entity-config { +.app-add-wizard-create-entity-config { margin-bottom: 9px; margin-top: 2px; } -.step2-entity-config button { +.app-add-wizard-create-entity-config button { margin-left: 8px; } #add-app-entity { http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/js/view/application-add-wizard.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/view/application-add-wizard.js b/usage/jsgui/src/main/webapp/assets/js/view/application-add-wizard.js new file mode 100644 index 0000000..2370878 --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/js/view/application-add-wizard.js @@ -0,0 +1,405 @@ +/** + * Builds a Twitter Bootstrap modal as the framework for a Wizard. + * Also creates an empty Application model. + */ +define([ + "underscore", "jquery", "backbone", "model/entity", "model/application", "formatJson", + "model/location", "text!tpl/app-add-wizard/modal-wizard.html", + + "text!tpl/app-add-wizard/create.html", + "text!tpl/app-add-wizard/create-entity-entry.html", "text!tpl/app-add-wizard/create-config-entry.html", + + "text!tpl/app-add-wizard/deploy.html", + "text!tpl/app-add-wizard/deploy-location-row.html", "text!tpl/app-add-wizard/deploy-location-option.html", + + "text!tpl/app-add-wizard/preview.html", + + "bootstrap" + +], function (_, $, Backbone, Entity, Application, FormatJSON, Location, ModalHtml, + CreateHtml, + CreateEntityEntryHtml, CreateConfigEntryHtml, + DeployHtml, + DeployLocationRowHtml, DeployLocationOptionHtml, + PreviewHtml + ) { + + var ModalWizard = Backbone.View.extend({ + tagName:'div', + className:'modal hide fade', + events:{ + 'click #next_step':'nextStep', + 'click #prev_step':'prevStep' + }, + template:_.template(ModalHtml), + initialize:function () { + this.model = new Application.Spec + this.currentStep = 0; + this.steps = [ + { + step_id:'what-app', + title:'Create Application', + instructions:'Define how the application is built and the configuration parameters', + view:new ModalWizard.StepCreate({ model:this.model}) + }, + { + step_id:'name-and-locations', + title:'Deploy Application', + instructions:'Enter the name of the new application and the location(s) where you wish to deploy it.', + view:new ModalWizard.StepDeploy({ model:this.model }) + }, + { + step_id:'preview', + title:'Application Preview', + instructions:'Confirm the code which will be sent to the server, optionally tweaking it or saving it for future reference.', + view:new ModalWizard.StepPreview({ model:this.model}) + } + ] + }, + beforeClose:function () { + // ensure we close the sub-views + _.each(this.steps, function (step) { + step.view.close() + }, this) + }, + render:function () { + this.$el.html(this.template({})) + this.renderCurrentStep() + return this + }, + + renderCurrentStep:function () { + this.title = this.$("h3#step_title") + this.instructions = this.$("p#step_instructions") + this.nextStepButton = this.$("#next_step") + this.prevStepButton = this.$("#prev_step") + + var currentStep = this.steps[this.currentStep] + this.title.html(currentStep.title) + this.instructions.html(currentStep.instructions) + this.currentView = currentStep.view + + // delegate to sub-views !! + this.$(".modal-body").replaceWith(this.currentView.render().el) + + if (this.currentStep > 0) { + this.prevStepButton.html("Previous").show() + } else { + this.prevStepButton.hide() + } + + if (this.currentStep < 2) { + this.nextStepButton.html("Next") + } else { + this.nextStepButton.html("Finish") + } + }, + submitApplication:function (event) { + var that = this + $.ajax({ + url:'/v1/applications', + type:'post', + contentType:'application/json', + processData:false, + data:JSON.stringify(this.model.toJSON()), + success:function (data) { + var $modal = $('#modal-container .modal') + $modal.modal('hide') + if (that.options.callback) that.options.callback(); + }, + error:function (data) { + that.steps[that.currentStep].view.showFailure() + } + }) + return false + }, + // TODO prev and next not so simple anymore, are they? + nextStep:function () { + if (this.currentView.validate()) { + if (this.currentStep < 2) { + this.currentStep += 1 + this.renderCurrentStep() + } else { + this.submitApplication() + } + } + }, + prevStep:function () { + this.currentStep -= 1 + this.renderCurrentStep() + } + }) + + // Note: this does not restore values on a back click; setting type and entity type+name is easy, + // but relevant config lines is a little bit more tedious + ModalWizard.StepCreate = Backbone.View.extend({ + className:'modal-body', + events:{ + 'click #add-app-entity':'addEntity', + 'click .editable-entity-heading':'expandEntity', + 'click .remove-entity-button':'removeEntityClick', + 'click .editable-entity-button':'saveEntityClick', + 'click #remove-config':'removeConfigRow', + 'click #add-config':'addConfigRow' + }, + template:_.template(CreateHtml), + initialize:function () { + var self = this + self.catalogEntities = [] + self.catalogApplications = [] + + this.$el.html(this.template({})) + this.addEntity() + + $.get('/v1/catalog/entities', {}, function (result) { + self.catalogEntities = result + self.$(".entity-type-input").typeahead().data('typeahead').source = self.catalogEntities + }) + $.get('/v1/catalog/applications', {}, function (result) { + self.catalogApplications = result + self.$(".application-type-input").typeahead().data('typeahead').source = self.catalogApplications + }) + }, + beforeClose:function () { + }, + renderConfiguredEntities:function () { + var $configuredEntities = this.$('#entitiesAccordionish').empty() + var that = this + if (this.model.get("entities").length > 0) { + _.each(this.model.get("entities"), function (entity) { + that.addEntityHtml($configuredEntities, entity) + }) + } + }, + + render:function () { + this.renderConfiguredEntities() + this.delegateEvents() + return this + }, + + expandEntity:function (event) { + $(event.currentTarget).next().show('fast').delay(1000).prev().hide('slow') + }, + saveEntityClick:function (event) { + this.saveEntity($(event.currentTarget).parent().parent().parent()); + }, + saveEntity:function ($entityGroup) { + var that = this + var name = $('#entity-name',$entityGroup).val() + var type = $('#entity-type',$entityGroup).val() + if (type=="" || !_.contains(that.catalogEntities, type)) { + $('.entity-info-message',$entityGroup).show('slow').delay(2000).hide('slow') + return false + } + var saveTarget = this.model.get("entities")[$entityGroup.index()]; + this.model.set("type", null) + saveTarget.name = name + saveTarget.type = type + saveTarget.config = this.getConfigMap($entityGroup) + + if (name=="") name=type; + if (name=="") name="<i>(new entity)</i>"; + $('#entity-name-header',$entityGroup).html( name ) + $('.editable-entity-body',$entityGroup).prev().show('fast').next().hide('fast') + return true; + }, + getConfigMap:function (root) { + var map = {} + $('.app-add-wizard-create-entity-config',root).each( function (index,elt) { + map[$('#key',elt).val()] = $('#value',elt).val() + }) + return map; + }, + saveTemplate:function () { + var that = this + var tab = $.find('#templateTab') + var type = $(tab).find('#entity-type').val() + if (!_.contains(this.catalogApplications, type)) { + $('.entity-info-message').show('slow').delay(2000).hide('slow') + return false + } + this.model.set("type", type); + this.model.set("config", this.getConfigMap(tab)) + return true; + }, + addEntity:function () { + var entity = new Entity.Model + this.model.addEntity( entity ) + this.addEntityHtml(this.$('#entitiesAccordionish'), entity) + }, + addEntityHtml:function (parent, entity) { + var $entity = _.template(CreateEntityEntryHtml, {}) + var that = this + parent.append($entity) + parent.children().last().find('.entity-type-input').typeahead({ source: that.catalogEntities }) + }, + removeEntityClick:function (event) { + var $entityGroup = $(event.currentTarget).parent().parent().parent(); + this.model.removeEntityIndex($entityGroup.index()) + $entityGroup.remove() + }, + + addConfigRow:function (event) { + var $row = _.template(CreateConfigEntryHtml, {}) + $(event.currentTarget).parent().prev().append($row) + }, + removeConfigRow:function (event) { + $(event.currentTarget).parent().remove() + }, + + validate:function () { + var that = this + var tabName = $('#app-add-wizard-create-tab li[class="active"] a').attr('href') + if (tabName=='#entitiesTab') { + var allokay = true + $($.find('.editable-entity-group')).each( + function (i,$entityGroup) { + allokay = that.saveEntity($entityGroup) & allokay + }) + if (!allokay) return false; + if (this.model.get("entities").length > 0) { + this.model.set("type", null); + return true; + } + } else if (tabName=='#templateTab') { + if (this.saveTemplate()) { + this.model.set("entities", []); + return true + } + } else { + // other tabs not implemented yet + // do nothing, show error return false below + } + this.$('div.app-add-wizard-create-info-message').show('slow').delay(2000).hide('slow') + return false + } + + }) + + ModalWizard.StepDeploy = Backbone.View.extend({ + className:'modal-body', + events:{ + 'click #add-selector-container':'addLocation', + 'click #remove-app-location':'removeLocation', + 'change select':'selection', + 'change option':'selection', + 'blur #application-name':'updateName' + }, + template:_.template(DeployHtml), + locationRowTemplate:_.template(DeployLocationRowHtml), + locationOptionTemplate:_.template(DeployLocationOptionHtml), + + initialize:function () { + this.model.on("change", this.render, this) + this.$el.html(this.template({})) + this.locations = new Location.Collection() + }, + beforeClose:function () { + this.model.off("change", this.render) + }, + renderName:function () { + this.$('#application-name').val(this.model.get("name")) + }, + renderAddedLocations:function () { + // renders the locations added to the model + var that = this; + var container = this.$("#selector-container") + container.empty() + for (var li = 0; li < this.model.get("locations").length; li++) { + var chosenLocation = this.model.get("locations")[li]; + container.append(that.locationRowTemplate({ + initialValue: chosenLocation, + rowId: li + })) + } + var $selectLocations = container.find('#select-location') + this.locations.each(function(aLocation) { + var $option = that.locationOptionTemplate({ + url:aLocation.getLinkByName("self"), + name:aLocation.getPrettyName() + }) + $selectLocations.append($option) + }) + $selectLocations.each(function(i) { + var url = $($selectLocations[i]).parent().attr('initialValue'); + $($selectLocations[i]).val(url) + }) + }, + render:function () { + var that = this + this.renderName() + this.locations.fetch({async:false, + success:function () { + if (that.model.get("locations").length==0) + that.addLocation() + else + that.renderAddedLocations() + }}) + this.delegateEvents() + return this + }, + addLocation:function () { + if (this.locations.models.length>0) { + this.model.addLocation(this.locations.models[0].getLinkByName("self")) + this.renderAddedLocations() + } else { + this.$('div.info-nolocs-message').show('slow').delay(2000).hide('slow') + } + }, + removeLocation:function (event) { + var toBeRemoved = $(event.currentTarget).parent().attr('rowId') + this.model.removeLocationIndex(toBeRemoved) + this.renderAddedLocations() + }, + selection:function (event) { + var url = $(event.currentTarget).val(); + var loc = this.locations.find(function (candidate) { + return candidate.getLinkByName("self")==url + }) + this.model.setLocationAtIndex($(event.currentTarget).parent().attr('rowId'), + loc.getLinkByName("self")) + }, + updateName:function () { + this.model.set("name", this.$('#application-name').val()) + }, + validate:function () { + if (this.model.get("name") !== "" && this.model.get("locations").length !== 0) { + return true + } + this.$('div.info-message').show('slow').delay(2000).hide('slow') + return false + } + }) + + ModalWizard.StepPreview = Backbone.View.extend({ + className:'modal-body', + initialize:function () { + this.$el.html(_.template(PreviewHtml)) + this.model.on("change", this.render, this) + }, + beforeClose:function () { + this.model.off("change", this.render) + }, + render:function () { + this.$('#app-summary').val(FormatJSON(this.model.toJSON())) + this.delegateEvents() + return this + }, + validate:function () { + if (this.model.get("name") != "" + && this.model.get("locations").length > 0 + && (this.model.get("type")!=null || + this.model.get("entities").length > 0)) { + return true + } + this.showFailure() + return false + }, + showFailure:function () { + this.$('div.info-message').show('slow').delay(2000).hide('slow') + } + }) + + return ModalWizard +}) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js b/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js index 4c7ff02..3ebf74f 100644 --- a/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js +++ b/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js @@ -5,9 +5,9 @@ */ define([ "underscore", "jquery", "backbone", - "./modal-wizard", "model/app-tree", "./application-tree", + "./application-add-wizard", "model/app-tree", "./application-tree", "text!tpl/apps/page.html" -], function (_, $, Backbone, ModalWizard, AppTree, ApplicationTreeView, PageHtml) { +], function (_, $, Backbone, AppAddWizard, AppTree, ApplicationTreeView, PageHtml) { var ApplicationExplorerView = Backbone.View.extend({ tagName:"div", @@ -52,7 +52,7 @@ define([ if (this._modal) { this._modal.close() } - var wizard = new ModalWizard({ + var wizard = new AppAddWizard({ appRouter:that.options.appRouter, callback:function() { that.refreshApplications() } }) http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/js/view/home.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/view/home.js b/usage/jsgui/src/main/webapp/assets/js/view/home.js index fc39bd8..67b246a 100644 --- a/usage/jsgui/src/main/webapp/assets/js/view/home.js +++ b/usage/jsgui/src/main/webapp/assets/js/view/home.js @@ -3,10 +3,10 @@ */ define([ - "underscore", "jquery", "backbone", "./modal-wizard", "model/location", + "underscore", "jquery", "backbone", "./application-add-wizard", "model/location", "text!tpl/home/applications.html", "text!tpl/home/summaries.html", "text!tpl/home/app-entry.html", "bootstrap" -], function (_, $, Backbone, ModalWizard, Location, ApplicationsHtml, HomeSummariesHtml, AppEntryHtml) { +], function (_, $, Backbone, AppAddWizard, Location, ApplicationsHtml, HomeSummariesHtml, AppEntryHtml) { var HomeView = Backbone.View.extend({ tagName:"div", @@ -115,7 +115,7 @@ define([ this._modal.close() } var that = this; - var wizard = new ModalWizard({appRouter:this.options.appRouter}) + var wizard = new AppAddWizard({appRouter:this.options.appRouter}) this._modal = wizard this.$("#modal-container").html(wizard.render().el) this.$("#modal-container .modal") http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/js/view/modal-wizard.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/view/modal-wizard.js b/usage/jsgui/src/main/webapp/assets/js/view/modal-wizard.js deleted file mode 100644 index bc007cb..0000000 --- a/usage/jsgui/src/main/webapp/assets/js/view/modal-wizard.js +++ /dev/null @@ -1,410 +0,0 @@ -/** - * Builds a Twitter Bootstrap modal as the framework for a Wizard. - * Also creates an empty Application model. - */ -define([ - "underscore", "jquery", "backbone", "model/entity", "model/application", "formatJson", - "model/location", "text!tpl/home/modal-wizard.html", - "text!tpl/home/step1.html", "text!tpl/home/step2.html", "text!tpl/home/step3.html", - "text!tpl/home/step1-location-row.html", "text!tpl/home/step1-location-option.html", - "text!tpl/home/step2-entity-entry.html", "text!tpl/home/step2-config-entry.html", "bootstrap" -], function (_, $, Backbone, Entity, Application, FormatJSON, Location, ModalHtml, - Step1Html, Step2Html, Step3Html, - Step1LocationRowHtml, LocationOptionHtml, - Step2EntityEntryHtml, Step2ConfigEntryHtml) { - - var ModalWizard = Backbone.View.extend({ - tagName:'div', - className:'modal hide fade', - events:{ - 'click #next_step':'nextStep', - 'click #prev_step':'prevStep' - }, - template:_.template(ModalHtml), - initialize:function () { - this.model = new Application.Spec - this.currentStep = 0 - this.steps = [ - { - step_number:1, - title:'Deploy Application', - instructions:'Enter the name of the new application and the location(s) where you wish to deploy it.', - view:new ModalWizard.Step1({ model:this.model }) - }, - { - step_number:2, - title:'Configure Application', - instructions:'Define how the application is built and the configuration parameters', - view:new ModalWizard.Step2({ model:this.model}) - }, - { - step_number:3, - title:'Application Summary', - instructions:'Confirm and save the JSON details which will be used to create the application', - view:new ModalWizard.Step3({ model:this.model}) - } - ] - }, - beforeClose:function () { - // ensure we close the sub-views - _.each(this.steps, function (step) { - step.view.close() - }, this) - }, - render:function () { - this.$el.html(this.template({})) - this.renderCurrentStep() - return this - }, - - renderCurrentStep:function () { - this.title = this.$("h3#step_title") - this.instructions = this.$("p#step_instructions") - this.nextStepButton = this.$("#next_step") - this.prevStepButton = this.$("#prev_step") - - var currentStep = this.steps[this.currentStep] - if (!this.isFirstStep()) var prevStep = this.steps[this.currentStep - 1] - var nextStep = this.steps[this.currentStep + 1] - - this.title.html(currentStep.title) - this.instructions.html(currentStep.instructions) - this.currentView = currentStep.view - // delegate to sub-views !! - this.$(".modal-body").replaceWith(this.currentView.render().el) - - if (prevStep) { - this.prevStepButton.html("Previous").show() - } else { - this.prevStepButton.hide() - } - if (nextStep) { - this.nextStepButton.html("Next") - } else { - this.nextStepButton.html("Finish") - } - }, - submitApplication:function (event) { - var that = this - $.ajax({ - url:'/v1/applications', - type:'post', - contentType:'application/json', - processData:false, - data:JSON.stringify(this.model.toJSON()), - success:function (data) { - var $modal = $('#modal-container .modal') - $modal.modal('hide') - if (that.options.callback) that.options.callback(); - }, - error:function (data) { - that.steps[that.currentStep].view.showFailure() - } - }) - return false - }, - nextStep:function () { - if (this.currentView.validate()) { - if (!this.isLastStep()) { - this.currentStep += 1 - this.renderCurrentStep() - } else { - this.submitApplication() - } - } - }, - prevStep:function () { - if (!this.isFirstStep()) { - this.currentStep -= 1 - this.renderCurrentStep() - } - }, - isFirstStep:function () { - return (this.currentStep == 0) - }, - isLastStep:function () { - return (this.currentStep == this.steps.length - 1) - } - }) - - /** - * Wizard for creating a new application. First step: assign a name and a location for the app. - */ - ModalWizard.Step1 = Backbone.View.extend({ - className:'modal-body', - events:{ - 'click #add-selector-container':'addLocation', - 'click #remove-app-location':'removeLocation', - 'change select':'selection', - 'change option':'selection', - 'blur #application-name':'updateName' - }, - template:_.template(Step1Html), - locationRowTemplate:_.template(Step1LocationRowHtml), - locationOptionTemplate:_.template(LocationOptionHtml), - - initialize:function () { - this.model.on("change", this.render, this) - this.$el.html(this.template({})) - this.locations = new Location.Collection() - }, - beforeClose:function () { - this.model.off("change", this.render) - }, - renderName:function () { - this.$('#application-name').val(this.model.get("name")) - }, - renderAddedLocations:function () { - // renders the locations added to the model - var that = this; - var container = this.$("#selector-container") - container.empty() - for (var li = 0; li < this.model.get("locations").length; li++) { - var chosenLocation = this.model.get("locations")[li]; - container.append(that.locationRowTemplate({ - initialValue: chosenLocation, - rowId: li - })) - } - var $selectLocations = container.find('#select-location') - this.locations.each(function(aLocation) { - var $option = that.locationOptionTemplate({ - url:aLocation.getLinkByName("self"), - name:aLocation.getPrettyName() - }) - $selectLocations.append($option) - }) - $selectLocations.each(function(i) { - var url = $($selectLocations[i]).parent().attr('initialValue'); - $($selectLocations[i]).val(url) - }) - }, - render:function () { - var that = this - this.renderName() - this.locations.fetch({async:false, - success:function () { - if (that.model.get("locations").length==0) - that.addLocation() - else - that.renderAddedLocations() - }}) - this.delegateEvents() - return this - }, - addLocation:function () { - if (this.locations.models.length>0) { - this.model.addLocation(this.locations.models[0].getLinkByName("self")) - this.renderAddedLocations() - } else { - this.$('div.info-nolocs-message').show('slow').delay(2000).hide('slow') - } - }, - removeLocation:function (event) { - var toBeRemoved = $(event.currentTarget).parent().attr('rowId') - this.model.removeLocationIndex(toBeRemoved) - this.renderAddedLocations() - }, - selection:function (event) { - var url = $(event.currentTarget).val(); - var loc = this.locations.find(function (candidate) { - return candidate.getLinkByName("self")==url - }) - this.model.setLocationAtIndex($(event.currentTarget).parent().attr('rowId'), - loc.getLinkByName("self")) - }, - updateName:function () { - this.model.set("name", this.$('#application-name').val()) - }, - validate:function () { - if (this.model.get("name") !== "" && this.model.get("locations").length !== 0) { - return true - } - this.$('div.info-message').show('slow').delay(2000).hide('slow') - return false - } - }) - - /** - * Second step from the create application wizard. Allows you to add and new entities and configure them. - */ - // Note: this does not restore values on a back click; setting type and entity type+name is easy, - // but relevant config lines is a little bit more tedious - ModalWizard.Step2 = Backbone.View.extend({ - className:'modal-body', - events:{ - 'click #add-app-entity':'addEntity', - 'click .editable-entity-heading':'expandEntity', - 'click .remove-entity-button':'removeEntityClick', - 'click .editable-entity-button':'saveEntityClick', - 'click #remove-config':'removeConfigRow', - 'click #add-config':'addConfigRow' - }, - template:_.template(Step2Html), - initialize:function () { - var self = this - self.catalogEntities = [] - self.catalogApplications = [] - - this.$el.html(this.template({})) - this.addEntity() - - $.get('/v1/catalog/entities', {}, function (result) { - self.catalogEntities = result - self.$(".entity-type-input").typeahead().data('typeahead').source = self.catalogEntities - }) - $.get('/v1/catalog/applications', {}, function (result) { - self.catalogApplications = result - self.$(".application-type-input").typeahead().data('typeahead').source = self.catalogApplications - }) - }, - beforeClose:function () { - }, - renderConfiguredEntities:function () { - var $configuredEntities = this.$('#entitiesAccordionish').empty() - var that = this - if (this.model.get("entities").length > 0) { - _.each(this.model.get("entities"), function (entity) { - that.addEntityHtml($configuredEntities, entity) - }) - } - }, - - render:function () { - this.renderConfiguredEntities() - this.delegateEvents() - return this - }, - - expandEntity:function (event) { - $(event.currentTarget).next().show('fast').delay(1000).prev().hide('slow') - }, - saveEntityClick:function (event) { - this.saveEntity($(event.currentTarget).parent().parent().parent()); - }, - saveEntity:function ($entityGroup) { - var that = this - var name = $('#entity-name',$entityGroup).val() - var type = $('#entity-type',$entityGroup).val() - if (type=="" || !_.contains(that.catalogEntities, type)) { - $('.entity-info-message',$entityGroup).show('slow').delay(2000).hide('slow') - return false - } - var saveTarget = this.model.get("entities")[$entityGroup.index()]; - this.model.set("type", null) - saveTarget.name = name - saveTarget.type = type - saveTarget.config = this.getConfigMap($entityGroup) - - if (name=="") name=type; - if (name=="") name="<i>(new entity)</i>"; - $('#entity-name-header',$entityGroup).html( name ) - $('.editable-entity-body',$entityGroup).prev().show('fast').next().hide('fast') - return true; - }, - getConfigMap:function (root) { - var map = {} - $('.step2-entity-config',root).each( function (index,elt) { - map[$('#key',elt).val()] = $('#value',elt).val() - }) - return map; - }, - saveTemplate:function () { - var that = this - var tab = $.find('#templateTab') - var type = $(tab).find('#entity-type').val() - if (!_.contains(this.catalogApplications, type)) { - $('.entity-info-message').show('slow').delay(2000).hide('slow') - return false - } - this.model.set("type", type); - this.model.set("config", this.getConfigMap(tab)) - return true; - }, - addEntity:function () { - var entity = new Entity.Model - this.model.addEntity( entity ) - this.addEntityHtml(this.$('#entitiesAccordionish'), entity) - }, - addEntityHtml:function (parent, entity) { - var $entity = _.template(Step2EntityEntryHtml, {}) - var that = this - parent.append($entity) - parent.children().last().find('.entity-type-input').typeahead({ source: that.catalogEntities }) - }, - removeEntityClick:function (event) { - var $entityGroup = $(event.currentTarget).parent().parent().parent(); - this.model.removeEntityIndex($entityGroup.index()) - $entityGroup.remove() - }, - - addConfigRow:function (event) { - var $row = _.template(Step2ConfigEntryHtml, {}) - $(event.currentTarget).parent().prev().append($row) - }, - removeConfigRow:function (event) { - $(event.currentTarget).parent().remove() - }, - - validate:function () { - var that = this - var tabName = $('#step2Tab li[class="active"] a').attr('href') - if (tabName=='#entitiesTab') { - var allokay = true - $($.find('.editable-entity-group')).each( - function (i,$entityGroup) { - allokay = that.saveEntity($entityGroup) & allokay - }) - if (!allokay) return false; - if (this.model.get("entities").length > 0) { - this.model.set("type", null); - return true; - } - } else if (tabName=='#templateTab') { - if (this.saveTemplate()) { - this.model.set("entities", []); - return true - } - } else { - // other tabs not implemented yet - // do nothing, show error return false below - } - this.$('div.step2-info-message').show('slow').delay(2000).hide('slow') - return false - } - - }) - /** - * Final step from the create application wizard. Review the summary and submit the request. - */ - ModalWizard.Step3 = Backbone.View.extend({ - className:'modal-body', - initialize:function () { - this.$el.html(_.template(Step3Html)) - this.model.on("change", this.render, this) - }, - beforeClose:function () { - this.model.off("change", this.render) - }, - render:function () { - this.$('#app-summary').val(FormatJSON(this.model.toJSON())) - this.delegateEvents() - return this - }, - validate:function () { - if (this.model.get("name") != "" - && this.model.get("locations").length > 0 - && (this.model.get("type")!=null || - this.model.get("entities").length > 0)) { - return true - } - this.showFailure() - return false - }, - showFailure:function () { - this.$('div.info-message').show('slow').delay(2000).hide('slow') - } - }) - - return ModalWizard -}) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create-config-entry.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create-config-entry.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create-config-entry.html new file mode 100644 index 0000000..f4a1779 --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create-config-entry.html @@ -0,0 +1,8 @@ +<div class="controls app-add-wizard-create-entity-config"> + <input id="key" type="text" class="input-medium" name="key" placeholder="key"> + <input id="value" type="text" class="input-medium" name="value" placeholder="value"> + + <button id="remove-config" class="btn btn-info btn-mini" type="button"> + <i class="icon-minus-sign"></i> + </button> +</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create-entity-entry.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create-entity-entry.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create-entity-entry.html new file mode 100644 index 0000000..df12216 --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create-entity-entry.html @@ -0,0 +1,44 @@ +<div class="editable-entity-group"> + <div class="editable-entity-heading hide"> + <span id="entity-name-header"><i>(new entity)</i></span> + <div style="float: right;"> + <button class="btn btn-info btn-mini"><i class="icon-chevron-down"></i></button> + </div> + </div> + + <div class="editable-entity-body"> + <div class="entity-info-message label-message hide"> + <span class="label-important">ERROR</span> Invalid entity/type definition + </div> + + <div style="float: right;"> + <button class="btn btn-info btn-mini remove-entity-button"> + <i class="icon-remove"></i> </button> + <button class="btn btn-info btn-mini editable-entity-button"> + <i class="icon-chevron-up"></i> </button> + </div> + <div class="control-group"> + <div class="controls"> + <div class="app-add-wizard-create-entity-label">Name</div> + <input id="entity-name" type="text" class="input-large app-add-wizard-create-entity-input" name="name" placeholder="name"> + </div> + </div> + + <div class="control-group"> + <div class="controls"> + <div class="app-add-wizard-create-entity-label">Type</div> + <input id="entity-type" type="text" name="type" class="input-large app-add-wizard-create-entity-input entity-type-input" placeholder="type"> + </div> + </div> + + <div class="control-group"> + <div class="app-add-wizard-create-entity-label-newline">Configuration</div> + <div class="controls"> + </div> + <div> + <button id="add-config" class="btn btn-mini btn-info"> + Add Config Key</button> + </div> + </div> + </div> +</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create.html new file mode 100644 index 0000000..0ae2c0a --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/create.html @@ -0,0 +1,62 @@ +<div class="app-add-wizard-create-info-message label-message hide"> + <div class="label-important">ERROR</div> Invalid application type/spec +</div> + +<div id="app-add-wizard-create-body"> + + <ul class="nav nav-tabs" id="app-add-wizard-create-tab"> + <li class="active"><a href="#templateTab" data-toggle="tab">Template</a></li> + <li><a href="#entitiesTab" data-toggle="tab">Entities</a></li> + + <li class="dropdown"><a class="dropdown-toggle" id="dropLanguage" + role="button" data-toggle="dropdown" href="#">Code <b class="caret"></b></a> + <ul id="menuLanguage" class="dropdown-menu" role="menu" aria-labelledby="dropLanguage"> + <li><a tabindex="-1" data-toggle="tab" href="#jsonTab">JSON</a></li> + <li><a tabindex="-1" data-toggle="tab" href="#xmlTab">XML</a></li> + <li class="divider"></li> + <li><a tabindex="-1" data-toggle="tab" href="#groovyTab">Groovy</a></li> + <li class="divider"></li> + <li><a tabindex="-1" data-toggle="tab" href="#uploadTab">JAR</a></li> + </ul></li> + </ul> + + <div class="tab-content"> + <div class="tab-pane active" id="templateTab"> + + <div class="control-group"> + <div class="app-add-wizard-create-entity-label-newline">Type</div> + <div class="controls app-type"> + <input id="entity-type" type="text" name="type" class="input-large app-add-wizard-create-entity-input application-type-input" placeholder="type"> + </div> + </div> + + <div class="control-group"> + <div class="app-add-wizard-create-entity-label-newline">Configuration</div> + <div class="controls"> + </div> + <div> + <button id="add-config" class="btn btn-mini btn-info"> + Add Config Key</button> + </div> + </div> + </div> + + + <div class="tab-pane" id="entitiesTab"> + <div id="entitiesAccordionish"></div> + <button id="add-app-entity" class="btn btn-info btn-mini" style="margin:5px;">Add Additional Entity</button> + </div> + + <div class="tab-pane" id="jsonTab"> + <br/><br/><i>coming soon!</i> + </div> + <div class="tab-pane" id="xmlTab"> + <br/><br/><i>coming soon!</i> + </div> + <div class="tab-pane" id="groovyTab"> + <br/><br/><i>coming soon!</i> + </div> + <div class="tab-pane" id="uploadTab"> + <br/><br/><i>coming soon!</i> + </div> +</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy-location-option.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy-location-option.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy-location-option.html new file mode 100644 index 0000000..9242353 --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy-location-option.html @@ -0,0 +1,3 @@ +<option value="<%= url %>"> + <span class="provider"><%= name %></span> +</option> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy-location-row.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy-location-row.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy-location-row.html new file mode 100644 index 0000000..ed51a2a --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy-location-row.html @@ -0,0 +1,6 @@ +<div id="location-row-<%= rowId %>" rowId="<%= rowId %>" initialValue="<%= initialValue %>" class="location-selector-row"> + <select id="select-location" style="margin:4px 0 4px 0; width:80%"></select> + <% if (rowId>0) { %> + <button id="remove-app-location" class="btn btn-info btn-mini" type="button"><i class="icon-minus-sign"></i></button> + <% } %> +</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy.html new file mode 100644 index 0000000..b69f5ba --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/deploy.html @@ -0,0 +1,28 @@ +<!-- New application wizard step 1: set name and locations --> + +<div class="info-message label-message hide"> + <span class="label-important">Important</span> + Name and location must be specified +</div> +<div class="info-nolocs-message label-message hide"> + <span class="label-important">Important</span> + Missing or unconfigured locations +</div> + + +<div class="control-group"> + <label for="application-name">Name</label> + + <div class="controls"> + <input id="application-name" name="name" type="text" style="width:80%"> + </div> +</div> + +<div id="app-locations"> + <div>Locations</div> + <div id="selector-container" class="control-group"> + </div> + <button id="add-selector-container" class="btn btn-info btn-mini">Add Additional Location</button> +</div> + +</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/modal-wizard.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/modal-wizard.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/modal-wizard.html new file mode 100644 index 0000000..540b37a --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/modal-wizard.html @@ -0,0 +1,13 @@ +<div class="modal-header"> + <button type="button" class="close" data-dismiss="modal">x</button> + <h3 id="step_title">Title placeholder</h3> + + <p id="step_instructions">Instructions placeholder</p> +</div> + +<div class="modal-body"></div> + +<div class="modal-footer"> + <button id="prev_step" type="button" class="btn btn-mini btn-info">Previous</button> + <button id="next_step" type="button" class="btn btn-mini btn-info">Next</button> +</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/preview.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/preview.html b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/preview.html new file mode 100644 index 0000000..3b9642f --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/app-add-wizard/preview.html @@ -0,0 +1,10 @@ +<!-- New application wizard step 3: summary and submit the app --> +<div> + <h3>Application Preview</h3> + <textarea id="app-summary" readonly="readonly" rows="16" style="width:100%;"></textarea> +</div> +<dl class="dl-horizontal"></dl> +<div class="info-message hide label-message"> + <span class="label-important">ERROR</span> + Invalid spec or server failure +</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/home/modal-wizard.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/modal-wizard.html b/usage/jsgui/src/main/webapp/assets/tpl/home/modal-wizard.html deleted file mode 100644 index 540b37a..0000000 --- a/usage/jsgui/src/main/webapp/assets/tpl/home/modal-wizard.html +++ /dev/null @@ -1,13 +0,0 @@ -<div class="modal-header"> - <button type="button" class="close" data-dismiss="modal">x</button> - <h3 id="step_title">Title placeholder</h3> - - <p id="step_instructions">Instructions placeholder</p> -</div> - -<div class="modal-body"></div> - -<div class="modal-footer"> - <button id="prev_step" type="button" class="btn btn-mini btn-info">Previous</button> - <button id="next_step" type="button" class="btn btn-mini btn-info">Next</button> -</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/home/step1-location-option.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/step1-location-option.html b/usage/jsgui/src/main/webapp/assets/tpl/home/step1-location-option.html deleted file mode 100644 index 9242353..0000000 --- a/usage/jsgui/src/main/webapp/assets/tpl/home/step1-location-option.html +++ /dev/null @@ -1,3 +0,0 @@ -<option value="<%= url %>"> - <span class="provider"><%= name %></span> -</option> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/home/step1-location-row.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/step1-location-row.html b/usage/jsgui/src/main/webapp/assets/tpl/home/step1-location-row.html deleted file mode 100644 index ed51a2a..0000000 --- a/usage/jsgui/src/main/webapp/assets/tpl/home/step1-location-row.html +++ /dev/null @@ -1,6 +0,0 @@ -<div id="location-row-<%= rowId %>" rowId="<%= rowId %>" initialValue="<%= initialValue %>" class="location-selector-row"> - <select id="select-location" style="margin:4px 0 4px 0; width:80%"></select> - <% if (rowId>0) { %> - <button id="remove-app-location" class="btn btn-info btn-mini" type="button"><i class="icon-minus-sign"></i></button> - <% } %> -</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/home/step1.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/step1.html b/usage/jsgui/src/main/webapp/assets/tpl/home/step1.html deleted file mode 100644 index b69f5ba..0000000 --- a/usage/jsgui/src/main/webapp/assets/tpl/home/step1.html +++ /dev/null @@ -1,28 +0,0 @@ -<!-- New application wizard step 1: set name and locations --> - -<div class="info-message label-message hide"> - <span class="label-important">Important</span> - Name and location must be specified -</div> -<div class="info-nolocs-message label-message hide"> - <span class="label-important">Important</span> - Missing or unconfigured locations -</div> - - -<div class="control-group"> - <label for="application-name">Name</label> - - <div class="controls"> - <input id="application-name" name="name" type="text" style="width:80%"> - </div> -</div> - -<div id="app-locations"> - <div>Locations</div> - <div id="selector-container" class="control-group"> - </div> - <button id="add-selector-container" class="btn btn-info btn-mini">Add Additional Location</button> -</div> - -</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/home/step2-config-entry.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/step2-config-entry.html b/usage/jsgui/src/main/webapp/assets/tpl/home/step2-config-entry.html deleted file mode 100644 index 8bf1df1..0000000 --- a/usage/jsgui/src/main/webapp/assets/tpl/home/step2-config-entry.html +++ /dev/null @@ -1,6 +0,0 @@ - <div class="controls step2-entity-config"> - <input id="key" type="text" class="input-medium" name="key" placeholder="key"> - <input id="value" type="text" class="input-medium" name="value" placeholder="value"> - <button id="remove-config" class="btn btn-info btn-mini" type="button"> - <i class="icon-minus-sign"></i> </button> - </div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/home/step2-entity-entry.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/step2-entity-entry.html b/usage/jsgui/src/main/webapp/assets/tpl/home/step2-entity-entry.html deleted file mode 100644 index 1c49cc3..0000000 --- a/usage/jsgui/src/main/webapp/assets/tpl/home/step2-entity-entry.html +++ /dev/null @@ -1,44 +0,0 @@ -<div class="editable-entity-group"> - <div class="editable-entity-heading hide"> - <span id="entity-name-header"><i>(new entity)</i></span> - <div style="float: right;"> - <button class="btn btn-info btn-mini"><i class="icon-chevron-down"></i></button> - </div> - </div> - - <div class="editable-entity-body"> - <div class="entity-info-message label-message hide"> - <span class="label-important">ERROR</span> Invalid entity/type definition - </div> - - <div style="float: right;"> - <button class="btn btn-info btn-mini remove-entity-button"> - <i class="icon-remove"></i> </button> - <button class="btn btn-info btn-mini editable-entity-button"> - <i class="icon-chevron-up"></i> </button> - </div> - <div class="control-group"> - <div class="controls"> - <div class="step2-entity-label">Name</div> - <input id="entity-name" type="text" class="input-large step2-entity-input" name="name" placeholder="name"> - </div> - </div> - - <div class="control-group"> - <div class="controls"> - <div class="step2-entity-label">Type</div> - <input id="entity-type" type="text" name="type" class="input-large step2-entity-input entity-type-input" placeholder="type"> - </div> - </div> - - <div class="control-group"> - <div class="step2-entity-label-newline">Configuration</div> - <div class="controls"> - </div> - <div> - <button id="add-config" class="btn btn-mini btn-info"> - Add Config Key</button> - </div> - </div> - </div> -</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/home/step2.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/step2.html b/usage/jsgui/src/main/webapp/assets/tpl/home/step2.html deleted file mode 100644 index fb65297..0000000 --- a/usage/jsgui/src/main/webapp/assets/tpl/home/step2.html +++ /dev/null @@ -1,64 +0,0 @@ -<!-- New application wizard step 2: add and configure entities --> - -<div class="step2-info-message label-message hide"> - <div class="label-important">ERROR</div> Invalid application type/spec -</div> - -<div id="step2body"> - - <ul class="nav nav-tabs" id="step2Tab"> - <li class="active"><a href="#templateTab" data-toggle="tab">Template</a></li> - <li><a href="#entitiesTab" data-toggle="tab">Entities</a></li> - - <li class="dropdown"><a class="dropdown-toggle" id="dropLanguage" - role="button" data-toggle="dropdown" href="#">Code <b class="caret"></b></a> - <ul id="menuLanguage" class="dropdown-menu" role="menu" aria-labelledby="dropLanguage"> - <li><a tabindex="-1" data-toggle="tab" href="#jsonTab">JSON</a></li> - <li><a tabindex="-1" data-toggle="tab" href="#xmlTab">XML</a></li> - <li class="divider"></li> - <li><a tabindex="-1" data-toggle="tab" href="#groovyTab">Groovy</a></li> - <li class="divider"></li> - <li><a tabindex="-1" data-toggle="tab" href="#uploadTab">JAR</a></li> - </ul></li> - </ul> - - <div class="tab-content"> - <div class="tab-pane active" id="templateTab"> - - <div class="control-group"> - <div class="step2-entity-label-newline">Type</div> - <div class="controls app-type"> - <input id="entity-type" type="text" name="type" class="input-large step2-entity-input application-type-input" placeholder="type"> - </div> - </div> - - <div class="control-group"> - <div class="step2-entity-label-newline">Configuration</div> - <div class="controls"> - </div> - <div> - <button id="add-config" class="btn btn-mini btn-info"> - Add Config Key</button> - </div> - </div> - </div> - - - <div class="tab-pane" id="entitiesTab"> - <div id="entitiesAccordionish"></div> - <button id="add-app-entity" class="btn btn-info btn-mini" style="margin:5px;">Add Additional Entity</button> - </div> - - <div class="tab-pane" id="jsonTab"> - <br/><br/><i>coming soon!</i> - </div> - <div class="tab-pane" id="xmlTab"> - <br/><br/><i>coming soon!</i> - </div> - <div class="tab-pane" id="groovyTab"> - <br/><br/><i>coming soon!</i> - </div> - <div class="tab-pane" id="uploadTab"> - <br/><br/><i>coming soon!</i> - </div> -</div> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/main/webapp/assets/tpl/home/step3.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/step3.html b/usage/jsgui/src/main/webapp/assets/tpl/home/step3.html deleted file mode 100644 index 1407cf7..0000000 --- a/usage/jsgui/src/main/webapp/assets/tpl/home/step3.html +++ /dev/null @@ -1,10 +0,0 @@ -<!-- New application wizard step 3: summary and submit the app --> -<div> - <h3>Request preview:</h3> - <textarea id="app-summary" readonly="readonly" rows="16" style="width:100%;"></textarea> -</div> -<dl class="dl-horizontal"></dl> -<div class="info-message hide label-message"> - <span class="label-important">ERROR</span> - Invalid JSON spec or server failure -</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/test/javascript/specs/view/application-add-wizard-spec.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/test/javascript/specs/view/application-add-wizard-spec.js b/usage/jsgui/src/test/javascript/specs/view/application-add-wizard-spec.js new file mode 100644 index 0000000..adae3d9 --- /dev/null +++ b/usage/jsgui/src/test/javascript/specs/view/application-add-wizard-spec.js @@ -0,0 +1,194 @@ +/** + * Test the ModalWizard can build a modal to view, edit and submit an application. + */ +define([ + "underscore", "jquery", "backbone", "view/application-add-wizard", "model/application", "model/location", + "text!tpl/home/step1.html", "text!tpl/home/step2.html", "text!tpl/home/step3.html", + "text!tpl/home/step1-location-row.html", "text!tpl/home/step1-location-option.html", + "text!tpl/home/step2-entity-entry.html", "text!tpl/home/step2-config-entry.html" +], function (_, $, Backbone, AppAddWizard, Application, Locations, Entities, + Step1Html, Step2Html, Step3Html, + Step1LocationRowHtml, LocationOptionHtml, + Step2EntityEntryHtml, Step2ConfigEntryHtml) { + + /* TEST disabled until we can more cleanly supply javascript. + * should probably move to have one big model, + * rather than passing around lots of small model items. + */ + +// Backbone.View.prototype.close = function () { +// if (this.beforeClose) { +// this.beforeClose() +// } +// this.remove() +// this.unbind() +// } +// +// var fakeRouter = new Backbone.Router() +// var modal = new ModalWizard({appRouter:fakeRouter}); +// +// describe("view/modal-wizard", function () { +// +// it("creates an empty Application.Spec", function () { +// expect(modal.model.get("name")).toBe("") +// expect(modal.model.get("entities")).toEqual([]) +// expect(modal.model.get("locations")).toEqual([]) +// }) +// +// it("creates a view for each of the 3 steps", function () { +// expect(modal.steps.length).toBe(3) +// expect(modal.steps[0].view instanceof ModalWizard.Step1).toBeTruthy() +// expect(modal.steps[1].view instanceof ModalWizard.Step2).toBeTruthy() +// expect(modal.steps[2].view instanceof ModalWizard.Step3).toBeTruthy() +// }) +// +// it("beforeClose method closes all 3 subviews", function () { +// spyOn(Backbone.View.prototype, "close").andCallThrough() +// modal.beforeClose() +// expect(modal.steps[0].view.close).toHaveBeenCalled() +// expect(modal.steps[1].view.close).toHaveBeenCalled() +// expect(modal.steps[2].view.close).toHaveBeenCalled() +// }) +// }) +// +// describe("view/modal-wizard step1", function () { +// var app, view +// +// beforeEach(function () { +// app = new Application.Spec +// view = new ModalWizard.Step1({model:app}) +// view.locations.url = "fixtures/location-list.json" +// view.locations.fetch({async:false}) +// view.render() +// }) +// +// afterEach(function () { +// view.close() +// }) +// +// it("does not validate empty view", function () { +// expect(view.validate()).toBe(false) +// expect(view.$("#app-locations ul").html()).toBe("") +// expect(view.$("#application-name").text()).toBe("") +// }) +// +// it("updates the name on blur", function () { +// view.$("#application-name").val("myapp") +// view.$("#application-name").trigger("blur") +// expect(app.get("name")).toBe("myapp") +// }) +// +// it("adds and removes location", function () { +// expect(app.get("locations").length).toBe(0) +// view.$("#add-app-location").trigger("click") +// expect(app.get("locations").length).toBe(1) +// view.$(".remove").trigger("click") +// expect(app.get("locations").length).toBe(0) +// }) +// +// }) +// +// describe("view/modal-wizard step2", function () { +// var app, view +// +// beforeEach(function () { +// app = new Application.Spec +// view = new ModalWizard.Step2({model:app}) +// // TODO supply catalog entities +// view.render() +// }) +// +// afterEach(function () { +// view.close() +// }) +// +// // to be added +// }) +// +// describe("view/modal-wizard step3", function () { +// var app, view +// +// beforeEach(function () { +// app = new Application.Spec +// view = new ModalWizard.Step3({model:app}) +// view.render() +// }) +// +// afterEach(function () { +// view.close() +// }) +// +// it("has #app-summary to render the application", function () { +// expect(view.$("#app-summary").length).toBe(1) +// }) +// +// it("validates only when application spec contains data", function () { +// expect(view.validate()).toBe(false) +// app.set({name:"myapp", locations:["/dummy/1"], entities:[ +// {} +// ]}) +// expect(view.validate()).toBe(true) +// }) +// }) +// +// describe('tpl/home/step1.html', function () { +// var $step = $(Step1Html) +// +// it('must have input#application-name', function () { +// expect($step.find('input#application-name').length).toEqual(1); +// }); +// +// it('must have div#app-locations', function () { +// var $appLocations = $step.filter('div#app-locations'); +// expect($appLocations.length).toEqual(1); +// expect($appLocations.find('h4').length).toEqual(1); +// expect($appLocations.find('ul').length).toEqual(1); +// expect($appLocations.find('button#toggle-selector-container').length).toEqual(1); +// }); +// +// it('must have select#select-location', function () { +// expect($step.find('select#select-location').length).toEqual(1); +// }); +// +// it('must have button#add-app-location', function () { +// expect($step.find('button#add-app-location').length).toEqual(1); +// }); +// it('must have div.info-message', function () { +// expect($step.filter('div.info-message').length).toEqual(1); +// }) +// }); +// +// describe('tpl/home/step2.html', function () { +// var $step = $(Step2Html); +// +// it('must have div#entities with h4 and ul', function () { +// var $div = $step.filter('div#entities'); +// expect($div.length).toEqual(1); +// expect($div.find('h4').length).toEqual(1); +// expect($div.find('ul').length).toEqual(1); +// expect($div.find('button#toggle-entity-form').length).toEqual(1); +// }); +// +// it('must have div#new-entity with all components', function () { +// var $div = $step.filter('div#new-entity'); +// expect($div.length).toEqual(1); +// expect($div.find('div#entity-form').length).toEqual(1); +// expect($div.find('button#add-app-entity').length).toEqual(1); +// expect($div.find('div.entity-info-message').length).toEqual(1); +// }); +// it('must have div.info-message', function () { +// expect($step.filter('div.info-message').length).toEqual(1); +// }); +// }); +// +// describe('tpl/home/step3.html', function () { +// var $step = $(Step3Html); +// it('div.body must have h3 and textarea#app-summary', function () { +// expect($step.find('h3').length).toEqual(1); +// expect($step.find('textarea#app-summary').length).toEqual(1); +// }); +// it('must have div.info-message', function () { +// expect($step.filter('div.info-message').length).toEqual(1); +// }); +// }); +}) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/b0412050/usage/jsgui/src/test/javascript/specs/view/modal-wizard-spec.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/test/javascript/specs/view/modal-wizard-spec.js b/usage/jsgui/src/test/javascript/specs/view/modal-wizard-spec.js deleted file mode 100644 index f98d70e..0000000 --- a/usage/jsgui/src/test/javascript/specs/view/modal-wizard-spec.js +++ /dev/null @@ -1,194 +0,0 @@ -/** - * Test the ModalWizard can build a modal to view, edit and submit an application. - */ -define([ - "underscore", "jquery", "backbone", "view/modal-wizard", "model/application", "model/location", - "text!tpl/home/step1.html", "text!tpl/home/step2.html", "text!tpl/home/step3.html", - "text!tpl/home/step1-location-row.html", "text!tpl/home/step1-location-option.html", - "text!tpl/home/step2-entity-entry.html", "text!tpl/home/step2-config-entry.html" -], function (_, $, Backbone, ModalWizard, Application, Locations, Entities, - Step1Html, Step2Html, Step3Html, - Step1LocationRowHtml, LocationOptionHtml, - Step2EntityEntryHtml, Step2ConfigEntryHtml) { - - /* TEST disabled until we can more cleanly supply javascript. - * should probably move to have one big model, - * rather than passing around lots of small model items. - */ - -// Backbone.View.prototype.close = function () { -// if (this.beforeClose) { -// this.beforeClose() -// } -// this.remove() -// this.unbind() -// } -// -// var fakeRouter = new Backbone.Router() -// var modal = new ModalWizard({appRouter:fakeRouter}); -// -// describe("view/modal-wizard", function () { -// -// it("creates an empty Application.Spec", function () { -// expect(modal.model.get("name")).toBe("") -// expect(modal.model.get("entities")).toEqual([]) -// expect(modal.model.get("locations")).toEqual([]) -// }) -// -// it("creates a view for each of the 3 steps", function () { -// expect(modal.steps.length).toBe(3) -// expect(modal.steps[0].view instanceof ModalWizard.Step1).toBeTruthy() -// expect(modal.steps[1].view instanceof ModalWizard.Step2).toBeTruthy() -// expect(modal.steps[2].view instanceof ModalWizard.Step3).toBeTruthy() -// }) -// -// it("beforeClose method closes all 3 subviews", function () { -// spyOn(Backbone.View.prototype, "close").andCallThrough() -// modal.beforeClose() -// expect(modal.steps[0].view.close).toHaveBeenCalled() -// expect(modal.steps[1].view.close).toHaveBeenCalled() -// expect(modal.steps[2].view.close).toHaveBeenCalled() -// }) -// }) -// -// describe("view/modal-wizard step1", function () { -// var app, view -// -// beforeEach(function () { -// app = new Application.Spec -// view = new ModalWizard.Step1({model:app}) -// view.locations.url = "fixtures/location-list.json" -// view.locations.fetch({async:false}) -// view.render() -// }) -// -// afterEach(function () { -// view.close() -// }) -// -// it("does not validate empty view", function () { -// expect(view.validate()).toBe(false) -// expect(view.$("#app-locations ul").html()).toBe("") -// expect(view.$("#application-name").text()).toBe("") -// }) -// -// it("updates the name on blur", function () { -// view.$("#application-name").val("myapp") -// view.$("#application-name").trigger("blur") -// expect(app.get("name")).toBe("myapp") -// }) -// -// it("adds and removes location", function () { -// expect(app.get("locations").length).toBe(0) -// view.$("#add-app-location").trigger("click") -// expect(app.get("locations").length).toBe(1) -// view.$(".remove").trigger("click") -// expect(app.get("locations").length).toBe(0) -// }) -// -// }) -// -// describe("view/modal-wizard step2", function () { -// var app, view -// -// beforeEach(function () { -// app = new Application.Spec -// view = new ModalWizard.Step2({model:app}) -// // TODO supply catalog entities -// view.render() -// }) -// -// afterEach(function () { -// view.close() -// }) -// -// // to be added -// }) -// -// describe("view/modal-wizard step3", function () { -// var app, view -// -// beforeEach(function () { -// app = new Application.Spec -// view = new ModalWizard.Step3({model:app}) -// view.render() -// }) -// -// afterEach(function () { -// view.close() -// }) -// -// it("has #app-summary to render the application", function () { -// expect(view.$("#app-summary").length).toBe(1) -// }) -// -// it("validates only when application spec contains data", function () { -// expect(view.validate()).toBe(false) -// app.set({name:"myapp", locations:["/dummy/1"], entities:[ -// {} -// ]}) -// expect(view.validate()).toBe(true) -// }) -// }) -// -// describe('tpl/home/step1.html', function () { -// var $step = $(Step1Html) -// -// it('must have input#application-name', function () { -// expect($step.find('input#application-name').length).toEqual(1); -// }); -// -// it('must have div#app-locations', function () { -// var $appLocations = $step.filter('div#app-locations'); -// expect($appLocations.length).toEqual(1); -// expect($appLocations.find('h4').length).toEqual(1); -// expect($appLocations.find('ul').length).toEqual(1); -// expect($appLocations.find('button#toggle-selector-container').length).toEqual(1); -// }); -// -// it('must have select#select-location', function () { -// expect($step.find('select#select-location').length).toEqual(1); -// }); -// -// it('must have button#add-app-location', function () { -// expect($step.find('button#add-app-location').length).toEqual(1); -// }); -// it('must have div.info-message', function () { -// expect($step.filter('div.info-message').length).toEqual(1); -// }) -// }); -// -// describe('tpl/home/step2.html', function () { -// var $step = $(Step2Html); -// -// it('must have div#entities with h4 and ul', function () { -// var $div = $step.filter('div#entities'); -// expect($div.length).toEqual(1); -// expect($div.find('h4').length).toEqual(1); -// expect($div.find('ul').length).toEqual(1); -// expect($div.find('button#toggle-entity-form').length).toEqual(1); -// }); -// -// it('must have div#new-entity with all components', function () { -// var $div = $step.filter('div#new-entity'); -// expect($div.length).toEqual(1); -// expect($div.find('div#entity-form').length).toEqual(1); -// expect($div.find('button#add-app-entity').length).toEqual(1); -// expect($div.find('div.entity-info-message').length).toEqual(1); -// }); -// it('must have div.info-message', function () { -// expect($step.filter('div.info-message').length).toEqual(1); -// }); -// }); -// -// describe('tpl/home/step3.html', function () { -// var $step = $(Step3Html); -// it('div.body must have h3 and textarea#app-summary', function () { -// expect($step.find('h3').length).toEqual(1); -// expect($step.find('textarea#app-summary').length).toEqual(1); -// }); -// it('must have div.info-message', function () { -// expect($step.filter('div.info-message').length).toEqual(1); -// }); -// }); -}) \ No newline at end of file
