Skip to contentSkip to conversation

Toaster patchset pull request

PATCH New Alex DAMIAN 1 participant 6 messages Jan 8, 2015 – Jan 9, 2015

lore
Share & tools
lore
#0 lore raw

cover Toaster patchset pull request

From: Alexandru DAMIAN <[email protected]>

Hi,

This is a toaster patchset with patches that have been reviewed on the toaster mailing list.

It contains bugfixes and new features in the frontend Web interface.

Can you please pull at your convenience ?

Cheers,
Alex

The following changes since commit 86704281b79e524dccccc88cbf996b299b33bae2:

ast: Add error when trying to use dash in sh function names (2015-01-08 10:37:06 +0000)

are available in the git repository at:

git://git.yoctoproject.org/poky-contrib adamian/20150108-submission-bb
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=adamian/20150108-submission-bb

Alexandru DAMIAN (4):
toaster: write pre-read conf file for build variables
toaster: do not launch web browser on noweb option
toaster: branch name priority resolution
toaster: implementation of project page

Michael Wood (1):
toaster: Improve client side error handling

 bin/toaster                                        |  13 +-
 lib/toaster/bldcontrol/bbcontroller.py             |   5 +
 .../bldcontrol/management/commands/runbuilds.py    |   5 +-
 lib/toaster/orm/models.py                          |   9 +-
 lib/toaster/toastergui/static/js/libtoaster.js     |  39 +++-
 lib/toaster/toastergui/static/js/projectapp.js     | 242 +++++++++++++++------
 lib/toaster/toastergui/templates/base.html         |   5 +
 lib/toaster/toastergui/templates/layers.html       |   8 +-
 lib/toaster/toastergui/templates/mrb_section.html  |   8 +-
 lib/toaster/toastergui/templates/project.html      |  50 +++--
 lib/toaster/toastergui/templates/targets.html      |   8 +-
 lib/toaster/toastergui/views.py                    | 103 ++++-----
 12 files changed, 329 insertions(+), 166 deletions(-)
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/5 toaster: Improve client side error handling

From: Michael Wood <[email protected]>

Make use of the toastermain.settings.DEBUG flag to toggle the client side error logging. Make the error logging consistent by using console.warn/error across the project, this adds traceability to the warnings. Also handles the case where console is not available by stubbing it in libtoaster.

---
 lib/toaster/toastergui/static/js/libtoaster.js    | 39 ++++++++++++++++++++---
 lib/toaster/toastergui/static/js/projectapp.js    | 28 ++++++++--------
 lib/toaster/toastergui/templates/base.html        |  5 +++
 lib/toaster/toastergui/templates/layers.html      |  8 ++---
 lib/toaster/toastergui/templates/mrb_section.html |  8 ++---
 lib/toaster/toastergui/templates/targets.html     |  8 ++---
 lib/toaster/toastergui/views.py                   |  6 ++--
 7 files changed, 69 insertions(+), 33 deletions(-)
lib/toaster/toastergui/static/js/libtoaster.js +34 -5
index 15815b3..a2a0abd 100644
@@ -81,14 +81,14 @@ var libtoaster = (function (){
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (_data) {
           if (_data.error != "ok") {
-            console.log(_data.error);
+            console.warn(_data.error);
           } else {
             if (onsuccess != undefined) onsuccess(_data);
           }
         },
         error: function (_data) {
-          console.log("Call failed");
-          console.log(_data);
+          console.warn("Call failed");
+          console.warn(_data);
           if (onfail) onfail(data);
     } });
   };
@@ -102,13 +102,13 @@ var libtoaster = (function (){
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (_data) {
           if (_data.error != "ok") {
-            console.log(_data.error);
+            console.warn(_data.error);
           } else {
             if (onsuccess != undefined) onsuccess(_data);
           }
         },
         error: function (_data) {
-          console.log(_data);
+          console.warn(_data);
           if (onfail) onfail(data);
         }
     });
@@ -168,6 +168,7 @@ var libtoaster = (function (){
     getProjectInfo: _getProjectInfo,
     getLayerDepsForProject : _getLayerDepsForProject,
     editProject : _editProject,
+    debug: false,
   }
 })();
 
@@ -203,6 +204,15 @@ function reload_params(params) {
 /* Things that happen for all pages */
 $(document).ready(function() {
 
+    /* If we don't have a console object which might be the case in some
+     * browsers, no-op it to avoid undefined errors.
+     */
+    if (!window.console) {
+      window.console = {};
+      window.console.warn = function() {};
+      window.console.error = function() {};
+    }
+
     /*
      * PrettyPrint plugin.
      *
@@ -320,4 +330,23 @@ $(document).ready(function() {
     if (location.href.search('#warnings') > -1) {
         $('#collapse-warnings').addClass('in');
     }
+
+    function check_for_duplicate_ids () {
+      /* warn about duplicate element ids */
+      var ids = {};
+      $("[id]").each(function() {
+        if (this.id && ids[this.id]) {
+          console.warn('Duplicate element id #'+this.id);
+        }
+        ids[this.id] = true;
+      });
+    }
+
+    if (libtoaster.debug) {
+      check_for_duplicate_ids();
+    } else {
+      /* Debug is false so supress warnings by overriding the functions */
+      window.console.warn = function () {};
+      window.console.error = function () {};
+   }
 });
