Add support for other distro comparisons

Turn the existing OE-Classic support into something a bit more
generic so we can import data from other distributions and compare it to
what we have in layers.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
Paul Eggleton 2018-05-14 16:35:06 +12:00
parent 8ab9c15085
commit 72d67231ec
12 changed files with 273 additions and 77 deletions

View File

@ -17,10 +17,10 @@ def layerindex_context(request):
else: else:
site_name = 'OpenEmbedded Layer Index' site_name = 'OpenEmbedded Layer Index'
return { return {
'all_branches': Branch.objects.exclude(name='oe-classic').order_by('sort_priority'), 'all_branches': Branch.objects.exclude(comparison=True).order_by('sort_priority'),
'unpublished_count': LayerItem.objects.filter(status='N').count(), 'unpublished_count': LayerItem.objects.filter(status='N').count(),
'oe_classic': Branch.objects.filter(name='oe-classic'),
'site_name': site_name, 'site_name': site_name,
'rrs_enabled': 'rrs' in settings.INSTALLED_APPS, 'rrs_enabled': 'rrs' in settings.INSTALLED_APPS,
'notices': SiteNotice.objects.filter(disabled=False).filter(Q(expires__isnull=True) | Q(expires__gte=datetime.now())), 'notices': SiteNotice.objects.filter(disabled=False).filter(Q(expires__isnull=True) | Q(expires__gte=datetime.now())),
'comparison_branches': Branch.objects.filter(comparison=True),
} }

View File

@ -215,7 +215,7 @@ BulkChangeEditFormSet = modelformset_factory(RecipeChange, form=BulkChangeEditFo
class ClassicRecipeSearchForm(forms.Form): class ClassicRecipeSearchForm(forms.Form):
COVER_STATUS_CHOICES = [('','(any)'), ('!','(not migrated)')] + ClassicRecipe.COVER_STATUS_CHOICES COVER_STATUS_CHOICES = [('','(any)'), ('!','(unknown / not available)')] + ClassicRecipe.COVER_STATUS_CHOICES
VERIFIED_CHOICES = [ VERIFIED_CHOICES = [
('', '(any)'), ('', '(any)'),
('1', 'Verified'), ('1', 'Verified'),

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('layerindex', '0014_sitenotice'),
]
operations = [
migrations.AddField(
model_name='branch',
name='comparison',
field=models.BooleanField(default=False, help_text='If enabled, branch is for comparison purposes only and will appear separately', verbose_name='Comparison'),
),
migrations.AlterField(
model_name='classicrecipe',
name='cover_status',
field=models.CharField(default='U', choices=[('U', 'Unknown'), ('N', 'Not available'), ('R', 'Replaced'), ('P', 'Provided (BBCLASSEXTEND)'), ('C', 'Provided (PACKAGECONFIG)'), ('S', 'Distro-specific'), ('O', 'Obsolete'), ('E', 'Equivalent functionality'), ('D', 'Direct match')], max_length=1),
),
]

View File

@ -71,6 +71,7 @@ class Branch(models.Model):
short_description = models.CharField(max_length=50, blank=True) short_description = models.CharField(max_length=50, blank=True)
sort_priority = models.IntegerField(blank=True, null=True) sort_priority = models.IntegerField(blank=True, null=True)
updates_enabled = models.BooleanField('Enable updates', default=True, help_text='Enable automatically updating layer metadata for this branch via the update script') updates_enabled = models.BooleanField('Enable updates', default=True, help_text='Enable automatically updating layer metadata for this branch via the update script')
comparison = models.BooleanField('Comparison', default=False, help_text='If enabled, branch is for comparison purposes only and will appear separately')
update_environment = models.ForeignKey(PythonEnvironment, blank=True, null=True, on_delete=models.SET_NULL) update_environment = models.ForeignKey(PythonEnvironment, blank=True, null=True, on_delete=models.SET_NULL)
updated = models.DateTimeField(auto_now=True, blank=True, null=True) updated = models.DateTimeField(auto_now=True, blank=True, null=True)
@ -80,7 +81,9 @@ class Branch(models.Model):
ordering = ['sort_priority'] ordering = ['sort_priority']
def __str__(self): def __str__(self):
if self.short_description: if self.comparison and self.short_description:
return self.short_description
elif self.short_description:
return '%s (%s)' % (self.name, self.short_description) return '%s (%s)' % (self.name, self.short_description)
else: else:
return self.name return self.name
@ -520,6 +523,7 @@ class ClassicRecipe(Recipe):
('R', 'Replaced'), ('R', 'Replaced'),
('P', 'Provided (BBCLASSEXTEND)'), ('P', 'Provided (BBCLASSEXTEND)'),
('C', 'Provided (PACKAGECONFIG)'), ('C', 'Provided (PACKAGECONFIG)'),
('S', 'Distro-specific'),
('O', 'Obsolete'), ('O', 'Obsolete'),
('E', 'Equivalent functionality'), ('E', 'Equivalent functionality'),
('D', 'Direct match'), ('D', 'Direct match'),

View File

@ -238,3 +238,19 @@ blockquote.span7.warn {
width: auto; width: auto;
height: 1em; height: 1em;
} }
td.success {
background-color: #dff0d8 !important;
}
td.error {
background-color: #f2dede !important;
}
td.warning {
background-color: #fcf8e3 !important;
}
td.info {
background-color: #d9edf7 !important;
}

View File

@ -129,16 +129,26 @@ urlpatterns = [
RedirectView.as_view(url=reverse_lazy('classic_recipe_search'), permanent=False), RedirectView.as_view(url=reverse_lazy('classic_recipe_search'), permanent=False),
name='classic'), name='classic'),
url(r'^oe-classic/recipes/$', url(r'^oe-classic/recipes/$',
ClassicRecipeSearchView.as_view( RedirectView.as_view(url=reverse_lazy('comparison_recipe_search', kwargs={'branch': 'oe-classic'}), permanent=False),
template_name='layerindex/classicrecipes.html'),
name='classic_recipe_search'), name='classic_recipe_search'),
url(r'^oe-classic/stats/$', url(r'^oe-classic/stats/$',
ClassicRecipeStatsView.as_view( RedirectView.as_view(url=reverse_lazy('comparison_recipe_stats', kwargs={'branch': 'oe-classic'}), permanent=False),
template_name='layerindex/classicstats.html'),
name='classic_recipe_stats'), name='classic_recipe_stats'),
url(r'^oe-classic/recipe/(?P<pk>[-\w]+)/$', url(r'^oe-classic/recipe/(?P<pk>[-\w]+)/$',
ClassicRecipeDetailView.as_view( ClassicRecipeDetailView.as_view(
template_name='layerindex/classicrecipedetail.html'), template_name='layerindex/classicrecipedetail.html'),
name='classic_recipe'), name='classic_recipe'),
url(r'^comparison/recipes/(?P<branch>[-\w]+)/$',
ClassicRecipeSearchView.as_view(
template_name='layerindex/classicrecipes.html'),
name='comparison_recipe_search'),
url(r'^comparison/stats/(?P<branch>[-\w]+)/$',
ClassicRecipeStatsView.as_view(
template_name='layerindex/classicstats.html'),
name='comparison_recipe_stats'),
url(r'^comparison/recipe/(?P<pk>[-\w]+)/$',
ClassicRecipeDetailView.as_view(
template_name='layerindex/classicrecipedetail.html'),
name='comparison_recipe'),
url(r'.*', page_not_found, kwargs={'exception': Exception("Page not Found")}) url(r'.*', page_not_found, kwargs={'exception': Exception("Page not Found")})
] ]

