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>
This commit is contained in:
Alexandru DAMIAN
2015-06-03 12:36:30 +01:00
committed by Richard Purdie
parent 751e9182ac
commit d9341d1a77
7 changed files with 102 additions and 70 deletions

View File

@@ -383,12 +383,13 @@ function tableInit(ctx){
*/
var params = {
'name' : filterName,
'search': tableParams.search
'search': tableParams.search,
'cmd': 'filterinfo',
};
$.ajax({
type: "GET",
url: ctx.url + 'filterinfo',
url: ctx.url,
data: params,
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
success: function (filterData) {

View File

@@ -19,7 +19,7 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from widgets import ToasterTable
from toastergui.widgets import ToasterTable
from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
from django.db.models import Q, Max
from django.conf.urls import url
@@ -29,9 +29,19 @@ class LayersTable(ToasterTable):
"""Table of layers in Toaster"""
def __init__(self, *args, **kwargs):
ToasterTable.__init__(self)
super(LayersTable, self).__init__(*args, **kwargs)
self.default_orderby = "layer__name"
def get_context_data(self, **kwargs):
context = super(LayersTable, self).get_context_data(**kwargs)
context['project'] = Project.objects.get(pk=kwargs['pid'])
context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
return context
def setup_queryset(self, *args, **kwargs):
prj = Project.objects.get(pk = kwargs['pid'])
compatible_layers = prj.compatible_layerversions()
@@ -132,14 +142,31 @@ class LayersTable(ToasterTable):
static_data_name="add-del-layers",
static_data_template='{% include "layer_btn.html" %}')
class LayerDetails(TemplateView):
def get_context_data(self, **kwargs):
context = super(LayerDetails, self).get_context_data(**kwargs)
context['project'] = Project.objects.get(pk=kwargs['pid'])
context['layerversion'] = Layer_Version.objects.get(pk=kwargs['layerid'])
context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
return context
class MachinesTable(ToasterTable):
"""Table of Machines in Toaster"""
def __init__(self, *args, **kwargs):
ToasterTable.__init__(self)
super(MachinesTable, self).__init__(*args, **kwargs)
self.empty_state = "No machines maybe you need to do a build?"
self.default_orderby = "name"
def get_context_data(self, **kwargs):
context = super(MachinesTable, self).get_context_data(**kwargs)
context['project'] = Project.objects.get(pk=kwargs['pid'])
context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
return context
def setup_queryset(self, *args, **kwargs):
prj = Project.objects.get(pk = kwargs['pid'])
compatible_layers = prj.compatible_layerversions()
@@ -191,7 +218,13 @@ class LayerMachinesTable(MachinesTable):
""" Smaller version of the Machines table for use in layer details """
def __init__(self, *args, **kwargs):
MachinesTable.__init__(self)
super(LayerMachinesTable, self).__init__(*args, **kwargs)
def get_context_data(self, **kwargs):
context = super(LayerMachinesTable, self).get_context_data(**kwargs)
context['layerversion'] = Layer_Version.objects.get(pk=kwargs['layerid'])
return context
def setup_queryset(self, *args, **kwargs):
MachinesTable.setup_queryset(self, *args, **kwargs)
@@ -219,10 +252,20 @@ class RecipesTable(ToasterTable):
"""Table of Recipes in Toaster"""
def __init__(self, *args, **kwargs):
ToasterTable.__init__(self)
super(RecipesTable, self).__init__(*args, **kwargs)
self.empty_state = "Toaster has no recipe information. To generate recipe information you can configure a layer source then run a build."
self.default_orderby = "name"
def get_context_data(self, **kwargs):
context = super(RecipesTable, self).get_context_data(**kwargs)
context['project'] = Project.objects.get(pk=kwargs['pid'])
context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
return context
def setup_queryset(self, *args, **kwargs):
prj = Project.objects.get(pk = kwargs['pid'])
@@ -293,10 +336,16 @@ class RecipesTable(ToasterTable):
static_data_template='{% include "recipe_btn.html" %}')
class LayerRecipesTable(RecipesTable):
""" Smaller version of the Machines table for use in layer details """
""" Smaller version of the Recipes table for use in layer details """
def __init__(self, *args, **kwargs):
RecipesTable.__init__(self)
super(LayerRecipesTable, self).__init__(*args, **kwargs)
def get_context_data(self, **kwargs):
context = super(LayerRecipesTable, self).get_context_data(**kwargs)
context['layerversion'] = Layer_Version.objects.get(pk=kwargs['layerid'])
return context
def setup_queryset(self, *args, **kwargs):
RecipesTable.setup_queryset(self, *args, **kwargs)
@@ -320,24 +369,3 @@ class LayerRecipesTable(RecipesTable):
self.add_column(title="Build recipe",
static_data_name="add-del-layers",
static_data_template=build_recipe_template)
# This needs to be staticaly defined here as django reads the url patterns
# on start up
urlpatterns = (
url(r'^machines/(?P<cmd>\w+)*', MachinesTable.as_view(),
name=MachinesTable.__name__.lower()),
url(r'^layers/(?P<cmd>\w+)*', LayersTable.as_view(),
name=LayersTable.__name__.lower()),
url(r'^recipes/(?P<cmd>\w+)*', RecipesTable.as_view(),
name=RecipesTable.__name__.lower()),
# layer details tables
url(r'^layer/(?P<layerid>\d+)/recipes/(?P<cmd>\w+)*',
LayerRecipesTable.as_view(),
name=LayerRecipesTable.__name__.lower()),
url(r'^layer/(?P<layerid>\d+)/machines/(?P<cmd>\w+)*',
LayerMachinesTable.as_view(),
name=LayerMachinesTable.__name__.lower()),
)

View File

@@ -33,7 +33,7 @@
$(document).ready(function (){
var ctx = {
projectBuildUrl : "{% url 'xhr_build' %}",
projectBuildUrl : "{% url 'xhr_projectbuild' project.id %}",
layerDetailsUrl : "{% url 'base_layerdetails' project.id %}",
xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}",
layerVersion : {

View File

@@ -10,7 +10,7 @@
var ctx = {
tableName : "{{table_name}}",
url : "{{ xhr_table_url }}",
url : "{{ xhr_table_url }}?format=json",
title : "{{title}}",
projectLayers : {{projectlayers|json}},
};

View File

@@ -10,7 +10,7 @@
var ctx = {
tableName : "{{table_name}}",
url : "{{ xhr_table_url }}",
url : "{{ xhr_table_url }}?format=json",
title : "{{title}}",
projectLayers : {{projectlayers|json}},
};

View File

@@ -20,8 +20,7 @@ from django.conf.urls import patterns, include, url
from django.views.generic import RedirectView, TemplateView
from django.http import HttpResponseBadRequest
import tables
from widgets import ToasterTemplateView
from toastergui import tables
urlpatterns = patterns('toastergui.views',
# landing page
@@ -81,32 +80,46 @@ urlpatterns = patterns('toastergui.views',
url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'),
url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'),
url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$',
ToasterTemplateView.as_view(template_name='layerdetails.html'),
name='layerdetails'),
url(r'^project/(?P<pid>\d+)/layer/$', lambda x,pid: HttpResponseBadRequest(), name='base_layerdetails'),
# the import layer is a project-specific functionality;
url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'),
# the table pages that have been converted to ToasterTable widget
url(r'^project/(?P<pid>\d+)/machines/$',
ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"),
tables.MachinesTable.as_view(template_name="generic-toastertable-page.html"),
{ 'table_name': tables.MachinesTable.__name__.lower(),
'title' : 'All compatible machines' },
name="all-machines"),
url(r'^project/(?P<pid>\d+)/recipes/$',
ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"),
tables.RecipesTable.as_view(template_name="generic-toastertable-page.html"),
{ 'table_name': tables.RecipesTable.__name__.lower(),
'title' : 'All compatible recipes' },
name="all-targets"),
url(r'^project/(?P<pid>\d+)/layers/$',
ToasterTemplateView.as_view(template_name="generic-toastertable-page.html"),
tables.LayersTable.as_view(template_name="generic-toastertable-page.html"),
{ 'table_name': tables.LayersTable.__name__.lower(),
'title' : 'All compatible layers' },
name="all-layers"),
url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$',
tables.LayerDetails.as_view(template_name='layerdetails.html'),
name='layerdetails'),
url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)/recipes/$',
tables.LayerRecipesTable.as_view(template_name="generic-toastertable-page.html"),
{ 'table_name': tables.LayerRecipesTable.__name__.lower(),
'title' : 'All recipes in layer' },
name=tables.LayerRecipesTable.__name__.lower()),
url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)/machines/$',
tables.LayerMachinesTable.as_view(template_name="generic-toastertable-page.html"),
{ 'table_name': tables.LayerMachinesTable.__name__.lower(),
'title' : 'All machines in layer' },
name=tables.LayerMachinesTable.__name__.lower()),
url(r'^xhr_projectbuild/(?P<pid>\d+)$', 'xhr_projectbuild', name='xhr_projectbuild'),
url(r'^xhr_projectinfo/$', 'xhr_projectinfo', name='xhr_projectinfo'),
@@ -116,7 +129,6 @@ urlpatterns = patterns('toastergui.views',
url(r'^xhr_datatypeahead/(?P<pid>\d+)$', 'xhr_datatypeahead', name='xhr_datatypeahead'),
url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
url(r'^xhr_updatelayer/$', 'xhr_updatelayer', name='xhr_updatelayer'),
url(r'^xhr_tables/project/(?P<pid>\d+)/', include('toastergui.tables')),
# dashboard for failed build requests
url(r'^project/(?P<pid>\d+)/buildrequest/(?P<brid>\d+)$', 'buildrequestdetails', name='buildrequestdetails'),

View File

@@ -32,29 +32,17 @@ from django.core.serializers.json import DjangoJSONEncoder
from django.core.exceptions import FieldError
from django.conf.urls import url, patterns
import urls
import types
import json
import collections
import operator
class ToasterTemplateView(TemplateView):
def get_context_data(self, **kwargs):
context = super(ToasterTemplateView, self).get_context_data(**kwargs)
if 'pid' in kwargs:
context['project'] = Project.objects.get(pk=kwargs['pid'])
context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
if 'layerid' in kwargs:
context['layerversion'] = Layer_Version.objects.get(pk=kwargs['layerid'])
return context
class ToasterTable(View):
def __init__(self):
class ToasterTable(TemplateView):
def __init__(self, *args, **kwargs):
super(ToasterTable, self).__init__()
if 'template_name' in kwargs:
self.template_name = kwargs['template_name']
self.title = None
self.queryset = None
self.columns = []
@@ -66,20 +54,23 @@ class ToasterTable(View):
self.default_orderby = ""
def get(self, request, *args, **kwargs):
self.setup_queryset(*args, **kwargs)
if request.GET.get('format', None) == 'json':
# Put the project id into the context for the static_data_template
if 'pid' in kwargs:
self.static_context_extra['pid'] = kwargs['pid']
self.setup_queryset(*args, **kwargs)
# Put the project id into the context for the static_data_template
if 'pid' in kwargs:
self.static_context_extra['pid'] = kwargs['pid']
cmd = kwargs['cmd']
if cmd and 'filterinfo' in cmd:
data = self.get_filter_info(request)
else:
# If no cmd is specified we give you the table data
data = self.get_data(request, **kwargs)
cmd = request.GET.get('cmd', None)
if cmd and 'filterinfo' in cmd:
data = self.get_filter_info(request)
else:
# If no cmd is specified we give you the table data
data = self.get_data(request, **kwargs)
return HttpResponse(data, content_type="application/json")
return HttpResponse(data, content_type="application/json")
return super(ToasterTable, self).get(request, *args, **kwargs)
def get_filter_info(self, request):
data = None