Toaster patchset pull request
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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 3/5 toaster: do not launch web browser on noweb option
In reply to Alex DAMIANFrom: 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
@@ -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
PATCH 4/5 toaster: branch name priority resolution
In reply to Alex DAMIANFrom: 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
@@ -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
PATCH 5/5 toaster: implementation of project page
In reply to Alex DAMIANFrom: 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
@@ -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