diff options
-rw-r--r-- | bitbake/lib/toaster/bldcontrol/models.py | 33 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/css/default.css | 4 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/projectapp.js | 24 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/base.html | 3 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/basetable_bottom.html | 13 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/layers.html | 124 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/mrb_section.html | 11 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/project.html | 48 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/targets.html | 340 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 157 |
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 */ |
63 | td a, td a > code { color: #333333; } | 63 | td a, td a > code { color: #333333; } |
64 | td a > code { white-space: normal; } | 64 | td code { white-space: normal; } |
65 | td a:hover { color: #000000; text-decoration: underline; } | 65 | td 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 | ||
97 | projectApp.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 |
96 | projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $location, $cookies, $q, $sce) { | 114 | projectApp.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 | ||
100 | var tooltipUpdateText; | ||
101 | |||
100 | function _makeXHREditCall(data, onsuccess, onfail) { | 102 | function _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 | ||
122 | function layerDel(layerId, layerName, layerURL) { | 124 | function 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 | ||
128 | function show_alert(text, cls) { | 131 | function show_alert(text, cls) { |
129 | $("#zone1alerts").html("<div class=\"alert alert-info\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\">×</button>" + text + "</div>"); | 132 | $("#zone1alerts").html("<div class=\"alert alert-info lead\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\">×</button>" + text + "</div>"); |
130 | } | 133 | } |
131 | 134 | ||
132 | function show_dependencies_modal(layerId, layerName, layerURL, dependencies) { | 135 | function 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 | ||
190 | function button_set(id, state) { | 204 | function 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 | ||
89 | function scheduleBuild(url, projectName, buildlist) { | 88 | function 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">×</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> | 110 | var tooltipUpdateText; |
102 | <script src="assets/js/main.js" type='text/javascript'></script> | 111 | |
103 | 112 | function _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 | |||
133 | function show_alert(text, cls) { | ||
134 | $("#zone1alerts").html("<div class=\"alert alert-info lead\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\">×</button>" + text + "</div>"); | ||
135 | } | ||
136 | |||
137 | |||
138 | function 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 | 186 | var pressedButton = undefined; |
134 | $('.dropdown-menu input, .dropdown-menu label').click(function(e) { | ||
135 | e.stopPropagation(); | ||
136 | }); | ||
137 | 187 | ||
138 | //show tooltip with applied filter | 188 | function 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() { | 211 | function 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">×</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">×</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 | 240 | function 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)) |