You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sj...@apache.org on 2014/08/19 12:30:39 UTC
[1/9] git commit: Catalog page uses Backbone.history
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master 21a037f75 -> 226f55fa5
Catalog page uses Backbone.history
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/98ff36ff
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/98ff36ff
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/98ff36ff
Branch: refs/heads/master
Commit: 98ff36ff2e0f8f063e72194d9171fd9a88d3d393
Parents: cf1775b
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Fri Aug 8 16:33:13 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 13 17:23:16 2014 +0100
----------------------------------------------------------------------
usage/jsgui/src/main/webapp/assets/js/router.js | 20 +++++----
.../src/main/webapp/assets/js/view/catalog.js | 43 ++++++++++++++++----
2 files changed, 46 insertions(+), 17 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/98ff36ff/usage/jsgui/src/main/webapp/assets/js/router.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/router.js b/usage/jsgui/src/main/webapp/assets/js/router.js
index f72baf8..029fad7 100644
--- a/usage/jsgui/src/main/webapp/assets/js/router.js
+++ b/usage/jsgui/src/main/webapp/assets/js/router.js
@@ -19,17 +19,17 @@
define([
"brooklyn", "underscore", "jquery", "backbone",
"model/application", "model/app-tree", "model/location", "model/ha",
- "view/home", "view/application-explorer", "view/catalog", "view/apidoc", "view/script-groovy",
+ "view/home", "view/application-explorer", "view/catalog", "view/apidoc", "view/script-groovy",
"text!tpl/help/page.html","text!tpl/labs/page.html", "text!tpl/home/server-not-ha-master.html"
], function (Brooklyn, _, $, Backbone,
Application, AppTree, Location, ha,
- HomeView, ExplorerView, CatalogView, ApidocView, ScriptGroovyView,
+ HomeView, ExplorerView, CatalogView, ApidocView, ScriptGroovyView,
HelpHtml, LabsHtml, ServerNotMasterHtml) {
// TODO this initialising - customising the View prototype - should be moved,
// and perhaps expanded to include other methods from viewutils
// see discussion at https://github.com/brooklyncentral/brooklyn/pull/939
-
+
// add close method to all views for clean-up
// (NB we have to update the prototype _here_ before any views are instantiated;
// see "close" called below in "showView")
@@ -96,6 +96,7 @@ define([
'v1/applications/*trail':'applicationsPage',
'v1/applications':'applicationsPage',
'v1/locations':'catalogPage',
+ 'v1/catalog/:kind/:id':'catalogPage',
'v1/catalog':'catalogPage',
'v1/apidoc':'apidocPage',
'v1/script/groovy':'scriptGroovyPage',
@@ -150,13 +151,14 @@ define([
if (trail !== undefined) appExplorer.show(trail)
}})
},
- catalogPage:function () {
- var that = this
+ catalogPage: function (catalogItemKind, id) {
var catalogResource = new CatalogView({
- locations:that.locations,
- appRouter:that
- })
- that.showView("#application-content", catalogResource)
+ locations: this.locations,
+ appRouter: this,
+ kind: catalogItemKind,
+ id: id
+ });
+ this.showView("#application-content", catalogResource);
},
apidocPage:function () {
var apidocResource = new ApidocView({})
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/98ff36ff/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
index 0e89c58..db927b9 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
@@ -212,6 +212,7 @@ define([
activeDetailsView = this.name;
this.activeCid = cid;
var model = this.collection.get(cid);
+ Backbone.history.navigate("v1/catalog/" + this.name + "/" + model.id);
this.options.onItemSelected(model, $event);
}
},
@@ -253,21 +254,24 @@ define([
name: "applications",
onItemSelected: _.partial(this.showCatalogItem, DetailsEntityHtml),
model: Entity.Model,
- autoOpen: true
+ autoOpen: !this.options.kind || this.options.kind == "applications"
}),
"entities": new AccordionItemView({
name: "entities",
onItemSelected: _.partial(this.showCatalogItem, DetailsEntityHtml),
- model: Entity.Model
+ model: Entity.Model,
+ autoOpen: this.options.kind == "entities"
}),
"policies": new AccordionItemView({
onItemSelected: _.partial(this.showCatalogItem, DetailsGenericHtml),
- name: "policies"
+ name: "policies",
+ autoOpen: this.options.kind == "policies"
}),
"locations": new AccordionItemView({
name: "locations",
onItemSelected: _.partial(this.showCatalogItem, LocationDetailsHtml),
collection: this.options.locations,
+ autoOpen: this.options.kind == "locations",
entryTemplateArgs: function (location, index) {
return {
type: location.getPrettyName(),
@@ -284,14 +288,16 @@ define([
render: function() {
this.$el.html(_.template(CatalogPageHtml, {}));
-
- // Show empty details view to start
- this.setDetailsView(new CatalogItemDetailsView().render());
-
var parent = this.$(".catalog-accordion-parent");
_.each(this.accordion, function(child) {
parent.append(child.render().$el);
});
+ if (this.options.kind && this.options.id) {
+ this.loadAccordionItem(this.options.kind, this.options.id)
+ } else {
+ // Show empty details view to start
+ this.setDetailsView(new CatalogItemDetailsView().render());
+ }
return this
},
@@ -302,11 +308,32 @@ define([
createNewThing: function(event) {
+ loadAccordionItem: function (kind, id) {
+ if (!this.accordion[kind]) {
+ console.error("No accordion for: " + kind);
+ } else {
+ var accordion = this.accordion[kind];
+ accordion.collection.fetch()
+ .then(function() {
+ var model = accordion.collection.get(id);
+ if (!model) {
+ console.log("Accordion for " + kind + " has no element with id " + id);
+ } else {
+ activeDetailsView = kind;
+ accordion.activeCid = model.cid;
+ accordion.options.onItemSelected(model);
+ }
+ });
+ }
},
showCatalogItem: function(template, model, $target) {
this.$(".accordion-nav-row").removeClass("active");
- $target.addClass("active");
+ if ($target) {
+ $target.addClass("active");
+ } else {
+ this.$("[data-cid=" + model.cid + "]").addClass("active");
+ }
var newView = new CatalogItemDetailsView({
model: model,
template: template
[7/9] git commit: Adds inputValue and bindModelFromForm functions to
brooklyn-util.js
Posted by sj...@apache.org.
Adds inputValue and bindModelFromForm functions to brooklyn-util.js
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/7724f121
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/7724f121
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/7724f121
Branch: refs/heads/master
Commit: 7724f1216615850a54d3d8109347e3e4a8f16392
Parents: 97d6d89
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Fri Aug 8 18:56:04 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 13 17:23:17 2014 +0100
----------------------------------------------------------------------
.../webapp/assets/js/libs/brooklyn-utils.js | 34 ++++++++++++-
.../javascript/specs/brooklyn-utils-spec.js | 52 +++++++++++++++++++-
2 files changed, 82 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7724f121/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-utils.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-utils.js b/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-utils.js
index 4207823..1fc8905 100644
--- a/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-utils.js
+++ b/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-utils.js
@@ -1,6 +1,6 @@
define([
- 'underscore'
-], function (_) {
+ 'jquery', 'underscore'
+], function ($, _) {
var Util = {};
@@ -79,6 +79,36 @@ define([
return a.pathname;
};
+ /**
+ * Extracts the value of the given input. Returns true/false for for checkboxes
+ * rather than "on" or "off".
+ */
+ Util.inputValue = function($input) {
+ if ($input.attr("type") === "checkbox") {
+ return $input.is(":checked");
+ } else {
+ return $input.val();
+ }
+ };
+
+ /**
+ * Updates or initialises the given model with the values of named elements under
+ * the given element. Force-updates the model by setting silent: true.
+ */
+ Util.bindModelFromForm = function(modelOrConstructor, $el) {
+ var model = _.isFunction(modelOrConstructor) ? new modelOrConstructor() : modelOrConstructor;
+ var inputs = {};
+
+ // Look up all named elements
+ $("[name]", $el).each(function(idx, inp) {
+ var input = $(inp);
+ var name = input.attr("name");
+ inputs[name] = Util.inputValue(input);
+ });
+ model.set(inputs, { silent: true });
+ return model;
+ };
+
return Util;
});
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7724f121/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js b/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js
index ba9d32c..2c4012e 100644
--- a/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js
+++ b/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js
@@ -17,8 +17,8 @@
* under the License.
*/
define([
- 'brooklyn-utils'
-], function (Util) {
+ 'brooklyn-utils', "backbone"
+], function (Util, Backbone) {
describe('Rounding numbers', function () {
@@ -83,4 +83,52 @@ define([
expect(Util.pathOf("/a/b/c/d#e")).toBe("/a/b/c/d");
})
});
+
+ describe("inputValue", function () {
+ it("should return inputs as strings", function () {
+ expect(Util.inputValue($('<input type="text" value="bob"/>'))).toBe("bob");
+ expect(Util.inputValue($('<textarea rows="10" cols="5">content</textarea>'))).toBe("content");
+ });
+
+ it("should return true/false for checkboxes", function () {
+ var input = $('<input type="checkbox" checked/>');
+ expect(Util.inputValue(input)).toBe(true);
+ input = $('<input type="checkbox" />');
+ expect(Util.inputValue(input)).toBe(false);
+ });
+ });
+
+ describe("bindModelFromForm", function () {
+ // pretend to be a Backbone model without bringing in Backbone as a dependency
+ var TestModel = Backbone.Model.extend({
+ urlRoot: function () {
+ return "/foo/bar/";
+ }
+
+ });
+ var form = $("<form>" +
+ "<input name='id' type='input' value='text'/>" +
+ "<input name='bool' type='checkbox' checked/>" +
+ "</form>");
+
+ it("should create a new model if given a constructor", function () {
+ var model = Util.bindModelFromForm(TestModel, form);
+ expect(model instanceof TestModel).toBe(true);
+ expect(model.url()).toBe("/foo/bar/text");
+ var inputs = model.attributes;
+ expect(_.keys(inputs).length).toBe(2);
+ expect(inputs.id).toBe("text");
+ expect(inputs.bool).toBe(true);
+ });
+
+ it("should update an existing model", function () {
+ var model = new TestModel({initialAttribute: "xyz"});
+ Util.bindModelFromForm(model, form);
+ var inputs = model.attributes;
+ expect(_.keys(inputs).length).toBe(3);
+ expect(inputs.id).toBe("text");
+ expect(inputs.bool).toBe(true);
+ expect(inputs.initialAttribute).toBe("xyz");
+ });
+ });
});
[5/9] git commit: Callers to router.js can defer actions to
post-ha-status-loaded
Posted by sj...@apache.org.
Callers to router.js can defer actions to post-ha-status-loaded
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/97d6d891
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/97d6d891
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/97d6d891
Branch: refs/heads/master
Commit: 97d6d891dc7a23691e0969ca1c7dd2b200b1aafe
Parents: 98ff36f
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Fri Aug 8 16:34:29 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 13 17:23:17 2014 +0100
----------------------------------------------------------------------
usage/jsgui/src/main/webapp/assets/js/router.js | 41 +++++++++++++-------
1 file changed, 27 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/97d6d891/usage/jsgui/src/main/webapp/assets/js/router.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/router.js b/usage/jsgui/src/main/webapp/assets/js/router.js
index 029fad7..9ef8053 100644
--- a/usage/jsgui/src/main/webapp/assets/js/router.js
+++ b/usage/jsgui/src/main/webapp/assets/js/router.js
@@ -70,24 +70,37 @@ define([
this._periodicFunctions[uid] = setInterval(periodic, interval)
}
+ /**
+ * @returns {jquery.Deferred}
+ * A promise that resolves when the high availability status has been
+ * loaded. Actions to be taken on the view after it has loaded should
+ * be registered with calls to .done()
+ */
// Not just defined as a function on Router because the delay if the HA status
// hasn't loaded requires a reference to the function, which we lose if we use
// 'this.showView'.
- var showViewImpl = function (router, selector, view) {
+ function showViewImpl(router, selector, view) {
// Don't do anything until the HA status has loaded.
- if (!ha.loaded) {
- _.delay(showViewImpl, 100, router, selector, view);
- } else {
- // close the previous view - does binding clean-up and avoids memory leaks
- if (router.currentView) {
- router.currentView.close();
+ var promise = $.Deferred()
+ .done(function () {
+ // close the previous view - does binding clean-up and avoids memory leaks
+ if (router.currentView) {
+ router.currentView.close();
+ }
+ // render the view inside the selector element
+ $(selector).html(view.render().el);
+ router.currentView = view;
+ return view
+ });
+ (function isComplete() {
+ if (ha.loaded) {
+ promise.resolve();
+ } else {
+ _.defer(isComplete, 100);
}
- // render the view inside the selector element
- $(selector).html(view.render().el);
- router.currentView = view;
- return view
- }
- };
+ })();
+ return promise;
+ }
var Router = Backbone.Router.extend({
routes:{
@@ -106,7 +119,7 @@ define([
},
showView: function(selector, view) {
- showViewImpl(this, selector, view);
+ return showViewImpl(this, selector, view);
},
defaultRoute: function() {
[4/9] git commit: jsgui: Add new entities to catalogue
Posted by sj...@apache.org.
jsgui: Add new entities to catalogue
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/ee59971b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/ee59971b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/ee59971b
Branch: refs/heads/master
Commit: ee59971bc50903e7fdc690f8e3f77f44d6451773
Parents: 002f70f
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Tue Aug 12 15:13:14 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 13 17:23:17 2014 +0100
----------------------------------------------------------------------
usage/jsgui/src/main/webapp/assets/css/base.css | 7 +
usage/jsgui/src/main/webapp/assets/js/router.js | 2 +-
.../src/main/webapp/assets/js/view/catalog.js | 133 +++++++++++++++++--
.../webapp/assets/js/view/effector-invoke.js | 2 +-
.../assets/tpl/catalog/add-catalog-entry.html | 33 +++++
.../webapp/assets/tpl/catalog/add-entity.html | 30 +++++
.../main/webapp/assets/tpl/catalog/page.html | 48 +------
.../javascript/specs/brooklyn-utils-spec.js | 1 -
8 files changed, 195 insertions(+), 61 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee59971b/usage/jsgui/src/main/webapp/assets/css/base.css
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/css/base.css b/usage/jsgui/src/main/webapp/assets/css/base.css
index c4d74df..8c50bf8 100644
--- a/usage/jsgui/src/main/webapp/assets/css/base.css
+++ b/usage/jsgui/src/main/webapp/assets/css/base.css
@@ -1134,6 +1134,13 @@ tr.app-add-wizard-config-entry {
padding-bottom: 180px;
text-align: center;
}
+.catalog-save-error {
+ background-color: #f2dede;
+ /* margin matches bootstrap input margin-bottom. */
+ margin: 9px 0 0 0;
+ padding: 7px;
+ border-radius: 3px;
+}
.float-right {
float: right;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee59971b/usage/jsgui/src/main/webapp/assets/js/router.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/router.js b/usage/jsgui/src/main/webapp/assets/js/router.js
index 9ef8053..c52c220 100644
--- a/usage/jsgui/src/main/webapp/assets/js/router.js
+++ b/usage/jsgui/src/main/webapp/assets/js/router.js
@@ -109,7 +109,7 @@ define([
'v1/applications/*trail':'applicationsPage',
'v1/applications':'applicationsPage',
'v1/locations':'catalogPage',
- 'v1/catalog/:kind/:id':'catalogPage',
+ 'v1/catalog/:kind(/:id)':'catalogPage',
'v1/catalog':'catalogPage',
'v1/apidoc':'apidocPage',
'v1/script/groovy':'scriptGroovyPage',
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee59971b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
index db927b9..4c38b5a 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
@@ -17,18 +17,21 @@
* under the License.
*/
define([
- "underscore", "jquery", "backbone", "formatJson",
+ "underscore", "jquery", "backbone", "formatJson", "brooklyn",
"model/location", "model/entity",
- "view/catalog-add-location-modal",
"text!tpl/catalog/page.html",
"text!tpl/catalog/details-entity.html",
"text!tpl/catalog/details-generic.html",
- "text!tpl/catalog/nav-entry.html",
"text!tpl/catalog/details-location.html",
+ "text!tpl/catalog/add-catalog-entry.html",
+ "text!tpl/catalog/add-entity.html",
+ "text!tpl/catalog/nav-entry.html",
"bootstrap", "jquery-form"
-], function(_, $, Backbone, FormatJSON, Location, Entity, AddLocationModalView,
- CatalogPageHtml, DetailsEntityHtml, DetailsGenericHtml, EntryHtml, LocationDetailsHtml) {
+], function(_, $, Backbone, FormatJSON, Brooklyn,
+ Location, Entity,
+ CatalogPageHtml, DetailsEntityHtml, DetailsGenericHtml, LocationDetailsHtml,
+ AddCatalogEntryHtml, AddEntityHtml, EntryHtml) {
// Holds the currently active details type, e.g. applications, policies. Bit of a workaround
// to share the active view with all instances of AccordionItemView, so clicking the 'reload
@@ -116,6 +119,89 @@ define([
}
});
+ var AddCatalogEntryView = Backbone.View.extend({
+ template: _.template(AddCatalogEntryHtml),
+ events: {
+ "click .show-context": "showContext"
+ },
+ initialize: function() {
+ _.bindAll(this);
+ },
+ render: function (initialView) {
+ this.$el.html(this.template());
+ if (initialView) {
+ this.$("[data-context='"+initialView+"']").addClass("active");
+ this.showFormForType(initialView)
+ }
+ return this;
+ },
+ beforeClose: function () {
+ if (this.contextView) {
+ this.contextView.close();
+ }
+ },
+ showContext: function(event) {
+ var $event = $(event.currentTarget);
+ var context = $event.data("context");
+ if (this.context !== context) {
+ if (this.contextView) {
+ this.contextView.close();
+ }
+ this.showFormForType(context)
+ }
+ },
+ showFormForType: function (type) {
+ this.context = type;
+ if (type == "entity") {
+ this.contextView = newEntityForm(this.options.parent);
+ } else if (type !== undefined) {
+ console.log("unknown catalog type " + type);
+ this.showFormForType("entity");
+ return;
+ }
+ Backbone.history.navigate("/v1/catalog/new/" + type);
+ this.$("#catalog-add-form").html(this.contextView.$el);
+ }
+ });
+
+ function newEntityForm(parent) {
+ return new Brooklyn.view.Form({
+ template: AddEntityHtml,
+ onSubmit: function (model) {
+ console.log("Submit entity", model.get("yaml"));
+ var submitButton = this.$(".catalog-submit-button");
+ // "loading" is an indicator to Bootstrap, not a string to display
+ submitButton.button("loading");
+ var self = this;
+ var options = {
+ url: "/v1/catalog/",
+ data: model.get("yaml"),
+ processData: false,
+ type: "post"
+ };
+ $.ajax(options)
+ .done(function (data, status, xhr) {
+ // Can extract location of new item with:
+ //model.url = Brooklyn.util.pathOf(xhr.getResponseHeader("Location"));
+ parent.loadAccordionItem("entities", data.id);
+ })
+ .fail(function (xhr, status, error) {
+ var message;
+ try {
+ message = JSON.parse(xhr.responseText).message;
+ } catch (e) {
+ message = "Error adding catalog item: " + error;
+ }
+ submitButton.button("reset");
+ self.$(".catalog-save-error")
+ .removeClass("hide")
+ .find(".catalog-error-message")
+ .html(message);
+ });
+ }
+ });
+ }
+
var Catalog = Backbone.Collection.extend({
initialize: function(models, options) {
this.name = options["name"];
@@ -225,6 +311,14 @@ define([
} else {
body.slideUp('fast')
}
+ },
+
+ show: function() {
+ var body = this.$(".accordion-body");
+ var hidden = this.hidden = body.css("display") == "none";
+ if (hidden) {
+ body.removeClass("hide").slideDown('fast');
+ }
}
});
@@ -236,11 +330,7 @@ define([
events: {
'click .refresh':'refresh',
- 'click #add-new-thing':'createNewThing',
- 'click #add-new-entity':'addNewCatalogResource',
- 'click #new-entity-submit':'newEntitySubmit',
- 'click #add-new-location':'addLocation',
- 'click .delete-location':'deleteLocation'
+ 'click #add-new-thing': 'createNewThing'
},
initialize: function() {
@@ -292,7 +382,9 @@ define([
_.each(this.accordion, function(child) {
parent.append(child.render().$el);
});
- if (this.options.kind && this.options.id) {
+ if (this.options.kind === "new") {
+ this.createNewThing(this.options.id);
+ } else if (this.options.kind && this.options.id) {
this.loadAccordionItem(this.options.kind, this.options.id)
} else {
// Show empty details view to start
@@ -306,7 +398,22 @@ define([
_.invoke(this.accordion, 'refresh');
},
- createNewThing: function(event) {
+ createNewThing: function (type) {
+ // Discard if it's the jquery event object.
+ if (!_.isString(type)) {
+ type = undefined;
+ }
+ var viewName = "createNewThing";
+ if (!type) {
+ Backbone.history.navigate("/v1/catalog/new");
+ }
+ activeDetailsView = viewName;
+ this.$(".accordion-nav-row").removeClass("active");
+ var newView = new AddCatalogEntryView({
+ parent: this
+ }).render(type);
+ this.setDetailsView(newView);
+ },
loadAccordionItem: function (kind, id) {
if (!this.accordion[kind]) {
@@ -322,6 +429,7 @@ define([
activeDetailsView = kind;
accordion.activeCid = model.cid;
accordion.options.onItemSelected(model);
+ accordion.show();
}
});
}
@@ -353,7 +461,6 @@ define([
}
this.detailsView = view;
}
-
});
return CatalogResourceView
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee59971b/usage/jsgui/src/main/webapp/assets/js/view/effector-invoke.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/effector-invoke.js b/usage/jsgui/src/main/webapp/assets/js/view/effector-invoke.js
index af25019..bf93cc7 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/effector-invoke.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/effector-invoke.js
@@ -63,7 +63,7 @@ define([
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"):"",
+ description:this.model.get("description")?this.model.get("description"):""
}))
// do we have parameters to render?
if (params.length !== 0) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee59971b/usage/jsgui/src/main/webapp/assets/tpl/catalog/add-catalog-entry.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/add-catalog-entry.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/add-catalog-entry.html
new file mode 100644
index 0000000..16fb9ee
--- /dev/null
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/add-catalog-entry.html
@@ -0,0 +1,33 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you 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="catalog-details">
+
+ <h2>Add a new...</h2>
+ <br/>
+
+ <div data-toggle="buttons-radio">
+ <button class="btn btn-large show-context" data-context="entity">Entity</button>
+ </div>
+
+ <hr/>
+
+ <div id="catalog-add-form">
+ <div class="context">Select the type you wish to add</div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee59971b/usage/jsgui/src/main/webapp/assets/tpl/catalog/add-entity.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/add-entity.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/add-entity.html
new file mode 100644
index 0000000..9c64e90
--- /dev/null
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/add-entity.html
@@ -0,0 +1,30 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<form>
+ <label for="new-blueprint">Enter blueprint:</label>
+ <textarea id='new-blueprint' name='yaml' rows='5' cols='15'></textarea>
+
+ <button class='catalog-submit-button btn' data-loading-text='Saving...'>Submit</button>
+ <p class="catalog-save-error hide">
+ <span class="alert-error">
+ <strong>Error:</strong><br/>
+ <span class="catalog-error-message"></span>
+ </span>
+ </p>
+</form>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee59971b/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
index 2c6a156..dc1b102 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
@@ -16,16 +16,15 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
-
-<!-- Catalog page template -->
<div id="catalog-resource">
<div class="row row-fluid">
<div class="span4" id="accord">
<div class="navbar_top">
<h3>Catalog</h3>
-
<div class="apps-tree-toolbar">
- <i class="icon-br-refresh refresh handy"/>
+ <i id="add-new-thing" class="icon-br-plus-sign handy"></i>
+
+ <i class="icon-br-refresh refresh handy"></i>
</div>
</div>
<div class="navbar_main_wrapper">
@@ -36,44 +35,3 @@ under the License.
<div class="span8" id="details"></div>
</div>
</div>
-
-<div class="modal hide fade" id="new-entity-modal">
- <form class="form-vertical" id="new-entity-form">
-
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal">x</button>
- <h3>Upload Catalog Resource</h3>
- </div>
-
- <div class="modal-body">
-
- <fieldset>
- <div class="row">
- <div class="span5">
-
- <label for="groovy-code" class="control-label">Select the source code file for the template/entity/policy you wish to upload.</label>
- <br/>
- <div class="control-group">
- <div class="controls">
- <input id="groovy-code" name="groovyCode" type="file" class="input-large">
- </div>
- </div>
- <br/>
- </div>
- </div>
- </fieldset>
- <div id="info-box">
- <p><span class="label label-info">Note:</span> This window will close automatically when file is
- uploaded</p>
- </div>
- </div>
-
- <div class="modal-footer form-actions">
- <button class="btn" data-dismiss="modal" type="button">Close</button>
- <button id="new-entity-submit" class="btn btn-primary" type="button">Save</button>
- </div>
-
- </form>
-</div>
-
-<div class="modal hide fade" id="new-location-modal"></div>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee59971b/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js b/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js
index 2c4012e..ab9566d 100644
--- a/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js
+++ b/usage/jsgui/src/test/javascript/specs/brooklyn-utils-spec.js
@@ -104,7 +104,6 @@ define([
urlRoot: function () {
return "/foo/bar/";
}
-
});
var form = $("<form>" +
"<input name='id' type='input' value='text'/>" +
[3/9] git commit: Fix display of generic details and make entity
details messages consistent
Posted by sj...@apache.org.
Fix display of generic details and make entity details messages consistent
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/68ae2354
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/68ae2354
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/68ae2354
Branch: refs/heads/master
Commit: 68ae235499d22e2ac7cfe9cdbe724a6b83314cda
Parents: 1a69146
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Thu Aug 7 18:00:43 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 13 17:23:16 2014 +0100
----------------------------------------------------------------------
.../assets/tpl/catalog/details-entity.html | 10 +++++---
.../assets/tpl/catalog/details-generic.html | 27 +++++++++++++-------
2 files changed, 25 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/68ae2354/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
index dac12f5..eaab99b 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
@@ -52,7 +52,7 @@ under the License.
<% } else if (!model.get("config")) { %>
<p>Loading...</p>
<% } else if (_.isEmpty(model.get("config"))) { %>
- <p>None available</p>
+ <p>No configuration</p>
<% } else { %>
<% var skip = [
'name',
@@ -90,7 +90,9 @@ under the License.
<div class="accordion-inner">
<% if (model.error) { %>
<p><i class="icon-exclamation-sign"></i> Could not load sensors</p>
- <% } else if (!model.get("sensors") || _.isEmpty(model.get("sensors"))) { %>
+ <% } else if (!model.get("sensors")) { %>
+ <p>Loading...</p>
+ <% } else if (_.isEmpty(model.get("sensors"))) { %>
<p>No sensors</p>
<% } else { %>
<table class="table table-striped table-condensed nonDatatables">
@@ -125,7 +127,9 @@ under the License.
<div class="accordion-inner">
<% if (model.error) { %>
<p><i class="icon-exclamation-sign"></i> Could not load effectors</p>
- <% } else if (!model.get("effectors") || _.isEmpty(model.get("effectors"))) { %>
+ <% } else if (!model.get("effectors")) { %>
+ <p>Loading...</p>
+ <% } else if (_.isEmpty(model.get("effectors"))) { %>
<p>No effectors</p>
<% } else { %>
<% _.each(model.get("effectors"), function(object, index) { %>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/68ae2354/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-generic.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-generic.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-generic.html
index 4277ac6..f57500e 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-generic.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-generic.html
@@ -17,16 +17,25 @@ specific language governing permissions and limitations
under the License.
-->
-<div class="catalog-details-generic">
+<div class="catalog-details">
-<% if ((typeof title !== 'undefined') && (title.length > 0)) { %>
- <h3><%= title %></h3>
-<% } %>
+ <% if (model.get("name") !== undefined) { %>
+ <h2><%= model.get("name") %></h2>
+ <% } else if (model.get("type") !== undefined) { %>
+ <h2><%= model.get("type") %></h2>
+ <% } %>
-<% if (typeof json === 'undefined') { %>
- <i>Loading...</i>
-<% } else { %>
- <textarea readonly="readonly" rows="25" style="width:100%;"><%= json %></textarea>
-<% } %>
+ <dl>
+ <% _.each(model.attributes, function(value, key) { %>
+ <% if (value) { %>
+ <dt><%= key %></dt>
+ <% if (_.isObject(value)) { %>
+ <dd>Not shown: is a complex object</dd>
+ <% } else { %>
+ <dd><%= value %></dd>
+ <% } %>
+ <% } %>
+ <% }) %>
+ </dl>
</div>
[9/9] git commit: This closes #116
Posted by sj...@apache.org.
This closes #116
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/226f55fa
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/226f55fa
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/226f55fa
Branch: refs/heads/master
Commit: 226f55fa5678f3533a187cb646c8f57be107cfcb
Parents: 21a037f ee59971
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Tue Aug 19 11:03:41 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Aug 19 11:03:41 2014 +0100
----------------------------------------------------------------------
usage/jsgui/src/main/webapp/assets/css/base.css | 7 +
usage/jsgui/src/main/webapp/assets/js/config.js | 1 +
.../webapp/assets/js/libs/brooklyn-utils.js | 34 +-
.../main/webapp/assets/js/libs/brooklyn-view.js | 74 ++++
.../src/main/webapp/assets/js/libs/brooklyn.js | 15 +-
usage/jsgui/src/main/webapp/assets/js/router.js | 61 ++--
.../src/main/webapp/assets/js/view/catalog.js | 359 +++++++++++++------
.../webapp/assets/js/view/effector-invoke.js | 2 +-
.../assets/tpl/catalog/add-catalog-entry.html | 33 ++
.../webapp/assets/tpl/catalog/add-entity.html | 30 ++
.../assets/tpl/catalog/details-entity.html | 10 +-
.../assets/tpl/catalog/details-generic.html | 27 +-
.../webapp/assets/tpl/catalog/nav-entry.html | 2 +-
.../main/webapp/assets/tpl/catalog/page.html | 53 +--
usage/jsgui/src/test/javascript/config.txt | 1 +
.../src/test/javascript/specs/brooklyn-spec.js | 81 +++++
.../javascript/specs/brooklyn-utils-spec.js | 51 ++-
.../main/java/brooklyn/rest/api/CatalogApi.java | 15 +-
18 files changed, 632 insertions(+), 224 deletions(-)
----------------------------------------------------------------------
[2/9] git commit: Simplifies showing catalogue details a bit.
Posted by sj...@apache.org.
Simplifies showing catalogue details a bit.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/cf1775be
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/cf1775be
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/cf1775be
Branch: refs/heads/master
Commit: cf1775bef90532be3f365ece3ceed8978f1c3105
Parents: 68ae235
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Fri Aug 8 14:52:08 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 13 17:23:16 2014 +0100
----------------------------------------------------------------------
.../src/main/webapp/assets/js/view/catalog.js | 203 +++++++++----------
.../webapp/assets/tpl/catalog/nav-entry.html | 2 +-
.../main/webapp/assets/tpl/catalog/page.html | 5 -
3 files changed, 96 insertions(+), 114 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf1775be/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
index 6f8d059..0e89c58 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
@@ -30,11 +30,14 @@ define([
], function(_, $, Backbone, FormatJSON, Location, Entity, AddLocationModalView,
CatalogPageHtml, DetailsEntityHtml, DetailsGenericHtml, EntryHtml, LocationDetailsHtml) {
- // Holds the currently active details type, e.g. applications, policies
- var activeDetails;
+ // Holds the currently active details type, e.g. applications, policies. Bit of a workaround
+ // to share the active view with all instances of AccordionItemView, so clicking the 'reload
+ // catalog' button (handled by the parent of the AIVs) does not apply the 'active' class to
+ // more than one element.
+ var activeDetailsView;
// TODO: Loading item's details should perform page navigation
- var DetailsView = Backbone.View.extend({
+ var CatalogItemDetailsView = Backbone.View.extend({
events: {
"click .delete": "deleteItem"
@@ -42,36 +45,50 @@ define([
initialize: function() {
_.bindAll(this);
+ this.options.template = _.template(this.options.template || DetailsGenericHtml);
},
- render: function(extraMessage) {
+ render: function() {
+ if (!this.options.model) {
+ return this.renderEmpty();
+ } else {
+ return this.renderDetails();
+ }
+ },
+
+ renderEmpty: function(extraMessage) {
this.$el.html("<div class='catalog-details'>" +
"<h3>Select an entry on the left</h3>" +
(extraMessage ? extraMessage : "") +
"</div>");
+ return this;
},
- show: function(model, template) {
- // Keep the previously open section open between items
- var open = this.$(".in").attr("id");
- var newHtml = $(template({model: model}));
- $(newHtml).find("#"+open).addClass("in");
- this.$el.html(newHtml);
-
- // rewire events. previous callbacks are removed automatically.
- this.delegateEvents()
- },
+ renderDetails: function() {
+ var that = this,
+ model = this.options.model,
+ template = this.options.template;
+ var show = function() {
+ // Keep the previously open section open between items. Duplication between
+ // here and setDetailsView, below. This case handles view refreshes from this
+ // view directly (e.g. when indicating an error), below handles keeping the
+ // right thing open when navigating from view to view.
+ var open = this.$(".in").attr("id");
+ var newHtml = $(template({model: model}));
+ $(newHtml).find("#"+open).addClass("in");
+ that.$el.html(newHtml);
+ // rewire events. previous callbacks are removed automatically.
+ that.delegateEvents()
+ };
- showDetailsFor: function(model, template) {
this.activeModel = model;
- var that = this;
// Load the view with currently available data and refresh once the load is complete.
// Only refreshes the view if the model changes and the user hasn't selected another
// item while the load was executing.
- this.show(model, template);
+ show();
model.on("change", function() {
if (that.activeModel.cid === model.cid) {
- that.show(model, template);
+ show();
}
});
model.fetch()
@@ -79,13 +96,14 @@ define([
console.log("error loading", model.id, ":", errorThrown);
if (that.activeModel.cid === model.cid) {
model.error = true;
- that.show(model, template);
+ show();
}
})
// Runs after the change event fires, or after the xhr completes
.always(function () {
model.off("change");
});
+ return this;
},
deleteItem: function(event) {
@@ -94,7 +112,7 @@ define([
// removal. Useful if delete fails for e.g. lack of entitlement.
this.activeModel.destroy();
var displayName = $(event.currentTarget).data("name");
- this.render(displayName ? "Deleted " + displayName : "");
+ this.renderEmpty(displayName ? "Deleted " + displayName : "");
}
});
@@ -111,10 +129,6 @@ define([
}
});
- var accordionBodyTemplate = _.template(
- "<div class='accordion-head capitalized'><%= name %></div>" +
- "<div class='accordion-body' style='display: <%= display %>'></div>");
-
/** Use to fill single accordion view list. */
var AccordionItemView = Backbone.View.extend({
tag: "div",
@@ -123,21 +137,25 @@ define([
'click .accordion-head': 'toggle',
'click .accordion-nav-row': 'showDetails'
},
+ bodyTemplate: _.template(
+ "<div class='accordion-head capitalized'><%= name %></div>" +
+ "<div class='accordion-body' style='display: <%= display %>'></div>"),
initialize: function() {
_.bindAll(this);
this.name = this.options.name;
if (!this.name) {
throw new Error("Name should have been given for accordion entry");
+ } else if (!this.options.onItemSelected) {
+ throw new Error("onItemSelected(model, element) callback should have been given for accordion entry");
}
// Generic templates
this.template = _.template(this.options.template || EntryHtml);
- this.detailsTemplate = _.template(this.options.detailsTemplate || DetailsGenericHtml);
// Returns template applied to function arguments. Alter if collection altered.
// Will be run in the context of the AccordionItemView.
- this.templateArgs = this.options.templateArgs || function(model, index) {
+ this.entryTemplateArgs = this.options.entryTemplateArgs || function(model, index) {
return {type: model.get("type"), id: model.get("id")};
};
@@ -160,7 +178,7 @@ define([
},
render: function() {
- this.$el.html(accordionBodyTemplate({
+ this.$el.html(this.bodyTemplate({
name: this.name,
display: this.options.autoOpen ? "block" : "none"
}));
@@ -169,38 +187,32 @@ define([
},
renderEntries: function() {
+ var name = this.name, active = this.activeCid;
var templater = function(model, index) {
- var args = _.extend({cid: model.cid}, this.templateArgs(model));
+ var args = _.extend({
+ cid: model.cid,
+ extraClasses: (activeDetailsView == name && model.cid == active) ? "active" : ""
+ }, this.entryTemplateArgs(model));
return this.template(args);
};
var elements = this.collection.map(templater, this);
this.$(".accordion-body")
.empty()
.append(elements.join(''));
- // Rehighlight active model
- if (this.activeCid && activeDetails === this.name) {
- $(".accordion-nav-row").removeClass("active");
- this.setActiveItem(this.$("[data-cid='"+this.activeCid+"'"));
- }
},
refresh: function() {
this.collection.fetch();
},
- setActiveItem: function($element) {
- $(".accordion-nav-row").removeClass("active");
- $element.addClass("active");
- activeDetails = this.name;
- },
-
showDetails: function(event) {
var $event = $(event.currentTarget);
- if (!$event.hasClass("active")) {
- this.setActiveItem($event);
- var cid = this.activeCid = $(event.currentTarget).data("cid");
+ var cid = $event.data("cid");
+ if (activeDetailsView !== this.name || this.activeCid !== cid) {
+ activeDetailsView = this.name;
+ this.activeCid = cid;
var model = this.collection.get(cid);
- this.options.details.showDetailsFor(model, this.detailsTemplate);
+ this.options.onItemSelected(model, $event);
}
},
@@ -208,15 +220,14 @@ define([
var body = this.$(".accordion-body");
var hidden = this.hidden = body.css("display") == "none";
if (hidden) {
- this.$el.addClass('active');
body.removeClass("hide").slideDown('fast');
} else {
- this.$el.removeClass('active');
body.slideUp('fast')
}
}
});
+ // Controls whole page. Parent of accordion items and details view.
var CatalogResourceView = Backbone.View.extend({
tagName:"div",
className:"container container-fluid",
@@ -234,50 +245,49 @@ define([
initialize: function() {
$(".nav1").removeClass("active");
$(".nav1_catalog").addClass("active");
- this.detailsView = new DetailsView();
- this.accordion = this.options.accordion || [
- new AccordionItemView({
+ // Important that bind happens before accordion object is created. If it happens after
+ // `this' will not be set correctly for the onItemSelected callbacks.
+ _.bindAll(this);
+ this.accordion = this.options.accordion || {
+ "applications": new AccordionItemView({
name: "applications",
- details: this.detailsView,
- detailsTemplate: DetailsEntityHtml,
+ onItemSelected: _.partial(this.showCatalogItem, DetailsEntityHtml),
model: Entity.Model,
autoOpen: true
}),
- new AccordionItemView({
+ "entities": new AccordionItemView({
name: "entities",
- details: this.detailsView,
- detailsTemplate: DetailsEntityHtml,
+ onItemSelected: _.partial(this.showCatalogItem, DetailsEntityHtml),
model: Entity.Model
}),
- new AccordionItemView({
- name: "policies",
- detailsTemplate: DetailsGenericHtml,
- details: this.detailsView
+ "policies": new AccordionItemView({
+ onItemSelected: _.partial(this.showCatalogItem, DetailsGenericHtml),
+ name: "policies"
}),
- new AccordionItemView({
+ "locations": new AccordionItemView({
name: "locations",
- details: this.detailsView,
- detailsTemplate: LocationDetailsHtml,
+ onItemSelected: _.partial(this.showCatalogItem, LocationDetailsHtml),
collection: this.options.locations,
- templateArgs: function(location, index) {
+ entryTemplateArgs: function (location, index) {
return {
type: location.getPrettyName(),
id: location.getLinkByName("self")
};
}
})
- ];
- _.bindAll(this);
+ };
},
beforeClose: function() {
_.invoke(this.accordion, 'close');
},
- render: function(eventName) {
+ render: function() {
this.$el.html(_.template(CatalogPageHtml, {}));
- this.detailsView.$el = this.$("#details");
- this.detailsView.render();
+
+ // Show empty details view to start
+ this.setDetailsView(new CatalogItemDetailsView().render());
+
var parent = this.$(".catalog-accordion-parent");
_.each(this.accordion, function(child) {
parent.append(child.render().$el);
@@ -291,53 +301,30 @@ define([
},
createNewThing: function(event) {
- var that = this;
- if (_.contains(that.genericTabs, that.activeAccordion)) {
- that.addNewCatalogResource(event)
- } else if (that.activeAccordion=='locations') {
- that.addLocation(event)
- } else {
- that.$('#accordion-empty-to-create-info-message').slideDown('slow').delay(2000).slideUp('slow')
- }
- },
- addNewCatalogResource: function(event) {
- $('#new-entity-modal').modal('show')
},
- newEntitySubmit: function(event) {
- var $entityForm = $('#new-entity-form'),
- $entityModal = $('#new-entity-modal'),
- self = this;
- $entityModal.fadeTo(500,0.5);
- var options = {
- url:'/v1/catalog/',
- type:'post',
- success: function(data) {
- $entityModal.modal('hide');
- $entityModal.fadeTo(500,1);
- self.refresh()
- },
- error: function(data) {
- $entityModal.fadeTo(100,1).delay(200).fadeTo(200,0.2).delay(200).fadeTo(200,1);
- // TODO render the error (want better feedback than this poor-man's flashing)
- }
- };
- $entityForm.ajaxSubmit(options);
- return false
- },
-
- addLocation: function(event) {
- var locationModalView = new AddLocationModalView({
- model:new Location.Model(),
- appRouter:this.options.appRouter
- });
- this.$('#new-location-modal').replaceWith(locationModalView.render().$el);
- this.$('#new-location-modal').modal('show');
+ showCatalogItem: function(template, model, $target) {
+ this.$(".accordion-nav-row").removeClass("active");
+ $target.addClass("active");
+ var newView = new CatalogItemDetailsView({
+ model: model,
+ template: template
+ }).render();
+ this.setDetailsView(newView)
},
- deleteLocation: function(event) {
- this.model.get(event.currentTarget['id']).destroy();
+ setDetailsView: function(view) {
+ this.$("#details").html(view.el);
+ if (this.detailsView) {
+ // Try to re-open sections that were previously visible.
+ var openedItem = this.detailsView.$(".in").attr("id");
+ if (openedItem) {
+ view.$("#" + openedItem).addClass("in");
+ }
+ this.detailsView.close();
+ }
+ this.detailsView = view;
}
});
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf1775be/usage/jsgui/src/main/webapp/assets/tpl/catalog/nav-entry.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/nav-entry.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/nav-entry.html
index 922f254..9c6dcbf 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/catalog/nav-entry.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/nav-entry.html
@@ -16,4 +16,4 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
-<div data-cid="<%= cid %>" class="accordion-nav-row"><%= type %></div>
+<div data-cid="<%= cid %>" class="accordion-nav-row <%= extraClasses %>"><%= type %></div>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf1775be/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
index a945329..2c6a156 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
@@ -29,11 +29,6 @@ under the License.
</div>
</div>
<div class="navbar_main_wrapper">
- <div id="accordion-empty-to-create-info-message" class="label-message hide">
- <div class="label-important full-width">ERROR</div>
- No category selected.
- Select the category of the item type you wish to add.
- </div>
<div class="catalog-accordion-parent catalog-accordion-wrapper"></div>
</div>
</div>
[8/9] git commit: Remove @Consumes(json) from CatalogApi class
Posted by sj...@apache.org.
Remove @Consumes(json) from CatalogApi class
It's untrue.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/a1b6a0d6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/a1b6a0d6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/a1b6a0d6
Branch: refs/heads/master
Commit: a1b6a0d645320359ce5824292000978c11540635
Parents: 7724f12
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Tue Aug 12 15:08:49 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 13 17:23:17 2014 +0100
----------------------------------------------------------------------
.../src/main/java/brooklyn/rest/api/CatalogApi.java | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1b6a0d6/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
index 0642612..0888e90 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/CatalogApi.java
@@ -39,7 +39,6 @@ import java.util.List;
@Path("/v1/catalog")
@Apidoc("Catalog")
@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
public interface CatalogApi {
@POST
@@ -82,9 +81,9 @@ public interface CatalogApi {
@ApiOperation(value = "List available entity types optionally matching a query", responseClass = "CatalogItemSummary", multiValueResponse = true)
public List<CatalogItemSummary> listEntities(
@ApiParam(name = "regex", value = "Regular expression to search for")
- final @QueryParam("regex") @DefaultValue("") String regex,
+ @QueryParam("regex") @DefaultValue("") String regex,
@ApiParam(name = "fragment", value = "Substring case-insensitive to search for")
- final @QueryParam("fragment") @DefaultValue("") String fragment
+ @QueryParam("fragment") @DefaultValue("") String fragment
) ;
@GET
@@ -92,9 +91,9 @@ public interface CatalogApi {
@ApiOperation(value = "Fetch a list of application templates optionally matching a query", responseClass = "CatalogItemSummary", multiValueResponse = true)
public List<CatalogItemSummary> listApplications(
@ApiParam(name = "regex", value = "Regular expression to search for")
- final @QueryParam("regex") @DefaultValue("") String regex,
+ @QueryParam("regex") @DefaultValue("") String regex,
@ApiParam(name = "fragment", value = "Substring case-insensitive to search for")
- final @QueryParam("fragment") @DefaultValue("") String fragment
+ @QueryParam("fragment") @DefaultValue("") String fragment
) ;
@GET
@@ -122,9 +121,9 @@ public interface CatalogApi {
@ApiOperation(value = "List available policies optionally matching a query", responseClass = "CatalogItemSummary", multiValueResponse = true)
public List<CatalogItemSummary> listPolicies(
@ApiParam(name = "regex", value = "Regular expression to search for")
- final @QueryParam("regex") @DefaultValue("") String regex,
+ @QueryParam("regex") @DefaultValue("") String regex,
@ApiParam(name = "fragment", value = "Substring case-insensitive to search for")
- final @QueryParam("fragment") @DefaultValue("") String fragment
+ @QueryParam("fragment") @DefaultValue("") String fragment
) ;
@GET
@@ -146,7 +145,7 @@ public interface CatalogApi {
@Produces("application/image")
public Response getIcon(
@ApiParam(name = "itemId", value = "ID of catalog item (application, entity, policy)")
- final @PathParam("itemId") @DefaultValue("") String itemId
+ @PathParam("itemId") @DefaultValue("") String itemId
) ;
}
[6/9] git commit: jsgui: Adds brooklyn views module
Posted by sj...@apache.org.
jsgui: Adds brooklyn views module
Contains GenericForm object that binds inputs to given model
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/002f70f3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/002f70f3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/002f70f3
Branch: refs/heads/master
Commit: 002f70f35c20a55e2f41cbdcb4cec40870ea7c0f
Parents: a1b6a0d
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Tue Aug 12 15:10:43 2014 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Aug 13 17:23:17 2014 +0100
----------------------------------------------------------------------
usage/jsgui/src/main/webapp/assets/js/config.js | 1 +
.../main/webapp/assets/js/libs/brooklyn-view.js | 74 ++++++++++++++++++
.../src/main/webapp/assets/js/libs/brooklyn.js | 15 ++--
usage/jsgui/src/test/javascript/config.txt | 1 +
.../src/test/javascript/specs/brooklyn-spec.js | 81 ++++++++++++++++++++
5 files changed, 166 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/002f70f3/usage/jsgui/src/main/webapp/assets/js/config.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/config.js b/usage/jsgui/src/main/webapp/assets/js/config.js
index 6a7d6df..8cff069 100644
--- a/usage/jsgui/src/main/webapp/assets/js/config.js
+++ b/usage/jsgui/src/main/webapp/assets/js/config.js
@@ -39,6 +39,7 @@ require.config({
"moment":"libs/moment.min",
"handlebars":"libs/handlebars-1.0.rc.1",
"brooklyn":"libs/brooklyn",
+ "brooklyn-view":"libs/brooklyn-view",
"brooklyn-utils":"libs/brooklyn-utils",
"datatables-extensions":"libs/dataTables.extensions",
"googlemaps":"view/googlemaps",
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/002f70f3/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-view.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-view.js b/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-view.js
new file mode 100644
index 0000000..8965e81
--- /dev/null
+++ b/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn-view.js
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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([
+ "jquery", "underscore", "backbone", "brooklyn-utils"
+], function (
+ $, _, Backbone, Util
+) {
+
+ /**
+ * A form that listens to modifications to its inputs, maintaining a model that is
+ * submitted when a button with class 'submit' is clicked.
+ */
+ var GenericForm = Backbone.View.extend({
+ events: {
+ "change": "onChange",
+ "submit": "onSubmit"
+ },
+
+ initialize: function() {
+ if (!this.options.template) {
+ throw new Error("template required by GenericForm");
+ } else if (!this.options.onSubmit) {
+ throw new Error("onSubmit function required by GenericForm");
+ }
+ this.onSubmitCallback = this.options.onSubmit;
+ this.template = _.template(this.options.template);
+ this.model = new (this.options.model || Backbone.Model);
+ _.bindAll(this, "onSubmit", "onChange");
+ this.render();
+ },
+
+ render: function() {
+ this.$el.html(this.template());
+ // Initialise the model with existing values
+ Util.bindModelFromForm(this.model, this.$el);
+ return this;
+ },
+
+ onChange: function(e) {
+ var target = $(e.target);
+ var name = target.attr("name");
+ this.model.set(name, Util.inputValue(target), { silent: true });
+ },
+
+ onSubmit: function(e) {
+ e.preventDefault();
+ // TODO: Could validate model
+ this.onSubmitCallback(this.model);
+ return false;
+ }
+
+ });
+
+ return {
+ Form: GenericForm
+ };
+
+});
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/002f70f3/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn.js b/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn.js
index d8abd14..9594d2d 100644
--- a/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn.js
+++ b/usage/jsgui/src/main/webapp/assets/js/libs/brooklyn.js
@@ -1,6 +1,7 @@
/** Client configuration. */
define([
-], function () {
+ "brooklyn-view", "brooklyn-utils"
+], function (BrooklynViews, BrooklynUtils) {
/**
* Makes the console API safe to use:
@@ -38,13 +39,15 @@ define([
}
})();
- var Config = {
- "refresh":true,
- "toggleRefresh":function () {
+ var Brooklyn = {
+ refresh: true,
+ toggleRefresh: function () {
this.refresh = !this.refresh;
return this.refresh;
- }
+ },
+ view: BrooklynViews,
+ util: BrooklynUtils
};
- return Config;
+ return Brooklyn;
});
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/002f70f3/usage/jsgui/src/test/javascript/config.txt
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/test/javascript/config.txt b/usage/jsgui/src/test/javascript/config.txt
index 8bf0b2b..369c404 100644
--- a/usage/jsgui/src/test/javascript/config.txt
+++ b/usage/jsgui/src/test/javascript/config.txt
@@ -16,6 +16,7 @@
"moment":"js/libs/moment.min",
"handlebars":"js/libs/handlebars-1.0.rc.1",
"brooklyn":"js/libs/brooklyn",
+ "brooklyn-view":"js/libs/brooklyn-view",
"brooklyn-utils":"js/libs/brooklyn-utils",
"datatables-extensions":"js/libs/dataTables.extensions",
"googlemaps":"view/googlemaps",
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/002f70f3/usage/jsgui/src/test/javascript/specs/brooklyn-spec.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/test/javascript/specs/brooklyn-spec.js b/usage/jsgui/src/test/javascript/specs/brooklyn-spec.js
new file mode 100644
index 0000000..8c9642d
--- /dev/null
+++ b/usage/jsgui/src/test/javascript/specs/brooklyn-spec.js
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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([
+ "brooklyn", "backbone"
+], function (B, Backbone) {
+
+ describe("view", function () {
+ describe("form", function() {
+ var formTemplate = '<form>' +
+ '<input name="id" type="text"/>' +
+ '<input name="initialvalue" type="text" value="present"/>' +
+ '<button type="submit" class="submit">Submit</button>' +
+ '</form>';
+
+ it("should set existing values on the model", function() {
+ var form = new B.view.Form({template: formTemplate, onSubmit: function() {}});
+ expect(form.model.get("initialvalue")).toBe("present");
+ expect(form.model.get("id")).toBe("");
+ });
+
+ it("should maintain a model as inputs change", function () {
+ var form = new B.view.Form({
+ template: formTemplate,
+ onSubmit: function() {}
+ });
+ // simulate id entry
+ form.$("[name=id]").val("987");
+ form.$("[name=id]").trigger("change");
+ expect(form.model.get("id")).toBe("987");
+ });
+
+ it("should call the onSubmit callback when the form is submitted", function () {
+ var wasCalled = false;
+ var onSubmit = function (model) {
+ wasCalled = true;
+ };
+ var form = new B.view.Form({
+ template: formTemplate,
+ onSubmit: onSubmit
+ });
+ console.log(form.$(".submit"));
+ form.$("form").trigger("submit");
+ expect(wasCalled).toBe(true);
+ });
+
+ // todo: expect failure jasmine method?
+ it("should fail if called without template or onSubmit", function () {
+ try {
+ new B.view.Form({template: ""});
+ fail;
+ } catch (e) {
+ // expected
+ }
+ try {
+ new B.view.Form({onSubmit: function() {}});
+ fail;
+ } catch (e) {
+ // expected
+ }
+
+ });
+ });
+
+ });
+});
\ No newline at end of file