bitbake: toaster: tables Add table for Packages and update SelectPackagesTable
Create a Packages table for use as the image details page. Change the SelectPackagesTable table to inherit from the Packages table. Remove the need for a separate view by adding the additional template context items to the Table's page context. (Bitbake rev: 336b1d8369d9e86ece78b63cb0e140e653216011) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: brian avery <avery.brian@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
43f0a05fa4
commit
d6e7e4ad43
|
@ -21,7 +21,7 @@
|
|||
|
||||
from toastergui.widgets import ToasterTable
|
||||
from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
|
||||
from orm.models import CustomImageRecipe, Package, Build, LogMessage, Task
|
||||
from orm.models import CustomImageRecipe, Package, Target, Build, LogMessage, Task
|
||||
from orm.models import ProjectTarget
|
||||
from django.db.models import Q, Max, Count, When, Case, Value, IntegerField
|
||||
from django.conf.urls import url
|
||||
|
@ -483,8 +483,8 @@ class CustomImagesTable(ToasterTable):
|
|||
def get_context_data(self, **kwargs):
|
||||
context = super(CustomImagesTable, self).get_context_data(**kwargs)
|
||||
project = Project.objects.get(pk=kwargs['pid'])
|
||||
# TODO put project into the ToasterTable base class
|
||||
context['project'] = project
|
||||
context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
|
||||
return context
|
||||
|
||||
def setup_queryset(self, *args, **kwargs):
|
||||
|
@ -502,22 +502,31 @@ class CustomImagesTable(ToasterTable):
|
|||
|
||||
self.add_column(title="Custom image",
|
||||
hideable=False,
|
||||
orderable=True,
|
||||
field_name="name",
|
||||
static_data_name="name",
|
||||
static_data_template=name_link_template)
|
||||
|
||||
self.add_column(title="Recipe file",
|
||||
static_data_name='recipe_file',
|
||||
static_data_template='')
|
||||
static_data_template='',
|
||||
field_name='local_path')
|
||||
|
||||
approx_packages_template = '''
|
||||
<a href="{% url 'customrecipe' extra.pid data.id %}">
|
||||
{{data.package_set.all|length}}
|
||||
</a>'''
|
||||
|
||||
approx_packages_template = '<a href="#imagedetails">{{data.packages.all|length}}</a>'
|
||||
self.add_column(title="Approx packages",
|
||||
static_data_name='approx_packages',
|
||||
static_data_template=approx_packages_template)
|
||||
|
||||
|
||||
build_btn_template = '''<button data-recipe-name="{{data.name}}"
|
||||
build_btn_template = '''
|
||||
<button data-recipe-name="{{data.name}}"
|
||||
class="btn btn-block build-recipe-btn" style="margin-top: 5px;" >
|
||||
Build</button>'''
|
||||
Build
|
||||
</button>'''
|
||||
|
||||
self.add_column(title="Build",
|
||||
hideable=False,
|
||||
|
@ -540,12 +549,19 @@ class ImageRecipesTable(RecipesTable):
|
|||
|
||||
|
||||
def setup_columns(self, *args, **kwargs):
|
||||
|
||||
name_link_template = '''
|
||||
<a href="{% url 'recipedetails' extra.pid data.pk %}">{{data.name}}</a>
|
||||
'''
|
||||
|
||||
self.add_column(title="Image recipe",
|
||||
help_text="When you build an image recipe, you get an "
|
||||
"image: a root file system you can"
|
||||
"deploy to a machine",
|
||||
hideable=False,
|
||||
orderable=True,
|
||||
static_data_name="name",
|
||||
static_data_template=name_link_template,
|
||||
field_name="name")
|
||||
|
||||
super(ImageRecipesTable, self).setup_columns(*args, **kwargs)
|
||||
|
@ -609,8 +625,96 @@ class SoftwareRecipesTable(RecipesTable):
|
|||
|
||||
self.add_column(**RecipesTable.build_col)
|
||||
|
||||
class PackagesTable(ToasterTable):
|
||||
""" Table to display the packages in a recipe from it's last successful
|
||||
build"""
|
||||
|
||||
class SelectPackagesTable(ToasterTable):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PackagesTable, self).__init__(*args, **kwargs)
|
||||
self.title = "Packages included"
|
||||
self.packages = None
|
||||
self.default_orderby = "name"
|
||||
|
||||
def create_package_list(self, recipe, project_id):
|
||||
"""Creates a list of packages for the specified recipe by looking for
|
||||
the last SUCCEEDED build of ther recipe"""
|
||||
|
||||
target = Target.objects.filter(Q(target=recipe.name) &
|
||||
Q(build__project_id=project_id) &
|
||||
Q(build__outcome=Build.SUCCEEDED)
|
||||
).last()
|
||||
|
||||
if target:
|
||||
return target.build.package_set.all()
|
||||
|
||||
# Target/recipe never successfully built so empty queryset
|
||||
return Package.objects.none()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Context for rendering the sidebar and other items on the recipe
|
||||
details page """
|
||||
context = super(PackagesTable, self).get_context_data(**kwargs)
|
||||
|
||||
recipe = Recipe.objects.get(pk=kwargs['recipe_id'])
|
||||
project = Project.objects.get(pk=kwargs['pid'])
|
||||
|
||||
in_project = (recipe.layer_version.pk in
|
||||
project.get_project_layer_versions(pk=True))
|
||||
|
||||
packages = self.create_package_list(recipe, project.pk)
|
||||
|
||||
context.update({'project': project,
|
||||
'recipe' : recipe,
|
||||
'packages': packages,
|
||||
'approx_pkg_size' : packages.aggregate(Sum('size')),
|
||||
'in_project' : in_project,
|
||||
})
|
||||
|
||||
return context
|
||||
|
||||
def setup_queryset(self, *args, **kwargs):
|
||||
recipe = Recipe.objects.get(pk=kwargs['recipe_id'])
|
||||
|
||||
self.queryset = self.create_package_list(recipe, kwargs['pid'])
|
||||
self.queryset = self.queryset.order_by('name')
|
||||
|
||||
def setup_columns(self, *args, **kwargs):
|
||||
self.add_column(title="Package",
|
||||
hideable=False,
|
||||
orderable=True,
|
||||
field_name="name")
|
||||
|
||||
self.add_column(title="Package Version",
|
||||
field_name="version",
|
||||
hideable=False)
|
||||
|
||||
self.add_column(title="Approx Size",
|
||||
orderable=True,
|
||||
static_data_name="size",
|
||||
static_data_template="{% load projecttags %} \
|
||||
{{data.size|filtered_filesizeformat}}")
|
||||
|
||||
self.add_column(title="License",
|
||||
field_name="license",
|
||||
orderable=True)
|
||||
|
||||
|
||||
self.add_column(title="Dependencies",
|
||||
static_data_name="dependencies",
|
||||
static_data_template='\
|
||||
{% include "snippets/pkg_dependencies_popover.html" %}')
|
||||
|
||||
self.add_column(title="Recipe",
|
||||
field_name="recipe__name",
|
||||
orderable=True,
|
||||
hidden=True)
|
||||
|
||||
self.add_column(title="Recipe version",
|
||||
field_name="recipe__version",
|
||||
hidden=True)
|
||||
|
||||
|
||||
class SelectPackagesTable(PackagesTable):
|
||||
""" Table to display the packages to add and remove from an image """
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -637,29 +741,25 @@ class SelectPackagesTable(ToasterTable):
|
|||
self.static_context_extra['current_packages'] = \
|
||||
cust_recipe.packages.values_list('pk', flat=True)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(SelectPackagesTable, self).get_context_data(**kwargs)
|
||||
custom_recipe = CustomImageRecipe.objects.get(pk=kwargs['recipe_id'])
|
||||
|
||||
context['recipe'] = custom_recipe
|
||||
context['approx_pkg_size'] = custom_recipe.package_set.aggregate(Sum('size'))
|
||||
return context
|
||||
|
||||
|
||||
def setup_columns(self, *args, **kwargs):
|
||||
self.add_column(title="Package",
|
||||
hideable=False,
|
||||
orderable=True,
|
||||
field_name="name")
|
||||
|
||||
self.add_column(title="Package Version",
|
||||
field_name="version")
|
||||
|
||||
self.add_column(title="Approx Size",
|
||||
orderable=True,
|
||||
static_data_name="size",
|
||||
static_data_template="{% load projecttags %} \
|
||||
{{data.size|filtered_filesizeformat}}")
|
||||
self.add_column(title="summary",
|
||||
field_name="summary")
|
||||
super(SelectPackagesTable, self).setup_columns(*args, **kwargs)
|
||||
|
||||
self.add_column(title="Add | Remove",
|
||||
hideable=False,
|
||||
help_text="Use the add and remove buttons to modify "
|
||||
"the package content of you custom image",
|
||||
static_data_name="add_rm_pkg_btn",
|
||||
static_data_template='{% include "pkg_add_rm_btn.html" %}',
|
||||
static_data_template='{% include "pkg_add_rm_btn.html" %}'
|
||||
filter_name="in_current_image"
|
||||
)
|
||||
|
||||
def setup_filters(self, *args, **kwargs):
|
||||
|
@ -681,12 +781,11 @@ class SelectPackagesTable(ToasterTable):
|
|||
self.filter_not_in_image)
|
||||
])
|
||||
|
||||
def filter_in_image(self, count_only=False):
|
||||
def filter_in_image(self):
|
||||
return self.queryset.filter(
|
||||
pk__in=self.static_context_extra['current_packages'])
|
||||
|
||||
|
||||
def filter_not_in_image(self, count_only=False):
|
||||
def filter_not_in_image(self):
|
||||
return self.queryset.exclude(
|
||||
pk__in=self.static_context_extra['current_packages'])
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{# Popover that displays the dependences and sizes of a package 'data' used in the Packages table #}
|
||||
{% with data.package_dependencies_source.count as dep_count %}
|
||||
{% load projecttags %}
|
||||
{% if dep_count %}
|
||||
<a data-content="<ul class='unstyled'>
|
||||
{% for dep in data.package_dependencies_source.all %}
|
||||
<li>{{dep.depends_on.name}} {% if dep.depends_on.size > 0 %}({{dep.depends_on.size|filtered_filesizeformat}}){% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>" title="" class="btn" data-original-title="
|
||||
<strong>{{data.name}}</strong> dependencies - <strong>{{data.package_dependencies_source.get_total_source_deps_size.depends_on__size__sum|filtered_filesizeformat}}</strong>">
|
||||
{{dep_count}}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endwith %}
|
|
@ -109,13 +109,10 @@ urlpatterns = patterns('toastergui.views',
|
|||
tables.NewCustomImagesTable.as_view(template_name="newcustomimage.html"),
|
||||
name="newcustomimage"),
|
||||
|
||||
|
||||
url(r'^project/(?P<pid>\d+)/layers/$',
|
||||
tables.LayersTable.as_view(template_name="generic-toastertable-page.html"),
|
||||
name="projectlayers"),
|
||||
|
||||
|
||||
|
||||
url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$',
|
||||
'layerdetails', name='layerdetails'),
|
||||
|
||||
|
@ -133,17 +130,20 @@ urlpatterns = patterns('toastergui.views',
|
|||
|
||||
|
||||
url(r'^project/(?P<pid>\d+)/customrecipe/(?P<recipeid>\d+)/selectpackages/$',
|
||||
tables.SelectPackagesTable.as_view(template_name="generic-toastertable-page.html"), name="recipeselectpackages"),
|
||||
tables.SelectPackagesTable.as_view(), name="recipeselectpackages"),
|
||||
|
||||
|
||||
url(r'^project/(?P<pid>\d+)/customrecipe/(?P<recipe_id>\d+)$',
|
||||
'customrecipe',
|
||||
tables.SelectPackagesTable.as_view(template_name="customrecipe.html"),
|
||||
name="customrecipe"),
|
||||
|
||||
url(r'^project/(?P<pid>\d+)/customrecipe/(?P<recipe_id>\d+)/download$',
|
||||
'customrecipe_download',
|
||||
name="customrecipedownload"),
|
||||
|
||||
url(r'^project/(?P<pid>\d+)/recipe/(?P<recipe_id>\d+)$',
|
||||
tables.PackagesTable.as_view(template_name="recipedetails.html"),
|
||||
name="recipedetails"),
|
||||
|
||||
# typeahead api end points
|
||||
url(r'^xhr_typeahead/(?P<pid>\d+)/layers$',
|
||||
|
|
|
@ -2594,15 +2594,6 @@ if True:
|
|||
|
||||
return(vars_managed,sorted(vars_fstypes),vars_blacklist)
|
||||
|
||||
def customrecipe(request, pid, recipe_id):
|
||||
project = Project.objects.get(pk=pid)
|
||||
context = {'project' : project,
|
||||
'projectlayers': [],
|
||||
'recipe' : CustomImageRecipe.objects.get(pk=recipe_id)
|
||||
}
|
||||
|
||||
return render(request, "customrecipe.html", context)
|
||||
|
||||
@_template_renderer("projectconf.html")
|
||||
def projectconf(request, pid):
|
||||
|
||||
|
|
Loading…
Reference in New Issue