[rhmessaging-commits] rhmessaging commits: r1633 - in mgmt/cumin: python/cumin and 2 other directories.

rhmessaging-commits at lists.jboss.org rhmessaging-commits at lists.jboss.org
Sat Feb 2 21:45:22 EST 2008


Author: justi9
Date: 2008-02-02 21:45:22 -0500 (Sat, 02 Feb 2008)
New Revision: 1633

Modified:
   mgmt/cumin/bin/cumin
   mgmt/cumin/python/cumin/__init__.py
   mgmt/cumin/python/cumin/action.py
   mgmt/cumin/python/cumin/action.strings
   mgmt/cumin/python/cumin/broker.py
   mgmt/cumin/python/cumin/broker.strings
   mgmt/cumin/python/cumin/brokergroup.py
   mgmt/cumin/python/cumin/client.py
   mgmt/cumin/python/cumin/client.strings
   mgmt/cumin/python/cumin/exchange.py
   mgmt/cumin/python/cumin/exchange.strings
   mgmt/cumin/python/cumin/model.py
   mgmt/cumin/python/cumin/page.py
   mgmt/cumin/python/cumin/page.strings
   mgmt/cumin/python/cumin/parameters.py
   mgmt/cumin/python/cumin/queue.py
   mgmt/cumin/python/cumin/queue.strings
   mgmt/cumin/python/cumin/stat.strings
   mgmt/cumin/python/cumin/util.py
   mgmt/cumin/python/cumin/widgets.py
   mgmt/cumin/python/cumin/widgets.strings
   mgmt/cumin/python/wooly/__init__.py
   mgmt/cumin/python/wooly/widgets.py
   mgmt/cumin/resources/wooly.js
Log:
Big update.

 * Add more ui metadata and use it for displaying actions

 * Adds a new actions ui.

 * Revamps header navigation.

 * Some style alterations.



Modified: mgmt/cumin/bin/cumin
===================================================================
--- mgmt/cumin/bin/cumin	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/bin/cumin	2008-02-03 02:45:22 UTC (rev 1633)
@@ -57,7 +57,7 @@
     config.load_file(os.path.join(os.path.expanduser("~"), ".cumin.conf"))
     config.load_args(sys.argv)
 
-    config.show()
+    config.prt()
 
     data = config.get("data")
     port = config.get("port")

Modified: mgmt/cumin/python/cumin/__init__.py
===================================================================
--- mgmt/cumin/python/cumin/__init__.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/__init__.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -10,13 +10,11 @@
 from time import sleep
 from threading import Thread, Event
 
-from model import CuminModel
+from model import CuminModel, ModelPage
 from demo import DemoData
 from page import CuminPage
-from queue import QueueXmlPage
-from exchange import ExchangeXmlPage
-from client import ClientXmlPage
 from stat import StatChartPage
+from action import ActionPage
 
 class Cumin(Application):
     def __init__(self, home, data_url):
@@ -25,19 +23,19 @@
         self.home = home
         self.add_resource_dir(os.path.join(self.home, "resources"))
 
-        self.model = CuminModel(data_url)
+        self.model = CuminModel(self, data_url)
         self.broker_connect_thread = BrokerConnectThread(self.model)
 
-        self.cumin_page = CuminPage(self, "cumin.html")
-        self.set_default_page(self.cumin_page)
+        self.main_page = CuminPage(self, "index.html")
+        self.add_page(self.main_page)
+        self.set_default_page(self.main_page)
 
         self.add_page(CssPage(self, "cumin.css"))
         self.add_page(JavascriptPage(self, "cumin.js"))
         self.add_page(ResourcePage(self, "resource"))
         self.add_page(DevelPage(self, "devel.html"))
-        self.add_page(QueueXmlPage(self, "queue.xml"))
-        self.add_page(ExchangeXmlPage(self, "exchange.xml"))
-        self.add_page(ClientXmlPage(self, "client.xml"))
+        self.add_page(ModelPage(self, "model.xml"))
+        self.add_page(ActionPage(self, "actions.html"))
         self.add_page(StatChartPage(self, "stats.png"))
 
     def check(self):

Modified: mgmt/cumin/python/cumin/action.py
===================================================================
--- mgmt/cumin/python/cumin/action.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/action.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -1,5 +1,6 @@
 from wooly import *
 from wooly.tables import *
+from datetime import datetime
 
 from util import *
 from formats import *
@@ -31,7 +32,8 @@
             return "When"
 
         def render_content(self, session, item):
-            return fmt_datetime(item.when)
+            delta = secs(datetime.now()) - secs(item.when)
+            return "%s ago" % fmt_duration(delta)
 
     class StatusColumn(ItemTableColumn):
         def get_title(self, session, object):
@@ -41,4 +43,14 @@
             return item.status
 
     def do_get_items(self, session, object):
-        return sorted_by(self.app.model.action_invocations, "when")
+        return sorted_by(self.app.model.invocations, "when")
+
+class ActionPage(Page):
+    def __init__(self, app, name):
+        super(ActionPage, self).__init__(app, name)
+
+        self.__actions = ActionInvocationSet(app, "actions")
+        self.add_child(self.__actions)
+
+    def get_title(self, session, object):
+        return "Actions"

Modified: mgmt/cumin/python/cumin/action.strings
===================================================================
--- mgmt/cumin/python/cumin/action.strings	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/action.strings	2008-02-03 02:45:22 UTC (rev 1633)
@@ -5,3 +5,23 @@
   </thead>
   <tbody>{items}</tbody>
 </table>
+
+[ActionPage.html]
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
+  <head>
+    <title>{title}</title>
+    <meta http-equiv="refresh" content="3"/>
+    <link rel="stylesheet" type="text/css" href="cumin.css"/>
+    <link rel="shortcut icon" href="resource?name=favicon.ico" type="image/x-icon"/>
+  </head>
+  <style>
+    body {
+      padding: 1em;
+    }
+  </style>
+  <body>
+    {actions}
+  </body>
+</html>

Modified: mgmt/cumin/python/cumin/broker.py
===================================================================
--- mgmt/cumin/python/cumin/broker.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/broker.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -53,9 +53,6 @@
         count = BrokerRegistration.select().count()
         return "Brokers %s" % fmt_count(count)
 
-    def get_item_count(self, session, model):
-        return BrokerRegistration.select().count()
-
     class Unregister(FormButton):
         def render_content(self, session, model):
             return "Unregister"
@@ -100,7 +97,7 @@
         def render_content(self, session, data):
             broker = Identifiable(data["id"])
             branch = session.branch()
-            self.page().show_broker(branch, broker).show_view(branch)
+            self.app.model.broker.show(branch, broker).show_view(branch)
             return fmt_olink(branch, broker, name=data["name"])
 
     class GroupsColumn(SqlTableColumn):
@@ -121,7 +118,7 @@
 
                 for group in broker.groups[:2]:
                     branch = session.branch()
-                    frame = self.page().show_broker_group(branch, group)
+                    frame = self.app.model.broker_group.show(branch, group)
                     frame.show_view(branch)
                     links.append(fmt_olink(branch, group))
 
@@ -304,8 +301,8 @@
     def get_title(self, session, broker):
         return "Broker '%s'" % broker.name
 
-    def render_name(self, session, broker):
-        return broker.name
+    def render_data_url(self, session, model):
+        return "model.xml"
 
     def render_address(self, session, broker):
         return broker.host + (broker.port and ":%i" % broker.port or "")
@@ -315,7 +312,8 @@
 
         for group in broker.groups:
             branch = session.branch()
-            self.page().show_broker_group(branch, group).show_view(branch)
+            self.frame().frame().show_broker_group(branch, group).show_view \
+                (branch)
             links.append(fmt_olink(branch, group))
 
         return ", ".join(links)
@@ -340,13 +338,12 @@
         else:
             return fmt_none()
 
