brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [03/10] git commit: Reworks jsgui catalogue page to display app/entity info
Date Fri, 11 Jul 2014 04:14:10 GMT
Reworks jsgui catalogue page to display app/entity info

Breaks deletion of locations


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/1c7fab35
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/1c7fab35
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/1c7fab35

Branch: refs/heads/master
Commit: 1c7fab35d193c79eb1d2499f65f80100ca63c74d
Parents: c358310
Author: Sam Corbett <sam.corbett@cloudsoftcorp.com>
Authored: Mon Jul 7 12:08:16 2014 +0100
Committer: Sam Corbett <sam.corbett@cloudsoftcorp.com>
Committed: Wed Jul 9 14:29:30 2014 +0100

----------------------------------------------------------------------
 usage/jsgui/src/main/webapp/assets/css/base.css |   4 +
 usage/jsgui/src/main/webapp/assets/js/router.js |   1 -
 .../assets/js/view/catalog-details-location.js  |  37 --
 .../src/main/webapp/assets/js/view/catalog.js   | 364 +++++++++++--------
 .../assets/tpl/catalog/details-entity.html      | 150 ++++++++
 .../assets/tpl/catalog/details-location.html    |  21 +-
 .../main/webapp/assets/tpl/catalog/page.html    |  75 +---
 7 files changed, 395 insertions(+), 257 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1c7fab35/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 2e3e020..cebcdcf 100644
--- a/usage/jsgui/src/main/webapp/assets/css/base.css
+++ b/usage/jsgui/src/main/webapp/assets/css/base.css
@@ -1371,3 +1371,7 @@ the element's children, who probably want to control their opacity separately.
*
     border-radius: 10px;
     color: black;
 }
