diff options
Diffstat (limited to 'bitbake/lib/toaster/toastergui/widgets.py')
-rw-r--r-- | bitbake/lib/toaster/toastergui/widgets.py | 141 |
1 files changed, 125 insertions, 16 deletions
diff --git a/bitbake/lib/toaster/toastergui/widgets.py b/bitbake/lib/toaster/toastergui/widgets.py index 005a5620db..026903d35d 100644 --- a/bitbake/lib/toaster/toastergui/widgets.py +++ b/bitbake/lib/toaster/toastergui/widgets.py | |||
@@ -22,23 +22,24 @@ | |||
22 | from django.views.generic import View, TemplateView | 22 | from django.views.generic import View, TemplateView |
23 | from django.views.decorators.cache import cache_control | 23 | from django.views.decorators.cache import cache_control |
24 | from django.shortcuts import HttpResponse | 24 | from django.shortcuts import HttpResponse |
25 | from django.http import HttpResponseBadRequest | ||
26 | from django.core import serializers | ||
27 | from django.core.cache import cache | 25 | from django.core.cache import cache |
28 | from django.core.paginator import Paginator, EmptyPage | 26 | from django.core.paginator import Paginator, EmptyPage |
29 | from django.db.models import Q | 27 | from django.db.models import Q |
30 | from orm.models import Project, ProjectLayer, Layer_Version | 28 | from orm.models import Project, Build |
31 | from django.template import Context, Template | 29 | from django.template import Context, Template |
32 | from django.template import VariableDoesNotExist | 30 | from django.template import VariableDoesNotExist |
33 | from django.template import TemplateSyntaxError | 31 | from django.template import TemplateSyntaxError |
34 | from django.core.serializers.json import DjangoJSONEncoder | 32 | from django.core.serializers.json import DjangoJSONEncoder |
35 | from django.core.exceptions import FieldError | 33 | from django.core.exceptions import FieldError |
36 | from django.conf.urls import url, patterns | 34 | from django.utils import timezone |
35 | from toastergui.templatetags.projecttags import sectohms, get_tasks | ||
36 | from toastergui.templatetags.projecttags import json as template_json | ||
37 | from django.http import JsonResponse | ||
38 | from django.core.urlresolvers import reverse | ||
37 | 39 | ||
38 | import types | 40 | import types |
39 | import json | 41 | import json |
40 | import collections | 42 | import collections |
41 | import operator | ||
42 | import re | 43 | import re |
43 | 44 | ||
44 | try: | 45 | try: |
@@ -55,6 +56,7 @@ from toastergui.tablefilter import TableFilterMap | |||
55 | class NoFieldOrDataName(Exception): | 56 | class NoFieldOrDataName(Exception): |
56 | pass | 57 | pass |
57 | 58 | ||
59 | |||
58 | class ToasterTable(TemplateView): | 60 | class ToasterTable(TemplateView): |
59 | def __init__(self, *args, **kwargs): | 61 | def __init__(self, *args, **kwargs): |
60 | super(ToasterTable, self).__init__() | 62 | super(ToasterTable, self).__init__() |
@@ -81,7 +83,7 @@ class ToasterTable(TemplateView): | |||
81 | def get_context_data(self, **kwargs): | 83 | def get_context_data(self, **kwargs): |
82 | context = super(ToasterTable, self).get_context_data(**kwargs) | 84 | context = super(ToasterTable, self).get_context_data(**kwargs) |
83 | context['title'] = self.title | 85 | context['title'] = self.title |
84 | context['table_name'] = type(self).__name__.lower() | 86 | context['table_name'] = type(self).__name__.lower() |
85 | context['empty_state'] = self.empty_state | 87 | context['empty_state'] = self.empty_state |
86 | 88 | ||
87 | return context | 89 | return context |
@@ -406,7 +408,6 @@ class ToasterTable(TemplateView): | |||
406 | return data | 408 | return data |
407 | 409 | ||
408 | 410 | ||
409 | |||
410 | class ToasterTypeAhead(View): | 411 | class ToasterTypeAhead(View): |
411 | """ A typeahead mechanism to support the front end typeahead widgets """ | 412 | """ A typeahead mechanism to support the front end typeahead widgets """ |
412 | MAX_RESULTS = 6 | 413 | MAX_RESULTS = 6 |
@@ -427,34 +428,142 @@ class ToasterTypeAhead(View): | |||
427 | error = "ok" | 428 | error = "ok" |
428 | 429 | ||
429 | search_term = request.GET.get("search", None) | 430 | search_term = request.GET.get("search", None) |
430 | if search_term == None: | 431 | if search_term is None: |
431 | # We got no search value so return empty reponse | 432 | # We got no search value so return empty reponse |
432 | return response({'error' : error , 'results': []}) | 433 | return response({'error': error, 'results': []}) |
433 | 434 | ||
434 | try: | 435 | try: |
435 | prj = Project.objects.get(pk=kwargs['pid']) | 436 | prj = Project.objects.get(pk=kwargs['pid']) |
436 | except KeyError: | 437 | except KeyError: |
437 | prj = None | 438 | prj = None |
438 | 439 | ||
439 | results = self.apply_search(search_term, prj, request)[:ToasterTypeAhead.MAX_RESULTS] | 440 | results = self.apply_search(search_term, |
441 | prj, | ||
442 | request)[:ToasterTypeAhead.MAX_RESULTS] | ||
440 | 443 | ||
441 | if len(results) > 0: | 444 | if len(results) > 0: |
442 | try: | 445 | try: |
443 | self.validate_fields(results[0]) | 446 | self.validate_fields(results[0]) |
444 | except MissingFieldsException as e: | 447 | except self.MissingFieldsException as e: |
445 | error = e | 448 | error = e |
446 | 449 | ||
447 | data = { 'results' : results, | 450 | data = {'results': results, |
448 | 'error' : error, | 451 | 'error': error} |
449 | } | ||
450 | 452 | ||
451 | return response(data) | 453 | return response(data) |
452 | 454 | ||
453 | def validate_fields(self, result): | 455 | def validate_fields(self, result): |
454 | if 'name' in result == False or 'detail' in result == False: | 456 | if 'name' in result is False or 'detail' in result is False: |
455 | raise MissingFieldsException("name and detail are required fields") | 457 | raise self.MissingFieldsException( |
458 | "name and detail are required fields") | ||
456 | 459 | ||
457 | def apply_search(self, search_term, prj): | 460 | def apply_search(self, search_term, prj): |
458 | """ Override this function to implement search. Return an array of | 461 | """ Override this function to implement search. Return an array of |
459 | dictionaries with a minium of a name and detail field""" | 462 | dictionaries with a minium of a name and detail field""" |
460 | pass | 463 | pass |
464 | |||
465 | |||
466 | class MostRecentBuildsView(View): | ||
467 | def _was_yesterday_or_earlier(self, completed_on): | ||
468 | now = timezone.now() | ||
469 | delta = now - completed_on | ||
470 | |||
471 | if delta.days >= 1: | ||
472 | return True | ||
473 | |||
474 | return False | ||
475 | |||
476 | def get(self, request, *args, **kwargs): | ||
477 | """ | ||
478 | Returns a list of builds in JSON format. | ||
479 | """ | ||
480 | project = None | ||
481 | |||
482 | project_id = request.GET.get('project_id', None) | ||
483 | if project_id: | ||
484 | try: | ||
485 | project = Project.objects.get(pk=project_id) | ||
486 | except: | ||
487 | # if project lookup fails, assume no project | ||
488 | pass | ||
489 | |||
490 | recent_build_objs = Build.get_recent(project) | ||
491 | recent_builds = [] | ||
492 | |||
493 | for build_obj in recent_build_objs: | ||
494 | dashboard_url = reverse('builddashboard', args=(build_obj.pk,)) | ||
495 | buildtime_url = reverse('buildtime', args=(build_obj.pk,)) | ||
496 | rebuild_url = \ | ||
497 | reverse('xhr_buildrequest', args=(build_obj.project.pk,)) | ||
498 | cancel_url = \ | ||
499 | reverse('xhr_buildrequest', args=(build_obj.project.pk,)) | ||
500 | |||
501 | build = {} | ||
502 | build['id'] = build_obj.pk | ||
503 | build['dashboard_url'] = dashboard_url | ||
504 | |||
505 | buildrequest_id = None | ||
506 | if hasattr(build_obj, 'buildrequest'): | ||
507 | buildrequest_id = build_obj.buildrequest.pk | ||
508 | build['buildrequest_id'] = buildrequest_id | ||
509 | |||
510 | build['recipes_parsed_percentage'] = \ | ||
511 | int((build_obj.recipes_parsed / | ||
512 | build_obj.recipes_to_parse) * 100) | ||
513 | |||
514 | tasks_complete_percentage = 0 | ||
515 | if build_obj.outcome in (Build.SUCCEEDED, Build.FAILED): | ||
516 | tasks_complete_percentage = 100 | ||
517 | elif build_obj.outcome == Build.IN_PROGRESS: | ||
518 | tasks_complete_percentage = build_obj.completeper() | ||
519 | build['tasks_complete_percentage'] = tasks_complete_percentage | ||
520 | |||
521 | build['state'] = build_obj.get_state() | ||
522 | |||
523 | build['errors'] = build_obj.errors.count() | ||
524 | build['dashboard_errors_url'] = dashboard_url + '#errors' | ||
525 | |||
526 | build['warnings'] = build_obj.warnings.count() | ||
527 | build['dashboard_warnings_url'] = dashboard_url + '#warnings' | ||
528 | |||
529 | build['buildtime'] = sectohms(build_obj.timespent_seconds) | ||
530 | build['buildtime_url'] = buildtime_url | ||
531 | |||
532 | build['rebuild_url'] = rebuild_url | ||
533 | build['cancel_url'] = cancel_url | ||
534 | |||
535 | build['is_default_project_build'] = build_obj.project.is_default | ||
536 | |||
537 | build['build_targets_json'] = \ | ||
538 | template_json(get_tasks(build_obj.target_set.all())) | ||
539 | |||
540 | # convert completed_on time to user's timezone | ||
541 | completed_on = timezone.localtime(build_obj.completed_on) | ||
542 | |||
543 | completed_on_template = '%H:%M' | ||
544 | if self._was_yesterday_or_earlier(completed_on): | ||
545 | completed_on_template = '%d/%m/%Y ' + completed_on_template | ||
546 | build['completed_on'] = completed_on.strftime( | ||
547 | completed_on_template) | ||
548 | |||
549 | targets = [] | ||
550 | target_objs = build_obj.get_sorted_target_list() | ||
551 | for target_obj in target_objs: | ||
552 | if target_obj.task: | ||
553 | targets.append(target_obj.target + ':' + target_obj.task) | ||
554 | else: | ||
555 | targets.append(target_obj.target) | ||
556 | build['targets'] = ' '.join(targets) | ||
557 | |||
558 | # abbreviated form of the full target list | ||
559 | abbreviated_targets = '' | ||
560 | num_targets = len(targets) | ||
561 | if num_targets > 0: | ||
562 | abbreviated_targets = targets[0] | ||
563 | if num_targets > 1: | ||
564 | abbreviated_targets += (' +%s' % (num_targets - 1)) | ||
565 | build['targets_abbreviated'] = abbreviated_targets | ||
566 | |||
567 | recent_builds.append(build) | ||
568 | |||
569 | return JsonResponse(recent_builds, safe=False) | ||