bitbake: toaster: move MostRecentBuildsView to its own widget

This view is specific to the builds dashboard rather than gernic api so
like ToasterTable and ToasterTypeAhead we class it as a widget as it has
a single purpose. Also clean up some flake8 identified issues.

Original author of the code moved in this commit is Elliot Smith.

(Bitbake rev: 05428514e64ec896faae4055619e149e98bc8f57)

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Michael Wood 2016-09-26 13:59:29 +03:00 committed by Richard Purdie
parent 4d0bc8d521
commit 8ba7ccd252
3 changed files with 127 additions and 125 deletions

View File

@ -33,10 +33,8 @@ from bldcontrol import bbcontroller
from django.http import HttpResponse, JsonResponse
from django.views.generic import View
from django.core.urlresolvers import reverse
from django.utils import timezone
from django.db.models import Q, F
from django.db import Error
from toastergui.templatetags.projecttags import json, sectohms, get_tasks
from toastergui.templatetags.projecttags import filtered_filesizeformat
logger = logging.getLogger("toaster")
@ -227,112 +225,6 @@ class XhrLayer(View):
})
class MostRecentBuildsView(View):
def _was_yesterday_or_earlier(self, completed_on):
now = timezone.now()
delta = now - completed_on
if delta.days >= 1:
return True
return False
def get(self, request, *args, **kwargs):
"""
Returns a list of builds in JSON format.
"""
project = None
project_id = request.GET.get('project_id', None)
if project_id:
try:
project = Project.objects.get(pk=project_id)
except:
# if project lookup fails, assume no project
pass
recent_build_objs = Build.get_recent(project)
recent_builds = []
for build_obj in recent_build_objs:
dashboard_url = reverse('builddashboard', args=(build_obj.pk,))
buildtime_url = reverse('buildtime', args=(build_obj.pk,))
rebuild_url = \
reverse('xhr_buildrequest', args=(build_obj.project.pk,))
cancel_url = \
reverse('xhr_buildrequest', args=(build_obj.project.pk,))
build = {}
build['id'] = build_obj.pk
build['dashboard_url'] = dashboard_url
buildrequest_id = None
if hasattr(build_obj, 'buildrequest'):
buildrequest_id = build_obj.buildrequest.pk
build['buildrequest_id'] = buildrequest_id
build['recipes_parsed_percentage'] = \
int((build_obj.recipes_parsed /
build_obj.recipes_to_parse) * 100)
tasks_complete_percentage = 0
if build_obj.outcome in (Build.SUCCEEDED, Build.FAILED):
tasks_complete_percentage = 100
elif build_obj.outcome == Build.IN_PROGRESS:
tasks_complete_percentage = build_obj.completeper()
build['tasks_complete_percentage'] = tasks_complete_percentage
build['state'] = build_obj.get_state()
build['errors'] = build_obj.errors.count()
build['dashboard_errors_url'] = dashboard_url + '#errors'
build['warnings'] = build_obj.warnings.count()
build['dashboard_warnings_url'] = dashboard_url + '#warnings'
build['buildtime'] = sectohms(build_obj.timespent_seconds)
build['buildtime_url'] = buildtime_url
build['rebuild_url'] = rebuild_url
build['cancel_url'] = cancel_url
build['is_default_project_build'] = build_obj.project.is_default
build['build_targets_json'] = \
json(get_tasks(build_obj.target_set.all()))
# convert completed_on time to user's timezone
completed_on = timezone.localtime(build_obj.completed_on)
completed_on_template = '%H:%M'
if self._was_yesterday_or_earlier(completed_on):
completed_on_template = '%d/%m/%Y ' + completed_on_template
build['completed_on'] = completed_on.strftime(
completed_on_template)
targets = []
target_objs = build_obj.get_sorted_target_list()
for target_obj in target_objs:
if target_obj.task:
targets.append(target_obj.target + ':' + target_obj.task)
else:
targets.append(target_obj.target)
build['targets'] = ' '.join(targets)
# abbreviated form of the full target list
abbreviated_targets = ''
num_targets = len(targets)
if num_targets > 0:
abbreviated_targets = targets[0]
if num_targets > 1:
abbreviated_targets += (' +%s' % (num_targets - 1))
build['targets_abbreviated'] = abbreviated_targets
recent_builds.append(build)
return JsonResponse(recent_builds, safe=False)
class XhrCustomRecipe(View):
""" Create a custom image recipe """

View File

