diff options
| -rw-r--r-- | bitbake/lib/toaster/toastergui/static/css/default.css | 27 | ||||
| -rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/projectapp.js | 182 | ||||
| -rw-r--r-- | bitbake/lib/toaster/toastergui/templates/project.html | 62 | ||||
| -rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 41 |
4 files changed, 244 insertions, 68 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/css/default.css b/bitbake/lib/toaster/toastergui/static/css/default.css index fb20fc9241..da9697c408 100644 --- a/bitbake/lib/toaster/toastergui/static/css/default.css +++ b/bitbake/lib/toaster/toastergui/static/css/default.css | |||
| @@ -113,6 +113,9 @@ select { width: auto; } | |||
| 113 | .top-air { margin-top: 40px;} | 113 | .top-air { margin-top: 40px;} |
| 114 | .progress { margin-bottom: 0px; } | 114 | .progress { margin-bottom: 0px; } |
| 115 | .lead .badge { font-size: 18px; font-weight: normal; border-radius: 15px; padding: 9px; } | 115 | .lead .badge { font-size: 18px; font-weight: normal; border-radius: 15px; padding: 9px; } |
| 116 | .lead ol > li, .lead ul > li { | ||
| 117 | line-height: 35px; | ||
| 118 | } | ||
| 116 | .well > .lead, .alert .lead { margin-bottom: 0px; } | 119 | .well > .lead, .alert .lead { margin-bottom: 0px; } |
| 117 | .well-transparent { background-color: transparent; } | 120 | .well-transparent { background-color: transparent; } |
| 118 | .no-results { margin: 10px 0; } | 121 | .no-results { margin: 10px 0; } |
| @@ -191,3 +194,27 @@ dd > span { line-height: 20px; } | |||
| 191 | .new-build form { margin: 5px 0 0; } | 194 | .new-build form { margin: 5px 0 0; } |
| 192 | .new-build .input-append { margin-bottom: 0; } | 195 | .new-build .input-append { margin-bottom: 0; } |
| 193 | #build-selected { margin-top: 15px; } | 196 | #build-selected { margin-top: 15px; } |
| 197 | |||
| 198 | |||
| 199 | .animate-repeat { | ||
| 200 | list-style:none; | ||
| 201 | box-sizing:border-box; | ||
| 202 | } | ||
| 203 | |||
| 204 | .animate-repeat.ng-move, | ||
| 205 | .animate-repeat.ng-enter, | ||
| 206 | .animate-repeat.ng-leave { | ||
| 207 | -webkit-transition:all linear 0.5s; | ||
| 208 | transition:all linear 0.5s; | ||
| 209 | } | ||
| 210 | |||
| 211 | .animate-repeat.ng-leave.ng-leave-active, | ||
| 212 | .animate-repeat.ng-move, | ||
| 213 | .animate-repeat.ng-enter { | ||
| 214 | opacity:0; | ||
| 215 | } | ||
| 216 | |||
| 217 | .animate-repeat.ng-leave, | ||
| 218 | .animate-repeat.ng-enter.ng-enter-active { | ||
| 219 | opacity:1; | ||
| 220 | } | ||
diff --git a/bitbake/lib/toaster/toastergui/static/js/projectapp.js b/bitbake/lib/toaster/toastergui/static/js/projectapp.js index b347451e88..356b92fc5a 100644 --- a/bitbake/lib/toaster/toastergui/static/js/projectapp.js +++ b/bitbake/lib/toaster/toastergui/static/js/projectapp.js | |||
| @@ -74,17 +74,34 @@ angular_formpost = function($httpProvider) { | |||
| 74 | * | 74 | * |
| 75 | * no return | 75 | * no return |
| 76 | */ | 76 | */ |
| 77 | function _diffArrays(oldArray, newArray, compareElements, onAdded, onDeleted ) { | 77 | function _diffArrays(existingArray, newArray, compareElements, onAdded, onDeleted ) { |
| 78 | if (onDeleted !== undefined) { | 78 | var added = []; |
| 79 | oldArray.filter(function (e) { var found = 0; newArray.map(function (f) { if (compareElements(e, f)) {found = 1};}); return !found;}).map(onDeleted); | 79 | var removed = []; |
| 80 | newArray.forEach( function( newElement, newIndex, _newArray) { | ||
| 81 | var existingIndex = existingArray.findIndex(function ( existingElement, _existingIndex, _existingArray ) { | ||
| 82 | return compareElements(newElement, existingElement); | ||
| 83 | }); | ||
| 84 | if (existingIndex < 0 && onAdded) { added.push(newElement); } | ||
| 85 | }); | ||
| 86 | existingArray.forEach( function( existingElement, existingIndex, _existingArray) { | ||
| 87 | var newIndex = newArray.findIndex(function ( newElement, _newIndex, _newArray ) { | ||
| 88 | return compareElements(newElement, existingElement); | ||
| 89 | }); | ||
| 90 | if (newIndex < 0 && onDeleted) { removed.push(existingElement); } | ||
| 91 | }); | ||
| 92 | |||
| 93 | if (onAdded) { | ||
| 94 | added.map(onAdded); | ||
| 80 | } | 95 | } |
| 81 | if (onAdded !== undefined) { | 96 | |
| 82 | newArray.filter(function (e) { var found = 0; oldArray.map(function (f) { if (compareElements(e, f)) {found = 1};}); return !found;}).map(onAdded); | 97 | if (onDeleted) { |
| 98 | removed.map(onDeleted); | ||
| 83 | } | 99 | } |
| 100 | |||
| 84 | } | 101 | } |
| 85 | 102 | ||
| 86 | 103 | ||
| 87 | var projectApp = angular.module('project', ['ui.bootstrap', 'ngCookies'], angular_formpost); | 104 | var projectApp = angular.module('project', ['ngCookies', 'ngAnimate', 'ui.bootstrap' ], angular_formpost); |
| 88 | 105 | ||
| 89 | // modify the template tag markers to prevent conflicts with Django | 106 | // modify the template tag markers to prevent conflicts with Django |
| 90 | projectApp.config(function($interpolateProvider) { | 107 | projectApp.config(function($interpolateProvider) { |
| @@ -111,7 +128,7 @@ projectApp.filter('timediff', function() { | |||
| 111 | 128 | ||
| 112 | 129 | ||
| 113 | // main controller for the project page | 130 | // main controller for the project page |
| 114 | projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $location, $cookies, $q, $sce) { | 131 | projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $location, $cookies, $q, $sce, $anchorScroll, $animate) { |
| 115 | 132 | ||
| 116 | $scope.getSuggestions = function(type, currentValue) { | 133 | $scope.getSuggestions = function(type, currentValue) { |
| 117 | var deffered = $q.defer(); | 134 | var deffered = $q.defer(); |
| @@ -159,40 +176,65 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc | |||
| 159 | deffered.reject(_data.error); | 176 | deffered.reject(_data.error); |
| 160 | } | 177 | } |
| 161 | else { | 178 | else { |
| 162 | // TODO: update screen data if we have fields here | ||
| 163 | 179 | ||
| 164 | if (_data.builds !== undefined) { | 180 | if (_data.builds !== undefined) { |
| 165 | 181 | var toDelete = []; | |
| 166 | var oldbuilds = $scope.builds; | 182 | // step 1 - delete entries not found |
| 167 | $scope.builds = _data.builds; | 183 | $scope.builds.forEach(function (elem) { |
| 168 | 184 | if (-1 == _data.builds.findIndex(function (elemX) { return elemX.id == elem.id && elemX.status == elem.status; })) { | |
| 169 | // identify canceled builds here, so we can display them. | 185 | toDelete.push(elem); |
| 170 | _diffArrays(oldbuilds, $scope.builds, | 186 | } |
| 171 | function (e,f) { return e.id == f.id }, // compare | 187 | }); |
| 172 | undefined, // added | 188 | toDelete.forEach(function (elem) { |
| 173 | function (e) { // deleted | 189 | $scope.builds.splice($scope.builds.indexOf(elem),1); |
| 174 | if (e.status == "deleted") return; | 190 | }); |
| 175 | e.status = "deleted"; | 191 | // step 2 - merge new entries |
| 176 | for (var i = 0; i < $scope.builds.length; i++) { | 192 | _data.builds.forEach(function (elem) { |
| 177 | if ($scope.builds[i].status == "queued" && $scope.builds[i].id > e.id) | 193 | var found = false; |
| 178 | continue; | 194 | var i = 0; |
| 179 | $scope.builds.splice(i, 0, e); | 195 | for (i = 0 ; i < $scope.builds.length; i ++) { |
| 180 | break; | 196 | if ($scope.builds[i].id > elem.id) continue; |
| 181 | } | 197 | if ($scope.builds[i].id == elem.id) { found=true; break;} |
| 182 | }); | 198 | if ($scope.builds[i].id < elem.id) break; |
| 199 | } | ||
| 200 | if (!found) { | ||
| 201 | $scope.builds.splice(i, 0, elem); | ||
| 202 | } | ||
| 203 | }); | ||
| 183 | 204 | ||
| 184 | } | 205 | } |
| 185 | if (_data.layers !== undefined) { | 206 | if (_data.layers !== undefined) { |
| 186 | var oldlayers = $scope.layers; | ||
| 187 | $scope.layers = _data.layers; | ||
| 188 | 207 | ||
| 189 | // show added/deleted layer notifications | ||
| 190 | var addedLayers = []; | 208 | var addedLayers = []; |
| 191 | var deletedLayers = []; | 209 | var deletedLayers = []; |
| 192 | _diffArrays( oldlayers, $scope.layers, function (e, f) { return e.id == f.id }, | ||
| 193 | function (e) { console.log("new layer", e);addedLayers.push(e); }, | ||
| 194 | function (e) { console.log("del layer", e);deletedLayers.push(e); }); | ||
| 195 | 210 | ||
| 211 | // step 1 - delete entries not found | ||
| 212 | $scope.layers.forEach(function (elem) { | ||
| 213 | if (-1 == _data.layers.findIndex(function (elemX) { return elemX.id == elem.id && elemX.name == elem.name; })) { | ||
| 214 | deletedLayers.push(elem); | ||
| 215 | } | ||
| 216 | }); | ||
| 217 | deletedLayers.forEach(function (elem) { | ||
| 218 | $scope.layers.splice($scope.layers.indexOf(elem),1); | ||
| 219 | }); | ||
| 220 | // step 2 - merge new entries | ||
| 221 | _data.layers.forEach(function (elem) { | ||
| 222 | var found = false; | ||
| 223 | var i; | ||
| 224 | for (i = 0 ; i < $scope.layers.length; i ++) { | ||
| 225 | if ($scope.layers[i].orderid < elem.orderid) continue; | ||
| 226 | if ($scope.layers[i].orderid == elem.orderid) { | ||
| 227 | found = true; break; | ||
| 228 | } | ||
| 229 | if ($scope.layers[i].orderid > elem.orderid) break; | ||
| 230 | } | ||
| 231 | if (!found) { | ||
| 232 | $scope.layers.splice(i, 0, elem); | ||
| 233 | addedLayers.push(elem); | ||
| 234 | } | ||
| 235 | }); | ||
| 236 | |||
| 237 | // step 3 - display alerts. | ||
| 196 | if (addedLayers.length > 0) { | 238 | if (addedLayers.length > 0) { |
| 197 | $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"); | 239 | $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"); |
| 198 | } | 240 | } |
| @@ -253,7 +295,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc | |||
| 253 | } | 295 | } |
| 254 | 296 | ||
| 255 | $scope.targetNamedBuild = function(target) { | 297 | $scope.targetNamedBuild = function(target) { |
| 256 | if ($scope.targetName === undefined){ | 298 | if ($scope.targetName === undefined && $scope.targetName1 === undefined){ |
| 257 | alert("No target defined, please type in a target name"); | 299 | alert("No target defined, please type in a target name"); |
| 258 | return; | 300 | return; |
| 259 | } | 301 | } |
| @@ -263,17 +305,26 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc | |||
| 263 | $scope._makeXHRCall({ | 305 | $scope._makeXHRCall({ |
| 264 | method: "POST", url: $scope.urls.xhr_build, | 306 | method: "POST", url: $scope.urls.xhr_build, |
| 265 | data : { | 307 | data : { |
| 266 | targets: $scope.targetName | 308 | targets: $scope.safeTargetName, |
| 267 | } | 309 | } |
| 268 | }).then(function (data) { | 310 | }).then(function (data) { |
| 269 | console.log("received ", data); | 311 | console.log("received ", data); |
| 270 | $scope.targetName = undefined; | 312 | $scope.targetName = undefined; |
| 313 | $scope.targetName1 = undefined; | ||
| 314 | $location.hash('buildslist'); | ||
| 315 | // call $anchorScroll() | ||
| 316 | $anchorScroll(); | ||
| 271 | }); | 317 | }); |
| 272 | } | 318 | } |
| 273 | 319 | ||
| 274 | $scope.sanitizeTargetName = function() { | 320 | $scope.sanitizeTargetName = function() { |
| 275 | if (undefined === $scope.targetName) return; | 321 | $scope.safeTargetName = undefined; |
| 276 | $scope.targetName = $scope.targetName.replace(/\[.*\]/, '').trim(); | 322 | if (undefined === $scope.targetName) $scope.safeTargetName = $scope.targetName1; |
| 323 | if (undefined === $scope.targetName1) $scope.safeTargetName = $scope.targetName; | ||
| 324 | |||
| 325 | if (undefined === $scope.safeTargetName) return; | ||
| 326 | |||
| 327 | $scope.safeTargetName = $scope.safeTargetName.replace(/\[.*\]/, '').trim(); | ||
| 277 | } | 328 | } |
| 278 | 329 | ||
| 279 | $scope.buildCancel = function(id) { | 330 | $scope.buildCancel = function(id) { |
| @@ -285,6 +336,16 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc | |||
| 285 | }); | 336 | }); |
| 286 | } | 337 | } |
| 287 | 338 | ||
| 339 | $scope.buildDelete = function(id) { | ||
| 340 | $scope._makeXHRCall({ | ||
| 341 | method: "POST", url: $scope.urls.xhr_build, | ||
| 342 | data: { | ||
| 343 | buildDelete: id, | ||
| 344 | } | ||
| 345 | }); | ||
| 346 | } | ||
| 347 | |||
| 348 | |||
| 288 | $scope.onLayerSelect = function (item, model, label) { | 349 | $scope.onLayerSelect = function (item, model, label) { |
| 289 | $scope.layerAddId = item.id; | 350 | $scope.layerAddId = item.id; |
| 290 | } | 351 | } |
| @@ -413,6 +474,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc | |||
| 413 | console.log("edit with ", elementid); | 474 | console.log("edit with ", elementid); |
| 414 | var alertText = undefined; | 475 | var alertText = undefined; |
| 415 | var alertZone = undefined; | 476 | var alertZone = undefined; |
| 477 | var oldLayers = []; | ||
| 416 | switch(elementid) { | 478 | switch(elementid) { |
| 417 | case '#select-machine': | 479 | case '#select-machine': |
| 418 | alertText = "You have changed the machine to: <b>" + $scope.machineName + "</b>"; | 480 | alertText = "You have changed the machine to: <b>" + $scope.machineName + "</b>"; |
| @@ -428,25 +490,61 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc | |||
| 428 | data['projectVersion'] = $scope.projectVersion; | 490 | data['projectVersion'] = $scope.projectVersion; |
| 429 | alertText = "You have changed the release to: "; | 491 | alertText = "You have changed the release to: "; |
| 430 | alertZone = $scope.zone3alerts; | 492 | alertZone = $scope.zone3alerts; |
| 493 | // save old layers | ||
| 494 | oldLayers = $scope.layers.slice(0); | ||
| 431 | break; | 495 | break; |
| 432 | default: | 496 | default: |
| 433 | throw "FIXME: implement conversion for element " + elementid; | 497 | throw "FIXME: implement conversion for element " + elementid; |
| 434 | } | 498 | } |
| 435 | 499 | ||
| 436 | console.log("calling edit with ", data); | ||
| 437 | $scope._makeXHRCall({ | 500 | $scope._makeXHRCall({ |
| 438 | method: "POST", url: $scope.urls.xhr_edit, data: data, | 501 | method: "POST", url: $scope.urls.xhr_edit, data: data, |
| 439 | }).then( function () { | 502 | }).then( function (_data) { |
| 440 | $scope.toggle(elementid); | 503 | $scope.toggle(elementid); |
| 441 | if (data['projectVersion'] != undefined) { | 504 | if (data['projectVersion'] != undefined) { |
| 442 | alertText += "<b>" + $scope.project.release.name + "</b>"; | 505 | alertText += "<strong>" + $scope.project.release.desc + "</strong>. "; |
| 506 | } | ||
| 507 | if (elementid == '#change-project-version') { | ||
| 508 | // requirement https://bugzilla.yoctoproject.org/attachment.cgi?id=2229, notification for changed version to include layers | ||
| 509 | $scope.zone2alerts.forEach(function (e) { e.close() }); | ||
| 510 | alertText += "This has caused the following changes in your project layers:<ul>" | ||
| 511 | |||
| 512 | if (_data.layers !== undefined) { | ||
| 513 | // show added/deleted layer notifications; scope.layers is already updated by this point. | ||
| 514 | var addedLayers = []; | ||
| 515 | var deletedLayers = []; | ||
| 516 | _diffArrays( oldLayers, $scope.layers, function (e, f) { return e.id == f.id }, | ||
| 517 | function (e) {addedLayers.push(e); }, | ||
| 518 | function (e) {deletedLayers.push(e); }); | ||
| 519 | |||
| 520 | // some of the deleted layers are actually replaced (changed) layers | ||
| 521 | var changedLayers = []; | ||
| 522 | deletedLayers.forEach(function (e) { | ||
| 523 | if ( -1 < addedLayers.findIndex(function (f) { return f.name == e.name })) { | ||
| 524 | changedLayers.push(e); | ||
| 525 | } | ||
| 526 | }); | ||
| 527 | |||
| 528 | changedLayers.forEach(function (e) { | ||
| 529 | deletedLayers.splice(deletedLayers.indexOf(e), 1); | ||
| 530 | }); | ||
| 531 | |||
| 532 | if (addedLayers.length > 0) { | ||
| 533 | alertText += "<li><strong>"+addedLayers.length+"</strong> layer" + ((addedLayers.length>1)?"s changed: ":" changed: ") + addedLayers.map(function (e) { return "<a href=\""+e.layerdetailurl+"\">"+e.name+"</a>" }).join(", ") + "</li>"; | ||
| 534 | } | ||
| 535 | if (deletedLayers.length > 0) { | ||
| 536 | alertText += "<li><strong>"+deletedLayers.length+"</strong> layer" + ((deletedLayers.length>1)?"s deleted: ":"deleted: ") + deletedLayers.map(function (e) { return "<a href=\""+e.layerdetailurl+"\">"+e.name+"</a>" }).join(", ") + "</li>"; | ||
| 537 | } | ||
| 538 | |||
| 539 | } | ||
| 540 | alertText += "</ul>"; | ||
| 443 | } | 541 | } |
| 444 | $scope.displayAlert(alertZone, alertText, "alert-info"); | 542 | $scope.displayAlert(alertZone, alertText, "alert-info"); |
| 445 | }); | 543 | }); |
| 446 | } | 544 | } |
| 447 | 545 | ||
| 448 | 546 | ||
| 449 | $scope.executeCommands = function() { | 547 | $scope.updateDisplayWithCommands = function() { |
| 450 | cmd = $location.path(); | 548 | cmd = $location.path(); |
| 451 | 549 | ||
| 452 | function _cmdExecuteWithParam(param, f) { | 550 | function _cmdExecuteWithParam(param, f) { |
| @@ -524,7 +622,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc | |||
| 524 | // init code | 622 | // init code |
| 525 | // | 623 | // |
| 526 | $scope.init = function() { | 624 | $scope.init = function() { |
| 527 | $scope.pollHandle = $interval(function () { $scope._makeXHRCall({method: "GET", url: $scope.urls.xhr_edit, data: undefined});}, 4000, 0); | 625 | $scope.pollHandle = $interval(function () { $scope._makeXHRCall({method: "GET", url: $scope.urls.xhr_edit, data: undefined});}, 2000, 0); |
| 528 | } | 626 | } |
| 529 | 627 | ||
| 530 | $scope.init(); | 628 | $scope.init(); |
| @@ -539,6 +637,8 @@ function test_diff_arrays() { | |||
| 539 | _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);}) | 637 | _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);}) |
| 540 | } | 638 | } |
| 541 | 639 | ||
| 640 | // test_diff_arrays(); | ||
| 641 | |||
| 542 | var s = undefined; | 642 | var s = undefined; |
| 543 | 643 | ||
| 544 | function test_set_alert(text) { | 644 | function test_set_alert(text) { |
diff --git a/bitbake/lib/toaster/toastergui/templates/project.html b/bitbake/lib/toaster/toastergui/templates/project.html index 6a812834d3..a8f2d6ad4f 100644 --- a/bitbake/lib/toaster/toastergui/templates/project.html +++ b/bitbake/lib/toaster/toastergui/templates/project.html | |||
| @@ -9,6 +9,7 @@ vim: expandtab tabstop=2 | |||
| 9 | 9 | ||
| 10 | {% block projectinfomain %} | 10 | {% block projectinfomain %} |
| 11 | <script src="{% static "js/angular.min.js" %}"></script> | 11 | <script src="{% static "js/angular.min.js" %}"></script> |
| 12 | <script src="{% static "js/angular-animate.min.js" %}"></script> | ||
| 12 | <script src="{% static "js/angular-cookies.min.js" %}"></script> | 13 | <script src="{% static "js/angular-cookies.min.js" %}"></script> |
| 13 | <script src="{% static "js/ui-bootstrap-tpls-0.11.0.js" %}"></script> | 14 | <script src="{% static "js/ui-bootstrap-tpls-0.11.0.js" %}"></script> |
| 14 | 15 | ||
| @@ -105,19 +106,21 @@ vim: expandtab tabstop=2 | |||
| 105 | </form> | 106 | </form> |
| 106 | </div> | 107 | </div> |
| 107 | 108 | ||
| 109 | <a id="buildslist"></a> | ||
| 108 | <h2 class="air" ng-if="builds.length">Latest builds</h2> | 110 | <h2 class="air" ng-if="builds.length">Latest builds</h2> |
| 109 | 111 | <div class="animate-repeat alert" ng-repeat="b in builds track by b.id" ng-class="{'queued':'alert-info', 'deleted':'alert-info', 'in progress': 'alert-info', 'failed':'alert-error', 'completed':{'In Progress':'alert-info', 'Succeeded':'alert-success', 'Failed':'alert-error'}[b.build[0].status]}[b.status]"> | |
| 110 | <div class="alert" ng-repeat="b in builds" ng-class="{'queued':'alert-info', 'deleted':'alert-info', 'in progress': 'alert-info', 'failed':'alert-error', 'completed':{'In Progress':'alert-info', 'Succeeded':'alert-success', 'Failed':'alert-error'}[b.build[0].status]}[b.status]" > | ||
| 111 | <div class="row-fluid"> | 112 | <div class="row-fluid"> |
| 112 | <switch ng-switch="b.status"> | 113 | <switch ng-switch="b.status"> |
| 114 | |||
| 113 | <case ng-switch-when="failed"> | 115 | <case ng-switch-when="failed"> |
| 114 | <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> | 116 | <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span></div> |
| 115 | <div class="row-fluid"> | 117 | <div class="row-fluid"> |
| 116 | <div class="air well" ng-repeat="e in b.errors"> | 118 | <div class="air well" ng-repeat="e in b.errors"> |
| 117 | {[e.type]}: <pre>{[e.msg]}</pre> | 119 | Error type {[e.type]}: <pre>{[e.msg]}</pre> |
| 118 | </div> | 120 | </div> |
| 119 | </div> | 121 | </div> |
| 120 | </case> | 122 | </case> |
| 123 | |||
| 121 | <case ng-switch-when="queued"> | 124 | <case ng-switch-when="queued"> |
| 122 | <div class="lead span5"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> | 125 | <div class="lead span5"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> |
| 123 | <div class="span4 lead" >Build queued | 126 | <div class="span4 lead" >Build queued |
| @@ -125,6 +128,7 @@ vim: expandtab tabstop=2 | |||
| 125 | </div> | 128 | </div> |
| 126 | <button class="btn pull-right btn-info" ng-click="buildCancel(b.id)">Cancel</button> | 129 | <button class="btn pull-right btn-info" ng-click="buildCancel(b.id)">Cancel</button> |
| 127 | </case> | 130 | </case> |
| 131 | |||
| 128 | <case ng-switch-when="created"> | 132 | <case ng-switch-when="created"> |
| 129 | <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> | 133 | <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> |
| 130 | <div class="span6" > | 134 | <div class="span6" > |
| @@ -132,35 +136,56 @@ vim: expandtab tabstop=2 | |||
| 132 | </div> | 136 | </div> |
| 133 | <button class="btn pull-right btn-info" ng-click="buildCancel(b.id)">Cancel</button> | 137 | <button class="btn pull-right btn-info" ng-click="buildCancel(b.id)">Cancel</button> |
| 134 | </case> | 138 | </case> |
| 139 | |||
| 135 | <case ng-switch-when="deleted"> | 140 | <case ng-switch-when="deleted"> |
| 136 | <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> | 141 | <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> |
| 137 | <div class="span6" id="{[b.id]}-deleted" > | 142 | <div class="span6" id="{[b.id]}-deleted" > |
| 138 | <span class="lead">Build deleted</span> | 143 | <span class="lead">Build deleted</span> |
| 139 | </div> | 144 | </div> |
| 140 | <button class="btn pull-right btn-info" ng-click="builds.splice(builds.indexOf(b), 1)">Close</button> | 145 | <button class="btn pull-right btn-info" ng-click="buildDelete(b.id)">Close</button> |
| 141 | </case> | 146 | </case> |
| 147 | |||
| 148 | |||
| 142 | <case ng-switch-when="in progress"> | 149 | <case ng-switch-when="in progress"> |
| 143 | <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> | 150 | <switch ng-switch="b.build.length"> |
| 144 | <div class="span4" > | 151 | <case ng-switch-when="0"> |
| 145 | <div class="progress" style="margin-top:5px;" data-toggle="tooltip" tooltip="{[b.build[0].completeper]}% of tasks complete"> | 152 | <div class="lead span5"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> |
| 146 | <div style="width: {[b.build[0].completeper]}%;" class="bar"></div> | 153 | <div class="span4 lead"> |
| 154 | Checking out layers | ||
| 147 | </div> | 155 | </div> |
| 148 | </div> | 156 | </case> |
| 149 | <div class="lead pull-right">ETA: at {[b.build[0].eta|date:"shortDate"]}</div> | 157 | <case ng-switch-default=""> |
| 158 | <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div> | ||
| 159 | <div class="span4 offset1" > | ||
| 160 | <div class="progress" style="margin-top:5px;" data-toggle="tooltip" tooltip="{[b.build[0].completeper]}% of tasks complete"> | ||
| 161 | <div style="width: {[b.build[0].completeper]}%;" class="bar"></div> | ||
| 162 | </div> | ||
| 163 | </div> | ||
| 164 | <div class="text-right lead">ETA: {[b.build[0].eta|date:"HH:mm:ss"]}</div> | ||
| 165 | </case> | ||
| 150 | </case> | 166 | </case> |
| 167 | |||
| 168 | |||
| 151 | <case ng-switch-when="completed"> | 169 | <case ng-switch-when="completed"> |
| 152 | <div class="lead span3"><a href="{[b.build[0].build_page_url]}"><span ng-repeat="t in b.targets" ng-include src="'target_display'"></span></a></div> | 170 | <div class="lead span3"><a href="{[b.build[0].build_page_url]}"><span ng-repeat="t in b.targets" ng-include src="'target_display'"></span></a></div> |
| 153 | <div class="span2 lead"> | 171 | <div class="span2 lead"> |
| 154 | {[b.build[0].completed_on|date:'dd/MM/yy HH:mm']} | 172 | <ngif ng-if="b.build[0].completed_on - todaydate > 0"> |
| 173 | {[b.build[0].completed_on|date:'HH:mm']} | ||
| 174 | </ngif> | ||
| 175 | <ngif ng-if="b.build[0].completed_on - todaydate < 0"> | ||
| 176 | {[b.build[0].completed_on|date:'dd/MM/yy HH:mm']} | ||
| 177 | </ngif> | ||
| 155 | </div> | 178 | </div> |
| 156 | <div class="span2"><span><a href="{[b.build[0].build_page_url]}#errors" class="lead error" ng-if="b.build[0].errors">{[b.build[0].errors]}</a></span></div> | 179 | <div class="span2"><span><a href="{[b.build[0].build_page_url]}#errors" class="lead error" ng-if="b.build[0].errors">{[b.build[0].errors]}</a></span></div> |
| 157 | <div class="span2"><span><a href="{[b.build[0].build_page_url]}#warnings" class="lead warning" ng-if="b.build[0].warnings">{[b.build[0].warnings]}</a></span></div> | 180 | <div class="span2"><span><a href="{[b.build[0].build_page_url]}#warnings" class="lead warning" ng-if="b.build[0].warnings">{[b.build[0].warnings]}</a></span></div> |
| 158 | <div> <span class="lead">Build time: {[b.build[0].build_time|timediff]}</span> | 181 | <div> <span class="lead">Build time: <a href="{[b.build[0].build_time_page_url]}">{[b.build[0].build_time|timediff]}</a></span> |
| 159 | <button class="btn pull-right" ng-class="{'Succeeded': 'btn-success', 'Failed': 'btn-danger'}[b.build[0].status]" | 182 | <button class="btn pull-right" ng-class="{'Succeeded': 'btn-success', 'Failed': 'btn-danger'}[b.build[0].status]" |
| 160 | ng-click="targetExistingBuild(b.targets)">Run again</button> | 183 | ng-click="targetExistingBuild(b.targets)">Run again</button> |
| 161 | 184 | ||
| 162 | </div> | 185 | </div> |
| 163 | </case> | 186 | </case> |
| 187 | |||
| 188 | |||
| 164 | <case ng-switch-default=""> | 189 | <case ng-switch-default=""> |
| 165 | <div>FIXME!</div> | 190 | <div>FIXME!</div> |
| 166 | </case> | 191 | </case> |
| @@ -206,7 +231,7 @@ vim: expandtab tabstop=2 | |||
| 206 | </form> | 231 | </form> |
| 207 | <p><a href="{% url 'layers' %}">View all layers</a> | <a href="{% url 'importlayer' %}">Import layer</a></p> | 232 | <p><a href="{% url 'layers' %}">View all layers</a> | <a href="{% url 'importlayer' %}">Import layer</a></p> |
| 208 | <ul class="unstyled configuration-list"> | 233 | <ul class="unstyled configuration-list"> |
| 209 | <li ng-repeat="l in layers"> | 234 | <li ng-repeat="l in layers track by l.id" class="animate-repeat"> |
| 210 | <a href="{[l.layerdetailurl]}" target="_#" class="layer-info" data-toggle="tooltip" tooltip="{[l.branch.layersource]} | {[l.branch.name]}">{[l.name]} </a> | 235 | <a href="{[l.layerdetailurl]}" target="_#" class="layer-info" data-toggle="tooltip" tooltip="{[l.branch.layersource]} | {[l.branch.name]}">{[l.name]} </a> |
| 211 | <i class="icon-trash" ng-click="layerDel(l.id)" tooltip="Delete"></i> | 236 | <i class="icon-trash" ng-click="layerDel(l.id)" tooltip="Delete"></i> |
| 212 | </li> | 237 | </li> |
| @@ -221,8 +246,8 @@ vim: expandtab tabstop=2 | |||
| 221 | <i class="icon-question-sign get-help heading-help" title="What you build, often a recipe producing a root file system file (an image). Something like <code>core-image-minimal</code> or <code>core-image-sato</code>"></i> | 246 | <i class="icon-question-sign get-help heading-help" title="What you build, often a recipe producing a root file system file (an image). Something like <code>core-image-minimal</code> or <code>core-image-sato</code>"></i> |
| 222 | </h3> | 247 | </h3> |
| 223 | <form ng-submit="targetNamedBuild()" class="input-append"> | 248 | <form ng-submit="targetNamedBuild()" class="input-append"> |
| 224 | <input type="text" class="input-xlarge" placeholder="Type the target(s) you want to build" autocomplete="off" data-minLength="1" ng-model="targetName" typeahead="e.name for e in getSuggestions('targets', $viewValue)|filter:$viewValue" typeahead-template-url="suggestion_details" ng-disabled="!layers.length"> | 249 | <input type="text" class="input-xlarge" placeholder="Type the target(s) you want to build" autocomplete="off" data-minLength="1" ng-model="targetName1" typeahead="e.name for e in getSuggestions('targets', $viewValue)|filter:$viewValue" typeahead-template-url="suggestion_details" ng-disabled="!layers.length"> |
| 225 | <button type="submit" id="build-button" class="btn btn-primary" ng-disabled="!targetName.length"> | 250 | <button type="submit" id="build-button" class="btn btn-primary" ng-disabled="!targetName1.length"> |
| 226 | Build </button> | 251 | Build </button> |
| 227 | {% csrf_token %} | 252 | {% csrf_token %} |
| 228 | </form> | 253 | </form> |
| @@ -343,13 +368,16 @@ angular.element(document).ready(function() { | |||
| 343 | scope.machine = {{machine|safe}}; | 368 | scope.machine = {{machine|safe}}; |
| 344 | scope.releases = {{releases|safe}}; | 369 | scope.releases = {{releases|safe}}; |
| 345 | 370 | ||
| 371 | var now = (new Date()).getTime(); | ||
| 372 | scope.todaydate = now - (now % 86400000); | ||
| 373 | |||
| 346 | scope.zone1alerts = []; | 374 | scope.zone1alerts = []; |
| 347 | scope.zone2alerts = []; | 375 | scope.zone2alerts = []; |
| 348 | scope.zone3alerts = []; | 376 | scope.zone3alerts = []; |
| 349 | 377 | ||
| 350 | scope.mostBuiltTargets = {}; | 378 | scope.mostBuiltTargets = {}; |
| 351 | 379 | ||
| 352 | scope.executeCommands(); | 380 | scope.updateDisplayWithCommands(); |
| 353 | scope.validateData(); | 381 | scope.validateData(); |
| 354 | 382 | ||
| 355 | scope.$digest(); | 383 | scope.$digest(); |
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index fb8075067a..3b29dbcfb2 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
| @@ -1943,11 +1943,13 @@ if toastermain.settings.MANAGED: | |||
| 1943 | "completed_on" : y.completed_on.strftime('%s')+"000", | 1943 | "completed_on" : y.completed_on.strftime('%s')+"000", |
| 1944 | "build_time" : (y.completed_on - y.started_on).total_seconds(), | 1944 | "build_time" : (y.completed_on - y.started_on).total_seconds(), |
| 1945 | "build_page_url" : reverse('builddashboard', args=(y.pk,)), | 1945 | "build_page_url" : reverse('builddashboard', args=(y.pk,)), |
| 1946 | 'build_time_page_url': reverse('buildtime', args=(y.pk,)), | ||
| 1946 | "errors": y.errors_no, | 1947 | "errors": y.errors_no, |
| 1947 | "warnings": y.warnings_no, | 1948 | "warnings": y.warnings_no, |
| 1948 | "completeper": y.completeper(), | 1949 | "completeper": y.completeper(), |
| 1949 | "eta": y.eta().ctime()}, Build.objects.filter(buildrequest = x)), | 1950 | "eta": y.eta().strftime('%s')+"000"}, Build.objects.filter(buildrequest = x)), |
| 1950 | }, prj.buildrequest_set.order_by("-pk")[:5]) | 1951 | }, list(prj.buildrequest_set.filter(Q(state__lt=BuildRequest.REQ_COMPLETED) or Q(state=BuildRequest.REQ_DELETED)).order_by("-pk")) + |
| 1952 | list(prj.buildrequest_set.filter(state__in=[BuildRequest.REQ_COMPLETED, BuildRequest.REQ_FAILED]).order_by("-pk")[:3])) | ||
| 1951 | 1953 | ||
| 1952 | 1954 | ||
| 1953 | # Shows the edit project page | 1955 | # Shows the edit project page |
| @@ -1979,10 +1981,17 @@ if toastermain.settings.MANAGED: | |||
| 1979 | context = { | 1981 | context = { |
| 1980 | "project" : prj, | 1982 | "project" : prj, |
| 1981 | "completedbuilds": Build.objects.filter(project = prj).exclude(outcome = Build.IN_PROGRESS), | 1983 | "completedbuilds": Build.objects.filter(project = prj).exclude(outcome = Build.IN_PROGRESS), |
| 1982 | "prj" : json.dumps({"name": prj.name, "release": { "id": prj.release.pk, "name": prj.release.name}}), | 1984 | "prj" : json.dumps({"name": prj.name, "release": { "id": prj.release.pk, "name": prj.release.name, "desc": prj.release.description}}), |
| 1983 | #"buildrequests" : prj.buildrequest_set.filter(state=BuildRequest.REQ_QUEUED), | 1985 | #"buildrequests" : prj.buildrequest_set.filter(state=BuildRequest.REQ_QUEUED), |
| 1984 | "builds" : json.dumps(_project_recent_build_list(prj)), | 1986 | "builds" : json.dumps(_project_recent_build_list(prj)), |
| 1985 | "layers" : json.dumps(map(lambda x: {"id": x.layercommit.pk, "name" : x.layercommit.layer.name, "url": x.layercommit.layer.layer_index_url, "layerdetailurl": reverse("layerdetails", args=(x.layercommit.layer.pk,)), "branch" : { "name" : x.layercommit.up_branch.name, "layersource" : x.layercommit.up_branch.layer_source.name}}, prj.projectlayer_set.all())), | 1987 | "layers" : json.dumps(map(lambda x: { |
| 1988 | "id": x.layercommit.pk, | ||
| 1989 | "orderid": x.pk, | ||
| 1990 | "name" : x.layercommit.layer.name, | ||
| 1991 | "url": x.layercommit.layer.layer_index_url, | ||
| 1992 | "layerdetailurl": reverse("layerdetails", args=(x.layercommit.layer.pk,)), | ||
| 1993 | "branch" : { "name" : x.layercommit.up_branch.name, "layersource" : x.layercommit.up_branch.layer_source.name}}, | ||
| 1994 | prj.projectlayer_set.all().order_by("id"))), | ||
| 1986 | "targets" : json.dumps(map(lambda x: {"target" : x.target, "task" : x.task, "pk": x.pk}, prj.projecttarget_set.all())), | 1995 | "targets" : json.dumps(map(lambda x: {"target" : x.target, "task" : x.task, "pk": x.pk}, prj.projecttarget_set.all())), |
| 1987 | "freqtargets": json.dumps(freqtargets), | 1996 | "freqtargets": json.dumps(freqtargets), |
| 1988 | "releases": json.dumps(map(lambda x: {"id": x.pk, "name": x.name}, Release.objects.all())), | 1997 | "releases": json.dumps(map(lambda x: {"id": x.pk, "name": x.name}, Release.objects.all())), |
| @@ -2012,12 +2021,17 @@ if toastermain.settings.MANAGED: | |||
| 2012 | for i in request.POST['buildCancel'].strip().split(" "): | 2021 | for i in request.POST['buildCancel'].strip().split(" "): |
| 2013 | try: | 2022 | try: |
| 2014 | br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED) | 2023 | br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED) |
| 2015 | print "selected for delete", br.pk | 2024 | br.state = BuildRequest.REQ_DELETED |
| 2016 | br.delete() | 2025 | br.save() |
| 2017 | print "selected for delete", br.pk | ||
| 2018 | except BuildRequest.DoesNotExist: | 2026 | except BuildRequest.DoesNotExist: |
| 2019 | pass | 2027 | pass |
| 2020 | 2028 | ||
| 2029 | if 'buildDelete' in request.POST: | ||
| 2030 | for i in request.POST['buildDelete'].strip().split(" "): | ||
| 2031 | try: | ||
| 2032 | br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_DELETED).delete() | ||
| 2033 | except BuildRequest.DoesNotExist: | ||
| 2034 | pass | ||
| 2021 | 2035 | ||
| 2022 | if 'targets' in request.POST: | 2036 | if 'targets' in request.POST: |
| 2023 | ProjectTarget.objects.filter(project = prj).delete() | 2037 | ProjectTarget.objects.filter(project = prj).delete() |
| @@ -2054,9 +2068,10 @@ if toastermain.settings.MANAGED: | |||
| 2054 | prj.name = request.POST['projectName'] | 2068 | prj.name = request.POST['projectName'] |
| 2055 | prj.save(); | 2069 | prj.save(); |
| 2056 | 2070 | ||
| 2057 | |||
| 2058 | if 'projectVersion' in request.POST: | 2071 | if 'projectVersion' in request.POST: |
| 2059 | prj.release = Release.objects.get(pk = request.POST['projectVersion']) | 2072 | prj.release = Release.objects.get(pk = request.POST['projectVersion']) |
| 2073 | # we need to change the bitbake version | ||
| 2074 | prj.bitbake_version = prj.release.bitbake_version | ||
| 2060 | prj.save() | 2075 | prj.save() |
| 2061 | # we need to change the layers | 2076 | # we need to change the layers |
| 2062 | for i in prj.projectlayer_set.all(): | 2077 | for i in prj.projectlayer_set.all(): |
| @@ -2067,13 +2082,19 @@ if toastermain.settings.MANAGED: | |||
| 2067 | # get rid of the old entry | 2082 | # get rid of the old entry |
| 2068 | i.delete() | 2083 | i.delete() |
| 2069 | 2084 | ||
| 2085 | if 'machineName' in request.POST: | ||
| 2086 | machinevar = prj.projectvariable_set.get(name="MACHINE") | ||
| 2087 | machinevar.value=request.POST['machineName'] | ||
| 2088 | machinevar.save() | ||
| 2089 | |||
| 2070 | # return all project settings | 2090 | # return all project settings |
| 2071 | return HttpResponse(json.dumps( { | 2091 | return HttpResponse(json.dumps( { |
| 2072 | "error": "ok", | 2092 | "error": "ok", |
| 2073 | "layers" : map(lambda x: {"id": x.layercommit.pk, "name" : x.layercommit.layer.name, "url": x.layercommit.layer.layer_index_url, "layerdetailurl": reverse("layerdetails", args=(x.layercommit.layer.pk,)), "branch" : { "name" : x.layercommit.up_branch.name, "layersource" : x.layercommit.up_branch.layer_source.name}}, prj.projectlayer_set.all()), | 2093 | "layers" : map(lambda x: {"id": x.layercommit.pk, "orderid" : x.pk, "name" : x.layercommit.layer.name, "url": x.layercommit.layer.layer_index_url, "layerdetailurl": reverse("layerdetails", args=(x.layercommit.layer.pk,)), "branch" : { "name" : x.layercommit.up_branch.name, "layersource" : x.layercommit.up_branch.layer_source.name}}, prj.projectlayer_set.all().order_by("id")), |
| 2074 | "builds" : _project_recent_build_list(prj), | 2094 | "builds" : _project_recent_build_list(prj), |
| 2075 | "variables": map(lambda x: (x.name, x.value), prj.projectvariable_set.all()), | 2095 | "variables": map(lambda x: (x.name, x.value), prj.projectvariable_set.all()), |
| 2076 | "prj": {"name": prj.name, "release": { "id": prj.release.pk, "name": prj.release.name}}, | 2096 | "machine": {"name": prj.projectvariable_set.get(name="MACHINE").value}, |
| 2097 | "prj": {"name": prj.name, "release": { "id": prj.release.pk, "name": prj.release.name, "desc": prj.release.description}}, | ||
| 2077 | }), content_type = "application/json") | 2098 | }), content_type = "application/json") |
| 2078 | 2099 | ||
| 2079 | except Exception as e: | 2100 | except Exception as e: |