lib/toaster/toastergui/static/js/projectapp.js +14 -14
index bb97f32..767ea13 100644
@@ -136,7 +136,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         $http({method:"GET", url: $scope.urls.xhr_datatypeahead, params : { type: type, value: currentValue}})
             .success(function (_data) {
                 if (_data.error != "ok") {
-                    alert(_data.error);
+                    console.warn(_data.error);
                     deffered.reject(_data.error);
                 }
                 deffered.resolve(_data.list);
@@ -152,12 +152,12 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         if (inXHRcall) {
             if (callparams.data === undefined) {
                 // we simply skip the data refresh calls
-                console.log("race on XHR, aborted");
+                console.warn("race on XHR, aborted");
                 return;
             } else {
                 // we return a promise that we'll solve by reissuing the command later
                 var delayed = $q.defer();
-                console.log("race on XHR, delayed");
+                console.warn("race on XHR, delayed");
                 $interval(function () {$scope._makeXHRCall(callparams).then(function (d) { delayed.resolve(d); });}, 100, 1);
 
                 return delayed.promise;
@@ -171,7 +171,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
 
         $http(callparams).success(function(_data, _status, _headers, _config) {
             if (_data.error != "ok") {
-                alert("Failed XHR request (" + _status + "): " + _data.error);
+                console.warn("Failed XHR request (" + _status + "): " + _data.error);
                 console.error("Failed XHR request: ", _data, _status, _headers, _config);
                 // stop refreshing hte page
                 $interval.cancel($scope.pollHandle);
@@ -267,7 +267,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                 deffered.resolve(_data);
             }
         }).error(function(_data, _status, _headers, _config) {
-                alert("Failed HTTP XHR request (" + _status + ")" + _data);
+                console.warn("Failed HTTP XHR request (" + _status + ")" + _data);
                 console.error("Failed HTTP XHR request: ", _data, _status, _headers, _config);
                 inXHRcall = false;
                 deffered.reject(_data.error);
@@ -298,7 +298,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
 
     $scope.targetNamedBuild = function(target) {
         if ($scope.targetName === undefined && $scope.targetName1 === undefined){
-            alert("No target defined, please type in a target name");
+            console.warn("No target defined, please type in a target name");
             return;
         }
 
@@ -310,7 +310,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                 targets: $scope.safeTargetName,
             }
         }).then(function (data) {
-            console.log("received ", data);
+            console.warn("received ", data);
             $scope.targetName = undefined;
             $scope.targetName1 = undefined;
             $location.hash('buildslist');
@@ -357,7 +357,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         $http({method:"GET", url: $scope.urls.xhr_datatypeahead, params : { type: "layerdeps", value: $scope.layerAddId }})
         .success(function (_data) {
              if (_data.error != "ok") {
-                 alert(_data.error);
+                 console.warn(_data.error);
              } else {
                  if (_data.list.length > 0) {
                      // activate modal
@@ -369,7 +369,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                          $scope.selectedItems = (function () { s = {}; for (var i = 0; i < items.length; i++) { s[items[i].id] = true; };return s; })();
 
                          $scope.ok = function() {
-                            console.log("scope selected is ", $scope.selectedItems);
+                            console.warn("scope selected is ", $scope.selectedItems);
                             $modalInstance.close(Object.keys($scope.selectedItems).filter(function (e) { return $scope.selectedItems[e];}));
                          };
 
@@ -378,7 +378,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                          };
 
                          $scope.update = function() {
-                            console.log("updated ", $scope.selectedItems);
+                            console.warn("updated ", $scope.selectedItems);
                          };
                        },
                        resolve: {
@@ -393,7 +393,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
 
                      modalInstance.result.then(function (selectedArray) {
                          selectedArray.push($scope.layerAddId);
-                         console.log("selected", selectedArray);
+                         console.warn("selected", selectedArray);
 
                          $scope._makeXHRCall({
                              method: "POST", url: $scope.urls.xhr_edit,
@@ -473,7 +473,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
 
     $scope.edit = function(elementid) {
         var data = {};
-        console.log("edit with ", elementid);
+        console.warn("edit with ", elementid);
         var alertText = undefined;
         var alertZone = undefined;
         var oldLayers = [];
@@ -675,7 +675,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
 */
 
 function test_diff_arrays() {
-    _diffArrays([1,2,3], [2,3,4], function(e,f) { return e==f; }, function(e) {console.log("added", e)}, function(e) {console.log("deleted", e);})
+    _diffArrays([1,2,3], [2,3,4], function(e,f) { return e==f; }, function(e) {console.warn("added", e)}, function(e) {console.warn("deleted", e);})
 }
 
 // test_diff_arrays();
@@ -685,6 +685,6 @@ var s = undefined;
 function test_set_alert(text) {
     s = angular.element("div#main").scope();
     s.displayAlert(s.zone3alerts, text);
-    console.log(s.zone3alerts);
+    console.warn(s.zone3alerts);
     s.$digest();
 }
lib/toaster/toastergui/templates/base.html +5 -0
index bc7a0ee..e95b5e0 100644
@@ -21,6 +21,11 @@
 </script>
 <script src="{% static 'js/libtoaster.js' %}">
 </script>
+{% if DEBUG %}
+<script>
+  libtoaster.debug = true;
+ </script>
+{% endif %}
 <script src="{% static 'js/base.js' %}"></script>
 {%if MANAGED %}
 <script>
lib/toaster/toastergui/templates/layers.html +4 -4
index ced54c2..33160e5 100644
@@ -126,15 +126,15 @@ function _makeXHREditCall(data, onsuccess, onfail) {
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (_data) {
             if (_data.error != "ok") {
-                alert(_data.error);
+                console.warn(_data.error);
             } else {
                 updateButtons(_data.layers.map(function (e) {return e.id}));
                 if (onsuccess != undefined) onsuccess(_data);
             }
         },
         error: function (_data) {
-            alert("Call failed");
-            console.log(_data);
+            console.warn("Call failed");
+            console.warn(_data);
         }
     });
 }
@@ -215,7 +215,7 @@ function layerAdd(layerId, layerName, layerURL) {
         data: {'type': 'layerdeps','value':layerId},
         success: function(_data) {
                 if (_data.error != "ok") {
-                    alert(_data.error);
+                    console.warn(_data.error);
                 } else {
                     updateLayerCountLabels(_data.list.length+1);
 
lib/toaster/toastergui/templates/mrb_section.html +4 -4
index 73031e2..432955a 100644
@@ -79,21 +79,21 @@ function _makeXHRBuildCall(url, data, onsuccess, onfail) {
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (_data) {
             if (_data.error != "ok") {
-                alert(_data.error);
+                console.warn(_data.error);
             } else {
                 if (onsuccess != undefined) onsuccess(_data);
             }
         },
         error: function (_data) {
-            alert("Call failed");
-            console.log(_data);
+            console.warn("Call failed");
+            console.warn(_data);
             if (onfail) onfail(data);
         } });
 }
 
 
 function scheduleBuild(url, projectName, buildlist) {
-  console.log("scheduleBuild");
+  console.warn("scheduleBuild");
   _makeXHRBuildCall(url, {targets: buildlist.join(" ")}, function (_data) {
 
       $('#latest-builds').prepend('<div class="alert alert-info" style="padding-top:0px">' + '<span class="label label-info" style="font-weight: normal; margin-bottom: 5px; margin-left:-15px; padding-top:5px;">'+projectName+'</span><div class="row-fluid">' +
lib/toaster/toastergui/templates/targets.html +4 -4
index f4313f9..cc339fb 100644
@@ -119,15 +119,15 @@ function _makeXHREditCall(data, onsuccess, onfail) {
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (_data) {
             if (_data.error != "ok") {
-                alert(_data.error);
+                console.warn(_data.error);
             } else {
                 updateButtons(_data.layers.map(function (e) {return e.id}));
                 if (onsuccess != undefined) onsuccess(_data);
             }
         },
         error: function (_data) {
-            alert("Call failed");
-            console.log(_data);
+            console.warn("Call failed");
+            console.warn(_data);
         }
     });
 }
@@ -202,7 +202,7 @@ function layerAdd(layerId, layerName, layerURL, pressedButtonId) {
         data: {'type': 'layerdeps','value':layerId},
         success: function(_data) {
                 if (_data.error != "ok") {
-                    alert(_data.error);
+                    console.warn(_data.error);
                 } else {
                     updateLayerCountLabels(_data.list.length+1);
 
lib/toaster/toastergui/views.py +4 -2
index 679c1e9..420b37c 100755
@@ -1898,7 +1898,8 @@ if toastermain.settings.MANAGED:
     def managedcontextprocessor(request):
         ret = {
             "projects": Project.objects.all(),
-            "MANAGED" : toastermain.settings.MANAGED
+            "MANAGED" : toastermain.settings.MANAGED,
+            "DEBUG" : toastermain.settings.DEBUG
         }
         if 'project_id' in request.session:
             try:
@@ -2923,7 +2924,8 @@ else:
     def managedcontextprocessor(request):
         return {
             "projects": [],
-            "MANAGED" : toastermain.settings.MANAGED
+            "MANAGED" : toastermain.settings.MANAGED,
+            "DEBUG" : toastermain.settings.DEBUG
         }
 
     def newproject(request):
Signature · 1 line
1.9.1
#2 lore raw

PATCH 2/5 toaster: write pre-read conf file for build variables

From: Alexandru DAMIAN <[email protected]>

We change the setting of variables from directly injection into the set-up cooker to writing a conf file that is pre-read on bitbake server startup. This is needed because the injection can only happen after the variable set is parsed, and the variables already inferred, so setting up variables happens too late.

[YOCTO #7045]

---
 bin/toaster                                             | 6 +++++-
 lib/toaster/bldcontrol/bbcontroller.py                  | 5 +++++
 lib/toaster/bldcontrol/management/commands/runbuilds.py | 5 +----
 lib/toaster/orm/models.py                               | 1 +
 4 files changed, 12 insertions(+), 5 deletions(-)
bin/toaster +5 -1
index 7511012..6969bf7 100755
@@ -251,7 +251,11 @@ case $CMD in
             return 4
         fi
         unset BBSERVER
-        bitbake --postread conf/toaster.conf --server-only -t xmlrpc -B 0.0.0.0:0
+        PREREAD=""
+        if [ -e conf/toaster-pre.conf ]; then
+                PREREAD="--read conf/toaster-pre.conf"
+        fi
+        bitbake $PREREAD --postread conf/toaster.conf --server-only -t xmlrpc -B 0.0.0.0:0
         if [ $? -ne 0 ]; then
             start_success=0
             echo "Bitbake server start failed"
lib/toaster/bldcontrol/bbcontroller.py +5 -0
index 7c27fe1..102606e 100644
@@ -135,6 +135,11 @@ class BuildEnvironmentController(object):
         bblayerconffile.write("# line added by toaster build control\nBBLAYERS = \"" + " ".join(layerlist) + "\"")
         bblayerconffile.close()
 
+    def writePreConfFile(self, variable_list):
+        prefilepath = os.path.join(self.be.builddir, "conf/toaster-pre.conf")
+        with open(prefilepath, "w") as prefile:
+            for i in variable_list:
+                prefile.write("%s=\"%s\"\n" % (i.name, i.value))
 
 
     def startBBServer(self, brbe):
lib/toaster/bldcontrol/management/commands/runbuilds.py +1 -4
index 56c989c..bdce6ee 100644
@@ -53,14 +53,11 @@ class Command(NoArgsCommand):
 
             # set up the buid environment with the needed layers
             bec.setLayers(br.brbitbake_set.all(), br.brlayer_set.all())
+            bec.writePreConfFile(br.brvariable_set.all())
 
             # get the bb server running with the build req id and build env id
             bbctrl = bec.getBBController("%d:%d" % (br.pk, bec.be.pk))
 
-            # set the build configuration
-            for variable in br.brvariable_set.all():
-                bbctrl.setVariable(variable.name, variable.value)
-
             # trigger the build command
             task = reduce(lambda x, y: x if len(y)== 0 else y, map(lambda y: y.task, br.brtarget_set.all()))
             if len(task) == 0:
lib/toaster/orm/models.py +1 -0
index 46b704c..6fbbeed 100644
@@ -529,6 +529,7 @@ class Recipe_Dependency(models.Model):
 
 
 class Machine(models.Model):
+    search_allowed_fields = ["name", "description"]
     layer_source = models.ForeignKey('LayerSource', default = None, null = True)  # from where did we get this machine
     up_id = models.IntegerField(null = True, default = None)                      # id of entry in the source
     up_date = models.DateTimeField(null = True, default = None)
Signature · 1 line
1.9.1
#3 lore raw

PATCH 3/5 toaster: do not launch web browser on noweb option

In reply to Alex DAMIAN

From: Alexandru DAMIAN <[email protected]>

This patch makes Toaster managed mode obey the "noweb" parameter by not starting the web server and launching the web browser command if the "noweb" parameter is specified.

The web browser will be pointed at 127.0.0.1 instead of 0.0.0.0

[YOCTO #7039]

---
 bin/toaster | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
bin/toaster +5 -2
index 6969bf7..a6d2e92 100755
@@ -185,11 +185,14 @@ if [ -z "$ZSH_NAME" ] && [ `basename \"$0\"` = `basename \"$BASH_SOURCE\"` ]; th
     }
     TOASTER_MANAGED=1
     export TOASTER_MANAGED=1
-    if ! webserverStartAll; then
+    if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
         echo "Failed to start the web server, stopping" 1>&2;
         exit 1;
     fi
-    xdg-open http://0.0.0.0:$WEB_PORT/ >/dev/null 2>&1 &
+    if [ $WEBSERVER -gt 0 ]; then
+        echo "Starting browser..."
+        xdg-open http://127.0.0.1:$WEB_PORT/ >/dev/null 2>&1 &
+    fi
     trap trap_ctrlc SIGINT
     echo "Running. Stop with Ctrl-C"
     while [ $RUNNING -gt 0 ]; do
Signature · 1 line
1.9.1
#4 lore raw

PATCH 4/5 toaster: branch name priority resolution

In reply to Alex DAMIAN

From: Alexandru DAMIAN <[email protected]>

Adding a Layer_Version function that gets back the branch name that should be used/displayed for finding the targeted git branch name.

Change the commit id to use the branch name instead of the last-updated commit hash from the layer source.

[YOCTO #7031]

---
 lib/toaster/orm/models.py | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
lib/toaster/orm/models.py +7 -1
index 6fbbeed..5eff955 100644
@@ -740,7 +740,7 @@ class LayerIndexLayerSource(LayerSource):
             lv.up_date = lbi['updated']
             lv.up_branch = Branch.objects.get(layer_source = self, up_id = lbi['branch'])
             lv.branch = lbi['actual_branch']
-            lv.commit = lbi['vcs_last_rev']
+            lv.commit = lbi['actual_branch']
             lv.dirpath = lbi['vcs_subdir']
             lv.save()
 
@@ -960,6 +960,12 @@ class Layer_Version(models.Model):
                 key = lambda x: _get_ls_priority(x.layer_source),
                 reverse = True)
 
+    def get_vcs_reference(self):
+        if self.commit is not None and len(self.commit) > 0:
+            return self.commit
+        if self.branch is not None and len(self.branch) > 0:
+            return self.branch
+        return self.up_branch.name
 
     def __unicode__(self):
         return  str(self.layer) + " (" + self.commit +")"
Signature · 1 line
1.9.1
#5 lore raw

PATCH 5/5 toaster: implementation of project page

In reply to Alex DAMIAN

From: Alexandru DAMIAN <[email protected]>

This patch brings the project page in line with the design, including build error handling and suggestions.

Includes some refactoring for already existing code.

[YOCTO #6587]

---
 lib/toaster/toastergui/static/js/projectapp.js | 234 ++++++++++++++++++-------
 lib/toaster/toastergui/templates/project.html  |  50 ++++--
 lib/toaster/toastergui/views.py                |  97 +++++-----
 3 files changed, 246 insertions(+), 135 deletions(-)
lib/toaster/toastergui/static/js/projectapp.js +166 -68
index 767ea13..0bdc55a 100644
@@ -100,6 +100,16 @@ function _diffArrays(existingArray, newArray, compareElements, onAdded, onDelete
 
 }
 
+// add Array findIndex if not there
+
+if (Array.prototype.findIndex === undefined) {
+    Array.prototype.findIndex = function (callback) {
+        var i = 0;
+        for ( i = 0; i < this.length; i++ )
+            if (callback(this[i], i, this)) return i;
+        return -1;
+    }
+}
 
 var projectApp = angular.module('project', ['ngCookies', 'ngAnimate', 'ui.bootstrap', 'ngRoute', 'ngSanitize'],  angular_formpost);
 
@@ -126,11 +136,17 @@ projectApp.filter('timediff', function() {
     }
 });
 
+/**
+ * main controller for the project page
+ */
 
-// main controller for the project page
 projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $location, $cookies, $cookieStore, $q, $sce, $anchorScroll, $animate, $sanitize) {
 
-    $scope.getSuggestions = function(type, currentValue) {
+    /**
+     * Retrieves text suggestions for text-edit drop down autocomplete boxes
+     */
+
+    $scope.getAutocompleteSuggestions = function(type, currentValue) {
         var deffered = $q.defer();
 
         $http({method:"GET", url: $scope.urls.xhr_datatypeahead, params : { type: type, value: currentValue}})
@@ -147,17 +163,19 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
 
     var inXHRcall = false;
 
-    // default handling of XHR calls that handles errors and updates commonly-used pages
+    /**
+     * XHR call wrapper that automatically handles errors and auto-updates the page content to reflect project state on server side.
+     */
     $scope._makeXHRCall = function(callparams) {
         if (inXHRcall) {
             if (callparams.data === undefined) {
                 // we simply skip the data refresh calls
-                console.warn("race on XHR, aborted");
+                console.warn("TRC1: race on XHR, aborted");
                 return;
             } else {
                 // we return a promise that we'll solve by reissuing the command later
                 var delayed = $q.defer();
-                console.warn("race on XHR, delayed");
+                console.warn("TRC2: race on XHR, delayed");
                 $interval(function () {$scope._makeXHRCall(callparams).then(function (d) { delayed.resolve(d); });}, 100, 1);
 
                 return delayed.promise;
@@ -178,33 +196,6 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                 deffered.reject(_data.error);
             }
             else {
-
-                if (_data.builds !== undefined) {
-                    var toDelete = [];
-                    // step 1 - delete entries not found
-                    $scope.builds.forEach(function (elem) {
-                        if (-1 == _data.builds.findIndex(function (elemX) { return elemX.id == elem.id && elemX.status == elem.status; })) {
-                            toDelete.push(elem);
-                        }
-                    });
-                    toDelete.forEach(function (elem) {
-                        $scope.builds.splice($scope.builds.indexOf(elem),1);
-                    });
-                    // step 2 - merge new entries
-                    _data.builds.forEach(function (elem) {
-                        var found = false;
-                        var i = 0;
-                        for (i = 0 ; i < $scope.builds.length; i ++) {
-                            if ($scope.builds[i].id > elem.id) continue;
-                            if ($scope.builds[i].id == elem.id) { found=true; break;}
-                            if ($scope.builds[i].id < elem.id) break;
-                        }
-                        if (!found) {
-                            $scope.builds.splice(i, 0, elem);
-                        }
-                    });
-
-                }
                 if (_data.layers !== undefined) {
 
                     var addedLayers = [];
@@ -239,12 +230,59 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                     // step 3 - display alerts.
                     if (addedLayers.length > 0) {
                         $scope.displayAlert($scope.zone2alerts, "You have added <b>"+addedLayers.length+"</b> layer" + ((addedLayers.length>1)?"s: ":": ") + addedLayers.map(function (e) { return "<a href=\""+e.layerdetailurl+"\">"+e.name+"</a>" }).join(", "), "alert-info");
+                        // invalidate error layer data based on current layers
+                        $scope.layersForTargets = {};
                     }
                     if (deletedLayers.length > 0) {
                         $scope.displayAlert($scope.zone2alerts, "You have deleted <b>"+deletedLayers.length+"</b> layer" + ((deletedLayers.length>1)?"s: ":": ") + deletedLayers.map(function (e) { return "<a href=\""+e.layerdetailurl+"\">"+e.name+"</a>" }).join(", "), "alert-info");
+                        // invalidate error layer data based on current layers
+                        $scope.layersForTargets = {};
                     }
 
                 }
+
+
+                if (_data.builds !== undefined) {
+                    var toDelete = [];
+                    // step 1 - delete entries not found
+                    $scope.builds.forEach(function (elem) {
+                        if (-1 == _data.builds.findIndex(function (elemX) { return elemX.id == elem.id && elemX.status == elem.status; })) {
+                            toDelete.push(elem);
+                        }
+                    });
+                    toDelete.forEach(function (elem) {
+                        $scope.builds.splice($scope.builds.indexOf(elem),1);
+                    });
+                    // step 2 - merge new entries
+                    _data.builds.forEach(function (elem) {
+                        var found = false;
+                        var i = 0;
+                        for (i = 0 ; i < $scope.builds.length; i ++) {
+                            if ($scope.builds[i].id > elem.id) continue;
+                            if ($scope.builds[i].id == elem.id) { found=true; break;}
+                            if ($scope.builds[i].id < elem.id) break;
+                        }
+                        if (!found) {
+                            $scope.builds.splice(i, 0, elem);
+                        }
+                    });
+                    // step 3 - merge "Canceled" builds
+                    $scope.canceledBuilds.forEach(function (elem) {
+                        // mock the build object
+                        var found = false;
+                        var i = 0;
+                        for (i = 0; i < $scope.builds.length; i ++) {
+                           if ($scope.builds[i].id > elem.id) continue;
+                            if ($scope.builds[i].id == elem.id) { found=true; break;}
+                            if ($scope.builds[i].id < elem.id) break;
+                        }
+                        if (!found) {
+                            $scope.builds.splice(i, 0, elem);
+                        }
+                    });
+
+                    $scope.fetchLayersForTargets();
+                }
                 if (_data.targets !== undefined) {
                     $scope.targets = _data.targets;
                 }
@@ -267,17 +305,26 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                 deffered.resolve(_data);
             }
         }).error(function(_data, _status, _headers, _config) {
-                console.warn("Failed HTTP XHR request (" + _status + ")" + _data);
+            if (_status == 0) {
+                // the server has gone away
+                alert("The server is not responding. The application will terminate now")
+                $interval.cancel($scope.pollHandle);
+            }
+            else {
                 console.error("Failed HTTP XHR request: ", _data, _status, _headers, _config);
                 inXHRcall = false;
                 deffered.reject(_data.error);
+            }
         });
 
         return deffered.promise;
     }
 
     $scope.layeralert = undefined;
-    // shows user alerts on invalid project data
+    /**
+     * Verifies and shows user alerts on invalid project data
+     */
+
     $scope.validateData = function () {
         if ($scope.layers.length == 0) {
             $scope.layeralert = $scope.displayAlert($scope.zone1alerts, "You need to add some layers to this project. <a href=\""+$scope.urls.layers+"\">View all layers available in Toaster</a> or <a href=\""+$scope.urls.importlayer+"\">import a layer</a>");
@@ -289,14 +336,14 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         }
     }
 
-    $scope.targetExistingBuild = function(targets) {
+    $scope.buildExistingTarget = function(targets) {
         var oldTargetName = $scope.targetName;
         $scope.targetName = targets.map(function(v,i,a){return v.target}).join(' ');
         $scope.targetNamedBuild();
         $scope.targetName = oldTargetName;
     }
 
-    $scope.targetNamedBuild = function(target) {
+    $scope.buildNamedTarget = function(target) {
         if ($scope.targetName === undefined && $scope.targetName1 === undefined){
             console.warn("No target defined, please type in a target name");
             return;
@@ -310,7 +357,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                 targets: $scope.safeTargetName,
             }
         }).then(function (data) {
-            console.warn("received ", data);
+            console.warn("TRC3: received ", data);
             $scope.targetName = undefined;
             $scope.targetName1 = undefined;
             $location.hash('buildslist');
@@ -329,22 +376,20 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         $scope.safeTargetName = $scope.safeTargetName.replace(/\[.*\]/, '').trim();
     }
 
-    $scope.buildCancel = function(id) {
+    $scope.buildCancel = function(build) {
         $scope._makeXHRCall({
             method: "POST", url: $scope.urls.xhr_build,
             data: {
-                buildCancel: id,
+                buildCancel: build.id,
             }
+        }).then( function () {
+            build['status'] = "deleted";
+            $scope.canceledBuilds.push(build);
         });
     }
 
-    $scope.buildDelete = function(id) {
-        $scope._makeXHRCall({
-            method: "POST", url: $scope.urls.xhr_build,
-            data: {
-                buildDelete: id,
-            }
-        });
+    $scope.buildDelete = function(build) {
+        $scope.canceledBuilds.splice($scope.canceledBuilds.indexOf(build), 1);
     }
 
 
@@ -352,6 +397,12 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         $scope.layerAddId = item.id;
     }
 
+
+    $scope.layerAddById = function (id) {
+        $scope.layerAddId = id;
+        $scope.layerAdd();
+    }
+
     $scope.layerAdd = function() {
 
         $http({method:"GET", url: $scope.urls.xhr_datatypeahead, params : { type: "layerdeps", value: $scope.layerAddId }})
@@ -369,7 +420,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                          $scope.selectedItems = (function () { s = {}; for (var i = 0; i < items.length; i++) { s[items[i].id] = true; };return s; })();
 
                          $scope.ok = function() {
-                            console.warn("scope selected is ", $scope.selectedItems);
+                            console.warn("TRC4: scope selected is ", $scope.selectedItems);
                             $modalInstance.close(Object.keys($scope.selectedItems).filter(function (e) { return $scope.selectedItems[e];}));
                          };
 
@@ -378,7 +429,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                          };
 
                          $scope.update = function() {
-                            console.warn("updated ", $scope.selectedItems);
+                            console.warn("TRC5: updated ", $scope.selectedItems);
                          };
                        },
                        resolve: {
@@ -393,7 +444,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
 
                      modalInstance.result.then(function (selectedArray) {
                          selectedArray.push($scope.layerAddId);
-                         console.warn("selected", selectedArray);
+                         console.warn("TRC6: selected", selectedArray);
 
                          $scope._makeXHRCall({
                              method: "POST", url: $scope.urls.xhr_edit,
@@ -429,7 +480,16 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
     }
 
 
-    $scope.test = function(elementid) {
+    /**
+     * Verifies if a project settings change would trigger layer updates. If user confirmation is needed,
+     * a modal dialog will prompt the user to ack the changes. If not, the editProjectSettings() function is called directly.
+     *
+     * Only "versionlayers" change for is supported (and hardcoded) for now.
+     */
+
+    $scope.testProjectSettingsChange = function(elementid) {
+        if (elementid != '#change-project-version') throw "Not implemented";
+
         $http({method:"GET", url: $scope.urls.xhr_datatypeahead, params : { type: "versionlayers", value: $scope.projectVersion }}).
         success(function (_data) {
             if (_data.error != "ok") {
@@ -463,17 +523,21 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                        }
                      });
 
-                     modalInstance.result.then(function () { $scope.edit(elementid)});
+                     modalInstance.result.then(function () { $scope.editProjectSettings(elementid)});
                  } else {
-                    $scope.edit(elementid);
+                    $scope.editProjectSettings(elementid);
                  }
             }
         });
     }
 
-    $scope.edit = function(elementid) {
+    /**
+     * Performs changes to project settings, and updates the user interface accordingly.
+     */
+
+    $scope.editProjectSettings = function(elementid) {
         var data = {};
-        console.warn("edit with ", elementid);
+        console.warn("TRC7: editProjectSettings with ", elementid);
         var alertText = undefined;
         var alertZone = undefined;
         var oldLayers = [];
@@ -508,10 +572,14 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
                 alertText += "<strong>" + $scope.project.release.desc + "</strong>. ";
             }
             if (elementid == '#change-project-version') {
+                $scope.layersForTargets = {};   // invalidate error layers for the targets, since layers changed
+
                 // requirement https://bugzilla.yoctoproject.org/attachment.cgi?id=2229, notification for changed version to include layers
                 $scope.zone2alerts.forEach(function (e) { e.close() });
                 alertText += "This has caused the following changes in your project layers:<ul>"
 
+
+                // warnings - this is executed AFTER the generic XHRCall handling is done; at this point,
                 if (_data.layers !== undefined) {
                     // show added/deleted layer notifications; scope.layers is already updated by this point.
                     var addedLayers = [];
@@ -547,6 +615,10 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
     }
 
 
+    /**
+     * Extracts a command passed through the local path in location, and executes/updates UI based on the command
+     */
+
     $scope.updateDisplayWithCommands = function() {
         cmd = $location.path();
 
@@ -630,6 +702,10 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         });
     }
 
+    /**
+     * Utility function to display an alert to the user
+     */
+
     $scope.displayAlert = function(zone, text, type) {
         if (zone.maxid === undefined) { zone.maxid = 0; }
         var crtid = zone.maxid ++;
@@ -644,6 +720,10 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         return o;
     }
 
+    /**
+     * Toggles display items between label and input box (the edit pencil icon) on selected settings in project page
+     */
+
     $scope.toggle = function(id) {
         $scope.projectName = $scope.project.name;
         $scope.projectVersion = $scope.project.release.id;
@@ -657,34 +737,52 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
         keys = Object.keys($scope.mostBuiltTargets);
         keys = keys.filter(function (e) { if ($scope.mostBuiltTargets[e]) return e });
         return keys.length == 0;
+    }
+
+    /**
+     * Helper function to deal with error string recognition and manipulation
+     */
 
+    $scope.getTargetNameFromErrorMsg = function (msg) {
+        targets = msg.split(" ").splice(2).map(function (v) { return v.replace(/'/g, '')})
+        return targets;
     }
 
-    // init code
-    //
-    $scope.init = function() {
-        $scope.pollHandle = $interval(function () { $scope._makeXHRCall({method: "GET", url: $scope.urls.xhr_edit, data: undefined});}, 2000, 0);
+    $scope.fetchLayersForTargets = function () {
+        $scope.builds.forEach(function (buildrequest) {
+            buildrequest.errors.forEach(function (error) {
+                if (error.msg.indexOf("Nothin") == 0) {
+                    $scope.getTargetNameFromErrorMsg(error.msg).forEach(function (target) {
+                        if ($scope.layersForTargets[target] === undefined)
+                        $scope.getAutocompleteSuggestions("layers4target", target).then( function (list) {
+                            $scope.layersForTargets[target] = list;
+                        })
+                    })
+                }
+            })
+        })
     }
 
-    $scope.init();
-});
 
+    /**
+     * Page init code - just init variables and set the automated refresh
+     */
 
-/**
-    TESTING CODE
-*/
+    $scope.init = function() {
+        $scope.canceledBuilds = [];
+        $scope.layersForTargets = {};
+        $scope.fetchLayersForTargets();
+        $scope.pollHandle = $interval(function () { $scope._makeXHRCall({method: "GET", url: $scope.urls.xhr_edit, data: undefined});}, 2000, 0);
+    }
 
-function test_diff_arrays() {
-    _diffArrays([1,2,3], [2,3,4], function(e,f) { return e==f; }, function(e) {console.warn("added", e)}, function(e) {console.warn("deleted", e);})
-}
+});
 
-// test_diff_arrays();
 
 var s = undefined;
 
 function test_set_alert(text) {
     s = angular.element("div#main").scope();
     s.displayAlert(s.zone3alerts, text);
-    console.warn(s.zone3alerts);
+    console.warn("TRC8: zone3alerts", s.zone3alerts);
     s.$digest();
 }
lib/toaster/toastergui/templates/project.html +36 -14

132 lines not on this page · raw message

lib/toaster/toastergui/views.py +44 -53

149 lines not on this page · raw message

Signature · 1 line
1.9.1