diff options
9 files changed, 239 insertions, 49 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js b/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js index b6ad380c19..58a32a056e 100644 --- a/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js +++ b/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js | |||
| @@ -7,7 +7,10 @@ function projectTopBarInit(ctx) { | |||
| 7 | var projectName = $("#project-name"); | 7 | var projectName = $("#project-name"); |
| 8 | var projectNameFormToggle = $("#project-change-form-toggle"); | 8 | var projectNameFormToggle = $("#project-change-form-toggle"); |
| 9 | var projectNameChangeCancel = $("#project-name-change-cancel"); | 9 | var projectNameChangeCancel = $("#project-name-change-cancel"); |
| 10 | |||
| 11 | // this doesn't exist for command-line builds | ||
| 10 | var newBuildTargetInput = $("#build-input"); | 12 | var newBuildTargetInput = $("#build-input"); |
| 13 | |||
| 11 | var newBuildTargetBuildBtn = $("#build-button"); | 14 | var newBuildTargetBuildBtn = $("#build-button"); |
| 12 | var selectedTarget; | 15 | var selectedTarget; |
| 13 | 16 | ||
| @@ -42,6 +45,12 @@ function projectTopBarInit(ctx) { | |||
| 42 | $(this).parent().removeClass('active'); | 45 | $(this).parent().removeClass('active'); |
| 43 | }); | 46 | }); |
| 44 | 47 | ||
| 48 | if (!newBuildTargetInput.length) { | ||
| 49 | return; | ||
| 50 | } | ||
| 51 | |||
| 52 | /* the following only applies for non-command-line projects */ | ||
| 53 | |||
| 45 | /* Recipe build input functionality */ | 54 | /* Recipe build input functionality */ |
| 46 | if (ctx.numProjectLayers > 0 && ctx.machine){ | 55 | if (ctx.numProjectLayers > 0 && ctx.machine){ |
| 47 | newBuildTargetInput.removeAttr("disabled"); | 56 | newBuildTargetInput.removeAttr("disabled"); |
diff --git a/bitbake/lib/toaster/toastergui/static/js/table.js b/bitbake/lib/toaster/toastergui/static/js/table.js index afe16b5e1b..7ac4ed5859 100644 --- a/bitbake/lib/toaster/toastergui/static/js/table.js +++ b/bitbake/lib/toaster/toastergui/static/js/table.js | |||
| @@ -33,6 +33,10 @@ function tableInit(ctx){ | |||
| 33 | 33 | ||
| 34 | loadData(tableParams); | 34 | loadData(tableParams); |
| 35 | 35 | ||
| 36 | // clicking on this set of elements removes the search | ||
| 37 | var clearSearchElements = $('.remove-search-btn-'+ctx.tableName + | ||
| 38 | ', .show-all-'+ctx.tableName); | ||
| 39 | |||
| 36 | function loadData(tableParams){ | 40 | function loadData(tableParams){ |
| 37 | $.ajax({ | 41 | $.ajax({ |
| 38 | type: "GET", | 42 | type: "GET", |
| @@ -62,9 +66,9 @@ function tableInit(ctx){ | |||
| 62 | paginationBtns.html(""); | 66 | paginationBtns.html(""); |
| 63 | 67 | ||
| 64 | if (tableParams.search) | 68 | if (tableParams.search) |
| 65 | $('.remove-search-btn-'+ctx.tableName).show(); | 69 | clearSearchElements.show(); |
| 66 | else | 70 | else |
| 67 | $('.remove-search-btn-'+ctx.tableName).hide(); | 71 | clearSearchElements.hide(); |
| 68 | 72 | ||
| 69 | $('.table-count-' + ctx.tableName).text(tableData.total); | 73 | $('.table-count-' + ctx.tableName).text(tableData.total); |
| 70 | tableTotal = tableData.total; | 74 | tableTotal = tableData.total; |
| @@ -230,9 +234,8 @@ function tableInit(ctx){ | |||
| 230 | 234 | ||
| 231 | } else { | 235 | } else { |
| 232 | /* Not orderable */ | 236 | /* Not orderable */ |
| 233 | header.addClass("muted"); | ||
| 234 | header.css("font-weight", "normal"); | 237 | header.css("font-weight", "normal"); |
| 235 | header.append(col.title+' '); | 238 | header.append('<span class="muted">' + col.title + '</span> '); |
| 236 | } | 239 | } |
| 237 | 240 | ||
| 238 | /* Setup the filter button */ | 241 | /* Setup the filter button */ |
| @@ -665,7 +668,7 @@ function tableInit(ctx){ | |||
| 665 | loadData(tableParams); | 668 | loadData(tableParams); |
| 666 | }); | 669 | }); |
| 667 | 670 | ||
| 668 | $('.remove-search-btn-'+ctx.tableName).click(function(e){ | 671 | clearSearchElements.click(function(e){ |
| 669 | e.preventDefault(); | 672 | e.preventDefault(); |
| 670 | 673 | ||
| 671 | tableParams.page = 1; | 674 | tableParams.page = 1; |
diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py index 58abe36b05..d0ed49625d 100644 --- a/bitbake/lib/toaster/toastergui/tables.py +++ b/bitbake/lib/toaster/toastergui/tables.py | |||
| @@ -23,9 +23,11 @@ from toastergui.widgets import ToasterTable | |||
| 23 | from toastergui.querysetfilter import QuerysetFilter | 23 | from toastergui.querysetfilter import QuerysetFilter |
| 24 | from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project | 24 | from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project |
| 25 | from orm.models import CustomImageRecipe, Package, Build, LogMessage, Task | 25 | from orm.models import CustomImageRecipe, Package, Build, LogMessage, Task |
| 26 | from orm.models import ProjectTarget | ||
| 26 | from django.db.models import Q, Max, Count | 27 | from django.db.models import Q, Max, Count |
| 27 | from django.conf.urls import url | 28 | from django.conf.urls import url |
| 28 | from django.core.urlresolvers import reverse | 29 | from django.core.urlresolvers import reverse, resolve |
| 30 | from django.http import HttpResponse | ||
| 29 | from django.views.generic import TemplateView | 31 | from django.views.generic import TemplateView |
| 30 | import itertools | 32 | import itertools |
| 31 | 33 | ||
| @@ -775,7 +777,7 @@ class ProjectsTable(ToasterTable): | |||
| 775 | ''' | 777 | ''' |
| 776 | 778 | ||
| 777 | errors_template = ''' | 779 | errors_template = ''' |
| 778 | {% if data.get_number_of_builds > 0 %} | 780 | {% if data.get_number_of_builds > 0 and data.get_last_errors > 0 %} |
| 779 | <a class="errors.count error" | 781 | <a class="errors.count error" |
| 780 | href="{% url "builddashboard" data.get_last_build_id %}#errors"> | 782 | href="{% url "builddashboard" data.get_last_build_id %}#errors"> |
| 781 | {{data.get_last_errors}} error{{data.get_last_errors | pluralize}} | 783 | {{data.get_last_errors}} error{{data.get_last_errors | pluralize}} |
| @@ -784,7 +786,7 @@ class ProjectsTable(ToasterTable): | |||
| 784 | ''' | 786 | ''' |
| 785 | 787 | ||
| 786 | warnings_template = ''' | 788 | warnings_template = ''' |
| 787 | {% if data.get_number_of_builds > 0 %} | 789 | {% if data.get_number_of_builds > 0 and data.get_last_warnings > 0 %} |
| 788 | <a class="warnings.count warning" | 790 | <a class="warnings.count warning" |
| 789 | href="{% url "builddashboard" data.get_last_build_id %}#warnings"> | 791 | href="{% url "builddashboard" data.get_last_build_id %}#warnings"> |
| 790 | {{data.get_last_warnings}} warning{{data.get_last_warnings | pluralize}} | 792 | {{data.get_last_warnings}} warning{{data.get_last_warnings | pluralize}} |
| @@ -886,30 +888,45 @@ class BuildsTable(ToasterTable): | |||
| 886 | def __init__(self, *args, **kwargs): | 888 | def __init__(self, *args, **kwargs): |
| 887 | super(BuildsTable, self).__init__(*args, **kwargs) | 889 | super(BuildsTable, self).__init__(*args, **kwargs) |
| 888 | self.default_orderby = '-completed_on' | 890 | self.default_orderby = '-completed_on' |
| 889 | self.title = 'All builds' | ||
| 890 | self.static_context_extra['Build'] = Build | 891 | self.static_context_extra['Build'] = Build |
| 891 | self.static_context_extra['Task'] = Task | 892 | self.static_context_extra['Task'] = Task |
| 892 | 893 | ||
| 894 | # attributes that are overridden in subclasses | ||
| 895 | |||
| 896 | # title for the page | ||
| 897 | self.title = '' | ||
| 898 | |||
| 899 | # 'project' or 'all'; determines how the mrb (most recent builds) | ||
| 900 | # section is displayed | ||
| 901 | self.mrb_type = '' | ||
| 902 | |||
| 903 | def get_builds(self): | ||
| 904 | """ | ||
| 905 | overridden in ProjectBuildsTable to return builds for a | ||
| 906 | single project | ||
| 907 | """ | ||
| 908 | return Build.objects.all() | ||
| 909 | |||
| 893 | def get_context_data(self, **kwargs): | 910 | def get_context_data(self, **kwargs): |
| 894 | context = super(BuildsTable, self).get_context_data(**kwargs) | 911 | context = super(BuildsTable, self).get_context_data(**kwargs) |
| 895 | 912 | ||
| 896 | # for the latest builds section | 913 | # for the latest builds section |
| 897 | queryset = Build.objects.all() | 914 | builds = self.get_builds() |
| 898 | 915 | ||
| 899 | finished_criteria = Q(outcome=Build.SUCCEEDED) | Q(outcome=Build.FAILED) | 916 | finished_criteria = Q(outcome=Build.SUCCEEDED) | Q(outcome=Build.FAILED) |
| 900 | 917 | ||
| 901 | latest_builds = itertools.chain( | 918 | latest_builds = itertools.chain( |
| 902 | queryset.filter(outcome=Build.IN_PROGRESS).order_by("-started_on"), | 919 | builds.filter(outcome=Build.IN_PROGRESS).order_by("-started_on"), |
| 903 | queryset.filter(finished_criteria).order_by("-completed_on")[:3] | 920 | builds.filter(finished_criteria).order_by("-completed_on")[:3] |
| 904 | ) | 921 | ) |
| 905 | 922 | ||
| 906 | context['mru'] = list(latest_builds) | 923 | context['mru'] = list(latest_builds) |
| 907 | context['mrb_type'] = 'all' | 924 | context['mrb_type'] = self.mrb_type |
| 908 | 925 | ||
| 909 | return context | 926 | return context |
| 910 | 927 | ||
| 911 | def setup_queryset(self, *args, **kwargs): | 928 | def setup_queryset(self, *args, **kwargs): |
| 912 | queryset = Build.objects.all() | 929 | queryset = self.get_builds() |
| 913 | 930 | ||
| 914 | # don't include in progress builds | 931 | # don't include in progress builds |
| 915 | queryset = queryset.exclude(outcome=Build.IN_PROGRESS) | 932 | queryset = queryset.exclude(outcome=Build.IN_PROGRESS) |
| @@ -949,7 +966,8 @@ class BuildsTable(ToasterTable): | |||
| 949 | {% if data.cooker_log_path %} | 966 | {% if data.cooker_log_path %} |
| 950 | | 967 | |
| 951 | <a href="{% url "build_artifact" data.id "cookerlog" data.id %}"> | 968 | <a href="{% url "build_artifact" data.id "cookerlog" data.id %}"> |
| 952 | <i class="icon-download-alt" title="Download build log"></i> | 969 | <i class="icon-download-alt get-help" |
| 970 | data-original-title="Download build log"></i> | ||
| 953 | </a> | 971 | </a> |
| 954 | {% endif %} | 972 | {% endif %} |
| 955 | ''' | 973 | ''' |
| @@ -1031,19 +1049,6 @@ class BuildsTable(ToasterTable): | |||
| 1031 | {% endif %} | 1049 | {% endif %} |
| 1032 | ''' | 1050 | ''' |
| 1033 | 1051 | ||
| 1034 | project_template = ''' | ||
| 1035 | {% load project_url_tag %} | ||
| 1036 | <a href="{% project_url data.project %}"> | ||
| 1037 | {{data.project.name}} | ||
| 1038 | </a> | ||
| 1039 | {% if data.project.is_default %} | ||
| 1040 | <i class="icon-question-sign get-help hover-help" title="" | ||
| 1041 | data-original-title="This project shows information about | ||
| 1042 | the builds you start from the command line while Toaster is | ||
| 1043 | running" style="visibility: hidden;"></i> | ||
| 1044 | {% endif %} | ||
| 1045 | ''' | ||
| 1046 | |||
| 1047 | self.add_column(title='Outcome', | 1052 | self.add_column(title='Outcome', |
| 1048 | help_text='Final state of the build (successful \ | 1053 | help_text='Final state of the build (successful \ |
| 1049 | or failed)', | 1054 | or failed)', |
| @@ -1098,16 +1103,16 @@ class BuildsTable(ToasterTable): | |||
| 1098 | help_text='The number of errors encountered during \ | 1103 | help_text='The number of errors encountered during \ |
| 1099 | the build (if any)', | 1104 | the build (if any)', |
| 1100 | hideable=True, | 1105 | hideable=True, |
| 1101 | orderable=False, | 1106 | orderable=True, |
| 1102 | static_data_name='errors', | 1107 | static_data_name='errors_no', |
| 1103 | static_data_template=errors_template) | 1108 | static_data_template=errors_template) |
| 1104 | 1109 | ||
| 1105 | self.add_column(title='Warnings', | 1110 | self.add_column(title='Warnings', |
| 1106 | help_text='The number of warnings encountered during \ | 1111 | help_text='The number of warnings encountered during \ |
| 1107 | the build (if any)', | 1112 | the build (if any)', |
| 1108 | hideable=True, | 1113 | hideable=True, |
| 1109 | orderable=False, | 1114 | orderable=True, |
| 1110 | static_data_name='warnings', | 1115 | static_data_name='warnings_no', |
| 1111 | static_data_template=warnings_template) | 1116 | static_data_template=warnings_template) |
| 1112 | 1117 | ||
| 1113 | self.add_column(title='Time', | 1118 | self.add_column(title='Time', |
| @@ -1125,12 +1130,6 @@ class BuildsTable(ToasterTable): | |||
| 1125 | static_data_name='image_files', | 1130 | static_data_name='image_files', |
| 1126 | static_data_template=image_files_template) | 1131 | static_data_template=image_files_template) |
| 1127 | 1132 | ||
| 1128 | self.add_column(title='Project', | ||
| 1129 | hideable=True, | ||
| 1130 | orderable=False, | ||
| 1131 | static_data_name='project-name', | ||
| 1132 | static_data_template=project_template) | ||
| 1133 | |||
| 1134 | def setup_filters(self, *args, **kwargs): | 1133 | def setup_filters(self, *args, **kwargs): |
| 1135 | # outcomes | 1134 | # outcomes |
| 1136 | outcome_filter = TableFilter( | 1135 | outcome_filter = TableFilter( |
| @@ -1239,3 +1238,122 @@ class BuildsTable(ToasterTable): | |||
| 1239 | failed_tasks_filter.add_action(with_failed_tasks_action) | 1238 | failed_tasks_filter.add_action(with_failed_tasks_action) |
| 1240 | failed_tasks_filter.add_action(without_failed_tasks_action) | 1239 | failed_tasks_filter.add_action(without_failed_tasks_action) |
| 1241 | self.add_filter(failed_tasks_filter) | 1240 | self.add_filter(failed_tasks_filter) |
| 1241 | |||
| 1242 | def post(self, request, *args, **kwargs): | ||
| 1243 | """ Process HTTP POSTs which make build requests """ | ||
| 1244 | |||
| 1245 | project = Project.objects.get(pk=kwargs['pid']) | ||
| 1246 | |||
| 1247 | if 'buildCancel' in request.POST: | ||
| 1248 | for i in request.POST['buildCancel'].strip().split(" "): | ||
| 1249 | try: | ||
| 1250 | br = BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_QUEUED) | ||
| 1251 | br.state = BuildRequest.REQ_DELETED | ||
| 1252 | br.save() | ||
| 1253 | except BuildRequest.DoesNotExist: | ||
| 1254 | pass | ||
| 1255 | |||
| 1256 | if 'buildDelete' in request.POST: | ||
| 1257 | for i in request.POST['buildDelete'].strip().split(" "): | ||
| 1258 | try: | ||
| 1259 | BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_DELETED).delete() | ||
| 1260 | except BuildRequest.DoesNotExist: | ||
| 1261 | pass | ||
| 1262 | |||
| 1263 | if 'targets' in request.POST: | ||
| 1264 | ProjectTarget.objects.filter(project = project).delete() | ||
| 1265 | s = str(request.POST['targets']) | ||
| 1266 | for t in s.translate(None, ";%|\"").split(" "): | ||
| 1267 | if ":" in t: | ||
| 1268 | target, task = t.split(":") | ||
| 1269 | else: | ||
| 1270 | target = t | ||
| 1271 | task = "" | ||
| 1272 | ProjectTarget.objects.create(project = project, | ||
| 1273 | target = target, | ||
| 1274 | task = task) | ||
| 1275 | project.schedule_build() | ||
| 1276 | |||
| 1277 | # redirect back to builds page so any new builds in progress etc. | ||
| 1278 | # are visible | ||
| 1279 | response = HttpResponse() | ||
| 1280 | response.status_code = 302 | ||
| 1281 | response['Location'] = request.build_absolute_uri() | ||
| 1282 | return response | ||
| 1283 | |||
| 1284 | class AllBuildsTable(BuildsTable): | ||
| 1285 | """ Builds page for all builds """ | ||
| 1286 | |||
| 1287 | def __init__(self, *args, **kwargs): | ||
| 1288 | super(AllBuildsTable, self).__init__(*args, **kwargs) | ||
| 1289 | self.title = 'All builds' | ||
| 1290 | self.mrb_type = 'all' | ||
| 1291 | |||
| 1292 | def setup_columns(self, *args, **kwargs): | ||
| 1293 | """ | ||
| 1294 | All builds page shows a column for the project | ||
| 1295 | """ | ||
| 1296 | |||
| 1297 | super(AllBuildsTable, self).setup_columns(*args, **kwargs) | ||
| 1298 | |||
| 1299 | project_template = ''' | ||
| 1300 | {% load project_url_tag %} | ||
| 1301 | <a href="{% project_url data.project %}"> | ||
| 1302 | {{data.project.name}} | ||
| 1303 | </a> | ||
| 1304 | {% if data.project.is_default %} | ||
| 1305 | <i class="icon-question-sign get-help hover-help" title="" | ||
| 1306 | data-original-title="This project shows information about | ||
| 1307 | the builds you start from the command line while Toaster is | ||
| 1308 | running" style="visibility: hidden;"></i> | ||
| 1309 | {% endif %} | ||
| 1310 | ''' | ||
| 1311 | |||
| 1312 | self.add_column(title='Project', | ||
| 1313 | hideable=True, | ||
| 1314 | orderable=True, | ||
| 1315 | static_data_name='project', | ||
| 1316 | static_data_template=project_template) | ||
| 1317 | |||
| 1318 | class ProjectBuildsTable(BuildsTable): | ||
| 1319 | """ | ||
| 1320 | Builds page for a single project; a BuildsTable, with the queryset | ||
| 1321 | filtered by project | ||
| 1322 | """ | ||
| 1323 | |||
| 1324 | def __init__(self, *args, **kwargs): | ||
| 1325 | super(ProjectBuildsTable, self).__init__(*args, **kwargs) | ||
| 1326 | self.title = 'All project builds' | ||
| 1327 | self.mrb_type = 'project' | ||
| 1328 | |||
| 1329 | # set from the querystring | ||
| 1330 | self.project_id = None | ||
| 1331 | |||
| 1332 | def setup_queryset(self, *args, **kwargs): | ||
| 1333 | """ | ||
| 1334 | NOTE: self.project_id must be set before calling super(), | ||
| 1335 | as it's used in setup_queryset() | ||
| 1336 | """ | ||
| 1337 | self.project_id = kwargs['pid'] | ||
| 1338 | super(ProjectBuildsTable, self).setup_queryset(*args, **kwargs) | ||
| 1339 | |||
| 1340 | project = Project.objects.get(pk=self.project_id) | ||
| 1341 | self.queryset = self.queryset.filter(project=project) | ||
| 1342 | |||
| 1343 | def get_context_data(self, **kwargs): | ||
| 1344 | """ | ||
| 1345 | NOTE: self.project_id must be set before calling super(), | ||
| 1346 | as it's used in get_context_data() | ||
| 1347 | """ | ||
| 1348 | self.project_id = kwargs['pid'] | ||
| 1349 | |||
| 1350 | context = super(ProjectBuildsTable, self).get_context_data(**kwargs) | ||
| 1351 | context['project'] = Project.objects.get(pk=self.project_id) | ||
| 1352 | |||
| 1353 | return context | ||
| 1354 | |||
| 1355 | def get_builds(self): | ||
| 1356 | """ override: only return builds for the relevant project """ | ||
| 1357 | |||
| 1358 | project = Project.objects.get(pk=self.project_id) | ||
| 1359 | return Build.objects.filter(project=project) | ||
diff --git a/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html b/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html index 1f45be462d..b143b78833 100644 --- a/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html +++ b/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | {% extends "base.html" %} | 1 | {% extends "base.html" %} |
| 2 | |||
| 2 | {% load projecttags %} | 3 | {% load projecttags %} |
| 3 | {% load humanize %} | 4 | {% load humanize %} |
| 4 | 5 | ||
diff --git a/bitbake/lib/toaster/toastergui/templates/mrb_section.html b/bitbake/lib/toaster/toastergui/templates/mrb_section.html index 52b3f1a7d3..2f4820c3e7 100644 --- a/bitbake/lib/toaster/toastergui/templates/mrb_section.html +++ b/bitbake/lib/toaster/toastergui/templates/mrb_section.html | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | {%if mru and mru.count > 0%} | 6 | {%if mru and mru.count > 0%} |
| 7 | 7 | ||
| 8 | {%if mrb_type == 'project' %} | 8 | {%if mrb_type == 'project' %} |
| 9 | <h2> | 9 | <h2 class="page-header"> |
| 10 | Latest project builds | 10 | Latest project builds |
| 11 | 11 | ||
| 12 | {% if project.is_default %} | 12 | {% if project.is_default %} |
diff --git a/bitbake/lib/toaster/toastergui/templates/projectbuilds-toastertable.html b/bitbake/lib/toaster/toastergui/templates/projectbuilds-toastertable.html new file mode 100644 index 0000000000..6d7e10bac5 --- /dev/null +++ b/bitbake/lib/toaster/toastergui/templates/projectbuilds-toastertable.html | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | {% extends 'base.html' %} | ||
| 2 | |||
| 3 | {% load static %} | ||
| 4 | |||
| 5 | {% block extraheadcontent %} | ||
| 6 | <link rel="stylesheet" href="{% static 'css/jquery-ui.min.css' %}" type='text/css'> | ||
| 7 | <link rel="stylesheet" href="{% static 'css/jquery-ui.structure.min.css' %}" type='text/css'> | ||
| 8 | <link rel="stylesheet" href="{% static 'css/jquery-ui.theme.min.css' %}" type='text/css'> | ||
| 9 | <script src="{% static 'js/jquery-ui.min.js' %}"> | ||
| 10 | </script> | ||
| 11 | {% endblock %} | ||
| 12 | |||
| 13 | {% block title %} {{title}} - {{project.name}} - Toaster {% endblock %} | ||
| 14 | |||
| 15 | {% block pagecontent %} | ||
| 16 | |||
| 17 | {% include "projecttopbar.html" %} | ||
| 18 | |||
| 19 | <div class="row-fluid"> | ||
| 20 | {% with mru=mru mrb_type=mrb_type %} | ||
| 21 | {% include 'mrb_section.html' %} | ||
| 22 | {% endwith %} | ||
| 23 | |||
| 24 | <h2 class="page-header top-air" data-role="page-title"></h2> | ||
| 25 | |||
| 26 | {% url 'projectbuilds' project.id as xhr_table_url %} | ||
| 27 | {% include 'toastertable.html' %} | ||
| 28 | </div> | ||
| 29 | |||
| 30 | <script> | ||
| 31 | $(document).ready(function () { | ||
| 32 | // title | ||
| 33 | var tableElt = $("#{{table_name}}"); | ||
| 34 | var titleElt = $("[data-role='page-title']"); | ||
| 35 | |||
| 36 | tableElt.on("table-done", function (e, total, tableParams) { | ||
| 37 | var title = "All project builds"; | ||
| 38 | |||
| 39 | if (tableParams.search || tableParams.filter) { | ||
| 40 | if (total === 0) { | ||
| 41 | title = "No project builds found"; | ||
| 42 | } | ||
| 43 | else if (total > 0) { | ||
| 44 | title = total + " project build" + (total > 1 ? 's' : '') + " found"; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | titleElt.text(title); | ||
| 49 | }); | ||
| 50 | |||
| 51 | // highlight builds tab | ||
| 52 | $("#topbar-builds-tab").addClass("active") | ||
| 53 | }); | ||
| 54 | </script> | ||
| 55 | |||
| 56 | {% endblock %} | ||
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 707b7d5f20..c8c1c6a1fe 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py | |||
| @@ -28,7 +28,7 @@ urlpatterns = patterns('toastergui.views', | |||
| 28 | url(r'^landing/$', 'landing', name='landing'), | 28 | url(r'^landing/$', 'landing', name='landing'), |
| 29 | 29 | ||
| 30 | url(r'^builds/$', | 30 | url(r'^builds/$', |
| 31 | tables.BuildsTable.as_view(template_name="builds-toastertable.html"), | 31 | tables.AllBuildsTable.as_view(template_name="builds-toastertable.html"), |
| 32 | name='all-builds'), | 32 | name='all-builds'), |
| 33 | 33 | ||
| 34 | # build info navigation | 34 | # build info navigation |
| @@ -83,7 +83,9 @@ urlpatterns = patterns('toastergui.views', | |||
| 83 | 83 | ||
| 84 | url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), | 84 | url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), |
| 85 | url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), | 85 | url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), |
| 86 | url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'), | 86 | url(r'^project/(?P<pid>\d+)/builds/$', |
| 87 | tables.ProjectBuildsTable.as_view(template_name="projectbuilds-toastertable.html"), | ||
| 88 | name='projectbuilds'), | ||
| 87 | 89 | ||
| 88 | # the import layer is a project-specific functionality; | 90 | # the import layer is a project-specific functionality; |
| 89 | url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'), | 91 | url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'), |
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 295773fc66..fbae36c69c 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
| @@ -91,6 +91,7 @@ def landing(request): | |||
| 91 | 91 | ||
| 92 | return render(request, 'landing.html', context) | 92 | return render(request, 'landing.html', context) |
| 93 | 93 | ||
| 94 | """ | ||
| 94 | # returns a list for most recent builds; | 95 | # returns a list for most recent builds; |
| 95 | def _get_latest_builds(prj=None): | 96 | def _get_latest_builds(prj=None): |
| 96 | queryset = Build.objects.all() | 97 | queryset = Build.objects.all() |
| @@ -101,8 +102,9 @@ def _get_latest_builds(prj=None): | |||
| 101 | return list(itertools.chain( | 102 | return list(itertools.chain( |
| 102 | queryset.filter(outcome=Build.IN_PROGRESS).order_by("-started_on"), | 103 | queryset.filter(outcome=Build.IN_PROGRESS).order_by("-started_on"), |
| 103 | queryset.filter(outcome__lt=Build.IN_PROGRESS).order_by("-started_on")[:3] )) | 104 | queryset.filter(outcome__lt=Build.IN_PROGRESS).order_by("-started_on")[:3] )) |
| 105 | """ | ||
| 104 | 106 | ||
| 105 | 107 | """ | |
| 106 | # a JSON-able dict of recent builds; for use in the Project page, xhr_ updates, and other places, as needed | 108 | # a JSON-able dict of recent builds; for use in the Project page, xhr_ updates, and other places, as needed |
| 107 | def _project_recent_build_list(prj): | 109 | def _project_recent_build_list(prj): |
| 108 | data = [] | 110 | data = [] |
| @@ -131,8 +133,7 @@ def _project_recent_build_list(prj): | |||
| 131 | data.append(d) | 133 | data.append(d) |
| 132 | 134 | ||
| 133 | return data | 135 | return data |
| 134 | 136 | """ | |
| 135 | |||
| 136 | 137 | ||
| 137 | def objtojson(obj): | 138 | def objtojson(obj): |
| 138 | from django.db.models.query import QuerySet | 139 | from django.db.models.query import QuerySet |
| @@ -1915,6 +1916,7 @@ if True: | |||
| 1915 | ''' The exception raised on invalid POST requests ''' | 1916 | ''' The exception raised on invalid POST requests ''' |
| 1916 | pass | 1917 | pass |
| 1917 | 1918 | ||
| 1919 | """ | ||
| 1918 | # helper function, to be used on "all builds" and "project builds" pages | 1920 | # helper function, to be used on "all builds" and "project builds" pages |
| 1919 | def _build_list_helper(request, queryset_all, redirect_page, pid=None): | 1921 | def _build_list_helper(request, queryset_all, redirect_page, pid=None): |
| 1920 | default_orderby = 'completed_on:-' | 1922 | default_orderby = 'completed_on:-' |
| @@ -2119,6 +2121,7 @@ if True: | |||
| 2119 | # merge daterange values | 2121 | # merge daterange values |
| 2120 | context.update(context_date) | 2122 | context.update(context_date) |
| 2121 | return context, pagesize, orderby | 2123 | return context, pagesize, orderby |
| 2124 | """ | ||
| 2122 | 2125 | ||
| 2123 | 2126 | ||
| 2124 | 2127 | ||
| @@ -2256,7 +2259,7 @@ if True: | |||
| 2256 | "completedbuilds": Build.objects.exclude(outcome = Build.IN_PROGRESS).filter(project_id = pid), | 2259 | "completedbuilds": Build.objects.exclude(outcome = Build.IN_PROGRESS).filter(project_id = pid), |
| 2257 | "prj" : {"name": prj.name, }, | 2260 | "prj" : {"name": prj.name, }, |
| 2258 | "buildrequests" : prj.build_set.filter(outcome=Build.IN_PROGRESS), | 2261 | "buildrequests" : prj.build_set.filter(outcome=Build.IN_PROGRESS), |
| 2259 | "builds" : _project_recent_build_list(prj), | 2262 | #"builds" : _project_recent_build_list(prj), |
| 2260 | "layers" : map(lambda x: { | 2263 | "layers" : map(lambda x: { |
| 2261 | "id": x.layercommit.pk, | 2264 | "id": x.layercommit.pk, |
| 2262 | "orderid": x.pk, | 2265 | "orderid": x.pk, |
| @@ -2827,10 +2830,8 @@ if True: | |||
| 2827 | # will set the GET parameters and redirect back to the | 2830 | # will set the GET parameters and redirect back to the |
| 2828 | # all-builds or projectbuilds page as appropriate; | 2831 | # all-builds or projectbuilds page as appropriate; |
| 2829 | # TODO don't use exceptions to control program flow | 2832 | # TODO don't use exceptions to control program flow |
| 2830 | @_template_renderer('projectbuilds.html') | 2833 | """ |
| 2831 | def projectbuilds(request, pid): | 2834 | def projectbuilds(request, pid): |
| 2832 | prj = Project.objects.get(id = pid) | ||
| 2833 | |||
| 2834 | if request.method == "POST": | 2835 | if request.method == "POST": |
| 2835 | # process any build request | 2836 | # process any build request |
| 2836 | 2837 | ||
| @@ -2880,6 +2881,7 @@ if True: | |||
| 2880 | context['mru'] = _get_latest_builds(prj) | 2881 | context['mru'] = _get_latest_builds(prj) |
| 2881 | 2882 | ||
| 2882 | return context | 2883 | return context |
| 2884 | """ | ||
| 2883 | 2885 | ||
| 2884 | 2886 | ||
| 2885 | def _file_name_for_artifact(b, artifact_type, artifact_id): | 2887 | def _file_name_for_artifact(b, artifact_type, artifact_id): |
diff --git a/bitbake/lib/toaster/toastergui/widgets.py b/bitbake/lib/toaster/toastergui/widgets.py index 47de30d631..bc081b818b 100644 --- a/bitbake/lib/toaster/toastergui/widgets.py +++ b/bitbake/lib/toaster/toastergui/widgets.py | |||
| @@ -61,7 +61,6 @@ class ToasterTable(TemplateView): | |||
| 61 | 61 | ||
| 62 | self.total_count = 0 | 62 | self.total_count = 0 |
| 63 | self.static_context_extra = {} | 63 | self.static_context_extra = {} |
| 64 | self.filter_actions = {} | ||
| 65 | self.empty_state = "Sorry - no data found" | 64 | self.empty_state = "Sorry - no data found" |
| 66 | self.default_orderby = "" | 65 | self.default_orderby = "" |
| 67 | 66 | ||
