diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py index 38088201d8..e5cab48c48 100644 --- a/bitbake/lib/toaster/toastergui/tables.py +++ b/bitbake/lib/toaster/toastergui/tables.py @@ -21,13 +21,12 @@ 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, Build +from django.db.models import Q, Max, Count from django.conf.urls import url from django.core.urlresolvers import reverse from django.views.generic import TemplateView - class ProjectFiltersMixin(object): """Common mixin for recipe, machine in project filters""" @@ -633,3 +632,224 @@ class SelectPackagesTable(ToasterTable): "the package content of you custom image", static_data_name="add_rm_pkg_btn", static_data_template='{% include "pkg_add_rm_btn.html" %}') + +class ProjectsTable(ToasterTable): + """Table of projects in Toaster""" + + def __init__(self, *args, **kwargs): + super(ProjectsTable, self).__init__(*args, **kwargs) + self.default_orderby = 'updated' + self.title = 'All projects' + self.static_context_extra['Build'] = Build + + def get_context_data(self, **kwargs): + return super(ProjectsTable, self).get_context_data(**kwargs) + + def setup_queryset(self, *args, **kwargs): + queryset = Project.objects.all() + + # annotate each project with its number of builds + queryset = queryset.annotate(num_builds=Count('build')) + + # exclude the command line builds project if it has no builds + q_default_with_builds = Q(is_default=True) & Q(num_builds__gt=0) + queryset = queryset.filter(Q(is_default=False) | + q_default_with_builds) + + # order rows + queryset = queryset.order_by(self.default_orderby) + + self.queryset = queryset + + # columns: last activity on (updated) - DEFAULT, project (name), release, machine, number of builds, last build outcome, recipe (name), errors, warnings, image files + def setup_columns(self, *args, **kwargs): + name_template = ''' + {% load project_url_tag %} + + + {{data.name}} + + + ''' + + last_activity_on_template = ''' + {% load project_url_tag %} + + + {{data.updated | date:"d/m/y H:i"}} + + + ''' + + release_template = ''' + + {% if data.release %} + + {{data.release.name}} + + {% elif data.is_default %} + Not applicable + + {% else %} + No release available + {% endif %} + + ''' + + machine_template = ''' + + {% if data.is_default %} + Not applicable + + {% else %} + + {{data.get_current_machine_name}} + + {% endif %} + + ''' + + number_of_builds_template = ''' + {% if data.get_number_of_builds > 0 %} + + {{data.get_number_of_builds}} + + {% else %} + 0 + {% endif %} + ''' + + last_build_outcome_template = ''' + {% if data.get_number_of_builds > 0 %} + + {% if data.get_last_outcome == extra.Build.SUCCEEDED %} + + {% elif data.get_last_outcome == extra.Build.FAILED %} + + {% endif %} + + {% endif %} + ''' + + recipe_template = ''' + {% if data.get_number_of_builds > 0 %} + + {{data.get_last_target}} + + {% endif %} + ''' + + errors_template = ''' + {% if data.get_number_of_builds > 0 %} + + {{data.get_last_errors}} error{{data.get_last_errors | pluralize}} + + {% endif %} + ''' + + warnings_template = ''' + {% if data.get_number_of_builds > 0 %} + + {{data.get_last_warnings}} warning{{data.get_last_warnings | pluralize}} + + {% endif %} + ''' + + image_files_template = ''' + {% load projecttags %} + {% if data.get_number_of_builds > 0 and data.get_last_outcome == extra.Build.SUCCEEDED %} + + {{fstypes | get_dict_value:data.id}} + + {% endif %} + ''' + + self.add_column(title='Project', + hideable=False, + orderable=True, + static_data_name='name', + static_data_template=name_template) + + self.add_column(title='Last activity on', + help_text='Starting date and time of the \ + last project build. If the project has no \ + builds, this shows the date the project was \ + created.', + hideable=True, + orderable=True, + static_data_name='updated', + static_data_template=last_activity_on_template) + + self.add_column(title='Release', + help_text='The version of the build system used by \ + the project', + hideable=False, + orderable=True, + static_data_name='release', + static_data_template=release_template) + + self.add_column(title='Machine', + help_text='The hardware currently selected for the \ + project', + hideable=False, + orderable=False, + static_data_name='machine', + static_data_template=machine_template) + + self.add_column(title='Number of builds', + help_text='The number of builds which have been run \ + for the project', + hideable=True, + orderable=False, + static_data_name='number_of_builds', + static_data_template=number_of_builds_template) + + self.add_column(title='Last build outcome', + help_text='Indicates whether the last project build \ + completed successfully or failed', + hideable=True, + orderable=False, + static_data_name='last_build_outcome', + static_data_template=last_build_outcome_template) + + self.add_column(title='Recipe', + help_text='The last recipe which was built in this \ + project', + hideable=True, + orderable=False, + static_data_name='recipe_name', + static_data_template=recipe_template) + + self.add_column(title='Errors', + help_text='The number of errors encountered during \ + the last project build (if any)', + hideable=True, + orderable=False, + static_data_name='errors', + static_data_template=errors_template) + + self.add_column(title='Warnings', + help_text='The number of warnings encountered during \ + the last project build (if any)', + hideable=True, + orderable=False, + static_data_name='warnings', + static_data_template=warnings_template) + + self.add_column(title='Image files', + help_text='', + hideable=True, + orderable=False, + static_data_name='image_files', + static_data_template=image_files_template) diff --git a/bitbake/lib/toaster/toastergui/templates/projects-toastertable.html b/bitbake/lib/toaster/toastergui/templates/projects-toastertable.html new file mode 100644 index 0000000000..5814f32d06 --- /dev/null +++ b/bitbake/lib/toaster/toastergui/templates/projects-toastertable.html @@ -0,0 +1,36 @@ +{% extends 'base.html' %} + +{% block title %} All projects - Toaster {% endblock %} + +{% block pagecontent %} + + + + {% url 'projects' as xhr_table_url %} + {% include 'toastertable.html' %} + + + +{% endblock %} diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 2bf2d99ae7..da97a31133 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py @@ -75,8 +75,14 @@ urlpatterns = patterns('toastergui.views', url(r'^newproject/$', 'newproject', name='newproject'), + # TODO remove when new toaster table is ready url(r'^projects/$', 'projects', name='all-projects'), + # TODO move to /projects/ when new toaster table is ready + url(r'^projects-new/$', + tables.ProjectsTable.as_view(template_name="projects-toastertable.html"), + name='all-projects-new'), + url(r'^project/(?P\d+)/$', 'project', name='project'), url(r'^project/(?P\d+)/configuration$', 'projectconf', name='projectconf'), url(r'^project/(?P\d+)/builds/$', 'projectbuilds', name='projectbuilds'),