-    def render_version(self, session, broker):
-        broker = broker.broker
-        if broker:
-            return broker.version
-
     class BrokerQueueTab(QueueSet):
         def get_object(self, session, broker):
+            # XXX
+            if not broker:
+                return
+
             broker = broker.broker # Navigate from registration to real broker
             if broker:
                 return Vhost.selectBy(broker=broker, name="/")[0]
@@ -509,7 +506,7 @@
 
     def render_add_broker_href(self, session, model):
         branch = session.branch()
-        self.page().show_broker_add(branch)
+        self.frame().show_broker_add(branch)
         return branch.marshal()
 
     def render_clear_filters_href(self, session, model):
@@ -663,7 +660,7 @@
 
     def process_cancel(self, session, model):
         branch = session.branch()
-        self.page().show_view(branch)
+        self.frame().show_view(branch)
         self.page().set_redirect_url(session, branch.marshal())
 
     def process_submit(self, session, model):
@@ -699,14 +696,15 @@
 
     def process_cancel(self, session, broker):
         branch = session.branch()
-        self.page().show_broker(branch, broker).show_view(branch)
+        self.frame().show_view(branch)
         self.page().set_redirect_url(session, branch.marshal())
 
     def process_submit(self, session, broker):
         broker.destroySelf()
 
         branch = session.branch()
-        self.page().show_view(branch)
+        frame = self.page().show_view(branch)
+        self.page().set_current_frame(branch, frame)
         self.page().set_redirect_url(session, branch.marshal())
 
     def render_submit_content(self, session, broker):

Modified: mgmt/cumin/python/cumin/broker.strings
===================================================================
--- mgmt/cumin/python/cumin/broker.strings	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/broker.strings	2008-02-03 02:45:22 UTC (rev 1633)
@@ -108,20 +108,29 @@
 }())
 </script>
 
+[BrokerView.javascript]
+function updateBroker(data) {
+    var model = data.objectify();
+
+    cumin.runModelListeners(model);
+}
+
 [BrokerView.html]
+<script>
+  wooly.setIntervalUpdate("{data_url}", updateBroker, 3000);
+</script>
+
 {status}
 
 <h1><img src="resource?name=broker-36.png"/>{title}</h1>
 
 <table class="props">
-  <tr><th>Name</th><td>{name}</td></tr>
   <tr><th>Address</th><td>{address}</td></tr>
 <!--
   <tr><th>Cluster</th><td>{cluster_link}</td></tr>
   <tr><th>Profile</th><td>{profile_link}</td></tr>
 -->
   <tr><th>Groups</th><td>{group_links}</td></tr>
-  <tr><th>Version</th><td>{version}</td></tr>
   <tr>
     <th class="actions" colspan="2">
       <h2>Act on This Broker:</h2>

Modified: mgmt/cumin/python/cumin/brokergroup.py
===================================================================
--- mgmt/cumin/python/cumin/brokergroup.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/brokergroup.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -16,7 +16,7 @@
 
     def render_group_add_href(self, session, model):
         branch = session.branch()
-        self.page().show_broker_group_add(branch)
+        self.frame().show_broker_group_add(branch)
         return branch.marshal()
 
     def do_get_items(self, session, model):
@@ -24,7 +24,7 @@
 
     def render_item_link(self, session, group):
         branch = session.branch()
-        self.page().show_broker_group(branch, group).show_view(branch)
+        self.frame().show_broker_group(branch, group).show_view(branch)
         return fmt_olink(branch, group)
 
     def render_item_config(self, session, group):
@@ -90,9 +90,6 @@
             return "Brokers %s" % \
                 fmt_count(self.get_item_count(session, group))
 
-        def get_item_count(self, session, group):
-            return group.brokers.count()
-
         def get_where_sql(self, session):
             # XXX ugh, get rid of None arg
             group = self.frame().get_object(session, None)
@@ -113,37 +110,36 @@
         self.group_name = TextInput(app, "name", self)
         self.add_child(self.group_name)
 
-    def process_group(self, session, group):
-        group.name = self.group_name.get(session)
-
-        branch = session.branch()
-        self.page().show_broker_group(branch, group).show_view(branch)
-
 class BrokerGroupAdd(BrokerGroupForm, Frame):
     def get_title(self, session, model):
         return "Add Group"
 
     def process_cancel(self, session, model):
         branch = session.branch()
-        self.page().show_view(branch)
+        self.frame().show_view(branch)
         self.page().set_redirect_url(session, branch.marshal())
     
     def process_submit(self, session, model):
-        group = BrokerGroup()
-        self.process_group(session, group)
+        args = {"name": self.group_name.get(session)}
+        method = self.app.model.broker_group.add
+        method.invoke(None, args)
+
         self.process_cancel(session, model)
-    
+
 class BrokerGroupEdit(BrokerGroupForm, Frame):
     def get_title(self, session, group):
         return "Edit Group '%s'" % group.name
 
     def process_cancel(self, session, group):
         branch = session.branch()
-        self.parent.show_view(branch)
+        self.frame().show_view(branch)
         self.page().set_redirect_url(session, branch.marshal())
 
     def process_submit(self, session, group):
-        self.process_group(session, group)
+        args = {"name": self.group_name.get(session)}
+        method = self.app.model.broker_group.edit
+        method.invoke(group, args)
+
         self.process_cancel(session, group)
 
     def process_display(self, session, group):
@@ -155,14 +151,15 @@
 
     def process_cancel(self, session, group):
         branch = session.branch()
-        self.page().show_broker_group(branch, group).show_view(branch)
+        self.app.model.broker_group.show(branch, group).show_view(branch)
         self.page().set_redirect_url(session, branch.marshal())
 
     def process_submit(self, session, group):
-        group.destroySelf()
+        method = self.app.model.broker_group.remove
+        method.invoke(group)
 
         branch = session.branch()
-        self.page().show_view(branch)
+        self.page().show_view(branch).show_messaging(branch)
         self.page().set_redirect_url(session, branch.marshal())
 
     def render_submit_content(self, session, group):

Modified: mgmt/cumin/python/cumin/client.py
===================================================================
--- mgmt/cumin/python/cumin/client.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/client.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -267,11 +267,8 @@
         return "Client '%s'" % client.address
 
     def render_data_url(self, session, client):
-        return "client.xml?id=%i" % client.id
+        return "model.xml?class=client;id=%i" % client.id
     
-    def render_address(self, session, client):
-        return client.address
-
     def render_created_deleted(self, session, client):
         return "%s &ndash; %s" % (fmt_datetime(client.creationTime),
                             fmt_datetime(client.deletionTime))
@@ -462,15 +459,3 @@
 
         def render_value(self, session, value):
             return fmt_predicate(value)
-
-class ClientXmlPage(CuminXmlPage):
-    def __init__(self, app, name):
-        super(ClientXmlPage, self).__init__(app, name)
-
-        self.param = ClientParameter(app, "param")
-        self.add_parameter(self.param)
-
-        self.clients = ListParameter(app, "id", self.param)
-        self.add_parameter(self.clients)
-
-        self.set_list_parameter(self.clients)

Modified: mgmt/cumin/python/cumin/client.strings
===================================================================
--- mgmt/cumin/python/cumin/client.strings	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/client.strings	2008-02-03 02:45:22 UTC (rev 1633)
@@ -46,8 +46,6 @@
 
   <!-- <div>{status_info}</div> -->
 
-  <div>{actions_pending}</div>
-
   <table>
     <tr>
       <th></th>
@@ -67,12 +65,13 @@
   </table>
 </div>
 <script>
-  cumin.listeners["{id}"] = updateClientStatus, 3000;
+  cumin.objectListeners["{id}"] = updateClientStatus, 3000;
 </script>
 
 [ClientView.javascript]
 function updateClient(data) {
-    var clients = data.root().object().client;
+    var model = data.objectify();
+    var clients = model.client;
     var client;
 
     for (var key in clients) {
@@ -80,9 +79,8 @@
         break;
     }
 
-    for (var id in cumin.listeners) {
-        cumin.listeners[id](id, client);
-    }
+    cumin.runModelListeners(model);
+    cumin.runObjectListeners(client);
 }
 
 [ClientView.html]
