=== modified file 'dashboard_app/extension.py'
@@ -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'
@@ -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'
@@ -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'
@@ -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'
@@ -0,0 +1,6 @@
+.lava-chart {
+ width: 600px;
+ height: 250px;
+ margin: 1em auto;
+ padding: 1em;
+}
=== modified file 'dashboard_app/templates/dashboard_app/_extrahead.html'
@@ -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'
@@ -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'
@@ -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 %}