[LNT] r264723 - [ui] Add a mechanism for selecting different compare_to and baseline runs
Chris Matthews via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 27 14:22:29 PDT 2016
Hi James,
This does not work for me. I get the search dialog, and can pick a run, but then nothing happens. Is the intent that it would refresh the page at that point?
> On Mar 29, 2016, at 5:11 AM, James Molloy via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>
> Author: jamesm
> Date: Tue Mar 29 07:11:28 2016
> New Revision: 264723
>
> URL: http://llvm.org/viewvc/llvm-project?rev=264723&view=rev
> Log:
> [ui] Add a mechanism for selecting different compare_to and baseline runs
>
> In the v4_runs page, we compute a run to compare to and a baseline run. It's possible for the user to pick a different run to compare to by choosing from the past 5 previous runs, but if the user wants to compare to a specific run, he has to go find that run, look up its run ID, and manually edit the URL, adding "?compare_to=ID".
>
> A similar procedure is required for changing the baseline.
>
> This patch adds an easier mechanism. Hovering over the table rows for "previous" or "baseline" reveals an edit icon - clicking on that launches a popover that contains a search box.
>
> The search mechanism (runTypeahead) was taken from the profiling infrastructure and has been found a new home in lnt_run.js.
>
> Added:
> lnt/trunk/lnt/server/ui/static/lnt_run.css
> lnt/trunk/lnt/server/ui/static/lnt_run.js
> Modified:
> lnt/trunk/lnt/server/ui/profile_views.py
> lnt/trunk/lnt/server/ui/static/lnt_profile.js
> lnt/trunk/lnt/server/ui/templates/reporting/runs.html
> lnt/trunk/lnt/server/ui/templates/v4_profile.html
> lnt/trunk/lnt/server/ui/templates/v4_run.html
> lnt/trunk/lnt/server/ui/views.py
>
> Modified: lnt/trunk/lnt/server/ui/profile_views.py
> URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/profile_views.py?rev=264723&r1=264722&r2=264723&view=diff
> ==============================================================================
> --- lnt/trunk/lnt/server/ui/profile_views.py (original)
> +++ lnt/trunk/lnt/server/ui/profile_views.py Tue Mar 29 07:11:28 2016
> @@ -173,7 +173,7 @@ def v4_profile(testid, run1_id, run2_id=
> else:
> json_run2 = {}
> urls = {
> - 'search': v4_url_for('v4_profile_search'),
> + 'search': v4_url_for('v4_search'),
> 'singlerun_template': v4_url_for('v4_profile_fwd',
> testid=1111,
> run1_id=2222) \
> @@ -194,64 +194,3 @@ def v4_profile(testid, run1_id, run2_id=
> ts=ts, test=test,
> run1=json_run1, run2=json_run2,
> urls=urls)
> -
> - at v4_route("/profile/search")
> -def v4_profile_search():
> - def _isint(i):
> - try:
> - int(i)
> - return True
> - except:
> - return False
> -
> - ts = request.get_testsuite()
> - query = request.args.get('q')
> - l = request.args.get('l', 8)
> - #default_machine = request.args.get('m')
> -
> - machine_queries = []
> - order_query = None
> - for q in query.split(' '):
> - if not q:
> - continue
> - if q.startswith('#'):
> - order_query = q[1:]
> - elif _isint(q):
> - order_query = q
> - else:
> - machine_queries.append(q)
> -
> - if not machine_queries and order_query is None:
> - return "{}"
> -
> - if machine_queries:
> - machines = []
> - for m in ts.query(ts.Machine).all():
> - if all(q in m.name for q in machine_queries):
> - machines.append(m.id)
> - if not machines:
> - return "{}"
> - else:
> - # FIXME:
> - return "{}"
> -
> - q = ts.query(ts.Run).filter(ts.Run.machine_id.in_(machines))
> - if order_query:
> - # FIXME: Is this generating a million billion queries under my feet?
> - # I hate ORMs :( I know this column exists, but because it's
> - # dynamically generated SQLAlchemy can't filter on it.
> - # Perhaps there's a way to provide it a manual column name?
> - # I want to do this:
> - # filter(ts.Run.order.llvm_project_revision.like('%' + order_query + '%'))
> - oq = str(order_query)
> - data = [i
> - for i in q.all()
> - if oq in str(i.order.llvm_project_revision)]
> -
> - else:
> - data = q.limit(l).all()
> -
> - return json.dumps(
> - [('%s #%s' % (r.machine.name, r.order.llvm_project_revision),
> - r.id)
> - for r in data])
>
> Modified: lnt/trunk/lnt/server/ui/static/lnt_profile.js
> URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/static/lnt_profile.js?rev=264723&r1=264722&r2=264723&view=diff
> ==============================================================================
> --- lnt/trunk/lnt/server/ui/static/lnt_profile.js (original)
> +++ lnt/trunk/lnt/server/ui/static/lnt_profile.js Tue Mar 29 07:11:28 2016
> @@ -348,101 +348,6 @@ ToolBar.prototype = {
> }
> };
>
> -function RunTypeahead(element, options) {
> - this.element = element;
> - this.options = options;
> - this.id = null;
> -
> - this_ = this;
> - element.typeahead({
> - source: function(query, process) {
> - $.ajax(options.searchURL, {
> - dataType: "json",
> - data: {'q': query},
> - success: function(data) {
> - process(data);
> - },
> - error: function(xhr, textStatus, errorThrown) {
> - pf_flash_error('accessing URL ' + options.searchURL +
> - '; ' + errorThrown);
> - }
> - });
> - },
> - // These identity functions are required because the defaults
> - // assume items are strings, whereas they're objects here.
> - sorter: function(items) {
> - // The results should be sorted on the server.
> - return items;
> - },
> - matcher: function(item) {
> - return item;
> - },
> - updater: function(item) {
> - // FIXME: the item isn't passed in as json any more, it's
> - // been rendered. Lame. To get around this, hack the
> - // components of the 2-tuple back apart.
> - name = item.split(',')[0];
> - id = item.split(',')[1];
> - this_.id = id;
> -
> - if (options.updated)
> - options.updated(name, id);
> - return name;
> - },
> - highlighter: function(item) {
> - // item is a 2-tuple [name, obj].
> - item = item[0];
> -
> - // This loop highlights each search term (split by space)
> - // individually. The content of the for loop is lifted from
> - // bootstrap.js (it's the original implementation of
> - // highlighter()). In particular I have no clue what that regex
> - // is doing, so don't bother asking.
> - var arr = this.query.split(' ');
> - for (i in arr) {
> - query = arr[i];
> - if (!query)
> - continue;
> - var q = query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,
> - '\\$&')
> - item = item.replace(new RegExp('(' + q + ')', 'ig'), function ($1, match) {
> - // We want to replace with <strong>match</strong here,
> - // but it's possible another search term will then
> - // match part of <strong>.
> - //
> - // Therefore, replace with two replaceable tokens that
> - // no search query is very likely to match...
> - return '%%%' + match + '£££'
> - });
> - }
> - return item
> - .replace(/%%%/g, '<strong>')
> - .replace(/£££/g, '</strong>');
> - }
> - });
> - // Bind an event disabling the function box and removing the profile
> - // if the run box is emptied.
> - element.change(function() {
> - if (!element.val()) {
> - this_.id = null;
> - if (options.cleared)
> - options.cleared();
> - }
> - });
> -}
> -
> -RunTypeahead.prototype = {
> - update: function (name, id) {
> - this.element.val(name);
> - this.id = id;
> - if (this.options.updated)
> - this.options.updated(name, id);
> - },
> - getSelectedRunId: function() {
> - return this.id;
> - }
> -};
> -
> function FunctionTypeahead(element, options) {
> this.element = element;
> this.options = options;
> @@ -623,12 +528,6 @@ $(document).ready(function () {
>
> return this.data('toolBar');
> },
> - runTypeahead: function(options) {
> - if (options)
> - this.data('runTypeahead',
> - new RunTypeahead(this, options));
> - return this.data('runTypeahead');
> - },
> functionTypeahead: function(options) {
> if (options)
> this.data('functionTypeahead',
>
> Added: lnt/trunk/lnt/server/ui/static/lnt_run.css
> URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/static/lnt_run.css?rev=264723&view=auto
> ==============================================================================
> --- lnt/trunk/lnt/server/ui/static/lnt_run.css (added)
> +++ lnt/trunk/lnt/server/ui/static/lnt_run.css Tue Mar 29 07:11:28 2016
> @@ -0,0 +1,20 @@
> +.editable {
> + position: absolute;
> + background-color: black;
> + right: 0px;
> + top: 0px;
> + bottom: 0px;
> + width: 25px;
> + opacity: 0.5;
> + text-align: center;
> + visibility: hidden;
> +}
> +
> +tr:hover > td > .editable {
> + visibility: visible;
> + cursor: pointer;
> +}
> +
> +.editable span {
> + position: relative;
> +}
> \ No newline at end of file
>
> Added: lnt/trunk/lnt/server/ui/static/lnt_run.js
> URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/static/lnt_run.js?rev=264723&view=auto
> ==============================================================================
> --- lnt/trunk/lnt/server/ui/static/lnt_run.js (added)
> +++ lnt/trunk/lnt/server/ui/static/lnt_run.js Tue Mar 29 07:11:28 2016
> @@ -0,0 +1,190 @@
> +function RunTypeahead(element, options) {
> + this.element = element;
> + this.options = options;
> + this.id = null;
> +
> + this_ = this;
> + element.typeahead({
> + source: function(query, process) {
> + $.ajax(options.searchURL, {
> + dataType: "json",
> + data: $.extend({}, this_.options.data, {'q': query}),
> + success: function(data) {
> + process(data);
> + },
> + error: function(xhr, textStatus, errorThrown) {
> + pf_flash_error('accessing URL ' + options.searchURL +
> + '; ' + errorThrown);
> + }
> + });
> + },
> + // These identity functions are required because the defaults
> + // assume items are strings, whereas they're objects here.
> + sorter: function(items) {
> + // The results should be sorted on the server.
> + return items;
> + },
> + matcher: function(item) {
> + return item;
> + },
> + updater: function(item) {
> + // FIXME: the item isn't passed in as json any more, it's
> + // been rendered. Lame. To get around this, hack the
> + // components of the 2-tuple back apart.
> + name = item.split(',')[0];
> + id = item.split(',')[1];
> + this_.id = id;
> +
> + if (options.updated)
> + options.updated(name, id);
> + return name;
> + },
> + highlighter: function(item) {
> + // item is a 2-tuple [name, obj].
> + item = item[0];
> +
> + // This loop highlights each search term (split by space)
> + // individually. The content of the for loop is lifted from
> + // bootstrap.js (it's the original implementation of
> + // highlighter()). In particular I have no clue what that regex
> + // is doing, so don't bother asking.
> + var arr = this.query.split(' ');
> + for (i in arr) {
> + query = arr[i];
> + if (!query)
> + continue;
> + var q = query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,
> + '\\$&')
> + item = item.replace(new RegExp('(' + q + ')', 'ig'), function ($1, match) {
> + // We want to replace with <strong>match</strong here,
> + // but it's possible another search term will then
> + // match part of <strong>.
> + //
> + // Therefore, replace with two replaceable tokens that
> + // no search query is very likely to match...
> + return '%%%' + match + '£££'
> + });
> + }
> + return item
> + .replace(/%%%/g, '<strong>')
> + .replace(/£££/g, '</strong>');
> + }
> + });
> + // Bind an event disabling the function box and removing the profile
> + // if the run box is emptied.
> + element.change(function() {
> + if (!element.val()) {
> + this_.id = null;
> + if (options.cleared)
> + options.cleared();
> + }
> + });
> +}
> +
> +RunTypeahead.prototype = {
> + update: function (name, id) {
> + this.element.val(name);
> + this.id = id;
> + if (this.options.updated)
> + this.options.updated(name, id);
> + },
> + getSelectedRunId: function() {
> + return this.id;
> + }
> +};
> +
> +function modifyURL(type, id) {
> + var url = window.location.href;
> +
> + if (type == 'Current') {
> + return url.replace(/\d+($|\?)/, id + '?');
> + }
> + if (type == 'Previous') {
> + if (url.indexOf('compare_to=') != -1)
> + return url.replace(/compare_to=\d+/, 'compare_to=' + id);
> + else if (url.indexOf('?') != -1)
> + return url + '&compare_to=' + id;
> + else
> + return url + '?compare_to=' + id;
> + }
> + if (type == 'Baseline') {
> + if (url.indexOf('baseline=') != -1)
> + return url.replace(/baseline=\d+/, 'baseline=' + id);
> + else if (url.indexOf('?') != -1)
> + return url + '&baseline=' + id;
> + else
> + return url + '?baseline=' + id;
> + }
> +}
> +
> +function makeEditable(type, td) {
> + var exterior = $('<span></span>');
> +
> + var content = $('<input type="text">')
> + .addClass("input-large");
> +
> + var title = $('<b></b>')
> + .text('Choose run...')
> + .append($('<span>×</span>')
> + .addClass('close'));
> +
> + var enableTypeahead = function() {
> + content.runTypeahead({
> + searchURL: g_urls.search,
> + data: {'m': g_machine},
> + updated: function(name, id) {
> + var url = modifyURL(type, id);
> + document.location.href = url;
> + },
> + cleared: function() {
> + console.log("jjg");
> + }
> + });
> + title.children('span').first().click(function() {
> + exterior.popover('hide');
> + });
> + }
> +
> + var h = td.height() / 2;
> +
> + var interior = $('<span></span>')
> + .css({marginTop: (h - 6) + 'px'})
> + .addClass('icon-pencil icon-white');
> +
> + exterior.addClass('editable')
> + .append(interior)
> + .popover({
> + title: title,
> + content: content,
> + html: true,
> + trigger: 'click'
> + }).on('shown.bs.popover', function(){
> + enableTypeahead();
> + });
> +
> + td.css({position: 'relative'})
> + .append(exterior);
> +}
> +
> +$(function() {
> +
> + jQuery.fn.extend({
> + runTypeahead: function(options) {
> + if (options)
> + this.data('runTypeahead',
> + new RunTypeahead(this, options));
> + return this.data('runTypeahead');
> + }
> + });
> +
> + makeEditable( 'Current', $('#run-table-Current')
> + .children('td')
> + .last());
> + makeEditable( 'Previous', $('#run-table-Previous')
> + .children('td')
> + .last());
> + makeEditable( 'Baseline', $('#run-table-Baseline')
> + .children('td')
> + .last());
> +
> +});
>
> Modified: lnt/trunk/lnt/server/ui/templates/reporting/runs.html
> URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/reporting/runs.html?rev=264723&r1=264722&r2=264723&view=diff
> ==============================================================================
> --- lnt/trunk/lnt/server/ui/templates/reporting/runs.html (original)
> +++ lnt/trunk/lnt/server/ui/templates/reporting/runs.html Tue Mar 29 07:11:28 2016
> @@ -96,7 +96,7 @@
> <tbody>
> {% for title, r in (('Current', run), ('Previous', compare_to), ('Baseline', baseline)) %}
> {% if r %}
> - <tr>
> + <tr id="run-table-{{ title }}">
> <td style="{{ styles['td'] }}"><a href="{{ ts_url }}/{{ r.id }}">{{ title }}</a></td>
> <td style="{{ styles['td'] }}"><a href="{{ ts_url }}/order/{{ r.order.id }}">{{ r.order.llvm_project_revision }}</a></td>
> <td style="{{ styles['td'] }}"><span class="utctime">{{ r.start_time.isoformat() }}</span></td>
> @@ -106,7 +106,9 @@
> {% endif %}
> </tr>
> {% else %}
> - <tr><td style="{{ styles['td'] }}" colspan="5">No {{ title }} Run</td></tr>
> + <tr id="run-table-{{ title }}">
> + <td style="{{ styles['td'] }}" colspan="5">No {{ title }} Run</td>
> + </tr>
> {% endif %}
> {% endfor %}
> </tbody>
>
> Modified: lnt/trunk/lnt/server/ui/templates/v4_profile.html
> URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/v4_profile.html?rev=264723&r1=264722&r2=264723&view=diff
> ==============================================================================
> --- lnt/trunk/lnt/server/ui/templates/v4_profile.html (original)
> +++ lnt/trunk/lnt/server/ui/templates/v4_profile.html Tue Mar 29 07:11:28 2016
> @@ -7,6 +7,9 @@
> {% block head %}
> <script language="javascript" type="text/javascript"
> src="{{ url_for('.static',
> + filename='lnt_run.js') }}"></script>
> + <script language="javascript" type="text/javascript"
> + src="{{ url_for('.static',
> filename='lnt_profile.js') }}"></script>
> <script language="javascript" type="text/javascript"
> src="{{ url_for('.static',
>
> Modified: lnt/trunk/lnt/server/ui/templates/v4_run.html
> URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/v4_run.html?rev=264723&r1=264722&r2=264723&view=diff
> ==============================================================================
> --- lnt/trunk/lnt/server/ui/templates/v4_run.html (original)
> +++ lnt/trunk/lnt/server/ui/templates/v4_run.html Tue Mar 29 07:11:28 2016
> @@ -15,8 +15,16 @@
> v4_url_for("v4_machine", id=machine.id))] %}
>
> {% block head %}
> + <script>
> + g_urls = {{urls|tojson|safe}};
> + g_machine = {{run.machine.id}};
> + </script>
> +
> <script src="{{ url_for('.static', filename='popup.js') }}"></script>
> <script src="{{ url_for('.static', filename='sorttable.js') }}"></script>
> + <script src="{{ url_for('.static', filename='lnt_run.js') }}"></script>
> + <link href="{{ url_for('.static', filename='lnt_run.css') }}" rel="stylesheet" media="screen"/>
> +
> <script type="text/javascript">
> function selectAll(source) {
> $(source).closest("table").find("input:checkbox").prop("checked", source.checked);
>
> Modified: lnt/trunk/lnt/server/ui/views.py
> URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/views.py?rev=264723&r1=264722&r2=264723&view=diff
> ==============================================================================
> --- lnt/trunk/lnt/server/ui/views.py (original)
> +++ lnt/trunk/lnt/server/ui/views.py Tue Mar 29 07:11:28 2016
> @@ -4,6 +4,7 @@ import re
> import tempfile
> import time
> import copy
> +import json
>
> import flask
> from flask import abort
> @@ -30,6 +31,7 @@ import lnt.server.ui.util
> import lnt.server.reporting.dailyreport
> import lnt.server.reporting.summaryreport
> import lnt.server.db.rules_manager
> +import lnt.server.db.search
> from collections import namedtuple
> from lnt.util import async_ops
>
> @@ -417,12 +419,16 @@ def v4_run(id):
>
> return flask.jsonify(**json_obj)
>
> + urls = {
> + 'search': v4_url_for('v4_search')
> + }
> return render_template(
> "v4_run.html", ts=ts, options=options,
> metric_fields=list(ts.Sample.get_metric_fields()),
> test_info=test_info, analysis=lnt.server.reporting.analysis,
> test_min_value_filter=test_min_value_filter,
> - request_info=info)
> + request_info=info, urls=urls
> +)
>
> @v4_route("/order/<int:id>")
> def v4_order(id):
> @@ -1233,3 +1239,26 @@ def health():
> if explode:
> return msg, 500
> return msg, 200
> +
> + at v4_route("/search")
> +def v4_search():
> + def _isint(i):
> + try:
> + int(i)
> + return True
> + except:
> + return False
> +
> + ts = request.get_testsuite()
> + query = request.args.get('q')
> + l = request.args.get('l', 8)
> + default_machine = request.args.get('m', None)
> +
> + assert query
> + results = lnt.server.db.search.search(ts, query, num_results=l,
> + default_machine=default_machine)
> +
> + return json.dumps(
> + [('%s #%s' % (r.machine.name, r.order.llvm_project_revision),
> + r.id)
> + for r in results])
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list