diff options
| author | David Reyna <David.Reyna@windriver.com> | 2015-02-26 21:42:00 +0000 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-02-27 07:36:08 +0000 |
| commit | 8c476c27bb532b33004cba363bdf5794bba3a6f7 (patch) | |
| tree | a95b3b6e89d70be7490d39aa9d15c20096463de0 | |
| parent | 6768a3069da45b3512601d8361bf64f06ee11e6f (diff) | |
| download | poky-8c476c27bb532b33004cba363bdf5794bba3a6f7.tar.gz | |
bitbake: toaster: all projects data and sorts
Implement the 'last build' data methods, enhance variable display,
add empty page and empty sort support.
[YOCTO #6682]
(Bitbake rev: cc6ca17e80844ecb4a777276d5f5177ebbcd93f9)
Signed-off-by: David Reyna <David.Reyna@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | bitbake/lib/toaster/bldcontrol/models.py | 2 | ||||
| -rw-r--r-- | bitbake/lib/toaster/orm/models.py | 63 | ||||
| -rw-r--r-- | bitbake/lib/toaster/toastergui/templates/managed_builds.html | 22 | ||||
| -rw-r--r-- | bitbake/lib/toaster/toastergui/templates/projects.html | 60 | ||||
| -rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 97 |
5 files changed, 190 insertions, 54 deletions
diff --git a/bitbake/lib/toaster/bldcontrol/models.py b/bitbake/lib/toaster/bldcontrol/models.py index 25d94cd3fe..02cfaf7086 100644 --- a/bitbake/lib/toaster/bldcontrol/models.py +++ b/bitbake/lib/toaster/bldcontrol/models.py | |||
| @@ -106,7 +106,7 @@ class BuildRequest(models.Model): | |||
| 106 | (REQ_ARCHIVE, "archive"), | 106 | (REQ_ARCHIVE, "archive"), |
| 107 | ) | 107 | ) |
| 108 | 108 | ||
| 109 | search_allowed_fields = ("brtarget__target",) | 109 | search_allowed_fields = ("brtarget__target", "build__project__name") |
| 110 | 110 | ||
| 111 | project = models.ForeignKey(Project) | 111 | project = models.ForeignKey(Project) |
| 112 | build = models.OneToOneField(Build, null = True) # TODO: toasterui should set this when Build is created | 112 | build = models.OneToOneField(Build, null = True) # TODO: toasterui should set this when Build is created |
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py index 4fa9f81e46..90e11d2383 100644 --- a/bitbake/lib/toaster/orm/models.py +++ b/bitbake/lib/toaster/orm/models.py | |||
| @@ -102,6 +102,69 @@ class Project(models.Model): | |||
| 102 | def __unicode__(self): | 102 | def __unicode__(self): |
| 103 | return "%s (%s, %s)" % (self.name, self.release, self.bitbake_version) | 103 | return "%s (%s, %s)" % (self.name, self.release, self.bitbake_version) |
| 104 | 104 | ||
| 105 | def get_current_machine_name(self): | ||
| 106 | try: | ||
| 107 | return self.projectvariable_set.get(name="MACHINE").value | ||
| 108 | except (ProjectVariable.DoesNotExist,IndexError): | ||
| 109 | return( "None" ); | ||
| 110 | |||
| 111 | def get_number_of_builds(self): | ||
| 112 | try: | ||
| 113 | return len(Build.objects.filter( project = self.id )) | ||
| 114 | except (Build.DoesNotExist,IndexError): | ||
| 115 | return( 0 ) | ||
| 116 | |||
| 117 | def get_last_build_id(self): | ||
| 118 | try: | ||
| 119 | return Build.objects.filter( project = self.id ).order_by('-completed_on')[0].id | ||
| 120 | except (Build.DoesNotExist,IndexError): | ||
| 121 | return( -1 ) | ||
| 122 | |||
| 123 | def get_last_outcome(self): | ||
| 124 | build_id = self.get_last_build_id | ||
| 125 | if (-1 == build_id): | ||
| 126 | return( "" ) | ||
| 127 | try: | ||
| 128 | return Build.objects.filter( id = self.get_last_build_id )[ 0 ].outcome | ||
| 129 | except (Build.DoesNotExist,IndexError): | ||
| 130 | return( "not_found" ) | ||
| 131 | |||
| 132 | def get_last_target(self): | ||
| 133 | build_id = self.get_last_build_id | ||
| 134 | if (-1 == build_id): | ||
| 135 | return( "" ) | ||
| 136 | try: | ||
| 137 | return Target.objects.filter(build = build_id)[0].target | ||
| 138 | except (Target.DoesNotExist,IndexError): | ||
| 139 | return( "not_found" ) | ||
| 140 | |||
| 141 | def get_last_errors(self): | ||
| 142 | build_id = self.get_last_build_id | ||
| 143 | if (-1 == build_id): | ||
| 144 | return( 0 ) | ||
| 145 | try: | ||
| 146 | return Build.objects.filter(id = build_id)[ 0 ].errors_no | ||
| 147 | except (Build.DoesNotExist,IndexError): | ||
| 148 | return( "not_found" ) | ||
| 149 | |||
| 150 | def get_last_warnings(self): | ||
| 151 | build_id = self.get_last_build_id | ||
| 152 | if (-1 == build_id): | ||
| 153 | return( 0 ) | ||
| 154 | try: | ||
| 155 | return Build.objects.filter(id = build_id)[ 0 ].warnings_no | ||
| 156 | except (Build.DoesNotExist,IndexError): | ||
| 157 | return( "not_found" ) | ||
| 158 | |||
| 159 | def get_last_imgfiles(self): | ||
| 160 | build_id = self.get_last_build_id | ||
| 161 | if (-1 == build_id): | ||
| 162 | return( "" ) | ||
| 163 | try: | ||
| 164 | return Variable.objects.filter(build = build_id, variable_name = "IMAGE_FSTYPES")[ 0 ].variable_value | ||
| 165 | except (Variable.DoesNotExist,IndexError): | ||
| 166 | return( "not_found" ) | ||
| 167 | |||
| 105 | # returns a queryset of compatible layers for a project | 168 | # returns a queryset of compatible layers for a project |
| 106 | def compatible_layerversions(self, release = None, layer_name = None): | 169 | def compatible_layerversions(self, release = None, layer_name = None): |
| 107 | if release == None: | 170 | if release == None: |
diff --git a/bitbake/lib/toaster/toastergui/templates/managed_builds.html b/bitbake/lib/toaster/toastergui/templates/managed_builds.html index a4db55b967..e23b832bae 100644 --- a/bitbake/lib/toaster/toastergui/templates/managed_builds.html +++ b/bitbake/lib/toaster/toastergui/templates/managed_builds.html | |||
| @@ -56,6 +56,13 @@ | |||
| 56 | </td> | 56 | </td> |
| 57 | <td class="target">{% for t in build.target_set.all %} <a href="{% url "builddashboard" build.id %}"> {{t.target}} </a> <br />{% endfor %}</td> | 57 | <td class="target">{% for t in build.target_set.all %} <a href="{% url "builddashboard" build.id %}"> {{t.target}} </a> <br />{% endfor %}</td> |
| 58 | <td class="machine"><a href="{% url "builddashboard" build.id %}">{{build.machine}}</a></td> | 58 | <td class="machine"><a href="{% url "builddashboard" build.id %}">{{build.machine}}</a></td> |
| 59 | {% if MANAGED %} | ||
| 60 | <td class="project"> | ||
| 61 | {% if build.project %} | ||
| 62 | <a href="{% url 'project' build.project.id %}">{{build.project.name}}</a> | ||
| 63 | {% endif %} | ||
| 64 | </td> | ||
| 65 | {% endif %} | ||
| 59 | <td class="started_on"><a href="{% url "builddashboard" build.id %}">{{build.started_on|date:"d/m/y H:i"}}</a></td> | 66 | <td class="started_on"><a href="{% url "builddashboard" build.id %}">{{build.started_on|date:"d/m/y H:i"}}</a></td> |
| 60 | <td class="completed_on"><a href="{% url "builddashboard" build.id %}">{{build.completed_on|date:"d/m/y H:i"}}</a></td> | 67 | <td class="completed_on"><a href="{% url "builddashboard" build.id %}">{{build.completed_on|date:"d/m/y H:i"}}</a></td> |
| 61 | <td class="failed_tasks error"> | 68 | <td class="failed_tasks error"> |
| @@ -91,13 +98,6 @@ | |||
| 91 | <a href="{%url "builddashboard" build.id%}#images">{{fstypes|get_dict_value:build.id}}</a> | 98 | <a href="{%url "builddashboard" build.id%}#images">{{fstypes|get_dict_value:build.id}}</a> |
| 92 | {% endif %} | 99 | {% endif %} |
| 93 | </td> | 100 | </td> |
| 94 | {% if MANAGED %} | ||
| 95 | <td class="project"> | ||
| 96 | {% if build.project %} | ||
| 97 | <a href="{% url 'project' build.project.id %}">{{build.project.name}}</a> | ||
| 98 | {% endif %} | ||
| 99 | </td> | ||
| 100 | {% endif %} | ||
| 101 | </tr> | 101 | </tr> |
| 102 | 102 | ||
| 103 | 103 | ||
| @@ -114,6 +114,11 @@ | |||
| 114 | <td class="machine"> | 114 | <td class="machine"> |
| 115 | <a href="{% url "buildrequestdetails" buildrequest.project.id buildrequest.id %}">{{buildrequest.machine}}</a> | 115 | <a href="{% url "buildrequestdetails" buildrequest.project.id buildrequest.id %}">{{buildrequest.machine}}</a> |
| 116 | </td> | 116 | </td> |
| 117 | {% if MANAGED %} | ||
| 118 | <td class="project"> | ||
| 119 | <a href="{% url 'project' buildrequest.project.id %}">{{buildrequest.project.name}}</a> | ||
| 120 | </td> | ||
| 121 | {% endif %} | ||
| 117 | <td class="started_on"> | 122 | <td class="started_on"> |
| 118 | <a href="{% url "buildrequestdetails" buildrequest.project.id buildrequest.id %}">{{buildrequest.created|date:"d/m/y H:i"}}</a> | 123 | <a href="{% url "buildrequestdetails" buildrequest.project.id buildrequest.id %}">{{buildrequest.created|date:"d/m/y H:i"}}</a> |
| 119 | </td> | 124 | </td> |
| @@ -132,9 +137,6 @@ | |||
| 132 | </td> | 137 | </td> |
| 133 | <td class="output"> {# we have no output here #} | 138 | <td class="output"> {# we have no output here #} |
| 134 | </td> | 139 | </td> |
| 135 | <td class="project"> | ||
| 136 | <a href="{% url 'project' buildrequest.project.id %}">{{buildrequest.project.name}}</a> | ||
| 137 | </td> | ||
| 138 | </tr> | 140 | </tr> |
| 139 | {%endif%} | 141 | {%endif%} |
| 140 | {% endfor %} | 142 | {% endfor %} |
diff --git a/bitbake/lib/toaster/toastergui/templates/projects.html b/bitbake/lib/toaster/toastergui/templates/projects.html index 0396e25a3a..88d5bd32df 100644 --- a/bitbake/lib/toaster/toastergui/templates/projects.html +++ b/bitbake/lib/toaster/toastergui/templates/projects.html | |||
| @@ -12,25 +12,61 @@ | |||
| 12 | 12 | ||
| 13 | <div class="page-header top-air"> | 13 | <div class="page-header top-air"> |
| 14 | <h1> | 14 | <h1> |
| 15 | All projects | 15 | {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %} |
| 16 | {{objects.paginator.count}} project{{objects.paginator.count|pluralize}} found | ||
| 17 | {%elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %} | ||
| 18 | No projects found | ||
| 19 | {%else%} | ||
| 20 | All projects | ||
| 21 | {%endif%} | ||
| 16 | </h1> | 22 | </h1> |
| 17 | </div> | 23 | </div> |
| 18 | 24 | ||
| 19 | {% include "basetable_top_projectbuilds.html" %} | 25 | {% if objects.paginator.count == 0 %} |
| 26 | <div class="row-fluid"> | ||
| 27 | <div class="alert"> | ||
| 28 | <form class="no-results input-append" id="searchform"> | ||
| 29 | <input id="search" name="search" class="input-xxlarge" type="text" value="{{request.GET.search}}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>{% endif %} | ||
| 30 | <button class="btn" type="submit" value="Search">Search</button> | ||
| 31 | <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all projects</button> | ||
| 32 | </form> | ||
| 33 | </div> | ||
| 34 | </div> | ||
| 35 | |||
| 36 | {% else %} {# We have builds to display #} | ||
| 37 | {% include "basetable_top_projectbuilds.html" %} | ||
| 20 | {% for o in objects %} | 38 | {% for o in objects %} |
| 21 | <tr class="data"> | 39 | <tr class="data"> |
| 22 | <td><a href="{% url 'project' o.id %}">{{o.name}}</a></td> | 40 | <td><a href="{% url 'project' o.id %}">{{o.name}}</a></td> |
| 23 | <td><a href="{% url 'project' o.id %}">{{o.release.name}}</a></td> | 41 | <td><a href="{% url 'project' o.id %}#project-details">{{o.release.name}}</a></td> |
| 24 | <td>{{o.get_current_machine_name}}</td> | 42 | <td><a href="{% url 'project' o.id %}#machine-distro">{{o.get_current_machine_name}}</a></td> |
| 25 | <td>{{o.get_number_of_builds}}</td> | 43 | {% if o.get_number_of_builds == 0 %} |
| 26 | <td class="loutcome">{{o.get_last_outcome}}</td> | 44 | <td class="muted">{{o.get_number_of_builds}}</td> |
| 27 | <td class="ltarget">{{o.get_last_target}}</td> | 45 | <td class="updated"></td> |
| 28 | <td class="lerrors">{{o.get_last_errors}}</td> | 46 | <td class="loutcome"></td> |
| 29 | <td class="lwarnings">{{o.get_last_warnings}}</td> | 47 | <td class="ltarget"></td> |
| 30 | <td class="limagefiles">{{o.get_last_imgfiles}}</td> | 48 | <td class="lerrors"></td> |
| 31 | <td class="updated">{{o.updated|date:"d/m/y H:i"}}</td> | 49 | <td class="lwarnings"></td> |
| 50 | <td class="limagefiles"></td> | ||
| 51 | {% else %} | ||
| 52 | <td><a href="{% url 'projectbuilds' o.id %}">{{o.get_number_of_builds}}</a></td> | ||
| 53 | <td class="updated"><a href="{% url "builddashboard" o.get_last_build_id %}">{{o.updated|date:"d/m/y H:i"}}</a></td> | ||
| 54 | <td class="loutcome"><a href="{% url "builddashboard" o.get_last_build_id %}">{%if o.get_last_outcome == build_SUCCEEDED%}<i class="icon-ok-sign success"></i>{%elif o.get_last_outcome == build_FAILED%}<i class="icon-minus-sign error"></i>{%else%}{%endif%}</a></td> | ||
| 55 | <td class="ltarget"><a href="{% url "builddashboard" o.get_last_build_id %}">{{o.get_last_target}} </a></td> | ||
| 56 | <td class="lerrors">{% if o.get_last_errors %}<a class="errors_no error" href="{% url "builddashboard" o.get_last_build_id %}#errors">{{o.get_last_errors}} error{{o.get_last_errors|pluralize}}</a>{%endif%}</td> | ||
| 57 | <td class="lwarnings">{% if o.get_last_warnings %}<a class="warnings_no warning" href="{% url "builddashboard" o.get_last_build_id %}#warnings">{{o.get_last_warnings}} warning{{o.get_last_warnings|pluralize}}</a>{%endif%}</td> | ||
| 58 | <td class="limagefiles"> | ||
| 59 | {% if o.get_last_outcome == build_SUCCEEDED %} | ||
| 60 | <a href="{%url "builddashboard" o.get_last_build_id %}#images">{{fstypes|get_dict_value:o.id}}</a> | ||
| 61 | {% endif %} | ||
| 62 | </td> | ||
| 63 | |||
| 64 | {% endif %} | ||
| 32 | </tr> | 65 | </tr> |
| 33 | {% endfor %} | 66 | {% endfor %} |
| 34 | {% include "basetable_bottom.html" %} | 67 | {% include "basetable_bottom.html" %} |
| 68 | {% endif %} {# empty #} | ||
| 35 | 69 | ||
| 36 | {% endblock %} | 70 | {% endblock %} |
| 71 | |||
| 72 | |||
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index a206f80b64..4f4ae67ca7 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
| @@ -1758,20 +1758,10 @@ if toastermain.settings.MANAGED: | |||
| 1758 | buildrequests = BuildRequest.objects.exclude(state__lte = BuildRequest.REQ_INPROGRESS).exclude(state=BuildRequest.REQ_DELETED) | 1758 | buildrequests = BuildRequest.objects.exclude(state__lte = BuildRequest.REQ_INPROGRESS).exclude(state=BuildRequest.REQ_DELETED) |
| 1759 | 1759 | ||
| 1760 | try: | 1760 | try: |
| 1761 | context, pagesize, orderby = _build_list_helper(request, buildrequests) | 1761 | context, pagesize, orderby = _build_list_helper(request, buildrequests, True) |
| 1762 | except InvalidRequestException as e: | 1762 | except InvalidRequestException as e: |
| 1763 | return _redirect_parameters( builds, request.GET, e.response) | 1763 | return _redirect_parameters( builds, request.GET, e.response) |
| 1764 | 1764 | ||
| 1765 | context['tablecols'].append( | ||
| 1766 | {'name': 'Project', 'clclass': 'projectx', | ||
| 1767 | 'filter': {'class': 'project', | ||
| 1768 | 'label': 'Project:', | ||
| 1769 | 'options': map(lambda x: (x.name,'project:%d' % x.id,x.build_set.filter(outcome__lt=BuildRequest.REQ_INPROGRESS).count()), Project.objects.all()), | ||
| 1770 | |||
| 1771 | } | ||
| 1772 | } | ||
| 1773 | ) | ||
| 1774 | |||
| 1775 | response = render(request, template, context) | 1765 | response = render(request, template, context) |
| 1776 | _save_parameters_cookies(response, pagesize, orderby, request) | 1766 | _save_parameters_cookies(response, pagesize, orderby, request) |
| 1777 | return response | 1767 | return response |
| @@ -1779,7 +1769,7 @@ if toastermain.settings.MANAGED: | |||
| 1779 | 1769 | ||
| 1780 | 1770 | ||
| 1781 | # helper function, to be used on "all builds" and "project builds" pages | 1771 | # helper function, to be used on "all builds" and "project builds" pages |
| 1782 | def _build_list_helper(request, buildrequests): | 1772 | def _build_list_helper(request, buildrequests, insert_projects): |
| 1783 | # ATTN: we use here the ordering parameters for interactive mode; the translation for BuildRequest fields will happen below | 1773 | # ATTN: we use here the ordering parameters for interactive mode; the translation for BuildRequest fields will happen below |
| 1784 | default_orderby = 'completed_on:-' | 1774 | default_orderby = 'completed_on:-' |
| 1785 | (pagesize, orderby) = _get_parameters_values(request, 10, default_orderby) | 1775 | (pagesize, orderby) = _get_parameters_values(request, 10, default_orderby) |
| @@ -1893,6 +1883,16 @@ if toastermain.settings.MANAGED: | |||
| 1893 | 'ordericon':_get_toggle_order_icon(request, "build__machine"), | 1883 | 'ordericon':_get_toggle_order_icon(request, "build__machine"), |
| 1894 | 'dclass': 'span3' | 1884 | 'dclass': 'span3' |
| 1895 | }, # a slightly wider column | 1885 | }, # a slightly wider column |
| 1886 | ] | ||
| 1887 | } | ||
| 1888 | |||
| 1889 | if (insert_projects): | ||
| 1890 | context['tablecols'].append( | ||
| 1891 | {'name': 'Project', 'clclass': 'project', | ||
| 1892 | } | ||
| 1893 | ) | ||
| 1894 | |||
| 1895 | context['tablecols'].append( | ||
| 1896 | {'name': 'Started on', 'clclass': 'started_on', 'hidden' : 1, # this is an unchecked box, which hides the column | 1896 | {'name': 'Started on', 'clclass': 'started_on', 'hidden' : 1, # this is an unchecked box, which hides the column |
| 1897 | 'qhelp': "The date and time you started the build", | 1897 | 'qhelp': "The date and time you started the build", |
| 1898 | 'orderfield': _get_toggle_order(request, "created", True), | 1898 | 'orderfield': _get_toggle_order(request, "created", True), |
| @@ -1905,7 +1905,9 @@ if toastermain.settings.MANAGED: | |||
| 1905 | ("This week's builds", 'created__gte:'+(timezone.now()-timedelta(days=7)).strftime("%Y-%m-%d"), queryset_all.filter(created__gte=(timezone.now()-timedelta(days=7))).count()), | 1905 | ("This week's builds", 'created__gte:'+(timezone.now()-timedelta(days=7)).strftime("%Y-%m-%d"), queryset_all.filter(created__gte=(timezone.now()-timedelta(days=7))).count()), |
| 1906 | ] | 1906 | ] |
| 1907 | } | 1907 | } |
| 1908 | }, | 1908 | } |
| 1909 | ) | ||
| 1910 | context['tablecols'].append( | ||
| 1909 | {'name': 'Completed on', | 1911 | {'name': 'Completed on', |
| 1910 | 'qhelp': "The date and time the build finished", | 1912 | 'qhelp': "The date and time the build finished", |
| 1911 | 'orderfield': _get_toggle_order(request, "updated", True), | 1913 | 'orderfield': _get_toggle_order(request, "updated", True), |
| @@ -1919,7 +1921,9 @@ if toastermain.settings.MANAGED: | |||
| 1919 | ("This week's builds", 'updated__gte:'+(timezone.now()-timedelta(days=7)).strftime("%Y-%m-%d"), queryset_all.filter(updated__gte=(timezone.now()-timedelta(days=7))).count()), | 1921 | ("This week's builds", 'updated__gte:'+(timezone.now()-timedelta(days=7)).strftime("%Y-%m-%d"), queryset_all.filter(updated__gte=(timezone.now()-timedelta(days=7))).count()), |
| 1920 | ] | 1922 | ] |
| 1921 | } | 1923 | } |
| 1922 | }, | 1924 | } |
| 1925 | ) | ||
| 1926 | context['tablecols'].append( | ||
| 1923 | {'name': 'Failed tasks', 'clclass': 'failed_tasks', # specifing a clclass will enable the checkbox | 1927 | {'name': 'Failed tasks', 'clclass': 'failed_tasks', # specifing a clclass will enable the checkbox |
| 1924 | 'qhelp': "How many tasks failed during the build", | 1928 | 'qhelp': "How many tasks failed during the build", |
| 1925 | 'filter' : {'class' : 'failed_tasks', | 1929 | 'filter' : {'class' : 'failed_tasks', |
| @@ -1931,7 +1935,9 @@ if toastermain.settings.MANAGED: | |||
| 1931 | queryset_all.filter(~Q(build__task_build__outcome=Task.OUTCOME_FAILED)).count()), | 1935 | queryset_all.filter(~Q(build__task_build__outcome=Task.OUTCOME_FAILED)).count()), |
| 1932 | ] | 1936 | ] |
| 1933 | } | 1937 | } |
| 1934 | }, | 1938 | } |
| 1939 | ) | ||
| 1940 | context['tablecols'].append( | ||
| 1935 | {'name': 'Errors', 'clclass': 'errors_no', | 1941 | {'name': 'Errors', 'clclass': 'errors_no', |
| 1936 | 'qhelp': "How many errors were encountered during the build (if any)", | 1942 | 'qhelp': "How many errors were encountered during the build (if any)", |
| 1937 | 'orderfield': _get_toggle_order(request, "build__errors_no", True), | 1943 | 'orderfield': _get_toggle_order(request, "build__errors_no", True), |
| @@ -1946,7 +1952,9 @@ if toastermain.settings.MANAGED: | |||
| 1946 | queryset_all.filter(build__errors_no=0).count()), | 1952 | queryset_all.filter(build__errors_no=0).count()), |
| 1947 | ] | 1953 | ] |
| 1948 | } | 1954 | } |
| 1949 | }, | 1955 | } |
| 1956 | ) | ||
| 1957 | context['tablecols'].append( | ||
| 1950 | {'name': 'Warnings', 'clclass': 'warnings_no', | 1958 | {'name': 'Warnings', 'clclass': 'warnings_no', |
| 1951 | 'qhelp': "How many warnings were encountered during the build (if any)", | 1959 | 'qhelp': "How many warnings were encountered during the build (if any)", |
| 1952 | 'orderfield': _get_toggle_order(request, "build__warnings_no", True), | 1960 | 'orderfield': _get_toggle_order(request, "build__warnings_no", True), |
| @@ -1959,19 +1967,23 @@ if toastermain.settings.MANAGED: | |||
| 1959 | ('Builds without warnings','build__warnings_no:0', queryset_all.filter(build__warnings_no=0).count()), | 1967 | ('Builds without warnings','build__warnings_no:0', queryset_all.filter(build__warnings_no=0).count()), |
| 1960 | ] | 1968 | ] |
| 1961 | } | 1969 | } |
| 1962 | }, | 1970 | } |
| 1971 | ) | ||
| 1972 | context['tablecols'].append( | ||
| 1963 | {'name': 'Time', 'clclass': 'time', 'hidden' : 1, | 1973 | {'name': 'Time', 'clclass': 'time', 'hidden' : 1, |
| 1964 | 'qhelp': "How long it took the build to finish", | 1974 | 'qhelp': "How long it took the build to finish", |
| 1965 | # 'orderfield': _get_toggle_order(request, "timespent", True), | 1975 | # 'orderfield': _get_toggle_order(request, "timespent", True), |
| 1966 | # 'ordericon':_get_toggle_order_icon(request, "timespent"), | 1976 | # 'ordericon':_get_toggle_order_icon(request, "timespent"), |
| 1967 | 'orderkey' : 'timespent', | 1977 | 'orderkey' : 'timespent', |
| 1968 | }, | 1978 | } |
| 1979 | ) | ||
| 1980 | context['tablecols'].append( | ||
| 1969 | {'name': 'Image files', 'clclass': 'output', | 1981 | {'name': 'Image files', 'clclass': 'output', |
| 1970 | 'qhelp': "The root file system types produced by the build. You can find them in your <code>/build/tmp/deploy/images/</code> directory", | 1982 | 'qhelp': "The root file system types produced by the build. You can find them in your <code>/build/tmp/deploy/images/</code> directory", |
| 1971 | # TODO: compute image fstypes from Target_Image_File | 1983 | # TODO: compute image fstypes from Target_Image_File |
| 1972 | }, | 1984 | } |
| 1973 | ] | 1985 | ) |
| 1974 | } | 1986 | |
| 1975 | return context, pagesize, orderby | 1987 | return context, pagesize, orderby |
| 1976 | 1988 | ||
| 1977 | # new project | 1989 | # new project |
| @@ -2898,7 +2910,7 @@ if toastermain.settings.MANAGED: | |||
| 2898 | buildrequests = BuildRequest.objects.filter(project_id = pid).exclude(state__lte = BuildRequest.REQ_INPROGRESS).exclude(state=BuildRequest.REQ_DELETED) | 2910 | buildrequests = BuildRequest.objects.filter(project_id = pid).exclude(state__lte = BuildRequest.REQ_INPROGRESS).exclude(state=BuildRequest.REQ_DELETED) |
| 2899 | 2911 | ||
| 2900 | try: | 2912 | try: |
| 2901 | context, pagesize, orderby = _build_list_helper(request, buildrequests) | 2913 | context, pagesize, orderby = _build_list_helper(request, buildrequests, False) |
| 2902 | except InvalidRequestException as e: | 2914 | except InvalidRequestException as e: |
| 2903 | return _redirect_parameters(projectbuilds, request.GET, e.response, pid = pid) | 2915 | return _redirect_parameters(projectbuilds, request.GET, e.response, pid = pid) |
| 2904 | 2916 | ||
| @@ -3019,7 +3031,7 @@ if toastermain.settings.MANAGED: | |||
| 3019 | def projects(request): | 3031 | def projects(request): |
| 3020 | template="projects.html" | 3032 | template="projects.html" |
| 3021 | 3033 | ||
| 3022 | (pagesize, orderby) = _get_parameters_values(request, 10, 'updated:+') | 3034 | (pagesize, orderby) = _get_parameters_values(request, 10, 'updated:-') |
| 3023 | mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby } | 3035 | mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby } |
| 3024 | retval = _verify_parameters( request.GET, mandatory_parameters ) | 3036 | retval = _verify_parameters( request.GET, mandatory_parameters ) |
| 3025 | if retval: | 3037 | if retval: |
| @@ -3039,7 +3051,27 @@ if toastermain.settings.MANAGED: | |||
| 3039 | # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds) | 3051 | # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds) |
| 3040 | build_mru = Build.objects.order_by("-started_on")[:3] | 3052 | build_mru = Build.objects.order_by("-started_on")[:3] |
| 3041 | 3053 | ||
| 3042 | 3054 | # translate the project's build target strings | |
| 3055 | fstypes_map = {}; | ||
| 3056 | for project in project_info: | ||
| 3057 | try: | ||
| 3058 | targets = Target.objects.filter( build_id = project.get_last_build_id() ) | ||
| 3059 | comma = ""; | ||
| 3060 | extensions = ""; | ||
| 3061 | for t in targets: | ||
| 3062 | if ( not t.is_image ): | ||
| 3063 | continue | ||
| 3064 | tif = Target_Image_File.objects.filter( target_id = t.id ) | ||
| 3065 | for i in tif: | ||
| 3066 | s=re.sub('.*tar.bz2', 'tar.bz2', i.file_name) | ||
| 3067 | if s == i.file_name: | ||
| 3068 | s=re.sub('.*\.', '', i.file_name) | ||
| 3069 | if None == re.search(s,extensions): | ||
| 3070 | extensions += comma + s | ||
| 3071 | comma = ", " | ||
| 3072 | fstypes_map[project.id]=extensions | ||
| 3073 | except (Target.DoesNotExist,IndexError): | ||
| 3074 | fstypes_map[project.id]=project.get_last_imgfiles | ||
| 3043 | 3075 | ||
| 3044 | context = { | 3076 | context = { |
| 3045 | 'mru' : build_mru, | 3077 | 'mru' : build_mru, |
| @@ -3049,6 +3081,9 @@ if toastermain.settings.MANAGED: | |||
| 3049 | 'default_orderby' : 'id:-', | 3081 | 'default_orderby' : 'id:-', |
| 3050 | 'search_term' : search_term, | 3082 | 'search_term' : search_term, |
| 3051 | 'total_count' : queryset_with_search.count(), | 3083 | 'total_count' : queryset_with_search.count(), |
| 3084 | 'fstypes' : fstypes_map, | ||
| 3085 | 'build_FAILED' : Build.FAILED, | ||
| 3086 | 'build_SUCCEEDED' : Build.SUCCEEDED, | ||
| 3052 | 'tablecols': [ | 3087 | 'tablecols': [ |
| 3053 | {'name': 'Project', | 3088 | {'name': 'Project', |
| 3054 | 'orderfield': _get_toggle_order(request, "name"), | 3089 | 'orderfield': _get_toggle_order(request, "name"), |
| @@ -3067,6 +3102,11 @@ if toastermain.settings.MANAGED: | |||
| 3067 | {'name': 'Number of builds', | 3102 | {'name': 'Number of builds', |
| 3068 | 'qhelp': "How many builds have been run for the project", | 3103 | 'qhelp': "How many builds have been run for the project", |
| 3069 | }, | 3104 | }, |
| 3105 | {'name': 'Last build', 'clclass': 'updated', | ||
| 3106 | 'orderfield': _get_toggle_order(request, "updated", True), | ||
| 3107 | 'ordericon':_get_toggle_order_icon(request, "updated"), | ||
| 3108 | 'orderkey' : 'updated', | ||
| 3109 | }, | ||
| 3070 | {'name': 'Last outcome', 'clclass': 'loutcome', | 3110 | {'name': 'Last outcome', 'clclass': 'loutcome', |
| 3071 | 'qhelp': "Tells you if the last project build completed successfully or failed", | 3111 | 'qhelp': "Tells you if the last project build completed successfully or failed", |
| 3072 | }, | 3112 | }, |
| @@ -3082,11 +3122,6 @@ if toastermain.settings.MANAGED: | |||
| 3082 | {'name': 'Last image files', 'clclass': 'limagefiles', 'hidden': 1, | 3122 | {'name': 'Last image files', 'clclass': 'limagefiles', 'hidden': 1, |
| 3083 | 'qhelp': "The root file system types produced by the last project build", | 3123 | 'qhelp': "The root file system types produced by the last project build", |
| 3084 | }, | 3124 | }, |
| 3085 | {'name': 'Last updated', 'clclass': 'updated', | ||
| 3086 | 'orderfield': _get_toggle_order(request, "updated"), | ||
| 3087 | 'ordericon':_get_toggle_order_icon(request, "updated"), | ||
| 3088 | 'orderkey' : 'updated', | ||
| 3089 | } | ||
| 3090 | ] | 3125 | ] |
| 3091 | } | 3126 | } |
| 3092 | return render(request, template, context) | 3127 | return render(request, template, context) |
