diff options
Diffstat (limited to 'bitbake/lib')
-rw-r--r-- | bitbake/lib/toaster/toastergui/tables.py | 226 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/projects-toastertable.html | 36 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/urls.py | 6 |
3 files changed, 265 insertions, 3 deletions
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 @@ | |||
21 | 21 | ||
22 | from toastergui.widgets import ToasterTable | 22 | from toastergui.widgets import ToasterTable |
23 | from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project | 23 | from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project |
24 | from orm.models import CustomImageRecipe, Package | 24 | from orm.models import CustomImageRecipe, Package, Build |
25 | from django.db.models import Q, Max | 25 | from django.db.models import Q, Max, Count |
26 | from django.conf.urls import url | 26 | from django.conf.urls import url |
27 | from django.core.urlresolvers import reverse | 27 | from django.core.urlresolvers import reverse |
28 | from django.views.generic import TemplateView | 28 | from django.views.generic import TemplateView |
29 | 29 | ||
30 | |||
31 | class ProjectFiltersMixin(object): | 30 | class ProjectFiltersMixin(object): |
32 | """Common mixin for recipe, machine in project filters""" | 31 | """Common mixin for recipe, machine in project filters""" |
33 | 32 | ||
@@ -633,3 +632,224 @@ class SelectPackagesTable(ToasterTable): | |||
633 | "the package content of you custom image", | 632 | "the package content of you custom image", |
634 | static_data_name="add_rm_pkg_btn", | 633 | static_data_name="add_rm_pkg_btn", |
635 | static_data_template='{% include "pkg_add_rm_btn.html" %}') | 634 | static_data_template='{% include "pkg_add_rm_btn.html" %}') |
635 | |||
636 | class ProjectsTable(ToasterTable): | ||
637 | """Table of projects in Toaster""" | ||
638 | |||
639 | def __init__(self, *args, **kwargs): | ||
640 | super(ProjectsTable, self).__init__(*args, **kwargs) | ||
641 | self.default_orderby = 'updated' | ||
642 | self.title = 'All projects' | ||
643 | self.static_context_extra['Build'] = Build | ||
644 | |||
645 | def get_context_data(self, **kwargs): | ||
646 | return super(ProjectsTable, self).get_context_data(**kwargs) | ||
647 | |||
648 | def setup_queryset(self, *args, **kwargs): | ||
649 | queryset = Project.objects.all() | ||
650 | |||
651 | # annotate each project with its number of builds | ||
652 | queryset = queryset.annotate(num_builds=Count('build')) | ||
653 | |||
654 | # exclude the command line builds project if it has no builds | ||
655 | q_default_with_builds = Q(is_default=True) & Q(num_builds__gt=0) | ||
656 | queryset = queryset.filter(Q(is_default=False) | | ||
657 | q_default_with_builds) | ||
658 | |||
659 | # order rows | ||
660 | queryset = queryset.order_by(self.default_orderby) | ||
661 | |||
662 | self.queryset = queryset | ||
663 | |||
664 | # columns: last activity on (updated) - DEFAULT, project (name), release, machine, number of builds, last build outcome, recipe (name), errors, warnings, image files | ||
665 | def setup_columns(self, *args, **kwargs): | ||
666 | name_template = ''' | ||
667 | {% load project_url_tag %} | ||
668 | <span data-project-field="name"> | ||
669 | <a href="{% project_url data %}"> | ||
670 | {{data.name}} | ||
671 | </a> | ||
672 | </span> | ||
673 | ''' | ||
674 | |||
675 | last_activity_on_template = ''' | ||
676 | {% load project_url_tag %} | ||
677 | <span data-project-field="updated"> | ||
678 | <a href="{% project_url data %}"> | ||
679 | {{data.updated | date:"d/m/y H:i"}} | ||
680 | </a> | ||
681 | </span> | ||
682 | ''' | ||
683 | |||
684 | release_template = ''' | ||
685 | <span data-project-field="release"> | ||
686 | {% if data.release %} | ||
687 | <a href="{% url 'project' data.id %}#project-details"> | ||
688 | {{data.release.name}} | ||
689 | </a> | ||
690 | {% elif data.is_default %} | ||
691 | <span class="muted">Not applicable</span> | ||
692 | <i class="icon-question-sign get-help hover-help" | ||
693 | data-original-title="This project does not have a release set. | ||
694 | It simply collects information about the builds you start from | ||
695 | the command line while Toaster is running" | ||
696 | style="visibility: hidden;"> | ||
697 | </i> | ||
698 | {% else %} | ||
699 | No release available | ||
700 | {% endif %} | ||
701 | </span> | ||
702 | ''' | ||
703 | |||
704 | machine_template = ''' | ||
705 | <span data-project-field="machine"> | ||
706 | {% if data.is_default %} | ||
707 | <span class="muted">Not applicable</span> | ||
708 | <i class="icon-question-sign get-help hover-help" | ||
709 | data-original-title="This project does not have a machine | ||
710 | set. It simply collects information about the builds you | ||
711 | start from the command line while Toaster is running" | ||
712 | style="visibility: hidden;"></i> | ||
713 | {% else %} | ||
714 | <a href="{% url 'project' data.id %}#machine-distro"> | ||
715 | {{data.get_current_machine_name}} | ||
716 | </a> | ||
717 | {% endif %} | ||
718 | </span> | ||
719 | ''' | ||
720 | |||
721 | number_of_builds_template = ''' | ||
722 | {% if data.get_number_of_builds > 0 %} | ||
723 | <a href="{% url 'projectbuilds' data.id %}"> | ||
724 | {{data.get_number_of_builds}} | ||
725 | </a> | ||
726 | {% else %} | ||
727 | <span class="muted">0</span> | ||
728 | {% endif %} | ||
729 | ''' | ||
730 | |||
731 | last_build_outcome_template = ''' | ||
732 | {% if data.get_number_of_builds > 0 %} | ||
733 | <a href="{% url 'builddashboard' data.get_last_build_id %}"> | ||
734 | {% if data.get_last_outcome == extra.Build.SUCCEEDED %} | ||
735 | <i class="icon-ok-sign success"></i> | ||
736 | {% elif data.get_last_outcome == extra.Build.FAILED %} | ||
737 | <i class="icon-minus-sign error"></i> | ||
738 | {% endif %} | ||
739 | </a> | ||
740 | {% endif %} | ||
741 | ''' | ||
742 | |||
743 | recipe_template = ''' | ||
744 | {% if data.get_number_of_builds > 0 %} | ||
745 | <a href="{% url "builddashboard" data.get_last_build_id %}"> | ||
746 | {{data.get_last_target}} | ||
747 | </a> | ||
748 | {% endif %} | ||
749 | ''' | ||
750 | |||
751 | errors_template = ''' | ||
752 | {% if data.get_number_of_builds > 0 %} | ||
753 | <a class="errors.count error" | ||
754 | href="{% url "builddashboard" data.get_last_build_id %}#errors"> | ||
755 | {{data.get_last_errors}} error{{data.get_last_errors | pluralize}} | ||
756 | </a> | ||
757 | {% endif %} | ||
758 | ''' | ||
759 | |||
760 | warnings_template = ''' | ||
761 | {% if data.get_number_of_builds > 0 %} | ||
762 | <a class="warnings.count warning" | ||
763 | href="{% url "builddashboard" data.get_last_build_id %}#warnings"> | ||
764 | {{data.get_last_warnings}} warning{{data.get_last_warnings | pluralize}} | ||
765 | </a> | ||
766 | {% endif %} | ||
767 | ''' | ||
768 | |||
769 | image_files_template = ''' | ||
770 | {% load projecttags %} | ||
771 | {% if data.get_number_of_builds > 0 and data.get_last_outcome == extra.Build.SUCCEEDED %} | ||
772 | <a href="{% url "builddashboard" data.get_last_build_id %}#images"> | ||
773 | {{fstypes | get_dict_value:data.id}} | ||
774 | </a> | ||
775 | {% endif %} | ||
776 | ''' | ||
777 | |||
778 | self.add_column(title='Project', | ||
779 | hideable=False, | ||
780 | orderable=True, | ||
781 | static_data_name='name', | ||
782 | static_data_template=name_template) | ||
783 | |||
784 | self.add_column(title='Last activity on', | ||
785 | help_text='Starting date and time of the \ | ||
786 | last project build. If the project has no \ | ||
787 | builds, this shows the date the project was \ | ||
788 | created.', | ||
789 | hideable=True, | ||
790 | orderable=True, | ||
791 | static_data_name='updated', | ||
792 | static_data_template=last_activity_on_template) | ||
793 | |||
794 | self.add_column(title='Release', | ||
795 | help_text='The version of the build system used by \ | ||
796 | the project', | ||
797 | hideable=False, | ||
798 | orderable=True, | ||
799 | static_data_name='release', | ||
800 | static_data_template=release_template) | ||
801 | |||
802 | self.add_column(title='Machine', | ||
803 | help_text='The hardware currently selected for the \ | ||
804 | project', | ||
805 | hideable=False, | ||
806 | orderable=False, | ||
807 | static_data_name='machine', | ||
808 | static_data_template=machine_template) | ||
809 | |||
810 | self.add_column(title='Number of builds', | ||
811 | help_text='The number of builds which have been run \ | ||
812 | for the project', | ||
813 | hideable=True, | ||
814 | orderable=False, | ||
815 | static_data_name='number_of_builds', | ||
816 | static_data_template=number_of_builds_template) | ||
817 | |||
818 | self.add_column(title='Last build outcome', | ||
819 | help_text='Indicates whether the last project build \ | ||
820 | completed successfully or failed', | ||
821 | hideable=True, | ||
822 | orderable=False, | ||
823 | static_data_name='last_build_outcome', | ||
824 | static_data_template=last_build_outcome_template) | ||
825 | |||
826 | self.add_column(title='Recipe', | ||
827 | help_text='The last recipe which was built in this \ | ||
828 | project', | ||
829 | hideable=True, | ||
830 | orderable=False, | ||
831 | static_data_name='recipe_name', | ||
832 | static_data_template=recipe_template) | ||
833 | |||
834 | self.add_column(title='Errors', | ||
835 | help_text='The number of errors encountered during \ | ||
836 | the last project build (if any)', | ||
837 | hideable=True, | ||
838 | orderable=False, | ||
839 | static_data_name='errors', | ||
840 | static_data_template=errors_template) | ||
841 | |||
842 | self.add_column(title='Warnings', | ||
843 | help_text='The number of warnings encountered during \ | ||
844 | the last project build (if any)', | ||
845 | hideable=True, | ||
846 | orderable=False, | ||
847 | static_data_name='warnings', | ||
848 | static_data_template=warnings_template) | ||
849 | |||
850 | self.add_column(title='Image files', | ||
851 | help_text='', | ||
852 | hideable=True, | ||
853 | orderable=False, | ||
854 | static_data_name='image_files', | ||
855 | 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 @@ | |||
1 | {% extends 'base.html' %} | ||
2 | |||
3 | {% block title %} All projects - Toaster {% endblock %} | ||
4 | |||
5 | {% block pagecontent %} | ||
6 | |||
7 | <div class="page-header top-air"> | ||
8 | <h1 data-role="page-title"></h1> | ||
9 | </div> | ||
10 | |||
11 | {% url 'projects' as xhr_table_url %} | ||
12 | {% include 'toastertable.html' %} | ||
13 | |||
14 | <script> | ||
15 | $(document).ready(function () { | ||
16 | var tableElt = $("#{{table_name}}"); | ||
17 | var titleElt = $("[data-role='page-title']"); | ||
18 | |||
19 | tableElt.on("table-done", function (e, total, tableParams) { | ||
20 | var title = "All projects"; | ||
21 | |||
22 | if (tableParams.search || tableParams.filter) { | ||
23 | if (total === 0) { | ||
24 | title = "No projects found"; | ||
25 | } | ||
26 | else if (total > 0) { | ||
27 | title = total + " project" + (total > 1 ? 's' : '') + " found"; | ||
28 | } | ||
29 | } | ||
30 | |||
31 | titleElt.text(title); | ||
32 | }); | ||
33 | }); | ||
34 | </script> | ||
35 | |||
36 | {% 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', | |||
75 | url(r'^newproject/$', 'newproject', name='newproject'), | 75 | url(r'^newproject/$', 'newproject', name='newproject'), |
76 | 76 | ||
77 | 77 | ||
78 | # TODO remove when new toaster table is ready | ||
78 | url(r'^projects/$', 'projects', name='all-projects'), | 79 | url(r'^projects/$', 'projects', name='all-projects'), |
79 | 80 | ||
81 | # TODO move to /projects/ when new toaster table is ready | ||
82 | url(r'^projects-new/$', | ||
83 | tables.ProjectsTable.as_view(template_name="projects-toastertable.html"), | ||
84 | name='all-projects-new'), | ||
85 | |||
80 | url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), | 86 | url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), |
81 | url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), | 87 | url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), |
82 | url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'), | 88 | url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'), |