mirror of
git://git.yoctoproject.org/layerindex-web.git
synced 2025-07-19 20:59:01 +02:00
rrs: Add initial support of recipes page
templates/rrs/base_toplevel.html: Add support for display statistics by Milestone. templates/rrs/recipes.html: Add initial page that display Recipe status by Milestone also details of every recipe. rrs/views.py: Add RecipeLitView for support recipes page. rrs/models.py: Add helper functions. rrs/static/*: Add css and js resources. Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
This commit is contained in:
parent
6b2b08456a
commit
02b0f4814d
|
@ -64,6 +64,11 @@ class RecipeMaintainer(models.Model):
|
||||||
recipe = models.ForeignKey(Recipe)
|
recipe = models.ForeignKey(Recipe)
|
||||||
maintainer = models.ForeignKey(Maintainer)
|
maintainer = models.ForeignKey(Maintainer)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_maintainer_by_recipe(recipe):
|
||||||
|
recipe_maintainer = RecipeMaintainer.objects.filter(recipe = recipe)[0]
|
||||||
|
return recipe_maintainer.maintainer
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return "%s: %s <%s>" % (self.recipe.pn, self.maintainer.name,
|
return "%s: %s <%s>" % (self.recipe.pn, self.maintainer.name,
|
||||||
self.maintainer.email)
|
self.maintainer.email)
|
||||||
|
@ -101,11 +106,13 @@ class RecipeUpstream(models.Model):
|
||||||
('D', 'Downgrade'),
|
('D', 'Downgrade'),
|
||||||
('U', 'Unknown'),
|
('U', 'Unknown'),
|
||||||
)
|
)
|
||||||
|
RECIPE_UPSTREAM_STATUS_CHOICES_DICT = dict(RECIPE_UPSTREAM_STATUS_CHOICES)
|
||||||
|
|
||||||
RECIPE_UPSTREAM_TYPE_CHOICES = (
|
RECIPE_UPSTREAM_TYPE_CHOICES = (
|
||||||
('A', 'Automatic'),
|
('A', 'Automatic'),
|
||||||
('M', 'Manual'),
|
('M', 'Manual'),
|
||||||
)
|
)
|
||||||
|
RECIPE_UPSTREAM_TYPE_CHOICES_DICT = dict(RECIPE_UPSTREAM_TYPE_CHOICES)
|
||||||
|
|
||||||
recipe = models.ForeignKey(Recipe)
|
recipe = models.ForeignKey(Recipe)
|
||||||
history = models.ForeignKey(RecipeUpstreamHistory, null=True)
|
history = models.ForeignKey(RecipeUpstreamHistory, null=True)
|
||||||
|
@ -115,6 +122,12 @@ class RecipeUpstream(models.Model):
|
||||||
no_update_reason = models.CharField(max_length=255, blank=True)
|
no_update_reason = models.CharField(max_length=255, blank=True)
|
||||||
date = models.DateTimeField()
|
date = models.DateTimeField()
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_by_recipe_and_history(recipe, history):
|
||||||
|
ru = RecipeUpstream.objects.filter(recipe = recipe, history = history)
|
||||||
|
return ru[0] if ru else None
|
||||||
|
|
||||||
def needs_upgrade(self):
|
def needs_upgrade(self):
|
||||||
if self.status == 'N':
|
if self.status == 'N':
|
||||||
return True
|
return True
|
||||||
|
|
107
rrs/static/css/rrs-additional.css
Normal file
107
rrs/static/css/rrs-additional.css
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
.version_column {
|
||||||
|
max-width: 150px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream_version_column {
|
||||||
|
min-width: 130px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upstream_status_column {
|
||||||
|
min-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maintainer_column {
|
||||||
|
min-width: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.distrolist {
|
||||||
|
margin-left: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.half-selector {
|
||||||
|
margin-bottom: -5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sorting styles */
|
||||||
|
|
||||||
|
th > a, th.muted {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sorted {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sorted:hover {
|
||||||
|
color: #000;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sorter {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table styles */
|
||||||
|
|
||||||
|
.navbar .nav > li > p {
|
||||||
|
color: #777777;
|
||||||
|
padding: 10px 5px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .badge {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-table-controls {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-controls {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: none;
|
||||||
|
box-shadow: none;
|
||||||
|
border:none;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-wk {
|
||||||
|
background-color: #fcf8e3;
|
||||||
|
color: #c09853;
|
||||||
|
}
|
||||||
|
|
||||||
|
th .caret {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* status styles */
|
||||||
|
|
||||||
|
.well{
|
||||||
|
padding: 8px 14px 8px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav > li.lead {
|
||||||
|
margin: 5px 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* about recipe styles */
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.well-transparent {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
1031
rrs/static/js/jquery.tablesorter.js
Normal file
1031
rrs/static/js/jquery.tablesorter.js
Normal file
File diff suppressed because it is too large
Load Diff
97
rrs/static/js/uitablefilter.js
Normal file
97
rrs/static/js/uitablefilter.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008 Greg Weber greg at gregweber.info
|
||||||
|
* Dual licensed under the MIT and GPLv2 licenses just as jQuery is:
|
||||||
|
* http://jquery.org/license
|
||||||
|
*
|
||||||
|
* documentation at http://gregweber.info/projects/uitablefilter
|
||||||
|
*
|
||||||
|
* allows table rows to be filtered (made invisible)
|
||||||
|
* <code>
|
||||||
|
* t = $('table')
|
||||||
|
* $.uiTableFilter( t, phrase )
|
||||||
|
* </code>
|
||||||
|
* arguments:
|
||||||
|
* jQuery object containing table rows
|
||||||
|
* phrase to search for
|
||||||
|
* optional arguments:
|
||||||
|
* column to limit search too (the column title in the table header)
|
||||||
|
* showHidden - if true, will search among the hidden elements
|
||||||
|
* ifHidden - callback to execute if one or more elements was hidden
|
||||||
|
*/
|
||||||
|
(function($) {
|
||||||
|
$.uiTableFilter = function(jq, phrase, column, showHidden, ifHidden){
|
||||||
|
var new_hidden = false;
|
||||||
|
if( this.last_phrase === phrase ) return false;
|
||||||
|
|
||||||
|
var phrase_length = phrase.length;
|
||||||
|
var words = phrase.toLowerCase().split(" ");
|
||||||
|
|
||||||
|
// these function pointers may change
|
||||||
|
var matches = function(elem) { elem.show(); }
|
||||||
|
var noMatch = function(elem) { elem.hide(); new_hidden = true }
|
||||||
|
var getText = function(elem) { return elem.text() }
|
||||||
|
|
||||||
|
if( column ) {
|
||||||
|
var index = null;
|
||||||
|
jq.find("thead > tr:last > th").each( function(i){
|
||||||
|
if( $.trim($(this).text()) == column ){
|
||||||
|
index = i; return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if( index == null ) throw("given column: " + column + " not found")
|
||||||
|
|
||||||
|
getText = function(elem){ return $(elem.find(
|
||||||
|
("td:eq(" + index + ")") )).text()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if added one letter to last time,
|
||||||
|
// just check newest word and only need to hide
|
||||||
|
if( (words.size > 1) && (phrase.substr(0, phrase_length - 1) ===
|
||||||
|
this.last_phrase) ) {
|
||||||
|
|
||||||
|
if( phrase[-1] === " " )
|
||||||
|
{ this.last_phrase = phrase; return false; }
|
||||||
|
|
||||||
|
var words = words[-1]; // just search for the newest word
|
||||||
|
|
||||||
|
// only hide visible rows
|
||||||
|
matches = function(elem) {;}
|
||||||
|
var elems = jq.find("tbody:first > tr:visible")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new_hidden = true;
|
||||||
|
if (showHidden) {
|
||||||
|
var elems = jq.find("tbody:first > tr");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var elems = jq.find("tbody:first > tr:visible");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elems.each(function(){
|
||||||
|
var elem = $(this);
|
||||||
|
$.uiTableFilter.has_words( getText(elem), words, false ) ?
|
||||||
|
matches(elem) : noMatch(elem);
|
||||||
|
});
|
||||||
|
|
||||||
|
last_phrase = phrase;
|
||||||
|
if( ifHidden && new_hidden ) ifHidden();
|
||||||
|
return jq;
|
||||||
|
};
|
||||||
|
|
||||||
|
// caching for speedup
|
||||||
|
$.uiTableFilter.last_phrase = ""
|
||||||
|
|
||||||
|
// not jQuery dependent
|
||||||
|
// "" [""] -> Boolean
|
||||||
|
// "" [""] Boolean -> Boolean
|
||||||
|
$.uiTableFilter.has_words = function( str, words, caseSensitive )
|
||||||
|
{
|
||||||
|
var text = caseSensitive ? str : str.toLowerCase();
|
||||||
|
for (var i=0; i < words.length; i++) {
|
||||||
|
if (text.indexOf(words[i]) === -1) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}) (jQuery);
|
115
rrs/views.py
115
rrs/views.py
|
@ -1,19 +1,128 @@
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from django.core.urlresolvers import resolve
|
from django.core.urlresolvers import resolve
|
||||||
|
|
||||||
from rrs.models import Milestone
|
from layerindex.models import Recipe
|
||||||
|
from rrs.models import Milestone, Maintainer, RecipeMaintainer, RecipeUpstream, \
|
||||||
|
RecipeUpstreamHistory
|
||||||
|
|
||||||
|
class RecipeList():
|
||||||
|
name = None
|
||||||
|
version = None
|
||||||
|
summary = None
|
||||||
|
upstream_status = None
|
||||||
|
upstream_version = None
|
||||||
|
maintainer_name = None
|
||||||
|
|
||||||
|
def __init__(self, name, version, summary, upstream_status,
|
||||||
|
upstream_version, maintainer_name):
|
||||||
|
self.name = name
|
||||||
|
self.version = version
|
||||||
|
self.summary = summary
|
||||||
|
self.upstream_status = upstream_status
|
||||||
|
self.upstream_version = upstream_version
|
||||||
|
self.maintainer_name = maintainer_name
|
||||||
|
|
||||||
class RecipeListView(ListView):
|
class RecipeListView(ListView):
|
||||||
context_object_name = 'recipe_list'
|
context_object_name = 'recipe_list'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
pass
|
self.milestone_name = self.kwargs['milestone_name']
|
||||||
|
milestone = get_object_or_404(Milestone, name=self.milestone_name)
|
||||||
|
|
||||||
|
if 'upstream_status' in self.request.GET.keys():
|
||||||
|
self.upstream_status = self.request.GET['upstream_status']
|
||||||
|
else:
|
||||||
|
self.upstream_status = 'All'
|
||||||
|
|
||||||
|
if 'maintainer_name' in self.request.GET.keys():
|
||||||
|
self.maintainer_name = self.request.GET['maintainer_name']
|
||||||
|
else:
|
||||||
|
self.maintainer_name = 'All'
|
||||||
|
|
||||||
|
recipe_upstream_history = RecipeUpstreamHistory.get_last_by_date_range(
|
||||||
|
milestone.start_date,
|
||||||
|
milestone.end_date
|
||||||
|
)
|
||||||
|
|
||||||
|
recipe_list = []
|
||||||
|
self.recipe_list_count = 0
|
||||||
|
|
||||||
|
self.recipes_up_to_date = 0
|
||||||
|
self.recipes_not_updated = 0
|
||||||
|
self.recipes_unknown = 0
|
||||||
|
self.recipes_percentage = '0.00'
|
||||||
|
if not recipe_upstream_history is None:
|
||||||
|
recipe_qry = Recipe.objects.filter().order_by('pn')
|
||||||
|
|
||||||
|
# get statistics by milestone
|
||||||
|
recipes_all = RecipeUpstream.objects.filter(history =
|
||||||
|
recipe_upstream_history).count()
|
||||||
|
self.recipes_up_to_date = RecipeUpstream.objects.filter(history =
|
||||||
|
recipe_upstream_history, status = 'Y').count()
|
||||||
|
self.recipes_not_updated = RecipeUpstream.objects.filter(history =
|
||||||
|
recipe_upstream_history, status = 'N').count()
|
||||||
|
self.recipes_unknown = recipes_all - (self.recipes_up_to_date +
|
||||||
|
self.recipes_not_updated)
|
||||||
|
self.recipes_percentage = "%.2f" % \
|
||||||
|
((float(self.recipes_up_to_date) / float(recipes_all)) * 100)
|
||||||
|
|
||||||
|
for recipe in recipe_qry:
|
||||||
|
recipe_upstream = RecipeUpstream.get_by_recipe_and_history(
|
||||||
|
recipe, recipe_upstream_history)
|
||||||
|
|
||||||
|
recipe_upstream_status = \
|
||||||
|
RecipeUpstream.RECIPE_UPSTREAM_STATUS_CHOICES_DICT[
|
||||||
|
recipe_upstream.status]
|
||||||
|
if self.upstream_status != 'All' and self.upstream_status != recipe_upstream_status:
|
||||||
|
continue
|
||||||
|
|
||||||
|
maintainer = RecipeMaintainer.get_maintainer_by_recipe(recipe)
|
||||||
|
if self.maintainer_name != 'All' and self.maintainer_name != maintainer.name:
|
||||||
|
continue
|
||||||
|
|
||||||
|
recipe_list_item = RecipeList(recipe.pn, recipe.pv, recipe.summary,
|
||||||
|
recipe_upstream_status, recipe_upstream.version, maintainer.name)
|
||||||
|
recipe_list.append(recipe_list_item)
|
||||||
|
|
||||||
|
self.recipe_list_count = len(recipe_list)
|
||||||
|
|
||||||
|
return recipe_list
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(RecipeListView, self).get_context_data(**kwargs)
|
context = super(RecipeListView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
context['this_url_name'] = resolve(self.request.path_info).url_name
|
context['this_url_name'] = resolve(self.request.path_info).url_name
|
||||||
context['milestone_name'] = self.kwargs['milestone_name']
|
|
||||||
|
context['milestone_name'] = self.milestone_name
|
||||||
context['all_milestones'] = Milestone.objects.filter().order_by('-id')
|
context['all_milestones'] = Milestone.objects.filter().order_by('-id')
|
||||||
|
|
||||||
|
context['recipes_percentage'] = self.recipes_percentage
|
||||||
|
context['recipes_up_to_date'] = self.recipes_up_to_date
|
||||||
|
context['recipes_not_updated'] = self.recipes_not_updated
|
||||||
|
context['recipes_unknown'] = self.recipes_unknown
|
||||||
|
|
||||||
|
context['recipe_list_count'] = self.recipe_list_count
|
||||||
|
|
||||||
|
context['upstream_status'] = self.upstream_status
|
||||||
|
all_upstream_status = ['All']
|
||||||
|
for us in RecipeUpstream.RECIPE_UPSTREAM_STATUS_CHOICES:
|
||||||
|
all_upstream_status.append(us[1])
|
||||||
|
context['all_upstream_status'] = all_upstream_status
|
||||||
|
|
||||||
|
context['maintainer_name'] = self.maintainer_name
|
||||||
|
all_maintainers = ['All']
|
||||||
|
for rm in RecipeMaintainer.objects.filter().values(
|
||||||
|
'maintainer__name').distinct().order_by('maintainer__name'):
|
||||||
|
all_maintainers.append(rm['maintainer__name'])
|
||||||
|
context['all_maintainers'] = all_maintainers
|
||||||
|
|
||||||
|
extra_url_param = '?' + urllib.urlencode({
|
||||||
|
'upstream_status': self.upstream_status,
|
||||||
|
'maintainer_name': self.maintainer_name.encode('utf8')
|
||||||
|
})
|
||||||
|
context['extra_url_param'] = extra_url_param
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
{% load url from future %}
|
{% load url from future %}
|
||||||
|
|
||||||
|
@ -13,9 +14,7 @@
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<link rel="stylesheet" href="{% static "css/rrs-additional.css" %}" />
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row-fluid">
|
|
||||||
|
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<div class="navbar-inner">
|
<div class="navbar-inner">
|
||||||
|
@ -37,6 +36,14 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
<li class="divider-vertical"></li>
|
||||||
|
<li class="lead" id="percentage"><strong>{{ recipes_percentage }}%</strong> done</li>
|
||||||
|
<li class="divider-vertical"></li>
|
||||||
|
<li class="lead" id="up-to-date-recipes">Recipes up-to-date: <strong class="text-success">{{ recipes_up_to_date }}</strong></li>
|
||||||
|
<li class="divider-vertical"></li>
|
||||||
|
<li class="lead" id="not-updated-recipes">Recipes not updated: <strong class="text-error">{{ recipes_not_updated }}</strong></li>
|
||||||
|
<li class="divider-vertical"></li>
|
||||||
|
<li class="lead" id="unknown-recipes">Unknown: <strong class="text-warning">{{ recipes_unknown }}</strong></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
|
@ -45,9 +52,25 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% block content_top %}
|
||||||
|
<ul class="nav nav-pills">
|
||||||
|
{% if this_url_name == 'recipes' %}
|
||||||
|
<li class="active">
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
{% endif %}
|
||||||
|
<a href="{% url this_url_name milestone_name %}{{ extra_url_param }}">Recipes status</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{% if this_url_name == 'maintainers' %}
|
||||||
|
<li class="active">
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
{% endif %}
|
||||||
|
<a href="#">Maintainer statistics</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content_inner %}{% endblock %}
|
{% block content_inner %}{% endblock %}
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends "rrs/base_toplevel.html" %}
|
{% extends "rrs/base_toplevel.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
{% load url from future %}
|
{% load url from future %}
|
||||||
|
|
||||||
|
@ -16,4 +17,88 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content_inner %}
|
{% block content_inner %}
|
||||||
|
<div class="navbar navbar-table-controls">
|
||||||
|
<div class="navbar-inner table-controls">
|
||||||
|
<ul class="nav">
|
||||||
|
<li class="dropdown">
|
||||||
|
<span class="badge">{{ recipe_list_count }} recipes</span>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a data-toggle="dropdown" href="#" class="dropdown-toggle" id="selected-status">
|
||||||
|
Upstream status: <strong>{{ upstream_status }}</strong>
|
||||||
|
<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu" id="select-status">
|
||||||
|
{% for us in all_upstream_status %}
|
||||||
|
{% if us = upstream_status %}
|
||||||
|
<li class="active">
|
||||||
|
<a href="#">
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
<a href="{% url this_url_name milestone_name %}?upstream_status={{ us|urlencode }}&maintainer_name={{ maintainer_name|urlencode }}">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ us }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><p>and</p></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a data-toggle="dropdown" href="#" class="dropdown-toggle" id="select-maintainer">
|
||||||
|
Maintainer: <strong>{{ maintainer_name }}</strong>
|
||||||
|
<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu" id="selected-maintainer">
|
||||||
|
{% for m in all_maintainers %}
|
||||||
|
{% if m = maintainer_name %}
|
||||||
|
<li class="active">
|
||||||
|
<a href="#">
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
<a href="{% url this_url_name milestone_name %}?upstream_status={{ upstream_status|urlencode }}&maintainer_name={{ m|urlencode }}">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ m }}</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<form class="navbar-form pull-right">
|
||||||
|
<input type="text" class="input-xxlarge" placeholder="Search all recipes" id="filter"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table table-bordered statustable tablesorter table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="recipe_column"><a href="#">Recipe</a></th>
|
||||||
|
<th class="version_column muted">Version</th>
|
||||||
|
<th class="upstream_status_column"><b class="caret"></b>Upstream status</th>
|
||||||
|
<th class="upstream_version_column muted">Upstream version</th>
|
||||||
|
<th class="maintainer_column"><b class="caret"></b>Maintainer</th>
|
||||||
|
<th class="summary_column muted span5">Summary</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for r in recipe_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ r.name }}</td>
|
||||||
|
<td>{{ r.version }}</td>
|
||||||
|
<td>{{ r.upstream_status }}</td>
|
||||||
|
<td>{{ r.upstream_version }}</td>
|
||||||
|
<td>{{ r.maintainer_name }}</td>
|
||||||
|
<td>{{ r.summary }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script src="{% static "js/uitablefilter.js" %}"></script>
|
||||||
|
<script src="{% static "js/jquery.tablesorter.js" %}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user