@@ -95,7 +93,6 @@
 <h1><img src="resource?name=client-36.png"/>{title}</h1>
 
 <table class="props">
-  <tr><th>Address</th><td>{address}</td></tr>
   <tr><th>Created &ndash; Deleted</th><td>{created_deleted}</td></tr>
   <tr><th>Updated</th><td>{updated}</td></tr>
   <tr>

Modified: mgmt/cumin/python/cumin/exchange.py
===================================================================
--- mgmt/cumin/python/cumin/exchange.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/exchange.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -210,9 +210,6 @@
             or "Default Exchange"
 
 class ExchangeStatus(CuminStatus):
-    def render_data_url(self, session, exchange):
-        return "exchange.xml?id=%i" % exchange.id
-    
     def render_messages_received(self, session, exchange):
         return self.app.model.exchange.get_stat("msgReceives").rate_html(exchange)
 
@@ -259,11 +256,8 @@
         return self.parent.get_title(session, exchange)
 
     def render_data_url(self, session, exchange):
-        return "exchange.xml?id=%i" % exchange.id
+        return "model.xml?class=exchange;id=%i" % exchange.id
 
-    def render_name(self, session, exchange):
-        return exchange.name
-
     def render_type(self, session, exchange):
         if exchange.type == "direct":
             return "Direct"
@@ -295,7 +289,7 @@
 
     def render_item_href(self, session, binding):
         branch = session.branch()
-        self.page().show_queue(branch, binding.queue)
+        self.frame().frame().show_queue(branch, binding.queue)
         return branch.marshal()
     
     def render_item_name(self, session, binding):
@@ -482,15 +476,3 @@
     def render_item_bytes_produced_rate(self, session, producer):
         value = producer.statsCurr.bytesProduced #XXX statify
         return fmt_rate(value, "byte", "sec")
-
-class ExchangeXmlPage(CuminXmlPage):
-    def __init__(self, app, name):
-        super(ExchangeXmlPage, self).__init__(app, name)
-
-        self.param = ExchangeParameter(app, "param")
-        self.add_parameter(self.param)
-
-        self.exchanges = ListParameter(app, "id", self.param)
-        self.add_parameter(self.exchanges)
-
-        self.set_list_parameter(self.exchanges)

Modified: mgmt/cumin/python/cumin/exchange.strings
===================================================================
--- mgmt/cumin/python/cumin/exchange.strings	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/exchange.strings	2008-02-03 02:45:22 UTC (rev 1633)
@@ -99,8 +99,6 @@
 
   <!-- <div>{status_info}</div> -->
 
-  <div>{actions_pending}</div>
-
   <table>
     <tr>
       <th></th>
@@ -125,12 +123,13 @@
   </table>
 </div>
 <script>
-  cumin.listeners["{id}"] = updateExchangeStatus
+  cumin.objectListeners["{id}"] = updateExchangeStatus
 </script>
 
 [ExchangeView.javascript]
 function updateExchange(data) {
-    var exchanges = data.root().object().exchange;
+    var model = data.objectify();
+    var exchanges = model.exchange;
     var exchange;
 
     for (var key in exchanges) {
@@ -138,9 +137,8 @@
         break;
     }
 
-    for (var id in cumin.listeners) {
-        cumin.listeners[id](id, exchange);
-    }
+    cumin.runModelListeners(model);
+    cumin.runObjectListeners(exchange);
 }
 
 [ExchangeView.html]
@@ -153,7 +151,6 @@
 <h1><img src="resource?name=exchange-36.png"/>{title}</h1>
 
 <table class="props">
-  <tr><th>Name</th><td>{name}</td></tr>
   <tr><th>Type</th><td>{type}</td></tr>
   <tr><th>Created &ndash; Deleted</th><td>{created_deleted}</td></tr>
   <tr><th>Updated</th><td>{updated}</td></tr>

Modified: mgmt/cumin/python/cumin/model.py
===================================================================
--- mgmt/cumin/python/cumin/model.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/model.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -1,25 +1,32 @@
 from mint import *
 from wooly import *
+from wooly.parameters import *
 from time import mktime
 from datetime import datetime, timedelta
 from types import *
 
 from util import *
 from formats import *
+from parameters import *
 
 class CuminModel(object):
-    def __init__(self, data_url):
+    def __init__(self, app, data_url):
+        self.app = app
         self.data = MintModel(data_url)
 
         self.classes = list()
-        self.action_invocations = set()
+        self.invocations = set()
         
+        CuminBroker(self)
         CuminQueue(self)
         CuminExchange(self)
         CuminBinding(self)
         CuminClient(self)
         CuminSession(self)
 
+        CuminBrokerRegistration(self)
+        CuminBrokerGroup(self)
+
     def check(self):
         self.data.check()
 
@@ -41,64 +48,33 @@
             if cls.name == name:
                 return cls
 
-class CuminClass(object):
-    def __init__(self, model, name, mint_class):
-        self.model = model
-        self.name = name
-        self.mint_class = mint_class
-        self.mint_stats_class = None
-        
-        self.stats = list()
-        self.actions = list()
+    def count_invocations(self, status):
+        count = 0
 
-        self.model.add_class(self)
+        for invoc in self.invocations:
+            if invoc.status == status:
+                count += 1
 
-    def add_stat(self, stat):
-        self.stats.append(stat)
-        setattr(self, stat.name, stat)
+        return count
 
-    # XXX get rid of this
-    def get_stat(self, name):
-        for stat in self.stats:
-            if stat.name == name:
-                return stat
+    def write_xml(self, writer, objects):
+        writer.write("<model>")
 
-    def add_action(self, action):
-        self.actions.append(action)
-        setattr(self, action.name, action)
+        pcount = self.count_invocations("pending")
+        ccount = self.count_invocations("OK")
+        fcount = len(self.invocations) - pcount - ccount
 
-    def get_title(self, session):
-        return "Object"
+        writer.write("<invocations pending=\"%i\" " % pcount +
+                     "completed=\"%i\" " % ccount +
+                     "failed=\"%i\"/>" % fcount)
 
-    def get_object_title(self, session, object):
-        title = self.get_title(session)
-        name = self.get_object_name(object)
-        return "%s '%s'" % (title, name)
+        for object in objects:
+            cls = self.get_class_by_object(object)
+            # XXX swap the args
+            cls.write_xml(object, writer)
 
-    def get_object_name(self, object):
-        return object.name
+        writer.write("</model>")
 
-    def write_event_xml(self, object, writer):
-        writer.write("<events errors=\"%i\" warnings=\"%i\"/>" % (0, 0))
-
-    def write_action_xml(self, object, writer):
-        count = len(self.model.data.outstandingMethodCalls)
-        writer.write("<actions pending=\"%i\"/>" % count)
-
-    def write_stat_xml(self, object, writer):
-        for stat in self.stats:
-            stat.write_xml(object, writer)
-
-    def write_xml(self, object, writer):
-        writer.write("<%s id=\"%i\" name=\"%s\">" % \
-                         (self.name, object.id, self.get_object_name(object)))
-
-        self.write_event_xml(object, writer)
-        self.write_action_xml(object, writer)
-        self.write_stat_xml(object, writer)
-            
-        writer.write("</%s>" % self.name)
-
 class CuminAction(object):
     def __init__(self, cls, name):
         self.model = cls.model
@@ -108,21 +84,21 @@
 
         self.cumin_class.add_action(self)
 
-    def invoke(self, object):
+    def invoke(self, object, args={}):
         invoc = CuminActionInvocation(self, object)
 
-        def callback(status, args):
+        def completion(status, args=None):
             invoc.status = status
             invoc.args = args
-            invoc.show()
+            #invoc.prt()
 
-        self.do_invoke(object, callback)
+        self.do_invoke(object, args, completion)
 
