=== modified file 'dashboard_app/extension.py'
--- dashboard_app/extension.py	2011-09-30 13:43:50 +0000
+++ dashboard_app/extension.py	2011-10-13 11:56:10 +0000
@@ -39,6 +39,12 @@
     def front_page_template(self):
         return "dashboard_app/front_page_snippet.html"
 
+    def get_front_page_context(self):
+        from dashboard_app.models import DataReport
+        return {
+            'report_list': DataReport.repository.filter(front_page=True)
+        }
+
     @property
     def description(self):
         return "Validation Dashboard"
@@ -56,10 +62,7 @@
 
     def contribute_to_settings(self, settings_module):
         super(DashboardExtension, self).contribute_to_settings(settings_module)
-        settings_module['INSTALLED_APPS'].extend([
-            "linaro_django_pagination",
-            "south",
-        ])
+        settings_module['INSTALLED_APPS'].append("linaro_django_pagination")
         settings_module['MIDDLEWARE_CLASSES'].append(
             'linaro_django_pagination.middleware.PaginationMiddleware')
         root_dir = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))

=== modified file 'dashboard_app/models.py'
--- dashboard_app/models.py	2011-09-28 02:35:22 +0000
+++ dashboard_app/models.py	2011-10-13 11:55:44 +0000
@@ -1276,6 +1276,10 @@
     def author(self):
         return self._data.get('author')
 
+    @property
+    def front_page(self):
+        return self._data['front_page']
+
 
 class ImageHealth(object):
 
@@ -1332,6 +1336,10 @@
         since = until - datetime.timedelta(days=last_n_days)
         return self.get_test_runs(
         ).select_related(
+            'denormalization',
+            'bundle',
+            'bundle__bundle_stream',
+            'test',
         ).filter(
             analyzer_assigned_date__range=(since, until)
         ).order_by('-analyzer_assigned_date')

=== modified file 'dashboard_app/repositories/__init__.py'
--- dashboard_app/repositories/__init__.py	2011-07-22 00:04:21 +0000
+++ dashboard_app/repositories/__init__.py	2011-10-13 11:55:18 +0000
@@ -16,9 +16,13 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with Launch Control.  If not, see <http://www.gnu.org/licenses/>.
 
+
+from __future__ import with_statement
+
 import abc
 import logging
 import os
+import thread
 
 from django.conf import settings
 
@@ -126,19 +130,23 @@
 
     __metaclass__ = abc.ABCMeta
 
+    loader_lock = thread.allocate_lock()
+
     def __init__(self):
         self.item_cls = None  # later patched by RepositoryItemMeta
         self._items = []
         self._did_load = False
 
     def _queryset(self):
-        # In development mode always reload repository items
-        if getattr(settings, "DEBUG", False) is True:
-            self._did_load = False
-        if not self._did_load:
-            self._items = []
-            self._load_default()
-            self._did_load = True
+        # HOT FIX: use a lock while loading the stuff from disk
+        with self.loader_lock:
+            # In development mode always reload repository items
+            if getattr(settings, "DEBUG", False) is True:
+                self._did_load = False
+            if not self._did_load:
+                self._items = []
+                self._load_default()
+                self._did_load = True
         return RepositoryQuerySet(self.item_cls, self._items)
 
     def all(self):

=== modified file 'dashboard_app/repositories/data_report.py'
--- dashboard_app/repositories/data_report.py	2011-07-22 00:07:21 +0000
+++ dashboard_app/repositories/data_report.py	2011-10-13 11:55:44 +0000
@@ -47,6 +47,7 @@
             if "name" not in attrs:
                 raise ValueError("Data report without a name")
             self.obj.name = attrs["name"]
+            self.obj.front_page = attrs.get('front_page') == "yes"
         elif name == "title" or name == "path":
             self._start_text()
                 
@@ -69,7 +70,8 @@
         return self.item_cls(
             name=handler.obj.name,
             title=handler.obj.title,
-            path=handler.obj.path)
+            path=handler.obj.path,
+            front_page=handler.obj.front_page)
 
 
 __all__ = [

=== added file 'dashboard_app/static/css/dashboard.css'
--- dashboard_app/static/css/dashboard.css	1970-01-01 00:00:00 +0000
+++ dashboard_app/static/css/dashboard.css	2011-10-13 14:40:48 +0000
@@ -0,0 +1,6 @@
+.lava-chart {
+  width: 600px;
+  height: 250px;
+  margin: 1em auto;
+  padding: 1em;
+}

=== modified file 'dashboard_app/templates/dashboard_app/_extrahead.html'
--- dashboard_app/templates/dashboard_app/_extrahead.html	2011-07-13 11:07:18 +0000
+++ dashboard_app/templates/dashboard_app/_extrahead.html	2011-10-13 14:40:48 +0000
@@ -1,3 +1,4 @@
 <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}lava-server/css/demo_table_jui.css"/>
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/dashboard.css"/>
 <script type="text/javascript" src="{{ STATIC_URL }}dashboard_app/js/FixedHeader.min.js"></script> 
 <script type="text/javascript" src="{{ STATIC_URL }}lava-server/js/jquery.dataTables.min.js"></script> 