+
+.capitalized {
+    text-transform: capitalize;
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1c7fab35/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 ad17fd7..4df8c05 100644
--- a/usage/jsgui/src/main/webapp/assets/js/router.js
+++ b/usage/jsgui/src/main/webapp/assets/js/router.js
@@ -139,7 +139,6 @@ define([
                 appRouter:that
             })
             that.showView("#application-content", catalogResource)
-            catalogResource.refresh()
         },
         apidocPage:function () {
             var apidocResource = new ApidocView({})

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1c7fab35/usage/jsgui/src/main/webapp/assets/js/view/catalog-details-location.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/catalog-details-location.js b/usage/jsgui/src/main/webapp/assets/js/view/catalog-details-location.js
deleted file mode 100644
index aff9efc..0000000
--- a/usage/jsgui/src/main/webapp/assets/js/view/catalog-details-location.js
+++ /dev/null
@@ -1,37 +0,0 @@
-define([
-    "underscore", "jquery", "backbone", "text!tpl/catalog/details-location.html"
-], function (_, $, Backbone, LocationDetailsHtml) {
-    /**
-     * Renders one location element.
-     */
-    var LocationDetailsView = Backbone.View.extend({
-        template:_.template(LocationDetailsHtml),
-
-        initialize:function () {
-//            this.model.bind('change', this.render, this)
-            this.model.bind('destroy', this.close, this)
-        },
-
-        render:function (eventName) {
-            this.$el.html(this.template({
-                title: this.model.getPrettyName(),
-                id: this.model.id,
-                name: this.model.get('name'),
-                spec: this.model.get('spec'),
-                config: this.model.get("config")
-            }))
-            if (_.size(this.model.get("config"))==0) {
-                $(".has-no-config", this.$el).show()
-            }
-            
-            return this
-        },
-
-        close:function (eventName) {
-//            this.$el.unbind()
-//            this.$el.remove()
-        }
-    })
-
-    return LocationDetailsView
-})
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1c7fab35/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 cd3c026..3048a2f 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/catalog.js
@@ -1,20 +1,161 @@
 define([
-    "underscore", "jquery", "backbone", "model/location", "formatJson",
-    "text!tpl/catalog/page.html", 
+    "underscore", "jquery", "backbone", "formatJson",
+    "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", 
-    
-    "view/catalog-details-location",
-    "view/catalog-add-location-modal", 
-    
+    "text!tpl/catalog/nav-entry.html",
+    "text!tpl/catalog/details-location.html",
+
     "bootstrap", "jquery-form"
-], function (_, $, Backbone, Location, FormatJSON,
-        CatalogPageHtml, 
-        DetailsGenericHtml, 
-        EntryHtml,
-        DetailsLocationView,
-        AddLocationModalView 
-        ) {
+], function(_, $, Backbone, FormatJSON, Location, Entity, AddLocationModalView,
+        CatalogPageHtml, DetailsEntityHtml, DetailsGenericHtml, EntryHtml, LocationDetailsHtml)
{
+
+    // TODO: Loading item's details should perform page navigation
+    var DetailsView = Backbone.View.extend({
+
+        genericDetails: _.template(DetailsGenericHtml),
+        entityDetails: _.template(DetailsEntityHtml),
+        locationDetails: _.template(LocationDetailsHtml),
+
+        render: function() {
+            this.$el.html("<div class='catalog-details'><h3>Select an entry on
the left</h3></div>");
+        },
+
+        showDetailsFor: function(event, type) {
+            var $event = $(event.currentTarget);
+            if ($event.hasClass("active")) return;
+
+            $(".accordion-nav-row").removeClass("active");
+            $event.addClass('active');
+            var chosenId = $event.attr('id');
+            var url, template, Model;
+            if (type == 'applications' || type == 'entities') {
+                // app templates are just normal entities, in the API
+                url = '/v1/catalog/entities/' + chosenId;
+                template = this.entityDetails;
+                Model = Entity.Model;
+            } else if (type == 'locations') {
+                url = chosenId;
+                template = this.locationDetails;
+                Model = Location.Model;
+            } else {
+                url = '/v1/catalog/' + type + '/' + chosenId;
+                template = this.genericDetails;
+            }
+
+            // TODO: Set 'Loading' template
+            //this.$el.html(this.genericDetails({title: chosenId}));
+            var that = this;
+            $.ajax({ url: url,
+                success: function (data) {
+                    var defaults = {
+                        "description": undefined,
+                        "planYaml": undefined,
+                        "sensors": [],
+                        "effectors": [],
+                        "id": undefined,
+                        "name": undefined,
+                        "spec": undefined,
+                        "config": undefined
+                    };
+                    if (Model) {
+                        defaults['model'] = new Model(data);
+                    }
+                    that.$el.html(template(_.extend(defaults, data)))
+                },
+                error: function (xhr, textStatus, error) {
+                    that.$el.html(that.genericDetails({
+                        title: chosenId,
+                        json: FormatJSON({ "status": textStatus, "error": error })
+                    }));
+                }
+            });
+        }
+    });
+
+    var Catalog = Backbone.Collection.extend({
+        initialize: function(models, options) {
+            this.name = options["name"];
+            if (!this.name) {
+                throw new Error("Catalog collection must know its name");
+            }
+        },
+        url: function() {
+            return "/v1/catalog/" + this.name;
+        }
+    });
+
+    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",
+        className: "accordion-item",
+        events: {
+            'click .accordion-head': 'toggle',
+            'click .accordion-nav-row': 'showDetails'
+        },
+
+        initialize: function() {
+            _.bindAll(this);
+            this.name = this.options.name;
+            if (!this.name) {
+                throw new Error("Name should have been given for accordion entry");
+            }
+
+            // Generic templates
+            this.template = _.template(this.options.template || EntryHtml);
+            // Returns template applied to function arguments. Alter if collection altered.
Will be run
+            // in the context of the AccordionItemView.
+            this.templateFn = this.options.templateFn || function(model, index) {
+                return this.template({type: model.get("type"), id: model.get("id")});
+            };
+
+            // undefined argument is for existing models
+            this.collection = this.options.collection || new Catalog(undefined, {"name":
this.name});
+            this.collection.on("sync", this.renderEntries);
+            this.refresh();
+        },
+        beforeClose: function() {
+            this.collection.off();
+        },
+        render: function() {
+            this.$el.html(accordionBodyTemplate({
+                name: this.name,
+                display: this.options.autoOpen ? "block" : "none"
+            }));
+            this.renderEntries();
+            return this;
+        },
+        renderEntries: function() {
+            var elements = this.collection.map(this.templateFn, this);
+            this.$el.find(".accordion-body")
+                .empty()
+                .append(elements.join(''));
+        },
+        refresh: function() {
+            this.collection.fetch();
+        },
+        showDetails: function(event) {
+            // TODO: Incorporate model from view collection.
+            this.options.details.showDetailsFor(event, this.name);
+        },
+        toggle: function() {
+            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')
+            }
+        }
+    });
 
     var CatalogResourceView = Backbone.View.extend({
         tagName:"div",
@@ -22,8 +163,6 @@ define([
         entryTemplate:_.template(EntryHtml),
 
         events:{
-            'click .accordion-head':'toggleAccordion',
-            'click .accordion-nav-row':'showDetailsFor',
             'click .refresh':'refresh',
             'click #add-new-thing':'createNewThing',
             'click #add-new-entity':'addNewCatalogResource',
@@ -32,132 +171,53 @@ define([
             'click .delete-location':'deleteLocation'
         },
 
-        initialize:function () {
+        initialize: function() {
             $(".nav1").removeClass("active");
             $(".nav1_catalog").addClass("active");
-            this.activeAccordion = null
-            this.activeItem = null
-            this.genericTabs = ['applications','entities','policies']
-            _.bindAll(this, "renderLocationsAccordion");
-            
-            var that = this;
-            _.defer(function() {
-                that.toggleAccordionDiv($("#applications div.accordion-head"), false)
-                $("#details-empty").show()
-            })
-        },
-        render:function (eventName) {
-            this.$el.html(_.template(CatalogPageHtml, {}))
-            this.$(".accordion-body", this.$el).slideUp()
-            this.renderLocationsAccordion()
-            this.refresh()
-            return this
+            this.detailsView = new DetailsView();
+            this.accordion = this.options.accordion || [
+                new AccordionItemView({name: "applications", details: this.detailsView, autoOpen:
true}),
+                new AccordionItemView({name: "entities", details: this.detailsView}),
+                new AccordionItemView({name: "policies", details: this.detailsView}),
+                new AccordionItemView({
+                    name: "locations",
+                    details: this.detailsView,
+                    collection: this.options.locations,
+                    templateFn: function(location, index) {
+                        // this reference is AccordionItemView intentionally
+                        return this.template({
+                            type: location.getPrettyName(),
+                            id: location.getLinkByName("self")
+                        });
+                    }
+                })
+            ];
+            _.bindAll(this);
         },
-        refresh: function() {
-            _.each(this.genericTabs, this.refreshGenericAccordion, this)
-            this.refreshLocationsAccordion()
-        },
-        refreshGenericAccordion: function(name) {
-            var that = this
-            $.get('/v1/catalog/'+name, {}, function (result) {
-                that.renderGenericAccordion($("#"+name+" div.accordion-body"), result)
-            })            
-        },
-        renderGenericAccordion: function(accordion, data) {
-            accordion.html('')
-            _.each(data, function (item, pos) {
-                accordion.append(this.entryTemplate({type:item.type, id:item.id}));
-            }, this)
-            accordion.find("div[id='"+this.activeItem+"']").addClass('active')
-        },
-        refreshLocationsAccordion: function() {
-            this.options.locations.fetch({success:this.renderLocationsAccordion})
-        },
-        renderLocationsAccordion: function() {
-            var accordion = $("#"+"locations"+" div.accordion-body")
-            accordion.html('')
-            _.each(this.options.locations.models, function (loc, pos) {
-                accordion.append(this.entryTemplate({
-                    type:loc.getPrettyName(), 
-                    id: loc.getLinkByName("self")}));
-            }, this)
-            accordion.find("div[id='"+this.activeItem+"']").addClass('active')
-        },
-        toggleAccordion: function(event) {
-            this.toggleAccordionDiv($(event.currentTarget), true)
-        },
-        toggleAccordionDiv: function(elt, animation) {
-            var hidden = elt.next()[0].style.display!='block'
-            elt.parent().parent().find('.accordion-head').removeClass('active')
-            if (animation)
-                elt.parent().parent().find('.accordion-body').slideUp('fast')
-            else
-                elt.parent().parent().find('.accordion-body').slideUp()
-                
-            if (hidden) {
-                elt.addClass('active')
-                if (animation)
-                    elt.next().slideDown('fast')
-                else
-                    elt.next().slideDown()
-                    
-                this.activeAccordion = elt.parent().attr('id')
-            } else {
-                this.activeAccordion = null
-            }
+
+        beforeClose: function() {
+            _.invoke(this.accordion, 'close');
         },
-        showDetailsFor: function(event) {
-            var that = this
-            var wasActive = $(event.currentTarget).hasClass('active')
-            this.$(".accordion-nav-row").removeClass('active')
-            $(".catalog-details").hide()
-            if (!wasActive) {
-                $(event.currentTarget).addClass('active')
-                that.activeItem = $(event.currentTarget).attr('id')
-                if (_.contains(that.genericTabs, that.activeAccordion)) {
-                    var url;
-                    if (that.activeAccordion == 'applications')
-                        // app templates are just normal entities, in the API
-                        url = '/v1/catalog/'+'entities'+'/' + that.activeItem
-                    else
-                        url = '/v1/catalog/'+that.activeAccordion+'/' + that.activeItem
-                    $("#details-"+that.activeAccordion).html(_.template(DetailsGenericHtml,
{
-                        title: that.activeItem
-                    }));
-                    console.log("LOADING")
-                    $.ajax({ url: url,
-                        
-                        success: function(data) {
-                            $("#details-"+that.activeAccordion).html(_.template(DetailsGenericHtml,
{
-                                    title: that.activeItem,
-                                    json: FormatJSON(data)
-                            }))
-                        },
-                        error: function(xhr, textStatus, error) {
-                            $("#details-"+that.activeAccordion).html(_.template(DetailsGenericHtml,
{
-                                title: that.activeItem,
-                                json: FormatJSON({ "status": textStatus, "error": error })
-                            }))
-                            // xhr has a lot more data, including responseText, which we
could show 
-                        }
-                    })
-                } else {
-                    that.showLocationDetails(that.activeItem)
-                }
-                $("#details-"+this.activeAccordion).show()
-            //TODO locations
-            } else {
-                this.activeItem = null
-            }
+
+        render: function(eventName) {
+            this.$el.html(_.template(CatalogPageHtml, {}));
+            this.detailsView.$el = this.$("#details");
+            this.detailsView.render();
+            var parent = this.$(".catalog-accordion-parent");
+            _.each(this.accordion, function(child) {
+                parent.append(child.render().$el);
+            });
+//            this.accordion[0].toggle();
+            return this
         },
-        showLocationDetails: function(id) {
-            var pane = $('#details-locations')
-            var l = _.find(this.options.locations.models, function(it) { return id == it.getLinkByName("self")
});
-            pane.html(new DetailsLocationView({model:l}).render().el)
+
+        /** Refreshes the contents of each accordion pane */
+        refresh: function() {
+            _.invoke(this.accordion, 'refresh');
         },
-        
+
         createNewThing: function(event) {
-            var that = this
+            var that = this;
             if (_.contains(that.genericTabs, that.activeAccordion)) {
                 that.addNewCatalogResource(event)
             } else if (that.activeAccordion=='locations') {
@@ -167,44 +227,46 @@ define([
             }
         },
 
-        addNewCatalogResource:function (event) {
+        addNewCatalogResource: function(event) {
             $('#new-entity-modal').modal('show')
         },
-        newEntitySubmit:function (event) {
+
+        newEntitySubmit: function(event) {
             var $entityForm = $('#new-entity-form'),
                 $entityModal = $('#new-entity-modal'),
-                self = this
+                self = this;
             $entityModal.fadeTo(500,0.5);
             var options = {
                 url:'/v1/catalog/',
                 type:'post',
-                success:function (data) {
-                    $entityModal.modal('hide')
+                success: function(data) {
+                    $entityModal.modal('hide');
                     $entityModal.fadeTo(500,1);
                     self.refresh()
                 },
                 error: function(data) {
-                    $entityModel.fadeTo(100,1).delay(200).fadeTo(200,0.2).delay(200).fadeTo(200,1);
+                    $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)
+            };
+            $entityForm.ajaxSubmit(options);
             return false
         },
         
-        addLocation:function (event) {
+        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')
+            });
+            this.$('#new-location-modal').replaceWith(locationModalView.render().$el);
+            this.$('#new-location-modal').modal('show');
         },
-        deleteLocation:function (event) {
-            this.model.get(event.currentTarget['id']).destroy()
+
+        deleteLocation: function(event) {
+            this.model.get(event.currentTarget['id']).destroy();
         }
         
-    })
+    });
     
     return CatalogResourceView
-})
+});

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1c7fab35/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
new file mode 100644
index 0000000..ab02b6e
--- /dev/null
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-entity.html
@@ -0,0 +1,150 @@
+
+<!--
+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><%= name %></h2>
+    <p><%= id %></p>
+    <p><%= description %></p>
+
+    <div id="catalog-details-accordion" class="accordion">
+        <div class="accordion-group">
+            <div class="accordion-heading">
+                <a class="accordion-toggle" data-toggle="collapse" data-parent="#catalog-details-accordion"
href="#collapseYaml">
+                    Plan
+                </a>
+            </div>
+            <div id="collapseYaml" class="accordion-body collapse">
+                <div class="accordion-inner">
+                    <% if (planYaml) { %>
+                    <textarea rows="15"><%= planYaml %></textarea>
+                    <% } else { %>
+                    <p>No plan</p>
+                    <% } %>
+                </div>
+            </div>
+        </div>
+        <div class="accordion-group">
+            <div class="accordion-heading">
+                <a class="accordion-toggle" data-toggle="collapse" data-parent="#catalog-details-accordion"
href="#collapseConfiguration">
+                    Configuration
+                </a>
+            </div>
+            <div id="collapseConfiguration" class="accordion-body collapse">
+                <div class="accordion-inner">
+                    <% if (!config || _.isEmpty(config)) { %>
+                        <p>None available</p>
+                    <% } else { %>
+                        <% var skip = [
+                            'name',
+                            'description',
+                            'label',
+                            'priority',
+                            'reconfigurable'
+                        ]; %>
+                        <% _.each(config, function(object, index) { %>
+                        <p><strong><%= object.name %></strong>: <%=
object.description %></p>
+                        <table class="table table-striped table-condensed nonDatatables">
+                            <tbody>
+                            <% _.each(object, function(value, key) { %>
+                            <% if (!_.contains(skip, key)) { %>
+                            <tr>
+                                <td><%= key %></td>
+                                <td><%= value %></td>
+                            </tr>
+                            <% } %>
+                            <% }); %>
+                            </tbody>
+                        </table>
+                        <% }); %>
+                    <% } %>
+                </div>
+            </div>
+        </div>
+        <div class="accordion-group">
+            <div class="accordion-heading">
+                <a class="accordion-toggle" data-toggle="collapse" data-parent="#catalog-details-accordion"
href="#collapseSensors">
+                    Sensors
+                </a>
+            </div>
+            <div id="collapseSensors" class="accordion-body collapse">
+                <div class="accordion-inner">
+                    <% if (!sensors || _.isEmpty(sensors)) { %>
+                        <p>No sensors</p>
+                    <% } else { %>
+                        <table class="table table-striped table-condensed nonDatatables">
+                            <thead>
+                                <tr>
+                                    <th>Name</th>
+                                    <th>Type</th>
+                                    <th>Description</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                            <% _.each(sensors, function(object, index) { %>
+                                <tr>
+                                    <td><%= object.name %></td>
+                                    <td><%= object.type %></td>
+                                    <td><%= object.description %></td>
+                                </tr>
+                            <% }); %>
+                            </tbody>
+                        </table>
+                    <% } %>
+                </div>
+            </div>
+        </div>
+        <div class="accordion-group">
+            <div class="accordion-heading">
+                <a class="accordion-toggle" data-toggle="collapse" data-parent="#catalog-details-accordion"
href="#collapseEffectors">
+                    Effectors
+                </a>
+            </div>
+            <div id="collapseEffectors" class="accordion-body collapse">
+                <div class="accordion-inner">
+                <% if (!effectors || _.isEmpty(effectors)) { %>
+                    <p>No effectors</p>
+                <% } else { %>
+                    <% _.each(effectors, function(object, index) { %>
+                        <p><strong><%= object.name %></strong>: <%=
object.description %></p>
+                        <% if (!object.parameters || _.isEmpty(object.parameters)) { %>
+                            <p>No parameters</p>
+                        <% } else { %>
+                            <table class="table table-striped table-condensed nonDatatables">
+                                <tbody>
+                                    <% _.each(object.parameters, function(parameter, index)
{ %>
+                                        <% _.each(parameter, function(value, key) { %>
+                                        <tr>
+                                            <td><%= key %></td>
+                                            <td><%= value %></td>
+                                        </tr>
+                                        <% }); %>
+                                    <% }); %>
+                                </tbody>
+                            </table>
+                        <% } %>
+                    <% }); %>
+                <% } %>
+                </div>
+            </div>
+        </div>
+    </div>
+
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1c7fab35/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-location.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-location.html b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-location.html
index c3a3a0f..3a5cf66 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-location.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/details-location.html
@@ -1,13 +1,12 @@
-<div class="catalog-details-location">
+<div class="catalog-details">
 
-<% if ((typeof title !== 'undefined') && (title.length > 0)) { %>
-    <div class="float-right"><button id="<%= id %>" class="btn btn-danger
delete-location">Delete</button></div>
-    
-    <h3><%= title %></h3>
-<% } %>
+    <h3><%= model.getPrettyName() %></h3>
 
-<% if (typeof config === 'undefined') { %>
-    <i>Loading...</i>
+    <!-- TODO -->
+    <!--<div class="float-right"><button id="<%= id %>" class="btn btn-danger
delete-location">Delete</button></div>-->
+
+<% if (typeof config === 'undefined' || _.isEmpty(config)) { %>
+    <em>No special configuration</em>
 <% } else { %>
 
     <br/>
@@ -32,10 +31,6 @@
         <% }); %>
         </tbody>
     </table>
-    <div class="has-no-config for-empty-table hide">
-        <i>No special configuration set</i>
-    </div>
-
 <% } %>
 
-</div>
\ No newline at end of file
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1c7fab35/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 868b836..0fa8af4 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/catalog/page.html
@@ -1,64 +1,29 @@
 <!-- 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 id="add-new-thing" class="icon-br-plus-sign handy" />
-                &nbsp;
-                <i class="icon-br-refresh refresh handy" />
+<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 id="add-new-thing" class="icon-br-plus-sign handy"/>
+                    &nbsp;
+                    <i class="icon-br-refresh refresh handy"/>
+                </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>
-        <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-wrapper">
 
-<div id="applications" class="accordion-item">
-    <div class="accordion-head">
-        Applications
+        <div class="span8" id="details"></div>
     </div>
-    <div class="accordion-body hide"></div>
 </div>
-<div id="entities" class="accordion-item">
-    <div class="accordion-head">
-        Entities
-    </div>
-    <div class="accordion-body hide"></div>
-</div>
-<div id="policies" class="accordion-item">
-    <div class="accordion-head">
-        Policies
-    </div>
-    <div class="accordion-body hide"></div>
-</div>
-<div id="locations" class="accordion-item">
-    <div class="accordion-head">
-        Locations
-    </div>
-    <div class="accordion-body hide"></div>
-</div>
-
-</div>
-        </div>
-        
-    </div>
-    <div class="span8" id="details">
-        <div id="details-empty" class="catalog-details hide">
-            <i>Nothing selected</i>
-        </div>
-        <div id="details-applications" class="catalog-details hide"/>
-        <div id="details-entities" class="catalog-details hide"/>
-        <div id="details-policies" class="catalog-details hide"/>
-        <div id="details-locations" class="catalog-details hide"/>
-    </div>
-</div></div>
 
 <div class="modal hide fade" id="new-entity-modal">
     <form class="form-vertical" id="new-entity-form">


Mime
View raw message