summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/toastergui')
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/base.js6
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/importlayer.js6
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/layerdetails.js4
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/libtoaster.js8
-rw-r--r--bitbake/lib/toaster/toastergui/templates/base.html2
-rw-r--r--bitbake/lib/toaster/toastergui/templates/layerdetails.html4
-rw-r--r--bitbake/lib/toaster/toastergui/templates/managed_mrb_section.html2
-rw-r--r--bitbake/lib/toaster/toastergui/templates/project.html52
-rw-r--r--bitbake/lib/toaster/toastergui/templates/runagain.html2
-rw-r--r--bitbake/lib/toaster/toastergui/templatetags/projecttags.py2
-rw-r--r--bitbake/lib/toaster/toastergui/tests.py6
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py8
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py208
-rw-r--r--bitbake/lib/toaster/toastergui/widgets.py6
14 files changed, 118 insertions, 198 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/base.js b/bitbake/lib/toaster/toastergui/static/js/base.js
index 9c8d01ef5a..747442cc9e 100644
--- a/bitbake/lib/toaster/toastergui/static/js/base.js
+++ b/bitbake/lib/toaster/toastergui/static/js/base.js
@@ -89,7 +89,7 @@ function basePageInit (ctx) {
89 if (!selectedTarget) 89 if (!selectedTarget)
90 selectedTarget = { name: newBuildTargetInput.val() }; 90 selectedTarget = { name: newBuildTargetInput.val() };
91 /* fire and forget */ 91 /* fire and forget */
92 libtoaster.startABuild(ctx.projectBuildUrl, libtoaster.ctx.projectId, selectedTarget.name, null, null); 92 libtoaster.startABuild(ctx.projectBuildsUrl, libtoaster.ctx.projectId, selectedTarget.name, null, null);
93 window.location.replace(libtoaster.ctx.projectPageUrl); 93 window.location.replace(libtoaster.ctx.projectPageUrl);
94 }); 94 });
95 95
@@ -105,13 +105,13 @@ function basePageInit (ctx) {
105 libtoaster.ctx.projectName = selectedProject.name; 105 libtoaster.ctx.projectName = selectedProject.name;
106 libtoaster.ctx.projectId = selectedProject.id; 106 libtoaster.ctx.projectId = selectedProject.id;
107 107
108 ctx.projectBuildUrl = selectedProject.projectBuildUrl; 108 ctx.projectBuildsUrl = selectedProject.projectBuildsUrl;
109 109
110 /* we can create a target typeahead only after we have a project selected */ 110 /* we can create a target typeahead only after we have a project selected */
111 newBuildTargetInput.prop("disabled", false); 111 newBuildTargetInput.prop("disabled", false);
112 newBuildTargetBuildBtn.prop("disabled", false); 112 newBuildTargetBuildBtn.prop("disabled", false);
113 113
114 libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.xhrProjectDataTypeaheadUrl, { type : "targets" }, function(item){ 114 libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.projectTargetsUrl, { format: "json" }, function(item){
115 /* successfully selected a target */ 115 /* successfully selected a target */
116 selectedTarget = item; 116 selectedTarget = item;
117 }); 117 });
diff --git a/bitbake/lib/toaster/toastergui/static/js/importlayer.js b/bitbake/lib/toaster/toastergui/static/js/importlayer.js
index beb2ede3dc..e1fc5c5187 100644
--- a/bitbake/lib/toaster/toastergui/static/js/importlayer.js
+++ b/bitbake/lib/toaster/toastergui/static/js/importlayer.js
@@ -18,7 +18,7 @@ function importLayerPageInit (ctx) {
18 18
19 $("#new-project-button").hide(); 19 $("#new-project-button").hide();
20 20
21 libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" }, function(item){ 21 libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.projectLayersUrl, { include_added: "true" }, function(item){
22 currentLayerDepSelection = item; 22 currentLayerDepSelection = item;
23 23
24 layerDepBtn.removeAttr("disabled"); 24 layerDepBtn.removeAttr("disabled");
@@ -28,7 +28,7 @@ function importLayerPageInit (ctx) {
28 /* We automatically add "openembedded-core" layer for convenience as a 28 /* We automatically add "openembedded-core" layer for convenience as a
29 * dependency as pretty much all layers depend on this one 29 * dependency as pretty much all layers depend on this one
30 */ 30 */
31 $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" , value: "openembedded-core" }, function(layer) { 31 $.getJSON(libtoaster.ctx.projectLayersUrl, { include_added: "true" , search: "openembedded-core" }, function(layer) {
32 if (layer.list.length == 1) { 32 if (layer.list.length == 1) {
33 currentLayerDepSelection = layer.list[0]; 33 currentLayerDepSelection = layer.list[0];
34 layerDepBtn.click(); 34 layerDepBtn.click();
@@ -211,7 +211,7 @@ function importLayerPageInit (ctx) {
211 var name = $(this).val(); 211 var name = $(this).val();
212 212
213 /* Check if the layer name exists */ 213 /* Check if the layer name exists */
214 $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" , value: name }, function(layer) { 214 $.getJSON(libtoaster.ctx.projectLayersUrl, { include_added: "true" , search: name }, function(layer) {
215 if (layer.list.length > 0) { 215 if (layer.list.length > 0) {
216 for (var i in layer.list){ 216 for (var i in layer.list){
217 if (layer.list[i].name == name) { 217 if (layer.list[i].name == name) {
diff --git a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
index 8e14b8f277..ab781829cd 100644
--- a/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
+++ b/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
@@ -9,7 +9,7 @@ function layerDetailsPageInit (ctx) {
9 var addRmLayerBtn = $("#add-remove-layer-btn"); 9 var addRmLayerBtn = $("#add-remove-layer-btn");
10 10
11 /* setup the dependencies typeahead */ 11 /* setup the dependencies typeahead */
12 libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.xhrProjectDataTypeaheadUrl, { type : "layers", project_id: libtoaster.ctx.projectId, include_added: "true" }, function(item){ 12 libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.projectLayersUrl, { include_added: "true" }, function(item){
13 currentLayerDepSelection = item; 13 currentLayerDepSelection = item;
14 14
15 layerDepBtn.removeAttr("disabled"); 15 layerDepBtn.removeAttr("disabled");
@@ -170,7 +170,7 @@ function layerDetailsPageInit (ctx) {
170 $(".build-target-btn").click(function(){ 170 $(".build-target-btn").click(function(){
171 /* fire a build */ 171 /* fire a build */
172 var target = $(this).data('target-name'); 172 var target = $(this).data('target-name');
173 libtoaster.startABuild(ctx.projectBuildUrl, libtoaster.ctx.projectId, target, null, null); 173 libtoaster.startABuild(ctx.projectBuildsUrl, libtoaster.ctx.projectId, target, null, null);
174 window.location.replace(libtoaster.ctx.projectPageUrl); 174 window.location.replace(libtoaster.ctx.projectPageUrl);
175 }); 175 });
176 }); 176 });
diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
index 87910299a5..2a9a790693 100644
--- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
+++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
@@ -93,7 +93,7 @@ var libtoaster = (function (){
93 } 93 }
94 94
95 /* cancelABuild: 95 /* cancelABuild:
96 * url: xhr_projectbuild 96 * url: projectbuilds
97 * builds_ids: space separated list of build request ids 97 * builds_ids: space separated list of build request ids
98 * onsuccess: callback for successful execution 98 * onsuccess: callback for successful execution
99 * onfail: callback for failed execution 99 * onfail: callback for failed execution
@@ -172,15 +172,15 @@ var libtoaster = (function (){
172 172
173 function _getLayerDepsForProject(projectId, layerId, onSuccess, onFail){ 173 function _getLayerDepsForProject(projectId, layerId, onSuccess, onFail){
174 /* Check for dependencies not in the current project */ 174 /* Check for dependencies not in the current project */
175 $.getJSON(libtoaster.ctx.xhrProjectDataTypeaheadUrl, 175 $.getJSON(libtoaster.ctx.projectLayersUrl,
176 { type: 'layerdeps', 'value': layerId , project_id: projectId }, 176 { format: 'json', search: layerId },
177 function(data) { 177 function(data) {
178 if (data.error != "ok") { 178 if (data.error != "ok") {
179 console.log(data.error); 179 console.log(data.error);
180 if (onFail !== undefined) 180 if (onFail !== undefined)
181 onFail(data); 181 onFail(data);
182 } else { 182 } else {
183 onSuccess(data); 183 onSuccess(data.layerdeps);
184 } 184 }
185 }, function() { 185 }, function() {
186 console.log("E: Failed to make request"); 186 console.log("E: Failed to make request");
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html
index 5d51bc3c95..7fee26eb42 100644
--- a/bitbake/lib/toaster/toastergui/templates/base.html
+++ b/bitbake/lib/toaster/toastergui/templates/base.html
@@ -33,12 +33,10 @@
33 htmlUrl : "{% static 'html/' %}", 33 htmlUrl : "{% static 'html/' %}",
34 projectsUrl : "{% url 'all-projects' %}", 34 projectsUrl : "{% url 'all-projects' %}",
35 {% if project.id %} 35 {% if project.id %}
36 xhrProjectDataTypeaheadUrl : "{% url 'xhr_datatypeahead' project.id %}",
37 projectPageUrl : "{% url 'project' project.id %}", 36 projectPageUrl : "{% url 'project' project.id %}",
38 projectName : "{{project.name}}", 37 projectName : "{{project.name}}",
39 projectId : {{project.id}}, 38 projectId : {{project.id}},
40 {% else %} 39 {% else %}
41 xhrProjectDataTypeaheadUrl : undefined,
42 projectPageUrl : undefined, 40 projectPageUrl : undefined,
43 projectName : undefined, 41 projectName : undefined,
44 projectId : undefined, 42 projectId : undefined,
diff --git a/bitbake/lib/toaster/toastergui/templates/layerdetails.html b/bitbake/lib/toaster/toastergui/templates/layerdetails.html
index c27d259a8c..ef1795c0e2 100644
--- a/bitbake/lib/toaster/toastergui/templates/layerdetails.html
+++ b/bitbake/lib/toaster/toastergui/templates/layerdetails.html
@@ -3,7 +3,7 @@
3{% load humanize %} 3{% load humanize %}
4{% load static %} 4{% load static %}
5{% block localbreadcrumb %} 5{% block localbreadcrumb %}
6<li><a href="{% url 'all-layers' project.id %}">All compatible layers</a></li> 6<li><a href="{% url 'projectlayers' project.id %}">All compatible layers</a></li>
7<li> 7<li>
8 {{layerversion.layer.name}} ({{layerversion.get_vcs_reference|truncatechars:13}}) 8 {{layerversion.layer.name}} ({{layerversion.get_vcs_reference|truncatechars:13}})
9</li> 9</li>
@@ -33,7 +33,7 @@
33 33
34 $(document).ready(function (){ 34 $(document).ready(function (){
35 var ctx = { 35 var ctx = {
36 projectBuildUrl : "{% url 'xhr_projectbuild' project.id %}", 36 projectBuildsUrl : "{% url 'projectbuilds' project.id %}",
37 layerDetailsUrl : "{% url 'base_layerdetails' project.id %}", 37 layerDetailsUrl : "{% url 'base_layerdetails' project.id %}",
38 xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}", 38 xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}",
39 layerVersion : { 39 layerVersion : {
diff --git a/bitbake/lib/toaster/toastergui/templates/managed_mrb_section.html b/bitbake/lib/toaster/toastergui/templates/managed_mrb_section.html
index c93c2af301..47e64eaaab 100644
--- a/bitbake/lib/toaster/toastergui/templates/managed_mrb_section.html
+++ b/bitbake/lib/toaster/toastergui/templates/managed_mrb_section.html
@@ -129,7 +129,7 @@
129 <div class="span4 lead">Build queued 129 <div class="span4 lead">Build queued
130 <i title="This build will start as soon as a build server is available" class="icon-question-sign get-help get-help-blue heading-help" data-toggle="tooltip"></i> 130 <i title="This build will start as soon as a build server is available" class="icon-question-sign get-help get-help-blue heading-help" data-toggle="tooltip"></i>
131 </div> 131 </div>
132 <button class="btn btn-info pull-right cancel-build-btn" data-build-id="{{buildrequest.id}}" data-request-url="{% url 'xhr_projectbuild' buildrequest.project.id %}" >Cancel</button> 132 <button class="btn btn-info pull-right cancel-build-btn" data-build-id="{{buildrequest.id}}" data-request-url="{% url 'projectbuilds' buildrequest.project.id %}" >Cancel</button>
133 133
134 {% elif buildrequest.state == buildrequest.REQ_CREATED %} 134 {% elif buildrequest.state == buildrequest.REQ_CREATED %}
135 135
diff --git a/bitbake/lib/toaster/toastergui/templates/project.html b/bitbake/lib/toaster/toastergui/templates/project.html
index e598631304..63fbc40f55 100644
--- a/bitbake/lib/toaster/toastergui/templates/project.html
+++ b/bitbake/lib/toaster/toastergui/templates/project.html
@@ -30,7 +30,7 @@ vim: expandtab tabstop=2
30 30
31{%else%} 31{%else%}
32 32
33<div id="main" role="main" data-ng-app="project" data-ng-controller="prjCtrl" class="top-padded"> 33<div id="main" role="main" data-ng-app="project" data-ng-controller="prjCtrl" class="top-padded" data-ng-cloak>
34 34
35 <!-- project name --> 35 <!-- project name -->
36 <div class="page-header"> 36 <div class="page-header">
@@ -46,10 +46,30 @@ vim: expandtab tabstop=2
46 46
47 <!-- custom templates for ng --> 47 <!-- custom templates for ng -->
48 48
49 <script type="text/ng-template" id="suggestion_details"> 49 <style>
50 <a> {[match.model.name]} {[match.model.detail]} </a> 50 .missing-layer {
51 color: lightgrey;
52 }
53 </style>
54 <script type="text/ng-template" id="recipes_suggestion_details">
55 <a> {[match.model.name]}
56 <span data-ng-class="{'missing-layer':($parent.$parent.$parent.$parent.filterProjectLayerIds().indexOf(match.model.projectcompatible_layer.id) == -1)}">
57 [{[match.model.layer_version__layer__name]}]
58 </span>
59 </a>
51 </script> 60 </script>
52 61
62 <script type="text/ng-template" id="machines_suggestion_details">
63 <a> {[match.model.name]} <span class="{'missing-layer':(filterProjectLayerIds().indexOf(match.model.layer_version_compatible_id) == -1)}">[{[match.model.layer_version__layer__name]}]</span> </a>
64 </script>
65
66 <script type="text/ng-template" id="layers_suggestion_details">
67 <a> {[match.model['layer__name']]} ( {[match.model.layer__vcs_url]} ) </a>
68 </script>
69
70
71
72
53 <!-- modal dialogs --> 73 <!-- modal dialogs -->
54 <script type="text/ng-template" id="dependencies_modal"> 74 <script type="text/ng-template" id="dependencies_modal">
55 <div class="modal-header"> 75 <div class="modal-header">
@@ -104,14 +124,14 @@ vim: expandtab tabstop=2
104 <div class="well"> 124 <div class="well">
105 <form class="build-form" data-ng-submit="buildNamedTarget()"> 125 <form class="build-form" data-ng-submit="buildNamedTarget()">
106 <div class="input-append controls"> 126 <div class="input-append controls">
107 <input type="text" class="huge input-xxlarge" placeholder="Type the recipe(s) you want to build" autocomplete="off" data-ng-model="targetName" data-typeahead="e.name for e in getAutocompleteSuggestions('targets', $viewValue)|filter:$viewValue" data-typeahead-template-url="suggestion_details" data-ng-disabled="!layers.length"/> 127 <input type="text" class="huge input-xxlarge" placeholder="Type the recipe(s) you want to build" autocomplete="off" data-ng-model="targetName" data-typeahead="a.name for a in getRecipesAutocompleteSuggestions($viewValue)" data-typeahead-template-url="recipes_suggestion_details" data-ng-disabled="!layers.length"/>
108 <button type="submit" class="btn btn-large btn-primary" data-ng-disabled="!targetName.length"> 128 <button type="submit" class="btn btn-large btn-primary" data-ng-disabled="!targetName.length">
109 Build 129 Build
110 </button> 130 </button>
111 </div> 131 </div>
112 <i class="icon-question-sign get-help get-help-blue" title="Type the name of one or more recipes you want to build, separated by a space. You can also specify a task by appending a semicolon and a task name to a recipe name, like so: <code>core-image-minimal:do_build</code>"></i> 132 <i class="icon-question-sign get-help get-help-blue" title="Type the name of one or more recipes you want to build, separated by a space. You can also specify a task by appending a semicolon and a task name to a recipe name, like so: <code>core-image-minimal:do_build</code>"></i>
113 <p> 133 <p>
114 <a href="{% url 'all-targets' project.id %}">View all compatible recipes</a> 134 <a href="{% url 'projecttargets' project.id %}">View all compatible recipes</a>
115 <i class="icon-question-sign get-help get-help-blue heading-help" title="View all the recipes you can build with the release selected for this project, which is {[project.release.desc]}"></i> 135 <i class="icon-question-sign get-help get-help-blue heading-help" title="View all the recipes you can build with the release selected for this project, which is {[project.release.desc]}"></i>
116 {% if completedbuilds.count %} 136 {% if completedbuilds.count %}
117 | <a href="{% url 'projectbuilds' project.id %}">View all project builds ({{completedbuilds.count}})</a> 137 | <a href="{% url 'projectbuilds' project.id %}">View all project builds ({{completedbuilds.count}})</a>
@@ -278,7 +298,7 @@ vim: expandtab tabstop=2
278 <p> 298 <p>
279 You can: 299 You can:
280 <ul> 300 <ul>
281 <li> <a href="{% url 'all-layers' project.id %}">View all compatible layers available in Toaster</a> 301 <li> <a href="{% url 'projectlayers' project.id %}">View all compatible layers available in Toaster</a>
282 <li> <a href="{% url 'importlayer' project.id %}">Import a layer</a> 302 <li> <a href="{% url 'importlayer' project.id %}">Import a layer</a>
283 <li> <a href="https://www.yoctoproject.org/docs/1.6.1/dev-manual/dev-manual.html#understanding-and-creating-layers" target="_blank">Read about layers in the manual</a> 303 <li> <a href="https://www.yoctoproject.org/docs/1.6.1/dev-manual/dev-manual.html#understanding-and-creating-layers" target="_blank">Read about layers in the manual</a>
284 </ul> 304 </ul>
@@ -287,13 +307,13 @@ vim: expandtab tabstop=2
287 </div> 307 </div>
288 <form data-ng-submit="layerAdd()"> 308 <form data-ng-submit="layerAdd()">
289 <div class="input-append"> 309 <div class="input-append">
290 <input type="text" class="input-xlarge" id="layer" autocomplete="off" placeholder="Type a layer name" data-minLength="1" data-ng-model="layerAddName" data-typeahead="e.name for e in getAutocompleteSuggestions('layers', $viewValue)|filter:$viewValue" data-typeahead-template-url="suggestion_details" data-typeahead-on-select="onLayerSelect($item, $model, $label)" data-typeahead-editable="false" data-ng-class="{ 'has-error': layerAddName.$invalid }" /> 310 <input type="text" class="input-xlarge" id="layer" autocomplete="off" placeholder="Type a layer name" data-minLength="1" data-ng-model="layerAddName" data-typeahead="e for e in getLayersAutocompleteSuggestions($viewValue)" data-typeahead-template-url="layers_suggestion_details" data-typeahead-on-select="onLayerSelect($item, $model, $label)" data-typeahead-editable="false" data-ng-class="{ 'has-error': layerAddName.$invalid }" />
291 <input type="submit" id="add-layer" class="btn" value="Add" data-ng-disabled="!layerAddName.length"/> 311 <input type="submit" id="add-layer" class="btn" value="Add" data-ng-disabled="!layerAddName.length"/>
292 </div> 312 </div>
293 {% csrf_token %} 313 {% csrf_token %}
294 </form> 314 </form>
295 <p> 315 <p>
296 <a href="{% url 'all-layers' project.id %}">View all compatible layers</a> 316 <a href="{% url 'projectlayers' project.id %}">View all compatible layers</a>
297 <i class="icon-question-sign get-help" title="View all the layers you can build with the release selected for this project, which is {[project.release.desc]}"></i> 317 <i class="icon-question-sign get-help" title="View all the layers you can build with the release selected for this project, which is {[project.release.desc]}"></i>
298 | 318 |
299 <a href="{% url 'importlayer' project.id %}">Import layer</a></p> 319 <a href="{% url 'importlayer' project.id %}">Import layer</a></p>
@@ -314,14 +334,14 @@ vim: expandtab tabstop=2
314 </h3> 334 </h3>
315 <form data-ng-submit="buildNamedTarget()"> 335 <form data-ng-submit="buildNamedTarget()">
316 <div class="input-append"> 336 <div class="input-append">
317 <input type="text" class="input-xlarge" placeholder="Type the recipe(s) you want to build" autocomplete="off" data-minLength="1" data-ng-model="targetName1" data-typeahead="e.name for e in getAutocompleteSuggestions('targets', $viewValue)|filter:$viewValue" data-typeahead-template-url="suggestion_details" data-ng-disabled="!layers.length"> 337 <input type="text" class="input-xlarge" placeholder="Type the recipe(s) you want to build" autocomplete="off" data-minLength="1" data-ng-model="targetName1" data-typeahead="a.name for a in getRecipesAutocompleteSuggestions($viewValue)" data-typeahead-template-url="recipes_suggestion_details" data-ng-disabled="!layers.length">
318 <button type="submit" class="btn btn-primary" data-ng-disabled="!targetName1.length"> 338 <button type="submit" class="btn btn-primary" data-ng-disabled="!targetName1.length">
319 Build </button> 339 Build </button>
320 </div> 340 </div>
321 {% csrf_token %} 341 {% csrf_token %}
322 </form> 342 </form>
323 <p> 343 <p>
324 <a href="{% url 'all-targets' project.id %}">View all compatible recipes</a> 344 <a href="{% url 'projecttargets' project.id %}">View all compatible recipes</a>
325 <i class="icon-question-sign get-help" title="View all the recipes you can build with the release selected for this project, which is {[project.release.desc]}"></i> 345 <i class="icon-question-sign get-help" title="View all the recipes you can build with the release selected for this project, which is {[project.release.desc]}"></i>
326 </p> 346 </p>
327 <div data-ng-if="frequenttargets.length"> 347 <div data-ng-if="frequenttargets.length">
@@ -355,13 +375,13 @@ vim: expandtab tabstop=2
355 You cannot really compare the builds for the new machine with the previous ones. 375 You cannot really compare the builds for the new machine with the previous ones.
356 </div> 376 </div>
357 <form data-ng-submit="editProjectSettings('#select-machine')" class="input-append"> 377 <form data-ng-submit="editProjectSettings('#select-machine')" class="input-append">
358 <input type="text" id="machine" autocomplete="off" data-ng-model="machineName" value="{[machine.name]}" data-typeahead="m.name for m in getAutocompleteSuggestions('machines', $viewValue)" data-typeahead-template-url="suggestion_details" /> 378 <input type="text" id="machine" autocomplete="off" data-ng-model="machineName" value="{[machine.name]}" data-typeahead="m.name for m in getMachinesAutocompleteSuggestions($viewValue)" data-typeahead-template-url="machines_suggestion_details" />
359 <input type="submit" id="apply-change-machine" class="btn" data-ng-disabled="machineName == machine.name || machineName.length == 0" value="Save"/> 379 <input type="submit" id="apply-change-machine" class="btn" data-ng-disabled="machineName == machine.name || machineName.length == 0" value="Save"/>
360 <input type="reset" id="cancel-machine" class="btn btn-link" data-ng-click="toggle('#select-machine')" value="Cancel"/> 380 <input type="reset" id="cancel-machine" class="btn btn-link" data-ng-click="toggle('#select-machine')" value="Cancel"/>
361 {% csrf_token %} 381 {% csrf_token %}
362 </form> 382 </form>
363 <p> 383 <p>
364 <a href="{% url 'all-machines' project.id %}" class="link">View all compatible machines</a> 384 <a href="{% url 'projectmachines' project.id %}" class="link">View all compatible machines</a>
365 <i class="icon-question-sign get-help" title="View all the machines you can set with the release selected for this project, which is {[project.release.desc]}"></i> 385 <i class="icon-question-sign get-help" title="View all the machines you can set with the release selected for this project, which is {[project.release.desc]}"></i>
366 </p> 386 </p>
367 </div> 387 </div>
@@ -429,11 +449,11 @@ vim: expandtab tabstop=2
429angular.element(document).ready(function() { 449angular.element(document).ready(function() {
430 scope = angular.element("#main").scope(); 450 scope = angular.element("#main").scope();
431 scope.urls = {}; 451 scope.urls = {};
432 scope.urls.xhr_build = "{% url 'xhr_projectbuild' project.id %}"; 452 scope.urls.xhr_build = "{% url 'projectbuilds' project.id %}";
433 scope.urls.xhr_edit = "{% url 'project' project.id %}?format=json"; 453 scope.urls.xhr_edit = "{% url 'project' project.id %}?format=json";
434 scope.urls.xhr_datatypeahead = "{% url 'xhr_datatypeahead' project.id %}"; 454 scope.urls.layers = "{% url 'projectlayers' project.id %}";
435 scope.urls.layers = "{% url 'all-layers' project.id %}"; 455 scope.urls.targets = "{% url 'projecttargets' project.id %}";
436 scope.urls.targets = "{% url 'all-targets' project.id %}"; 456 scope.urls.machines = "{% url 'projectmachines' project.id %}";
437 scope.urls.importlayer = "{% url 'importlayer' project.id %}"; 457 scope.urls.importlayer = "{% url 'importlayer' project.id %}";
438 scope.urls.layer = "{% url 'base_layerdetails' project.id %}"; 458 scope.urls.layer = "{% url 'base_layerdetails' project.id %}";
439 scope.project = {{prj|json}}; 459 scope.project = {{prj|json}};
diff --git a/bitbake/lib/toaster/toastergui/templates/runagain.html b/bitbake/lib/toaster/toastergui/templates/runagain.html
index a78c0ddc78..b4ba5fbf15 100644
--- a/bitbake/lib/toaster/toastergui/templates/runagain.html
+++ b/bitbake/lib/toaster/toastergui/templates/runagain.html
@@ -1,6 +1,6 @@
1{% load projecttags %} 1{% load projecttags %}
2onclick='scheduleBuild( 2onclick='scheduleBuild(
3 {% url 'xhr_projectbuild' buildrequest.project.id as bpi %}{{bpi|json}}, 3 {% url 'projectbuilds' buildrequest.project.id as bpi %}{{bpi|json}},
4 {{buildrequest.project.name|json}}, 4 {{buildrequest.project.name|json}},
5 {% url 'project' buildrequest.project.id as bpurl %}{{bpurl|json}}, 5 {% url 'project' buildrequest.project.id as bpurl %}{{bpurl|json}},
6 {{buildrequest.brtarget_set.all|get_tasks|json}}) 6 {{buildrequest.brtarget_set.all|get_tasks|json}})
diff --git a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
index e79a4e5848..75f2261be8 100644
--- a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
+++ b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
@@ -55,7 +55,7 @@ def json(value, default = None):
55 # JSON spec says that "\/" is functionally identical to "/" to allow for HTML-tag embedding in JSON strings 55 # JSON spec says that "\/" is functionally identical to "/" to allow for HTML-tag embedding in JSON strings
56 # unfortunately, I can't find any option in the json module to turn on forward-slash escaping, so we do 56 # unfortunately, I can't find any option in the json module to turn on forward-slash escaping, so we do
57 # it manually here 57 # it manually here
58 return mark_safe(JsonLib.dumps(value, default = default, ensure_ascii=False).replace('</', '<\\/')) 58 return mark_safe(JsonLib.dumps(value, indent=2, default = default, ensure_ascii=False).replace('</', '<\\/'))
59 59
60@register.assignment_tag 60@register.assignment_tag
61def query(qs, **kwargs): 61def query(qs, **kwargs):
diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py
index c92c5feeb5..77e80fe3a9 100644
--- a/bitbake/lib/toaster/toastergui/tests.py
+++ b/bitbake/lib/toaster/toastergui/tests.py
@@ -38,9 +38,9 @@ class AllProjectsViewTestCase(ProvisionedProjectTestCase):
38 38
39 self.assertTrue(AllProjectsViewTestCase.TEST_PROJECT_NAME in map(lambda x: x["name"], data["list"])) 39 self.assertTrue(AllProjectsViewTestCase.TEST_PROJECT_NAME in map(lambda x: x["name"], data["list"]))
40 self.assertTrue("id" in data["list"][0]) 40 self.assertTrue("id" in data["list"][0])
41 self.assertTrue("xhrProjectDataTypeaheadUrl" in data["list"][0]) 41 self.assertTrue("projectLayersUrl" in data["list"][0])
42 self.assertTrue("projectPageUrl" in data["list"][0]) 42 self.assertTrue("projectPageUrl" in data["list"][0])
43 self.assertTrue("projectBuildUrl" in data["list"][0]) 43 self.assertTrue("projectBuildsUrl" in data["list"][0])
44 44
45class ProvisionedLayersProjectTestCase(ProvisionedProjectTestCase): 45class ProvisionedLayersProjectTestCase(ProvisionedProjectTestCase):
46 LAYER_NAME = "base-layer" 46 LAYER_NAME = "base-layer"
@@ -59,7 +59,7 @@ class XHRDataTypeAheadTestCase(ProvisionedLayersProjectTestCase):
59 self.assertTrue(self.lv in self.project.compatible_layerversions()) 59 self.assertTrue(self.lv in self.project.compatible_layerversions())
60 60
61 def test_xhr_datatypeahead_layer(self): 61 def test_xhr_datatypeahead_layer(self):
62 response = self.client.get(reverse('xhr_datatypeahead', args=(self.project.id,)), {"type": "layers"}) 62 response = self.client.get(reverse('xhr_datatypeahead', args=(self.project.id,)), {"type": "layerdeps"})
63 self.assertEqual(response.status_code, 200) 63 self.assertEqual(response.status_code, 200)
64 self.assertTrue(response['Content-Type'].startswith('application/json')) 64 self.assertTrue(response['Content-Type'].startswith('application/json'))
65 65
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index d527be0017..f1b74cdd14 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -91,19 +91,19 @@ urlpatterns = patterns('toastergui.views',
91 tables.MachinesTable.as_view(template_name="generic-toastertable-page.html"), 91 tables.MachinesTable.as_view(template_name="generic-toastertable-page.html"),
92 { 'table_name': tables.MachinesTable.__name__.lower(), 92 { 'table_name': tables.MachinesTable.__name__.lower(),
93 'title' : 'All compatible machines' }, 93 'title' : 'All compatible machines' },
94 name="all-machines"), 94 name="projectmachines"),
95 95
96 url(r'^project/(?P<pid>\d+)/recipes/$', 96 url(r'^project/(?P<pid>\d+)/recipes/$',
97 tables.RecipesTable.as_view(template_name="generic-toastertable-page.html"), 97 tables.RecipesTable.as_view(template_name="generic-toastertable-page.html"),
98 { 'table_name': tables.RecipesTable.__name__.lower(), 98 { 'table_name': tables.RecipesTable.__name__.lower(),
99 'title' : 'All compatible recipes' }, 99 'title' : 'All compatible recipes' },
100 name="all-targets"), 100 name="projecttargets"),
101 101
102 url(r'^project/(?P<pid>\d+)/layers/$', 102 url(r'^project/(?P<pid>\d+)/layers/$',
103 tables.LayersTable.as_view(template_name="generic-toastertable-page.html"), 103 tables.LayersTable.as_view(template_name="generic-toastertable-page.html"),
104 { 'table_name': tables.LayersTable.__name__.lower(), 104 { 'table_name': tables.LayersTable.__name__.lower(),
105 'title' : 'All compatible layers' }, 105 'title' : 'All compatible layers' },
106 name="all-layers"), 106 name="projectlayers"),
107 107
108 url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$', 108 url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$',
109 tables.LayerDetails.as_view(template_name='layerdetails.html'), 109 tables.LayerDetails.as_view(template_name='layerdetails.html'),
@@ -121,10 +121,8 @@ urlpatterns = patterns('toastergui.views',
121 'title' : 'All machines in layer' }, 121 'title' : 'All machines in layer' },
122 name=tables.LayerMachinesTable.__name__.lower()), 122 name=tables.LayerMachinesTable.__name__.lower()),
123 123
124 url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'),
125 url(r'^xhr_configvaredit/(?P<pid>\d+)$', 'xhr_configvaredit', name='xhr_configvaredit'), 124 url(r'^xhr_configvaredit/(?P<pid>\d+)$', 'xhr_configvaredit', name='xhr_configvaredit'),
126 125
127 url(r'^xhr_datatypeahead/(?P<pid>\d+)$', 'xhr_datatypeahead', name='xhr_datatypeahead'),
128 url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'), 126 url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
129 url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'), 127 url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'),
130 128
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index c25c512a84..5221f1f728 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -136,28 +136,6 @@ def _template_renderer(template):
136 136
137 # we're about to return; to keep up with the XHR API, we set the error to OK 137 # we're about to return; to keep up with the XHR API, we set the error to OK
138 context["error"] = "ok" 138 context["error"] = "ok"
139 def _objtojson(obj):
140 from django.db.models.query import QuerySet
141 from django.db.models import Model, IntegerField
142 if isinstance(obj, datetime):
143 return obj.isoformat()
144 elif isinstance(obj, timedelta):
145 return obj.total_seconds()
146 elif isinstance(obj, QuerySet) or isinstance(obj, set):
147 return list(obj)
148 elif hasattr( obj, '__dict__'):
149 d = obj.__dict__
150 nd = dict(d)
151 for di in d:
152 if di.startswith("_"):
153 del nd[di]
154 elif isinstance(d[di], Model):
155 nd[di] = d[di].pk
156 elif isinstance(d[di], int) and hasattr(obj, "get_%s_display" % di):
157 nd[di] = getattr(obj, "get_%s_display" % di)()
158 return nd
159 else:
160 raise TypeError("Unserializable object %s of type %s" % ( obj, type(obj)))
161 139
162 return HttpResponse(jsonfilter(context, default=objtojson ), 140 return HttpResponse(jsonfilter(context, default=objtojson ),
163 content_type = "application/json; charset=utf-8") 141 content_type = "application/json; charset=utf-8")
@@ -167,6 +145,21 @@ def _template_renderer(template):
167 return func_wrapper 145 return func_wrapper
168 146
169 147
148def _lv_to_dict(prj, x = None):
149 if x is None:
150 def wrapper(x):
151 return _lv_to_dict(prj, x)
152 return wrapper
153
154 return {"id": x.pk,
155 "name": x.layer.name,
156 "tooltip": x.layer.vcs_url+" | "+x.get_vcs_reference(),
157 "detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.get_vcs_reference()+")"),
158 "giturl": x.layer.vcs_url,
159 "layerdetailurl" : reverse('layerdetails', args=(prj.id,x.pk)),
160 "revision" : x.get_vcs_reference(),
161 }
162
170 163
171def _build_page_range(paginator, index = 1): 164def _build_page_range(paginator, index = 1):
172 try: 165 try:
@@ -335,7 +328,6 @@ def _search_tuple(request, model):
335def _get_queryset(model, queryset, filter_string, search_term, ordering_string, ordering_secondary=''): 328def _get_queryset(model, queryset, filter_string, search_term, ordering_string, ordering_secondary=''):
336 if filter_string: 329 if filter_string:
337 filter_query = _get_filtering_query(filter_string) 330 filter_query = _get_filtering_query(filter_string)
338# raise Exception(filter_query)
339 queryset = queryset.filter(filter_query) 331 queryset = queryset.filter(filter_query)
340 else: 332 else:
341 queryset = queryset.all() 333 queryset = queryset.all()
@@ -2330,82 +2322,12 @@ if toastermain.settings.MANAGED:
2330 return context 2322 return context
2331 2323
2332 2324
2333 def xhr_projectbuild(request, pid):
2334 try:
2335 if request.method != "POST":
2336 raise BadParameterException("invalid method")
2337 pid = pid
2338 prj = Project.objects.get(id = pid)
2339
2340
2341 if 'buildCancel' in request.POST:
2342 for i in request.POST['buildCancel'].strip().split(" "):
2343 try:
2344 br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED)
2345 br.state = BuildRequest.REQ_DELETED
2346 br.save()
2347 except BuildRequest.DoesNotExist:
2348 pass
2349
2350 if 'buildDelete' in request.POST:
2351 for i in request.POST['buildDelete'].strip().split(" "):
2352 try:
2353 br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_DELETED).delete()
2354 except BuildRequest.DoesNotExist:
2355 pass
2356
2357 if 'targets' in request.POST:
2358 ProjectTarget.objects.filter(project = prj).delete()
2359 s = str(request.POST['targets'])
2360 for t in s.translate(None, ";%|\"").split(" "):
2361 if ":" in t:
2362 target, task = t.split(":")
2363 else:
2364 target = t
2365 task = ""
2366 ProjectTarget.objects.create(project = prj, target = target, task = task)
2367
2368 br = prj.schedule_build()
2369
2370 return HttpResponse(jsonfilter({"error":"ok",
2371 "builds" : _project_recent_build_list(prj),
2372 }), content_type = "application/json")
2373 except Exception as e:
2374 return HttpResponse(jsonfilter({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
2375
2376
2377 from django.views.decorators.csrf import csrf_exempt 2325 from django.views.decorators.csrf import csrf_exempt
2378 @csrf_exempt 2326 @csrf_exempt
2379 def xhr_datatypeahead(request, pid): 2327 def xhr_datatypeahead(request, pid):
2380 try: 2328 try:
2381 prj = Project.objects.get(pk = pid) 2329 prj = Project.objects.get(pk = pid)
2382 2330
2383 def _lv_to_dict(x):
2384 return {"id": x.pk,
2385 "name": x.layer.name,
2386 "tooltip": x.layer.vcs_url+" | "+x.get_vcs_reference(),
2387 "detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.get_vcs_reference()+")"),
2388 "giturl": x.layer.vcs_url,
2389 "layerdetailurl" : reverse('layerdetails', args=(prj.id,x.pk)),
2390 "revision" : x.get_vcs_reference(),
2391 }
2392
2393
2394 # returns layers for current project release that are not in the project set, matching the name
2395 if request.GET.get('type', None) == "layers":
2396 # all layers for the current project
2397 queryset_all = prj.compatible_layerversions().filter(layer__name__icontains=request.GET.get('search',''))
2398
2399 # but not layers with equivalent layers already in project
2400 if not request.GET.has_key('include_added'):
2401 queryset_all = queryset_all.exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()])[:8]
2402
2403 # and show only the selected layers for this project
2404 final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset_all])
2405
2406 return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict, sorted(final_list, key = lambda x: x.layer.name)) }), content_type = "application/json")
2407
2408
2409 # returns layer dependencies for a layer, excluding current project layers 2331 # returns layer dependencies for a layer, excluding current project layers
2410 if request.GET.get('type', None) == "layerdeps": 2332 if request.GET.get('type', None) == "layerdeps":
2411 queryset = prj.compatible_layerversions().exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()]).filter( 2333 queryset = prj.compatible_layerversions().exclude(pk__in = [x.id for x in prj.projectlayer_equivalent_set()]).filter(
@@ -2413,8 +2335,7 @@ if toastermain.settings.MANAGED:
2413 2335
2414 final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset]) 2336 final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset])
2415 2337
2416 return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict, sorted(final_list, key = lambda x: x.layer.name)) }), content_type = "application/json") 2338 return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict(prj), sorted(final_list, key = lambda x: x.layer.name)) }), content_type = "application/json")
2417
2418 2339
2419 2340
2420 # returns layer versions that would be deleted on the new release__pk 2341 # returns layer versions that would be deleted on the new release__pk
@@ -2428,7 +2349,7 @@ if toastermain.settings.MANAGED:
2428 retval.append(i) 2349 retval.append(i)
2429 2350
2430 return HttpResponse(jsonfilter( {"error":"ok", 2351 return HttpResponse(jsonfilter( {"error":"ok",
2431 "list" : map( _lv_to_dict, map(lambda x: x.layercommit, retval )) 2352 "list" : map( _lv_to_dict(prj), map(lambda x: x.layercommit, retval ))
2432 }), content_type = "application/json") 2353 }), content_type = "application/json")
2433 2354
2434 2355
@@ -2446,52 +2367,8 @@ if toastermain.settings.MANAGED:
2446 # and show only the selected layers for this project 2367 # and show only the selected layers for this project
2447 final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset_all]) 2368 final_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset_all])
2448 2369
2449 return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict, final_list) }), content_type = "application/json") 2370 return HttpResponse(jsonfilter( { "error":"ok", "list" : map( _lv_to_dict(prj), final_list) }), content_type = "application/json")
2450 2371
2451 # returns targets provided by current project layers
2452 if request.GET.get('type', None) == "targets":
2453 search_token = request.GET.get('search','')
2454 queryset_all = Recipe.objects.filter(layer_version__layer__name__in = [x.layercommit.layer.name for x in prj.projectlayer_set.all().select_related("layercommit__layer")]).filter(Q(name__icontains=search_token) | Q(layer_version__layer__name__icontains=search_token))
2455
2456# layer_equivalent_set = []
2457# for i in prj.projectlayer_set.all().select_related("layercommit__up_branch", "layercommit__layer"):
2458# layer_equivalent_set += i.layercommit.get_equivalents_wpriority(prj)
2459
2460# queryset_all = queryset_all.filter(layer_version__in = layer_equivalent_set)
2461
2462 # if we have more than one hit here (for distinct name and version), max the id it out
2463 queryset_all_maxids = queryset_all.values('name').distinct().annotate(max_id=Max('id')).values_list('max_id')
2464 queryset_all = queryset_all.filter(id__in = queryset_all_maxids).order_by("name").select_related("layer_version__layer")
2465
2466
2467 return HttpResponse(jsonfilter({ "error":"ok",
2468 "list" :
2469 # 7152 - sort by token position
2470 sorted (
2471 map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name +"]"},
2472 queryset_all[:8]),
2473 key = lambda i: i["name"].find(search_token) if i["name"].find(search_token) > -1 else 9999,
2474 )
2475
2476 }), content_type = "application/json")
2477
2478 # returns machines provided by the current project layers
2479 if request.GET.get('type', None) == "machines":
2480 queryset_all = Machine.objects.all()
2481 if 'project_id' in request.session:
2482 queryset_all = queryset_all.filter(layer_version__in = prj.projectlayer_equivalent_set()).order_by("name")
2483
2484 search_token = request.GET.get('search','')
2485 queryset_all = queryset_all.filter(Q(name__icontains=search_token) | Q(description__icontains=search_token))
2486
2487 return HttpResponse(jsonfilter({ "error":"ok",
2488 "list" :
2489 # 7152 - sort by the token position
2490 sorted (
2491 map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name+ "]"}, queryset_all[:8]),
2492 key = lambda i: i["name"].find(search_token) if i["name"].find(search_token) > -1 else 9999,
2493 )
2494 }), content_type = "application/json")
2495 2372
2496 raise Exception("Unknown request! " + request.GET.get('type', "No parameter supplied")) 2373 raise Exception("Unknown request! " + request.GET.get('type', "No parameter supplied"))
2497 except Exception as e: 2374 except Exception as e:
@@ -2791,7 +2668,41 @@ if toastermain.settings.MANAGED:
2791 2668
2792 @_template_renderer('projectbuilds.html') 2669 @_template_renderer('projectbuilds.html')
2793 def projectbuilds(request, pid): 2670 def projectbuilds(request, pid):
2794 buildrequests = BuildRequest.objects.filter(project_id = pid).exclude(state__lte = BuildRequest.REQ_INPROGRESS).exclude(state=BuildRequest.REQ_DELETED) 2671 # process any build request
2672 prj = Project.objects.get(id = pid)
2673 if request.method == "POST":
2674
2675 if 'buildCancel' in request.POST:
2676 for i in request.POST['buildCancel'].strip().split(" "):
2677 try:
2678 br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED)
2679 br.state = BuildRequest.REQ_DELETED
2680 br.save()
2681 except BuildRequest.DoesNotExist:
2682 pass
2683
2684 if 'buildDelete' in request.POST:
2685 for i in request.POST['buildDelete'].strip().split(" "):
2686 try:
2687 br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_DELETED).delete()
2688 except BuildRequest.DoesNotExist:
2689 pass
2690
2691 if 'targets' in request.POST:
2692 ProjectTarget.objects.filter(project = prj).delete()
2693 s = str(request.POST['targets'])
2694 for t in s.translate(None, ";%|\"").split(" "):
2695 if ":" in t:
2696 target, task = t.split(":")
2697 else:
2698 target = t
2699 task = ""
2700 ProjectTarget.objects.create(project = prj, target = target, task = task)
2701
2702 br = prj.schedule_build()
2703
2704
2705 buildrequests = BuildRequest.objects.filter(project = prj).exclude(state__lte = BuildRequest.REQ_INPROGRESS).exclude(state=BuildRequest.REQ_DELETED)
2795 2706
2796 try: 2707 try:
2797 context, pagesize, orderby = _build_list_helper(request, buildrequests, False) 2708 context, pagesize, orderby = _build_list_helper(request, buildrequests, False)
@@ -2940,9 +2851,10 @@ if toastermain.settings.MANAGED:
2940 # add fields needed in JSON dumps for API call support 2851 # add fields needed in JSON dumps for API call support
2941 for p in project_info.object_list: 2852 for p in project_info.object_list:
2942 p.id = p.pk 2853 p.id = p.pk
2943 p.xhrProjectDataTypeaheadUrl = reverse('xhr_datatypeahead', args=(p.id,))
2944 p.projectPageUrl = reverse('project', args=(p.id,)) 2854 p.projectPageUrl = reverse('project', args=(p.id,))
2945 p.projectBuildUrl = reverse('xhr_projectbuild', args=(p.id,)) 2855 p.projectLayersUrl = reverse('projectlayers', args=(p.id,))
2856 p.projectBuildsUrl = reverse('projectbuilds', args=(p.id,))
2857 p.projectTargetsUrl = reverse('projecttargets', args=(p.id,))
2946 2858
2947 # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds) 2859 # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds)
2948 build_mru = _managed_get_latest_builds() 2860 build_mru = _managed_get_latest_builds()
@@ -3242,14 +3154,6 @@ else:
3242 return {} 3154 return {}
3243 3155
3244 @_template_renderer('landing_not_managed.html') 3156 @_template_renderer('landing_not_managed.html')
3245 def xhr_projectbuild(request, pid):
3246 return {}
3247
3248 @_template_renderer('landing_not_managed.html')
3249 def xhr_datatypeahead(request):
3250 return {}
3251
3252 @_template_renderer('landing_not_managed.html')
3253 def xhr_configvaredit(request, pid): 3157 def xhr_configvaredit(request, pid):
3254 return {} 3158 return {}
3255 3159
diff --git a/bitbake/lib/toaster/toastergui/widgets.py b/bitbake/lib/toaster/toastergui/widgets.py
index 8bc3d7f160..f5a1b3e7b9 100644
--- a/bitbake/lib/toaster/toastergui/widgets.py
+++ b/bitbake/lib/toaster/toastergui/widgets.py
@@ -253,8 +253,8 @@ class ToasterTable(TemplateView):
253 253
254 data = cache.get(cache_name) 254 data = cache.get(cache_name)
255 255
256 if data: 256 #if data:
257 return data 257 # return data
258 258
259 self.setup_columns(**kwargs) 259 self.setup_columns(**kwargs)
260 260
@@ -277,9 +277,9 @@ class ToasterTable(TemplateView):
277 'default_orderby' : self.default_orderby, 277 'default_orderby' : self.default_orderby,
278 'columns' : self.columns, 278 'columns' : self.columns,
279 'rows' : [], 279 'rows' : [],
280 'error' : "ok",
280 } 281 }
281 282
282
283 try: 283 try:
284 for row in page.object_list: 284 for row in page.object_list:
285 #Use collection to maintain the order 285 #Use collection to maintain the order