=== modified file 'dashboard_app/templates/dashboard_app/front_page_snippet.html'
--- dashboard_app/templates/dashboard_app/front_page_snippet.html	2011-09-19 11:20:07 +0000
+++ dashboard_app/templates/dashboard_app/front_page_snippet.html	2011-10-13 14:40:48 +0000
@@ -1,29 +1,13 @@
-<p>Click on image description to see automatic QA report</p>
-{% regroup dashboard.interesting_images by rootfs_type as rootfs_list %}
-{% for rootfs in rootfs_list %}
-<style type="text/css">
-  .column {
-    float: left;
-    width: 25em;
-    padding: 2pt; 
-  }
-  .column h4 {
-    margin: 0;
-  }
-  .column ul {
-    padding: 0;
-    margin: 0 0 0 1em;
-    list-style-position: inside;
-  }
+<!--[if IE]><script type="text/javascript" src="{{ STATIC_URL }}dashboard_app/js/excanvas.min.js"></script><![endif]-->
+<script type="text/javascript" src="{{ STATIC_URL }}dashboard_app/js/jquery.rpc.js"></script>
+<script type="text/javascript" src="{{ STATIC_URL }}dashboard_app/js/jquery.flot.min.js"></script>
+<script type="text/javascript" src="{{ STATIC_URL }}dashboard_app/js/jquery.dashboard.js"></script>
+{% include "dashboard_app/_extrahead.html" %}
 
-</style>
-<div class="column">
-  <h4>{{ rootfs.grouper|capfirst }}</h4>
-  <ul>
-    {% for image_health in rootfs.list %}
-    <li><a href="{{ image_health.get_absolute_url }}">{{ image_health.rootfs_type }} + {{ image_health.hwpack_type }}</a></li>
-    {% endfor %}
-  </ul>
-</div>
-{% endfor %} 
-<div style="clear:both;"></div>
+{% for report in report_list %}
+<h4>{{ report }}</h4>
+{{ report.get_html|safe }}
+{% empty %}
+<p>Currently no reports are configured for
+display on the front page</p>
+{% endfor %}

=== modified file 'dashboard_app/templates/dashboard_app/image_status_detail.html'
--- dashboard_app/templates/dashboard_app/image_status_detail.html	2011-08-19 04:06:47 +0000
+++ dashboard_app/templates/dashboard_app/image_status_detail.html	2011-10-11 12:02:02 +0000
@@ -110,58 +110,70 @@
   }); 
 </script>
 <style type="text/css">
-  .result_0 {
+  .result_pass {
     background-color: #3aad3a;
   }
   
-  .result_1 {
+  .result_fail {
     background-color: #ff3800;
   }
   
-  .result_2 {
+  .result_skip {
     background-color: yellow;
   }
   
-  .result_3 {
+  .result_unknown {
     background-color: #aaad9c;
   }
-
+  
   .helper {
     float: left;
     height: 1em;
     margin-left: 1px;
   }
+
+  table.special {
+    border-collapse: collapse;
+    width: 100%;
+  }
+
+  table.special th {
+    text-align: left;
+    border-bottom: 1px solid #333;
+    padding: 2pt;
+  }
 </style>
-<table style="width: 100%">
+<table class="special">
   {% regroup recent_test_run_list by analyzer_assigned_date|date:"Y-m-d" as test_run_cluster_list %}
   {% for test_run_cluster in test_run_cluster_list %}
   <tr>
-    <th colspan="3" style="text-align: left; border-bottom: 1px solid #333;"
-      >Tests ran on {{ test_run_cluster.grouper }}</th>
+    <th colspan="2">Tests ran on {{ test_run_cluster.grouper }}</th>
+    <th>Pass</th>
+    <th>Fail</th>
+    <th>Skip</th>
+    <th>Unknown</th>
   </tr>
   {% for test_run in test_run_cluster.list %}
   <tr>
-    {% with test_run.test_results.all.order_by as all_results %}
     <td><a href="{{ test_run.get_absolute_url }}">{{ test_run.test }}</a></td>
-    <td>{{ all_results.count }}</td>
+    {% with test_run.denormalization as denormalization %}
     <td>
       {% spaceless %}
-      {% regroup all_results|dictsort:"result" by result as result_group_list %}
-      {% for result_group in result_group_list %}
-      {% if result_group.list|length > 300 %}
-      <div class="result_{{ result_group.grouper }} helper"
-        style="width: {% widthratio result_group.list|length all_results.count 190 %}px;"></div>
-      <div style="float: left; width: 2:0px; text-align: center">...</div>
-      <div class="result_{{ result_group.grouper }} helper"
-        style="width: {% widthratio result_group.list|length all_results.count 190 %}px;"></div>
-      {% else %}
-      <div class="result_{{ result_group.grouper }} helper"
-        style="width: {% widthratio result_group.list|length all_results.count all_results.count %}px;"></div>
-      {% endif %}
-      {% endfor %}
+      <div class="result_pass helper"
+        style="width: {% widthratio denormalization.count_pass denormalization.count_all 500 %}px;"></div>
+      <div class="result_fail helper"
+        style="width: {% widthratio denormalization.count_fail denormalization.count_all 500 %}px;"></div>
+      <div class="result_skip helper"
+        style="width: {% widthratio denormalization.count_skip denormalization.count_all 500 %}px;"></div>
+      <div class="result_unknown helper"
+        style="width: {% widthratio denormalization.count_unknown denormalization.count_all 500 %}px;"></div>
       {% endspaceless %}
-      {% endwith %}
     </td>
+    <td>{{ denormalization.count_pass }}</td>
+    <td>{{ denormalization.count_fail }}</td>
+    <td>{{ denormalization.count_skip }}</td>
+    <td>{{ denormalization.count_unknown }}</td>
+    {% endwith %}
   </tr>
   {% endfor %}
   {% endfor %}

