diff options
Diffstat (limited to 'bitbake/lib/toaster')
-rw-r--r-- | bitbake/lib/toaster/toastergui/api.py | 161 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/libtoaster.js | 3 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/projectpage.js | 147 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/tests/test.js | 7 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/base.html | 1 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/urls.py | 4 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 131 |
7 files changed, 179 insertions, 275 deletions
diff --git a/bitbake/lib/toaster/toastergui/api.py b/bitbake/lib/toaster/toastergui/api.py index be18090daf..8876409964 100644 --- a/bitbake/lib/toaster/toastergui/api.py +++ b/bitbake/lib/toaster/toastergui/api.py | |||
@@ -20,11 +20,13 @@ | |||
20 | 20 | ||
21 | import re | 21 | import re |
22 | import logging | 22 | import logging |
23 | from collections import Counter | ||
23 | 24 | ||
24 | from orm.models import Project, ProjectTarget, Build, Layer_Version | 25 | from orm.models import Project, ProjectTarget, Build, Layer_Version |
25 | from orm.models import LayerVersionDependency, LayerSource, ProjectLayer | 26 | from orm.models import LayerVersionDependency, LayerSource, ProjectLayer |
26 | from orm.models import Recipe, CustomImageRecipe, CustomImagePackage | 27 | from orm.models import Recipe, CustomImageRecipe, CustomImagePackage |
27 | from orm.models import Layer, Target, Package, Package_Dependency | 28 | from orm.models import Layer, Target, Package, Package_Dependency |
29 | from orm.models import ProjectVariable | ||
28 | from bldcontrol.models import BuildRequest | 30 | from bldcontrol.models import BuildRequest |
29 | from bldcontrol import bbcontroller | 31 | from bldcontrol import bbcontroller |
30 | 32 | ||
@@ -772,3 +774,162 @@ class XhrCustomRecipePackages(View): | |||
772 | except CustomImageRecipe.DoesNotExist: | 774 | except CustomImageRecipe.DoesNotExist: |
773 | return error_response("Tried to remove package that wasn't" | 775 | return error_response("Tried to remove package that wasn't" |
774 | " present") | 776 | " present") |
777 | |||
778 | |||
779 | class XhrProject(View): | ||
780 | """ Create, delete or edit a project | ||
781 | |||
782 | Entry point: /xhr_project/<project_id> | ||
783 | """ | ||
784 | def post(self, request, *args, **kwargs): | ||
785 | """ | ||
786 | Edit project control | ||
787 | |||
788 | Args: | ||
789 | layerAdd = layer_version_id layer_version_id ... | ||
790 | layerDel = layer_version_id layer_version_id ... | ||
791 | projectName = new_project_name | ||
792 | machineName = new_machine_name | ||
793 | |||
794 | Returns: | ||
795 | {"error": "ok"} | ||
796 | or | ||
797 | {"error": <error message>} | ||
798 | """ | ||
799 | try: | ||
800 | prj = Project.objects.get(pk=kwargs['project_id']) | ||
801 | except Project.DoesNotExist: | ||
802 | return error_response("No such project") | ||
803 | |||
804 | # Add layers | ||
805 | if 'layerAdd' in request.POST and len(request.POST['layerAdd']) > 0: | ||
806 | for layer_version_id in request.POST['layerAdd'].split(','): | ||
807 | try: | ||
808 | lv = Layer_Version.objects.get(pk=int(layer_version_id)) | ||
809 | ProjectLayer.objects.get_or_create(project=prj, | ||
810 | layercommit=lv) | ||
811 | except Layer_Version.DoesNotExist: | ||
812 | return error_response("Layer version %s asked to add " | ||
813 | "doesn't exist" % layer_version_id) | ||
814 | |||
815 | # Remove layers | ||
816 | if 'layerDel' in request.POST and len(request.POST['layerDel']) > 0: | ||
817 | layer_version_ids = request.POST['layerDel'].split(',') | ||
818 | ProjectLayer.objects.filter( | ||
819 | project=prj, | ||
820 | layercommit_id__in=layer_version_ids).delete() | ||
821 | |||
822 | # Project name change | ||
823 | if 'projectName' in request.POST: | ||
824 | prj.name = request.POST['projectName'] | ||
825 | prj.save() | ||
826 | |||
827 | # Machine name change | ||
828 | if 'machineName' in request.POST: | ||
829 | machinevar = prj.projectvariable_set.get(name="MACHINE") | ||
830 | machinevar.value = request.POST['machineName'] | ||
831 | machinevar.save() | ||
832 | |||
833 | return JsonResponse({"error": "ok"}) | ||
834 | |||
835 | def get(self, request, *args, **kwargs): | ||
836 | """ | ||
837 | Returns: | ||
838 | json object representing the current project | ||
839 | or: | ||
840 | {"error": <error message>} | ||
841 | """ | ||
842 | |||
843 | try: | ||
844 | project = Project.objects.get(pk=kwargs['project_id']) | ||
845 | except Project.DoesNotExist: | ||
846 | return error_response("Project %s does not exist" % | ||
847 | kwargs['project_id']) | ||
848 | |||
849 | # Create the frequently built targets list | ||
850 | |||
851 | freqtargets = Counter(Target.objects.filter( | ||
852 | Q(build__project=project), | ||
853 | ~Q(build__outcome=Build.IN_PROGRESS) | ||
854 | ).order_by("target").values_list("target", flat=True)) | ||
855 | |||
856 | freqtargets = freqtargets.most_common(5) | ||
857 | |||
858 | # We now have the targets in order of frequency but if there are two | ||
859 | # with the same frequency then we need to make sure those are in | ||
860 | # alphabetical order without losing the frequency ordering | ||
861 | |||
862 | tmp = [] | ||
863 | switch = None | ||
864 | for i, freqtartget in enumerate(freqtargets): | ||
865 | target, count = freqtartget | ||
866 | try: | ||
867 | target_next, count_next = freqtargets[i+1] | ||
868 | if count == count_next and target > target_next: | ||
869 | switch = target | ||
870 | continue | ||
871 | except IndexError: | ||
872 | pass | ||
873 | |||
874 | tmp.append(target) | ||
875 | |||
876 | if switch: | ||
877 | tmp.append(switch) | ||
878 | switch = None | ||
879 | |||
880 | freqtargets = tmp | ||
881 | |||
882 | layers = [] | ||
883 | for layer in project.projectlayer_set.all(): | ||
884 | layers.append({ | ||
885 | "id": layer.layercommit.pk, | ||
886 | "name": layer.layercommit.layer.name, | ||
887 | "vcs_url": layer.layercommit.layer.vcs_url, | ||
888 | "local_source_dir": layer.layercommit.layer.local_source_dir, | ||
889 | "vcs_reference": layer.layercommit.get_vcs_reference(), | ||
890 | "url": layer.layercommit.layer.layer_index_url, | ||
891 | "layerdetailurl": layer.layercommit.get_detailspage_url( | ||
892 | project.pk), | ||
893 | "layersource": layer.layercommit.layer_source | ||
894 | }) | ||
895 | |||
896 | data = { | ||
897 | "name": project.name, | ||
898 | "layers": layers, | ||
899 | "freqtargets": freqtargets, | ||
900 | } | ||
901 | |||
902 | if project.release is not None: | ||
903 | data['release'] = { | ||
904 | "id": project.release.pk, | ||
905 | "name": project.release.name, | ||
906 | "description": project.release.description | ||
907 | } | ||
908 | |||
909 | try: | ||
910 | data["machine"] = {"name": | ||
911 | project.projectvariable_set.get( | ||
912 | name="MACHINE").value} | ||
913 | except ProjectVariable.DoesNotExist: | ||
914 | data["machine"] = None | ||
915 | try: | ||
916 | data["distro"] = project.projectvariable_set.get( | ||
917 | name="DISTRO").value | ||
918 | except ProjectVariable.DoesNotExist: | ||
919 | data["distro"] = "-- not set yet" | ||
920 | |||
921 | data['error'] = "ok" | ||
922 | |||
923 | return JsonResponse(data) | ||
924 | |||
925 | def put(self, request, *args, **kwargs): | ||
926 | # TODO create new project api | ||
927 | return HttpResponse() | ||
928 | |||
929 | def delete(self, request, *args, **kwargs): | ||
930 | try: | ||
931 | Project.objects.get(kwargs['project_id']).delete() | ||
932 | except Project.DoesNotExist: | ||
933 | return error_response("Project %s does not exist" % | ||
934 | kwargs['project_id']) | ||
935 | return JsonResponse({"error": "ok"}) | ||
diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js index f56affd8ea..b2099a6048 100644 --- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js +++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js | |||
@@ -167,7 +167,6 @@ var libtoaster = (function () { | |||
167 | function _getProjectInfo(url, onsuccess, onfail){ | 167 | function _getProjectInfo(url, onsuccess, onfail){ |
168 | $.ajax({ | 168 | $.ajax({ |
169 | type: "GET", | 169 | type: "GET", |
170 | data : { format: "json" }, | ||
171 | url: url, | 170 | url: url, |
172 | headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, | 171 | headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, |
173 | success: function (_data) { | 172 | success: function (_data) { |
@@ -194,7 +193,7 @@ var libtoaster = (function () { | |||
194 | function _editCurrentProject(data, onSuccess, onFail){ | 193 | function _editCurrentProject(data, onSuccess, onFail){ |
195 | $.ajax({ | 194 | $.ajax({ |
196 | type: "POST", | 195 | type: "POST", |
197 | url: libtoaster.ctx.projectPageUrl + "?format=json", | 196 | url: libtoaster.ctx.xhrProjectUrl, |
198 | data: data, | 197 | data: data, |
199 | headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, | 198 | headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, |
200 | success: function (data) { | 199 | success: function (data) { |
diff --git a/bitbake/lib/toaster/toastergui/static/js/projectpage.js b/bitbake/lib/toaster/toastergui/static/js/projectpage.js index b75b3e1869..3bf3cbaf2b 100644 --- a/bitbake/lib/toaster/toastergui/static/js/projectpage.js +++ b/bitbake/lib/toaster/toastergui/static/js/projectpage.js | |||
@@ -27,11 +27,10 @@ function projectPageInit(ctx) { | |||
27 | 27 | ||
28 | var urlParams = libtoaster.parseUrlParams(); | 28 | var urlParams = libtoaster.parseUrlParams(); |
29 | 29 | ||
30 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){ | 30 | libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){ |
31 | updateProjectLayers(prjInfo.layers); | 31 | updateProjectLayers(prjInfo.layers); |
32 | updateFreqBuildRecipes(prjInfo.freqtargets); | 32 | updateFreqBuildRecipes(prjInfo.freqtargets); |
33 | updateProjectRelease(prjInfo.release); | 33 | updateProjectRelease(prjInfo.release); |
34 | updateProjectReleases(prjInfo.releases, prjInfo.release); | ||
35 | 34 | ||
36 | /* If we're receiving a machine set from the url and it's different from | 35 | /* If we're receiving a machine set from the url and it's different from |
37 | * our current machine then activate set machine sequence. | 36 | * our current machine then activate set machine sequence. |
@@ -287,7 +286,9 @@ function projectPageInit(ctx) { | |||
287 | machineNameTitle.text(machineName); | 286 | machineNameTitle.text(machineName); |
288 | } | 287 | } |
289 | 288 | ||
290 | libtoaster.makeTypeahead(machineChangeInput, libtoaster.ctx.machinesTypeAheadUrl, { }, function(item){ | 289 | libtoaster.makeTypeahead(machineChangeInput, |
290 | libtoaster.ctx.machinesTypeAheadUrl, | ||
291 | { }, function(item){ | ||
291 | currentMachineAddSelection = item.name; | 292 | currentMachineAddSelection = item.name; |
292 | machineChangeBtn.removeAttr("disabled"); | 293 | machineChangeBtn.removeAttr("disabled"); |
293 | }); | 294 | }); |
@@ -324,146 +325,10 @@ function projectPageInit(ctx) { | |||
324 | releaseTitle.text(release.description); | 325 | releaseTitle.text(release.description); |
325 | } | 326 | } |
326 | 327 | ||
327 | function updateProjectReleases(releases, current){ | ||
328 | for (var i in releases){ | ||
329 | var releaseOption = $("<option></option>"); | ||
330 | 328 | ||
331 | releaseOption.val(releases[i].id); | 329 | $("#delete-project-confirmed").click(function(e){ |
332 | releaseOption.text(releases[i].description); | ||
333 | releaseOption.data('release', releases[i]); | ||
334 | |||
335 | if (releases[i].id == current.id) | ||
336 | releaseOption.attr("selected", "selected"); | ||
337 | |||
338 | releaseForm.children("select").append(releaseOption); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | releaseChangeFormToggle.click(function(){ | ||
343 | releaseForm.slideDown(); | ||
344 | releaseTitle.hide(); | ||
345 | $(this).hide(); | ||
346 | }); | ||
347 | |||
348 | cancelReleaseChange.click(function(e){ | ||
349 | e.preventDefault(); | 330 | e.preventDefault(); |
350 | releaseForm.slideUp(function(){ | 331 | |
351 | releaseTitle.show(); | ||
352 | releaseChangeFormToggle.show(); | ||
353 | }); | ||
354 | }); | ||
355 | |||
356 | function changeProjectRelease(release, layersToRm){ | ||
357 | libtoaster.editCurrentProject({ projectVersion : release.id }, | ||
358 | function(){ | ||
359 | /* Success */ | ||
360 | /* Update layers list with new layers */ | ||
361 | layersInPrjList.addClass('muted'); | ||
362 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, | ||
363 | function(prjInfo){ | ||
364 | layersInPrjList.children().remove(); | ||
365 | updateProjectLayers(prjInfo.layers); | ||
366 | layersInPrjList.removeClass('muted'); | ||
367 | releaseChangedNotification(release, prjInfo.layers, layersToRm); | ||
368 | }); | ||
369 | updateProjectRelease(release); | ||
370 | cancelReleaseChange.click(); | ||
371 | }); | ||
372 | } | ||
373 | |||
374 | /* Create a notification to show the changes to the layer configuration | ||
375 | * caused by changing a release. | ||
376 | */ | ||
377 | |||
378 | function releaseChangedNotification(release, layers, layersToRm){ | ||
379 | |||
380 | var message; | ||
381 | |||
382 | if (layers.length === 0 && layersToRm.length === 0){ | ||
383 | message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>.'); | ||
384 | message.find("#notify-release-name").text(release.description); | ||
385 | libtoaster.showChangeNotification(message); | ||
386 | return; | ||
387 | } | ||
388 | |||
389 | /* Create the whitespace separated list of layers removed */ | ||
390 | var layersDelList = ""; | ||
391 | |||
392 | layersToRm.map(function(layer, i){ | ||
393 | layersDelList += layer.name; | ||
394 | if (layersToRm[i+1] !== undefined) | ||
395 | layersDelList += ', '; | ||
396 | }); | ||
397 | |||
398 | message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>. This has caused the following changes in your project layers:</span><ul id="notify-layers-changed-list"></ul></span>'); | ||
399 | |||
400 | var changedList = message.find("#notify-layers-changed-list"); | ||
401 | |||
402 | message.find("#notify-release-name").text(release.description); | ||
403 | |||
404 | /* Manually construct the list item for changed layers */ | ||
405 | var li = '<li><strong>'+layers.length+'</strong> layers changed to the <strong>'+release.name+'</strong> release: '; | ||
406 | for (var i in layers){ | ||
407 | li += '<a href='+layers[i].layerdetailurl+'>'+layers[i].name+'</a>'; | ||
408 | if (i !== 0) | ||
409 | li += ', '; | ||
410 | } | ||
411 | |||
412 | changedList.append($(li)); | ||
413 | |||
414 | /* Layers removed */ | ||
415 | if (layersToRm && layersToRm.length > 0){ | ||
416 | if (layersToRm.length == 1) | ||
417 | li = '<li><strong>1</strong> layer removed: '+layersToRm[0].name+'</li>'; | ||
418 | else | ||
419 | li = '<li><strong>'+layersToRm.length+'</strong> layers deleted: '+layersDelList+'</li>'; | ||
420 | |||
421 | changedList.append($(li)); | ||
422 | } | ||
423 | |||
424 | libtoaster.showChangeNotification(message); | ||
425 | } | ||
426 | |||
427 | /* Show the modal dialog which gives the option to remove layers which | ||
428 | * aren't compatible with the proposed release | ||
429 | */ | ||
430 | function showReleaseLayerChangeModal(release, layers){ | ||
431 | var layersToRmList = releaseModal.find("#layers-to-remove-list"); | ||
432 | layersToRmList.text(""); | ||
433 | |||
434 | releaseModal.find(".proposed-release-change-name").text(release.description); | ||
435 | releaseModal.data("layers", layers); | ||
436 | releaseModal.data("release", release); | ||
437 | |||
438 | for (var i in layers){ | ||
439 | layersToRmList.append($("<li></li>").text(layers[i].name)); | ||
440 | } | ||
441 | releaseModal.modal('show'); | ||
442 | } | ||
443 | |||
444 | $("#change-release-btn").click(function(e){ | ||
445 | e.preventDefault(); | ||
446 | |||
447 | var newRelease = releaseForm.find("option:selected").data('release'); | ||
448 | |||
449 | $.getJSON(ctx.testReleaseChangeUrl, | ||
450 | { new_release_id: newRelease.id }, | ||
451 | function(layers) { | ||
452 | if (layers.rows.length === 0){ | ||
453 | /* No layers to change for this release */ | ||
454 | changeProjectRelease(newRelease, []); | ||
455 | } else { | ||
456 | showReleaseLayerChangeModal(newRelease, layers.rows); | ||
457 | } | ||
458 | }); | ||
459 | }); | ||
460 | |||
461 | /* Release change modal accept */ | ||
462 | $("#change-release-and-rm-layers").click(function(){ | ||
463 | var layers = releaseModal.data("layers"); | ||
464 | var release = releaseModal.data("release"); | ||
465 | |||
466 | changeProjectRelease(release, layers); | ||
467 | }); | 332 | }); |
468 | 333 | ||
469 | } | 334 | } |
diff --git a/bitbake/lib/toaster/toastergui/static/js/tests/test.js b/bitbake/lib/toaster/toastergui/static/js/tests/test.js index f8d566b3e3..d7953de447 100644 --- a/bitbake/lib/toaster/toastergui/static/js/tests/test.js +++ b/bitbake/lib/toaster/toastergui/static/js/tests/test.js | |||
@@ -42,9 +42,8 @@ QUnit.test("Layer alert notification", function(assert) { | |||
42 | 42 | ||
43 | QUnit.test("Project info", function(assert){ | 43 | QUnit.test("Project info", function(assert){ |
44 | var done = assert.async(); | 44 | var done = assert.async(); |
45 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){ | 45 | libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){ |
46 | assert.ok(prjInfo.machine.name); | 46 | assert.ok(prjInfo.machine.name); |
47 | assert.ok(prjInfo.releases.length > 0); | ||
48 | assert.ok(prjInfo.layers.length > 0); | 47 | assert.ok(prjInfo.layers.length > 0); |
49 | assert.ok(prjInfo.freqtargets); | 48 | assert.ok(prjInfo.freqtargets); |
50 | assert.ok(prjInfo.release); | 49 | assert.ok(prjInfo.release); |
@@ -82,11 +81,11 @@ QUnit.test("Add layer", function(assert){ | |||
82 | }, 200); | 81 | }, 200); |
83 | 82 | ||
84 | /* Compare the number of layers before and after the add in the project */ | 83 | /* Compare the number of layers before and after the add in the project */ |
85 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){ | 84 | libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){ |
86 | var origNumLayers = prjInfo.layers.length; | 85 | var origNumLayers = prjInfo.layers.length; |
87 | 86 | ||
88 | libtoaster.addRmLayer(layer, true, function(deps){ | 87 | libtoaster.addRmLayer(layer, true, function(deps){ |
89 | libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, | 88 | libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, |
90 | function(prjInfo){ | 89 | function(prjInfo){ |
91 | assert.ok(prjInfo.layers.length > origNumLayers, | 90 | assert.ok(prjInfo.layers.length > origNumLayers, |
92 | "Layer not added to project"); | 91 | "Layer not added to project"); |
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html index 58491eba81..c1b1417a76 100644 --- a/bitbake/lib/toaster/toastergui/templates/base.html +++ b/bitbake/lib/toaster/toastergui/templates/base.html | |||
@@ -44,6 +44,7 @@ | |||
44 | {% if project.id %} | 44 | {% if project.id %} |
45 | projectId : {{project.id}}, | 45 | projectId : {{project.id}}, |
46 | projectPageUrl : {% url 'project' project.id as purl %}{{purl|json}}, | 46 | projectPageUrl : {% url 'project' project.id as purl %}{{purl|json}}, |
47 | xhrProjectUrl : {% url 'xhr_project' project.id as pxurl %}{{pxurl|json}}, | ||
47 | projectName : {{project.name|json}}, | 48 | projectName : {{project.name|json}}, |
48 | recipesTypeAheadUrl: {% url 'xhr_recipestypeahead' project.id as paturl%}{{paturl|json}}, | 49 | recipesTypeAheadUrl: {% url 'xhr_recipestypeahead' project.id as paturl%}{{paturl|json}}, |
49 | layersTypeAheadUrl: {% url 'xhr_layerstypeahead' project.id as paturl%}{{paturl|json}}, | 50 | layersTypeAheadUrl: {% url 'xhr_layerstypeahead' project.id as paturl%}{{paturl|json}}, |
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 9509cd5928..1232611e2e 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py | |||
@@ -220,6 +220,10 @@ urlpatterns = patterns('toastergui.views', | |||
220 | api.XhrBuildRequest.as_view(), | 220 | api.XhrBuildRequest.as_view(), |
221 | name='xhr_buildrequest'), | 221 | name='xhr_buildrequest'), |
222 | 222 | ||
223 | url(r'xhr_project/(?P<project_id>\d+)$', | ||
224 | api.XhrProject.as_view(), | ||
225 | name='xhr_project'), | ||
226 | |||
223 | url(r'^mostrecentbuilds$', api.MostRecentBuildsView.as_view(), | 227 | url(r'^mostrecentbuilds$', api.MostRecentBuildsView.as_view(), |
224 | name='most_recent_builds'), | 228 | name='most_recent_builds'), |
225 | 229 | ||
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 365a1e88ff..2efb0fd56c 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
@@ -1361,136 +1361,11 @@ if True: | |||
1361 | 1361 | ||
1362 | raise Exception("Invalid HTTP method for this page") | 1362 | raise Exception("Invalid HTTP method for this page") |
1363 | 1363 | ||
1364 | |||
1365 | |||
1366 | # Shows the edit project page | 1364 | # Shows the edit project page |
1367 | @_template_renderer('project.html') | ||
1368 | def project(request, pid): | 1365 | def project(request, pid): |
1369 | prj = Project.objects.get(id = pid) | 1366 | project = Project.objects.get(pk=pid) |
1370 | 1367 | context = {"project": project} | |
1371 | try: | 1368 | return render(request, "project.html", context) |
1372 | puser = User.objects.get(id = prj.user_id) | ||
1373 | except User.DoesNotExist: | ||
1374 | puser = None | ||
1375 | |||
1376 | # execute POST requests | ||
1377 | if request.method == "POST": | ||
1378 | # add layers | ||
1379 | if 'layerAdd' in request.POST and len(request.POST['layerAdd']) > 0: | ||
1380 | for lc in Layer_Version.objects.filter(pk__in=[i for i in request.POST['layerAdd'].split(",") if len(i) > 0]): | ||
1381 | ProjectLayer.objects.get_or_create(project = prj, layercommit = lc) | ||
1382 | |||
1383 | # remove layers | ||
1384 | if 'layerDel' in request.POST and len(request.POST['layerDel']) > 0: | ||
1385 | for t in request.POST['layerDel'].strip().split(" "): | ||
1386 | pt = ProjectLayer.objects.filter(project = prj, layercommit_id = int(t)).delete() | ||
1387 | |||
1388 | if 'projectName' in request.POST: | ||
1389 | prj.name = request.POST['projectName'] | ||
1390 | prj.save(); | ||
1391 | |||
1392 | if 'projectVersion' in request.POST: | ||
1393 | # If the release is the current project then return now | ||
1394 | if prj.release.pk == int(request.POST.get('projectVersion',-1)): | ||
1395 | return {} | ||
1396 | |||
1397 | prj.release = Release.objects.get(pk = request.POST['projectVersion']) | ||
1398 | # we need to change the bitbake version | ||
1399 | prj.bitbake_version = prj.release.bitbake_version | ||
1400 | prj.save() | ||
1401 | # we need to change the layers | ||
1402 | for project in prj.projectlayer_set.all(): | ||
1403 | # find and add a similarly-named layer on the new branch | ||
1404 | try: | ||
1405 | layer_versions = prj.get_all_compatible_layer_versions() | ||
1406 | layer_versions = layer_versions.filter(layer__name = project.layercommit.layer.name) | ||
1407 | ProjectLayer.objects.get_or_create(project = prj, layercommit = layer_versions.first()) | ||
1408 | except IndexError: | ||
1409 | pass | ||
1410 | finally: | ||
1411 | # get rid of the old entry | ||
1412 | project.delete() | ||
1413 | |||
1414 | if 'machineName' in request.POST: | ||
1415 | machinevar = prj.projectvariable_set.get(name="MACHINE") | ||
1416 | machinevar.value=request.POST['machineName'] | ||
1417 | machinevar.save() | ||
1418 | |||
1419 | |||
1420 | # we use implicit knowledge of the current user's project to filter layer information, e.g. | ||
1421 | pid = prj.id | ||
1422 | |||
1423 | from collections import Counter | ||
1424 | |||
1425 | freqtargets = Counter(Target.objects.filter( | ||
1426 | Q(build__project=prj), | ||
1427 | ~Q(build__outcome=Build.IN_PROGRESS) | ||
1428 | ).order_by("target").values_list("target", flat=True)) | ||
1429 | |||
1430 | freqtargets = freqtargets.most_common(5) | ||
1431 | |||
1432 | # We now have the targets in order of frequency but if there are two | ||
1433 | # with the same frequency then we need to make sure those are in | ||
1434 | # alphabetical order without losing the frequency ordering | ||
1435 | |||
1436 | tmp = [] | ||
1437 | switch = None | ||
1438 | for i, freqtartget in enumerate(freqtargets): | ||
1439 | target, count = freqtartget | ||
1440 | try: | ||
1441 | target_next, count_next = freqtargets[i+1] | ||
1442 | if count == count_next and target > target_next: | ||
1443 | switch = target | ||
1444 | continue | ||
1445 | except IndexError: | ||
1446 | pass | ||
1447 | |||
1448 | tmp.append(target) | ||
1449 | |||
1450 | if switch: | ||
1451 | tmp.append(switch) | ||
1452 | switch = None | ||
1453 | |||
1454 | freqtargets = tmp | ||
1455 | |||
1456 | layers = [{"id": x.layercommit.pk, "orderid": x.pk, "name" : x.layercommit.layer.name, | ||
1457 | "vcs_url": x.layercommit.layer.vcs_url, "local_source_dir": x.layercommit.layer.local_source_dir, "vcs_reference" : x.layercommit.get_vcs_reference(), | ||
1458 | "url": x.layercommit.layer.layer_index_url, "layerdetailurl": x.layercommit.get_detailspage_url(prj.pk), | ||
1459 | "branch" : {"name" : x.layercommit.get_vcs_reference(), | ||
1460 | "layersource" : x.layercommit.layer_source } | ||
1461 | } for x in prj.projectlayer_set.all().order_by("id")] | ||
1462 | |||
1463 | context = { | ||
1464 | "project" : prj, | ||
1465 | "lvs_nos" : Layer_Version.objects.all().count(), | ||
1466 | "completedbuilds": Build.objects.exclude(outcome = Build.IN_PROGRESS).filter(project_id = pid), | ||
1467 | "prj" : {"name": prj.name, }, | ||
1468 | "buildrequests" : prj.build_set.filter(outcome=Build.IN_PROGRESS), | ||
1469 | "builds" : Build.get_recent(prj), | ||
1470 | "layers" : layers, | ||
1471 | "targets" : [{"target" : x.target, "task" : x.task, "pk": x.pk} for x in prj.projecttarget_set.all()], | ||
1472 | "variables": [(x.name, x.value) for x in prj.projectvariable_set.all()], | ||
1473 | "freqtargets": freqtargets, | ||
1474 | "releases": [{"id": x.pk, "name": x.name, "description":x.description} for x in Release.objects.all()], | ||
1475 | "project_html": 1, | ||
1476 | "recipesTypeAheadUrl": reverse('xhr_recipestypeahead', args=(prj.pk,)), | ||
1477 | "projectBuildsUrl": reverse('projectbuilds', args=(prj.pk,)), | ||
1478 | } | ||
1479 | |||
1480 | if prj.release is not None: | ||
1481 | context['release'] = { "id": prj.release.pk, "name": prj.release.name, "description": prj.release.description} | ||
1482 | |||
1483 | |||
1484 | try: | ||
1485 | context["machine"] = {"name": prj.projectvariable_set.get(name="MACHINE").value} | ||
1486 | except ProjectVariable.DoesNotExist: | ||
1487 | context["machine"] = None | ||
1488 | try: | ||
1489 | context["distro"] = prj.projectvariable_set.get(name="DISTRO").value | ||
1490 | except ProjectVariable.DoesNotExist: | ||
1491 | context["distro"] = "-- not set yet" | ||
1492 | |||
1493 | return context | ||
1494 | 1369 | ||
1495 | def jsunittests(request): | 1370 | def jsunittests(request): |
1496 | """ Provides a page for the js unit tests """ | 1371 | """ Provides a page for the js unit tests """ |