View File

@ -1,10 +1,12 @@
# layerindex-web - view definitions # layerindex-web - view definitions
# #
# Copyright (C) 2013-2016 Intel Corporation # Copyright (C) 2013-2018 Intel Corporation
# #
# Licensed under the MIT license, see COPYING.MIT for details # Licensed under the MIT license, see COPYING.MIT for details
import sys import sys
from pkg_resources import parse_version
from itertools import islice
from django.shortcuts import get_object_or_404, get_list_or_404, render from django.shortcuts import get_object_or_404, get_list_or_404, render
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404 from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404
from django.core.urlresolvers import reverse, reverse_lazy, resolve from django.core.urlresolvers import reverse, reverse_lazy, resolve
@ -15,10 +17,13 @@ from datetime import datetime
from django.views.generic import TemplateView, DetailView, ListView from django.views.generic import TemplateView, DetailView, ListView
from django.views.generic.edit import CreateView, DeleteView, UpdateView from django.views.generic.edit import CreateView, DeleteView, UpdateView
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
from django.contrib.messages.views import SuccessMessageMixin
from layerindex.forms import EditLayerForm, LayerMaintainerFormSet, EditNoteForm, EditProfileForm, RecipeChangesetForm, AdvancedRecipeSearchForm, BulkChangeEditFormSet, ClassicRecipeForm, ClassicRecipeSearchForm from layerindex.forms import EditLayerForm, LayerMaintainerFormSet, EditNoteForm, EditProfileForm, RecipeChangesetForm, AdvancedRecipeSearchForm, BulkChangeEditFormSet, ClassicRecipeForm, ClassicRecipeSearchForm
from django.db import transaction from django.db import transaction
from django.contrib.auth.models import User, Permission from django.contrib.auth.models import User, Permission
from django.db.models import Q, Count, Sum from django.db.models import Q, Count, Sum
from django.db.models.functions import Lower
from django.db.models.query import QuerySet
from django.template.loader import get_template from django.template.loader import get_template
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
@ -867,21 +872,65 @@ class RecipeDetailView(DetailView):
return context return context
class ClassicRecipeLinkWrapper:
def __init__(self, queryset):
self.queryset = queryset
# This function is required by generic views, create another proxy
def _clone(self):
return ClassicRecipeLinkIterator(self.queryset._clone(), **self.kwargs)
def _annotate(self, obj):
recipe = None
vercmp = 0
if obj.cover_layerbranch and obj.cover_pn:
rq = Recipe.objects.filter(layerbranch=obj.cover_layerbranch).filter(pn=obj.cover_pn)
if rq:
recipe = rq.first()
if obj.pv and recipe.pv:
obj_ver = parse_version(obj.pv)
recipe_ver = parse_version(recipe.pv)
vercmp = ((recipe_ver > obj_ver) - (recipe_ver < obj_ver))
setattr(obj, 'cover_recipe', recipe)
setattr(obj, 'cover_vercmp', vercmp)
def __iter__(self):
for obj in self.queryset:
self._annotate(obj)
yield obj
def _slice(self, start, stop, step=1):
for item in islice(self.queryset, start, stop, step):
self._annotate(item)
yield item
def __getitem__(self, key):
if isinstance(key, slice):
return self._slice(key.start, key.stop, key.step)
else:
return next(self._slice(key, key+1))
def __len__(self):
if isinstance(self.queryset, QuerySet):
return self.queryset.count()
else:
return len(self.queryset)
class ClassicRecipeSearchView(RecipeSearchView): class ClassicRecipeSearchView(RecipeSearchView):
def render_to_response(self, context, **kwargs): def render_to_response(self, context, **kwargs):
# Bypass the redirect-to-single-instance behaviour of RecipeSearchView # Bypass the redirect-to-single-instance behaviour of RecipeSearchView
return super(ListView, self).render_to_response(context, **kwargs) return super(ListView, self).render_to_response(context, **kwargs)
def get_queryset(self): def get_queryset(self):
self.kwargs['branch'] = 'oe-classic' self.kwargs['branch'] = self.kwargs.get('branch', 'oe-classic')
query_string = self.request.GET.get('q', '') query_string = self.request.GET.get('q', '')
cover_status = self.request.GET.get('cover_status', None) cover_status = self.request.GET.get('cover_status', None)
cover_verified = self.request.GET.get('cover_verified', None) cover_verified = self.request.GET.get('cover_verified', None)
category = self.request.GET.get('category', None) category = self.request.GET.get('category', None)
init_qs = ClassicRecipe.objects.filter(layerbranch__branch__name='oe-classic') init_qs = ClassicRecipe.objects.filter(layerbranch__branch__name=self.kwargs['branch'])
if cover_status: if cover_status:
if cover_status == '!': if cover_status == '!':
init_qs = init_qs.filter(cover_status__in=['U', 'N']) init_qs = init_qs.filter(cover_status__in=['U', 'N', 'S'])
else: else:
init_qs = init_qs.filter(cover_status=cover_status) init_qs = init_qs.filter(cover_status=cover_status)
if cover_verified: if cover_verified:
@ -889,7 +938,7 @@ class ClassicRecipeSearchView(RecipeSearchView):
if category: if category:
init_qs = init_qs.filter(classic_category__icontains=category) init_qs = init_qs.filter(classic_category__icontains=category)
if query_string.strip(): if query_string.strip():
order_by = ('pn', 'layerbranch__layer') order_by = (Lower('pn'), 'layerbranch__layer')
qs0 = init_qs.filter(pn=query_string).order_by(*order_by) qs0 = init_qs.filter(pn=query_string).order_by(*order_by)
@ -902,30 +951,33 @@ class ClassicRecipeSearchView(RecipeSearchView):
qs = list(utils.chain_unique(qs0, qs1, qs2)) qs = list(utils.chain_unique(qs0, qs1, qs2))
else: else:
if 'q' in self.request.GET: if 'q' in self.request.GET:
qs = init_qs.order_by('pn', 'layerbranch__layer') qs = init_qs.order_by(Lower('pn'), 'layerbranch__layer')
else: else:
# It's a bit too slow to return all records by default, and most people # It's a bit too slow to return all records by default, and most people
# won't actually want that (if they do they can just hit the search button # won't actually want that (if they do they can just hit the search button
# with no query string) # with no query string)
return Recipe.objects.none() return Recipe.objects.none()
return qs return ClassicRecipeLinkWrapper(qs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ClassicRecipeSearchView, self).get_context_data(**kwargs) context = super(ClassicRecipeSearchView, self).get_context_data(**kwargs)
context['multi_classic_layers'] = LayerItem.objects.filter(classic=True).count() > 1 context['this_url_name'] = 'recipe_search'
branchname = self.kwargs.get('branch', 'oe-classic')
context['branch'] = get_object_or_404(Branch, name=branchname)
if 'q' in self.request.GET: if 'q' in self.request.GET:
searched = True searched = True
search_form = ClassicRecipeSearchForm(self.request.GET) search_form = ClassicRecipeSearchForm(self.request.GET)
else: else:
searched = False searched = False
search_form = ClassicRecipeSearchForm() search_form = ClassicRecipeSearchForm()
context['compare'] = self.request.GET.get('compare', False)
context['search_form'] = search_form context['search_form'] = search_form
context['searched'] = searched context['searched'] = searched
return context return context
class ClassicRecipeDetailView(UpdateView): class ClassicRecipeDetailView(SuccessMessageMixin, UpdateView):
model = ClassicRecipe model = ClassicRecipe
form_class = ClassicRecipeForm form_class = ClassicRecipeForm
context_object_name = 'recipe' context_object_name = 'recipe'
@ -946,24 +998,41 @@ class ClassicRecipeDetailView(UpdateView):
return super(ClassicRecipeDetailView, self).post(request, *args, **kwargs) return super(ClassicRecipeDetailView, self).post(request, *args, **kwargs)
def get_success_message(self, cleaned_data):
return "Comparison saved successfully"
def get_success_url(self): def get_success_url(self):
return reverse_lazy('classic_recipe_search') return reverse_lazy('comparison_recipe', args=(self.object.id,))
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ClassicRecipeDetailView, self).get_context_data(**kwargs) context = super(ClassicRecipeDetailView, self).get_context_data(**kwargs)
context['can_edit'] = self._can_edit() context['can_edit'] = self._can_edit()
recipe = context['recipe']
context['branch'] = recipe.layerbranch.branch
# Get covering recipe if any
cover_recipe = None
if recipe.cover_pn:
rq = Recipe.objects.filter(layerbranch=recipe.cover_layerbranch).filter(pn=recipe.cover_pn)
if rq:
cover_recipe = rq.first()
context['cover_recipe'] = cover_recipe
return context return context
class ClassicRecipeStatsView(TemplateView): class ClassicRecipeStatsView(TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ClassicRecipeStatsView, self).get_context_data(**kwargs) context = super(ClassicRecipeStatsView, self).get_context_data(**kwargs)
branchname = self.kwargs.get('branch', 'oe-classic')
context['branch'] = get_object_or_404(Branch, name=branchname)
context['url_branch'] = branchname
context['this_url_name'] = 'recipe_search'
# *** Cover status chart *** # *** Cover status chart ***
recipes = ClassicRecipe.objects.filter(layerbranch__branch=context['branch'])
statuses = [] statuses = []
status_counts = {} status_counts = {}
for choice, desc in ClassicRecipe.COVER_STATUS_CHOICES: for choice, desc in ClassicRecipe.COVER_STATUS_CHOICES:
statuses.append(desc) statuses.append(desc)
status_counts[desc] = ClassicRecipe.objects.filter(cover_status=choice).count() status_counts[desc] = recipes.filter(cover_status=choice).count()
statuses = sorted(statuses, key=lambda status: status_counts[status], reverse=True) statuses = sorted(statuses, key=lambda status: status_counts[status], reverse=True)
chartdata = {'x': statuses, 'y': [status_counts[k] for k in statuses]} chartdata = {'x': statuses, 'y': [status_counts[k] for k in statuses]}
context['charttype_status'] = 'pieChart' context['charttype_status'] = 'pieChart'
@ -976,7 +1045,7 @@ class ClassicRecipeStatsView(TemplateView):
} }
# *** Categories chart *** # *** Categories chart ***
categories = ['obsoletedir', 'nonworkingdir'] categories = ['obsoletedir', 'nonworkingdir']
uniquevals = ClassicRecipe.objects.exclude(classic_category='').values_list('classic_category', flat=True).distinct() uniquevals = recipes.exclude(classic_category='').values_list('classic_category', flat=True).distinct()
for value in uniquevals: for value in uniquevals:
cats = value.split() cats = value.split()
for cat in cats: for cat in cats:
@ -984,7 +1053,7 @@ class ClassicRecipeStatsView(TemplateView):
categories.append(cat) categories.append(cat)
categories.append('none') categories.append('none')
catcounts = dict.fromkeys(categories, 0) catcounts = dict.fromkeys(categories, 0)
unmigrated = ClassicRecipe.objects.filter(cover_status='U') unmigrated = recipes.filter(cover_status='U')
catcounts['none'] = unmigrated.filter(classic_category='').count() catcounts['none'] = unmigrated.filter(classic_category='').count()
values = unmigrated.exclude(classic_category='').values_list('classic_category', flat=True) values = unmigrated.exclude(classic_category='').values_list('classic_category', flat=True)
# We gather data this way because an item might be in more than one category, thus # We gather data this way because an item might be in more than one category, thus