-        self.model.action_invocations.add(invoc)
+        self.model.invocations.add(invoc)
 
         return invoc
 
-    def do_invoke(self, object, callback):
+    def do_invoke(self, object, args, completion):
         pass
 
 class CuminActionInvocation(object):
@@ -134,12 +110,17 @@
         self.args = None
 
     def get_description(self, session):
-        action = self.action.get_title(session)
-        cls = self.action.model.get_class_by_object(self.object)
-        name = cls.get_object_title(session, self.object)
-        return "%s %s" % (action, name)
+        verb = self.action.get_title(session)
 
-    def show(self):
+        if self.object:
+            cls = self.action.model.get_class_by_object(self.object)
+            object = cls.get_object_title(session, self.object)
+        else:
+            object = self.action.cumin_class.get_title(session)
+
+        return "%s %s" % (verb, object)
+
+    def prt(self):
         print "action", self.action.name, self.when, self.status, self.args
 
 class CuminStat(object):
@@ -250,12 +231,112 @@
         writer.write("<stat name=\"%s\" value=\"%s\" rate=\"%s\"/>" \
                      % (self.name, value, rate))
 
+class CuminClass(object):
+    def __init__(self, model, name, mint_class, mint_stats_class):
+        self.model = model
+        self.name = name
+        self.mint_class = mint_class
+        self.mint_stats_class = mint_stats_class
+        
+        self.stats = list()
+        self.actions = list()
+
+        self.Add(self, "add")
+        self.Edit(self, "edit")
+        self.Remove(self, "remove")
+
+        self.model.add_class(self)
+ 
+    def add_stat(self, stat):
+        self.stats.append(stat)
+        setattr(self, stat.name, stat)
+
+    # XXX get rid of this
+    def get_stat(self, name):
+        for stat in self.stats:
+            if stat.name == name:
+                return stat
+
+    def add_action(self, action):
+        self.actions.append(action)
+        setattr(self, action.name, action)
+
+    def get_title(self, session):
+        return "Object"
+
+    def get_object_title(self, session, object):
+        title = self.get_title(session)
+        name = self.get_object_name(object)
+        return "%s '%s'" % (title, name)
+
+    def get_object_name(self, object):
+        return object.name
+
+    def write_event_xml(self, object, writer):
+        writer.write("<events errors=\"%i\" warnings=\"%i\"/>" % (0, 0))
+
+    def write_stat_xml(self, object, writer):
+        for stat in self.stats:
+            stat.write_xml(object, writer)
+
+    def write_xml(self, object, writer):
+        writer.write("<%s id=\"%i\" name=\"%s\">" % \
+                         (self.name, object.id, self.get_object_name(object)))
+
+        self.write_event_xml(object, writer)
+        self.write_stat_xml(object, writer)
+            
+        writer.write("</%s>" % self.name)
+
+    class Add(CuminAction):
+        def get_title(self, session):
+            return "Add"
+
+        def do_invoke(self, object, args, completion):
+            try:
+                object = self.cumin_class.mint_class()
+                object.set(**args)
+                object.syncUpdate()
+                completion("OK")
+            except Exception, e:
+                completion(e.message or "failed")
+
+    class Edit(CuminAction):
+        def get_title(self, session):
+            return "Edit"
+
+        def do_invoke(self, object, args, completion):
+            try:
+                object.set(**args)
+                object.syncUpdate()
+                completion("OK")
+            except Exception, e:
+                completion(e.message or "failed")
+
+    class Remove(CuminAction):
+        def get_title(self, session):
+            return "Remove"
+
+        def do_invoke(self, object, args, completion):
+            try:
+                object.destroySelf();
+                object.syncUpdate()
+                completion("OK")
+            except Exception, e:
+                completion(e.message or "failed")
+
+class CuminBroker(CuminClass):
+    def __init__(self, model):
+        super(CuminBroker, self).__init__(model, "broker", Broker, BrokerStats)
+
+    def show(self, session, broker):
+        frame = self.model.app.main_page.show_view(session)
+        return frame.show_messaging(session).show_broker(session, broker)
+
 class CuminQueue(CuminClass):
     def __init__(self, model):
-        super(CuminQueue, self).__init__(model, "queue", Queue)
+        super(CuminQueue, self).__init__(model, "queue", Queue, QueueStats)
         
-        self.mint_stats_class = QueueStats
-        
         stat = CuminStat(self, "consumers", "int")
         stat.title = "Consumers"
         stat.unit = "consumer"
@@ -430,15 +511,14 @@
         def get_title(self, session):
             return "Purge"
 
-        def do_invoke(self, object, callback):
-            object.purge(self.model.data, object.managedBroker, callback)
+        def do_invoke(self, object, args, completion):
+            object.purge(self.model.data, object.managedBroker, completion)
 
 class CuminExchange(CuminClass):
     def __init__(self, model):
-        super(CuminExchange, self).__init__(model, "exchange", Exchange)
+        super(CuminExchange, self).__init__(model, "exchange",
+                                            Exchange, ExchangeStats)
         
-        self.mint_stats_class = ExchangeStats
-        
         stat = CuminStat(self, "producers", "int")
         stat.title = "Producers"
         stat.unit = "producer"
@@ -486,10 +566,9 @@
     
 class CuminBinding(CuminClass):
     def __init__(self, model):
-        super(CuminBinding, self).__init__(model, "binding", Binding)
+        super(CuminBinding, self).__init__(model, "binding",
+                                           Binding, BindingStats)
 
-        self.mint_stats_class = BindingStats
-
         stat = CuminStat(self, "msgMatched", "int")
         stat.title = "Msgs. Matched"
         stat.unit = "message"
@@ -503,10 +582,8 @@
 
 class CuminClient(CuminClass):
     def __init__(self, model):
-        super(CuminClient, self).__init__(model, "client", Client)
+        super(CuminClient, self).__init__(model, "client", Client, ClientStats)
 
-        self.mint_stats_class = ClientStats
-
         stat = CuminStat(self, "bytesFromClient", "int")
         stat.title = "Bytes Sent"
         stat.unit = "byte"
@@ -539,15 +616,14 @@
         def get_title(self, session):
             return "Close"
 
-        def do_invoke(self, object, callback):
-            object.close(self.model.data, object.managedBroker, callback)
+        def do_invoke(self, object, args, completion):
+            object.close(self.model.data, object.managedBroker, completion)
 
 class CuminSession(CuminClass):
     def __init__(self, model):
-        super(CuminSession, self).__init__(model, "session", Session)
+        super(CuminSession, self).__init__(model, "session",
+                                           Session, SessionStats)
 
-        self.mint_stats_class = SessionStats
-
         stat = CuminStat(self, "remainingLifespan", "int")
         stat.title = "Remaining Lifespan"
         stat.unit = "second"
@@ -564,6 +640,7 @@
 
         self.Close(self, "close")
         self.Detach(self, "detach")
+        # XXX de studly these
         self.ResetLifespan(self, "resetLifespan")
         self.SolicitAck(self, "solicitAck")
 
@@ -574,28 +651,79 @@
         def get_title(self, session):
             return "Close"
 
-        def do_invoke(self, object, callback):
-            object.close(self.model.data, object.managedBroker, callback)
+        def do_invoke(self, object, args, completion):
+            object.close(self.model.data, object.managedBroker, completion)
 
     class Detach(CuminAction):
         def get_title(self, session):
             return "Detach"
 
-        def do_invoke(self, object, callback):
-            object.detach(self.model.data, object.managedBroker, callback)
+        def do_invoke(self, object, args, completion):
+            object.detach(self.model.data, object.managedBroker, completion)
 
     class ResetLifespan(CuminAction):
         def get_title(self, session):
             return "Reset Lifespan"
 
-        def do_invoke(self, object, callback):
+        def do_invoke(self, object, args, completion):
             object.resetLifespan(self.model.data, object.managedBroker,
-                                 callback)
+                                 completion)
 
     class SolicitAck(CuminAction):
         def get_title(self, session):
             return "Solicit Acknowledgment"
 
