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.

Signed-off-by: Michael Wood <[email protected]>
---
 bitbake/lib/toaster/toastergui/tables.py           | 149 +++++++++++++++++----
 .../snippets/pkg_dependencies_popover.html         |  14 ++
 bitbake/lib/toaster/toastergui/urls.py             |  10 +-
 bitbake/lib/toaster/toastergui/views.py            |   9 --
 4 files changed, 143 insertions(+), 39 deletions(-)
 create mode 100644 
bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html

diff --git a/bitbake/lib/toaster/toastergui/tables.py 
b/bitbake/lib/toaster/toastergui/tables.py
index 6bbf0d7..7ce6651 100644
--- a/bitbake/lib/toaster/toastergui/tables.py
+++ b/bitbake/lib/toaster/toastergui/tables.py
@@ -21,8 +21,8 @@
 
 from toastergui.widgets import ToasterTable
 from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
-from orm.models import CustomImageRecipe, Package
-from django.db.models import Q, Max
+from orm.models import CustomImageRecipe, Package, Target, Build
+from django.db.models import Q, Max, Sum
 from django.conf.urls import url
 from django.core.urlresolvers import reverse
 from django.views.generic import TemplateView
@@ -440,8 +440,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):
@@ -459,22 +459,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,
@@ -497,12 +506,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)
@@ -565,8 +581,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"""
+
+    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(ToasterTable):
+class SelectPackagesTable(PackagesTable):
     """ Table to display the packages to add and remove from an image """
 
     def __init__(self, *args, **kwargs):
@@ -593,24 +697,20 @@ class SelectPackagesTable(ToasterTable):
         self.static_context_extra['current_packages'] = \
                 cust_recipe.packages.values_list('pk', flat=True)
 
-    def setup_columns(self, *args, **kwargs):
-        self.add_column(title="Package",
-                        hideable=False,
-                        orderable=True,
-                        field_name="name")
+    def get_context_data(self, **kwargs):
+        context = super(SelectPackagesTable, self).get_context_data(**kwargs)
+        custom_recipe = CustomImageRecipe.objects.get(pk=kwargs['recipe_id'])
 
-        self.add_column(title="Package Version",
-                        field_name="version")
+        context['recipe'] = custom_recipe
+        context['approx_pkg_size'] =  
custom_recipe.package_set.aggregate(Sum('size'))
+        return context
 
-        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")
+
+    def setup_columns(self, *args, **kwargs):
+        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",
@@ -637,11 +737,10 @@ 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'])
diff --git 
a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
 
b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
new file mode 100644
index 0000000..a08409a
--- /dev/null
+++ 
b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
@@ -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 %}
diff --git a/bitbake/lib/toaster/toastergui/urls.py 
b/bitbake/lib/toaster/toastergui/urls.py
index 50acb1b..36e5c38 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -103,13 +103,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'),
 
@@ -127,17 +124,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$',
diff --git a/bitbake/lib/toaster/toastergui/views.py 
b/bitbake/lib/toaster/toastergui/views.py
index c10b19f..53553a5 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -2886,15 +2886,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):
 
-- 
2.1.4

-- 
_______________________________________________
toaster mailing list
[email protected]
https://lists.yoctoproject.org/listinfo/toaster

Reply via email to