View File

@ -28,16 +28,19 @@
{% for branch in all_branches %} {% for branch in all_branches %}
<li><a href="{% url this_url_name branch.name %}{{ extra_url_param }}"> <li><a href="{% url this_url_name branch.name %}{{ extra_url_param }}">
{% if branch.name == url_branch %}<b>{% endif %} {% if branch.name == url_branch %}<b>{% endif %}
{{ branch.name }} {{ branch }}
{% if branch.short_description %}
({{ branch.short_description }})
{% endif %}
{% if branch.name == url_branch %}</b>{% endif %} {% if branch.name == url_branch %}</b>{% endif %}
</a></li> </a></li>
{% endfor %} {% endfor %}
{% if oe_classic %} {% if comparison_branches %}
<li class="divider"></li> <li class="divider"></li>
<li><a href="{% url 'classic' %}">OE-Classic</a></li> {% for branch in comparison_branches %}
<li><a href="{% url 'comparison_recipe_search' branch.name %}">
{% if branch.name == url_branch %}<b>{% endif %}
{{ branch }}
{% if branch.name == url_branch %}</b>{% endif %}
</a></li>
{% endfor %}
{% endif %} {% endif %}
</ul> </ul>
</li> </li>

View File

@ -15,42 +15,23 @@
{% block title_append %} - OE-Classic{% endblock %} {% block title_append %} - OE-Classic{% endblock %}
--> -->
{% block branch_selector %}
{% autoescape on %}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Branch: <b>OE-Classic</b>
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
{% for branch in all_branches %}
<li><a href="{% url 'layer_list' branch.name %}">
{{ branch.name }}
{% if branch.short_description %}
({{ branch.short_description }})
{% endif %}
</a></li>
{% endfor %}
<li class="divider"></li>
<li><a href="{% url 'classic' %}"><b>OE-Classic</b></a></li>
</ul>
</li>
{% endautoescape %}
{% endblock %}
{% block content_inner %} {% block content_inner %}
{% autoescape on %} {% autoescape on %}
<div class="container-fluid"> <div class="container-fluid">
<div class="row-fluid"> <div class="row-fluid">
{% if branch.name == 'oe-classic' %}
<h2>OE-Classic</h2> <h2>OE-Classic</h2>
<p>OpenEmbedded-Classic (OE-Classic) is the name for the old monolithic version of OpenEmbedded. It contained a number of recipes some of which have not yet been migrated on top of OE-Core. To help people to find and migrate these recipes we provide an index here as well as some statistics to get an idea of the migration.</p> <p>OpenEmbedded-Classic (OE-Classic) is the name for the old monolithic version of OpenEmbedded. It contained a number of recipes some of which have not yet been migrated on top of OE-Core. To help people to find and migrate these recipes we provide an index here as well as some statistics to get an idea of the migration.</p>
{% else %}
<h2>{{ branch.short_description }}</h2>
{% endif %}
<a class="btn btn-large btn-primary" href="{% url 'classic_recipe_search' %}">Recipes</a> <a class="btn btn-large btn-primary" href="{% url 'comparison_recipe_search' branch.name %}">Recipes</a>
<a class="btn btn-large" href="{% url 'classic_recipe_search' %}?q=&cover_status=!">Unmigrated Recipes</a> <a class="btn btn-large" href="{% url 'comparison_recipe_search' branch.name %}?q=&cover_status=!">Unmigrated Recipes</a>
<a class="btn btn-large btn-primary" href="{% url 'classic_recipe_stats' %}">Stats</a> <a class="btn btn-large btn-primary" href="{% url 'comparison_recipe_stats' branch.name %}">Stats</a>
</div> </div>
</div> </div>

