summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorMichael Wood <michael.g.wood@intel.com>2015-05-11 18:51:28 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-05-14 18:04:09 +0100
commit23f5b009e0ebf59cfcc9ae90a1084468fc88e42f (patch)
tree06eb458cbd9a95dd635160adac7d90aeae6afea1 /bitbake
parent7f8c44771cc6219ad7e58da7840fffbe93f11b39 (diff)
downloadpoky-23f5b009e0ebf59cfcc9ae90a1084468fc88e42f.tar.gz
bitbake: toaster: Port All recipes, layers and machines to ToasterTables
Port of the main tables to the new ToasterTable widget. (Bitbake rev: 6de539d5953b2dca2a9ed75556a59764337a194c) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/toaster/orm/models.py11
-rw-r--r--bitbake/lib/toaster/toastergui/static/css/default.css3
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/layerBtn.js5
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/libtoaster.js3
-rw-r--r--bitbake/lib/toaster/toastergui/tables.py279
-rw-r--r--bitbake/lib/toaster/toastergui/templates/layer_btn.html9
-rw-r--r--bitbake/lib/toaster/toastergui/templates/layers.html132
-rw-r--r--bitbake/lib/toaster/toastergui/templates/machine_btn.html8
-rw-r--r--bitbake/lib/toaster/toastergui/templates/machines.html88
-rw-r--r--bitbake/lib/toaster/toastergui/templates/recipe_btn.html8
-rw-r--r--bitbake/lib/toaster/toastergui/templates/targets.html142
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py28
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py267
13 files changed, 349 insertions, 634 deletions
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index b097504bbb..20b02bbbb3 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -567,6 +567,17 @@ class Recipe(models.Model):
567 567
568 return self.file_path 568 return self.file_path
569 569
570 def get_vcs_recipe_file_link_url(self):
571 return self.layer_version.get_vcs_file_link_url(self.file_path)
572
573 def get_description_or_summary(self):
574 if self.description:
575 return self.description
576 elif self.summary:
577 return self.summary
578 else:
579 return ""
580
570 class Meta: 581 class Meta:
571 unique_together = ("layer_version", "file_path") 582 unique_together = ("layer_version", "file_path")
572 583
diff --git a/bitbake/lib/toaster/toastergui/static/css/default.css b/bitbake/lib/toaster/toastergui/static/css/default.css
index bc3d63e6b9..739efbfbbe 100644
--- a/bitbake/lib/toaster/toastergui/static/css/default.css
+++ b/bitbake/lib/toaster/toastergui/static/css/default.css
@@ -256,3 +256,6 @@ div.add-deps { margin-top: 15px; }
256.machines-highlight { -webkit-animation: machines-fade 7s 1; -moz-animation: machines-fade 7s 1; animation: machines-fade 7s 1; } 256.machines-highlight { -webkit-animation: machines-fade 7s 1; -moz-animation: machines-fade 7s 1; animation: machines-fade 7s 1; }
257 257
258.tab-pane table { margin-top: 10px; } 258.tab-pane table { margin-top: 10px; }
259
260thead .description, .get_description_or_summary { width: 364px; }
261thead .add-del-layers { width: 124px; }
diff --git a/bitbake/lib/toaster/toastergui/static/js/layerBtn.js b/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
index 6a1d4b1606..44bf612a58 100644
--- a/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
+++ b/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
@@ -2,7 +2,10 @@
2 2
3function layerBtnsInit(ctx) { 3function layerBtnsInit(ctx) {
4 4
5 $(".layerbtn").click(function (){ 5 /* Remove any current bindings to avoid duplicated binds */
6 $(".layerbtn").unbind('click');
7
8 $(".layerbtn").click(function (){
6 var layerObj = $(this).data("layer"); 9 var layerObj = $(this).data("layer");
7 var add = ($(this).data('directive') === "add"); 10 var add = ($(this).data('directive') === "add");
8 var thisBtn = $(this); 11 var thisBtn = $(this);
diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
index 6bf915d15a..1ac26d4c7f 100644
--- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
+++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
@@ -361,6 +361,7 @@ $(document).ready(function() {
361 }); 361 });
362 362
363 363
364 /* START TODO Delete this section now redundant */
364 /* Belen's additions */ 365 /* Belen's additions */
365 366
366 // turn Edit columns dropdown into a multiselect menu 367 // turn Edit columns dropdown into a multiselect menu
@@ -409,6 +410,8 @@ $(document).ready(function() {
409 $(this).find(".hover-help").css("visibility","hidden"); 410 $(this).find(".hover-help").css("visibility","hidden");
410 }); 411 });
411 412
413 /* END TODO Delete this section now redundant */
414
412 // show task type and outcome in task details pages 415 // show task type and outcome in task details pages
413 $(".task-info").tooltip({ container: 'body', html: true, delay: {show: 200}, placement: 'right' }); 416 $(".task-info").tooltip({ container: 'body', html: true, delay: {show: 200}, placement: 'right' });
414 417
diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py
new file mode 100644
index 0000000000..e6395834a5
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/tables.py
@@ -0,0 +1,279 @@
1#
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# BitBake Toaster Implementation
6#
7# Copyright (C) 2015 Intel Corporation
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22from widgets import ToasterTable
23from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
24from django.db.models import Q, Max
25from django.conf.urls import url
26from django.views.generic import TemplateView
27
28class LayersTable(ToasterTable):
29 """Table of layers in Toaster"""
30
31 def __init__(self, *args, **kwargs):
32 ToasterTable.__init__(self)
33 self.default_orderby = "layer__name"
34
35 def setup_queryset(self, *args, **kwargs):
36 prj = Project.objects.get(pk = kwargs['pid'])
37 compatible_layers = prj.compatible_layerversions()
38
39 self.queryset = compatible_layers.order_by(self.default_orderby)
40
41 def setup_columns(self, *args, **kwargs):
42
43 layer_link_template = '''
44 <a href="{% url 'layerdetails' extra.pid data.id %}">
45 {{data.layer.name}}
46 </a>
47 '''
48
49 self.add_column(title="Layer",
50 hideable=False,
51 orderable=True,
52 static_data_name="layer__name",
53 static_data_template=layer_link_template)
54
55 self.add_column(title="Summary",
56 field_name="layer__summary")
57
58 git_url_template = '''
59 <a href="{% url 'layerdetails' extra.pid data.id %}">
60 <code>{{data.layer.vcs_url}}</code>
61 </a>
62 {% if data.get_vcs_link_url %}
63 <a target="_blank" href="{{ data.get_vcs_link_url }}">
64 <i class="icon-share get-info"></i>
65 </a>
66 {% endif %}
67 '''
68
69 self.add_column(title="Git repository URL",
70 help_text="The Git repository for the layer source code",
71 hidden=True,
72 static_data_name="git_url",
73 static_data_template=git_url_template)
74
75 git_dir_template = '''
76 <a href="{% url 'layerdetails' extra.pid data.id %}">
77 <code>{{data.dirpath}}</code>
78 </a>
79 {% if data.dirpath and data.get_vcs_dirpath_link_url %}
80 <a target="_blank" href="{{ data.get_vcs_dirpath_link_url }}">
81 <i class="icon-share get-info"></i>
82 </a>
83 {% endif %}'''
84
85 self.add_column(title="Subdirectory",
86 help_text="The layer directory within the Git repository",
87 hidden=True,
88 static_data_name="git_subdir",
89 static_data_template=git_dir_template)
90
91 revision_template = '''
92 {% load projecttags %}
93 {% with vcs_ref=data.get_vcs_reference %}
94 {% if vcs_ref|is_shaid %}
95 <a class="btn" data-content="<ul class='unstyled'> <li>{{vcs_ref}}</li> </ul>">
96 {{vcs_ref|truncatechars:10}}
97 </a>
98 {% else %}
99 {{vcs_ref}}
100 {% endif %}
101 {% endwith %}
102 '''
103
104 self.add_column(title="Revision",
105 help_text="The Git branch, tag or commit. For the layers from the OpenEmbedded layer source, the revision is always the branch compatible with the Yocto Project version you selected for this project",
106 static_data_name="revision",
107 static_data_template=revision_template)
108
109 deps_template = '''
110 {% with ods=data.dependencies.all%}
111 {% if ods.count %}
112 <a class="btn" title="<a href='{% url "layerdetails" extra.pid data.id %}'>{{data.layer.name}}</a> dependencies"
113 data-content="<ul class='unstyled'>
114 {% for i in ods%}
115 <li><a href='{% url "layerdetails" extra.pid i.depends_on.pk %}'>{{i.depends_on.layer.name}}</a></li>
116 {% endfor %}
117 </ul>">
118 {{ods.count}}
119 </a>
120 {% endif %}
121 {% endwith %}
122 '''
123
124 self.add_column(title="Dependencies",
125 help_text="Other layers a layer depends upon",
126 static_data_name="dependencies",
127 static_data_template=deps_template)
128
129 self.add_column(title="Add | Delete",
130 help_text="Add or delete layers to / from your project",
131 hideable=False,
132 static_data_name="add-del-layers",
133 static_data_template='{% include "layer_btn.html" %}')
134
135
136class MachinesTable(ToasterTable):
137 """Table of Machines in Toaster"""
138
139 def __init__(self, *args, **kwargs):
140 ToasterTable.__init__(self)
141 self.empty_state = "No machines maybe you need to do a build?"
142 self.default_orderby = "name"
143
144 def setup_queryset(self, *args, **kwargs):
145 prj = Project.objects.get(pk = kwargs['pid'])
146 compatible_layers = prj.compatible_layerversions()
147
148 self.queryset = Machine.objects.filter(layer_version__in=compatible_layers).order_by(self.default_orderby)
149
150 def setup_columns(self, *args, **kwargs):
151
152 self.add_column(title="Machine",
153 hideable=False,
154 orderable=True,
155 field_name="name")
156
157 self.add_column(title="Description",
158 field_name="description")
159
160 layer_link_template = '''
161 <a href="{% url 'layerdetails' extra.pid data.layer_version.id %}">
162 {{data.layer_version.layer.name}}</a>
163 '''
164
165 self.add_column(title="Layer",
166 static_data_name="layer_version__layer__name",
167 static_data_template=layer_link_template,
168 orderable=True)
169
170 self.add_column(title="Revision",
171 help_text="The Git branch, tag or commit. For the layers from the OpenEmbedded layer source, the revision is always the branch compatible with the Yocto Project version you selected for this project",
172 hidden=True,
173 field_name="layer_version__get_vcs_reference")
174
175 machine_file_template = '''<code>conf/machine/{{data.name}}.conf</code>
176 <a href="{{data.get_vcs_machine_file_link_url}}" target="_blank"><i class="icon-share get-info"></i></a>'''
177
178 self.add_column(title="Machine file",
179 hidden=True,
180 static_data_name="machinefile",
181 static_data_template=machine_file_template,
182 field_name="name")
183
184 self.add_column(title="Select",
185 help_text="Sets the selected machine as the project machine. You can only have one machine per project",
186 hideable=False,
187 static_data_name="add-del-layers",
188 static_data_template='{% include "machine_btn.html" %}',
189 field_name="layer_version__id")
190
191
192
193class RecipesTable(ToasterTable):
194 """Table of Recipes in Toaster"""
195
196 def __init__(self, *args, **kwargs):
197 ToasterTable.__init__(self)
198 self.empty_state = "Toaster has no recipe information. To generate recipe information you can configure a layer source then run a build."
199 self.default_orderby = "name"
200
201 def setup_queryset(self, *args, **kwargs):
202 prj = Project.objects.get(pk = kwargs['pid'])
203
204 self.queryset = Recipe.objects.filter(Q(layer_version__up_branch__name= prj.release.name) | Q(layer_version__build__in = prj.build_set.all())).filter(name__regex=r'.{1,}.*')
205
206 search_maxids = map(lambda i: i[0], list(self.queryset.values('name').distinct().annotate(max_id=Max('id')).values_list('max_id')))
207
208 self.queryset = self.queryset.filter(id__in=search_maxids).select_related('layer_version', 'layer_version__layer', 'layer_version__up_branch', 'layer_source')
209 self.queryset = self.queryset.order_by(self.default_orderby)
210
211
212 def setup_columns(self, *args, **kwargs):
213
214 self.add_column(title="Recipe",
215 help_text="Information about a single piece of software, including where to download the source, configuration options, how to compile the source files and how to package the compiled output",
216 hideable=False,
217 orderable=True,
218 field_name="name")
219
220 self.add_column(title="Recipe Version",
221 hidden=True,
222 field_name="version")
223
224 self.add_column(title="Description",
225 field_name="get_description_or_summary")
226
227 recipe_file_template = '''
228 <code>{{data.file_path}}</code>
229 <a href="{{data.get_vcs_recipe_file_link_url}}" target="_blank">
230 <i class="icon-share get-info"></i>
231 </a>
232 '''
233
234 self.add_column(title="Recipe file",
235 help_text="Path to the recipe .bb file",
236 static_data_name="recipe-file",
237 static_data_template=recipe_file_template)
238
239 self.add_column(title="Section",
240 help_text="The section in which recipes should be categorized",
241 orderable=True,
242 field_name="section")
243
244 layer_link_template = '''
245 <a href="{% url 'layerdetails' extra.pid data.layer_version.id %}">
246 {{data.layer_version.layer.name}}</a>
247 '''
248
249 self.add_column(title="Layer",
250 help_text="The name of the layer providing the recipe",
251 orderable=True,
252 static_data_name="layer_version__layer__name",
253 static_data_template=layer_link_template)
254
255 self.add_column(title="License",
256 help_text="The list of source licenses for the recipe. Multiple license names separated by the pipe character indicates a choice between licenses. Multiple license names separated by the ampersand character indicates multiple licenses exist that cover different parts of the source",
257 orderable=True,
258 field_name="license")
259
260 self.add_column(title="Revision",
261 field_name="layer_version__get_vcs_reference")
262
263
264 self.add_column(title="Build",
265 help_text="Add or delete recipes to and from your project",
266 hideable=False,
267 static_data_name="add-del-layers",
268 static_data_template='{% include "recipe_btn.html" %}')
269
270# This needs to be staticaly defined here as django reads the url patterns
271# on start up
272urlpatterns = (
273 url(r'^machines/(?P<cmd>\w+)*', MachinesTable.as_view(),
274 name=MachinesTable.__name__.lower()),
275 url(r'^layers/(?P<cmd>\w+)*', LayersTable.as_view(),
276 name=LayersTable.__name__.lower()),
277 url(r'^recipes/(?P<cmd>\w+)*', RecipesTable.as_view(),
278 name=RecipesTable.__name__.lower()),
279)
diff --git a/bitbake/lib/toaster/toastergui/templates/layer_btn.html b/bitbake/lib/toaster/toastergui/templates/layer_btn.html
new file mode 100644
index 0000000000..6672017256
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/layer_btn.html
@@ -0,0 +1,9 @@
1<button class="btn btn-danger btn-block layer-exists-{{data.pk}} layerbtn" style="display:none;" data-layer='{ "id": {{data.pk}}, "name": "{{data.layer.name}}", "url": "{%url 'layerdetails' extra.pid data.pk%}"}' data-directive="remove" >
2 <i class="icon-trash"></i>
3 Delete layer
4</button>
5<button class="btn btn-block layer-add-{{data.pk}} layerbtn" data-layer='{ "id": {{data.pk}}, "name": "{{data.layer.name}}", "url": "{%url 'layerdetails' extra.pid data.pk%}"}' data-directive="add">
6 <i class="icon-plus"></i>
7 Add layer
8</button>
9
diff --git a/bitbake/lib/toaster/toastergui/templates/layers.html b/bitbake/lib/toaster/toastergui/templates/layers.html
deleted file mode 100644
index e6861c2708..0000000000
--- a/bitbake/lib/toaster/toastergui/templates/layers.html
+++ /dev/null
@@ -1,132 +0,0 @@
1{% extends "baseprojectpage.html" %}
2{% load projecttags %}
3{% load humanize %}
4{% load static %}
5
6{% block localbreadcrumb %}
7<li>All compatible layers</li>
8{% endblock %}
9
10
11{% block projectinfomain %}
12
13<script src="{% static 'js/layerBtn.js' %}"></script>
14<script>
15
16 $(document).ready(function (){
17 var ctx = {
18 projectLayers : {{projectlayerset}},
19 };
20
21 try {
22 layerBtnsInit(ctx);
23 } catch (e) {
24 document.write("Sorry, An error has occurred loading this page");
25 console.warn(e);
26 }
27 });
28</script>
29
30 <div class="page-header">
31 <h1>
32 {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %}
33 {{objects.paginator.count}} layer{{objects.paginator.count|pluralize}} found
34 {% elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
35 No layers found
36 {%else%}
37 All compatible layers
38 {%endif%}
39 <i class="icon-question-sign get-help heading-help" title="This page lists all the layers compatible with the release selected for this project, which is {{project.release.description}}"></i>
40 </h1>
41 </div>
42
43 <div id="zone1alerts" style="display:none">
44 <div class="alert alert-info lead">
45 <button type="button" class="close" id="hide-alert">&times;</button>
46 <span id="alert-msg"></span>
47 </div>
48 </div>
49
50{% if objects.paginator.count == 0 %}
51 {% if request.GET.filter or request.GET.search %}
52 <div class="row-fluid">
53 <div class="alert">
54 <form class="no-results input-append" id="searchform">
55 <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 %}
56 <button class="btn" type="submit" value="Search">Search</button>
57 <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all layers</button>
58 </form>
59 </div>
60 </div>
61 {% else %}
62 <div class="alert alert-info lead">
63 <p>Toaster has no layer information. To generate layer information you can:</p>
64 <ul>
65 <li><a href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#layer-source">Configure a layer source</a></li>
66 <li><a href="{% url 'importlayer' %}">Import a layer</a></li>
67 </ul>
68 </div>
69 {% endif %}
70
71{% else %}
72
73{% include "basetable_top_layers.html" %}
74 {% for o in objects %}
75 <tr class="data">
76 <td class="layer"><a href="{% url 'layerdetails' project.id o.id %}">{{o.layer.name}}</a></td>
77 <td class="description">{% if o.layer.summary %}{{o.layer.summary}}{%endif%}</td>
78 <td class="git-repo"><a href="{% url 'layerdetails' project.id o.pk %}"><code>{{o.layer.vcs_url}}</code></a>
79 {% if o.get_vcs_link_url %}
80 <a target="_blank" href="{{ o.get_vcs_link_url }}"><i class="icon-share get-info"></i></a>
81 {% endif %}
82 </td>
83 <td class="git-subdir" style="display: table-cell;"><a href="{% url 'layerdetails' project.id o.pk %}"><code>{{o.dirpath}}</code></a>
84 {% if o.dirpath and o.get_vcs_dirpath_link_url %}
85 <a target="_blank" href="{{ o.get_vcs_dirpath_link_url }}"><i class="icon-share get-info"></i></a>
86 {% endif %}
87 </td>
88 <td class="branch">
89 {% with vcs_ref=o.get_vcs_reference %}
90 {% if vcs_ref|is_shaid %}
91 <a class="btn" data-content="<ul class='unstyled'> <li>{{vcs_ref}}</li> </ul>">
92 {{vcs_ref|truncatechars:10}}
93 </a>
94 {% else %}
95 {{vcs_ref}}
96 {% endif %}
97 {% endwith %}
98 </td>
99 <td class="dependencies">
100 {% with ods=o.dependencies.all%}
101 {% if ods.count %}
102 <a class="btn"
103 title="<a href='{% url "layerdetails" project.id o.pk %}'>{{o.layer.name}}</a> dependencies"
104 data-content="<ul class='unstyled'>
105 {% for i in ods%}
106 <li><a href='{% url "layerdetails" project.id i.depends_on.pk %}'>{{i.depends_on.layer.name}}</a></li>
107 {% endfor %}
108 </ul>">
109 {{ods.count}}
110 </a>
111 {% endif %}
112 {% endwith %}
113 </td>
114 {% if project %}
115 <td class="add-del-layers" data-value="{{o.pk}}">
116 <button class="btn btn-danger btn-block layer-exists-{{o.pk}} layerbtn" style="display:none;" data-layer='{ "id": {{o.pk}}, "name": "{{o.layer.name}}", "url": "{%url 'layerdetails' project.id o.pk%}"}' data-directive="remove" >
117 <i class="icon-trash"></i>
118 Delete layer
119 </button>
120 <button class="btn btn-block layer-add-{{o.pk}} layerbtn" data-layer='{ "id": {{o.pk}}, "name": "{{o.layer.name}}", "url": "{%url 'layerdetails' project.id o.pk%}"}' data-directive="add">
121 <i class="icon-plus"></i>
122 Add layer
123 </button>
124 </td>
125 {% endif %}
126 </tr>
127 {% endfor %}
128{% include "basetable_bottom.html" %}
129
130{%endif%}
131
132{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/templates/machine_btn.html b/bitbake/lib/toaster/toastergui/templates/machine_btn.html
new file mode 100644
index 0000000000..fffb536e2b
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/machine_btn.html
@@ -0,0 +1,8 @@
1<a href="{% url 'project' extra.pid %}#/machineselect={{data.name}}" class="btn btn-block layer-exists-{{data.layer_version.id}}" style="margin-top: 5px; display:none">
2 Select machine</a>
3<button class="btn btn-block layerbtn layer-add-{{data.layer_version.id}}" data-layer='{ "id": {{data.layer_version.id}}, "name": "{{data.layer_version.layer.name}}", "url": "{%url 'layerdetails' extra.pid data.layer_version.id %}"}' data-directive="add">
4 <i class="icon-plus"></i>
5 Add layer
6 <i title="" class="icon-question-sign get-help" data-original-title="To enable this machine, you must first add the {{data.layer_version.layer.name}} layer to your project"></i>
7</button>
8
diff --git a/bitbake/lib/toaster/toastergui/templates/machines.html b/bitbake/lib/toaster/toastergui/templates/machines.html
deleted file mode 100644
index 9979376b07..0000000000
--- a/bitbake/lib/toaster/toastergui/templates/machines.html
+++ /dev/null
@@ -1,88 +0,0 @@
1{% extends "baseprojectpage.html" %}
2{% load projecttags %}
3{% load humanize %}
4{% load static %}
5{% block localbreadcrumb %}
6<li>All compatible machines</li>
7{% endblock %}
8
9{% block projectinfomain %}
10
11<script src="{% static 'js/layerBtn.js' %}"></script>
12<script>
13
14 $(document).ready(function (){
15 var ctx = {
16 projectLayers : {{projectlayerset}},
17 };
18
19 try {
20 layerBtnsInit(ctx);
21 } catch (e) {
22 document.write("Sorry, An error has occurred loading this page");
23 console.warn(e);
24 }
25 });
26</script>
27<div class="page-header">
28 <h1>
29 {% if request.GET.search or request.GET.filter %}
30 {% if objects.paginator.count != 0 %}
31 {{objects.paginator.count}} machines found
32 {% else %}
33 No machines found
34 {% endif %}
35 {% else %}
36
37 All compatible machines
38 <i class="icon-question-sign get-help heading-help" title="This page lists all the machines compatible with the current project that Toaster knows about. They include community-created targets suitable for use on top of OpenEmbedded Core and any targets you have imported"></i>
39 {% endif %}
40 </h1>
41</div>
42
43<div id="zone1alerts" style="display:none">
44 <div class="alert alert-info lead">
45 <button type="button" class="close" id="hide-alert">&times;</button>
46 <span id="alert-msg"></span>
47 </div>
48</div>
49{% if objects.paginator.count == 0 %}
50 {% if request.GET.search %}
51 <div class="alert row-fluid">
52 <form class="navbar-search input-append pull-left" id="searchform">
53 <input class="input-xxlarge" id="search" name="search" type="text" placeholder="Search machines" value="{{request.GET.search}}"><a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>
54 <input type="hidden" name="orderby" value="">
55 <input type="hidden" name="page" value="1">
56 <button class="btn" type="submit" value="Search">Search</button>
57 <button type="submit" class="btn btn-link" id="show-all-btn">Show all machines</button>
58 </form>
59 </div>
60 {% else %}
61 <div class="alert alert-info lead">
62 Toaster has no machine information. To generate machine information you should <a href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#layer-source">configure a layer source</a>
63 </div>
64 {% endif %}
65
66{% else %}
67 {% include "basetable_top.html" %}
68 {% for o in objects %}
69 <tr class="data">
70 <td class="machine">{{o.name}}</td>
71 <td class="description">{{o.description}}</td>
72 <td class="layer"><a href="{%url "layerdetails" project.id o.layer_version.id %}">{{o.layer_version.layer.name}}</a></td>
73 <td class="branch">{{o.layer_version.get_vcs_reference}}</td>
74 <td class="machinefile"><code>/machine/conf/{{o.name}}.conf</code><a href="{{o.get_vcs_machine_file_link_url}}" target="_blank"><i class="icon-share get-info"></i></a></td>
75 <td class="select-or-add" style="height: 32px;">
76 <a href="{% url 'project' project.id %}#/machineselect={{o.name}}" class="btn btn-block layer-exists-{{o.layer_version.id}}" style="margin-top: 5px; display:none">Select machine</a>
77 <button class="btn btn-block layerbtn layer-add-{{o.layer_version.id}}" data-layer='{ "id": {{o.layer_version.id}}, "name": "{{o.layer_version.layer.name}}", "url": "{%url 'layerdetails' project.id o.layer_version.id %}"}' data-directive="add">
78 <i class="icon-plus"></i>
79 Add layer
80 <i title="" class="icon-question-sign get-help" data-original-title="To enable this machine, you must first add the {{o.layer_version.layer.name}} layer to your project"></i>
81 </button>
82 </td>
83 </tr>
84 {% endfor %}
85 {% include "basetable_bottom.html" %}
86{% endif %}
87
88{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/templates/recipe_btn.html b/bitbake/lib/toaster/toastergui/templates/recipe_btn.html
new file mode 100644
index 0000000000..1c7c58ca3f
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/templates/recipe_btn.html
@@ -0,0 +1,8 @@
1<a href="{% url 'project' extra.pid %}#/targetbuild={{data.name}}" class="btn btn-block layer-exists-{{data.layer_version.pk}}" style="display:none; margin-top: 5px;" >
2 Build recipe
3</a>
4<button class="btn btn-block layerbtn layer-add-{{data.layer_version.pk}}" data-layer='{ "id": {{data.layer_version.pk}}, "name": "{{data.layer_version.layer.name}}", "url": "{%url 'layerdetails' extra.pid data.layer_version.pk%}"}' data-directive="add">
5 <i class="icon-plus"></i>
6 Add layer
7 <i title="" class="icon-question-sign get-help" data-original-title="To build this target, you must first add the {{data.layer_version.layer.name}} layer to your project"></i>
8</button>
diff --git a/bitbake/lib/toaster/toastergui/templates/targets.html b/bitbake/lib/toaster/toastergui/templates/targets.html
deleted file mode 100644
index 224288ea35..0000000000
--- a/bitbake/lib/toaster/toastergui/templates/targets.html
+++ /dev/null
@@ -1,142 +0,0 @@
1{% extends "baseprojectpage.html" %}
2{% load projecttags %}
3{% load humanize %}
4{% load static %}
5
6{% block localbreadcrumb %}
7<li>All compatible recipes</li>
8{% endblock %}
9
10{% block projectinfomain %}
11
12<script src="{% static 'js/layerBtn.js' %}"></script>
13<script>
14
15 $(document).ready(function (){
16 var ctx = {
17 projectLayers : {{projectlayerset}},
18 };
19
20 try {
21 layerBtnsInit(ctx);
22 } catch (e) {
23 document.write("Sorry, An error has occurred loading this page");
24 console.warn(e);
25 }
26 });
27</script>
28
29
30<div class="page-header">
31 <h1>
32 {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %}
33 {{objects.paginator.count}} recipe{{objects.paginator.count|pluralize}} found
34 {% elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
35 No recipes found
36 {%else%}
37 All compatible recipes
38 {%endif%}
39 <i class="icon-question-sign get-help heading-help" title="This page lists all the recipes compatible with the release selected for this project, which is {{project.release.description}}"></i>
40 </h1>
41</div>
42
43<div id="zone1alerts" style="display:none">
44 <div class="alert alert-info lead">
45 <button type="button" class="close" id="hide-alert">&times;</button>
46 <span id="alert-msg"></span>
47 </div>
48</div>
49{% if objects.paginator.count == 0 %}
50 {% if request.GET.filter or request.GET.search %}
51 <div class="row-fluid">
52 <div class="alert">
53 <form class="no-results input-append" id="searchform">
54 <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 %}
55 <button class="btn" type="submit" value="Search">Search</button>
56 <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all recipes</button>
57 </form>
58 </div>
59 </div>
60 {% else %}
61 <div class="alert alert-info lead">
62 <p>Toaster has no recipe information. To generate recipe information you can:</p>
63 <ul>
64 <li><a href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#layer-source">Configure a layer source</a></li>
65 <li><a href="{% url 'importlayer' project.id %}">Import a layer</a>, then run a build</li>
66 </ul>
67 </div>
68 {% endif %}
69
70{% else %}
71
72{% include "basetable_top.html" %}
73 {% for o in objects %}
74 <tr class="data">
75 <td class="target">
76 {{o.name}}
77 <a target="_blank" href="{{o.get_layersource_view_url}}"><i class="icon-share get-info"></i></a>
78 </td>
79 <td class="version">{{o.version}}</td>
80 <td class="description">{% if o.description %}{{o.description}}{% else %}{{o.summary}}{%endif%}</td>
81 <td class="recipe-file">
82 <code>{{o.file_path}}</code>
83 <a href="{{o.vcs_link_url}}" target="_blank"><i class="icon-share get-info"></i></a>
84 </td>
85 <td class="target-section">{{o.section}}</td>
86 <td class="license">{{o.license}}</td>
87 <td class="layer"><a href="{% url 'layerdetails' project.id o.preffered_layerversion.id%}">{{o.preffered_layerversion.layer.name}}</a></td>
88 <td class="branch">
89 {% if o.preffered_layerversion.up_branch %}
90 {{o.preffered_layerversion.up_branch.name}}
91 {% else %}
92 <a class="btn"
93 data-content="<ul class='unstyled'>
94 <li>{{o.layer_version.commit}}</li>
95 </ul>">
96 {{o.layer_version.commit|truncatechars:13}}
97 </a>
98 {% endif %}
99 </td>
100 <td class="add-layer" data-value="{{o.pk}}">
101 <a href="{% url 'project' project.id %}#/targetbuild={{o.name}}" class="btn btn-block layer-exists-{{o.preffered_layerversion.pk}}" style="display:none; margin-top: 5px;" >
102 Build recipe
103 </a>
104 <button class="btn btn-block layerbtn layer-add-{{o.preffered_layerversion.pk}}" data-layer='{ "id": {{o.preffered_layerversion.pk}}, "name": "{{o.preffered_layerversion.layer.name}}", "url": "{%url 'layerdetails' project.id o.preffered_layerversion.pk%}"}' data-directive="add">
105 <i class="icon-plus"></i>
106 Add layer
107 <i title="" class="icon-question-sign get-help" data-original-title="To build this target, you must first add the {{o.preffered_layerversion.layer.name}} layer to your project"></i>
108 </button>
109 </td>
110 </tr>
111 {% endfor %}
112{% include "basetable_bottom.html" %}
113
114 <!-- Modals -->
115
116 <!-- 'Layer dependencies modal' -->
117 <div id="dependencies_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true">
118 <form id="dependencies_modal_form">
119 <div class="modal-header">
120 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
121 <h3><span class="layer-name"></span> dependencies</h3>
122 </div>
123 <div class="modal-body">
124 <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>
125 <ul class="unstyled" id="dependencies_list">
126 </ul>
127 </div>
128 <div class="modal-footer">
129 <button class="btn btn-primary" type="submit">Add layers</button>
130 <button class="btn" type="reset" data-dismiss="modal">Cancel</button>
131 </div>
132 </form>
133 </div>
134
135{% endif %}
136
137{% if project %}
138<script>
139</script>
140{%endif%}
141
142{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index d686c967dc..d0c176b593 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -17,9 +17,11 @@
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 18
19from django.conf.urls import patterns, include, url 19from django.conf.urls import patterns, include, url
20from django.views.generic import RedirectView 20from django.views.generic import RedirectView, TemplateView
21 21
22from django.http import HttpResponseBadRequest 22from django.http import HttpResponseBadRequest
23import tables
24from widgets import ToasterTemplateView
23 25
24urlpatterns = patterns('toastergui.views', 26urlpatterns = patterns('toastergui.views',
25 # landing page 27 # landing page
@@ -77,19 +79,34 @@ urlpatterns = patterns('toastergui.views',
77 79
78 url(r'^project/$', lambda x: HttpResponseBadRequest(), name='base_project'), 80 url(r'^project/$', lambda x: HttpResponseBadRequest(), name='base_project'),
79 81
80 url(r'^project/(?P<pid>\d+)$', 'project', name='project'), 82 url(r'^project/(?P<pid>\d+)/$', 'project', name='project'),
81 url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), 83 url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'),
82 url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'), 84 url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'),
83 85
84 url(r'^project/(?P<pid>\d+)/layers/$', 'layers', name='all-layers'),
85 url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$', 'layerdetails', name='layerdetails'), 86 url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$', 'layerdetails', name='layerdetails'),
86 url(r'^project/(?P<pid>\d+)/layer/$', lambda x,pid: HttpResponseBadRequest(), name='base_layerdetails'), 87 url(r'^project/(?P<pid>\d+)/layer/$', lambda x,pid: HttpResponseBadRequest(), name='base_layerdetails'),
87 88
88 # the import layer is a project-specific functionality; 89 # the import layer is a project-specific functionality;
89 url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'), 90 url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'),
90 91
91 url(r'^project/(?P<pid>\d+)/targets/$', 'targets', name='all-targets'), 92 url(r'^project/(?P<pid>\d+)/machines/$',
92 url(r'^project/(?P<pid>\d+)/machines/$', 'machines', name='all-machines'), 93 ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"),
94 { 'table_name': tables.MachinesTable.__name__.lower(),
95 'title' : 'All compatible machines' },
96 name="all-machines"),
97
98 url(r'^project/(?P<pid>\d+)/recipes/$',
99 ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"),
100 { 'table_name': tables.RecipesTable.__name__.lower(),
101 'title' : 'All compatible recipes' },
102 name="all-targets"),
103
104 url(r'^project/(?P<pid>\d+)/layers/$',
105 ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"),
106 { 'table_name': tables.LayersTable.__name__.lower(),
107 'title' : 'All compatible layers' },
108 name="all-layers"),
109
93 110
94 url(r'^xhr_build/$', 'xhr_build', name='xhr_build'), 111 url(r'^xhr_build/$', 'xhr_build', name='xhr_build'),
95 url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'), 112 url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'),
@@ -100,6 +117,7 @@ urlpatterns = patterns('toastergui.views',
100 url(r'^xhr_datatypeahead/(?P<pid>\d+)$', 'xhr_datatypeahead', name='xhr_datatypeahead'), 117 url(r'^xhr_datatypeahead/(?P<pid>\d+)$', 'xhr_datatypeahead', name='xhr_datatypeahead'),
101 url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'), 118 url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
102 url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'), 119 url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'),
120 url(r'^xhr_tables/(?P<pid>\d+)/', include('toastergui.tables')),
103 121
104 # dashboard for failed build requests 122 # dashboard for failed build requests
105 url(r'^project/(?P<pid>\d+)/buildrequest/(?P<brid>\d+)$', 'buildrequestdetails', name='buildrequestdetails'), 123 url(r'^project/(?P<pid>\d+)/buildrequest/(?P<brid>\d+)$', 'buildrequestdetails', name='buildrequestdetails'),
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index c22f2c1aba..9217d8a100 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -2317,7 +2317,7 @@ if toastermain.settings.MANAGED:
2317 "tooltip": x.layer.vcs_url+" | "+x.get_vcs_reference(), 2317 "tooltip": x.layer.vcs_url+" | "+x.get_vcs_reference(),
2318 "detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.get_vcs_reference()+")"), 2318 "detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.get_vcs_reference()+")"),
2319 "giturl": x.layer.vcs_url, 2319 "giturl": x.layer.vcs_url,
2320 "layerdetailurl" : reverse('layerdetails', args=(pid, x.pk,)), 2320 "layerdetailurl" : reverse('layerdetails', args=(prj.id,x.pk)),
2321 "revision" : x.get_vcs_reference(), 2321 "revision" : x.get_vcs_reference(),
2322 } 2322 }
2323 2323
@@ -2656,81 +2656,6 @@ if toastermain.settings.MANAGED:
2656 return render(request, template, context) 2656 return render(request, template, context)
2657 2657
2658 2658
2659 def layers(request, pid):
2660
2661 template = "layers.html"
2662 # define here what parameters the view needs in the GET portion in order to
2663 # be able to display something. 'count' and 'page' are mandatory for all views
2664 # that use paginators.
2665 (pagesize, orderby) = _get_parameters_values(request, 100, 'layer__name:+')
2666 mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby };
2667 retval = _verify_parameters( request.GET, mandatory_parameters )
2668 if retval:
2669 return _redirect_parameters( 'all-layers', request.GET, mandatory_parameters, pid=pid)
2670
2671 # boilerplate code that takes a request for an object type and returns a queryset
2672 # for that object type. copypasta for all needed table searches
2673 (filter_string, search_term, ordering_string) = _search_tuple(request, Layer_Version)
2674
2675 prj = Project.objects.get(pk = pid)
2676
2677 queryset_all = prj.compatible_layerversions()
2678
2679 queryset_all = _get_queryset(Layer_Version, queryset_all, filter_string, search_term, ordering_string, '-layer__name')
2680
2681 object_list = set([x.get_equivalents_wpriority(prj)[0] for x in queryset_all])
2682 object_list = list(object_list)
2683
2684
2685 # retrieve the objects that will be displayed in the table; layers a paginator and gets a page range to display
2686 layer_info = _build_page_range(Paginator(object_list, request.GET.get('count', 10)),request.GET.get('page', 1))
2687
2688
2689 context = {
2690 'project' : prj,
2691 'projectlayerset' : jsonfilter(map(lambda x: x.layercommit.id, prj.projectlayer_set.all())),
2692 'objects' : layer_info,
2693 'objectname' : "layers",
2694 'default_orderby' : 'layer__name:+',
2695
2696 'tablecols' : [
2697 { 'name': 'Layer',
2698 'orderfield': _get_toggle_order(request, "layer__name"),
2699 'ordericon' : _get_toggle_order_icon(request, "layer__name"),
2700 },
2701 { 'name': 'Description',
2702 'dclass': 'span4',
2703 'clclass': 'description',
2704 },
2705 { 'name': 'Git repository URL',
2706 'dclass': 'span6',
2707 'clclass': 'git-repo', 'hidden': 1,
2708 'qhelp': "The Git repository for the layer source code",
2709 },
2710 { 'name': 'Subdirectory',
2711 'clclass': 'git-subdir',
2712 'hidden': 1,
2713 'qhelp': "The layer directory within the Git repository",
2714 },
2715 { 'name': 'Revision',
2716 'clclass': 'branch',
2717 'qhelp': "The Git branch, tag or commit. For the layers from the OpenEmbedded layer source, the revision is always the branch compatible with the Yocto Project version you selected for this project",
2718 },
2719 { 'name': 'Dependencies',
2720 'clclass': 'dependencies',
2721 'qhelp': "Other layers a layer depends upon",
2722 },
2723 { 'name': 'Add | Delete',
2724 'dclass': 'span2',
2725 'qhelp': "Add or delete layers to / from your project ",
2726 },
2727 ]
2728 }
2729
2730 response = render(request, template, context)
2731 _save_parameters_cookies(response, pagesize, orderby, request)
2732
2733 return response
2734 2659
2735 def layerdetails(request, pid, layerid): 2660 def layerdetails(request, pid, layerid):
2736 template = "layerdetails.html" 2661 template = "layerdetails.html"
@@ -2776,187 +2701,6 @@ if toastermain.settings.MANAGED:
2776 } 2701 }
2777 return render(request, template, context) 2702 return render(request, template, context)
2778 2703
2779 def targets(request, pid):
2780 template = 'targets.html'
2781 (pagesize, orderby) = _get_parameters_values(request, 100, 'name:+')
2782 mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby }
2783 retval = _verify_parameters( request.GET, mandatory_parameters )
2784 if retval:
2785 return _redirect_parameters( 'all-targets', request.GET, mandatory_parameters, pid = pid)
2786 (filter_string, search_term, ordering_string) = _search_tuple(request, Recipe)
2787
2788 prj = Project.objects.get(pk = pid)
2789 queryset_all = Recipe.objects.filter(Q(layer_version__up_branch__name= prj.release.name) | Q(layer_version__build__in = prj.build_set.all())).filter(name__regex=r'.{1,}.*')
2790
2791 queryset_with_search = _get_queryset(Recipe, queryset_all, None, search_term, ordering_string, '-name')
2792
2793 # get unique values for 'name', and select the maximum ID for each entry (the max id is the newest one)
2794
2795 # force evaluation of the query here; to process the MAX/GROUP BY, a temporary table is used, on which indexing is very slow
2796 # by forcing the evaluation here we also prime the caches
2797 queryset_with_search_maxids = map(lambda i: i[0], list(queryset_with_search.values('name').distinct().annotate(max_id=Max('id')).values_list('max_id')))
2798
2799 queryset_with_search = queryset_with_search.filter(id__in=queryset_with_search_maxids).select_related('layer_version', 'layer_version__layer', 'layer_version__up_branch', 'layer_source')
2800
2801
2802 # retrieve the objects that will be displayed in the table; targets a paginator and gets a page range to display
2803 target_info = _build_page_range(Paginator(queryset_with_search, request.GET.get('count', 10)),request.GET.get('page', 1))
2804
2805 for e in target_info.object_list:
2806 e.preffered_layerversion = e.layer_version.get_equivalents_wpriority(prj)[0]
2807 e.vcs_link_url = Layer.objects.filter(name = e.preffered_layerversion.layer.name).exclude(vcs_web_file_base_url__isnull=True)[0].vcs_web_file_base_url
2808 if e.vcs_link_url != None:
2809 fp = e.preffered_layerversion.dirpath + "/" + e.file_path
2810 e.vcs_link_url = e.vcs_link_url.replace('%path%', fp)
2811 e.vcs_link_url = e.vcs_link_url.replace('%branch%', e.preffered_layerversion.up_branch.name)
2812
2813 context = {
2814 'project' : prj,
2815 'projectlayerset' : jsonfilter(map(lambda x: x.layercommit.id, prj.projectlayer_set.all().select_related("layercommit"))),
2816 'objects' : target_info,
2817 'objectname' : "recipes",
2818 'default_orderby' : 'name:+',
2819
2820 'tablecols' : [
2821 { 'name': 'Recipe',
2822 'orderfield': _get_toggle_order(request, "name"),
2823 'ordericon' : _get_toggle_order_icon(request, "name"),
2824 },
2825 { 'name': 'Recipe version',
2826 'dclass': 'span2',
2827 },
2828 { 'name': 'Description',
2829 'dclass': 'span5',
2830 'clclass': 'description',
2831 },
2832 { 'name': 'Recipe file',
2833 'clclass': 'recipe-file',
2834 'hidden': 1,
2835 'dclass': 'span5',
2836 },
2837 { 'name': 'Section',
2838 'clclass': 'target-section',
2839 'hidden': 1,
2840 'orderfield': _get_toggle_order(request, "section"),
2841 'ordericon': _get_toggle_order_icon(request, "section"),
2842 'orderkey': "section",
2843 },
2844 { 'name': 'License',
2845 'clclass': 'license',
2846 'hidden': 1,
2847 'orderfield': _get_toggle_order(request, "license"),
2848 'ordericon': _get_toggle_order_icon(request, "license"),
2849 'orderkey': "license",
2850 },
2851 { 'name': 'Layer',
2852 'clclass': 'layer',
2853 'orderfield': _get_toggle_order(request, "layer_version__layer__name"),
2854 'ordericon': _get_toggle_order_icon(request, "layer_version__layer__name"),
2855 'orderkey': "layer_version__layer__name",
2856 },
2857 { 'name': 'Revision',
2858 'clclass': 'branch',
2859 'qhelp': "The Git branch, tag or commit. For the layers from the OpenEmbedded layer source, the revision is always the branch compatible with the Yocto Project version you selected for this project.",
2860 'hidden': 1,
2861 },
2862 ]
2863 }
2864
2865 context['tablecols'] += [
2866 { 'name': 'Build',
2867 'dclass': 'span2',
2868 'qhelp': "Add or delete targets to / from your project ",
2869 }, ]
2870
2871 response = render(request, template, context)
2872 _save_parameters_cookies(response, pagesize, orderby, request)
2873
2874 return response
2875
2876 def machines(request, pid):
2877 template = "machines.html"
2878 # define here what parameters the view needs in the GET portion in order to
2879 # be able to display something. 'count' and 'page' are mandatory for all views
2880 # that use paginators.
2881 (pagesize, orderby) = _get_parameters_values(request, 100, 'name:+')
2882 mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby };
2883 retval = _verify_parameters( request.GET, mandatory_parameters )
2884 if retval:
2885 return _redirect_parameters( 'all-machines', request.GET, mandatory_parameters, pid = pid)
2886
2887 # boilerplate code that takes a request for an object type and returns a queryset
2888 # for that object type. copypasta for all needed table searches
2889 (filter_string, search_term, ordering_string) = _search_tuple(request, Machine)
2890
2891 prj = Project.objects.get(pk = pid)
2892 compatible_layers = prj.compatible_layerversions()
2893
2894 queryset_all = Machine.objects.filter(layer_version__in=compatible_layers)
2895 queryset_all = _get_queryset(Machine, queryset_all, None, search_term, ordering_string, 'name')
2896
2897 queryset_all = queryset_all.prefetch_related('layer_version')
2898
2899
2900 # Make sure we only show machines / layers which are compatible
2901 # with the current project
2902
2903 project_layers = ProjectLayer.objects.filter(project_id=pid).values_list('layercommit',flat=True)
2904
2905 # Now we need to weed out the layers which will appear as duplicated
2906 # because they're from a layer source which doesn't need to be used
2907 for machine in queryset_all:
2908 to_rm = machine.layer_version.get_equivalents_wpriority(prj)[1:]
2909 if len(to_rm) > 0:
2910 queryset_all = queryset_all.exclude(layer_version__in=to_rm)
2911
2912 machine_info = _build_page_range(Paginator(queryset_all, request.GET.get('count', 100)),request.GET.get('page', 1))
2913
2914 context = {
2915 'project': prj,
2916 'objects' : machine_info,
2917 'projectlayerset' : jsonfilter(map(lambda x: x.layercommit.id, prj.projectlayer_set.all())),
2918 'objectname' : "machines",
2919 'default_orderby' : 'name:+',
2920
2921 'tablecols' : [
2922 { 'name': 'Machine',
2923 'orderfield': _get_toggle_order(request, "name"),
2924 'ordericon' : _get_toggle_order_icon(request, "name"),
2925 'orderkey' : "name",
2926 },
2927 { 'name': 'Description',
2928 'dclass': 'span5',
2929 'clclass': 'description',
2930 },
2931 { 'name': 'Layer',
2932 'clclass': 'layer',
2933 'orderfield': _get_toggle_order(request, "layer_version__layer__name"),
2934 'ordericon' : _get_toggle_order_icon(request, "layer_version__layer__name"),
2935 'orderkey' : "layer_version__layer__name",
2936 },
2937 { 'name': 'Revision',
2938 'clclass': 'branch',
2939 'qhelp' : "The Git branch, tag or commit. For the layers from the OpenEmbedded layer source, the revision is always the branch compatible with the Yocto Project version you selected for this project",
2940 'hidden': 1,
2941 },
2942 { 'name' : 'Machine file',
2943 'clclass' : 'machinefile',
2944 'hidden' : 1,
2945 },
2946 { 'name': 'Select',
2947 'dclass': 'select span2',
2948 'qhelp': "Sets the selected machine as the project machine. You can only have one machine per project",
2949 },
2950
2951 ]
2952 }
2953
2954 response = render(request, template, context)
2955 _save_parameters_cookies(response, pagesize, orderby, request)
2956
2957 return response
2958
2959
2960 def get_project_configvars_context(): 2704 def get_project_configvars_context():
2961 # Vars managed outside of this view 2705 # Vars managed outside of this view
2962 vars_managed = { 2706 vars_managed = {
@@ -3497,18 +3241,9 @@ else:
3497 def importlayer(request): 3241 def importlayer(request):
3498 return render(request, 'landing_not_managed.html') 3242 return render(request, 'landing_not_managed.html')
3499 3243
3500 def layers(request):
3501 return render(request, 'landing_not_managed.html')
3502
3503 def layerdetails(request, layerid): 3244 def layerdetails(request, layerid):
3504 return render(request, 'landing_not_managed.html') 3245 return render(request, 'landing_not_managed.html')
3505 3246
3506 def targets(request, pid):
3507 return render(request, 'landing_not_managed.html')
3508
3509 def machines(request):
3510 return render(request, 'landing_not_managed.html')
3511
3512 def projectconf(request, pid): 3247 def projectconf(request, pid):
3513 return render(request, 'landing_not_managed.html') 3248 return render(request, 'landing_not_managed.html')
3514 3249