summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2015-06-03 12:36:30 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-06-12 00:01:47 +0100
commitd9341d1a774ccea25e64583f9adc61b163fb1f95 (patch)
treea2989f7885d4b1a3acce138cfdd93b864fd81832
parent751e9182ac7f37506c3d85cade00ef6f3986eb7a (diff)
downloadpoky-d9341d1a774ccea25e64583f9adc61b163fb1f95.tar.gz
bitbake: toaster: toastertables REST refactoring
This patch refactors the ToasterTables to bring them in line with REST principles - - all table pages now support the "format=json" GET parameter that returns the data in JSON format - the tables themselves This cleans up the URL namespace by aleviating the need to have two URLS for each table (one for the template and one for the data loading), and fixes minor things in the ToasterTable implementation. (Bitbake rev: 1778dac9fd39dae75c55bf2cf836cdd488dbc265) Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/table.js5
-rw-r--r--bitbake/lib/toaster/toastergui/tables.py84
-rw-r--r--bitbake/lib/toaster/toastergui/templates/layerdetails.html2
-rw-r--r--bitbake/lib/toaster/toastergui/templates/toastertable-simple.html2
-rw-r--r--bitbake/lib/toaster/toastergui/templates/toastertable.html2
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py30
-rw-r--r--bitbake/lib/toaster/toastergui/widgets.py47
7 files changed, 102 insertions, 70 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/table.js b/bitbake/lib/toaster/toastergui/static/js/table.js
index 2e35e3871c..7588a4ab9a 100644
--- a/bitbake/lib/toaster/toastergui/static/js/table.js
+++ b/bitbake/lib/toaster/toastergui/static/js/table.js
@@ -383,12 +383,13 @@ function tableInit(ctx){
383 */ 383 */
384 var params = { 384 var params = {
385 'name' : filterName, 385 'name' : filterName,
386 'search': tableParams.search 386 'search': tableParams.search,
387 'cmd': 'filterinfo',
387 }; 388 };
388 389
389 $.ajax({ 390 $.ajax({
390 type: "GET", 391 type: "GET",
391 url: ctx.url + 'filterinfo', 392 url: ctx.url,
392 data: params, 393 data: params,
393 headers: { 'X-CSRFToken' : $.cookie('csrftoken')}, 394 headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
394 success: function (filterData) { 395 success: function (filterData) {
diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py
index 9a93ff9aad..b75e565246 100644
--- a/bitbake/lib/toaster/toastergui/tables.py
+++ b/bitbake/lib/toaster/toastergui/tables.py
@@ -19,7 +19,7 @@
19# with this program; if not, write to the Free Software Foundation, Inc., 19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 21
22from widgets import ToasterTable 22from toastergui.widgets import ToasterTable
23from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project 23from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
24from django.db.models import Q, Max 24from django.db.models import Q, Max
25from django.conf.urls import url 25from django.conf.urls import url
@@ -29,9 +29,19 @@ class LayersTable(ToasterTable):
29 """Table of layers in Toaster""" 29 """Table of layers in Toaster"""
30 30
31 def __init__(self, *args, **kwargs): 31 def __init__(self, *args, **kwargs):
32 ToasterTable.__init__(self) 32 super(LayersTable, self).__init__(*args, **kwargs)
33 self.default_orderby = "layer__name" 33 self.default_orderby = "layer__name"
34 34
35 def get_context_data(self, **kwargs):
36 context = super(LayersTable, self).get_context_data(**kwargs)
37
38 context['project'] = Project.objects.get(pk=kwargs['pid'])
39
40 context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
41
42 return context
43
44
35 def setup_queryset(self, *args, **kwargs): 45 def setup_queryset(self, *args, **kwargs):
36 prj = Project.objects.get(pk = kwargs['pid']) 46 prj = Project.objects.get(pk = kwargs['pid'])
37 compatible_layers = prj.compatible_layerversions() 47 compatible_layers = prj.compatible_layerversions()
@@ -132,14 +142,31 @@ class LayersTable(ToasterTable):
132 static_data_name="add-del-layers", 142 static_data_name="add-del-layers",
133 static_data_template='{% include "layer_btn.html" %}') 143 static_data_template='{% include "layer_btn.html" %}')
134 144
145class LayerDetails(TemplateView):
146 def get_context_data(self, **kwargs):
147 context = super(LayerDetails, self).get_context_data(**kwargs)
148
149 context['project'] = Project.objects.get(pk=kwargs['pid'])
150 context['layerversion'] = Layer_Version.objects.get(pk=kwargs['layerid'])
151 context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
152
153 return context
154
135class MachinesTable(ToasterTable): 155class MachinesTable(ToasterTable):
136 """Table of Machines in Toaster""" 156 """Table of Machines in Toaster"""
137 157
138 def __init__(self, *args, **kwargs): 158 def __init__(self, *args, **kwargs):
139 ToasterTable.__init__(self) 159 super(MachinesTable, self).__init__(*args, **kwargs)
140 self.empty_state = "No machines maybe you need to do a build?" 160 self.empty_state = "No machines maybe you need to do a build?"
141 self.default_orderby = "name" 161 self.default_orderby = "name"
142 162
163 def get_context_data(self, **kwargs):
164 context = super(MachinesTable, self).get_context_data(**kwargs)
165 context['project'] = Project.objects.get(pk=kwargs['pid'])
166 context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
167 return context
168
169
143 def setup_queryset(self, *args, **kwargs): 170 def setup_queryset(self, *args, **kwargs):
144 prj = Project.objects.get(pk = kwargs['pid']) 171 prj = Project.objects.get(pk = kwargs['pid'])
145 compatible_layers = prj.compatible_layerversions() 172 compatible_layers = prj.compatible_layerversions()
@@ -191,7 +218,13 @@ class LayerMachinesTable(MachinesTable):
191 """ Smaller version of the Machines table for use in layer details """ 218 """ Smaller version of the Machines table for use in layer details """
192 219
193 def __init__(self, *args, **kwargs): 220 def __init__(self, *args, **kwargs):
194 MachinesTable.__init__(self) 221 super(LayerMachinesTable, self).__init__(*args, **kwargs)
222
223 def get_context_data(self, **kwargs):
224 context = super(LayerMachinesTable, self).get_context_data(**kwargs)
225 context['layerversion'] = Layer_Version.objects.get(pk=kwargs['layerid'])
226 return context
227
195 228
196 def setup_queryset(self, *args, **kwargs): 229 def setup_queryset(self, *args, **kwargs):
197 MachinesTable.setup_queryset(self, *args, **kwargs) 230 MachinesTable.setup_queryset(self, *args, **kwargs)
@@ -219,10 +252,20 @@ class RecipesTable(ToasterTable):
219 """Table of Recipes in Toaster""" 252 """Table of Recipes in Toaster"""
220 253
221 def __init__(self, *args, **kwargs): 254 def __init__(self, *args, **kwargs):
222 ToasterTable.__init__(self) 255 super(RecipesTable, self).__init__(*args, **kwargs)
223 self.empty_state = "Toaster has no recipe information. To generate recipe information you can configure a layer source then run a build." 256 self.empty_state = "Toaster has no recipe information. To generate recipe information you can configure a layer source then run a build."
224 self.default_orderby = "name" 257 self.default_orderby = "name"
225 258
259 def get_context_data(self, **kwargs):
260 context = super(RecipesTable, self).get_context_data(**kwargs)
261
262 context['project'] = Project.objects.get(pk=kwargs['pid'])
263
264 context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
265
266 return context
267
268
226 def setup_queryset(self, *args, **kwargs): 269 def setup_queryset(self, *args, **kwargs):
227 prj = Project.objects.get(pk = kwargs['pid']) 270 prj = Project.objects.get(pk = kwargs['pid'])
228 271
@@ -293,10 +336,16 @@ class RecipesTable(ToasterTable):
293 static_data_template='{% include "recipe_btn.html" %}') 336 static_data_template='{% include "recipe_btn.html" %}')
294 337
295class LayerRecipesTable(RecipesTable): 338class LayerRecipesTable(RecipesTable):
296 """ Smaller version of the Machines table for use in layer details """ 339 """ Smaller version of the Recipes table for use in layer details """
297 340
298 def __init__(self, *args, **kwargs): 341 def __init__(self, *args, **kwargs):
299 RecipesTable.__init__(self) 342 super(LayerRecipesTable, self).__init__(*args, **kwargs)
343
344 def get_context_data(self, **kwargs):
345 context = super(LayerRecipesTable, self).get_context_data(**kwargs)
346 context['layerversion'] = Layer_Version.objects.get(pk=kwargs['layerid'])
347 return context
348
300 349
301 def setup_queryset(self, *args, **kwargs): 350 def setup_queryset(self, *args, **kwargs):
302 RecipesTable.setup_queryset(self, *args, **kwargs) 351 RecipesTable.setup_queryset(self, *args, **kwargs)
@@ -320,24 +369,3 @@ class LayerRecipesTable(RecipesTable):
320 self.add_column(title="Build recipe", 369 self.add_column(title="Build recipe",
321 static_data_name="add-del-layers", 370 static_data_name="add-del-layers",
322 static_data_template=build_recipe_template) 371 static_data_template=build_recipe_template)
323
324
325
326# This needs to be staticaly defined here as django reads the url patterns
327# on start up
328urlpatterns = (
329 url(r'^machines/(?P<cmd>\w+)*', MachinesTable.as_view(),
330 name=MachinesTable.__name__.lower()),
331 url(r'^layers/(?P<cmd>\w+)*', LayersTable.as_view(),
332 name=LayersTable.__name__.lower()),
333 url(r'^recipes/(?P<cmd>\w+)*', RecipesTable.as_view(),
334 name=RecipesTable.__name__.lower()),
335
336 # layer details tables
337 url(r'^layer/(?P<layerid>\d+)/recipes/(?P<cmd>\w+)*',
338 LayerRecipesTable.as_view(),
339 name=LayerRecipesTable.__name__.lower()),
340 url(r'^layer/(?P<layerid>\d+)/machines/(?P<cmd>\w+)*',
341 LayerMachinesTable.as_view(),
342 name=LayerMachinesTable.__name__.lower()),
343)
diff --git a/bitbake/lib/toaster/toastergui/templates/layerdetails.html b/bitbake/lib/toaster/toastergui/templates/layerdetails.html
index 259a59ea0a..c27d259a8c 100644
--- a/bitbake/lib/toaster/toastergui/templates/layerdetails.html
+++ b/bitbake/lib/toaster/toastergui/templates/layerdetails.html
@@ -33,7 +33,7 @@
33 33
34 $(document).ready(function (){ 34 $(document).ready(function (){
35 var ctx = { 35 var ctx = {
36 projectBuildUrl : "{% url 'xhr_build' %}", 36 projectBuildUrl : "{% url 'xhr_projectbuild' project.id %}",
37 layerDetailsUrl : "{% url 'base_layerdetails' project.id %}", 37 layerDetailsUrl : "{% url 'base_layerdetails' project.id %}",
38 xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}", 38 xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}",
39 layerVersion : { 39 layerVersion : {
diff --git a/bitbake/lib/toaster/toastergui/templates/toastertable-simple.html b/bitbake/lib/toaster/toastergui/templates/toastertable-simple.html
index 23a75260a1..ea7b38e130 100644
--- a/bitbake/lib/toaster/toastergui/templates/toastertable-simple.html
+++ b/bitbake/lib/toaster/toastergui/templates/toastertable-simple.html
@@ -10,7 +10,7 @@
10 10
11 var ctx = { 11 var ctx = {
12 tableName : "{{table_name}}", 12 tableName : "{{table_name}}",
13 url : "{{ xhr_table_url }}", 13 url : "{{ xhr_table_url }}?format=json",
14 title : "{{title}}", 14 title : "{{title}}",
15 projectLayers : {{projectlayers|json}}, 15 projectLayers : {{projectlayers|json}},
16 }; 16 };
diff --git a/bitbake/lib/toaster/toastergui/templates/toastertable.html b/bitbake/lib/toaster/toastergui/templates/toastertable.html
index 5c79ab4ae1..c7c7a84bf7 100644
--- a/bitbake/lib/toaster/toastergui/templates/toastertable.html
+++ b/bitbake/lib/toaster/toastergui/templates/toastertable.html
@@ -10,7 +10,7 @@
10 10
11 var ctx = { 11 var ctx = {
12 tableName : "{{table_name}}", 12 tableName : "{{table_name}}",
13 url : "{{ xhr_table_url }}", 13 url : "{{ xhr_table_url }}?format=json",
14 title : "{{title}}", 14 title : "{{title}}",
15 projectLayers : {{projectlayers|json}}, 15 projectLayers : {{projectlayers|json}},
16 }; 16 };
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index 4e328dae17..e10e0bb159 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -20,8 +20,7 @@ from django.conf.urls import patterns, include, url
20from django.views.generic import RedirectView, TemplateView 20from django.views.generic import RedirectView, TemplateView
21 21
22from django.http import HttpResponseBadRequest 22from django.http import HttpResponseBadRequest
23import tables 23from toastergui import tables
24from widgets import ToasterTemplateView
25 24
26urlpatterns = patterns('toastergui.views', 25urlpatterns = patterns('toastergui.views',
27 # landing page 26 # landing page
@@ -81,32 +80,46 @@ urlpatterns = patterns('toastergui.views',
81 url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'), 80 url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'),
82 url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'), 81 url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'),
83 82
84 url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$',
85 ToasterTemplateView.as_view(template_name='layerdetails.html'),
86 name='layerdetails'),
87 url(r'^project/(?P<pid>\d+)/layer/$', lambda x,pid: HttpResponseBadRequest(), name='base_layerdetails'), 83 url(r'^project/(?P<pid>\d+)/layer/$', lambda x,pid: HttpResponseBadRequest(), name='base_layerdetails'),
88 84
89 # the import layer is a project-specific functionality; 85 # the import layer is a project-specific functionality;
90 url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'), 86 url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'),
91 87
88
89 # the table pages that have been converted to ToasterTable widget
92 url(r'^project/(?P<pid>\d+)/machines/$', 90 url(r'^project/(?P<pid>\d+)/machines/$',
93 ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"), 91 tables.MachinesTable.as_view(template_name="generic-toastertable-page.html"),
94 { 'table_name': tables.MachinesTable.__name__.lower(), 92 { 'table_name': tables.MachinesTable.__name__.lower(),
95 'title' : 'All compatible machines' }, 93 'title' : 'All compatible machines' },
96 name="all-machines"), 94 name="all-machines"),
97 95
98 url(r'^project/(?P<pid>\d+)/recipes/$', 96 url(r'^project/(?P<pid>\d+)/recipes/$',
99 ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"), 97 tables.RecipesTable.as_view(template_name="generic-toastertable-page.html"),
100 { 'table_name': tables.RecipesTable.__name__.lower(), 98 { 'table_name': tables.RecipesTable.__name__.lower(),
101 'title' : 'All compatible recipes' }, 99 'title' : 'All compatible recipes' },
102 name="all-targets"), 100 name="all-targets"),
103 101
104 url(r'^project/(?P<pid>\d+)/layers/$', 102 url(r'^project/(?P<pid>\d+)/layers/$',
105 ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"), 103 tables.LayersTable.as_view(template_name="generic-toastertable-page.html"),
106 { 'table_name': tables.LayersTable.__name__.lower(), 104 { 'table_name': tables.LayersTable.__name__.lower(),
107 'title' : 'All compatible layers' }, 105 'title' : 'All compatible layers' },
108 name="all-layers"), 106 name="all-layers"),
109 107
108 url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$',
109 tables.LayerDetails.as_view(template_name='layerdetails.html'),
110 name='layerdetails'),
111
112 url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)/recipes/$',
113 tables.LayerRecipesTable.as_view(template_name="generic-toastertable-page.html"),
114 { 'table_name': tables.LayerRecipesTable.__name__.lower(),
115 'title' : 'All recipes in layer' },
116 name=tables.LayerRecipesTable.__name__.lower()),
117
118 url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)/machines/$',
119 tables.LayerMachinesTable.as_view(template_name="generic-toastertable-page.html"),
120 { 'table_name': tables.LayerMachinesTable.__name__.lower(),
121 'title' : 'All machines in layer' },
122 name=tables.LayerMachinesTable.__name__.lower()),
110 123
111 url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'), 124 url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'),
112 url(r'^xhr_projectinfo/$', 'xhr_projectinfo', name='xhr_projectinfo'), 125 url(r'^xhr_projectinfo/$', 'xhr_projectinfo', name='xhr_projectinfo'),
@@ -116,7 +129,6 @@ urlpatterns = patterns('toastergui.views',
116 url(r'^xhr_datatypeahead/(?P<pid>\d+)$', 'xhr_datatypeahead', name='xhr_datatypeahead'), 129 url(r'^xhr_datatypeahead/(?P<pid>\d+)$', 'xhr_datatypeahead', name='xhr_datatypeahead'),
117 url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'), 130 url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
118 url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'), 131 url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'),
119 url(r'^xhr_tables/project/(?P<pid>\d+)/', include('toastergui.tables')),
120 132
121 # dashboard for failed build requests 133 # dashboard for failed build requests
122 url(r'^project/(?P<pid>\d+)/buildrequest/(?P<brid>\d+)$', 'buildrequestdetails', name='buildrequestdetails'), 134 url(r'^project/(?P<pid>\d+)/buildrequest/(?P<brid>\d+)$', 'buildrequestdetails', name='buildrequestdetails'),
diff --git a/bitbake/lib/toaster/toastergui/widgets.py b/bitbake/lib/toaster/toastergui/widgets.py
index 8cf6e1bc2d..4347a3f081 100644
--- a/bitbake/lib/toaster/toastergui/widgets.py
+++ b/bitbake/lib/toaster/toastergui/widgets.py
@@ -32,29 +32,17 @@ from django.core.serializers.json import DjangoJSONEncoder
32from django.core.exceptions import FieldError 32from django.core.exceptions import FieldError
33from django.conf.urls import url, patterns 33from django.conf.urls import url, patterns
34 34
35import urls
36import types 35import types
37import json 36import json
38import collections 37import collections
39import operator 38import operator
40 39
41 40
42class ToasterTemplateView(TemplateView): 41class ToasterTable(TemplateView):
43 def get_context_data(self, **kwargs): 42 def __init__(self, *args, **kwargs):
44 context = super(ToasterTemplateView, self).get_context_data(**kwargs) 43 super(ToasterTable, self).__init__()
45 if 'pid' in kwargs: 44 if 'template_name' in kwargs:
46 context['project'] = Project.objects.get(pk=kwargs['pid']) 45 self.template_name = kwargs['template_name']
47
48 context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
49
50 if 'layerid' in kwargs:
51 context['layerversion'] = Layer_Version.objects.get(pk=kwargs['layerid'])
52
53 return context
54
55
56class ToasterTable(View):
57 def __init__(self):
58 self.title = None 46 self.title = None
59 self.queryset = None 47 self.queryset = None
60 self.columns = [] 48 self.columns = []
@@ -66,20 +54,23 @@ class ToasterTable(View):
66 self.default_orderby = "" 54 self.default_orderby = ""
67 55
68 def get(self, request, *args, **kwargs): 56 def get(self, request, *args, **kwargs):
69 self.setup_queryset(*args, **kwargs) 57 if request.GET.get('format', None) == 'json':
70 58
71 # Put the project id into the context for the static_data_template 59 self.setup_queryset(*args, **kwargs)
72 if 'pid' in kwargs: 60 # Put the project id into the context for the static_data_template
73 self.static_context_extra['pid'] = kwargs['pid'] 61 if 'pid' in kwargs:
62 self.static_context_extra['pid'] = kwargs['pid']
74 63
75 cmd = kwargs['cmd'] 64 cmd = request.GET.get('cmd', None)
76 if cmd and 'filterinfo' in cmd: 65 if cmd and 'filterinfo' in cmd:
77 data = self.get_filter_info(request) 66 data = self.get_filter_info(request)
78 else: 67 else:
79 # If no cmd is specified we give you the table data 68 # If no cmd is specified we give you the table data
80 data = self.get_data(request, **kwargs) 69 data = self.get_data(request, **kwargs)
70
71 return HttpResponse(data, content_type="application/json")
81 72
82 return HttpResponse(data, content_type="application/json") 73 return super(ToasterTable, self).get(request, *args, **kwargs)
83 74
84 def get_filter_info(self, request): 75 def get_filter_info(self, request):
85 data = None 76 data = None