]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/commitdiff
bitbake: toaster: Clean up and convert to rest api project edit and get calls
authorMichael Wood <michael.g.wood@intel.com>
Mon, 26 Sep 2016 10:59:28 +0000 (13:59 +0300)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Fri, 30 Sep 2016 15:52:21 +0000 (16:52 +0100)
Convert the project xhr calls into proper rest api and port the client
side calls to use the new API. Fix all the pyflakes identified issues
and clean up unused fields.

Also remove the api and client side code for changing release on the fly
as this is no longer supported.

[YOCTO #9519]

(Bitbake rev: 8b01767d6e787cdb09789116ebf57dfb70f521bc)

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
bitbake/lib/toaster/toastergui/api.py
bitbake/lib/toaster/toastergui/static/js/libtoaster.js
bitbake/lib/toaster/toastergui/static/js/projectpage.js
bitbake/lib/toaster/toastergui/static/js/tests/test.js
bitbake/lib/toaster/toastergui/templates/base.html
bitbake/lib/toaster/toastergui/urls.py
bitbake/lib/toaster/toastergui/views.py

index be18090daf8f6c3aafd34304a6cbd8d5868627c4..8876409964e5808b44651b60e24944bc58c9d624 100644 (file)
 
 import re
 import logging
+from collections import Counter
 
 from orm.models import Project, ProjectTarget, Build, Layer_Version
 from orm.models import LayerVersionDependency, LayerSource, ProjectLayer
 from orm.models import Recipe, CustomImageRecipe, CustomImagePackage
 from orm.models import Layer, Target, Package, Package_Dependency
+from orm.models import ProjectVariable
 from bldcontrol.models import BuildRequest
 from bldcontrol import bbcontroller
 
@@ -772,3 +774,162 @@ class XhrCustomRecipePackages(View):
         except CustomImageRecipe.DoesNotExist:
             return error_response("Tried to remove package that wasn't"
                                   " present")
+
+
+class XhrProject(View):
+    """ Create, delete or edit a project
+
+    Entry point: /xhr_project/<project_id>
+    """
+    def post(self, request, *args, **kwargs):
+        """
+          Edit project control
+
+          Args:
+              layerAdd = layer_version_id layer_version_id ...
+              layerDel = layer_version_id layer_version_id ...
+              projectName = new_project_name
+              machineName = new_machine_name
+
+          Returns:
+              {"error": "ok"}
+            or
+              {"error": <error message>}
+        """
+        try:
+            prj = Project.objects.get(pk=kwargs['project_id'])
+        except Project.DoesNotExist:
+            return error_response("No such project")
+
+        # Add layers
+        if 'layerAdd' in request.POST and len(request.POST['layerAdd']) > 0:
+            for layer_version_id in request.POST['layerAdd'].split(','):
+                try:
+                    lv = Layer_Version.objects.get(pk=int(layer_version_id))
+                    ProjectLayer.objects.get_or_create(project=prj,
+                                                       layercommit=lv)
+                except Layer_Version.DoesNotExist:
+                    return error_response("Layer version %s asked to add "
+                                          "doesn't exist" % layer_version_id)
+
+        # Remove layers
+        if 'layerDel' in request.POST and len(request.POST['layerDel']) > 0:
+            layer_version_ids = request.POST['layerDel'].split(',')
+            ProjectLayer.objects.filter(
+                project=prj,
+                layercommit_id__in=layer_version_ids).delete()
+
+        # Project name change
+        if 'projectName' in request.POST:
+            prj.name = request.POST['projectName']
+            prj.save()
+
+        # Machine name change
+        if 'machineName' in request.POST:
+            machinevar = prj.projectvariable_set.get(name="MACHINE")
+            machinevar.value = request.POST['machineName']
+            machinevar.save()
+
+        return JsonResponse({"error": "ok"})
+
+    def get(self, request, *args, **kwargs):
+        """
+        Returns:
+            json object representing the current project
+        or:
+            {"error": <error message>}
+        """
+
+        try:
+            project = Project.objects.get(pk=kwargs['project_id'])
+        except Project.DoesNotExist:
+            return error_response("Project %s does not exist" %
+                                  kwargs['project_id'])
+
+        # Create the frequently built targets list
+
+        freqtargets = Counter(Target.objects.filter(
+            Q(build__project=project),
+            ~Q(build__outcome=Build.IN_PROGRESS)
+        ).order_by("target").values_list("target", flat=True))
+
+        freqtargets = freqtargets.most_common(5)
+
+        # We now have the targets in order of frequency but if there are two
+        # with the same frequency then we need to make sure those are in
+        # alphabetical order without losing the frequency ordering
+
+        tmp = []
+        switch = None
+        for i, freqtartget in enumerate(freqtargets):
+            target, count = freqtartget
+            try:
+                target_next, count_next = freqtargets[i+1]
+                if count == count_next and target > target_next:
+                    switch = target
+                    continue
+            except IndexError:
+                pass
+
+            tmp.append(target)
+
+            if switch:
+                tmp.append(switch)
+                switch = None
+
+        freqtargets = tmp
+
+        layers = []
+        for layer in project.projectlayer_set.all():
+            layers.append({
+                "id": layer.layercommit.pk,
+                "name": layer.layercommit.layer.name,
+                "vcs_url": layer.layercommit.layer.vcs_url,
+                "local_source_dir": layer.layercommit.layer.local_source_dir,
+                "vcs_reference": layer.layercommit.get_vcs_reference(),
+                "url": layer.layercommit.layer.layer_index_url,
+                "layerdetailurl": layer.layercommit.get_detailspage_url(
+                    project.pk),
+                "layersource": layer.layercommit.layer_source
+            })
+
+        data = {
+            "name": project.name,
+            "layers": layers,
+            "freqtargets": freqtargets,
+        }
+
+        if project.release is not None:
+            data['release'] = {
+                "id": project.release.pk,
+                "name": project.release.name,
+                "description": project.release.description
+            }
+
+        try:
+            data["machine"] = {"name":
+                               project.projectvariable_set.get(
+                                   name="MACHINE").value}
+        except ProjectVariable.DoesNotExist:
+            data["machine"] = None
+        try:
+            data["distro"] = project.projectvariable_set.get(
+                name="DISTRO").value
+        except ProjectVariable.DoesNotExist:
+            data["distro"] = "-- not set yet"
+
+        data['error'] = "ok"
+
+        return JsonResponse(data)
+
+    def put(self, request, *args, **kwargs):
+        # TODO create new project api
+        return HttpResponse()
+
+    def delete(self, request, *args, **kwargs):
+        try:
+            Project.objects.get(kwargs['project_id']).delete()
+        except Project.DoesNotExist:
+            return error_response("Project %s does not exist" %
+                                  kwargs['project_id'])
+        return JsonResponse({"error": "ok"})
index f56affd8eab20e42e3e003bd081765c31e789cb4..b2099a6048df88214634eb107082d8974645eed3 100644 (file)
@@ -167,7 +167,6 @@ var libtoaster = (function () {
   function _getProjectInfo(url, onsuccess, onfail){
     $.ajax({
         type: "GET",
-        data : { format: "json" },
         url: url,
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (_data) {
@@ -194,7 +193,7 @@ var libtoaster = (function () {
   function _editCurrentProject(data, onSuccess, onFail){
     $.ajax({
         type: "POST",
-        url: libtoaster.ctx.projectPageUrl + "?format=json",
+        url: libtoaster.ctx.xhrProjectUrl,
         data: data,
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (data) {
index b75b3e18693201e442ac5c08b697f50181420de9..3bf3cbaf2b37516d09827ab53b5c74f0d6e14464 100644 (file)
@@ -27,11 +27,10 @@ function projectPageInit(ctx) {
 
   var urlParams = libtoaster.parseUrlParams();
 
-  libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
+  libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){
     updateProjectLayers(prjInfo.layers);
     updateFreqBuildRecipes(prjInfo.freqtargets);
     updateProjectRelease(prjInfo.release);
-    updateProjectReleases(prjInfo.releases, prjInfo.release);
 
     /* If we're receiving a machine set from the url and it's different from
      * our current machine then activate set machine sequence.
@@ -287,7 +286,9 @@ function projectPageInit(ctx) {
     machineNameTitle.text(machineName);
   }
 
-  libtoaster.makeTypeahead(machineChangeInput, libtoaster.ctx.machinesTypeAheadUrl, { }, function(item){
+  libtoaster.makeTypeahead(machineChangeInput,
+                           libtoaster.ctx.machinesTypeAheadUrl,
+                           { }, function(item){
     currentMachineAddSelection = item.name;
     machineChangeBtn.removeAttr("disabled");
   });
@@ -324,146 +325,10 @@ function projectPageInit(ctx) {
     releaseTitle.text(release.description);
   }
 
-  function updateProjectReleases(releases, current){
-    for (var i in releases){
-      var releaseOption = $("<option></option>");
 
-      releaseOption.val(releases[i].id);
-      releaseOption.text(releases[i].description);
-      releaseOption.data('release', releases[i]);
-
-      if (releases[i].id == current.id)
-        releaseOption.attr("selected", "selected");
-
-      releaseForm.children("select").append(releaseOption);
-    }
-  }
-
-  releaseChangeFormToggle.click(function(){
-    releaseForm.slideDown();
-    releaseTitle.hide();
-    $(this).hide();
-  });
-
-  cancelReleaseChange.click(function(e){
+  $("#delete-project-confirmed").click(function(e){
     e.preventDefault();
-    releaseForm.slideUp(function(){
-      releaseTitle.show();
-      releaseChangeFormToggle.show();
-    });
-  });
-
-  function changeProjectRelease(release, layersToRm){
-    libtoaster.editCurrentProject({ projectVersion : release.id },
-      function(){
-        /* Success */
-        /* Update layers list with new layers */
-        layersInPrjList.addClass('muted');
-        libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl,
-            function(prjInfo){
-              layersInPrjList.children().remove();
-              updateProjectLayers(prjInfo.layers);
-              layersInPrjList.removeClass('muted');
-              releaseChangedNotification(release, prjInfo.layers, layersToRm);
-        });
-        updateProjectRelease(release);
-        cancelReleaseChange.click();
-    });
-  }
-
-  /* Create a notification to show the changes to the layer configuration
-   * caused by changing a release.
-   */
-
-  function releaseChangedNotification(release, layers, layersToRm){
-
-    var message;
-
-    if (layers.length === 0 && layersToRm.length === 0){
-      message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>.');
-      message.find("#notify-release-name").text(release.description);
-      libtoaster.showChangeNotification(message);
-      return;
-    }
-
-    /* Create the whitespace separated list of layers removed */
-    var layersDelList = "";
-
-    layersToRm.map(function(layer, i){
-      layersDelList += layer.name;
-      if (layersToRm[i+1] !== undefined)
-        layersDelList += ', ';
-    });
-
-    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>');
-
-    var changedList = message.find("#notify-layers-changed-list");
-
-    message.find("#notify-release-name").text(release.description);
-
-    /* Manually construct the list item for changed layers */
-    var li = '<li><strong>'+layers.length+'</strong> layers changed to the <strong>'+release.name+'</strong> release: ';
-    for (var i in layers){
-      li += '<a href='+layers[i].layerdetailurl+'>'+layers[i].name+'</a>';
-      if (i !== 0)
-        li += ', ';
-    }
-
-    changedList.append($(li));
-
-    /* Layers removed */
-    if (layersToRm && layersToRm.length > 0){
-      if (layersToRm.length == 1)
-        li = '<li><strong>1</strong> layer removed: '+layersToRm[0].name+'</li>';
-      else
-        li = '<li><strong>'+layersToRm.length+'</strong> layers deleted: '+layersDelList+'</li>';
-
-      changedList.append($(li));
-    }
-
-    libtoaster.showChangeNotification(message);
-  }
-
-  /* Show the modal dialog which gives the option to remove layers which
-   * aren't compatible with the proposed release
-   */
-  function showReleaseLayerChangeModal(release, layers){
-    var layersToRmList = releaseModal.find("#layers-to-remove-list");
-    layersToRmList.text("");
-
-    releaseModal.find(".proposed-release-change-name").text(release.description);
-    releaseModal.data("layers", layers);
-    releaseModal.data("release", release);
-
-    for (var i in layers){
-      layersToRmList.append($("<li></li>").text(layers[i].name));
-    }
-    releaseModal.modal('show');
-  }
-
-  $("#change-release-btn").click(function(e){
-    e.preventDefault();
-
-    var newRelease = releaseForm.find("option:selected").data('release');
-
-    $.getJSON(ctx.testReleaseChangeUrl,
-      { new_release_id: newRelease.id },
-      function(layers) {
-        if (layers.rows.length === 0){
-          /* No layers to change for this release */
-          changeProjectRelease(newRelease, []);
-        } else {
-          showReleaseLayerChangeModal(newRelease, layers.rows);
-        }
-    });
-  });
-
-  /* Release change modal accept */
-  $("#change-release-and-rm-layers").click(function(){
-    var layers = releaseModal.data("layers");
-    var release =  releaseModal.data("release");
-
-    changeProjectRelease(release, layers);
+  
   });
 
 }
index f8d566b3e3fff3081c4e65273140c30214853a13..d7953de4477204557e16b5059b66f2a0e15bcf11 100644 (file)
@@ -42,9 +42,8 @@ QUnit.test("Layer alert notification", function(assert) {
 
 QUnit.test("Project info", function(assert){
   var done = assert.async();
-  libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
+  libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){
     assert.ok(prjInfo.machine.name);
-    assert.ok(prjInfo.releases.length > 0);
     assert.ok(prjInfo.layers.length > 0);
     assert.ok(prjInfo.freqtargets);
     assert.ok(prjInfo.release);
@@ -82,11 +81,11 @@ QUnit.test("Add layer", function(assert){
   }, 200);
 
   /* Compare the number of layers before and after the add in the project */
-  libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
+  libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){
     var origNumLayers = prjInfo.layers.length;
 
     libtoaster.addRmLayer(layer, true, function(deps){
-      libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl,
+      libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl,
         function(prjInfo){
         assert.ok(prjInfo.layers.length > origNumLayers,
           "Layer not added to project");
index 58491eba81ac4b858152eefce79bc17210f7d09d..c1b1417a7630a948cacbe099b5460651727da9bd 100644 (file)
@@ -44,6 +44,7 @@
         {% if project.id %}
         projectId : {{project.id}},
         projectPageUrl : {% url 'project' project.id as purl %}{{purl|json}},
+        xhrProjectUrl : {% url 'xhr_project' project.id as pxurl %}{{pxurl|json}},
         projectName : {{project.name|json}},
         recipesTypeAheadUrl: {% url 'xhr_recipestypeahead' project.id as paturl%}{{paturl|json}},
         layersTypeAheadUrl: {% url 'xhr_layerstypeahead' project.id as paturl%}{{paturl|json}},
index 9509cd5928c6484d3c06dd769224d0ae048fe810..1232611e2ebdf7c67e84a11893b938f39411a5a2 100644 (file)
@@ -220,6 +220,10 @@ urlpatterns = patterns('toastergui.views',
             api.XhrBuildRequest.as_view(),
             name='xhr_buildrequest'),
 
+        url(r'xhr_project/(?P<project_id>\d+)$',
+            api.XhrProject.as_view(),
+            name='xhr_project'),
+
         url(r'^mostrecentbuilds$', api.MostRecentBuildsView.as_view(),
             name='most_recent_builds'),
 
index 365a1e88fffb9c48881d527b91719ea1b8ac0860..2efb0fd56cd3d179ab69eecafd22a2cde702b166 100755 (executable)
@@ -1361,136 +1361,11 @@ if True:
 
         raise Exception("Invalid HTTP method for this page")
 
-
-
     # Shows the edit project page
-    @_template_renderer('project.html')
     def project(request, pid):
-        prj = Project.objects.get(id = pid)
-
-        try:
-            puser = User.objects.get(id = prj.user_id)
-        except User.DoesNotExist:
-            puser = None
-
-        # execute POST requests
-        if request.method == "POST":
-            # add layers
-            if 'layerAdd' in request.POST and len(request.POST['layerAdd']) > 0:
-                for lc in Layer_Version.objects.filter(pk__in=[i for i in request.POST['layerAdd'].split(",") if len(i) > 0]):
-                    ProjectLayer.objects.get_or_create(project = prj, layercommit = lc)
-
-            # remove layers
-            if 'layerDel' in request.POST and len(request.POST['layerDel']) > 0:
-                for t in request.POST['layerDel'].strip().split(" "):
-                    pt = ProjectLayer.objects.filter(project = prj, layercommit_id = int(t)).delete()
-
-            if 'projectName' in request.POST:
-                prj.name = request.POST['projectName']
-                prj.save();
-
-            if 'projectVersion' in request.POST:
-                # If the release is the current project then return now
-                if prj.release.pk == int(request.POST.get('projectVersion',-1)):
-                    return {}
-
-                prj.release = Release.objects.get(pk = request.POST['projectVersion'])
-                # we need to change the bitbake version
-                prj.bitbake_version = prj.release.bitbake_version
-                prj.save()
-                # we need to change the layers
-                for project in prj.projectlayer_set.all():
-                    # find and add a similarly-named layer on the new branch
-                    try:
-                        layer_versions = prj.get_all_compatible_layer_versions()
-                        layer_versions = layer_versions.filter(layer__name = project.layercommit.layer.name)
-                        ProjectLayer.objects.get_or_create(project = prj, layercommit = layer_versions.first())
-                    except IndexError:
-                        pass
-                    finally:
-                        # get rid of the old entry
-                        project.delete()
-
-            if 'machineName' in request.POST:
-                machinevar = prj.projectvariable_set.get(name="MACHINE")
-                machinevar.value=request.POST['machineName']
-                machinevar.save()
-
-
-        # we use implicit knowledge of the current user's project to filter layer information, e.g.
-        pid = prj.id
-
-        from collections import Counter
-
-        freqtargets = Counter(Target.objects.filter(
-            Q(build__project=prj),
-            ~Q(build__outcome=Build.IN_PROGRESS)
-        ).order_by("target").values_list("target", flat=True))
-
-        freqtargets = freqtargets.most_common(5)
-
-        # We now have the targets in order of frequency but if there are two
-        # with the same frequency then we need to make sure those are in
-        # alphabetical order without losing the frequency ordering
-
-        tmp = []
-        switch = None
-        for i, freqtartget in enumerate(freqtargets):
-            target, count = freqtartget
-            try:
-                target_next, count_next = freqtargets[i+1]
-                if count == count_next and target > target_next:
-                    switch = target
-                    continue
-            except IndexError:
-                pass
-
-            tmp.append(target)
-
-            if switch:
-                tmp.append(switch)
-                switch = None
-
-        freqtargets = tmp
-
-        layers = [{"id": x.layercommit.pk, "orderid": x.pk, "name" : x.layercommit.layer.name,
-                   "vcs_url": x.layercommit.layer.vcs_url, "local_source_dir": x.layercommit.layer.local_source_dir, "vcs_reference" : x.layercommit.get_vcs_reference(),
-                   "url": x.layercommit.layer.layer_index_url, "layerdetailurl": x.layercommit.get_detailspage_url(prj.pk),
-                   "branch" : {"name" : x.layercommit.get_vcs_reference(),
-                               "layersource" : x.layercommit.layer_source }
-                   } for x in prj.projectlayer_set.all().order_by("id")]
-
-        context = {
-            "project" : prj,
-            "lvs_nos" : Layer_Version.objects.all().count(),
-            "completedbuilds": Build.objects.exclude(outcome = Build.IN_PROGRESS).filter(project_id = pid),
-            "prj" : {"name": prj.name, },
-            "buildrequests" : prj.build_set.filter(outcome=Build.IN_PROGRESS),
-            "builds" : Build.get_recent(prj),
-            "layers" : layers,
-            "targets" : [{"target" : x.target, "task" : x.task, "pk": x.pk} for x in prj.projecttarget_set.all()],
-            "variables": [(x.name, x.value) for x in prj.projectvariable_set.all()],
-            "freqtargets": freqtargets,
-            "releases": [{"id": x.pk, "name": x.name, "description":x.description} for x in Release.objects.all()],
-            "project_html": 1,
-            "recipesTypeAheadUrl": reverse('xhr_recipestypeahead', args=(prj.pk,)),
-            "projectBuildsUrl": reverse('projectbuilds', args=(prj.pk,)),
-        }
-
-        if prj.release is not None:
-            context['release'] = { "id": prj.release.pk, "name": prj.release.name, "description": prj.release.description}
-
-
-        try:
-            context["machine"] = {"name": prj.projectvariable_set.get(name="MACHINE").value}
-        except ProjectVariable.DoesNotExist:
-            context["machine"] = None
-        try:
-            context["distro"] = prj.projectvariable_set.get(name="DISTRO").value
-        except ProjectVariable.DoesNotExist:
-            context["distro"] = "-- not set yet"
-
-        return context
+        project = Project.objects.get(pk=pid)
+        context = {"project": project}
+        return render(request, "project.html", context)
 
     def jsunittests(request):
         """ Provides a page for the js unit tests """