diff options
author | Michael Wood <michael.g.wood@intel.com> | 2015-05-11 18:51:28 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-05-14 18:04:09 +0100 |
commit | 23f5b009e0ebf59cfcc9ae90a1084468fc88e42f (patch) | |
tree | 06eb458cbd9a95dd635160adac7d90aeae6afea1 /bitbake/lib | |
parent | 7f8c44771cc6219ad7e58da7840fffbe93f11b39 (diff) | |
download | poky-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/lib')
-rw-r--r-- | bitbake/lib/toaster/orm/models.py | 11 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/css/default.css | 3 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/layerBtn.js | 5 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/static/js/libtoaster.js | 3 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/tables.py | 279 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/layer_btn.html | 9 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/layers.html | 132 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/machine_btn.html | 8 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/machines.html | 88 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/recipe_btn.html | 8 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/targets.html | 142 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/urls.py | 28 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 267 |
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 | |||
260 | thead .description, .get_description_or_summary { width: 364px; } | ||
261 | thead .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 | ||
3 | function layerBtnsInit(ctx) { | 3 | function 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 | |||
22 | from widgets import ToasterTable | ||
23 | from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project | ||
24 | from django.db.models import Q, Max | ||
25 | from django.conf.urls import url | ||
26 | from django.views.generic import TemplateView | ||
27 | |||
28 | class 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 | |||
136 | class 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 | |||
193 | class 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 | ||
272 | urlpatterns = ( | ||
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">×</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">×</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">×</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 | ||
19 | from django.conf.urls import patterns, include, url | 19 | from django.conf.urls import patterns, include, url |
20 | from django.views.generic import RedirectView | 20 | from django.views.generic import RedirectView, TemplateView |
21 | 21 | ||
22 | from django.http import HttpResponseBadRequest | 22 | from django.http import HttpResponseBadRequest |
23 | import tables | ||
24 | from widgets import ToasterTemplateView | ||
23 | 25 | ||
24 | urlpatterns = patterns('toastergui.views', | 26 | urlpatterns = 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 | ||