rrs: Add Maintainer statistics page.

Maintainer statistics page gives information by Milestone and
Maintainers assigned recipes, status of recipes (up-to-date,
not-update, unknown) and percertange of work done.

Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
This commit is contained in:
Aníbal Limón 2015-01-29 18:13:28 -06:00 committed by Paul Eggleton
parent 6dfc369f29
commit dc38557582
4 changed files with 205 additions and 8 deletions

View File

@ -1,7 +1,7 @@
from django.conf.urls import patterns, include, url
from rrs.models import Milestone
from rrs.views import RecipeListView, RecipeDetailView
from rrs.views import RecipeListView, RecipeDetailView, MaintainerListView
urlpatterns = patterns('',
url(r'^$', redirect_to, {'url' : reverse_lazy('recipes', args=(Milestone.get_current().name,))},
@ -14,4 +14,8 @@ urlpatterns = patterns('',
RecipeDetailView.as_view(
template_name='rrs/recipedetail.html'),
name='recipedetail'),
url(r'^maintainers/(?P<milestone_name>.*)/$',
MaintainerListView.as_view(
template_name='rrs/maintainers.html'),
name="maintainers"),
)

View File

@ -26,7 +26,7 @@ def _get_layer_branch_url(branch, layer_name):
return ("http://layers.openembedded.org/layerindex/branch/%s/layer/%s/"\
% (branch, layer_name))
def _get_milestone_statistics(milestone):
def _get_milestone_statistics(milestone, maintainer_name=None):
milestone_statistics = {}
recipe_upstream_history = RecipeUpstreamHistory.get_last_by_date_range(
@ -35,22 +35,51 @@ def _get_milestone_statistics(milestone):
)
if recipe_upstream_history is None:
milestone_statistics['all'] = '0'
milestone_statistics['up_to_date'] = '0'
milestone_statistics['not_updated'] = '0'
milestone_statistics['unknown'] = '0'
milestone_statistics['percentage'] = '0.0'
else:
recipes_all = RecipeUpstream.objects.filter(history =
elif maintainer_name is None:
recipe_count = RecipeUpstream.objects.filter(history =
recipe_upstream_history).count()
milestone_statistics['all'] = recipe_count
milestone_statistics['up_to_date'] = RecipeUpstream.objects.filter(
history = recipe_upstream_history, status = 'Y').count()
milestone_statistics['not_updated'] = RecipeUpstream.objects.filter(
history = recipe_upstream_history, status = 'N').count()
milestone_statistics['unknown'] = recipes_all - \
milestone_statistics['unknown'] = milestone_statistics['all'] - \
(milestone_statistics['up_to_date'] + milestone_statistics['not_updated'])
milestone_statistics['percentage'] = "%.2f" % \
((float(milestone_statistics['up_to_date']) / float(recipes_all)) * 100)
((float(milestone_statistics['up_to_date']) /
float(milestone_statistics['all'])) * 100)
else:
recipe_maintainer_history = RecipeMaintainerHistory.get_by_end_date(
milestone.end_date)
recipes_all = []
for rm in RecipeMaintainer.objects.filter(history = recipe_maintainer_history,
maintainer__name = maintainer_name):
ru = RecipeUpstream.objects.filter(recipe = rm.recipe, history =
recipe_upstream_history)[0]
recipes_all.append(ru)
milestone_statistics['all'] = len(recipes_all)
milestone_statistics['up_to_date'] = 0
milestone_statistics['not_updated'] = 0
milestone_statistics['unknown'] = 0
for ru in recipes_all:
if ru.status == 'Y':
milestone_statistics['up_to_date'] += 1
elif ru.status == 'N':
milestone_statistics['not_updated'] += 1
else:
milestone_statistics['unknown'] += 1
milestone_statistics['percentage'] = "%.2f" % \
((float(milestone_statistics['up_to_date']) /
float(milestone_statistics['all'])) * 100)
return milestone_statistics
@ -266,3 +295,64 @@ class RecipeDetailView(DetailView):
context['recipe_distros'] = RecipeDistro.get_distros_by_recipe(recipe)
return context
class MaintainerList():
name = None
recipes_all = 0
recipes_up_to_date = '0'
recipes_not_updated = '0'
recipes_unknown = '0'
percentage_done = '0.00'
def __init__(self, name):
self.name = name
class MaintainerListView(ListView):
context_object_name = 'maintainer_list'
def get_queryset(self):
maintainer_list = []
self.maintainer_count = 0
self.milestone_name = self.kwargs['milestone_name']
milestone = get_object_or_404(Milestone, name=self.milestone_name)
self.milestone_statistics = _get_milestone_statistics(milestone)
recipe_maintainer_history = RecipeMaintainerHistory.get_by_end_date(
milestone.end_date)
if recipe_maintainer_history:
for rm in RecipeMaintainer.objects.filter(history =
recipe_maintainer_history).values(
'maintainer__name').distinct().order_by('maintainer__name'):
maintainer_list.append(MaintainerList(rm['maintainer__name']))
self.maintainer_count = len(maintainer_list)
for ml in maintainer_list:
milestone_statistics = _get_milestone_statistics(milestone, ml.name)
ml.recipes_all = milestone_statistics['all']
ml.recipes_up_to_date = milestone_statistics['up_to_date']
ml.recipes_not_updated = milestone_statistics['not_updated']
ml.recipes_unknown = milestone_statistics['unknown']
ml.percentage_done = milestone_statistics['percentage']
return maintainer_list
def get_context_data(self, **kwargs):
context = super(MaintainerListView, self).get_context_data(**kwargs)
context['this_url_name'] = resolve(self.request.path_info).url_name
context['milestone_name'] = self.milestone_name
context['all_milestones'] = Milestone.objects.filter().order_by('-id')
context['recipes_percentage'] = self.milestone_statistics['percentage']
context['recipes_up_to_date'] = self.milestone_statistics['up_to_date']
context['recipes_not_updated'] = self.milestone_statistics['not_updated']
context['recipes_unknown'] = self.milestone_statistics['unknown']
context['maintainer_count'] = self.maintainer_count
return context

View File

@ -56,18 +56,22 @@
<ul class="nav nav-pills">
{% if this_url_name == 'recipes' %}
<li class="active">
<a href="#">
{% else %}
<li>
<a href="{% url 'recipes' milestone_name %}{{ extra_url_param }}">
{% endif %}
<a href="{% url this_url_name milestone_name %}{{ extra_url_param }}">Recipes status</a>
Recipes status</a>
</li>
{% if this_url_name == 'maintainers' %}
<li class="active">
<a href="#">
{% else %}
<li>
<a href="{% url 'maintainers' milestone_name %}">
{% endif %}
<a href="#">Maintainer statistics</a>
Maintainer statistics</a>
</li>
</ul>
{% endblock %}

View File

@ -0,0 +1,99 @@
{% extends "rrs/base_toplevel.html" %}
{% load i18n %}
{% load staticfiles %}
{% load url from future %}
{% comment %}
rrs-web - maintainers page template
Copyright (C) 2015 Intel Corporation
Licensed under the MIT license, see COPYING.MIT for details
{% endcomment %}
{% block navs %}
{% endblock %}
{% block content_inner %}
<div class="navbar navbar-table-controls">
<div class="navbar-inner table-controls">
<ul class="nav">
<li class="dropdown">
<span class="badge" style="margin-top:11px;">{{ maintainer_count }} maintainers</span>
</li>
</ul>
<form class="navbar-form pull-right">
<input type="text" class="input-xxlarge pull-right" placeholder="Search maintainers" id="filter">
</form>
</div>
</div>
{% if maintainer_count == 0 %}
<div class="alert"> No maintainers found</div>
{% else %}
<table class="table table-bordered table-hover statisticstable">
<thead>
<tr>
<th>Maintainer</th>
<th class="muted">Assigned recipes</th>
<th class="muted">Up-to-date</th>
<th>Not updated</th>
<th class="muted">Unknown</th>
<th>% done</th>
<th class="current-wk">wk1</th>
<th class="muted">wk2</th>
<th class="muted">wk3</th>
<th class="muted">wk4</th>
</tr>
</thead>
<tbody>
{% for ml in maintainer_list %}
<tr>
<td>
<a href="{% url 'recipes' milestone_name %}?maintainer_name={{ ml.name|urlencode }}">
{{ ml.name }}
</a>
</td>
<td>{{ ml.recipes_all }}</td>
<td>
<a href="{% url 'recipes' milestone_name %}?upstream_status={{ "Up-to-date"|urlencode }}&maintainer_name={{ ml.name|urlencode }}">
{{ ml.recipes_up_to_date }}
</a>
</td>
<td>
<a href="{% url 'recipes' milestone_name %}?upstream_status={{ "Not updated"|urlencode }}&maintainer_name={{ ml.name|urlencode }}">
{{ ml.recipes_not_updated }}
</a>
</td>
<td>
<a href="{% url 'recipes' milestone_name %}?upstream_status={{ "Unknown"|urlencode }}&maintainer_name={{ ml.name|urlencode }}">
{{ ml.recipes_unknown }}
</a>
</td>
<td>{{ ml.percentage_done }}</td>
<td class="current-wk"></td>
<td></td>
<td></td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %}
{% block scripts %}
{% if maintainer_count > 0 %}
<script src="{% static "js/uitablefilter.js" %}"></script>
<script>
$(document).ready(function() {
$("#filter").keyup(function() {
var table = $('.statisticstable');
$.uiTableFilter(table, this.value);
});
});
</script>
{% endif %}
{% endblock %}