diff options
author | Milo Casagrande <milo.casagrande@linaro.org> | 2015-01-20 12:14:14 +0100 |
---|---|---|
committer | Milo Casagrande <milo.casagrande@linaro.org> | 2015-01-20 12:14:14 +0100 |
commit | b71aaba97c0d684111edab4cc80302da0bb342d6 (patch) | |
tree | 4dcd8cfb07261e10359ff28fc73c9310e5f291dc | |
parent | dec4cb63e4c9bead118ae5932e27f4c69ca31b01 (diff) |
Add new builds view.
* Add view to show all builds for job+kernel+defconfig.
Change-Id: I47fa30a4d4de2d22578b3aa38cb0fcde0ac8fa7e
-rw-r--r-- | app/dashboard/static/js/linaro-boots-all-job-kernel-defconfig-0.0.1.js | 362 | ||||
-rw-r--r-- | app/dashboard/templates/boots-all-job-kernel-defconfig.html | 59 | ||||
-rw-r--r-- | app/dashboard/utils/route.py | 8 | ||||
-rw-r--r-- | app/dashboard/views/boot.py | 22 |
4 files changed, 451 insertions, 0 deletions
diff --git a/app/dashboard/static/js/linaro-boots-all-job-kernel-defconfig-0.0.1.js b/app/dashboard/static/js/linaro-boots-all-job-kernel-defconfig-0.0.1.js new file mode 100644 index 0000000..3a35de7 --- /dev/null +++ b/app/dashboard/static/js/linaro-boots-all-job-kernel-defconfig-0.0.1.js @@ -0,0 +1,362 @@ +var jobName = $('#job-name').val(); +var kernelName = $('#kernel-name').val(); +var defconfigFull = $('#defconfig-full').val(); +var pageLen = $('#page-len').val(); +var searchFilter = $('#search-filter').val(); +var fileServer = $('#file-server').val(); + +function populateBootsTable(data) { + 'use strict'; + var localData = data.result, + dataLen = localData.length, + table = null; + + if (dataLen > 0) { + table = $('#boots-table').dataTable({ + 'dom': '<"row"<"col-xs-12 col-sm-12 col-md-6 col-lg-6"' + + '<"length-menu"l>>' + + '<"col-xs-12 col-sm-12 col-md-4 col-lg-4 col-lg-offset-2"f>r' + + '<"col-xs-12 col-sm-12 col-md-12 col-lg-12"t>>' + + '<"row"<"col-xs-12 col-sm-12 col-md-6 col-lg-6"i>' + + '<"col-xs-12 col-sm-12 col-md-6 col-lg-6"p>>', + 'language': { + 'lengthMenu': '_MENU_ <strong>boot reports ' + + 'per page</strong>', + 'zeroRecords': '<h4>No boot reports to display.</h4>', + 'search': '<div id="search-area" class="input-group">' + + '<span class="input-group-addon">' + + '<i class="fa fa-search"></i></span>_INPUT_</div>' + }, + 'initComplete': function(settings, data) { + $('#table-loading').remove(); + $('#table-div').fadeIn('slow', 'linear'); + + var api = this.api(); + + if (pageLen !== undefined && pageLen !== null) { + if (pageLen.length > 0) { + pageLen = Number(pageLen); + if (isNaN(pageLen)) { + pageLen = 25; + } + + api.page.len(pageLen).draw(); + } + } + + if (searchFilter !== null && searchFilter !== undefined) { + if (searchFilter.length > 0) { + api.search(searchFilter, true).draw(); + } + } + }, + 'lengthMenu': [25, 50, 75, 100], + 'deferRender': true, + 'ordering': true, + 'processing': true, + 'stateDuration': -1, + 'stateSave': true, + 'order': [5, 'desc'], + 'search': { + 'regex': true, + 'smart': true + }, + 'data': localData, + 'columns': [ + { + 'data': '_id', + 'visible': false, + 'searchable': false, + 'orderable': false + }, + { + 'data': 'board', + 'title': 'Board Model', + 'render': function(data, type, object) { + return '<a class="table-link" href="/boot/' + data + + '/job/' + jobName + '/kernel/' + + kernelName + '/">' + data + '</a>'; + } + }, + { + 'data': 'lab_name', + 'title': 'Lab Name', + 'render': function(data, type, object) { + return '<a class="table-link" href="/boot/all/lab/' + + data + '/">' + data + '</a>'; + } + }, + { + 'data': 'boot_result_description', + 'title': 'Failure Reason', + 'type': 'string', + 'render': function(data, type, object) { + var display = '', + status = object.status; + if (data !== null && status !== 'PASS') { + if (data.length > 45) { + display = '<span rel="tooltip" ' + + 'data-toggle="tooltip"' + + 'title="' + data + '">' + + data.slice(0, 46) + '…</span>'; + } else { + display = data; + } + } + return display; + } + }, + { + 'data': 'boot_log', + 'title': 'Boot Log', + 'type': 'string', + 'render': function(data, type, object) { + var arch = object.arch, + fileServerUrl = object.file_server_url, + fileServerResource = object.file_server_resource, + defconfigFull = object.defconfig_full, + labName = object.lab_name, + logPath = null, + fileServerUri = null, + pathUrl = null, + uriPath = null, + bootLog = data, + bootLogHtml = object.boot_log_html, + display = ''; + + if (fileServerUrl !== null && + fileServerUrl !== undefined) { + fileServer = fileServerUrl; + } + + if (fileServerResource !== null && + fileServerResource !== undefined) { + pathUrl = fileServerResource; + } else { + pathUrl = jobName + '/' + kernelName + '/' + + arch + '-' + defconfigFull + '/'; + } + + fileServerUri = new URI(fileServer); + uriPath = fileServerUri.path() + '/' + pathUrl; + + if (bootLog !== null) { + if (bootLog.search(labName) === -1) { + logPath = uriPath + '/' + labName + '/' + + bootLog; + } else { + logPath = uriPath + '/' + bootLog; + } + display += '<span rel="tooltip" ' + + 'data-toggle="tooltip" ' + + 'title="View raw text boot log"><a href="' + + fileServerUri + .path(logPath) + .normalizePath().href() + + '">txt' + + ' <i class="fa fa-external-link">' + + '</i></a></span>'; + } + + if (bootLogHtml !== null) { + if (bootLog !== null) { + display += ' — '; + } + if (bootLogHtml.search(labName) === -1) { + logPath = uriPath + '/' + labName + '/' + + bootLogHtml; + } else { + logPath = uriPath + '/' + bootLogHtml; + } + display += '<span rel="tooltip" ' + + 'data-toggle="tooltip" ' + + 'title="View HTML boot log"><a href="' + + fileServerUri + .path(logPath) + .normalizePath().href() + + '">html <i class="fa fa-external-link">' + + '</i></a></span>'; + } + return display; + } + }, + { + 'data': 'created_on', + 'title': 'Date', + 'type': 'date', + 'className': 'pull-center', + 'render': function(data) { + var created = new Date(data.$date); + return created.getCustomISODate(); + } + }, + { + 'data': 'status', + 'title': 'Status', + 'type': 'string', + 'className': 'pull-center', + 'render': function(data) { + var displ; + switch (data) { + case 'PASS': + displ = '<span rel="tooltip" ' + + 'data-toggle="tooltip"' + + 'title="Boot completed">' + + '<span class="label label-success">' + + '<i class="fa fa-check"></i></span>' + + '</span>'; + break; + case 'FAIL': + displ = '<span rel="tooltip" ' + + 'data-toggle="tooltip"' + + 'title="Boot failed">' + + '<span class="label label-danger">' + + '<i class="fa fa-exclamation-triangle">' + + '</i></span></span>'; + break; + case 'OFFLINE': + displ = '<span rel="tooltip"' + + 'data-toggle="tooltip"' + + 'title="Board offline"' + + '<span class="label label-info">' + + '<i class="fa fa-power-off">' + + '</i></span></span>'; + break; + default: + displ = '<span rel="tooltip" ' + + 'data-toggle="tooltip"' + + 'title="Unknown status">' + + '<span class="label label-warning">' + + '<i class="fa fa-question">' + + '</i></span></span>'; + break; + } + return displ; + } + }, + { + 'data': 'board', + 'title': '', + 'orderable': false, + 'searchable': false, + 'className': 'pull-center', + 'render': function(data, type, object) { + var lab = object.lab_name; + + return '<span rel="tooltip" data-toggle="tooltip"' + + 'title="Details for board ' + data + + ' with ' + + jobName + '‐' + kernelName + '‐' + + defconfigFull + + ' ‐ (' + lab + ')' + + '"><a href="/boot/' + data + '/job/' + jobName + + '/kernel/' + kernelName + '/defconfig/' + + defconfigFull + + '/lab/' + lab + '/?_id=' + object._id.$oid + '">' + + '<i class="fa fa-search"></i></a></span>'; + } + } + ] + }); + + $(document).on('click', '#labtable tbody tr', function() { + var localTable = table.fnGetData(this), + location = '#'; + if (localTable) { + location = '/boot/' + localTable.board + '/job/' + + localTable.job + '/kernel/' + localTable.kernel + + '/defconfig/' + localTable.defconfig_full + '/lab/' + + localTable.lab_name + '/'; + if (localTable._id !== null) { + location += '?_id=' + localTable._id.$oid; + } + window.location = location; + } + }); + + $('#search-area > .input-sm').attr('placeholder', 'Filter the results'); + $('.input-sm').keyup(function(key) { + // Remove focus from input when Esc is pressed. + if (key.keyCode === 27) { + $(this).blur(); + } + }); + } else { + $('#table-loading').remove(); + JSBase.replaceContentByID( + '#table-div', + '<strong>No boot reports found.</strong>'); + } +} + +function ajaxDeferredFailed() { + 'use strict'; + $('#table-loading').remove(); + JSBase.replaceContentByID( + '#table-div', + '<strong>Error loading data.</strong>'); +} + +$(document).ready(function() { + 'use strict'; + $('#li-boot').addClass('active'); + $('#table-div').hide(); + + var ajaxDeferredCall = null, + ajaxData = null, + errorReason = 'Error loading boot reports data'; + + JSBase.replaceContentByID( + '#dd-tree', + '<span rel="tooltip" data-toggle="tooltip" ' + + 'title="Boot details for ' + jobName + '">' + + '<a href="/boot/all/job/' + jobName + '">' + jobName + + '</a></span>' + + ' — ' + + '<span rel="tooltip" data-toggle="tooltip" ' + + 'title="Details for job ' + jobName + + '"><a href="/job/' + jobName + + '"><i class="fa fa-sitemap"></i></a></span>' + ); + JSBase.replaceContentByID( + '#dd-git-describe', + '<span rel="tooltip" data-toggle="tooltip" ' + + 'title="Boot report details for ' + jobName + + ' ‐ ' + + kernelName + '"><a href="/boot/all/job/' + jobName + + '/kernel/' + kernelName + '">' + kernelName + + '</a></span>' + + ' — ' + + '<span rel="tooltip" data-toggle="tooltip" ' + + 'title="Details for build ' + jobName + + ' ‐ ' + + kernelName + '"><a href="/build/' + jobName + + '/kernel/' + kernelName + + '"><i class="fa fa-cube"></i></a></span>' + ); + JSBase.replaceContentByID( + '#dd-defconfig', + defconfigFull + ' — ' + + '<span rel="tooltip" data-toggle="tooltip" title="' + + 'Details for build ' + jobName + ' ‐ ' + + kernelName + ' ‐ ' + defconfigFull + '">' + + '<a href="/build/' + jobName + '/kernel/' + kernelName + '/defconfig/' + + defconfigFull + '/"><i class="fa fa-cube"></i></a></span>' + ); + + ajaxData = { + 'job': jobName, + 'kernel': kernelName, + 'defconfig_full': defconfigFull + }; + ajaxDeferredCall = JSBase.createDeferredCall( + '/_ajax/boot', + 'GET', + ajaxData, + null, + ajaxDeferredFailed, + errorReason + ); + + $.when(ajaxDeferredCall).done(populateBootsTable); +}); diff --git a/app/dashboard/templates/boots-all-job-kernel-defconfig.html b/app/dashboard/templates/boots-all-job-kernel-defconfig.html new file mode 100644 index 0000000..149cf88 --- /dev/null +++ b/app/dashboard/templates/boots-all-job-kernel-defconfig.html @@ -0,0 +1,59 @@ +{%- extends "base.html" %} +{%- block meta -%} + <meta name="csrf-token" content="{{ csrf_token_r() }}"> +{%- endblock %} +{%- block title %}{{ page_title|safe }}{%- endblock %} +{%- block head %} +{{ super() }} +<link rel="stylesheet" type="text/css" href="//cdn.datatables.net/plug-ins/9dcbecd42ad/integration/bootstrap/3/dataTables.bootstrap.css"> +{%- endblock %} +{%- block content %} +<div class="row"> + <div class="page-header"> + <h3>{{ body_title|safe }}</h3> + </div> + <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12"> + <dl class="dl-horizontal"> + <dt>Tree</dt> + <dd id="dd-tree" class="loading-content"> + <i class="fa fa-cog fa-spin"></i> loading… + </dd> + <dt>Git describe</dt> + <dd id="dd-git-describe" class="loading-content"> + <i class="fa fa-cog fa-spin"></i> loading… + </dd> + <dt>Defconfig</dt> + <dd id="dd-defconfig" class="loading-content"> + <i class="fa fa-cog fa-spin"></i> loading… + </dd> + </dl> + </div> +</div> +<div class="row" id="boot-reports"> + <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12"> + <div id="table-loading" class="pull-center"> + <i class="fa fa-cog fa-2x fa-spin"></i> loading… + </div> + {%- if is_mobile %} + <div class="table-responsive" id="table-div"> + {%- else %} + <div class="table" id="table-div"> + {%- endif %} + <table class="table table-hover table-striped table-condensed clickable-table big-table" id="boots-table"> + </table> + </div> + </div> +</div> +<input type="hidden" id="file-server" value="{{ config['FILE_SERVER_URL'] }}"> +<input type="hidden" id="job-name" value="{{ job }}"> +<input type="hidden" id="kernel-name" value="{{ kernel }}"> +<input type="hidden" id="defconfig-full" value="{{ defconfig }}"> +<input type="hidden" id="search-filter" value="{{ search_filter }}"> +<input type="hidden" id="page-len" value="{{ page_len }}"> +{%- endblock %} +{%- block scripts %} +{{ super() }} +<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/datatables/1.10.3/js/jquery.dataTables.min.js"></script> +<script type="text/javascript" src="//cdn.datatables.net/plug-ins/9dcbecd42ad/integration/bootstrap/3/dataTables.bootstrap.js"></script> +<script type="text/javascript" src="/static/js/linaro-boots-all-job-kernel-defconfig-0.0.1.js"></script> +{%- endblock %}
\ No newline at end of file diff --git a/app/dashboard/utils/route.py b/app/dashboard/utils/route.py index 644e57e..76ee1f1 100644 --- a/app/dashboard/utils/route.py +++ b/app/dashboard/utils/route.py @@ -103,6 +103,14 @@ def init(): ) add_rule( ( + "/boot/all/job/<string:job>/kernel/<string:kernel>/" + "defconfig/<string:defconfig>/" + ), + view_func=vboot.BootAllJobKernelDefconfigView.as_view("boot-all-jkd"), + methods=["GET"] + ) + add_rule( + ( "/boot/<string:board>/job/<string:job>/kernel/<string:kernel>/" "defconfig/<string:defconfig>/" ), diff --git a/app/dashboard/views/boot.py b/app/dashboard/views/boot.py index a902b90..bf7d8bf 100644 --- a/app/dashboard/views/boot.py +++ b/app/dashboard/views/boot.py @@ -44,6 +44,28 @@ class BootAllView(BootGeneralView): ) +class BootAllJobKernelDefconfigView(BootGeneralView): + def dispatch_request(self, **kwargs): + + page_title = self.BOOT_PAGES_TITLE + "" + body_title = ( + "Boot reports for «%(job)s - %(kernel)s» " + "<small>(%(defconfig)s)</small>" % kwargs + ) + search_filter, page_len = get_search_parameters(request) + + return render_template( + "boots-all-job-kernel-defconfig.html", + page_title=page_title, + body_title=body_title, + job=kwargs["job"], + kernel=kwargs["kernel"], + defconfig=kwargs["defconfig"], + search_filter=search_filter, + page_len=page_len + ) + + class BootDefconfigView(BootGeneralView): def dispatch_request(self, **kwargs): |