-        def do_invoke(self, object, callback):
+        def do_invoke(self, object, args, completion):
             object.solicitAck(self.model.data, object.managedBroker,
-                              callback)
+                              completion)
+
+class CuminBrokerRegistration(CuminClass):
+    def __init__(self, model):
+        super(CuminBrokerRegistration, self).__init__ \
+            (model, "broker_registration", BrokerRegistration, None)
+
+    def get_title(self, session):
+        return "Broker Registration"
+
+class CuminBrokerGroup(CuminClass):
+    def __init__(self, model):
+        super(CuminBrokerGroup, self).__init__ \
+            (model, "broker_group", BrokerGroup, None)
+
+    def show(self, session, group):
+        frame = self.model.app.main_page.show_view(session)
+        return frame.show_messaging(session).show_broker_group(session, group)
+
+    def get_title(self, session):
+        return "Broker Group"
+
+class ModelPage(Page):
+    def __init__(self, app, name):
+        super(ModelPage, self).__init__(app, name)
+
+        self.__class = CuminClassParameter(app, "class")
+        self.add_parameter(self.__class)
+
+        param = IntegerParameter(app, "param")
+        self.add_parameter(param)
+
+        self.__ids = ListParameter(app, "id", param)
+        self.add_parameter(self.__ids)
+
+    def get_content_type(self, session):
+        return Page.xml_content_type
+
+    def do_render(self, session, model):
+        writer = Writer()
+        writer.write(Page.xml_1_0_declaration)
+
+        cls = self.__class.get(session)
+        objects = list()
+
+        if cls:
+            for id in self.__ids.get(session):
+                objects.append(cls.mint_class.get(id))
+        
+        self.app.model.write_xml(writer, objects)
+        
+        return writer.to_string()

Modified: mgmt/cumin/python/cumin/page.py
===================================================================
--- mgmt/cumin/python/cumin/page.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/page.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -6,6 +6,7 @@
 from brokergroup import *
 from brokerprofile import *
 from brokercluster import *
+from system import *
 from action import *
 from widgets import *
 from util import *
@@ -16,53 +17,28 @@
     def __init__(self, app, name):
         super(CuminPage, self).__init__(app, name)
 
-        self.frames = self.FramesAttribute(app, "frames")
-        self.add_attribute(self.frames)
+        self.__frames = self.FramesAttribute(app, "frames")
+        self.add_attribute(self.__frames)
 
-        self.object = Attribute(app, "object")
-        self.add_attribute(self.object)
+        self.__modal = Attribute(app, "modal")
+        self.add_attribute(self.__modal)
 
-        self.modal = Attribute(app, "modal")
-        self.add_attribute(self.modal)
+        self.__view = MainView(app, "main")
+        self.add_mode(self.__view)
 
-        self.frame_tmpl = Template(self, "frame_html")
+    def show_view(self, session):
+        return self.show_mode(session, self.__view)
 
-        self.view = MainView(app, "view")
-        self.add_mode(self.view)
+    def show_broker(self, session, broker):
+        frame = self.show_view(session).show_messaging(session)
+        return frame.show_broker(session, broker)
 
-        self.broker = BrokerFrame(app, "broker")
-        self.add_mode(self.broker)
-
-        self.broker_add = BrokerAdd(app, "brokeradd")
-        self.add_mode(self.broker_add)
-
-        self.brokers_remove = BrokerSetRemove(app, "brokersremove")
-        self.add_mode(self.brokers_remove)
-
-        self.group = BrokerGroupFrame(app, "group")
-        self.add_mode(self.group)
-
-        self.group_add = BrokerGroupAdd(app, "groupadd")
-        self.add_mode(self.group_add)
-
-        self.profile = BrokerProfileFrame(app, "profile")
-        self.add_mode(self.profile)
-
-        self.profile_add = BrokerProfileAdd(app, "profileadd")
-        self.add_mode(self.profile_add)
-
-        self.cluster = BrokerClusterFrame(app, "cluster")
-        self.add_mode(self.cluster)
-
-        self.cluster_add = BrokerClusterAdd(app, "clusteradd")
-        self.add_mode(self.cluster_add)
-
     def save_session(self, session):
         if self.app.debug:
             self.app.debug.sessions.append(session)
 
     def set_modal(self, session, modal):
-        self.modal.set(session, modal)
+        self.__modal.set(session, modal)
 
     def get_object(self, session, object):
         return self.app.model
@@ -72,12 +48,114 @@
             return list()
 
     def get_frames(self, session):
-        return self.frames.get(session)
+        return self.__frames.get(session)
 
-    def show_view(self, session):
-        self.set_current_frame(session, self)
-        return self.show_mode(session, self.view)
+    def do_process(self, session, model):
+        super(CuminPage, self).do_process(session, model)
 
+        if self.get_current_frame(session) is self:
+            self.show_view(session).show_messaging(session)
+
+    def render_class(self, session, object):
+        return self.__modal.get(session) and "modal"
+
+    def get_title(self, session, model):
+        return "MRG Management"
+
+class MainView(TabSet):
+    def __init__(self, app, name):
+        super(MainView, self).__init__(app, name)
+
+        self.__frame_tmpl = Template(self, "frame_html")
+
+        self.__object = Attribute(app, "object")
+        self.add_attribute(self.__object)
+
+        self.__messaging = MessagingFrame(app, "msg")
+        self.add_tab(self.__messaging)
+        self.add_tab(GridFrame(app, "grd"))
+        self.add_tab(SystemsFrame(app, "sys"))
+
+    def show_messaging(self, session):
+        frame = self.show_mode(session, self.__messaging)
+        return self.page().set_current_frame(session, frame)
+
+    def render_tab_href(self, session, mode):
+        branch = session.branch()
+        self.set_selected_mode(branch, mode)
+
+        if mode not in self.page().get_current_frame(branch).ancestors():
+            self.page().set_current_frame(branch, mode)
+
+        return branch.marshal()
+
+    def render_frames(self, session, object):
+        self.__object.set(session, object)
+        writer = Writer()
+
+        for frame in self.page().get_frames(session):
+            self.__frame_tmpl.render(session, frame, writer)
+
+        return writer.to_string()
+
+    def render_frame_href(self, session, frame):
+        object = frame.get_object(session, self.__object.get(session))
+        return frame.render_href(session, object)
+
+    def render_frame_title(self, session, frame):
+        object = frame.get_object(session, self.__object.get(session))
+        return frame.render_title(session, object)
+
+    def render_pending_count(self, session, object):
+        return self.app.model.count_invocations("pending")
+
+    def render_completed_count(self, session, object):
+        return self.app.model.count_invocations("OK")
+
+    def render_failed_count(self, session, object):
+        pcount = self.app.model.count_invocations("pending")
+        ccount = self.app.model.count_invocations("OK")
+        return len(self.app.model.invocations) - pcount - ccount
+
+class MessagingFrame(CuminFrame):
+    def __init__(self, app, name):
+        super(MessagingFrame, self).__init__(app, name)
+
+        self.__view = MessagingView(app, "view")
+        self.add_mode(self.__view)
+        self.set_view_mode(self.__view)
+
+        self.__broker = BrokerFrame(app, "broker")
+        self.add_mode(self.__broker)
+
+        # XXX rename to BrokerSetAdd
+        self.__broker_add = BrokerAdd(app, "brokeradd")
+        self.add_mode(self.__broker_add)
+
+        self.__brokers_remove = BrokerSetRemove(app, "brokersremove")
+        self.add_mode(self.__brokers_remove)
+
+        self.__group = BrokerGroupFrame(app, "group")
+        self.add_mode(self.__group)
+
+        self.__group_add = BrokerGroupAdd(app, "groupadd")
+        self.add_mode(self.__group_add)
+
+        self.__profile = BrokerProfileFrame(app, "profile")
+        self.add_mode(self.__profile)
+
+        self.__profile_add = BrokerProfileAdd(app, "profileadd")
+        self.add_mode(self.__profile_add)
+
+        self.__cluster = BrokerClusterFrame(app, "cluster")
+        self.add_mode(self.__cluster)
+
+        self.__cluster_add = BrokerClusterAdd(app, "clusteradd")
+        self.add_mode(self.__cluster_add)
+
+    def get_title(self, session, model):
+        return "Messaging"
+
     def show_broker(self, session, broker):
         cluster = None #broker.get_broker_cluster()
 