View File

@ -3,9 +3,9 @@
{% comment %} {% comment %}
layerindex-web - recipe detail page template layerindex-web - comparison recipe detail page template
Copyright (C) 2013 Intel Corporation Copyright (C) 2013, 2018 Intel Corporation
Licensed under the MIT license, see COPYING.MIT for details Licensed under the MIT license, see COPYING.MIT for details
{% endcomment %} {% endcomment %}
@ -13,7 +13,7 @@
<!-- <!--
{% autoescape on %} {% autoescape on %}
{% block title_append %} - OE-Classic - {{ recipe.pn }}{% endblock %} {% block title_append %} - {{ branch.short_description }} - {{ recipe.pn }}{% endblock %}
{% endautoescape %} {% endautoescape %}
--> -->
@ -21,7 +21,7 @@
{% autoescape on %} {% autoescape on %}
<ul class="breadcrumb"> <ul class="breadcrumb">
<li><a href="{% url 'classic_recipe_search' %}">OE-Classic</a> <span class="divider">&rarr;</span></li> <li><a href="{% url 'comparison_recipe_search' branch.name %}">{{ branch.short_description }}</a> <span class="divider">&rarr;</span></li>
<li class="active">{{ recipe.name }}</li> <li class="active">{{ recipe.name }}</li>
</ul> </ul>
@ -33,9 +33,11 @@
<h1>{{ recipe.name }} {{ recipe.pv }}</h1> <h1>{{ recipe.name }} {{ recipe.pv }}</h1>
</div> </div>
{% if branch.name == 'oe-classic' %}
<div class="alert alert-warning"> <div class="alert alert-warning">
<b>NOTE:</b> This recipe is for OE-Classic, the older monolithic version of OpenEmbedded which is no longer actively developed. See below for migration information. If no replacement is available in current OpenEmbedded layers, you may be able to <a href="http://www.openembedded.org/wiki/Migrating_metadata_to_OE-Core">migrate the recipe</a> yourself. <b>NOTE:</b> This recipe is for OE-Classic, the older monolithic version of OpenEmbedded which is no longer actively developed. See below for migration information. If no replacement is available in current OpenEmbedded layers, you may be able to <a href="http://www.openembedded.org/wiki/Migrating_metadata_to_OE-Core">migrate the recipe</a> yourself.
</div> </div>
{% endif %}
<table class="table table-striped table-bordered"> <table class="table table-striped table-bordered">
<tbody> <tbody>
@ -61,7 +63,7 @@
</tr> </tr>
<tr> <tr>
<th>License</th> <th>License</th>
<td>{{ recipe.license }}*</td> <td>{{ recipe.license }}{% if branch.name == 'oe-classic' %}*{% endif %}</td>
</tr> </tr>
<tr> <tr>
<th>Homepage</th> <th>Homepage</th>
@ -74,7 +76,7 @@
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<th>Recipe file</th> <th>{% if branch.name == 'oe-classic' %}Recipe file{% else %}Package file{% endif %}</th>
<td> <td>
{% if recipe.vcs_web_url %} {% if recipe.vcs_web_url %}
<a href="{{ recipe.vcs_web_url }}">{{ recipe.full_path }}</a> <a href="{{ recipe.vcs_web_url }}">{{ recipe.full_path }}</a>
@ -86,9 +88,37 @@
</tbody> </tbody>
</table> </table>
{% if branch.name == 'oe-classic' %}
<p>* - in OE-Classic, some of the license values were not accurate. Please refer to current recipes (if available) for this information.</p> <p>* - in OE-Classic, some of the license values were not accurate. Please refer to current recipes (if available) for this information.</p>
{% endif %}
<h2>Patches</h2>
{% if recipe.patch_set.exists %}
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Patch</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for patch in recipe.patch_set.all %}
<tr>
<td><a href="{{ patch.vcs_web_url }}">{{ patch.src_path }}</a></td>
<td>{{ patch.get_status_display }} {{ patch.status_extra }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>None</p>
{% endif %}
{% if branch.name == 'oe-classic' %}
<h2>Migration information</h2> <h2>Migration information</h2>
{% else %}
<h2>Comparison information</h2>
{% endif %}
{% if can_edit %} {% if can_edit %}
<form id="migration_form" class="form-inline" method="post"> <form id="migration_form" class="form-inline" method="post">
@ -122,6 +152,10 @@
<th class="span2">Coverage</th> <th class="span2">Coverage</th>
<td>{{ recipe.get_cover_desc }}</td> <td>{{ recipe.get_cover_desc }}</td>
</tr> </tr>
{% if recipe.cover_pn %}
<th>Covering recipe</th>
<td>{% if cover_recipe %}<a href="{% url 'recipe' cover_recipe.id %}">{% endif %}{{ recipe.cover_pn }}{% if cover_recipe %}</a>{% endif %}{% if recipe.cover_layerbranch %} (in <a href="{% url 'layer_item' 'master' recipe.cover_layerbranch.layer.name %}">{{ recipe.cover_layerbranch.layer.name }}</a>){% endif %}</td>
{% endif %}
<tr> <tr>
<th>Categories</th> <th>Categories</th>
<td>{{ recipe.classic_category }}</td> <td>{{ recipe.classic_category }}</td>
@ -141,7 +175,7 @@
<script> <script>
enable_value_field = function() { enable_value_field = function() {
cover_status = $('#id_cover_status').val() cover_status = $('#id_cover_status').val()
if( cover_status == 'U' || cover_status == 'N' ) { if( cover_status == 'U' || cover_status == 'N' || cover_status == 'S' ) {
$('#id_cover_pn').prop('readonly', true); $('#id_cover_pn').prop('readonly', true);
$('#id_cover_layerbranch').prop('readonly', true); $('#id_cover_layerbranch').prop('readonly', true);
$('#id_cover_verified').prop('readonly', true); $('#id_cover_verified').prop('readonly', true);

View File

@ -3,22 +3,22 @@
{% comment %} {% comment %}
layerindex-web - OE-Classic recipe search page template layerindex-web - comparison recipe search page template
Copyright (C) 2013 Intel Corporation Copyright (C) 2013, 2018 Intel Corporation
Licensed under the MIT license, see COPYING.MIT for details Licensed under the MIT license, see COPYING.MIT for details
{% endcomment %} {% endcomment %}
<!-- <!--
{% block title_append %} - OE-Classic recipes{% endblock %} {% block title_append %} - {% if branch.name == 'oe-classic' %}OE-Classic recipes{% else %}{{ branch.short_description }} packages{% endif %}{% endblock %}
--> -->
{% block navs %} {% block navs %}
{% autoescape on %} {% autoescape on %}
<li class="active"><a href="{% url 'classic_recipe_search' %}">Recipes</a></li> <li class="active"><a href="{% url 'comparison_recipe_search' branch.name %}">Recipes</a></li>
<li><a href="{% url 'classic_recipe_stats' %}">Stats</a></li> <li><a href="{% url 'comparison_recipe_stats' branch.name %}">Stats</a></li>
{% endautoescape %} {% endautoescape %}
{% endblock %} {% endblock %}
@ -28,11 +28,16 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span12"> <div class="span12">
{% if branch.name == 'oe-classic' %}
<h2>OE-Classic recipes</h2> <h2>OE-Classic recipes</h2>
<div class="alert alert-warning"> <div class="alert alert-warning">
<b>NOTE:</b> This is the recipe search for OE-Classic, the older monolithic version of OpenEmbedded which is no longer actively developed. <a href="{% url 'recipe_search' 'master' %}">Click here</a> to search current recipes. <b>NOTE:</b> This is the recipe search for OE-Classic, the older monolithic version of OpenEmbedded which is no longer actively developed. <a href="{% url 'recipe_search' 'master' %}">Click here</a> to search current recipes.
</div> </div>
{% else %}
<h2>{{ branch.short_description }} packages</h2>
{% endif %}
<div class="row-fluid"> <div class="row-fluid">
<form id="search-form" class="form-inline" method="GET"> <form id="search-form" class="form-inline" method="GET">
@ -48,6 +53,7 @@
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
<tr><td><label class="checkbox"><input type="checkbox" name="compare" {% if compare %}checked{% endif %}></input>Show comparison</label></td></tr>
</tbody> </tbody>
</table> </table>
<button class="btn" type="submit">Search</button> <button class="btn" type="submit">Search</button>
@ -58,28 +64,68 @@
<table class="table table-striped table-bordered recipestable"> <table class="table table-striped table-bordered recipestable">
<thead> <thead>
<tr> <tr>
{% if compare %}
{% if branch.name == 'oe-classic' %}
<th>Recipe name</th> <th>Recipe name</th>
{% else %}
<th>Package name</th>
{% endif %}
<th>Version</th>
<th>Patches</th>
<th>Status</th>
<th>OE Layer</th>
<th>OE Recipe</th>
<th>OE Version</th>
<th>OE Patches</th>
{% else %}
{% if branch.name == 'oe-classic' %}
<th>Recipe name</th>
{% else %}
<th>Package name</th>
{% endif %}
<th>Version</th> <th>Version</th>
<th class="span7">Description</th> <th class="span7">Description</th>
<th class="span5">Status</th> <th class="span5">Status</th>
<th>Covering recipe</th>
<th>Categories</th> <th>Categories</th>
{% if multi_classic_layers %} {% endif %}
<th>Layer</th>
{% endif %}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for recipe in recipe_list %} {% for recipe in recipe_list %}
<tr {% if recipe.preferred_count > 0 %}class="muted"{% endif %}> <tr {% if recipe.preferred_count > 0 %}class="muted"{% endif %}>
{% if compare %}
{% if branch.name == 'oe-classic' %}
<td><a href="{% url 'classic_recipe' recipe.id %}">{{ recipe.name }}</a></td> <td><a href="{% url 'classic_recipe' recipe.id %}">{{ recipe.name }}</a></td>
{% else %}
<td><a href="{% url 'comparison_recipe' recipe.id %}">{{ recipe.name }}</a></td>
{% endif %}
<td>{{ recipe.pv|truncatechars:10 }}</td>
<td>{% if recipe.patch_set.exists %}{{ recipe.patch_set.count }}{% endif %}</td>
<td>{{ recipe.get_cover_status_display }}{% if recipe.cover_comment %} <a href="{% url 'classic_recipe' recipe.id %}"><i class="icon-comment" data-toggle="tooltip" title="{{ recipe.cover_comment }}"></i></a>{% endif %}</td>
<td>{% if recipe.cover_layerbranch %}<a href="{% url 'layer_item' 'master' recipe.cover_layerbranch.layer.name %}">{{ recipe.cover_layerbranch.layer.name }}</a>{% endif %}</td>
{% if recipe.cover_pn %}
<td>{% if recipe.cover_recipe %}<a href="{% url 'recipe' recipe.cover_recipe.id %}">{% endif %}{{ recipe.cover_pn }}{% if recipe.cover_recipe %}</a>{% endif %}</td>
<td {% if recipe.cover_vercmp < 0 %}class="error"{% endif %}>{% if recipe.cover_recipe %}{{ recipe.cover_recipe.pv|truncatechars:10 }}{% endif %}</td>
<td>{% if recipe.cover_recipe and recipe.cover_recipe.patch_set.exists %}{{ recipe.cover_recipe.patch_set.count }}{% endif %}</td>
{% else %}
<td></td>
<td></td>
<td></td>
{% endif %}
{% else %}
{% if branch.name == 'oe-classic' %}
<td><a href="{% url 'classic_recipe' recipe.id %}">{{ recipe.name }}</a></td>
{% else %}
<td><a href="{% url 'comparison_recipe' recipe.id %}">{{ recipe.name }}</a></td>
{% endif %}
<td>{{ recipe.pv }}</td> <td>{{ recipe.pv }}</td>
<td>{{ recipe.short_desc }}</td> <td>{{ recipe.short_desc }}</td>
<td>{{ recipe.get_cover_desc }}</td> <td>{{ recipe.get_cover_desc }}</td>
<td>{% if recipe.cover_pn %}{% if recipe.cover_recipe %}<a href="{% url 'recipe' recipe.cover_recipe.id %}">{% endif %}{{ recipe.cover_pn }}{% if recipe.cover_recipe %}</a>{% endif %}{% endif %}</td>
<td>{{ recipe.classic_category }}</td> <td>{{ recipe.classic_category }}</td>
{% if multi_classic_layers %} {% endif %}
<td><a href="{% url 'layer_item' recipe.layerbranch.layer.name %}">{{ recipe.layerbranch.layer.name }}</a></td>
{% endif %}
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -91,7 +137,11 @@
{% endif %} {% endif %}
{% else %} {% else %}
{% if searched %} {% if searched %}
{% if branch.name == 'oe-classic' %}
<p>No matching OE-Classic recipes in database.</p> <p>No matching OE-Classic recipes in database.</p>
{% else %}
<p>No matching {{ branch }} packages in database.</p>
{% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}
@ -107,6 +157,7 @@
{% block scripts %} {% block scripts %}
<script> <script>
$(document).ready(function() { $(document).ready(function() {
$('[data-toggle="tooltip"]').tooltip();
firstfield = $("#search-form input:text").first() firstfield = $("#search-form input:text").first()
if( ! firstfield.val() ) if( ! firstfield.val() )
firstfield.focus() firstfield.focus()

View File

@ -7,20 +7,20 @@
layerindex-web - OE-Classic recipe migration stats template layerindex-web - OE-Classic recipe migration stats template
Copyright (C) 2013 Intel Corporation Copyright (C) 2013, 2018 Intel Corporation
Licensed under the MIT license, see COPYING.MIT for details Licensed under the MIT license, see COPYING.MIT for details
{% endcomment %} {% endcomment %}
<!-- <!--
{% block title_append %} - OE-Classic recipe statistics{% endblock %} {% block title_append %} - {% if branch.name == 'oe-classic' %}OE-Classic{% else %}{{ branch.short_description }}{% endif %} recipe statistics{% endblock %}
--> -->
{% block navs %} {% block navs %}
{% autoescape on %} {% autoescape on %}
<li><a href="{% url 'classic_recipe_search' %}">Recipes</a></li> <li><a href="{% url 'comparison_recipe_search' branch.name %}">Recipes</a></li>
<li class="active"><a href="{% url 'classic_recipe_stats' %}">Stats</a></li> <li class="active"><a href="{% url 'comparison_recipe_stats' branch.name %}">Stats</a></li>
{% endautoescape %} {% endautoescape %}
{% endblock %} {% endblock %}
@ -31,12 +31,16 @@
<div class="row-fluid"> <div class="row-fluid">
{% if branch.name == 'oe-classic' %}
<h2>OE-Classic statistics</h2> <h2>OE-Classic statistics</h2>
{% else %}
<h2>{{ branch.short_description }} statistics</h2>
{% endif %}
<h3>Migration status</h3> <h3>Comparison status</h3>
{% include_container "chart_status" 400 600 %} {% include_container "chart_status" 400 600 %}
<h3>Unmigrated recipes by category</h3> <h3>Unavailable recipes by category</h3>
{% include_container "chart_category" 400 600 %} {% include_container "chart_category" 400 600 %}
</div> </div>