@ -24,6 +24,7 @@ from toastergui import tables
from toastergui import buildtables
from toastergui import typeaheads
from toastergui import api
from toastergui import widgets
urlpatterns = patterns('toastergui.views',
# landing page
@ -224,7 +225,7 @@ urlpatterns = patterns('toastergui.views',
api.XhrProject.as_view(),
name='xhr_project'),
url(r'^mostrecentbuilds$', api.MostRecentBuildsView.as_view(),
url(r'^mostrecentbuilds$', widgets.MostRecentBuildsView.as_view(),
name='most_recent_builds'),
# default redirection

View File

@ -22,23 +22,24 @@
from django.views.generic import View, TemplateView
from django.views.decorators.cache import cache_control
from django.shortcuts import HttpResponse
from django.http import HttpResponseBadRequest
from django.core import serializers
from django.core.cache import cache
from django.core.paginator import Paginator, EmptyPage
from django.db.models import Q
from orm.models import Project, ProjectLayer, Layer_Version
from orm.models import Project, Build
from django.template import Context, Template
from django.template import VariableDoesNotExist
from django.template import TemplateSyntaxError
from django.core.serializers.json import DjangoJSONEncoder
from django.core.exceptions import FieldError
from django.conf.urls import url, patterns
from django.utils import timezone
from toastergui.templatetags.projecttags import sectohms, get_tasks
from toastergui.templatetags.projecttags import json as template_json
from django.http import JsonResponse
from django.core.urlresolvers import reverse
import types
import json
import collections
import operator
import re
try:
@ -55,6 +56,7 @@ from toastergui.tablefilter import TableFilterMap
class NoFieldOrDataName(Exception):
pass
class ToasterTable(TemplateView):
def __init__(self, *args, **kwargs):
super(ToasterTable, self).__init__()
@ -81,7 +83,7 @@ class ToasterTable(TemplateView):
def get_context_data(self, **kwargs):
context = super(ToasterTable, self).get_context_data(**kwargs)
context['title'] = self.title
context['table_name'] = type(self).__name__.lower()
context['table_name'] = type(self).__name__.lower()
context['empty_state'] = self.empty_state
return context
@ -406,7 +408,6 @@ class ToasterTable(TemplateView):
return data
class ToasterTypeAhead(View):
""" A typeahead mechanism to support the front end typeahead widgets """
MAX_RESULTS = 6
@ -427,34 +428,142 @@ class ToasterTypeAhead(View):
error = "ok"
search_term = request.GET.get("search", None)
if search_term == None:
if search_term is None:
# We got no search value so return empty reponse
return response({'error' : error , 'results': []})
return response({'error': error, 'results': []})
try:
prj = Project.objects.get(pk=kwargs['pid'])
except KeyError:
prj = None
results = self.apply_search(search_term, prj, request)[:ToasterTypeAhead.MAX_RESULTS]
results = self.apply_search(search_term,
prj,
request)[:ToasterTypeAhead.MAX_RESULTS]
if len(results) > 0:
try:
self.validate_fields(results[0])
except MissingFieldsException as e:
except self.MissingFieldsException as e:
error = e
data = { 'results' : results,
'error' : error,
}
data = {'results': results,
'error': error}
return response(data)
def validate_fields(self, result):
if 'name' in result == False or 'detail' in result == False:
raise MissingFieldsException("name and detail are required fields")
if 'name' in result is False or 'detail' in result is False:
raise self.MissingFieldsException(
"name and detail are required fields")
def apply_search(self, search_term, prj):
""" Override this function to implement search. Return an array of
dictionaries with a minium of a name and detail field"""
pass
class MostRecentBuildsView(View):
def _was_yesterday_or_earlier(self, completed_on):
now = timezone.now()
delta = now - completed_on
if delta.days >= 1:
return True
return False
def get(self, request, *args, **kwargs):
"""
Returns a list of builds in JSON format.
"""
project = None
project_id = request.GET.get('project_id', None)
if project_id:
try:
project = Project.objects.get(pk=project_id)
except:
# if project lookup fails, assume no project
pass
recent_build_objs = Build.get_recent(project)
recent_builds = []
for build_obj in recent_build_objs:
dashboard_url = reverse('builddashboard', args=(build_obj.pk,))
buildtime_url = reverse('buildtime', args=(build_obj.pk,))
rebuild_url = \
reverse('xhr_buildrequest', args=(build_obj.project.pk,))
cancel_url = \
reverse('xhr_buildrequest', args=(build_obj.project.pk,))
build = {}
build['id'] = build_obj.pk
build['dashboard_url'] = dashboard_url
buildrequest_id = None
if hasattr(build_obj, 'buildrequest'):
buildrequest_id = build_obj.buildrequest.pk
build['buildrequest_id'] = buildrequest_id
build['recipes_parsed_percentage'] = \
int((build_obj.recipes_parsed /
build_obj.recipes_to_parse) * 100)
tasks_complete_percentage = 0
if build_obj.outcome in (Build.SUCCEEDED, Build.FAILED):
tasks_complete_percentage = 100
elif build_obj.outcome == Build.IN_PROGRESS:
tasks_complete_percentage = build_obj.completeper()
build['tasks_complete_percentage'] = tasks_complete_percentage
build['state'] = build_obj.get_state()
build['errors'] = build_obj.errors.count()
build['dashboard_errors_url'] = dashboard_url + '#errors'
build['warnings'] = build_obj.warnings.count()
build['dashboard_warnings_url'] = dashboard_url + '#warnings'
build['buildtime'] = sectohms(build_obj.timespent_seconds)
build['buildtime_url'] = buildtime_url
build['rebuild_url'] = rebuild_url
build['cancel_url'] = cancel_url
build['is_default_project_build'] = build_obj.project.is_default
build['build_targets_json'] = \
template_json(get_tasks(build_obj.target_set.all()))
# convert completed_on time to user's timezone
completed_on = timezone.localtime(build_obj.completed_on)
completed_on_template = '%H:%M'
if self._was_yesterday_or_earlier(completed_on):
completed_on_template = '%d/%m/%Y ' + completed_on_template
build['completed_on'] = completed_on.strftime(
completed_on_template)
targets = []
target_objs = build_obj.get_sorted_target_list()
for target_obj in target_objs:
if target_obj.task:
targets.append(target_obj.target + ':' + target_obj.task)
else:
targets.append(target_obj.target)
build['targets'] = ' '.join(targets)
# abbreviated form of the full target list
abbreviated_targets = ''
num_targets = len(targets)
if num_targets > 0:
abbreviated_targets = targets[0]
if num_targets > 1:
abbreviated_targets += (' +%s' % (num_targets - 1))
build['targets_abbreviated'] = abbreviated_targets
recent_builds.append(build)
return JsonResponse(recent_builds, safe=False)