@@ -85,96 +163,67 @@
             frame = self.show_broker_cluster(session, cluster)
             frame = frame.show_broker(session, broker)
         else:
-            frame = self.show_mode(session, self.broker)
+            frame = self.show_mode(session, self.__broker)
             frame.set_object(session, broker)
 
-        return self.set_current_frame(session, frame)
+        return self.page().set_current_frame(session, frame)
 
     def show_broker_add(self, session):
-        frame = self.show_mode(session, self.broker_add)
-        return self.set_current_frame(session, frame)
+        frame = self.show_mode(session, self.__broker_add)
+        return self.page().set_current_frame(session, frame)
 
     def show_brokers_remove(self, session):
-        frame = self.show_mode(session, self.brokers_remove)
-        return self.set_current_frame(session, frame)
+        frame = self.show_mode(session, self.__brokers_remove)
+        return self.page().set_current_frame(session, frame)
 
     def show_broker_group(self, session, group):
-        frame = self.show_mode(session, self.group)
+        frame = self.show_mode(session, self.__group)
         frame.set_object(session, group)
-        return self.set_current_frame(session, frame)
+        return self.page().set_current_frame(session, frame)
 
     def show_broker_group_add(self, session):
-        frame = self.show_mode(session, self.group_add)
-        return self.set_current_frame(session, frame)
+        frame = self.show_mode(session, self.__group_add)
+        return self.page().set_current_frame(session, frame)
 
     def show_broker_profile(self, session, profile):
-        frame = self.show_mode(session, self.profile)
+        frame = self.show_mode(session, self.__profile)
         frame.set_object(session, profile)
-        return self.set_current_frame(session, frame)
+        return self.page().set_current_frame(session, frame)
 
     def show_broker_profile_add(self, session):
-        frame = self.show_mode(session, self.profile_add)
-        return self.set_current_frame(session, frame)
+        frame = self.show_mode(session, self.__profile_add)
+        return self.page().set_current_frame(session, frame)
 
     def show_broker_cluster(self, session, cluster):
-        frame = self.show_mode(session, self.cluster)
+        frame = self.show_mode(session, self.__cluster)
         frame.set_object(session, cluster)
-        return self.set_current_frame(session, frame)
+        return self.page().set_current_frame(session, frame)
 
     def show_broker_cluster_add(self, session):
-        frame = self.show_mode(session, self.cluster_add)
-        return self.set_current_frame(session, frame)
+        frame = self.show_mode(session, self.__cluster_add)
+        return self.page().set_current_frame(session, frame)
 
-    def show_queue(self, session, queue):
-        frame = self.show_broker(session, queue.vhost.broker.registration)
-        return frame.show_queue(session, queue)
+#     def show_queue(self, session, queue):
+#         frame = self.show_broker(session, queue.vhost.broker.registration)
+#         return frame.show_queue(session, queue)
 
-    def show_exchange(self, session, exchange):
-        frame = self.show_broker(session, exchange.vhost.broker.registration)
-        return frame.show_exchange(session, exchange)
+#     def show_exchange(self, session, exchange):
+#         frame = self.show_broker(session, exchange.vhost.broker.registration)
+#         return frame.show_exchange(session, exchange)
 
-    def show_client(self, session, client):
-        frame = self.show_broker(session, client.vhost.broker.registration)
-        return frame.show_client(session, client)
+#     def show_client(self, session, client):
+#         frame = self.show_broker(session, client.vhost.broker.registration)
+#         return frame.show_client(session, client)
 
-    def render_class(self, session, object):
-        return self.modal.get(session) and "modal"
-
-    def render_href(self, session, object):
-        branch = session.branch()
-        self.show_view(branch)
-        return branch.marshal()
-
-    def get_title(self, session, model):
-        return "MRG Messaging"
-
-    def render_frames(self, session, object):
-        self.object.set(session, object)
-        writer = Writer()
-
-        for frame in self.get_frames(session):
-            self.frame_tmpl.render(session, frame, writer)
-
-        return writer.to_string()
-
-    def render_frame_href(self, session, frame):
-        object = frame.get_object(session, self.object.get(session))
-        return frame.render_href(session, object)
-
-    def render_frame_title(self, session, frame):
-        object = frame.get_object(session, self.object.get(session))
-        return frame.render_title(session, object)
-
-class MainView(TabSet):
+class MessagingView(TabSet):
     def __init__(self, app, name):
-        super(MainView, self).__init__(app, name)
+        super(MessagingView, self).__init__(app, name)
 
         self.add_tab(BrokerBrowser(app, "brokers"))
         self.add_tab(BrokerGroupSet(app, "groups"))
         #self.add_tab(BrokerProfileSet(app, "profiles"))
         #self.add_tab(BrokerClusterSet(app, "clusters"))
         #self.add_tab(self.TagTab(app, "tags"))
-        self.add_tab(self.ActionTab(app, "actions"))
 
     def show_broker_group(self, session, group):
         mode = self.show_mode(session, self.brokers)
@@ -184,10 +233,50 @@
     def get_title(self, session, model):
         return "Messaging"
 
+    def render_data_url(self, session, model):
+        return "model.xml"
+
     class TagTab(Widget):
         def get_title(self, session, model):
             return "Tags"
 
-    class ActionTab(ActionInvocationSet):
-        def get_title(self, session, model):
-            return "Actions"
+class GridFrame(CuminFrame):
+    def __init__(self, app, name):
+        super(GridFrame, self).__init__(app, name)
+
+        self.__view = GridView(app, "view")
+        self.add_mode(self.__view)
+        self.set_view_mode(self.__view)
+
+    def get_title(self, session, model):
+        return "Grid"
+
+class GridView(TabSet):
+    def get_title(self, session, model):
+        return "Grid"
+
+    def render_data_url(self, session, model):
+        return "model.xml"
+
+class SystemsFrame(CuminFrame):
+    def __init__(self, app, name):
+        super(SystemsFrame, self).__init__(app, name)
+
+        self.__view = SystemsView(app, "view")
+        self.add_mode(self.__view)
+        self.set_view_mode(self.__view)
+
+    def get_title(self, session, model):
+        return "Systems"
+
+class SystemsView(TabSet):
+    def __init__(self, app, name):
+        super(SystemsView, self).__init__(app, name)
+
+        self.add_tab(SystemSet(app, "systems"))
+
+    def get_title(self, session, model):
+        return "Systems"
+
+    def render_data_url(self, session, model):
+        return "model.xml"

Modified: mgmt/cumin/python/cumin/page.strings
===================================================================
--- mgmt/cumin/python/cumin/page.strings	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/page.strings	2008-02-03 02:45:22 UTC (rev 1633)
@@ -8,10 +8,6 @@
                "Trebuchet MS", verdana, helvetica, arial, sans-serif;
 }
 
-body.modal #head {
-  opacity: 0.2;
-}
-
 body.modal {
   background-color: #f7f7f7;
 }
@@ -49,34 +45,6 @@
   color: #999;
 }
 
-#head {
-  padding: 0.4em 0.75em 0.2em 0.75em;
-  background-color: #f7f7f7;
-  border-bottom: 1px dotted #eee;
-  font-size: 0.9em;
-  /* background-color: #685b8a; */
-  /* background-color: #564979; */
-}
-
-#body {
-  padding: 1em;
-}
-
-#logo {
-  vertical-align: -20%;
-}
-
-ul#whonav {
-  float: right;
-  list-style: none;
-  color: #333;
-  margin: 0;
-}
-
-ul#whonav li {
-  display: inline;
-}
-
 h1, h2 {
   margin: 0;
 }
