Addeed reconfigurable policy UI to usage/jsgui
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/056d4ac5 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/056d4ac5 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/056d4ac5 Branch: refs/heads/0.5.0 Commit: 056d4ac5802726a01b4e7bd81397d043746236d5 Parents: ea45c01 Author: Andrew Kennedy <[email protected]> Authored: Tue Feb 5 18:54:02 2013 +0000 Committer: Andrew Kennedy <[email protected]> Committed: Wed Feb 27 17:26:56 2013 +0000 ---------------------------------------------------------------------- .../assets/js/model/policy-config-summary.js | 34 +++++++ .../webapp/assets/js/model/policy-summary.js | 4 + .../webapp/assets/js/view/entity-policies.js | 99 +++++++++++++++++--- .../js/view/policy-config-update-invoke.js | 87 +++++++++++++++++ .../assets/tpl/apps/policy-config-modal.html | 18 ++++ .../assets/tpl/apps/policy-config-row.html | 11 +++ .../main/webapp/assets/tpl/apps/policy-row.html | 2 +- .../src/main/webapp/assets/tpl/apps/policy.html | 20 ++++ 8 files changed, 262 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/056d4ac5/usage/jsgui/src/main/webapp/assets/js/model/policy-config-summary.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/model/policy-config-summary.js b/usage/jsgui/src/main/webapp/assets/js/model/policy-config-summary.js new file mode 100644 index 0000000..392a1ba --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/js/model/policy-config-summary.js @@ -0,0 +1,34 @@ +define([ + "underscore", "backbone" +], function (_, Backbone) { + + var PolicyConfigSummary = {} + + PolicyConfigSummary.Model = Backbone.Model.extend({ + defaults:function () { + return { + name:"", + type:"", + description:"", + defaultValue:"", + reconfigurable:"", + links:{ + self:"", + application:"", + entity:"", + policy:"", + edit:"", + } + } + }, + getLinkByName:function (name) { + if (name) return this.get("links")[name] + }, + }) + + PolicyConfigSummary.Collection = Backbone.Collection.extend({ + model:PolicyConfigSummary.Model + }) + + return PolicyConfigSummary +}) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/056d4ac5/usage/jsgui/src/main/webapp/assets/js/model/policy-summary.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/model/policy-summary.js b/usage/jsgui/src/main/webapp/assets/js/model/policy-summary.js index 7402f5f..38b21ac 100644 --- a/usage/jsgui/src/main/webapp/assets/js/model/policy-summary.js +++ b/usage/jsgui/src/main/webapp/assets/js/model/policy-summary.js @@ -12,6 +12,7 @@ define([ state:"", links:{ self:"", + config:"", start:"", stop:"", destroy:"", @@ -22,6 +23,9 @@ define([ }, getLinkByName:function (name) { if (name) return this.get("links")[name] + }, + getPolicyConfigUpdateUrl:function () { + return this.getLinkByName("self") + "/config/current-state" } }) http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/056d4ac5/usage/jsgui/src/main/webapp/assets/js/view/entity-policies.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/view/entity-policies.js b/usage/jsgui/src/main/webapp/assets/js/view/entity-policies.js index fec2476..6bad6c3 100644 --- a/usage/jsgui/src/main/webapp/assets/js/view/entity-policies.js +++ b/usage/jsgui/src/main/webapp/assets/js/view/entity-policies.js @@ -5,17 +5,36 @@ * @type {*} */ define([ - "underscore", "jquery", "backbone", "model/policy-summary", - "text!tpl/apps/policy.html", "text!tpl/apps/policy-row.html", "bootstrap" -], function (_, $, Backbone, PolicySummary, PolicyHtml, PolicyRowHtml) { + "underscore", + "jquery", + "backbone", + "model/policy-summary", + "model/policy-config-summary", + "text!tpl/apps/policy.html", + "text!tpl/apps/policy-row.html", + "text!tpl/apps/policy-config-row.html", + "bootstrap" +], function ( + _, + $, + Backbone, + PolicySummary, + PolicyConfigSummary, + PolicyHtml, + PolicyRowHtml, + PolicyConfigRowHtml + ) { var EntityPoliciesView = Backbone.View.extend({ template:_.template(PolicyHtml), policyRow:_.template(PolicyRowHtml), + policyConfigRow:_.template(PolicyConfigRowHtml), events:{ + "click #policies-table tr":"rowClick", "click .policy-start":"callStart", "click .policy-stop":"callStop", "click .policy-destroy":"callDestroy", +// "click .policy-config-edit":"policyConfigEdit", }, initialize:function () { this.$el.html(this.template({})) @@ -23,7 +42,9 @@ define([ this._policies = new PolicySummary.Collection() // fetch the list of policies and create a view for each one this._policies.url = this.model.getLinkByName("policies") - this.callPeriodically("entity-policies", function() { that.refresh() }, 3000) + this.callPeriodically("entity-policies", function() { + that.refresh() + }, 3000) this.refresh() }, refresh: function() { @@ -33,22 +54,75 @@ define([ }}) }, render:function () { - var that = this - var $tableBody = this.$('#policies-table tbody').empty() + var that = this, + $tbody = this.$('#policies-table tbody').empty() if (this._policies.length==0) { this.$(".has-no-policies").show(); - } else { + this.$("#policy-config").hide() + this.$("#policy-config-none-selected").hide() + } else { this.$(".has-no-policies").hide(); this._policies.each(function (policy) { - $tableBody.append(that.policyRow({ - name: policy.get("name"), - state: policy.get("state"), - summary: policy + $tbody.append(that.policyRow({ + cid:policy.get("id"), + name:policy.get("name"), + state:policy.get("state"), + summary:policy })) - }) + if (that.activePolicy) { + $("#policies-table tr[id='"+that.activePolicy+"']").addClass("selected") + that.showPolicyConfig(that.activePolicy) + } else { + this.$("#policy-config").hide() + this.$("#policy-config-none-selected").show() + } + }) } return this }, + rowClick: function(evt) { + var row = $(evt.currentTarget).closest("tr") + var id = row.attr("id") + $("#policies-table tr").removeClass("selected") + if (this.activePolicy == id) { + // deselected + this.activePolicy = null + this.$("#policy-config").hide(100) + this.$("#policy-config-none-selected").show(100) + } else { + row.addClass("selected") + this.activePolicy = id + // fetch the list of policy config entries + var policy = this._policies.get(id) + this._config = new PolicyConfigSummary.Collection() + this._config.url = policy.getLinkByName("config") + this._config.fetch({success:function () { + this.showPolicyConfig(id) + }}) + } + }, + showPolicyConfig:function (id) { + this.$("#policy-config-none-selected").hide(100) + var $tc = this.$('#policy-config-table tbody').empty() + if (this._config.length==0) { + this.$(".has-no-policy-config").show(); + } else { + this.$(".has-no-policy-config").hide(); + var policyConfigRow = _.template(PolicyConfigRowHtml) + this._config.each(function (config) { + $tc.append(policyConfigRow({ + name:config.get("name"), + description:config.get("description"), + defaultValue:config.get("defaultValue"), + reconfigurable:config.get("reconfigurable"), + })) + // TODO tooltip doesn't work on 'i' elements in table (bottom left toolbar) + $tc.find('*[rel="tooltip"]').tooltip() + }) + } + this.$("#policy-config").show(100) + this.$("#policy-config-table").show(100) + }, callStart: function(event) { this.doPost(event, "start") }, callStop: function(event) { this.doPost(event, "stop") }, callDestroy: function(event) { this.doPost(event, "destroy") }, @@ -64,5 +138,6 @@ define([ }}) } }) + return EntityPoliciesView }) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/056d4ac5/usage/jsgui/src/main/webapp/assets/js/view/policy-config-update-invoke.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/view/policy-config-update-invoke.js b/usage/jsgui/src/main/webapp/assets/js/view/policy-config-update-invoke.js new file mode 100644 index 0000000..4053d87 --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/js/view/policy-config-update-invoke.js @@ -0,0 +1,87 @@ +/** + * Render an entity effector as a modal. + */ +define([ + "underscore", "jquery", "backbone", "text!tpl/apps/effector-modal.html", "text!tpl/apps/param.html", + "text!tpl/apps/param-list.html", "brooklyn-utils" +], function (_, $, Backbone, EffectorModalHtml, ParamHtml, ParamListHtml) { + + var EffectorInvokeView = Backbone.View.extend({ + template:_.template(EffectorModalHtml), + effectorParam:_.template(ParamHtml), + effectorParamList:_.template(ParamListHtml), + events:{ + "click .invoke-effector":"invokeEffector", + "shown":"unfade" + }, + render:function () { + var that = this, params = this.model.get("parameters") + this.$el.html(this.template({ + name:this.model.get("name"), + entityName:this.options.entity.get("name"), + description:this.model.get("description")?this.model.get("description"):"" + })) + // do we have parameters to render? + if (params.length !== 0) { + this.$(".modal-body").html(this.effectorParamList({})) + // select the body of the table we just rendered and append params + var $tbody = this.$("tbody") + _(params).each(function (param) { + $tbody.append(that.effectorParam({ + name:param.name, + type:param.type, + description:param.description?param.description:"" + })) + }) + } + this.$(".modal-body").find('*[rel="tooltip"]').tooltip() + return this + }, + unfade: function() { + this.$el.fadeTo(500,1); + }, + extractParamsFromTable:function () { + var parameters = {} + // iterate over the rows + this.$(".effector-param").each(function (index) { + var key = $(this).find(".param-name").text(), + value = $(this).find(".param-value").val() + // we need to create an object out of the input so it will send as the server expects: java Map + parameters[key] = $.parseJSON(value) + }) + return parameters + }, + invokeEffector:function () { + var that = this + var url = this.model.getLinkByName("self") + var parameters = this.extractParamsFromTable() + this.$el.fadeTo(500,0.5); + $.ajax({ + type:"POST", + url:url+"?timeout=0", + data:JSON.stringify(parameters), + contentType:"application/json", + success:function (data) { + that.$el.modal("hide") + that.$el.fadeTo(500,1); + // data.id contains the task, if we wanted to switch to showing it + // NB we now timeout immediately, so always run in background + // ideally we might have a timeout of 300ms + // switch to task if it is still running + // otherwise show the answer + // ... or simpler, just switch to task, so response can be shown + }, + error: function(data) { + that.$el.fadeTo(100,1).delay(200).fadeTo(200,0.2).delay(200).fadeTo(200,1); + // TODO render the error better than poor-man's flashing + // (would just be connection error -- with timeout=0 we get a task even for invalid input) + + log("ERROR invoking effector") + log(data) + }}) + // un-delegate events + this.undelegateEvents() + } + }) + return EffectorInvokeView +}) http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/056d4ac5/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-config-modal.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-config-modal.html b/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-config-modal.html new file mode 100644 index 0000000..657551d --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-config-modal.html @@ -0,0 +1,18 @@ +<!-- modal to render policy config default value--> + +<div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h3><%= policyName %> <%= name %></h3> + + <p><%= description %></p> +</div> + +<div class="modal-body"> + <!-- what goes here --> + <p><i>No arguments required</i></p> +</div> + +<div class="modal-footer"> + <button type="button" class="btn btn-info btn-mini" data-dismiss="modal">Cancel</button> + <button type="button" class="btn btn-danger btn-mini invoke-effector">Save</button> +</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/056d4ac5/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-config-row.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-config-row.html b/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-config-row.html new file mode 100644 index 0000000..66a5aa1 --- /dev/null +++ b/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-config-row.html @@ -0,0 +1,11 @@ +<tr class="policy-config-row"> + <td><span class="policy-config-name" + rel="tooltip" title="<b><%= description %></b><br/>(<%= type %>)" data-placement="left" + ><%= name %></span></td> + <td class="policy-config-defautValue"><%= (defaultValue === undefined ? "" : defaultValue) %></td> + <td class="policy-config-action"> + <% if (reconfigurable) { %> + <button class="btn btn-info btn-mini policy-config-edit" link="<%= config.getLinkByName('edit') %>">Edit</button> + <% } %> + </td> +</tr> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/056d4ac5/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-row.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-row.html b/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-row.html index b283883..03b6836 100644 --- a/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-row.html +++ b/usage/jsgui/src/main/webapp/assets/tpl/apps/policy-row.html @@ -1,4 +1,4 @@ -<tr> +<tr class="policy-row" id="<%= cid %>"> <td class="policy-name"><%= name %></td> <td><%= state %></td> <td class="policy-action"> http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/056d4ac5/usage/jsgui/src/main/webapp/assets/tpl/apps/policy.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/apps/policy.html b/usage/jsgui/src/main/webapp/assets/tpl/apps/policy.html index 6dbc79a..1b322ac 100644 --- a/usage/jsgui/src/main/webapp/assets/tpl/apps/policy.html +++ b/usage/jsgui/src/main/webapp/assets/tpl/apps/policy.html @@ -11,3 +11,23 @@ <div class="has-no-policies for-empty-table hide"> <i>No policies currently attached to this entity</i> </div> + +<div id="policy-config"> + <table id="policy-config-table" class="table table-striped table-condensed nonDatatables"> + <thead> + <tr> + <th width="40%">Name</th> + <th width="40%">Default Value</th> + <th width="20%">Edit</th> + </tr> + </thead> + <tbody></tbody> + </table> + <div class="has-no-policy-config for-empty-table hide"> + <i>No configuration currently available on this policy</i> + </div> +</div> + +<div id="policy-config-none-selected"> + <i>Select a policy above to view or edit configuration.</i> +</div>
