summaryrefslogtreecommitdiffstats
path: root/bitbake/lib
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib')
-rw-r--r--bitbake/lib/toaster/bldcontrol/models.py33
-rw-r--r--bitbake/lib/toaster/toastergui/static/css/default.css4
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/projectapp.js24
-rw-r--r--bitbake/lib/toaster/toastergui/templates/base.html3
-rw-r--r--bitbake/lib/toaster/toastergui/templates/basetable_bottom.html13
-rw-r--r--bitbake/lib/toaster/toastergui/templates/layers.html124
-rw-r--r--bitbake/lib/toaster/toastergui/templates/mrb_section.html11
-rw-r--r--bitbake/lib/toaster/toastergui/templates/project.html48
-rw-r--r--bitbake/lib/toaster/toastergui/templates/targets.html340
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py157
10 files changed, 458 insertions, 299 deletions
diff --git a/bitbake/lib/toaster/bldcontrol/models.py b/bitbake/lib/toaster/bldcontrol/models.py
index f72fb8fbc9..e643d08603 100644
--- a/bitbake/lib/toaster/bldcontrol/models.py
+++ b/bitbake/lib/toaster/bldcontrol/models.py
@@ -42,11 +42,34 @@ class BuildEnvironment(models.Model):
42 42
43 def get_artifact_type(self, path): 43 def get_artifact_type(self, path):
44 if self.betype == BuildEnvironment.TYPE_LOCAL: 44 if self.betype == BuildEnvironment.TYPE_LOCAL:
45 import magic 45 try:
46 m = magic.open(magic.MAGIC_MIME_TYPE) 46 import magic
47 m.load() 47
48 return m.file(path) 48 # fair warning: this is a mess; there are multiple competeing and incompatible
49 raise Exception("FIXME: not implemented") 49 # magic modules floating around, so we try some of the most common combinations
50
51 try: # we try ubuntu's python-magic 5.4
52 m = magic.open(magic.MAGIC_MIME_TYPE)
53 m.load()
54 return m.file(path)
55 except AttributeError:
56 pass
57
58 try: # we try python-magic 0.4.6
59 m = magic.Magic(magic.MAGIC_MIME)
60 return m.from_file(path)
61 except AttributeError:
62 pass
63
64 try: # we try pip filemagic 1.6
65 m = magic.Magic(flags=magic.MAGIC_MIME_TYPE)
66 return m.id_filename(path)
67 except AttributeError:
68 pass
69
70 return "binary/octet-stream"
71 except ImportError:
72 return "binary/octet-stream"
50 73
51 def get_artifact(self, path): 74 def get_artifact(self, path):
52 if self.betype == BuildEnvironment.TYPE_LOCAL: 75 if self.betype == BuildEnvironment.TYPE_LOCAL:
diff --git a/bitbake/lib/toaster/toastergui/static/css/default.css b/bitbake/lib/toaster/toastergui/static/css/default.css
index 9e62c6c8e7..fb20fc9241 100644
--- a/bitbake/lib/toaster/toastergui/static/css/default.css
+++ b/bitbake/lib/toaster/toastergui/static/css/default.css
@@ -61,8 +61,8 @@ dd p { line-height: 20px; }
61 61
62/* Override default Twitter Boostrap styles for anchor tags inside tables */ 62/* Override default Twitter Boostrap styles for anchor tags inside tables */
63td a, td a > code { color: #333333; } 63td a, td a > code { color: #333333; }
64td a > code { white-space: normal; } 64td code { white-space: normal; }
65td a:hover { color: #000000; text-decoration: underline; } 65td a:hover, td a > code:hover { color: #000000; text-decoration: underline; }
66 66
67/* Override default Twitter Bootstrap styles for tr.error */ 67/* Override default Twitter Bootstrap styles for tr.error */
68.table tbody tr.error > td { background-color: transparent; } /* override default Bootstrap behaviour */ 68.table tbody tr.error > td { background-color: transparent; } /* override default Bootstrap behaviour */
diff --git a/bitbake/lib/toaster/toastergui/static/js/projectapp.js b/bitbake/lib/toaster/toastergui/static/js/projectapp.js
index e674d8ffd1..b347451e88 100644
--- a/bitbake/lib/toaster/toastergui/static/js/projectapp.js
+++ b/bitbake/lib/toaster/toastergui/static/js/projectapp.js
@@ -92,6 +92,24 @@ projectApp.config(function($interpolateProvider) {
92 $interpolateProvider.endSymbol("]}"); 92 $interpolateProvider.endSymbol("]}");
93}); 93});
94 94
95
96// add time interval to HH:mm filter
97projectApp.filter('timediff', function() {
98 return function(input) {
99 function pad(j) {
100 if (parseInt(j) < 10) {return "0" + j}
101 return j;
102 }
103 seconds = parseInt(input);
104 minutes = Math.floor(seconds / 60);
105 seconds = seconds - minutes * 60;
106 hours = Math.floor(seconds / 3600);
107 seconds = seconds - hours * 3600;
108 return pad(hours) + ":" + pad(minutes) + ":" + pad(seconds);
109 }
110});
111
112
95// main controller for the project page 113// main controller for the project page
96projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $location, $cookies, $q, $sce) { 114projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $location, $cookies, $q, $sce) {
97 115
@@ -150,7 +168,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
150 168
151 // identify canceled builds here, so we can display them. 169 // identify canceled builds here, so we can display them.
152 _diffArrays(oldbuilds, $scope.builds, 170 _diffArrays(oldbuilds, $scope.builds,
153 function (e,f) { return e.status == f.status && e.id == f.id }, // compare 171 function (e,f) { return e.id == f.id }, // compare
154 undefined, // added 172 undefined, // added
155 function (e) { // deleted 173 function (e) { // deleted
156 if (e.status == "deleted") return; 174 if (e.status == "deleted") return;
@@ -421,7 +439,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
421 }).then( function () { 439 }).then( function () {
422 $scope.toggle(elementid); 440 $scope.toggle(elementid);
423 if (data['projectVersion'] != undefined) { 441 if (data['projectVersion'] != undefined) {
424 alertText += "<b>" + $scope.release.name + "</b>"; 442 alertText += "<b>" + $scope.project.release.name + "</b>";
425 } 443 }
426 $scope.displayAlert(alertZone, alertText, "alert-info"); 444 $scope.displayAlert(alertZone, alertText, "alert-info");
427 }); 445 });
@@ -506,7 +524,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
506 // init code 524 // init code
507 // 525 //
508 $scope.init = function() { 526 $scope.init = function() {
509 $scope.pollHandle = $interval(function () { $scope._makeXHRCall({method: "POST", url: $scope.urls.xhr_edit, data: undefined});}, 4000, 0); 527 $scope.pollHandle = $interval(function () { $scope._makeXHRCall({method: "GET", url: $scope.urls.xhr_edit, data: undefined});}, 4000, 0);
510 } 528 }
511 529
512 $scope.init(); 530 $scope.init();
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html
index d414bfbbde..f377081849 100644
--- a/bitbake/lib/toaster/toastergui/templates/base.html
+++ b/bitbake/lib/toaster/toastergui/templates/base.html
@@ -1,6 +1,6 @@
1<!DOCTYPE html> 1<!DOCTYPE html>
2{% load static %} 2{% load static %}
3<html> 3<html lang="en">
4 <head> 4 <head>
5 <title>{% if objectname %} {{objectname|title}} - {% endif %}Toaster</title> 5 <title>{% if objectname %} {{objectname|title}} - {% endif %}Toaster</title>
6<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css"> 6<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css">
@@ -9,6 +9,7 @@
9<link rel="stylesheet" href="{% static 'css/prettify.css' %}" type='text/css'> 9<link rel="stylesheet" href="{% static 'css/prettify.css' %}" type='text/css'>
10<link rel="stylesheet" href="{% static 'css/default.css' %}" type='text/css'> 10<link rel="stylesheet" href="{% static 'css/default.css' %}" type='text/css'>
11<meta name="viewport" content="width=device-width, initial-scale=1.0" /> 11<meta name="viewport" content="width=device-width, initial-scale=1.0" />
12<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
12<script src="{% static 'js/jquery-2.0.3.min.js' %}"> 13<script src="{% static 'js/jquery-2.0.3.min.js' %}">
13</script> 14</script>
14<script src="{% static 'js/jquery.cookie.js' %}"> 15<script src="{% static 'js/jquery.cookie.js' %}">
diff --git a/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html b/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html
index 091e11a51e..d48ad92020 100644
--- a/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html
+++ b/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html
@@ -58,9 +58,12 @@
58 } 58 }
59 59
60 // load cookie for number of entries to be displayed on page 60 // load cookie for number of entries to be displayed on page
61 pagesize = $.cookie('count'); 61 if ({{request.GET.count}} != "") {
62 if (!pagesize) 62 pagesize = {{request.GET.count}};
63 pagesize = 10; 63 } else {
64 pagesize = $.cookie('_count');
65 }
66
64 $('.pagesize option').prop('selected', false) 67 $('.pagesize option').prop('selected', false)
65 .filter('[value="' + pagesize + '"]') 68 .filter('[value="' + pagesize + '"]')
66 .attr('selected', true); 69 .attr('selected', true);
@@ -81,9 +84,9 @@
81 $('.progress, .lead span').tooltip({container:'table', placement:'top'}); 84 $('.progress, .lead span').tooltip({container:'table', placement:'top'});
82 85
83 $(".pagesize").change(function () { 86 $(".pagesize").change(function () {
84 reload_params({"count":$(this).val()});
85 // save cookie with pagesize 87 // save cookie with pagesize
86 $.cookie("count", $(this).val(), { path : $(location).attr('pathname') }); 88 $.cookie("_count", $(this).val(), { path : $(location).attr('pathname') });
89 reload_params({"count":$(this).val()});
87 }); 90 });
88}); 91});
89</script> 92</script>
diff --git a/bitbake/lib/toaster/toastergui/templates/layers.html b/bitbake/lib/toaster/toastergui/templates/layers.html
index 51f4dd96e7..db34fe4818 100644
--- a/bitbake/lib/toaster/toastergui/templates/layers.html
+++ b/bitbake/lib/toaster/toastergui/templates/layers.html
@@ -9,67 +9,66 @@
9{% block projectinfomain %} 9{% block projectinfomain %}
10 <div class="page-header"> 10 <div class="page-header">
11 <h1> 11 <h1>
12 {% if request.GET.search and objects.paginator.count > 0 %} 12 {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %}
13 {{objects.paginator.count}} layer{{objects.paginator.count|pluralize}} found 13 {{objects.paginator.count}} layer{{objects.paginator.count|pluralize}} found
14 {%elif request.GET.search and objects.paginator.count == 0%} 14 {% elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
15 No layer found 15 No layers found
16 {%else%} 16 {%else%}
17 All layers 17 All layers
18 {%endif%} 18 {%endif%}
19 <i class="icon-question-sign get-help heading-help" title="This page lists all the layers compatible with " + {{project.release.name}} + " that Toaster knows about."></i> 19 <i class="icon-question-sign get-help heading-help" title="This page lists all the layers compatible with {{project.release.name}} that Toaster knows about."></i>
20 </h1> 20 </h1>
21 </div> 21 </div>
22 22
23 <div id="zone1alerts"> 23 <div id="zone1alerts">
24
25 </div> 24 </div>
26 25
27 26
28 <div id="layer-added" class="alert alert-info lead" style="display:none;"></div>
29
30
31{% include "basetable_top_layers.html" %} 27{% include "basetable_top_layers.html" %}
32 {% for lv in objects %} 28 {% for o in objects %}
33 <tr class="data"> 29 <tr class="data">
34 <td class="layer"><a href="{% url 'layerdetails' lv.id %}">{{lv.layer.name}}</a></td> 30 <td class="layer"><a href="{% url 'layerdetails' o.id %}">{{o.layer.name}}</a></td>
35 <td class="description">{{lv.layer.summary}}</td> 31 <td class="description">{% if o.layer.summary %}{{o.layer.summary}}{%endif%}</td>
36 <td class="source"><a href="{% url 'layerdetails' lv.pk %}">{{lv.layer_source.name}}</a></td> 32 <td class="source"><a href="{% url 'layerdetails' o.pk %}">{{o.layer_source.name}}</a></td>
37 <td class="git-repo"><a href="{% url 'layerdetails' lv.pk %}"><code>{{lv.layer.vcs_url}}</code></a> 33 <td class="git-repo"><a href="{% url 'layerdetails' o.pk %}"><code>{{o.layer.vcs_url}}</code></a>
38 {% if lv.get_vcs_link_url %} 34 {% if o.get_vcs_link_url %}
39 <a target="_blank" href="{{ lv.get_vcs_link_url }}"><i class="icon-share get-info"></i></a> 35 <a target="_blank" href="{{ o.get_vcs_link_url }}"><i class="icon-share get-info"></i></a>
40 {% endif %} 36 {% endif %}
41 </td> 37 </td>
42 <td class="git-subdir" style="display: table-cell;"><a href="{% url 'layerdetails' lv.pk %}"><code>{{lv.dirpath}}</code></a> 38 <td class="git-subdir" style="display: table-cell;"><a href="{% url 'layerdetails' o.pk %}"><code>{{o.dirpath}}</code></a>
43 {% if lv.dirpath and lv.get_vcs_dirpath_link_url %} 39 {% if o.dirpath and o.get_vcs_dirpath_link_url %}
44 <a target="_blank" href="{{ lv.get_vcs_dirpath_link_url }}"><i class="icon-share get-info"></i></a> 40 <a target="_blank" href="{{ o.get_vcs_dirpath_link_url }}"><i class="icon-share get-info"></i></a>
45 {% endif %} 41 {% endif %}
46 </td> 42 </td>
47 <td class="branch">{% if lv.branch %}{{lv.branch}}{% else %}{{lv.up_branch.name}}{% endif %}</td> 43 <td class="branch">{% if o.branch %}{{o.branch}}{% else %}{{o.up_branch.name}}{% endif %}</td>
48 <td class="dependencies"> 44 <td class="dependencies">
49 {% with lvds=lv.dependencies.all%} 45 {% with ods=o.dependencies.all%}
50 {% if lvds.count %} 46 {% if ods.count %}
51 <a class="btn" 47 <a class="btn"
52 title="<a href='{% url "layerdetails" lv.pk %}'>{{lv.layer.name}}</a> dependencies" 48 title="<a href='{% url "layerdetails" o.pk %}'>{{o.layer.name}}</a> dependencies"
53 data-content="<ul class='unstyled'> 49 data-content="<ul class='unstyled'>
54 {% for i in lvds%} 50 {% for i in ods%}
55 <li><a href='{% url "layerdetails" i.depends_on.pk %}'>{{i.depends_on.layer.name}}</a></li> 51 <li><a href='{% url "layerdetails" i.depends_on.pk %}'>{{i.depends_on.layer.name}}</a></li>
56 {% endfor %} 52 {% endfor %}
57 </ul>"> 53 </ul>">
58 {{lvds.count}} 54 {{ods.count}}
59 </a> 55 </a>
60 {% endif %} 56 {% endif %}
61 {% endwith %} 57 {% endwith %}
62 </td> 58 </td>
63 <td class="add-del-layers" value="{{lv.pk}}"> 59 {% if project %}
64 <button id="layer-del-{{lv.pk}}" class="btn btn-danger btn-block remove-layer" style="display:none;" onclick="layerDel({{lv.pk}}, '{{lv.layer.name}}', '{%url 'layerdetails' lv.pk%}')"> 60 <td class="add-del-layers" value="{{o.pk}}">
61 <div id="layer-tooltip-{{o.pk}}" style="display: none; font-size: 11px; line-height: 1.3;" class="tooltip-inner">layer was modified</div>
62 <button id="layer-del-{{o.pk}}" class="btn btn-danger btn-block remove-layer layerbtn" style="display:none;" onclick="layerDel({{o.pk}}, '{{o.layer.name}}', '{%url 'layerdetails' o.pk%}')" >
65 <i class="icon-trash"></i> 63 <i class="icon-trash"></i>
66 Delete layer 64 Delete layer
67 </button> 65 </button>
68 <button id="layer-add-{{lv.pk}}" class="btn btn-block" style="display:none;" onclick="layerAdd({{lv.pk}}, '{{lv.layer.name}}', '{%url 'layerdetails' lv.pk%}')" > 66 <button id="layer-add-{{o.pk}}" class="btn btn-block layerbtn" style="display:none;" onclick="layerAdd({{o.pk}}, '{{o.layer.name}}', '{%url 'layerdetails' o.pk%}')" title="layer added">
69 <i class="icon-plus"></i> 67 <i class="icon-plus"></i>
70 Add layer 68 Add layer
71 </button> 69 </button>
72 </td> 70 </td>
71 {% endif %}
73 </tr> 72 </tr>
74 {% endfor %} 73 {% endfor %}
75{% include "basetable_bottom.html" %} 74{% include "basetable_bottom.html" %}
@@ -78,7 +77,7 @@
78 77
79 <!-- 'Layer dependencies modal' --> 78 <!-- 'Layer dependencies modal' -->
80 <div id="dependencies_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true"> 79 <div id="dependencies_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true">
81 <form id="dependencies_modal_form"> 80 <form id="dependencies_modal_form" style="margin: 0px">
82 <div class="modal-header"> 81 <div class="modal-header">
83 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button> 82 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
84 <h3><span class="layer-name"></span> dependencies</h3> 83 <h3><span class="layer-name"></span> dependencies</h3>
@@ -95,8 +94,11 @@
95 </form> 94 </form>
96 </div> 95 </div>
97 96
97{% if project %}
98<script> 98<script>
99 99
100var tooltipUpdateText;
101
100function _makeXHREditCall(data, onsuccess, onfail) { 102function _makeXHREditCall(data, onsuccess, onfail) {
101 $.ajax( { 103 $.ajax( {
102 type: "POST", 104 type: "POST",
@@ -120,13 +122,14 @@ function _makeXHREditCall(data, onsuccess, onfail) {
120 122
121 123
122function layerDel(layerId, layerName, layerURL) { 124function layerDel(layerId, layerName, layerURL) {
125 tooltipUpdateText = "1 layer deleted";
123 _makeXHREditCall({ 'layerDel': layerId }, function () { 126 _makeXHREditCall({ 'layerDel': layerId }, function () {
124 show_alert("<strong>1</strong> layer deleted from <a href=\"{% url 'project' project.id%}\">{{project.name}}</a>: <a href=\""+layerURL+"\">" + layerName +"</a>"); 127 show_alert("You have deleted <strong>1</strong> layer from <a href=\"{% url 'project' project.id%}\">{{project.name}}</a>: <a href=\""+layerURL+"\">" + layerName +"</a>");
125 }); 128 });
126} 129}
127 130
128function show_alert(text, cls) { 131function show_alert(text, cls) {
129 $("#zone1alerts").html("<div class=\"alert alert-info\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>" + text + "</div>"); 132 $("#zone1alerts").html("<div class=\"alert alert-info lead\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>" + text + "</div>");
130} 133}
131 134
132function show_dependencies_modal(layerId, layerName, layerURL, dependencies) { 135function show_dependencies_modal(layerId, layerName, layerURL, dependencies) {
@@ -142,25 +145,35 @@ function show_dependencies_modal(layerId, layerName, layerURL, dependencies) {
142 } 145 }
143 $('#dependencies_list').html(deplistHtml); 146 $('#dependencies_list').html(deplistHtml);
144 147
148 var selected = [layerId];
149 var layer_link_list = "<a href='"+layerURL+"'>"+layerName+"</a>";
150
145 $("#dependencies_modal_form").submit(function (e) { 151 $("#dependencies_modal_form").submit(function (e) {
146 e.preventDefault(); 152 e.preventDefault();
147 var selected = [layerId];
148 $("input[name='dependencies']:checked").map(function () { selected.push(parseInt($(this).val()))}); 153 $("input[name='dependencies']:checked").map(function () { selected.push(parseInt($(this).val()))});
154 if (selected.length > 1) {
155 tooltipUpdateText = "" + selected.length + " layers added";
156 } else {
157 tooltipUpdateText = "1 layer added";
158 }
149 159
150 _makeXHREditCall({ 'layerAdd': selected.join(",") }, function () { 160 for (var i = 0; i < selected.length; i++) {
151 var layer_link_list = "<a href='"+layerURL+"'>"+layerName+"</a>"; 161 for (var j = 0; j < dependencies.length; j++) {
152 for (var i = 0; i < selected.length; i++) { 162 if (dependencies[j].id == selected[i]) {
153 for (var j = 0; j < dependencies.length; i++) { 163 layer_link_list+= ", <a href='"+dependencies[j].layerdetailurl+"'>"+dependencies[j].name+"</a>"
154 if (dependencies[j].id == selected[i]) { 164 break;
155 layer_link_list+= ", <a href='"+dependencies[j].layerdetailurl+"'>"+dependencies[j].name+"</a>"
156 break;
157 }
158 } 165 }
159 } 166 }
167 }
168
169 $('#dependencies_modal').modal('hide');
160 170
161 $('#dependencies_modal').modal('hide'); 171 {% if project %}
162 show_alert("<strong>"+selected.length+"</strong> layers added to <a href=\"{% url 'project' project.id%}\">{{project.name}}</a>:" + layer_link_list); 172 _makeXHREditCall({ 'layerAdd': selected.join(",") }, function () {
173 show_alert("You have added <strong>"+selected.length+"</strong> layers to <a href=\"{% url 'project' project.id%}\">{{project.name}}</a>: " + layer_link_list);
163 }); 174 });
175 {% endif %}
176
164 }); 177 });
165 $('#dependencies_modal').modal('show'); 178 $('#dependencies_modal').modal('show');
166} 179}
@@ -178,8 +191,9 @@ function layerAdd(layerId, layerName, layerURL) {
178 show_dependencies_modal(layerId, layerName, layerURL, _data.list); 191 show_dependencies_modal(layerId, layerName, layerURL, _data.list);
179 } 192 }
180 else { 193 else {
194 tooltipUpdateText = "1 layer added";
181 _makeXHREditCall({ 'layerAdd': layerId }, function () { 195 _makeXHREditCall({ 'layerAdd': layerId }, function () {
182 show_alert("<strong>1</strong> layer added to <a href=\"{% url 'project' project.id%}\">{{project.name}}</a>: <a href=\""+layerURL+"\">" + layerName +"</a>"); 196 show_alert("You have added <strong>1</strong> layer to <a href=\"{% url 'project' project.id%}\">{{project.name}}</a>: <a href=\""+layerURL+"\">" + layerName +"</a>");
183 }); 197 });
184 } 198 }
185 } 199 }
@@ -188,15 +202,31 @@ function layerAdd(layerId, layerName, layerURL) {
188} 202}
189 203
190function button_set(id, state) { 204function button_set(id, state) {
205 var tohide, toshow;
191 if (state == "add") 206 if (state == "add")
192 { 207 {
193 $("#layer-add-" + id).show(); 208 tohide = "#layer-del-";
194 $("#layer-del-" + id).hide(); 209 toshow = "#layer-add-";
195 } 210 }
196 else if (state == "del") 211 else if (state == "del")
197 { 212 {
198 $("#layer-add-" + id).hide(); 213 tohide = "#layer-add-";
199 $("#layer-del-" + id).show(); 214 toshow = "#layer-del-";
215 }
216
217
218 var previouslyvisible = $(tohide + id).is(":visible");
219 if (previouslyvisible) {
220 $(tohide + id).fadeOut( function() {
221 $("#layer-tooltip-" + id).text(tooltipUpdateText);
222 $("#layer-tooltip-" + id).fadeIn().delay(2000).fadeOut(function(){
223 $(toshow + id).delay(300).fadeIn();
224 });
225 });
226 } else {
227 $(tohide + id).hide();
228 $("#layer-tooltip-" + id).hide();
229 $(toshow + id).show();
200 } 230 }
201}; 231};
202 232
@@ -214,9 +244,11 @@ function updateButtons(projectLayers) {
214} 244}
215 245
216$(document).ready(function (){ 246$(document).ready(function (){
247 $('.layerbtn').tooltip({ trigger: 'manual' });
217 updateButtons({{projectlayerset}}); 248 updateButtons({{projectlayerset}});
218}); 249});
219 250
220</script> 251</script>
252{%endif%}
221 253
222{% endblock %} 254{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/templates/mrb_section.html b/bitbake/lib/toaster/toastergui/templates/mrb_section.html
index 3d17ac62e4..586c47bfae 100644
--- a/bitbake/lib/toaster/toastergui/templates/mrb_section.html
+++ b/bitbake/lib/toaster/toastergui/templates/mrb_section.html
@@ -44,7 +44,7 @@
44 Build time: <a href="{% url 'buildtime' build.pk %}">{{ build.timespent|sectohms }}</a> 44 Build time: <a href="{% url 'buildtime' build.pk %}">{{ build.timespent|sectohms }}</a>
45 </span> 45 </span>
46 {% if build.project %} 46 {% if build.project %}
47 <a class="btn {%if build.outcome == build.SUCCEEDED%}btn-success{%elif build.outcome == build.FAILED%}btn-danger{%else%}btn-info{%endif%} pull-right" onclick="scheduleBuild({%url 'xhr_projectbuild' build.project.id as myurl %}{{myurl|json}}, {{build.project.name|json}}, {{build.get_sorted_target_list|mapselect:'target'|json}})">Run again</a> 47 <a class="btn {%if build.outcome == build.SUCCEEDED%}btn-success{%elif build.outcome == build.FAILED%}btn-danger{%else%}btn-info{%endif%} pull-right" onclick="scheduleBuild({% url 'xhr_projectbuild' build.project.id as bpi%}{{bpi|json}}, {{build.project.name|json}}, {{build.get_sorted_target_list|mapselect:'target'|json}})">Run again</a>
48 {% endif %} 48 {% endif %}
49 </div> 49 </div>
50 {%endif%} 50 {%endif%}
@@ -81,19 +81,18 @@ function _makeXHRBuildCall(url, data, onsuccess, onfail) {
81 alert("Call failed"); 81 alert("Call failed");
82 console.log(_data); 82 console.log(_data);
83 if (onfail) onfail(data); 83 if (onfail) onfail(data);
84 } 84 } });
85 });
86} 85}
87 86
88 87
89function scheduleBuild(url, projectName, buildlist) { 88function scheduleBuild(url, projectName, buildlist) {
90 console.log("scheduleBuild"); 89 console.log("scheduleBuild");
91// _makeXHRBuildCall(url , {targets: buildlist.join(" ")}, function (_data) { 90 _makeXHRBuildCall(url, {targets: buildlist.join(" ")}, function (_data) {
92 91
93 $('#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">' + 92 $('#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">' +
94 '<div class="span4 lead">' + buildlist.join(" ") + 93 '<div class="span4 lead">' + buildlist.join(" ") +
95 '</div><div class="span4 lead pull-right">Build queued. Your build will start shortly.</div></div></div>'); 94 '</div><div class="span4 lead pull-right">Build queued. Your build will start shortly.</div></div></div>');
96// } 95 });
97} 96}
98 97
99</script> 98</script>
diff --git a/bitbake/lib/toaster/toastergui/templates/project.html b/bitbake/lib/toaster/toastergui/templates/project.html
index 9399b312ca..6a812834d3 100644
--- a/bitbake/lib/toaster/toastergui/templates/project.html
+++ b/bitbake/lib/toaster/toastergui/templates/project.html
@@ -76,6 +76,14 @@ vim: expandtab tabstop=2
76 </div> 76 </div>
77 </script> 77 </script>
78 78
79 <script type="text/ng-template" id="target_display">
80 <div ng-switch on="t.task.length">
81 <div ng-switch-when="0">{[t.target]}</div>
82 <div ng-switch-default>{[t.target]}:{[t.task]}</div>
83 </div>
84 </script>
85
86
79 <!-- build form --> 87 <!-- build form -->
80 <div class="well"> 88 <div class="well">
81 <form class="build-form" ng-submit="targetNamedBuild()"> 89 <form class="build-form" ng-submit="targetNamedBuild()">
@@ -99,11 +107,11 @@ vim: expandtab tabstop=2
99 107
100 <h2 class="air" ng-if="builds.length">Latest builds</h2> 108 <h2 class="air" ng-if="builds.length">Latest builds</h2>
101 109
102 <div class="alert" ng-repeat="b in builds" ng-class="{'queued':'alert-info', 'deleted':'alert-info', 'in progress': 'alert-info', 'In Progress':'alert-info', 'Succeeded':'alert-success', 'failed':'alert-error', 'Failed':'alert-error'}[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]" >
103 <div class="row-fluid"> 111 <div class="row-fluid">
104 <switch ng-switch="b.status"> 112 <switch ng-switch="b.status">
105 <case ng-switch-when="failed"> 113 <case ng-switch-when="failed">
106 <div class="lead span3"> <span ng-repeat="t in b.targets">{[t.target]} </span> </div> 114 <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div>
107 <div class="row-fluid"> 115 <div class="row-fluid">
108 <div class="air well" ng-repeat="e in b.errors"> 116 <div class="air well" ng-repeat="e in b.errors">
109 {[e.type]}: <pre>{[e.msg]}</pre> 117 {[e.type]}: <pre>{[e.msg]}</pre>
@@ -111,53 +119,51 @@ vim: expandtab tabstop=2
111 </div> 119 </div>
112 </case> 120 </case>
113 <case ng-switch-when="queued"> 121 <case ng-switch-when="queued">
114 <div class="lead span5"> <span ng-repeat="t in b.targets">{[t.target]} </span> </div> 122 <div class="lead span5"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div>
115 <div class="span4 lead" >Build queued 123 <div class="span4 lead" >Build queued
116 <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> 124 <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>
117 </div> 125 </div>
118 <button class="btn pull-right btn-info" ng-click="buildCancel(b.id)">Cancel</button> 126 <button class="btn pull-right btn-info" ng-click="buildCancel(b.id)">Cancel</button>
119 </case> 127 </case>
120 <case ng-switch-when="created"> 128 <case ng-switch-when="created">
121 <div class="lead span3"> <span ng-repeat="t in b.targets">{[t.target]} </span> </div> 129 <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div>
122 <div class="span6" > 130 <div class="span6" >
123 <span class="lead">Creating build</span> 131 <span class="lead">Creating build</span>
124 </div> 132 </div>
125 <button class="btn pull-right btn-info" ng-click="buildCancel(b.id)">Cancel</button> 133 <button class="btn pull-right btn-info" ng-click="buildCancel(b.id)">Cancel</button>
126 </case> 134 </case>
127 <case ng-switch-when="deleted"> 135 <case ng-switch-when="deleted">
128 <div class="lead span3"> <span ng-repeat="t in b.targets">{[t.target]} </span> </div> 136 <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div>
129 <div class="span6" id="{[b.id]}-deleted" > 137 <div class="span6" id="{[b.id]}-deleted" >
130 <span class="lead">Build deleted</span> 138 <span class="lead">Build deleted</span>
131 </div> 139 </div>
132 <button class="btn pull-right btn-info" ng-click="builds.splice(builds.indexOf(b), 1)">Close</button> 140 <button class="btn pull-right btn-info" ng-click="builds.splice(builds.indexOf(b), 1)">Close</button>
133 </case> 141 </case>
134 <case ng-switch-when="in progress"> 142 <case ng-switch-when="in progress">
135 <div class="lead span3"> <span ng-repeat="t in b.targets">{[t.target]} </span> </div> 143 <div class="lead span3"> <span ng-repeat="t in b.targets" ng-include src="'target_display'"></span> </div>
136 <div class="span4" >
137 </div>
138 <div class="lead pull-right">Build starting shortly</div>
139 </case>
140 <case ng-switch-when="In Progress">
141 <div class="span4" > 144 <div class="span4" >
142 <div class="progress" style="margin-top:5px;" data-toggle="tooltip" tooltip="{[b.completeper]}% of tasks complete"> 145 <div class="progress" style="margin-top:5px;" data-toggle="tooltip" tooltip="{[b.build[0].completeper]}% of tasks complete">
143 <div style="width: {[b.completeper]}%;" class="bar"></div> 146 <div style="width: {[b.build[0].completeper]}%;" class="bar"></div>
144 </div> 147 </div>
145 </div> 148 </div>
146 <div class="lead pull-right">ETA: at {[b.eta]}</div> 149 <div class="lead pull-right">ETA: at {[b.build[0].eta|date:"shortDate"]}</div>
147 </case> 150 </case>
148 <case ng-switch-default=""> 151 <case ng-switch-when="completed">
149 <div class="lead span3"><a href="{[b.build_page_url]}"><span ng-repeat="t in b.targets">{[t.target]} </span> </div></a> 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>
150 <div class="span2 lead"> 153 <div class="span2 lead">
151 {[b.completed_on|date:'dd/MM/yy HH:mm']} 154 {[b.build[0].completed_on|date:'dd/MM/yy HH:mm']}
152 </div> 155 </div>
153 <div class="span2"><span>{[b.errors.len]}</span></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>
154 <div class="span2"><span>{[b.warnings.len]}</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>
155 <div> <span class="lead">Build time: {[b.build_time|date:"HH:mm"]}</span> 158 <div> <span class="lead">Build time: {[b.build[0].build_time|timediff]}</span>
156 <button class="btn pull-right" ng-class="{'Succeeded': 'btn-success', 'Failed': 'btn-danger'}[b.status]" 159 <button class="btn pull-right" ng-class="{'Succeeded': 'btn-success', 'Failed': 'btn-danger'}[b.build[0].status]"
157 ng-click="targetExistingBuild(b.targets)">Run again</button> 160 ng-click="targetExistingBuild(b.targets)">Run again</button>
158 161
159 </div> 162 </div>
160 </case> 163 </case>
164 <case ng-switch-default="">
165 <div>FIXME!</div>
166 </case>
161 </switch> 167 </switch>
162 <div class="lead pull-right"> 168 <div class="lead pull-right">
163 </div> 169 </div>
diff --git a/bitbake/lib/toaster/toastergui/templates/targets.html b/bitbake/lib/toaster/toastergui/templates/targets.html
index 3afdf0a5e9..32a644a743 100644
--- a/bitbake/lib/toaster/toastergui/templates/targets.html
+++ b/bitbake/lib/toaster/toastergui/templates/targets.html
@@ -9,55 +9,74 @@
9{% block projectinfomain %} 9{% block projectinfomain %}
10 <div class="page-header"> 10 <div class="page-header">
11 <h1> 11 <h1>
12 All targets 12 {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %}
13 <i class="icon-question-sign get-help heading-help" title="This page lists all the targets compatible with Yocto Project 1.7 'Dxxxx' that Toaster knows about. They include community-created targets suitable for use on top of OpenEmbedded Core and any targets you have imported"></i> 13 {{objects.paginator.count}} target{{objects.paginator.count|pluralize}} found
14 {% elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
15 No targets found
16 {%else%}
17 All targets
18 {%endif%}
19 <i class="icon-question-sign get-help heading-help" title="This page lists all the targets compatible with " + {{project.release.name}} + " that Toaster knows about."></i>
14 </h1> 20 </h1>
15 </div> 21 </div>
16 <!--div class="alert">
17 <div class="input-append" style="margin-bottom:0px;">
18 <input class="input-xxlarge" type="text" placeholder="Search targets" value="browser" />
19 <a class="add-on btn">
20 <i class="icon-remove"></i>
21 </a>
22 <button class="btn" type="button">Search</button>
23 <a class="btn btn-link" href="#">Show all targets</a>
24 </div>
25 </div-->
26 <div id="target-added" class="alert alert-info lead" style="display:none;"></div>
27 <div id="target-removed" class="alert alert-info lead" style="display:none;">
28 <button type="button" class="close" data-dismiss="alert">&times;</button>
29 <strong>1</strong> target deleted from <a href="project-with-targets.html">your project</a>: <a href="#">meta-aarch64</a>
30 </div>
31 22
23 <div id="zone1alerts">
24
25 </div>
26
27{% if objects.paginator.count == 0 %}
28 <div class="row-fluid">
29 <div class="alert">
30 <form class="no-results input-append" id="searchform">
31 <input id="search" name="search" class="input-xxlarge" type="text" value="{{request.GET.search}}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>{% endif %}
32 <button class="btn" type="submit" value="Search">Search</button>
33 <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all targets</button>
34 </form>
35 </div>
36 </div>
37
38{% else %}
32 39
33{% include "basetable_top.html" %} 40{% include "basetable_top.html" %}
34 {% for o in objects %} 41 {% for o in objects %}
35 <tr class="data"> 42 <tr class="data">
36 <td class="target"> 43 <td class="target">
37 {{o.name}} ({{o.id}}, {{o.up_id}}) 44 {{o.name}}
38 <a target="_blank" href="{{o.get_layersource_view_url}}"><i class="icon-share get-info"></i></a> 45 <a target="_blank" href="{{o.get_layersource_view_url}}"><i class="icon-share get-info"></i></a>
39 </td> 46 </td>
40 <td class="version">{{o.version}}</td> 47 <td class="version">{{o.version}}</td>
41 <td class="description">{{o.description}}</td> 48 <td class="description">{% if o.description %}{{o.description}}{% else %}{{o.summary}}{%endif%}</td>
42 <td class="recipe-file"> 49 <td class="recipe-file">
43 <code>{{o.file_path}}</code> 50 <code>{{o.file_path}}</code>
44 <a href="{{o.get_vcs_link_url}}" target="_blank"><i class="icon-share get-info"></i></a> 51 <a href="{{o.get_vcs_link_url}}{{o.file_path}}" target="_blank"><i class="icon-share get-info"></i></a>
45 </td> 52 </td>
46 <td class="target-section">{{o.section}}</td> 53 <td class="target-section">{{o.section}}</td>
47 <td class="license">{{o.license}}</td> 54 <td class="license">{{o.license}}</td>
48 <td class="layer"><a href="#">{{o.layer_version.layer.name}}</a></td> 55 <td class="layer"><a href="{% url 'layerdetails' o.layer_version.id%}">{{o.layer_version.layer.name}}</a></td>
49 <td class="source">{{o.layer_source.name}}</td> 56 <td class="source">{{o.layer_source.name}}</td>
50 <td class="branch">{{o.layer_version.commit}}</td> 57 <td class="branch">
51 <td class="build"> 58 {% if o.layer_version.up_branch %}
52 <a id="build-target" href="project-with-targets.html?target=3g-router-image" class="btn btn-block" style="display:none;"> 59 {{o.layer_version.up_branch.name}}
53 Build target 60 {% else %}
54 </a> 61 <a class="btn"
55 <a id="add-layer" href="#" class="btn btn-block nopop" title="1 layer added"> 62 data-content="<ul class='unstyled'>
56 <i class="icon-plus"></i> 63 <li>{{o.layer_version.commit}}</li>
57 Add layer 64 </ul>">
58 <i class="icon-question-sign get-help" title="To build this target, you must first add the meta-embeddedgeeks layer to your project"></i> 65 {{o.layer_version.commit|truncatechars:13}}
59 </a> 66 </a>
60 </td> 67 {% endif %}
68 </td>
69 <td class="add-layer" value="{{o.pk}}" layerversion_id="{{o.layer_version.pk}}">
70 <div id="layer-tooltip-{{o.pk}}" style="display: none; font-size: 11px; line-height: 1.3;" class="tooltip-inner">layer was modified</div>
71 <a href="{% url 'project' project.id %}#/targetbuild={{o.name}}" id="target-build-{{o.pk}}" class="btn btn-block remove-layer" style="display:none;" >
72 Build target
73 </a>
74 <a id="layer-add-{{o.pk}}" class="btn btn-block" style="display:none;" href="javascript:layerAdd({{o.layer_version.pk}}, '{{o.layer_version.layer.name}}', '{%url 'layerdetails' o.layer_version.pk%}', {{o.pk}})" >
75 <i class="icon-plus"></i>
76 Add layer
77 <i title="" class="icon-question-sign get-help" data-original-title="To build this target, you must first add the {{o.layer_version.layer.name}} layer to your project"></i>
78 </a>
79 </td>
61 </tr> 80 </tr>
62 {% endfor %} 81 {% endfor %}
63{% include "basetable_bottom.html" %} 82{% include "basetable_bottom.html" %}
@@ -65,122 +84,177 @@
65 <!-- Modals --> 84 <!-- Modals -->
66 85
67 <!-- 'Layer dependencies modal' --> 86 <!-- 'Layer dependencies modal' -->
68 <div id="dependencies-message" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true"> 87 <div id="dependencies_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true">
88 <form id="dependencies_modal_form">
69 <div class="modal-header"> 89 <div class="modal-header">
70 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button> 90 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
71 <h3>meta-acer dependencies</h3> 91 <h3><span class="layer-name"></span> dependencies</h3>
72 </div> 92 </div>
73 <div class="modal-body"> 93 <div class="modal-body">
74 <p><strong>meta-acer</strong> depends on some targets that are not added to your project. Select the ones you want to add:</p> 94 <p><strong class="layer-name"></strong> depends on some layers that are not added to your project. Select the ones you want to add:</p>
75 <ul class="unstyled"> 95 <ul class="unstyled" id="dependencies_list">
76 <li>
77 <label class="checkbox">
78 <input type="checkbox" checked="checked">
79 meta-android
80 </label>
81 </li>
82 <li>
83 <label class="checkbox">
84 <input type="checkbox" checked="checked">
85 meta-oe
86 </label>
87 </li>
88 </ul> 96 </ul>
89 </div> 97 </div>
90 <div class="modal-footer"> 98 <div class="modal-footer">
91 <button id="add-target-dependencies" type="submit" class="btn btn-primary" data-dismiss="modal" >Add targets</button> 99 <button class="btn btn-primary" type="submit">Add layers</button>
92 <button class="btn" data-dismiss="modal">Cancel</button> 100 <button class="btn" type="reset" data-dismiss="modal">Cancel</button>
93 </div> 101 </div>
102 </form>
94 </div> 103 </div>
95 104
96 <script src="assets/js/jquery-1.9.1.min.js" type='text/javascript'></script> 105{% endif %}
97 <script src="assets/js/jquery.tablesorter.min.js" type='text/javascript'></script> 106
98 <script src="assets/js/jquery-ui-1.10.3.custom.min.js"></script> 107{% if project %}
99 <script src="assets/js/bootstrap.min.js" type='text/javascript'></script> 108<script>
100 <script src="assets/js/prettify.js" type='text/javascript'></script> 109
101 <script src="assets/js/jit.js" type='text/javascript'></script> 110var tooltipUpdateText;
102 <script src="assets/js/main.js" type='text/javascript'></script> 111
103 112function _makeXHREditCall(data, onsuccess, onfail) {
104 <script> 113 $.ajax( {
105 $(document).ready(function() { 114 type: "POST",
106 115 url: "{% url 'xhr_projectedit' project.id %}",
107 //show or hide selected columns on load 116 data: data,
108 $("input:checkbox").each(function(){ 117 headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
109 var selectedType = $(this).val(); 118 success: function (_data) {
110 if($(this).is(":checked")){ 119 if (_data.error != "ok") {
111 $("."+selectedType).show(); 120 alert(_data.error);
121 } else {
122 updateButtons(_data.layers.map(function (e) {return e.id}));
123 if (onsuccess != undefined) onsuccess(_data);
112 } 124 }
113 else{ 125 },
114 $("."+selectedType).hide(); 126 error: function (_data) {
127 alert("Call failed");
128 console.log(_data);
129 }
130 });
131}
132
133function show_alert(text, cls) {
134 $("#zone1alerts").html("<div class=\"alert alert-info lead\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>" + text + "</div>");
135}
136
137
138function show_dependencies_modal(layerId, layerName, layerURL, dependencies) {
139 // update layer name
140 $('.layer-name').text(layerName);
141 var deplistHtml = "";
142 for (var i = 0; i < dependencies.length; i++) {
143 deplistHtml += "<li><label class=\"checkbox\"><input name=\"dependencies\" value=\""
144 deplistHtml += dependencies[i].id;
145 deplistHtml +="\" type=\"checkbox\" checked=\"checked\"/>";
146 deplistHtml += dependencies[i].name;
147 deplistHtml += "</label></li>";
148 }
149 $('#dependencies_list').html(deplistHtml);
150
151 var selected = [layerId];
152 var layer_link_list = undefined;
153
154 $("#dependencies_modal_form").submit(function (e) {
155 e.preventDefault();
156 $("input[name='dependencies']:checked").map(function () { selected.push(parseInt($(this).val()))});
157 layer_link_list = "<a href='"+layerURL+"'>"+layerName+"</a>";
158 if (selected.length > 1) {
159 tooltipUpdateText = "" + selected.length + " layers added";
160 } else {
161 tooltipUpdateText = "1 layer added";
162 }
163
164 for (var i = 0; i < selected.length; i++) {
165 for (var j = 0; j < dependencies.length; j++) {
166 if (dependencies[j].id == selected[i]) {
167 layer_link_list+= ", <a href='"+dependencies[j].layerdetailurl+"'>"+dependencies[j].name+"</a>"
168 break;
169 }
115 } 170 }
171 }
172
173 $('#dependencies_modal').modal('hide');
174
175 {% if project %}
176 _makeXHREditCall({ 'layerAdd': selected.join(",") }, function onXHRSuccess() {
177 show_alert("You have added <strong>"+selected.length+"</strong> layer(s) to <a href=\"{% url 'project' project.id%}\">{{project.name}}</a>:" + layer_link_list);
116 }); 178 });
179 {% endif %}
117 180
118 // enable add target button 181 });
119 $('#add-target-with-deps').removeAttr('disabled'); 182 $('#dependencies_modal').modal('show');
183}
120 184
121 //edit columns functionality (show / hide table columns)
122 $("input:checkbox").change();
123 $("input:checkbox").change(function(){
124 var selectedType = $(this).val();
125 if($(this).is(":checked")){
126 $("."+selectedType).show();
127 }
128 else{
129 $("."+selectedType).hide();
130 }
131 });
132 185
133 //turn edit columns dropdown into a multi-select menu 186var pressedButton = undefined;
134 $('.dropdown-menu input, .dropdown-menu label').click(function(e) {
135 e.stopPropagation();
136 });
137 187
138 //show tooltip with applied filter 188function layerAdd(layerId, layerName, layerURL, pressedButtonId) {
139 $('#filtered').tooltip({container:'table', placement:'bottom', delay:{hide:1500}, html:true}); 189 pressedButton = pressedButtonId;
190 $.ajax({
191 url: '{% url "xhr_datatypeahead" %}',
192 data: {'type': 'layerdeps','value':layerId},
193 success: function(_data) {
194 if (_data.error != "ok") {
195 alert(_data.error);
196 } else {
197 if (_data.list.length > 0) {
198 show_dependencies_modal(layerId, layerName, layerURL, _data.list);
199 }
200 else {
201 tooltipUpdateText = "1 layer added";
202 _makeXHREditCall({ 'layerAdd': layerId }, function () {
203 show_alert("You have added <strong>1</strong> layer to <a href=\"{% url 'project' project.id%}\">{{project.name}}</a>: <a href=\""+layerURL+"\">" + layerName +"</a>");
204 });
205 }
206 }
207 }
208 })
209}
140 210
141 $('#filtered').click(function() { 211function buttonSet(id, state) {
142 $(this).tooltip('hide'); 212 var tohide, toshow;
143 }); 213 if (state == "add")
214 {
215 toshow = "#layer-add-";
216 tohide = "#target-build-";
217 }
218 else if (state == "build")
219 {
220 tohide = "#layer-add-";
221 toshow = "#target-build-";
222 }
144 223
145 //show target added tooltip 224 var previouslyvisible = $(tohide + id).is(":visible");
146 $("#remove-target, #add-target, #add-target-with-deps2").tooltip({ trigger: 'manual' }); 225 if (previouslyvisible && id == pressedButton) {
147 226 $(tohide + id).fadeOut( function() {
148 // add target without dependencies 227 $("#layer-tooltip-" + id).text(tooltipUpdateText);
149 $("#add-target").click(function(){ 228 $("#layer-tooltip-" + id).fadeIn().delay(2000).fadeOut(function(){
150 $('#target-removed').hide(); 229 $(toshow + id).delay(300).fadeIn();
151 $('#target-added').html('<button type="button" class="close" data-dismiss="alert">&times;</button><strong>1</strong> target added to <a href="project-with-targets.html">your project</a>: <a href="#">meta-aarch64</a>').fadeIn();
152 $('#add-target').tooltip('show');
153 $("#add-target").hide();
154 $(".add-targets .tooltip").delay(2000).fadeOut(function(){
155 $("#remove-target").delay(300).fadeIn();
156 }); 230 });
157 }); 231 });
232 } else {
233 $(tohide + id).hide();
234 $("#layer-tooltip-" + id).hide();
235 $(toshow + id).show();
236 }
237};
158 238
159 // add target with dependencies
160 $(document).on("click", "#add-target-dependencies", function() {
161 $('#target-removed').hide();
162 $('#target-added').html('<button type="button" class="close" data-dismiss="alert">&times;</button><strong>3</strong> targets added to <a href="project-with-targets.html">your project</a>: <a href="#">meta-acer</a> and its dependencies <a href="#">meta-android</a> and <a href="#">meta-oe</a>').delay(400).fadeIn(function(){
163 $('#add-target-with-deps').tooltip('show');
164 $("#add-target-with-deps, #add-target-with-deps").hide();
165 $(".add-targets .tooltip").delay(2000).fadeOut(function(){
166 $("#remove-target-with-deps").delay(300).fadeIn();
167 });
168 });
169 });
170 239
171 // delete target 240function updateButtons(projectLayers) {
172 $("#remove-target").click(function(){ 241 var displayedLayers = [];
173 $('#target-added').hide(); 242 $(".add-layer").map(function () { displayedLayers.push( { "l": parseInt($(this).attr('layerversion_id')), "i": parseInt($(this).attr('value'))})});
174 $('#target-removed').show(); 243 for (var i=0; i < displayedLayers.length; i++) {
175 $('#remove-target').tooltip('show'); 244 if (projectLayers.indexOf(displayedLayers[i].l) > -1) {
176 $("#remove-target").hide(); 245 buttonSet(displayedLayers[i].i, "build");
177 $(".add-targets .tooltip").delay(2000).fadeOut(function(){ 246 }
178 $("#add-target").delay(300).fadeIn(); 247 else {
179 }); 248 buttonSet(displayedLayers[i].i, "add");
180 }); 249 }
250 }
251}
181 252
182 }); 253$(document).ready(function (){
254 updateButtons({{projectlayerset}});
255});
183 256
184</script> 257</script>
258{%endif%}
185 259
186{% endblock %} 260{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index e568ee70ed..fb8075067a 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -123,7 +123,7 @@ def _redirect_parameters(view, g, mandatory_parameters, *args, **kwargs):
123 params[i] = g[i] 123 params[i] = g[i]
124 for i in mandatory_parameters: 124 for i in mandatory_parameters:
125 if not i in params: 125 if not i in params:
126 params[i] = mandatory_parameters[i] 126 params[i] = urllib.unquote(str(mandatory_parameters[i]))
127 127
128 return redirect(url + "?%s" % urllib.urlencode(params), *args, **kwargs) 128 return redirect(url + "?%s" % urllib.urlencode(params), *args, **kwargs)
129 129
@@ -202,6 +202,7 @@ def _get_search_results(search_term, queryset, model):
202 202
203 search_objects.append(reduce(operator.or_, q_map)) 203 search_objects.append(reduce(operator.or_, q_map))
204 search_object = reduce(operator.and_, search_objects) 204 search_object = reduce(operator.and_, search_objects)
205 print "search objects", search_object
205 queryset = queryset.filter(search_object) 206 queryset = queryset.filter(search_object)
206 207
207 return queryset 208 return queryset
@@ -1914,8 +1915,7 @@ if toastermain.settings.MANAGED:
1914 login(request, user) 1915 login(request, user)
1915 1916
1916 # save the project 1917 # save the project
1917 prj = Project.objects.create_project(name = request.POST['projectname'], 1918 prj = Project.objects.create_project(name = request.POST['projectname'], release = Release.objects.get(pk = request.POST['projectversion']))
1918 release = Release.objects.get(pk = request.POST['projectversion']))
1919 prj.user_id = request.user.pk 1919 prj.user_id = request.user.pk
1920 prj.save() 1920 prj.save()
1921 return redirect(reverse(project, args = (prj.pk,)) + "#/newproject") 1921 return redirect(reverse(project, args = (prj.pk,)) + "#/newproject")
@@ -1933,36 +1933,21 @@ if toastermain.settings.MANAGED:
1933 1933
1934 1934
1935 def _project_recent_build_list(prj): 1935 def _project_recent_build_list(prj):
1936 # build requests not yet started 1936 return map(lambda x: {
1937 return (map(lambda x: {
1938 "id": x.pk,
1939 "targets" : map(lambda y: {"target": y.target }, x.brtarget_set.all()),
1940 "status": x.get_state_display(),
1941 }, prj.buildrequest_set.filter(state__lt = BuildRequest.REQ_INPROGRESS).order_by("-pk")) +
1942 # build requests started, but with no build yet
1943 map(lambda x: {
1944 "id": x.pk, 1937 "id": x.pk,
1945 "targets" : map(lambda y: {"target": y.target }, x.brtarget_set.all()), 1938 "targets" : map(lambda y: {"target": y.target, "task": y.task }, x.brtarget_set.all()),
1946 "status": x.get_state_display(),
1947 }, prj.buildrequest_set.filter(state = BuildRequest.REQ_INPROGRESS, build = None).order_by("-pk")) +
1948 # build requests that failed
1949 map(lambda x: {
1950 "id": x.pk,
1951 "targets" : map(lambda y: {"target": y.target }, x.brtarget_set.all()),
1952 "status": x.get_state_display(), 1939 "status": x.get_state_display(),
1953 "errors": map(lambda y: {"type": y.errtype, "msg": y.errmsg, "tb": y.traceback}, x.brerror_set.all()), 1940 "errors": map(lambda y: {"type": y.errtype, "msg": y.errmsg, "tb": y.traceback}, x.brerror_set.all()),
1954 }, prj.buildrequest_set.filter(state = BuildRequest.REQ_FAILED).order_by("-pk")) + 1941 "build" : map( lambda y: {"id": y.pk,
1955 # and already made builds 1942 "status": y.get_outcome_display(),
1956 map(lambda x: { 1943 "completed_on" : y.completed_on.strftime('%s')+"000",
1957 "id": x.pk, 1944 "build_time" : (y.completed_on - y.started_on).total_seconds(),
1958 "targets": map(lambda y: {"target": y.target }, x.target_set.all()), 1945 "build_page_url" : reverse('builddashboard', args=(y.pk,)),
1959 "status": x.get_outcome_display(), 1946 "errors": y.errors_no,
1960 "completed_on" : x.completed_on.strftime('%s')+"000", 1947 "warnings": y.warnings_no,
1961 "build_time" : (x.completed_on - x.started_on).total_seconds(), 1948 "completeper": y.completeper(),
1962 "build_page_url" : reverse('builddashboard', args=(x.pk,)), 1949 "eta": y.eta().ctime()}, Build.objects.filter(buildrequest = x)),
1963 "completeper": x.completeper(), 1950 }, prj.buildrequest_set.order_by("-pk")[:5])
1964 "eta": x.eta().ctime(),
1965 }, prj.build_set.all()))
1966 1951
1967 1952
1968 # Shows the edit project page 1953 # Shows the edit project page
@@ -2025,10 +2010,14 @@ if toastermain.settings.MANAGED:
2025 2010
2026 if 'buildCancel' in request.POST: 2011 if 'buildCancel' in request.POST:
2027 for i in request.POST['buildCancel'].strip().split(" "): 2012 for i in request.POST['buildCancel'].strip().split(" "):
2028 br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED) 2013 try:
2029 print "selected for delete", br.pk 2014 br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED)
2030 br.delete() 2015 print "selected for delete", br.pk
2031 print "selected for delete", br.pk 2016 br.delete()
2017 print "selected for delete", br.pk
2018 except BuildRequest.DoesNotExist:
2019 pass
2020
2032 2021
2033 if 'targets' in request.POST: 2022 if 'targets' in request.POST:
2034 ProjectTarget.objects.filter(project = prj).delete() 2023 ProjectTarget.objects.filter(project = prj).delete()
@@ -2059,7 +2048,7 @@ if toastermain.settings.MANAGED:
2059 # remove layers 2048 # remove layers
2060 if 'layerDel' in request.POST: 2049 if 'layerDel' in request.POST:
2061 for t in request.POST['layerDel'].strip().split(" "): 2050 for t in request.POST['layerDel'].strip().split(" "):
2062 pt = ProjectLayer.objects.get(project = prj, layercommit_id = int(t)).delete() 2051 pt = ProjectLayer.objects.filter(project = prj, layercommit_id = int(t)).delete()
2063 2052
2064 if 'projectName' in request.POST: 2053 if 'projectName' in request.POST:
2065 prj.name = request.POST['projectName'] 2054 prj.name = request.POST['projectName']
@@ -2071,8 +2060,8 @@ if toastermain.settings.MANAGED:
2071 prj.save() 2060 prj.save()
2072 # we need to change the layers 2061 # we need to change the layers
2073 for i in prj.projectlayer_set.all(): 2062 for i in prj.projectlayer_set.all():
2074 # find and add a similarly-named layer from the same layer source on the new branch 2063 # find and add a similarly-named layer on the new branch
2075 lv = Layer_Version.objects.filter(layer_source = i.layercommit.layer_source, layer__name = i.layercommit.layer.name, up_branch__in = Branch.objects.filter(name = prj.release.branch)) 2064 lv = Layer_Version.objects.filter(layer__name = i.layercommit.layer.name, up_branch__release = prj.release)
2076 if lv.count() == 1: 2065 if lv.count() == 1:
2077 ProjectLayer.objects.get_or_create(project = prj, layercommit = lv[0]) 2066 ProjectLayer.objects.get_or_create(project = prj, layercommit = lv[0])
2078 # get rid of the old entry 2067 # get rid of the old entry
@@ -2095,17 +2084,19 @@ if toastermain.settings.MANAGED:
2095 @csrf_exempt 2084 @csrf_exempt
2096 def xhr_datatypeahead(request): 2085 def xhr_datatypeahead(request):
2097 try: 2086 try:
2087 # returns layers for current project release that are not in the project set
2098 if request.GET['type'] == "layers": 2088 if request.GET['type'] == "layers":
2099 queryset_all = Layer_Version.objects.all() 2089 queryset_all = Layer_Version.objects.all()
2100 if 'project_id' in request.session: 2090 if 'project_id' in request.session:
2101 prj = Project.objects.get(pk = request.session['project_id']) 2091 prj = Project.objects.get(pk = request.session['project_id'])
2102 queryset_all = queryset_all.filter(up_branch__in = Branch.objects.filter(name = prj.release.name)).exclude(pk__in = map(lambda x: x.layercommit_id, prj.projectlayer_set.all())) 2092 queryset_all = queryset_all.filter(up_branch__release = prj.release).exclude(pk__in = map(lambda x: x.layercommit_id, prj.projectlayer_set.all()))
2103 queryset_all = queryset_all.filter(layer__name__icontains=request.GET.get('value','')) 2093 queryset_all = queryset_all.filter(layer__name__icontains=request.GET.get('value',''))
2104 return HttpResponse(json.dumps( { "error":"ok", 2094 return HttpResponse(json.dumps( { "error":"ok",
2105 "list" : map( lambda x: {"id": x.pk, "name": x.layer.name, "detail": "(" + x.layer.layer_source.name + (")" if x.up_branch == None else " | "+x.up_branch.name+")")}, 2095 "list" : map( lambda x: {"id": x.pk, "name": x.layer.name, "detail": "(" + x.layer.layer_source.name + (")" if x.up_branch == None else " | "+x.up_branch.name+")")},
2106 queryset_all[:8]) 2096 queryset_all[:8])
2107 }), content_type = "application/json") 2097 }), content_type = "application/json")
2108 2098
2099 # returns layer dependencies for a layer, excluding current project layers
2109 if request.GET['type'] == "layerdeps": 2100 if request.GET['type'] == "layerdeps":
2110 queryset_all = LayerVersionDependency.objects.filter(layer_version_id = request.GET['value']) 2101 queryset_all = LayerVersionDependency.objects.filter(layer_version_id = request.GET['value'])
2111 2102
@@ -2122,6 +2113,7 @@ if toastermain.settings.MANAGED:
2122 map(lambda x: x.depends_on, queryset_all)) 2113 map(lambda x: x.depends_on, queryset_all))
2123 }), content_type = "application/json") 2114 }), content_type = "application/json")
2124 2115
2116 # returns layer versions that would be deleted on the new release__pk
2125 if request.GET['type'] == "versionlayers": 2117 if request.GET['type'] == "versionlayers":
2126 if not 'project_id' in request.session: 2118 if not 'project_id' in request.session:
2127 raise Exception("This call cannot makes no sense outside a project context") 2119 raise Exception("This call cannot makes no sense outside a project context")
@@ -2129,8 +2121,8 @@ if toastermain.settings.MANAGED:
2129 retval = [] 2121 retval = []
2130 prj = Project.objects.get(pk = request.session['project_id']) 2122 prj = Project.objects.get(pk = request.session['project_id'])
2131 for i in prj.projectlayer_set.all(): 2123 for i in prj.projectlayer_set.all():
2132 lv = Layer_Version.objects.filter(layer_source = i.layercommit.layer_source, layer__name = i.layercommit.layer.name, up_branch__in = Branch.objects.filter(name = Release.objects.get(pk=request.GET['value']).branch)) 2124 lv = Layer_Version.objects.filter(layer__name = i.layercommit.layer.name, up_branch__release__pk=request.GET['value'])
2133 if lv.count() != 1: 2125 if lv.count() != 1: # there is no layer_version with the new release id, and the same name
2134 retval.append(i) 2126 retval.append(i)
2135 2127
2136 return HttpResponse(json.dumps( {"error":"ok", 2128 return HttpResponse(json.dumps( {"error":"ok",
@@ -2138,14 +2130,14 @@ if toastermain.settings.MANAGED:
2138 lambda x: {"id": x.layercommit.pk, "name": x.layercommit.layer.name, "detail": "(" + x.layercommit.layer.layer_source.name + (")" if x.layercommit.up_branch == None else " | "+x.layercommit.up_branch.name+")")}, 2130 lambda x: {"id": x.layercommit.pk, "name": x.layercommit.layer.name, "detail": "(" + x.layercommit.layer.layer_source.name + (")" if x.layercommit.up_branch == None else " | "+x.layercommit.up_branch.name+")")},
2139 retval) }), content_type = "application/json") 2131 retval) }), content_type = "application/json")
2140 2132
2141 2133 # returns targets provided by current project layers
2142 if request.GET['type'] == "targets": 2134 if request.GET['type'] == "targets":
2143 queryset_all = Recipe.objects.all() 2135 queryset_all = Recipe.objects.all()
2144 if 'project_id' in request.session: 2136 if 'project_id' in request.session:
2145 queryset_all = queryset_all.filter(layer_version__layer__in = map(lambda x: x.layercommit.layer, ProjectLayer.objects.filter(project_id=request.session['project_id']))) 2137 queryset_all = queryset_all.filter(layer_version__layer__in = map(lambda x: x.layercommit.layer, ProjectLayer.objects.filter(project_id=request.session['project_id'])))
2146 return HttpResponse(json.dumps({ "error":"ok", 2138 return HttpResponse(json.dumps({ "error":"ok",
2147 "list" : map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name+ (" | " + x.layer_version.up_branch.name + "]" if x.layer_version.up_branch is not None else "]")}, 2139 "list" : map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name+ (" | " + x.layer_version.up_branch.name + "]" if x.layer_version.up_branch is not None else "]")},
2148 queryset_all.filter(name__istartswith=request.GET.get('value',''))[:8]), 2140 queryset_all.filter(name__icontains=request.GET.get('value',''))[:8]),
2149 2141
2150 }), content_type = "application/json") 2142 }), content_type = "application/json")
2151 2143
@@ -2155,7 +2147,7 @@ if toastermain.settings.MANAGED:
2155 queryset_all = queryset_all.filter(layer_version__layer__in = map(lambda x: x.layercommit.layer, ProjectLayer.objects.filter(project_id=request.session['project_id']))) 2147 queryset_all = queryset_all.filter(layer_version__layer__in = map(lambda x: x.layercommit.layer, ProjectLayer.objects.filter(project_id=request.session['project_id'])))
2156 return HttpResponse(json.dumps({ "error":"ok", 2148 return HttpResponse(json.dumps({ "error":"ok",
2157 "list" : map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name+ (" | " + x.layer_version.up_branch.name + "]" if x.layer_version.up_branch is not None else "]")}, 2149 "list" : map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name+ (" | " + x.layer_version.up_branch.name + "]" if x.layer_version.up_branch is not None else "]")},
2158 queryset_all.filter(name__istartswith=request.GET.get('value',''))[:8]), 2150 queryset_all.filter(name__icontains=request.GET.get('value',''))[:8]),
2159 2151
2160 }), content_type = "application/json") 2152 }), content_type = "application/json")
2161 2153
@@ -2173,11 +2165,15 @@ if toastermain.settings.MANAGED:
2173 2165
2174 2166
2175 def layers(request): 2167 def layers(request):
2168 if not 'project_id' in request.session:
2169 raise Exception("invalid page: cannot show page without a project")
2170
2176 template = "layers.html" 2171 template = "layers.html"
2177 # define here what parameters the view needs in the GET portion in order to 2172 # define here what parameters the view needs in the GET portion in order to
2178 # be able to display something. 'count' and 'page' are mandatory for all views 2173 # be able to display something. 'count' and 'page' are mandatory for all views
2179 # that use paginators. 2174 # that use paginators.
2180 mandatory_parameters = { 'count': 10, 'page' : 1, 'orderby' : 'layer__name:+' }; 2175 (pagesize, orderby) = _get_parameters_values(request, 100, 'layer__name:+')
2176 mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby };
2181 retval = _verify_parameters( request.GET, mandatory_parameters ) 2177 retval = _verify_parameters( request.GET, mandatory_parameters )
2182 if retval: 2178 if retval:
2183 return _redirect_parameters( 'layers', request.GET, mandatory_parameters) 2179 return _redirect_parameters( 'layers', request.GET, mandatory_parameters)
@@ -2187,18 +2183,9 @@ if toastermain.settings.MANAGED:
2187 (filter_string, search_term, ordering_string) = _search_tuple(request, Layer_Version) 2183 (filter_string, search_term, ordering_string) = _search_tuple(request, Layer_Version)
2188 2184
2189 queryset_all = Layer_Version.objects.all() 2185 queryset_all = Layer_Version.objects.all()
2190 # mock an empty Project if we are outside project context
2191 class _mockProject(object):
2192 id = -1
2193 class _mockManager(object):
2194 def all(self):
2195 return []
2196 projectlayer_set = _mockManager()
2197 prj = _mockProject()
2198 2186
2199 if 'project_id' in request.session: 2187 prj = Project.objects.get(pk = request.session['project_id'])
2200 prj = Project.objects.get(pk = request.session['project_id']) 2188 queryset_all = queryset_all.filter(up_branch__release = prj.release)
2201 queryset_all = queryset_all.filter(up_branch__in = Branch.objects.filter(name = prj.release.name))
2202 2189
2203 queryset_with_search = _get_queryset(Layer_Version, queryset_all, None, search_term, ordering_string, '-layer__name') 2190 queryset_with_search = _get_queryset(Layer_Version, queryset_all, None, search_term, ordering_string, '-layer__name')
2204 queryset = _get_queryset(Layer_Version, queryset_all, filter_string, search_term, ordering_string, '-layer__name') 2191 queryset = _get_queryset(Layer_Version, queryset_all, filter_string, search_term, ordering_string, '-layer__name')
@@ -2265,7 +2252,6 @@ if toastermain.settings.MANAGED:
2265 2252
2266 } 2253 }
2267 }, 2254 },
2268
2269 ] 2255 ]
2270 } 2256 }
2271 2257
@@ -2279,31 +2265,30 @@ if toastermain.settings.MANAGED:
2279 return render(request, template, context) 2265 return render(request, template, context)
2280 2266
2281 def targets(request): 2267 def targets(request):
2282 template = "targets.html" 2268 if not 'project_id' in request.session:
2283 # define here what parameters the view needs in the GET portion in order to 2269 raise Exception("invalid page: cannot show page without a project")
2284 # be able to display something. 'count' and 'page' are mandatory for all views 2270
2285 # that use paginators. 2271 template = 'targets.html'
2286 mandatory_parameters = { 'count': 10, 'page' : 1, 'orderby' : 'name:+' }; 2272 (pagesize, orderby) = _get_parameters_values(request, 100, 'name:+')
2273 mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby }
2287 retval = _verify_parameters( request.GET, mandatory_parameters ) 2274 retval = _verify_parameters( request.GET, mandatory_parameters )
2288 if retval: 2275 if retval:
2289 return _redirect_parameters( 'targets', request.GET, mandatory_parameters) 2276 return _redirect_parameters( 'targets', request.GET, mandatory_parameters)
2290
2291 # boilerplate code that takes a request for an object type and returns a queryset
2292 # for that object type. copypasta for all needed table searches
2293 (filter_string, search_term, ordering_string) = _search_tuple(request, Recipe) 2277 (filter_string, search_term, ordering_string) = _search_tuple(request, Recipe)
2294 2278
2295 queryset_all = Recipe.objects.all() 2279 prj = Project.objects.get(pk = request.session['project_id'])
2296 if 'project_id' in request.session: 2280 queryset_all = Recipe.objects.filter(Q(layer_version__up_branch__release = prj.release) | Q(layer_version__build__in = prj.build_set.all()))
2297 queryset_all = queryset_all.filter(Q(layer_version__up_branch__in = Branch.objects.filter(name = Project.objects.get(pk=request.session['project_id']).release.name)) | Q(layer_version__build__in = Project.objects.get(pk = request.session['project_id']).build_set.all()))
2298 2281
2299 queryset_with_search = _get_queryset(Recipe, queryset_all, None, search_term, ordering_string, '-name') 2282 queryset_with_search = _get_queryset(Recipe, queryset_all, None, search_term, ordering_string, '-name')
2300 queryset = _get_queryset(Recipe, queryset_all, filter_string, search_term, ordering_string, '-name') 2283
2284 queryset_with_search.prefetch_related("layer_source")
2301 2285
2302 # retrieve the objects that will be displayed in the table; targets a paginator and gets a page range to display 2286 # retrieve the objects that will be displayed in the table; targets a paginator and gets a page range to display
2303 target_info = _build_page_range(Paginator(queryset, request.GET.get('count', 10)),request.GET.get('page', 1)) 2287 target_info = _build_page_range(Paginator(queryset_with_search, request.GET.get('count', 10)),request.GET.get('page', 1))
2304 2288
2305 2289
2306 context = { 2290 context = {
2291 'projectlayerset' : json.dumps(map(lambda x: x.layercommit.id, prj.projectlayer_set.all())),
2307 'objects' : target_info, 2292 'objects' : target_info,
2308 'objectname' : "targets", 2293 'objectname' : "targets",
2309 'default_orderby' : 'name:+', 2294 'default_orderby' : 'name:+',
@@ -2329,13 +2314,19 @@ if toastermain.settings.MANAGED:
2329 { 'name': 'Section', 2314 { 'name': 'Section',
2330 'clclass': 'target-section', 2315 'clclass': 'target-section',
2331 'hidden': 1, 2316 'hidden': 1,
2317 'orderfield': _get_toggle_order(request, "section"),
2318 'ordericon': _get_toggle_order_icon(request, "section"),
2332 }, 2319 },
2333 { 'name': 'License', 2320 { 'name': 'License',
2334 'clclass': 'license', 2321 'clclass': 'license',
2335 'hidden': 1, 2322 'hidden': 1,
2323 'orderfield': _get_toggle_order(request, "license"),
2324 'ordericon': _get_toggle_order_icon(request, "license"),
2336 }, 2325 },
2337 { 'name': 'Layer', 2326 { 'name': 'Layer',
2338 'clclass': 'layer', 2327 'clclass': 'layer',
2328 'orderfield': _get_toggle_order(request, "layer_version__layer__name"),
2329 'ordericon': _get_toggle_order_icon(request, "layer_version__layer__name"),
2339 }, 2330 },
2340 { 'name': 'Layer source', 2331 { 'name': 'Layer source',
2341 'clclass': 'source', 2332 'clclass': 'source',
@@ -2345,20 +2336,32 @@ if toastermain.settings.MANAGED:
2345 'filter': { 2336 'filter': {
2346 'class': 'target', 2337 'class': 'target',
2347 'label': 'Show:', 2338 'label': 'Show:',
2348 'options': map(lambda x: (x.name, 'layer_source__pk:' + str(x.id), queryset_with_search.filter(layer_source__pk = x.id).count() ), LayerSource.objects.all()), 2339 'options': map(lambda x: ("Targets provided by " + x.name + " layers", 'layer_source__pk:' + str(x.id), queryset_with_search.filter(layer_source__pk = x.id).count() ), LayerSource.objects.all()),
2349 } 2340 }
2350 }, 2341 },
2351 { 'name': 'Branch, tag or commit', 2342 { 'name': 'Branch, tag or commit',
2352 'clclass': 'branch', 2343 'clclass': 'branch',
2353 'hidden': 1, 2344 'hidden': 1,
2354 }, 2345 },
2346 ]
2347 }
2348
2349 if 'project_id' in request.session:
2350 context['tablecols'] += [
2355 { 'name': 'Build', 2351 { 'name': 'Build',
2356 'dclass': 'span2', 2352 'dclass': 'span2',
2357 'qhelp': "Add or delete targets to / from your project ", 2353 'qhelp': "Add or delete targets to / from your project ",
2358 }, 2354 'filter': {
2355 'class': 'add-layer',
2356 'label': 'Show:',
2357 'options': [
2358 ('Targets provided by layers added to this project', "layer_version__projectlayer__project:" + str(prj.id), queryset_with_search.filter(layer_version__projectlayer__project = prj.id).count()),
2359 ('Targets provided by layers not added to this project', "layer_version__projectlayer__project:NOT" + str(prj.id), queryset_with_search.exclude(layer_version__projectlayer__project = prj.id).count()),
2360 ]
2361
2362 }
2363 }, ]
2359 2364
2360 ]
2361 }
2362 2365
2363 return render(request, template, context) 2366 return render(request, template, context)
2364 2367
@@ -2378,7 +2381,7 @@ if toastermain.settings.MANAGED:
2378 2381
2379 queryset_all = Machine.objects.all() 2382 queryset_all = Machine.objects.all()
2380# if 'project_id' in request.session: 2383# if 'project_id' in request.session:
2381# queryset_all = queryset_all.filter(Q(layer_version__up_branch__in = Branch.objects.filter(name = Project.objects.get(request.session['project_id']).release.name)) | Q(layer_version__build__in = Project.objects.get(request.session['project_id']).build_set.all())) 2384# queryset_all = queryset_all.filter(Q(layer_version__up_branch__release = Project.objects.get(request.session['project_id']).release) | Q(layer_version__build__in = Project.objects.get(request.session['project_id']).build_set.all()))
2382 2385
2383 queryset_with_search = _get_queryset(Machine, queryset_all, None, search_term, ordering_string, '-name') 2386 queryset_with_search = _get_queryset(Machine, queryset_all, None, search_term, ordering_string, '-name')
2384 queryset = _get_queryset(Machine, queryset_all, filter_string, search_term, ordering_string, '-name') 2387 queryset = _get_queryset(Machine, queryset_all, filter_string, search_term, ordering_string, '-name')
@@ -2643,7 +2646,7 @@ if toastermain.settings.MANAGED:
2643 def projects(request): 2646 def projects(request):
2644 template="projects.html" 2647 template="projects.html"
2645 2648
2646 (pagesize, orderby) = _get_parameters_values(request, 10, 'updated:-') 2649 (pagesize, orderby) = _get_parameters_values(request, 10, 'updated:+')
2647 mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby } 2650 mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby }
2648 retval = _verify_parameters( request.GET, mandatory_parameters ) 2651 retval = _verify_parameters( request.GET, mandatory_parameters )
2649 if retval: 2652 if retval:
@@ -2654,8 +2657,8 @@ if toastermain.settings.MANAGED:
2654 # boilerplate code that takes a request for an object type and returns a queryset 2657 # boilerplate code that takes a request for an object type and returns a queryset
2655 # for that object type. copypasta for all needed table searches 2658 # for that object type. copypasta for all needed table searches
2656 (filter_string, search_term, ordering_string) = _search_tuple(request, Project) 2659 (filter_string, search_term, ordering_string) = _search_tuple(request, Project)
2657 queryset_with_search = _get_queryset(Project, queryset_all, None, search_term, ordering_string, 'updated:-') 2660 queryset_with_search = _get_queryset(Project, queryset_all, None, search_term, ordering_string, '-updated')
2658 queryset = _get_queryset(Project, queryset_all, filter_string, search_term, ordering_string, 'updated:-') 2661 queryset = _get_queryset(Project, queryset_all, filter_string, search_term, ordering_string, '-updated')
2659 2662
2660 # retrieve the objects that will be displayed in the table; projects a paginator and gets a page range to display 2663 # retrieve the objects that will be displayed in the table; projects a paginator and gets a page range to display
2661 project_info = _build_page_range(Paginator(queryset, pagesize), request.GET.get('page', 1)) 2664 project_info = _build_page_range(Paginator(queryset, pagesize), request.GET.get('page', 1))