@@ -106,28 +74,6 @@
   padding: 0 1em;
 }
 
-ul#context {
-  display: inline;
-  list-style: none;
-  padding: 0;
-  margin: 0;
-}
-
-ul#context li {
-  display: inline;
-}
-
-ul#context li:before {
-  content: " > ";
-  font-weight: bold;
-  font-size: 0.8em;
-  color: #999;
-}
-
-ul#context li:last-child a {
-  color: #333;
-}
-
 ul.actions {
   padding: 0;
   margin: 0 0 1em 0;
@@ -390,6 +336,11 @@
   margin: 0 0.75em 0 0;
 }
 
+ul.radiotabs li:last-child {
+  display: inline;
+  margin: 0;
+}
+
 ul.radiotabs li a:before {
   content: url(resource?name=radio-button.png);
   margin: 0 0.5em 0 0;
@@ -573,7 +524,20 @@
     cumin = new Cumin();
 
     function Cumin() {
-        this.listeners = new Object();
+        this.modelListeners = new Object();
+        this.objectListeners = new Object();
+
+        this.runModelListeners = function(model) {
+            for (var id in this.modelListeners) {
+                this.modelListeners[id](id, model);
+            }
+        }
+
+        this.runObjectListeners = function(object) {
+            for (var id in this.objectListeners) {
+                this.objectListeners[id](id, object);
+            }
+        }
     }
 }())
 
@@ -590,33 +554,199 @@
     <script src="cumin.js"> </script>
   </head>
   <body class="{class}">
-    <div id="head">
-      <ul id="whonav">
-        <!--
-        <li>Hi, <strong>nsantos</strong></li>
-        <li><a class="nav" href="">Log Out</a></li>
-        -->
-      </ul>
-
-      <!-- <a id="logo" href="{href}"><img src="resource?name=rhm-32x14.png"/></a> -->
-      <a href="{href}">Home</a>
-      <ul id="context">{frames}</ul>
-    </div>
-    <div id="body">{mode}</div>
-    <div id="foot">
-    </div>
+    {mode}
   </body>
 </html>
 
-[CuminPage.frame_html]
+[MainView.css]
+#head {
+  padding: 0;
+  background-color: #666;
+  border-bottom: 2px solid #999;
+  border-top: 3px solid #000;
+  color: #ddd;
+}
+
+#head a {
+  color: #fff;
+}
+
+body.modal #head {
+  opacity: 0.2;
+}
+
+#head .tabs {
+  padding: 0 0 0.25em 0.5em;
+  margin: 0;
+  list-style: none;
+}
+
+#head .tabs li {
+  display: inline;
+}
+
+#head .tabs li a {
+  padding: 0.275em 0.5em;
+  border-right: 2px solid #444;
+  background-color: #333;
+  color: #ccc;
+  line-height: 1.5em;
+}
+
+#head .tabs li:last-child a {
+  border-right: 0;
+}
+
+#head .tabs li a.selected {
+  background-color: #000;
+  color: #fff;
+  position: relative;
+  z-index: 2;
+}
+
+#body {
+  padding: 1em;
+}
+
+#logo {
+  vertical-align: -20%;
+}
+
+#user {
+  padding: 0.25em 0.25em 0 1em;
+  float: right;
+  list-style: none;
+  color: #fff;
+  margin: 0;
+}
+
+#user li {
+  display: inline;
+}
+
+#actions {
+  padding: 0.25em 0.5em;
+  float: right;
+  font-size: 0.9em;
+}
+
+#context {
+  display: inline;
+  list-style: none;
+  padding: 0 1em;
+  margin: 0;
+  line-height: 1.75em;
+  font-size: 0.9em;
+  color: #fff;
+}
+
+#context li {
+  display: inline;
+}
+
+#context li:before {
+  content: " > ";
+  font-weight: bold;
+  font-size: 0.8em;
+  color: #ccc;
+}
+
+#context li:last-child a {
+  color: #ddd;
+}
+
+#context li:first-child:before {
+  content: "";
+}
+
+[MainView.javascript]
+function updateActions(id, model) {
+    var pcount = model.invocations.pending;
+    var ccount = model.invocations.completed;
+    var ecount = model.invocations.failed;
+
+    var div = wooly.doc().elembyid(id);
+    var phs = div.elems("span", null, null, 0, 3);
+    var ph;
+
+    ph = phs.next();
+    ph.set(pcount);
+
+    ph = phs.next();
+    ph.set(ccount);
+
+    ph = phs.next();
+    ph.set(ecount);
+}
+
+function popupActions() {
+    window.open("actions.html", "actions",
+                "width=640,height=480,scrollbars=yes");
+}
+
+function updateMain(data) {
+    var model = data.objectify();
+
+    cumin.runModelListeners(model);
+}
+
+[MainView.html]
+<div id="head">
+  <div>
+    <ul id="user">
+      <li>Hi, <strong>nsantos</strong></li>
+      <li><a class="nav" href="">Log Out</a></li>
+    </ul>
+
+    <ul class="tabs">{tabs}</ul>
+  </div>
+
+  <div>
+    <div id="actions">
+      Actions:
+      <a href="javascript:popupActions()">
+        <span>{pending_count}</span> pending,
+        <span>{completed_count}</span> completed,
+        <span>{failed_count}</span> failed
+      </a>
+    </div>
+    <script>
+      cumin.modelListeners["actions"] = updateActions
+    </script>
+
+    <ul id="context">{frames}</ul>
+  </div>
+  <!-- <a id="logo" href="{href}"><img src="resource?name=rhm-32x14.png"/></a> -->
+</div>
+<div id="body">{mode}</div>
+<div id="foot"/>
+
+[MainView.frame_html]
 <li><a href="{frame_href}">{frame_title}</a></li>
 
-[MainView.html]
+[MessagingView.html]
+<script>
+  wooly.setIntervalUpdate("{data_url}", updateMain, 3000);
+</script>
 <div class="oblock">
-  <h1>
-    <img src="resource?name=mrg-36.png"/>{title}
-  </h1>
+  <ul class="TabSet tabs">{tabs}</ul>
+  <div class="TabSet mode">{mode}</div>
+</div>
 
+[GridView.html]
+<script>
+  wooly.setIntervalUpdate("{data_url}", updateMain, 3000);
+</script>
+<div class="oblock">
   <ul class="TabSet tabs">{tabs}</ul>
   <div class="TabSet mode">{mode}</div>
 </div>
+
+[SystemView.html]
+<script>
+  wooly.setIntervalUpdate("{data_url}", updateMain, 3000);
+</script>
+<div class="oblock">
+  <ul class="TabSet tabs">{tabs}</ul>
+  <div class="TabSet mode">{mode}</div>
+</div>

Modified: mgmt/cumin/python/cumin/parameters.py
===================================================================
--- mgmt/cumin/python/cumin/parameters.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/parameters.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -3,7 +3,7 @@
 
 class CuminClassParameter(Parameter):
     def do_unmarshal(self, string):
-        return self.app.model.get_class_by_name(string)
+        return getattr(self.app.model, string, None)
 
     def do_marshal(self, cls):
         return cls.name

Modified: mgmt/cumin/python/cumin/queue.py
===================================================================
--- mgmt/cumin/python/cumin/queue.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/queue.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -281,11 +281,8 @@
         return "Queue '%s'" % queue.name
 
     def render_data_url(self, session, queue):
-        return "queue.xml?id=%i" % queue.id
+        return "model.xml?class=queue;id=%i" % queue.id
 
-    def render_name(self, session, queue):
-        return queue.name
-
     def render_durable(self, session, queue):
         return fmt_predicate(queue.durable)
 
