Index: /trunk/controllers/servicegroups.php
===================================================================
--- /trunk/controllers/servicegroups.php	(revision 82)
+++ /trunk/controllers/servicegroups.php	(revision 86)
@@ -15,4 +15,7 @@
  */
 
+require_once("include/auth.php");
+require_once("plugins/npc/controllers/comments.php");
+
 /**
  * Servicegroups controller class
@@ -91,5 +94,5 @@
 
     /**
-     * getServiceStatusPortlet
+     * getServicegroupServiceStatus
      * 
      * Returns service status counts by servicegroup.
@@ -97,5 +100,5 @@
      * @return string   json output
      */
-    function getServiceStatusPortlet() {
+    function getServicegroupServiceStatus() {
 
         // Initialize the output array
@@ -109,11 +112,6 @@
         $results = $this->setupResultsArray();
 
-        // Loop through the results array and build an ouput array
-        // that includes a single record per servicegroup
-        // and the number of crit, warn , ok services within 
-        // that servicegroup.
         for ($i = 0; $i < count($results); $i++) {
             $sg = $results[$i]['servicegroup_object_id'];
-            $hostState = $this->getServicegroupMemberHoststatus($results[$i]['host_name']);
             if(!isset($output[$sg])) {
                 $output[$sg] = array('critical' => 0,
@@ -172,9 +170,9 @@
             if(!isset($temp[$sg][$host])) {
                 $temp[$sg][$host] = array('host_state' => $hostState,
-                                            'critical' => 0,
-                                            'warning'  => 0,
-                                            'unknown'  => 0,
-                                            'ok'       => 0,
-                                            'pending'  => 0);
+                                          'critical' => 0,
+                                          'warning'  => 0,
+                                          'unknown'  => 0,
+                                          'ok'       => 0,
+                                          'pending'  => 0);
             }
             foreach ($results[$i] as $key => $val) {
@@ -230,13 +228,25 @@
     function getServices() {
 
-        $output = $this->setupResultsArray();
+        $results = $this->setupResultsArray();
+
+        $comments = new NpcCommentsController;
+
+        $services = $this->flattenArray($results);
+
+        for ($i = 0; $i < count($services); $i++) {
+            if ($services[$i]['problem_has_been_acknowledged']) {
+                $services[$i]['acknowledgement'] = $comments->getAck($services[$i]['service_object_id']);
+            }
+            // Add the last comment to the array
+            $services[$i]['comment'] = $comments->getLastComment($services[$i]['service_object_id']);
+        }
 
         // Set the total number of records 
-        $this->numRecords = count($output);
+        $this->numRecords = count($services);
 
         // Implement paging by slicing the ouput array
-        $output = array_slice($output, $this->start, $this->limit);
-
-        return($this->jsonOutput($output));
+        $services = array_slice($services, $this->start, $this->limit);
+
+        return($this->jsonOutput($services));
     }
 
@@ -280,9 +290,7 @@
         $q->select('i.instance_name,'
                     .'o1.name1 AS servicegroup_name,'
-                    .'ss.service_object_id,'
-                    .'ss.current_state,' 
-                    .'ss.output,' 
                     .'o2.name1 AS host_name,'
                     .'o2.name2 AS service_description,'
+                    .'ss.*,' 
                     .'sg.*')
             ->from('NpcServicegroups sg')
Index: /trunk/controllers/hostgroups.php
===================================================================
--- /trunk/controllers/hostgroups.php	(revision 82)
+++ /trunk/controllers/hostgroups.php	(revision 86)
@@ -38,4 +38,99 @@
 
     /**
+     * getHostgroupHostStatus
+     * 
+     * Returns host status counts by hostgroup.
+     *
+     * @return string   json output
+     */
+    function getHostgroupHostStatus() {
+
+        // Initialize the output array
+        $output = array();
+
+        // Initialize the hosts array
+        $hosts = array();
+
+        $fields = array('hostgroup_object_id',
+                        'alias',
+                        'instance_id');
+
+        $results = $this->setupResultsArray();
+
+        for ($i = 0; $i < count($results); $i++) {
+            $hg = $results[$i]['hostgroup_object_id'];
+            if(!isset($output[$hg])) {
+                $output[$hg] = array('down'        => 0,
+                                     'unreachable' => 0,
+                                     'up'          => 0,
+                                     'pending'     => 0);
+            }
+            if (!isset($hosts[$hg][$results[$i]['host_name']])) {
+                $output[$hg][$this->hostState[$results[$i]['current_state']]]++;
+                $hosts[$hg][$results[$i]['host_name']] = 1;
+            }
+            foreach ($results[$i] as $key => $val) {
+                if (in_array($key, $fields)) {
+                    $output[$hg][$key] = $val;
+                }
+            }
+        }
+
+        // Set the total number of records 
+        $this->numRecords = count($output);
+
+        // Implement paging by slicing the ouput array
+        $output = array_slice($output, $this->start, $this->limit);
+
+        return($this->jsonOutput($output));
+    }
+
+    /**
+     * getHostgroupServiceStatus
+     * 
+     * Returns service status counts by hostgroup.
+     *
+     * @return string   json output
+     */
+    function getHostgroupServiceStatus() {
+
+        // Initialize the output array
+        $output = array();
+
+        $fields = array('hostgroup_object_id',
+                        'alias',
+                        'instance_id');
+                 
+        // Combine servicegroup/service/host etc. into a single record
+        $results = $this->setupResultsArray();
+
+        for ($i = 0; $i < count($results); $i++) {
+            $hg = $results[$i]['hostgroup_object_id'];
+            $ss = $this->getHostgroupMemberServiceStatus($results[$i]['host_object_id']);
+            if(!isset($output[$hg])) {
+                $output[$hg] = $ss;
+            } else {
+                foreach ($ss as $k => $v) {
+                    $output[$hg][$k] = $output[$hg][$k] + $v;
+                }
+            }
+            foreach ($results[$i] as $key => $val) {
+                if (in_array($key, $fields)) {
+                    $output[$hg][$key] = $val;
+                }
+            }
+        }
+
+        // Set the total number of records 
+        $this->numRecords = count($output);
+
+        // Implement paging by slicing the ouput array
+        $output = array_slice($output, $this->start, $this->limit);
+
+        return($this->jsonOutput($output));
+    }
+
+
+    /**
      * getOverview
      * 
@@ -58,8 +153,9 @@
         $results = $this->setupResultsArray();
 
-        // Loop through the results array and build an ouput array
-        // that includes a single record per host within the hostgroup
-        // and the number of crit, warn , ok services within 
-        // that hostgroup.
+        /*  Loop through the results array and build an ouput array
+         *  that includes a single record per host within the hostgroup
+         *  and the number of crit, warn , ok services within 
+         *  that hostgroup.
+         */
         for ($i = 0; $i < count($results); $i++) {
             $hg = $results[$i]['hostgroup_object_id'];
Index: /trunk/controllers/layout.php
===================================================================
--- /trunk/controllers/layout.php	(revision 84)
+++ /trunk/controllers/layout.php	(revision 86)
@@ -93,4 +93,6 @@
           <script type="text/javascript" src="<?php echo $config["url_path"]; ?>plugins/npc/js/dashboard/servicegroup-service-status-portlet.js"></script>
           <script type="text/javascript" src="<?php echo $config["url_path"]; ?>plugins/npc/js/dashboard/servicegroup-host-status-portlet.js"></script>
+          <script type="text/javascript" src="<?php echo $config["url_path"]; ?>plugins/npc/js/dashboard/hostgroup-host-status-portlet.js"></script>
+          <script type="text/javascript" src="<?php echo $config["url_path"]; ?>plugins/npc/js/dashboard/hostgroup-service-status-portlet.js"></script>
 
           <script type="text/javascript">
Index: /trunk/setup.php
===================================================================
--- /trunk/setup.php	(revision 75)
+++ /trunk/setup.php	(revision 86)
@@ -81,8 +81,10 @@
         "serviceSummary" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol1%5Ehidden%3Db%253A0%5Eindex%3Ds%253A2%5Erefresh%3Dn%253A60%5Erows%3Dn%253A10',
         "servicegroupServiceStatus" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol1%5Ehidden%3Db%253A0%5Eindex%3Ds%253A2%5Erefresh%3Dn%253A60%5Erows%3Dn%253A10',
+        "hostgroupServiceStatus" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol1%5Ehidden%3Db%253A0%5Eindex%3Ds%253A3%5Erefresh%3Dn%253A60%5Erows%3Dn%253A10',
         "monitoringPerf" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol2%5Ehidden%3Db%253A0%5Eindex%3Ds%253A0%5Erefresh%3Dn%253A60%5Erows%3Dn%253A10',
         "hostSummary" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol2%5Ehidden%3Db%253A0%5Eindex%3Ds%253A1%5Erefresh%3Dn%253A60%5Erows%3Dn%253A10',
         "servicegroupHostStatus" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol2%5Ehidden%3Db%253A0%5Eindex%3Ds%253A2%5Erefresh%3Dn%253A60%5Erows%3Dn%253A10',
-        "eventLog" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol2%5Ehidden%3Db%253A1%5Eindex%3Ds%253A3%5Erefresh%3Dn%253A60%5Erows%3Dn%253A5'
+        "hostgroupHostStatus" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol2%5Ehidden%3Db%253A0%5Eindex%3Ds%253A3%5Erefresh%3Dn%253A60%5Erows%3Dn%253A10',
+        "eventLog" => 'o%3Acollapsed%3Db%253A0%5Ecolumn%3Ds%253Adashcol2%5Ehidden%3Db%253A1%5Eindex%3Ds%253A4%5Erefresh%3Dn%253A60%5Erows%3Dn%253A5'
     );
 
Index: /trunk/js/dashboard/hostgroup-host-status-portlet.js
===================================================================
--- /trunk/js/dashboard/hostgroup-host-status-portlet.js	(revision 76)
+++ /trunk/js/dashboard/hostgroup-host-status-portlet.js	(revision 86)
@@ -8,5 +8,5 @@
 
     // Portlet URL
-    var url = 'npc.php?module=hostgroups&action=getHostStatusPortlet';
+    var url = 'npc.php?module=hostgroups&action=getHostgroupHostStatus';
 
     // Default column
@@ -26,5 +26,5 @@
             'alias',
             {name: 'instance_id', type: 'int'},
-            {name: 'servicegroup_object_id', type: 'int'},
+            {name: 'hostgroup_object_id', type: 'int'},
             {name: 'down', type: 'int'},
             {name: 'unreachable', type: 'int'},
@@ -134,10 +134,10 @@
     }
 
-    grid.on('rowclick', sgClick);
+    grid.on('rowclick', hgClick);
 
-    function sgClick(grid, rowIndex, e) {
-        var hoi = grid.getStore().getAt(rowIndex).json.servicegroup_object_id;
+    function hgClick(grid, rowIndex, e) {
+        var hoi = grid.getStore().getAt(rowIndex).json.hostgroup_object_id;
         var name = grid.getStore().getAt(rowIndex).json.alias;
-        npc.app.hostGroupGrid('hostGroupGrid-'+soi, 'Hostgroup: '+name, hoi);
+        npc.app.hostGroupGrid('hostGroupGrid-'+hoi, 'Hostgroup: '+name, hoi);
     }
 };
Index: /trunk/js/dashboard/hostgroup-service-status-portlet.js
===================================================================
--- /trunk/js/dashboard/hostgroup-service-status-portlet.js	(revision 86)
+++ /trunk/js/dashboard/hostgroup-service-status-portlet.js	(revision 86)
@@ -0,0 +1,151 @@
+npc.app.portlet.hostgroupServiceStatus = function(){
+
+    // Portlet name
+    var name = 'Hostgroup: Service Status';
+
+    // Portlet ID
+    var id = 'hostgroupServiceStatus';
+
+    // Portlet URL
+    var url = 'npc.php?module=hostgroups&action=getHostgroupServiceStatus';
+
+    // Default column
+    var column = 'dashcol2';
+
+    // Default # of events to display
+    var pageSize = 10;
+
+    // Setup the data store
+    var store = new Ext.data.JsonStore({
+        url:url,
+        autoload:true,
+        sortInfo:{field: 'alias', direction: "ASC"},
+        totalProperty:'totalCount',
+        root:'data',
+        fields:[
+            'alias',
+            {name: 'instance_id', type: 'int'},
+            {name: 'hostgroup_object_id', type: 'int'},
+            {name: 'critical', type: 'int'},
+            {name: 'warning', type: 'int'},
+            {name: 'unknown', type: 'int'},
+            {name: 'ok', type: 'int'},
+            {name: 'pending', type: 'int'}
+        ]
+    });
+
+    // Setup the column model
+    var cm = new Ext.grid.ColumnModel([{
+        header:"Hostgroup",
+        dataIndex:'alias',
+        sortable:true
+    },{
+        id: 'hgSSCRITICAL',
+        header:"Critical",
+        dataIndex:'critical',
+        align:'center',
+        width:40,
+        renderer: npc.app.renderStatusBg
+    },{
+        id: 'hgSSWARNING',
+        header:"Warning",
+        dataIndex:'warning',
+        align:'center',
+        width:40,
+        renderer: npc.app.renderStatusBg
+    },{
+        id: 'hgSSUNKNOWN',
+        header:"Unknown",
+        dataIndex:'unknown',
+        align:'center',
+        width:40,
+        renderer: npc.app.renderStatusBg
+    },{
+        id: 'hgSSOK',
+        header:"Ok",
+        dataIndex:'ok',
+        align:'center',
+        width:20,
+        renderer: npc.app.renderStatusBg
+    },{
+        id: 'hgSSPENDING',
+        header:"Pending",
+        dataIndex:'pending',
+        align:'center',
+        width:40,
+        renderer: npc.app.renderStatusBg
+    }]);
+
+    // Setup the grid
+    var grid = new Ext.grid.GridPanel({
+        id: 'hostgroup-service-status-grid',
+        autoHeight:true,
+        autoExpandColumn: 'alias',
+        store:store,
+        cm:cm,
+        sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
+        stripeRows: true,
+        view: new Ext.grid.GridView({
+             forceFit:true,
+             autoFill:true,
+             scrollOffset:0
+        }),
+        bbar: new Ext.PagingToolbar({
+            pageSize: pageSize,
+            store: store,
+            displayInfo: true,
+            displayMsg: ''
+        })
+    });
+
+    // Create a portlet to hold the grid
+    npc.app.addPortlet(id, name, column);
+
+    // Add the grid to the portlet
+    Ext.getCmp(id).items.add(grid);
+
+    // Refresh the dashboard
+    Ext.getCmp('centerTabPanel').doLayout();
+
+    // Render the grid
+    grid.render();
+
+    // Load the data store
+    store.load({params:{start:0, limit:pageSize}});
+
+    // Start auto refresh of the grid
+    if (Ext.getCmp(id).isVisible()) {
+        doAutoRefresh();
+    }
+
+    // Add listeners to the portlet to stop and start auto refresh
+    // depending on wether or not the portlet is visible.
+    var listeners = {
+        hide: function() {
+            store.stopAutoRefresh();
+        },
+        show: function() {
+            doAutoRefresh();
+        },
+        collapse: function() {
+            store.stopAutoRefresh();
+        },
+        expand: function() {
+            doAutoRefresh();
+        }
+    };
+
+    Ext.getCmp(id).addListener(listeners);
+
+    function doAutoRefresh() {
+        store.startAutoRefresh(npc.app.params.npc_portlet_refresh);
+    }
+
+    grid.on('rowclick', hgClick);
+
+    function hgClick(grid, rowIndex, e) {
+        var hoi = grid.getStore().getAt(rowIndex).json.hostgroup_object_id;
+        var name = grid.getStore().getAt(rowIndex).json.alias;
+        npc.app.hostgroupGrid('hostgroupGrid-'+hoi, 'Hostgroup: '+name, hoi);
+    }
+};
Index: /trunk/js/dashboard/servicegroup-service-status-portlet.js
===================================================================
--- /trunk/js/dashboard/servicegroup-service-status-portlet.js	(revision 78)
+++ /trunk/js/dashboard/servicegroup-service-status-portlet.js	(revision 86)
@@ -8,5 +8,5 @@
 
     // Portlet URL
-    var url = 'npc.php?module=servicegroups&action=getServiceStatusPortlet';
+    var url = 'npc.php?module=servicegroups&action=getServicegroupServiceStatus';
 
     // Default column
Index: /trunk/js/hosts.js
===================================================================
--- /trunk/js/hosts.js	(revision 85)
+++ /trunk/js/hosts.js	(revision 86)
@@ -53,8 +53,9 @@
             'comment',
             {name: 'service_count', type: 'int'},
-            'output',
             {name: 'current_state', type: 'int'},
             'current_check_attempt',
             'max_check_attempts',
+            'output',
+            'acknowledgement',
             {name: 'last_check', type: 'date', dateFormat: 'Y-m-d H:i:s'},
             {name: 'next_check', type: 'date', dateFormat: 'Y-m-d H:i:s'},
Index: /trunk/js/npc.js
===================================================================
--- /trunk/js/npc.js	(revision 85)
+++ /trunk/js/npc.js	(revision 86)
@@ -309,5 +309,5 @@
             if (record.data.problem_has_been_acknowledged == 1) {
                 var ack = record.data.acknowledgement.split("*|*");
-                img = String.format('&nbsp;<img ext:qtitle="Acknowledged by {0}" ext:qtip="{1}" src="images/icons/wrench.png">', ack[0], ack[1]);
+                img = String.format('&nbsp;<img ext:qtitle="Acknowledged by {0}" ext:qtip=\'{1}\' src="images/icons/wrench.png">', ack[0], ack[1]);
             }
             if (record.data.notifications_enabled == 0) {
@@ -316,5 +316,5 @@
             if (record.data.comment) {
                 var c = record.data.comment.split("*|*");
-                img = String.format('&nbsp;<img qtitle="{0}" ext:qtip="{1}" src="images/icons/comment.png">', c[0], c[1]) + img;
+                img = String.format('&nbsp;<img qtitle="{0}" ext:qtip=\'{1}\' src="images/icons/comment.png">', c[0], c[1]) + img;
             }
             if (record.data.is_flapping) {
Index: /trunk/js/servicegroupGrid.js
===================================================================
--- /trunk/js/servicegroupGrid.js	(revision 84)
+++ /trunk/js/servicegroupGrid.js	(revision 86)
@@ -65,5 +65,13 @@
             'service_object_id',
             'host_name',
-            'service_description'
+            'service_description',
+            'comment',
+            'acknowledgement',
+            {name: 'problem_has_been_acknowledged', type: 'int'},
+            {name: 'notifications_enabled', type: 'int'},
+            {name: 'active_checks_enabled', type: 'int'},
+            {name: 'passive_checks_enabled', type: 'int'},
+            {name: 'is_flapping', type: 'int'}
+
         ]),
         groupField:'alias'
@@ -78,4 +86,5 @@
         header:"Service",
         dataIndex:'service_description',
+        renderer:npc.app.renderExtraIcons,
         width:75
     },{
