diff options
-rw-r--r-- | rrs/urls.py | 7 | ||||
-rw-r--r-- | rrs/views.py | 82 | ||||
-rw-r--r-- | templates/rrs/base_toplevel.html | 12 | ||||
-rw-r--r-- | templates/rrs/rrs_stats.html | 48 |
4 files changed, 146 insertions, 3 deletions
diff --git a/rrs/urls.py b/rrs/urls.py index 18fa61be54..4524b9633e 100644 --- a/rrs/urls.py +++ b/rrs/urls.py @@ -2,7 +2,8 @@ from django.conf.urls import patterns, include, url from rrs.models import Release, Milestone from rrs.views import RecipeListView, recipes_report, RecipeDetailView, \ - MaintainerListView, FrontPageRedirect, MaintenancePlanRedirect + MaintainerListView, FrontPageRedirect, MaintenancePlanRedirect, \ + MaintenanceStatsView urlpatterns = patterns('', url(r'^$', FrontPageRedirect.as_view(), @@ -25,4 +26,8 @@ urlpatterns = patterns('', MaintainerListView.as_view( template_name='rrs/maintainers.html'), name="rrs_maintainers"), + url(r'^stats/(?P<maintplan_name>.*)/(?P<release_name>.*)/(?P<milestone_name>.*)/$', + MaintenanceStatsView.as_view( + template_name='rrs/rrs_stats.html'), + name="rrs_stats"), ) diff --git a/rrs/views.py b/rrs/views.py index ed05e8196e..432e30ac03 100644 --- a/rrs/views.py +++ b/rrs/views.py @@ -6,7 +6,7 @@ from django.http import HttpResponse from datetime import date, datetime from django.http import Http404 from django.shortcuts import get_object_or_404 -from django.views.generic import ListView, DetailView, RedirectView +from django.views.generic import TemplateView, ListView, DetailView, RedirectView from django.core.urlresolvers import resolve, reverse, reverse_lazy from django.db import connection @@ -841,3 +841,83 @@ class MaintainerListView(ListView): return context + +class MaintenanceStatsView(TemplateView): + def get_context_data(self, **kwargs): + context = super(MaintenanceStatsView, self).get_context_data(**kwargs) + + context['this_url_name'] = resolve(self.request.path_info).url_name + + self.maintplan_name = self.kwargs['maintplan_name'] + maintplan = get_object_or_404(MaintenancePlan, name=self.maintplan_name) + self.release_name = self.kwargs['release_name'] + release = get_object_or_404(Release, plan=maintplan, name=self.release_name) + self.milestone_name = self.kwargs['milestone_name'] + milestone = get_object_or_404(Milestone, release = release, name=self.milestone_name) + + self.milestone_statistics = _get_milestone_statistics(milestone) + + context['recipes_percentage'] = self.milestone_statistics['percentage'] + context['recipes_all_upgraded'] = self.milestone_statistics['all_upgraded'] + context['recipes_all_not_upgraded'] = self.milestone_statistics['all_not_upgraded'] + context['recipes_up_to_date'] = self.milestone_statistics['up_to_date'] + context['recipes_not_updated'] = self.milestone_statistics['not_updated'] + context['recipes_cant_be_updated'] = self.milestone_statistics['cant_be_updated'] + context['recipes_unknown'] = self.milestone_statistics['unknown'] + context['recipes_percentage_up_to_date'] = \ + self.milestone_statistics['percentage_up_to_date'] + context['recipes_percentage_not_updated'] = \ + self.milestone_statistics['percentage_not_updated'] + context['recipes_percentage_cant_be_updated'] = \ + self.milestone_statistics['percentage_cant_be_updated'] + context['recipes_percentage_unknown'] = \ + self.milestone_statistics['percentage_unknown'] + + # *** Upstream status chart *** + statuses = [] + status_counts = {} + statuses.append('Up-to-date') + status_counts['Up-to-date'] = self.milestone_statistics['up_to_date'] + statuses.append('Not updated') + status_counts['Not updated'] = self.milestone_statistics['not_updated'] + statuses.append('Can\'t be updated') + status_counts['Can\'t be updated'] = self.milestone_statistics['cant_be_updated'] + statuses.append('Unknown') + status_counts['Unknown'] = self.milestone_statistics['unknown'] + + statuses = sorted(statuses, key=lambda status: status_counts[status], reverse=True) + chartdata = {'x': statuses, 'y': [status_counts[k] for k in statuses]} + context['charttype_status'] = 'discreteBarChart' + context['chartdata_status'] = chartdata + context['extra_status'] = { + 'x_is_date': False, + 'x_axis_format': '', + 'tag_script_js': True, + 'jquery_on_ready': False, + } + + # *** Patch status chart *** + patch_statuses = [] + patch_status_counts = {} + for maintplanlayer in maintplan.maintenanceplanlayerbranch_set.all(): + layerbranch = maintplanlayer.layerbranch + patches = Patch.objects.filter(recipe__layerbranch=layerbranch) + for choice, desc in Patch.PATCH_STATUS_CHOICES: + if desc not in patch_statuses: + patch_statuses.append(desc) + patch_status_counts[desc] = patch_status_counts.get(desc, 0) + patches.filter(status=choice).count() + + patch_statuses = sorted(patch_statuses, key=lambda status: patch_status_counts[status], reverse=True) + chartdata = {'x': patch_statuses, 'y': [patch_status_counts[k] for k in patch_statuses]} + context['charttype_patchstatus'] = 'discreteBarChart' + context['chartdata_patchstatus'] = chartdata + context['extra_patchstatus'] = { + 'x_is_date': False, + 'x_axis_format': '', + 'tag_script_js': True, + 'jquery_on_ready': False, + } + + return context + + diff --git a/templates/rrs/base_toplevel.html b/templates/rrs/base_toplevel.html index e22684b497..47bc71900f 100644 --- a/templates/rrs/base_toplevel.html +++ b/templates/rrs/base_toplevel.html @@ -131,7 +131,17 @@ {% endif %} Maintainer statistics</a> </li> - </ul> + + {% if this_url_name == 'rrs_stats' %} + <li class="active"> + <a href="#"> + {% else %} + <li> + <a href="{% url 'rrs_stats' maintplan_name release_name milestone_name %}"> + {% endif %} + Charts</a> + </li> + </ul> {% endblock %} {% block content_inner %}{% endblock %} diff --git a/templates/rrs/rrs_stats.html b/templates/rrs/rrs_stats.html new file mode 100644 index 0000000000..092d817b9f --- /dev/null +++ b/templates/rrs/rrs_stats.html @@ -0,0 +1,48 @@ +{% extends "rrs/base_toplevel.html" %} +{% load i18n %} +{% load nvd3_tags %} +{% load staticfiles %} + +{% comment %} + + rrs-web - recipe maintenance stats template + + Copyright (C) 2013, 2018 Intel Corporation + Licensed under the MIT license, see COPYING.MIT for details + +{% endcomment %} + + +<!-- +{% block title_append %} - recipe maintenance statistics - {{ maintplan_name }} {{ release_name }} {{ milestone_name }}{% endblock %} +--> + + +{% block content_inner %} +{% autoescape on %} + + <div class="row-fluid"> + + <h2>Maintenance statistics - {{ maintplan_name }} {{ release_name }} {{ milestone_name }}</h2> + + <h3>Upstream status (milestone)</h3> + {% include_container "chart_status" 400 500 %} + + <h3>Patch status (current)</h3> + {% include_container "chart_patchstatus" 400 700 %} + + </div> + +{% endautoescape %} + +{% endblock %} + +{% block scripts %} + + <link media="all" href="{% static "css/nv.d3.css" %}" type="text/css" rel="stylesheet" /> + <script src="{% static "js/d3.js" %}" type="text/javascript"></script> + <script src="{% static "js/nv.d3.js" %}" type="text/javascript"></script> + +{% load_chart charttype_status chartdata_status "chart_status" extra_status %} +{% load_chart charttype_patchstatus chartdata_patchstatus "chart_patchstatus" extra_patchstatus %} +{% endblock %} |