@@ -322,7 +319,7 @@
 
     def render_item_href(self, session, binding):
         branch = session.branch()
-        self.page().show_exchange(branch, binding.exchange)
+        self.frame().frame().show_exchange(branch, binding.exchange)
         return branch.marshal()
     
     def render_item_name(self, session, binding):
@@ -634,15 +631,3 @@
     def render_item_unacked_messages(self, session, consumer):
         stat = self.app.model.consumer.get_stat("unackedMessages")
         return stat.value(consumer)
-
-class QueueXmlPage(CuminXmlPage):
-    def __init__(self, app, name):
-        super(QueueXmlPage, self).__init__(app, name)
-
-        self.param = QueueParameter(app, "param")
-        self.add_parameter(self.param)
-
-        self.queues = ListParameter(app, "id", self.param)
-        self.add_parameter(self.queues)
-        
-        self.set_list_parameter(self.queues)

Modified: mgmt/cumin/python/cumin/queue.strings
===================================================================
--- mgmt/cumin/python/cumin/queue.strings	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/queue.strings	2008-02-03 02:45:22 UTC (rev 1633)
@@ -92,8 +92,6 @@
 
   <!-- <div>{status_info}</div> -->
 
-  <div>{actions_pending}</div>
-
   <table>
     <tr>
       <th></th>
@@ -123,12 +121,13 @@
   </table>
 </div>
 <script>
-  cumin.listeners["{id}"] = updateQueueStatus
+  cumin.objectListeners["{id}"] = updateQueueStatus
 </script>
 
 [QueueView.javascript]
 function updateQueue(data) {
-    var queues = data.root().object().queue;
+    var model = data.objectify();
+    var queues = model.queue;
     var queue;
 
     for (var key in queues) {
@@ -136,9 +135,8 @@
         break;
     }
 
-    for (var id in cumin.listeners) {
-        cumin.listeners[id](id, queue);
-    }
+    cumin.runModelListeners(model);
+    cumin.runObjectListeners(queue);
 
     //throw new Error();
 }
@@ -153,7 +151,6 @@
 <h1><img src="resource?name=queue-36.png"/>{title}</h1>
 
 <table class="props">
-  <tr><th>Name</th><td>{name}</td></tr>
   <tr><th>Durable?</th><td>{durable}</td></tr>
   <tr><th>Exclusive?</th><td>{exclusive}</td></tr>
   <tr><th>Created &ndash; Deleted</th><td>{created_deleted}</td></tr>

Modified: mgmt/cumin/python/cumin/stat.strings
===================================================================
--- mgmt/cumin/python/cumin/stat.strings	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/stat.strings	2008-02-03 02:45:22 UTC (rev 1633)
@@ -52,7 +52,7 @@
   {items}
 </table>
 <script>
-  cumin.listeners["{id}"] = updateStats;
+  cumin.objectListeners["{id}"] = updateStats;
 </script>
 
 [StatSet.item_html]
@@ -114,7 +114,7 @@
   </tr>
 </table>
 <script>
-  cumin.listeners["{id}"] = updateChart
+  cumin.objectListeners["{id}"] = updateChart
 </script>
 
 [StatValueChart.stat_html]

Modified: mgmt/cumin/python/cumin/util.py
===================================================================
--- mgmt/cumin/python/cumin/util.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/util.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -119,7 +119,7 @@
 
         return missing
 
-    def show(self):
+    def prt(self):
         print "Configuration:"
 
         for param in self.__params:

Modified: mgmt/cumin/python/cumin/widgets.py
===================================================================
--- mgmt/cumin/python/cumin/widgets.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/widgets.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -27,7 +27,8 @@
         self.__param = param
 
     def get_object(self, session, object):
-        return self.__param.get(session)
+        if self.__param:
+            return self.__param.get(session)
 
     def set_object(self, session, object):
         return self.__param.set(session, object)
@@ -183,10 +184,6 @@
         else:
             return "mstatus green"
 
-    def render_actions_pending(self, session, object):
-        count = len(self.app.model.data.outstandingMethodCalls)
-        return "%i action%s pending" % (count, ess(count))
-
     def render_status_info(self, session, object):
         error_count = 0 #XXX len(object.errors)
         warning_count = 0 #XXX len(object.warnings)
@@ -194,36 +191,7 @@
         return "%i error%s, %i warning%s" % \
                (error_count, ess(error_count),
                 warning_count, ess(warning_count))
-
-class CuminXmlPage(Page):
-    def __init__(self, app, name):
-        super(CuminXmlPage, self).__init__(app, name)
-
-        self.__param = None
     
-    def set_list_parameter(self, param):
-        self.__param = param
-
-    def get_object(self, session, objects):
-        return self.__param.get(session)
-
-    def get_content_type(self, session):
-        return Page.xml_content_type
-
-    def do_render(self, session, objects):
-        writer = Writer()
-
-        writer.write(Page.xml_1_0_declaration)
-        writer.write("<objects>");
-
-        for object in objects:
-            cls = self.app.model.get_class_by_object(object)
-            cls.write_xml(object, writer)
-
-        writer.write("</objects>");
-        
-        return writer.to_string()
-    
 class StateSwitch(ItemSet):
     def __init__(self, app, name):
         super(StateSwitch, self).__init__(app, name)

Modified: mgmt/cumin/python/cumin/widgets.strings
===================================================================
--- mgmt/cumin/python/cumin/widgets.strings	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/cumin/widgets.strings	2008-02-03 02:45:22 UTC (rev 1633)
@@ -86,14 +86,16 @@
     }
     */
 
+    /*
     var divs = status.elems("div", null, null, 0, 2)
 
-    //divs.next().set(errors + ", " + warnings);
+    divs.next().set(errors + ", " + warnings);
 
     var acount = object.actions.pending;
     var actions = acount + " " + (acount == "1" && "action" || "actions") + " pending";
 
     divs.next().set(actions);
+    */
 }
 
 [CuminStatus.html]
@@ -101,8 +103,6 @@
   <h2>Status</h2>
 
   <!-- <div>{status_info}</div> -->
-
-  <div>{actions_pending}</div>
 </div>
 
 [StateSwitch.html]

Modified: mgmt/cumin/python/wooly/__init__.py
===================================================================
--- mgmt/cumin/python/wooly/__init__.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/wooly/__init__.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -308,7 +308,7 @@
     def render_error_message(self, session, error):
         return error.message
 
-    def show(self):
+    def prt(self):
         print self
 
         for key, value in sorted(self.__dict__.items()):

Modified: mgmt/cumin/python/wooly/widgets.py
===================================================================
--- mgmt/cumin/python/wooly/widgets.py	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/python/wooly/widgets.py	2008-02-03 02:45:22 UTC (rev 1633)
@@ -19,7 +19,7 @@
         super(ModeSet, self).add_child(mode)
 
         if not self.mode.default:
-            self.mode.set_default(mode.name)
+            self.mode.default = mode.name
 
     def get_selected_mode(self, session):
         return self.get_child(self.mode.get(session))

Modified: mgmt/cumin/resources/wooly.js
===================================================================
--- mgmt/cumin/resources/wooly.js	2008-01-31 20:03:05 UTC (rev 1632)
+++ mgmt/cumin/resources/wooly.js	2008-02-03 02:45:22 UTC (rev 1633)
@@ -257,6 +257,7 @@
             return new WoolyElement(this, node.documentElement);
         }
 
+        // XXX rename to id
         this.elembyid = function(id) {
             var node = this.node.getElementById(id);
 
@@ -283,6 +284,10 @@
         this.elem = function(name, n) {
             return this.elems(name, n).next();
         }
+
+        this.objectify = function() {
+            return this.root().object();
+        }
     }
 
     function WoolyCollection(doc, nodes, nodeClass) {
@@ -383,6 +388,7 @@
             return dict;
         }
 
+        // XXX Rename to objectify
         this.object = function() {
             return translate(this.node, null);
         }




More information about the rhmessaging-commits mailing list