diff options
author | David Reyna <David.Reyna@windriver.com> | 2014-02-28 05:55:46 -0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2014-03-09 12:24:01 -0700 |
commit | 4717749fd651e6983a31e3cefe3f210d2646ca87 (patch) | |
tree | 5ba0090617b97f5d49b5c78ee84563a0cab6b7f5 /bitbake | |
parent | 31d4bf8484ee42690386c6b7a6bd6c7a2be54464 (diff) | |
download | ast2050-yocto-poky-4717749fd651e6983a31e3cefe3f210d2646ca87.zip ast2050-yocto-poky-4717749fd651e6983a31e3cefe3f210d2646ca87.tar.gz |
bitbake: toaster: implement the configuration pagedreyna/configure-detail-view
Update the configuration page with the file list pop-up, implement the file and description filters.
[YOCTO #4259]
(Bitbake rev: 54a767809960b66b2fe2d3bc46aa9c7e040c4ae3)
Signed-off-by: David Reyna <David.Reyna@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
5 files changed, 299 insertions, 44 deletions
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html index 8d4771c..96f093f 100644 --- a/bitbake/lib/toaster/toastergui/templates/base.html +++ b/bitbake/lib/toaster/toastergui/templates/base.html @@ -48,6 +48,59 @@ function reload_params(params) { } </script> + +<script> + $(document).ready(function() { + //show or hide selected columns on load + $("input:checkbox").each(function(){ + var selectedType = $(this).val(); + if($(this).is(":checked")){ + $("."+selectedType).show(); + } + else{ + $("."+selectedType).hide(); + } + }); + //edit columns functionality (show / hide table columns) + $("input:checkbox").change(); + $("input:checkbox").change(function(){ + var selectedType = $(this).val(); + if($(this).is(":checked")){ + $("."+selectedType).show(); + } + else{ + $("."+selectedType).hide(); + } + }); + //turn edit columns dropdown into a multi-select menu + $('.dropdown-menu input, .dropdown-menu label').click(function(e) { + e.stopPropagation(); + }); + //show help information inside modal dialogs + $("#filter-variables i").tooltip({ html: true, delay: {show: 500} }); + //show applied filter tooltip + $('.filtered').tooltip({container:'body', placement:'bottom', delay:{hide:1500}, html:true}); + //hide the applied filter tooltip when you click the filter button + $('.btn-primary').on('click', function () { + $('.tooltip').hide(); + }); + + $('.full-variable, .full-variable-hide').hide(); + $('.full-variable-show').click(function(){ + $('.full-variable').slideDown(function(){ + $('.full-variable-hide').show(); + }); + $(this).hide(); + }); + $('.full-variable-hide').click(function(){ + $(this).hide(); + $('.full-variable').slideUp(function(){ + $('.full-variable-show').show(); + }); + }); + }); +</script> + </head> <body style="height: 100%"> diff --git a/bitbake/lib/toaster/toastergui/templates/configuration.html b/bitbake/lib/toaster/toastergui/templates/configuration.html index 467fbd0..ddfa5af 100644 --- a/bitbake/lib/toaster/toastergui/templates/configuration.html +++ b/bitbake/lib/toaster/toastergui/templates/configuration.html @@ -3,6 +3,8 @@ <li>Configuration</li> {% endblock %} +{% load projecttags %} + {% block buildinfomain %} <!-- page title --> <div class="row-fluid span10"> @@ -22,15 +24,19 @@ <div id="summary" class="tab-pane active"> <h3>Build configuration</h3> <dl class="dl-horizontal"> - <dt>BitBake version</dt><dd>1.19.1</dd> - <dt>Build system</dt><dd>x86_64-linux</dd> - <dt>Host distribution</dt><dd>Ubuntu-12.04</dd> - <dt>Target system</dt><dd>i586-poky-linux</dd> - <dt><i class="icon-question-sign get-help" data-toggle="tooltip" title="Specifies the target device for which the image is built"></i> Machine</dt><dd>atom-pc</dd> - <dt><i class="icon-question-sign get-help" data-toggle="tooltip" title="The short name of the distribution"></i> Distro</dt><dd>poky</dd> - <dt>Distro version</dt><dd>1.4+snapshot-20130718</dd> - <dt>Tune features</dt><dd>m32 i586</dd> - <dt>Target(s)</dt><dd>core-image-sato</dd> + {%if BB_VERSION %}<dt>BitBake version</dt><dd>{{BB_VERSION}}</dd> {% endif %} + {%if BUILD_SYS %}<dt>Build system</dt><dd>{{BUILD_SYS}}</dd> {% endif %} + {%if NATIVELSBSTRING %}<dt>Host distribution</dt><dd>{{NATIVELSBSTRING}}</dd> {% endif %} + {%if TARGET_SYS %}<dt>Target system</dt><dd>{{TARGET_SYS}}</dd> {% endif %} + {%if MACHINE %}<dt>Machine</dt><dd>{{MACHINE}}</dd> {% endif %} + {%if DISTRO %}<dt>Distro</dt><dd>{{DISTRO}}</dd> {% endif %} + {%if DISTRO_VERSION %}<dt>Distro version</dt><dd>{{DISTRO_VERSION}}</dd> {% endif %} + {%if TUNE_FEATURES %}<dt>Tune features</dt><dd>{{TUNE_FEATURES}}</dd> {% endif %} + {%if TARGET_FPU %}<dt>Target FPU</dt><dd>{{TARGET_FPU}}</dd> {% endif %} + {%if targets.all %}<dt>Target(s)</dt> + <dd> <ul> {% for target in targets.all %} + <li>{{target.target}}{%if forloop.counter > 1 %}<br>{% endif %}</li> + {% endfor %} </ul> </dd> {% endif %} </dl> <h3>Layers</h3> <div class="span9" style="margin-left:0px;"> @@ -45,7 +51,13 @@ </thead> <tbody>{% for lv in build.layer_version_build.all %} <tr> - <td>{{lv.layer.name}}<a href="{{lv.layer.layer_index_url}}" target="_blank"> <i class="icon-share get-info"></i></a></td><td>{{lv.branch}}</td><td class="layer_commit"><a data-content="{{lv.commit}}" title="" href="#" class="btn" data-original-title="">{{lv.commit|slice:":8"}}...</a></td><td>{{lv.layer.local_path}}</td> + <td>{{lv.layer.name}}</td> + <td>{{lv.branch}}</td> + <td> <a class="btn" data-content="<ul class='unstyled'> + <li>{{lv.commit}}</li> </ul>"> + {{lv.commit|truncatechars:13}} + </a></td> + <td>{{lv.layer.local_path}}</td> </tr>{% endfor %} </tbody> </table> diff --git a/bitbake/lib/toaster/toastergui/templates/configvars.html b/bitbake/lib/toaster/toastergui/templates/configvars.html index ae45119..cd41cca 100644 --- a/bitbake/lib/toaster/toastergui/templates/configvars.html +++ b/bitbake/lib/toaster/toastergui/templates/configvars.html @@ -3,38 +3,110 @@ <li>Configuration</li> {% endblock %} +{% load projecttags %} + {% block buildinfomain %} <!-- page title --> <div class="row-fluid span10"> <div class="page-header"> - <h1>Configuration</h1> + <h1> + {% if request.GET.filter or request.GET.search and objects.count > 0 %} + {{objects.paginator.count}} variable{{objects.paginator.count|pluralize}} found + {%elif objects.paginator.count == 0%} + No variables + {%else%} + Configuration + {%endif%} + </h1> </div> </div> <!-- configuration table --> <div class="row-fluid pull-right span10" id="navTab"> -<ul class="nav nav-pills"> + <ul class="nav nav-pills"> <li class=""><a href="{% url 'configuration' build.id %}">Summary</a></li> <li class="active"><a href="#" >BitBake variables</a></li> -</ul> - + </ul> <!-- variables --> <div id="variables" class="tab-pane"> -{% include "basetable_top.html" %} + {% include "basetable_top.html" %} -{% for variable in objects %} - <tr class="data"> - <td class="variable">{{variable.variable_name}}</td> - <td class="variable_value">{{variable.variable_value}}</td> - <td class="file">{% for vh in variable.vhistory_set.all %}{{vh.operation}} in {{vh.file_name}}:{{vh.line_number}}<br/>{%endfor%}</td> - <td class="description">{% if variable.description %}{{variable.description}}{% endif %}</td> + {% for variable in objects %} + <tr class="data"> + <td class="variable_name"><a data-toggle="modal" href="#variable-{{variable.pk}}">{{variable.variable_name}}</a></td> + <td class="variable_value"><a data-toggle="modal" href="#variable-{{variable.pk}}">{{variable.variable_value|truncatechars:153}}</a></td> + <td class="file"><a data-toggle="modal" href="#variable-{{variable.pk}}"> + {% if variable.vhistory.all %} {% autoescape off %} + {{variable.vhistory.all | filter_setin_files:file_filter }} + {% endautoescape %} {% endif %} + </a></td> + <td class="description"> + {% if variable.description %} + {{variable.description}} + <a href="http://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-{{variable.variable_name|variable_parent_name}}" target="_blank"> + <i class="icon-share get-info"></i></a> + {% endif %} + </td> </tr> {% endfor %} {% include "basetable_bottom.html" %} +</div> <!-- endvariables --> - </div> <!-- endvariables --> +<!-- file list popups --> +{% for variable in objects %} + {% if variable.vhistory.count %} + <div id="variable-{{variable.pk}}" class="modal hide fade" tabindex="-1" role="dialog"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button> + <h3>History of {{variable.variable_name}}</h3> + </div> + <div class="modal-body"> + {% if variable.variable_value %} + {% if variable.variable_value|length < 570 %} + <h4>{{variable.variable_name}} value is:</h4> + <p> + {{variable.variable_value}} + </p> + {% else %} + <h4>{{variable.variable_name}} value is:</h4> + <p> + <span>{{variable.variable_value|string_slice:':570'}} + <span class="full-variable"> {{variable.variable_value|string_slice:'570:'}} + </span> + <a class="btn btn-mini full-variable-show">...</a> + </span> + </p> + <a class="btn btn-mini full-variable-hide">Collapse variable value<i class="icon-caret-up"></i> + </a> + {% endif %} + {% else %} + <div class="alert alert-info">The value of <strong>{{variable.variable_name}}</strong> is an empty string</div> + {% endif %} + <h4>The value was set in the following configuration files:</h4> + <table class="table table-bordered table-hover"> + <thead> + <tr> + <th>Order</th> + <th>Configuration file</th> + <th>Operation</th> + <th>Line number</th> + </tr> + </thead> + <tbody> + {% for vh in variable.vhistory.all %} + <tr> + <td>{{forloop.counter}}</td><td>{{vh.file_name}}</td><td>{{vh.operation}}</td><td>{{vh.line_number}}</td> + </tr> + {%endfor%} + </tbody> + </table> + </div> + </div> + {% endif %} +{% endfor %} + +</div> <!-- buildinfomain --> -</div> {% endblock %} diff --git a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py index b1e573b..857680b 100644 --- a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py +++ b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py @@ -129,3 +129,62 @@ def check_filter_status(options, filter): if filter == option[1]: return "" return "checked" + +@register.filter +def variable_parent_name(value): + """ filter extended variable names to the parent name + """ + value=re.sub('_\$.*', '', value) + return re.sub('_[a-z].*', '', value) + +@register.filter +def filter_setin_files(file_list,matchstr): + """ filter/search the 'set in' file lists. Note + that this output is not autoescaped to allow + the <p> marks, but this is safe as the data + is file paths + """ + + # no filters, show last file (if any) + if matchstr == ":": + if file_list: + return file_list[len(file_list)-1].file_name + else: + return '' + + search, filter = matchstr.partition(':')[::2] + htmlstr="" + # match only filters + if search == '': + for i in range(len(file_list)): + if file_list[i].file_name.find(filter) >= 0: + htmlstr += file_list[i].file_name + "<p>" + return htmlstr + + # match only search string, plus always last file + if filter == "": + for i in range(len(file_list)-1): + if file_list[i].file_name.find(search) >= 0: + htmlstr += file_list[i].file_name + "<p>" + htmlstr += file_list[len(file_list)-1].file_name + return htmlstr + + # match filter or search string + for i in range(len(file_list)): + if (file_list[i].file_name.find(filter) >= 0) or (file_list[i].file_name.find(search) >= 0): + htmlstr += file_list[i].file_name + "<p>" + return htmlstr + + +@register.filter +def string_slice(strvar,slicevar): + """ slice a string with |string_slice:'[first]:[last]' + """ + first,last= slicevar.partition(':')[::2] + if first=='': + return strvar[:int(last)] + elif last=='': + return strvar[int(first):] + else: + return strvar[int(first):int(last)] + diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index b77be1a..3a362e6 100644 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py @@ -733,59 +733,118 @@ def recipes(request, build_id): def configuration(request, build_id): template = 'configuration.html' - context = {'build': Build.objects.filter(pk=build_id)[0]} + + variables = Variable.objects.filter(build=build_id) + BB_VERSION=variables.filter(variable_name='BB_VERSION')[0].variable_value + BUILD_SYS=variables.filter(variable_name='BUILD_SYS')[0].variable_value + NATIVELSBSTRING=variables.filter(variable_name='NATIVELSBSTRING')[0].variable_value + TARGET_SYS=variables.filter(variable_name='TARGET_SYS')[0].variable_value + MACHINE=variables.filter(variable_name='MACHINE')[0].variable_value + DISTRO=variables.filter(variable_name='DISTRO')[0].variable_value + DISTRO_VERSION=variables.filter(variable_name='DISTRO_VERSION')[0].variable_value + TUNE_FEATURES=variables.filter(variable_name='TUNE_FEATURES')[0].variable_value + TARGET_FPU=variables.filter(variable_name='TARGET_FPU')[0].variable_value + + targets = Target.objects.filter(build=build_id) + + context = { + 'objectname': 'configuration', + 'object_search_display':'variables', + 'filter_search_display':'variables', + 'build': Build.objects.filter(pk=build_id)[0], + 'BB_VERSION':BB_VERSION, + 'BUILD_SYS':BUILD_SYS, + 'NATIVELSBSTRING':NATIVELSBSTRING, + 'TARGET_SYS':TARGET_SYS, + 'MACHINE':MACHINE, + 'DISTRO':DISTRO, + 'DISTRO_VERSION':DISTRO_VERSION, + 'TUNE_FEATURES':TUNE_FEATURES, + 'TARGET_FPU':TARGET_FPU, + 'targets':targets, + } return render(request, template, context) def configvars(request, build_id): template = 'configvars.html' - mandatory_parameters = { 'count': 100, 'page' : 1}; + mandatory_parameters = { 'count': 100, 'page' : 1, 'orderby':'variable_name:+', 'filter':'description__regex:.+'}; retval = _verify_parameters( request.GET, mandatory_parameters ) if retval: return _redirect_parameters( 'configvars', request.GET, mandatory_parameters, build_id = build_id) (filter_string, search_term, ordering_string) = _search_tuple(request, Variable) - queryset = Variable.objects.filter(build=build_id) + queryset = Variable.objects.filter(build=build_id).exclude(variable_name__istartswith='B_').exclude(variable_name__istartswith='do_') queryset = _get_queryset(Variable, queryset, filter_string, search_term, ordering_string) + # remove duplicate records from multiple search hits in the VariableHistory table + queryset = queryset.distinct() + # remove records where the value is empty AND there are no history files + queryset = queryset.exclude(variable_value='',vhistory__file_name__isnull=True) variables = _build_page_range(Paginator(queryset, request.GET.get('count', 50)), request.GET.get('page', 1)) + file_filter= search_term + ":" + if filter_string.find('conf/local.conf') > 0: + file_filter += 'conf/local.conf' + if filter_string.find('conf/machine/') > 0: + file_filter += 'conf/machine/' + if filter_string.find('conf/distro/') > 0: + file_filter += 'conf/distro/' + if filter_string.find('/bitbake.conf') > 0: + file_filter += '/bitbake.conf' + context = { + 'objectname': 'configvars', + 'object_search_display':'variables', + 'filter_search_display':'variables', + 'file_filter': file_filter, 'build': Build.objects.filter(pk=build_id)[0], 'objects' : variables, # Specifies the display of columns for the table, appearance in "Edit columns" box, toggling default show/hide, and specifying filters for columns 'tablecols' : [ {'name': 'Variable ', - 'qhelp': "Base variable expanded name", - 'clclass' : 'variable', + 'qhelp': "BitBake is a generic task executor that considers a list of tasks with dependencies and handles metadata that consists of variables in a certain format that get passed to the tasks", 'dclass' : "span3", 'orderfield': _get_toggle_order(request, "variable_name"), + 'ordericon':_get_toggle_order_icon(request, "variable_name"), }, {'name': 'Value ', 'qhelp': "The value assigned to the variable", - 'clclass': 'variable_value', 'dclass': "span4", 'orderfield': _get_toggle_order(request, "variable_value"), + 'ordericon':_get_toggle_order_icon(request, "variable_value"), }, - {'name': 'Configuration file(s) ', - 'qhelp': "The configuration file(s) that touched the variable value", - 'clclass': 'file', + {'name': 'Set in file', + 'qhelp': "The last configuration file that touched the variable value", + 'clclass': 'file', 'hidden' : 0, 'dclass': "span6", - 'orderfield': _get_toggle_order(request, "variable_vhistory__file_name"), - 'filter' : { 'class': 'file', 'label' : 'Show only', 'options' : { - } - } + 'orderfield': _get_toggle_order(request, "vhistory__file_name"), + 'ordericon':_get_toggle_order_icon(request, "vhistory__file_name"), + 'filter' : { + 'class' : 'vhistory__file_name', + 'label': 'Show:', + 'options' : [ + ('Local configuration variables', 'vhistory__file_name__contains:conf/local.conf'), + ('Machine configuration variables', 'vhistory__file_name__contains:conf/machine/'), + ('Distro configuration variables', 'vhistory__file_name__contains:conf/distro/'), + ('Layer configuration variables', 'vhistory__file_name__contains:conf/layer.conf'), + ('bitbake.conf variables', 'vhistory__file_name__contains:/bitbake.conf'), + ] + }, }, {'name': 'Description ', - 'qhelp': "A brief explanation of a variable", - 'clclass': 'description', + 'qhelp': "A brief explanation of the variable", + 'clclass': 'description', 'hidden' : 0, 'dclass': "span5", - 'orderfield': _get_toggle_order(request, "description"), - 'filter' : { 'class' : 'description', 'label' : 'No', 'options' : { - } - }, - } - ] + 'filter' : { + 'class' : 'description', + 'label': 'Show:', + 'options' : [ + ('Variables with description', 'description__regex:.+'), + ] + }, + }, + ], } return render(request, template, context) |