From bf7fbf5c0ee39564d813f82e194242f9d4f73c47 Mon Sep 17 00:00:00 2001 From: Alexandru DAMIAN Date: Fri, 13 Dec 2013 17:14:34 +0000 Subject: [PATCH] toaster: Build dashboard implementation This patch adds the build dashboard page implementation, which is the landing page for the Toaster GUI. Also adds correct links from the main build page to the various parts of the dashboard. [YOCTO #4258] Signed-off-by: Alexandru DAMIAN --- .../toastergui/templates/basebuildpage.html | 7 +- .../templates/basetable_bottom.html | 4 +- lib/toaster/toastergui/templates/build.html | 17 +++-- .../toastergui/templates/builddashboard.html | 66 +++++++++++++++++++ .../toastergui/templatetags/projecttags.py | 18 +++++ lib/toaster/toastergui/views.py | 36 +++++++--- 6 files changed, 125 insertions(+), 23 deletions(-) diff --git a/lib/toaster/toastergui/templates/basebuildpage.html b/lib/toaster/toastergui/templates/basebuildpage.html index 1b037f9539f..7d2a1f388ef 100644 --- a/lib/toaster/toastergui/templates/basebuildpage.html +++ b/lib/toaster/toastergui/templates/basebuildpage.html @@ -3,7 +3,7 @@ {% block pagecontent %} -
+
- + -
{% block buildinfomain %}{% endblock %} -
+
diff --git a/lib/toaster/toastergui/templates/basetable_bottom.html b/lib/toaster/toastergui/templates/basetable_bottom.html index 2a6f0849299..00703fe4c1c 100644 --- a/lib/toaster/toastergui/templates/basetable_bottom.html +++ b/lib/toaster/toastergui/templates/basetable_bottom.html @@ -53,8 +53,8 @@ $('.progress, .lead span').tooltip({container:'table', placement:'top'}); $(".pagesize").change(function () { - $(".pagesize option:selected").each(function () - {reload_params({"count":$(this).text()}); }); + console.log("page size change"); + reload_params({"count":$(this).val()}); ; }); }); diff --git a/lib/toaster/toastergui/templates/build.html b/lib/toaster/toastergui/templates/build.html index 27ce1ccbc54..43b491d5581 100644 --- a/lib/toaster/toastergui/templates/build.html +++ b/lib/toaster/toastergui/templates/build.html @@ -12,7 +12,6 @@ Recent Builds
-{{build_mru}} {% for build in mru %}
@@ -74,17 +73,17 @@ {% for build in objects %} - {%if build.outcome == build.SUCCEEDED%}{%elif build.outcome == build.FAILED%}{%else%}{%endif%} + {%if build.outcome == build.SUCCEEDED%}{%elif build.outcome == build.FAILED%}{%else%}{%endif%} {% for t in build.target_set.all %}{%if t.is_image %}{% endif %}{{t.target}}{% if t.is_image %}{% endif %}
{% endfor %} - {{build.machine}} - {{build.started_on}} - {{build.completed_on}} + {{build.machine}} + {{build.started_on}} + {{build.completed_on}} - {% if build.errors_no %}{{build.errors_no}} error{{build.errors_no|pluralize}}{%endif%} - {% if build.warnings_no %}{{build.warnings_no}} warning{{build.warnings_no|pluralize}}{%endif%} - {{build|timespent}} + {% if build.errors_no %}{{build.errors_no}} error{{build.errors_no|pluralize}}{%endif%} + {% if build.warnings_no %}{{build.warnings_no}} warning{{build.warnings_no|pluralize}}{%endif%} + {{build|timespent}} {{build.log}} - {% if build.outcome == 0 %}{% for t in build.target_set.all %}{% if t.is_image %}{{build.image_fstypes}}{% endif %}{% endfor %}{% endif %} + {% if build.outcome == 0 %}{% for t in build.target_set.all %}{% if t.is_image %}{{build.image_fstypes}}{% endif %}{% endfor %}{% endif %} {% endfor %} diff --git a/lib/toaster/toastergui/templates/builddashboard.html b/lib/toaster/toastergui/templates/builddashboard.html index 7c58cc0b25d..3b184372bfa 100644 --- a/lib/toaster/toastergui/templates/builddashboard.html +++ b/lib/toaster/toastergui/templates/builddashboard.html @@ -1,8 +1,74 @@ {% extends "basebuildpage.html" %} +{% load humanize %} +{% load projecttags %} {% block localbreadcrumb %}
  • Dashboard
  • {% endblock %} {% block buildinfomain %} + +
    + +
    + + +
    +
    +
    + {%if build.outcome == build.SUCCEEDED%}Completed{%elif build.outcome == build.FAILED%}Failed{%else%}{%endif%} {{build.completed_on|naturaltime}} with {%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %}{% if build.errors_no %} + {{build.errors_no}} error{{build.errors_no|pluralize}} +{% endif %} +{% if build.warnings_no %} + {{build.warnings_no}} warning{{build.warnings_no|pluralize}} +{% endif %} + Build time: {{ build|timespent }} +{%endif%} +
    +
    +
    + +{%if build.outcome == build.SUCCEEDED%} + +
    +

    Images

    + +
    +
    +
    + +{%else%} + +{%endif%} + + +
    +

    Build summary

    +
    +

    Configuration

    +
    +
    Machine
    {{build.machine}}
    +
    Distro
    +
    Layers
    {% for i in build.layer_version_build.all %}
    {{i.layer.name}}
    {%endfor%} +
    +
    +
    +

    Tasks

    +
    +
    Total number of tasks
    {{build.task_build.all.count}}
    +
    Tasks executed
    {% query build.task_build task_executed=1 order__gt=0 as exectask%}{{exectask.count}}
    +
    Tasks prebuilt
    {% query build.task_build task_executed=0 order__gt=0 as noexectask%}{{noexectask.count}}
    +
    Reuse
    {% query build.task_build order__gt=0 as texec %}{{noexectask.count|multiply:100|divide:texec.count}}%
    +
    +
    +
    +

    Recipes & Packages

    +
    +
    Recipes used
    {{recipecount}}
    +
    Packages built
    {{build.package_set.all.count}}
    +
    +
    +
    {% endblock %} diff --git a/lib/toaster/toastergui/templatetags/projecttags.py b/lib/toaster/toastergui/templatetags/projecttags.py index 5f603799322..14550267545 100644 --- a/lib/toaster/toastergui/templatetags/projecttags.py +++ b/lib/toaster/toastergui/templatetags/projecttags.py @@ -29,3 +29,21 @@ def time_difference(start_time, end_time): def timespent(build_object): tdsec = (build_object.completed_on - build_object.started_on).total_seconds() return "%02d:%02d:%02d" % (int(tdsec/3600), int((tdsec - tdsec/ 3600)/ 60), int(tdsec) % 60) + +@register.assignment_tag +def query(qs, **kwargs): + """ template tag which allows queryset filtering. Usage: + {% query books author=author as mybooks %} + {% for book in mybooks %} + ... + {% endfor %} + """ + return qs.filter(**kwargs) + +@register.filter +def divide(value, arg): + return int(value) / int(arg) + +@register.filter +def multiply(value, arg): + return int(value) * int(arg) diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py index 663e03dfd26..7d4d710f833 100644 --- a/lib/toaster/toastergui/views.py +++ b/lib/toaster/toastergui/views.py @@ -59,10 +59,10 @@ def _verify_parameters(g, mandatory_parameters): return miss return None -def _redirect_parameters(view, g, mandatory_parameters): +def _redirect_parameters(view, g, mandatory_parameters, *args, **kwargs): import urllib from django.core.urlresolvers import reverse - url = reverse(view) + url = reverse(view, kwargs=kwargs) params = {} for i in g: params[i] = g[i] @@ -70,7 +70,7 @@ def _redirect_parameters(view, g, mandatory_parameters): if not i in params: params[i] = mandatory_parameters[i] - return redirect(url + "?%s" % urllib.urlencode(params)) + return redirect(url + "?%s" % urllib.urlencode(params), *args, **kwargs) # shows the "all builds" page @@ -82,7 +82,7 @@ def builds(request): mandatory_parameters = { 'count': 10, 'page' : 1}; retval = _verify_parameters( request.GET, mandatory_parameters ) if retval: - return _redirect_parameters( builds, request.GET, mandatory_parameters) + return _redirect_parameters( 'all-builds', request.GET, mandatory_parameters) # retrieve the objects that will be displayed in the table build_info = _build_page_range(Paginator(Build.objects.exclude(outcome = Build.IN_PROGRESS).order_by("-id"), request.GET.get('count', 10)),request.GET.get('page', 1)) @@ -125,6 +125,7 @@ def builddashboard(request, build_id): return redirect(builds) context = { 'build' : Build.objects.filter(pk=build_id)[0], + 'recipecount' : Recipe.objects.filter(layer_version__id__in=Layer_Version.objects.filter(build=build_id)).count() } return render(request, template, context) @@ -186,8 +187,12 @@ def _find_task_provider(task): def tasks(request, build_id): template = 'task.html' + mandatory_parameters = { 'count': 100, 'page' : 1}; + retval = _verify_parameters( request.GET, mandatory_parameters ) + if retval: + return _redirect_parameters( 'tasks', request.GET, mandatory_parameters, build_id = build_id) - tasks = _build_page_range(Paginator(Task.objects.filter(build=build_id), 100),request.GET.get('page', 1)) + tasks = _build_page_range(Paginator(Task.objects.filter(build=build_id, order__gt=0), request.GET.get('count', 100)),request.GET.get('page', 1)) for t in tasks: if t.outcome == Task.OUTCOME_COVERED: @@ -199,16 +204,25 @@ def tasks(request, build_id): def recipes(request, build_id): template = 'recipe.html' + mandatory_parameters = { 'count': 100, 'page' : 1}; + retval = _verify_parameters( request.GET, mandatory_parameters ) + if retval: + return _redirect_parameters( 'recipes', request.GET, mandatory_parameters, build_id = build_id) - recipes = _build_page_range(Paginator(Recipe.objects.filter(build_recipe=build_id), 100),request.GET.get('page', 1)) + recipes = _build_page_range(Paginator(Recipe.objects.filter(layer_version__id__in=Layer_Version.objects.filter(build=build_id)), request.GET.get('count', 100)),request.GET.get('page', 1)) - context = {'build': Build.objects.filter(pk=build_id)[0], 'objects': recipes} + context = {'build': Build.objects.filter(pk=build_id)[0], 'objects': recipes, } return render(request, template, context) def configuration(request, build_id): template = 'configuration.html' + mandatory_parameters = { 'count': 100, 'page' : 1}; + retval = _verify_parameters( request.GET, mandatory_parameters ) + if retval: + return _redirect_parameters( 'configuration', request.GET, mandatory_parameters, build_id = build_id) + variables = _build_page_range(Paginator(Variable.objects.filter(build=build_id), 50), request.GET.get('page', 1)) context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : variables} return render(request, template, context) @@ -245,7 +259,13 @@ def diskio(request, build_id): def bpackage(request, build_id): template = 'bpackage.html' - packages = Package.objects.filter(build = build_id) + mandatory_parameters = { 'count': 100, 'page' : 1}; + retval = _verify_parameters( request.GET, mandatory_parameters ) + if retval: + return _redirect_parameters( 'packages', request.GET, mandatory_parameters, build_id = build_id) + + packages = _build_page_range(Paginator(Package.objects.filter(build = build_id), request.GET.get('count', 100)),request.GET.get('page', 1)) + context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : packages} return render(request, template, context) -- 2.47.3