[LNT] r255954 - Merge of Regression Details with states
Chris Matthews via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 17 17:22:12 PST 2015
Author: cmatthews
Date: Thu Dec 17 19:22:12 2015
New Revision: 255954
URL: http://llvm.org/viewvc/llvm-project?rev=255954&view=rev
Log:
Merge of Regression Details with states
Modified:
lnt/trunk/lnt/server/db/fieldchange.py
lnt/trunk/lnt/server/db/testsuitedb.py
lnt/trunk/lnt/server/ui/regression_views.py
lnt/trunk/lnt/server/ui/templates/layout.html
lnt/trunk/lnt/server/ui/templates/v4_regression_detail.html
lnt/trunk/lnt/server/ui/templates/v4_regression_list.html
Modified: lnt/trunk/lnt/server/db/fieldchange.py
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/db/fieldchange.py?rev=255954&r1=255953&r2=255954&view=diff
==============================================================================
--- lnt/trunk/lnt/server/db/fieldchange.py (original)
+++ lnt/trunk/lnt/server/db/fieldchange.py Thu Dec 17 19:22:12 2015
@@ -3,7 +3,7 @@ import sqlalchemy.sql
import lnt.server.reporting.analysis
from lnt.testing.util.commands import warning
from lnt.testing.util.commands import note
-from lnt.server.ui.regression_views import new_regression
+from lnt.server.ui.regression_views import new_regression, RegressionState
# How many runs backwards to use in the previous run set.
# More runs are slower (more DB access), but may provide
# more accurate results.
@@ -105,12 +105,29 @@ def is_overlaping(fc1, fc2):
(r1_min < r2_max and r2_min < r1_max)
-def rebuild_title(regression, new_size):
+def shortname(benchmark):
+ """Given a benchmarks full name, make a short version"""
+ return benchmark.split("/")[-1]
+
+
+def rebuild_title(ts, regression):
"""Update the title of a regresson."""
if re.match("Regression of \d+ benchmarks.*", regression.title):
- new_title = "Regression of {} benchmarks".format(new_size)
- regression.title = new_title
- print new_title
+ old_changes = ts.query(ts.RegressionIndicator) \
+ .filter(ts.RegressionIndicator.regression_id == regression.id) \
+ .all()
+ new_size = len(old_changes)
+ benchmarks = set()
+ for ri in old_changes:
+ fc = ri.field_change
+ benchmarks.add(shortname(fc.test.name))
+ print benchmarks
+ FMT = "Regression of {} benchmarks: {}"
+ title = FMT.format(new_size, ', '.join(benchmarks))
+ # Crop long titles.
+ title = (title[:120] + '...') if len(title) > 120 else title
+ regression.title = title
+ print title
return regression
@@ -142,7 +159,7 @@ def identify_related_changes(ts, regress
ri = ts.RegressionIndicator(regression, fc)
ts.add(ri)
# Update the default title if needed.
- rebuild_title(regression, len(regression_indicators) + 1)
+ rebuild_title(ts, regression)
return (True, regression)
note("Could not find a partner, creating new Regression for change")
new_reg = new_regression(ts, [fc.id])
Modified: lnt/trunk/lnt/server/db/testsuitedb.py
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/db/testsuitedb.py?rev=255954&r1=255953&r2=255954&view=diff
==============================================================================
--- lnt/trunk/lnt/server/db/testsuitedb.py (original)
+++ lnt/trunk/lnt/server/db/testsuitedb.py Thu Dec 17 19:22:12 2015
@@ -444,9 +444,10 @@ class TestSuiteDB(object):
bug = Column("BugLink", String(256), unique=False, index=False)
state = Column("State", Integer)
- def __init__(self, title, bug):
+ def __init__(self, title, bug, state):
self.title = title
self.bug = bug
+ self.state = state
def __repr__(self):
return '%s_%s:"%s"' % (db_key_name, self.__class__.__name__,
Modified: lnt/trunk/lnt/server/ui/regression_views.py
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/regression_views.py?rev=255954&r1=255953&r2=255954&view=diff
==============================================================================
--- lnt/trunk/lnt/server/ui/regression_views.py (original)
+++ lnt/trunk/lnt/server/ui/regression_views.py Thu Dec 17 19:22:12 2015
@@ -19,9 +19,38 @@ from random import randint
from sqlalchemy import desc, asc
from lnt.server.ui.util import FLASH_DANGER, FLASH_INFO, FLASH_SUCCESS
from lnt.server.reporting.analysis import REGRESSED
-from wtforms import SelectMultipleField, StringField, widgets
+from wtforms import SelectMultipleField, StringField, widgets, SelectField
from flask_wtf import Form
from wtforms.validators import DataRequired
+import lnt.server.ui.util as util
+
+import lnt.server.db.fieldchange
+
+
+class RegressionState:
+ # A new regression, not approved by the user yet.
+ DETECTED = 0
+ # Approved, but waiting for cooldown.
+ STAGED = 1
+ # Needs to be investigated.
+ ACTIVE = 10
+
+ # We won't fix this.
+ NTBF = 20
+ # This is not a real regression.
+ IGNORED = 21
+ # Manually marked as fixed.
+ FIXED = 22
+ # System detected it is fixed.
+ DETECTED_FIXED = 23
+ names = {DETECTED: u'Detected',
+ STAGED: u'Staged',
+ ACTIVE: u'Active',
+ NTBF: u'Not to be Fixed',
+ IGNORED: u'Ignored',
+ DETECTED_FIXED: u'Verify',
+ FIXED: u'Fixed'
+ }
class MultiCheckboxField(SelectMultipleField):
@@ -71,15 +100,15 @@ class PrecomputedCR():
def new_regression(ts, field_changes):
"""Make a new regression and add to DB."""
today = datetime.date.today()
- MSG = "Regression of {} benchmarks on {}"
- title = MSG.format(len(field_changes),
- today.strftime('%b %d %Y'))
- regression = ts.Regression(title, "")
+ MSG = "Regression of 0 benchmarks"
+ title = MSG
+ regression = ts.Regression(title, "", RegressionState.DETECTED)
ts.add(regression)
for fc_id in field_changes:
fc = get_fieldchange(ts, fc_id)
ri1 = ts.RegressionIndicator(regression, fc)
ts.add(ri1)
+ lnt.server.db.fieldchange.rebuild_title(ts, regression)
ts.commit()
return regression
@@ -196,23 +225,89 @@ def get_cr_for_field_change(ts, field_ch
return cr, runs.after[0]
- at v4_route("/regressions/")
+def calc_impact(ts, fcs):
+ crs = []
+ for fc in fcs:
+ if fc == None:
+ continue
+ if fc.old_value is None:
+ cr, _ = get_cr_for_field_change(ts, fc)
+ else:
+ cr = PrecomputedCR(fc.old_value, fc.new_value, fc.field.bigger_is_better)
+ crs.append(cr)
+ if crs:
+ olds = sum([x.previous for x in crs])
+ news = sum([x.current for x in crs])
+ new_cr = PrecomputedCR(olds, news, crs[0].bigger_is_better) # TODO both directions
+ return new_cr
+ else:
+ return PrecomputedCR(1, 1, True)
+
+
+class MergeRegressionForm(Form):
+ regression_checkboxes = MultiCheckboxField("regression_checkboxes",
+ coerce=int)
+
+
+ at v4_route("/regressions/", methods=["GET", "POST"])
def v4_regression_list():
ts = request.get_testsuite()
+ form = MergeRegressionForm(request.form)
- regression_info = ts.query(ts.Regression) \
- .all()[::-1]
+ if request.method == 'POST' and \
+ request.form['merge_btn'] == "Merge Regressions":
+ regressions_id_to_merge = form.regression_checkboxes.data
+ regressions = ts.query(ts.Regression) \
+ .filter(ts.Regression.id.in_(regressions_id_to_merge)).all()
+ reg_inds = ts.query(ts.RegressionIndicator) \
+ .filter(ts.RegressionIndicator.regression_id.in_(
+ regressions_id_to_merge)) \
+ .all()
+ new_regress = new_regression(ts, [x.field_change_id for x in reg_inds])
+ new_regress.state = regressions[0].state
+ [ts.delete(x) for x in reg_inds]
+ [ts.delete(x) for x in regressions]
+ ts.commit()
+ flash("Created" + new_regress.title, FLASH_SUCCESS)
+ return redirect(v4_url_for("v4_regression_detail", id=new_regress.id))
+ state_filter = int(request.args.get('state', RegressionState.ACTIVE))
+ q = ts.query(ts.Regression)
+ title = "All Regressions"
+ if state_filter != -1:
+ q = q.filter(ts.Regression.state == state_filter)
+ title = RegressionState.names[state_filter]
+ regression_info = q.all()[::-1]
+
+ form.regression_checkboxes.choices = list()
+ regression_sizes = []
+ impacts = []
+ for regression in regression_info:
+ form.regression_checkboxes.choices.append((regression.id, 1,))
+ reg_inds = ts.query(ts.RegressionIndicator) \
+ .filter(ts.RegressionIndicator.regression_id ==
+ regression.id) \
+ .all()
+ regression_sizes.append(len(reg_inds))
+ impacts.append(calc_impact(ts, [x.field_change for x in reg_inds]))
return render_template("v4_regression_list.html",
testsuite_name=g.testsuite_name,
regressions=regression_info,
- highlight=request.args.get('highlight'))
+ highlight=request.args.get('highlight'),
+ title=title,
+ RegressionState=RegressionState,
+ form=form,
+ sizes=regression_sizes,
+ impacts=impacts,
+ analysis=lnt.server.reporting.analysis)
class EditRegressionForm(Form):
title = StringField(u'Title', validators=[DataRequired()])
bug = StringField(u'Bug', validators=[DataRequired()])
field_changes = MultiCheckboxField("Changes", coerce=int)
+ choices = RegressionState.names.items()
+ state = SelectField(u'State', choices=choices)
@v4_route("/regressions/<int:id>", methods=["GET", "POST"])
@@ -223,43 +318,80 @@ def v4_regression_detail(id):
regression_info = ts.query(ts.Regression) \
.filter(ts.Regression.id == id) \
.one()
+
if request.method == 'POST' and request.form['save_btn'] == "Save Changes":
regression_info.title = form.title.data
regression_info.bug = form.bug.data
+ regression_info.state = form.state.data
ts.commit()
flash("Updated " + regression_info.title, FLASH_SUCCESS)
return redirect(v4_url_for("v4_regression_list",
- highlight=regression_info.id))
+ highlight=regression_info.id,
+ state=regression_info.state))
if request.method == 'POST' and request.form['save_btn'] == "Split Regression":
# For each of the regression indicators, grab their field ids.
-
res_inds = ts.query(ts.RegressionIndicator) \
- .filter(ts.RegressionIndicator.id.in_(form.field_changes.data)) \
+ .filter(ts.RegressionIndicator.field_change_id.in_(form.field_changes.data)) \
.all()
fc_ids = [x.field_change_id for x in res_inds]
second_regression = new_regression(ts, fc_ids)
+ second_regression.state = regression_info.state
+
# Now remove our links to this regression.
for res_ind in res_inds:
ts.delete(res_ind)
+ lnt.server.db.fieldchange.rebuild_title(ts, regression_info)
ts.commit()
flash("Split " + second_regression.title, FLASH_SUCCESS)
return redirect(v4_url_for("v4_regression_list",
highlight=second_regression.id))
+ if request.method == 'POST' and request.form['save_btn'] == "Delete":
+ # For each of the regression indicators, grab their field ids.
+ title = regression_info.title
+ res_inds = ts.query(ts.RegressionIndicator) \
+ .filter(ts.RegressionIndicator.regression_id == regression_info.id) \
+ .all()
+ # Now remove our links to this regression.
+ for res_ind in res_inds:
+ ts.delete(res_ind)
+ ts.delete(regression_info)
+ ts.commit()
+ flash("Deleted " + title, FLASH_SUCCESS)
+ return redirect(v4_url_for("v4_regression_list"))
form.field_changes.choices = list()
+ form.state.default = regression_info.state
+ form.process()
+ form.title.data = regression_info.title
+ form.bug.data = regression_info.bug
regression_indicators = ts.query(ts.RegressionIndicator) \
.filter(ts.RegressionIndicator.regression_id == id) \
.all()
- indicators = []
+ # indicators = []
+ # for regression in regression_indicators:
+ # fc = regression.field_change
+ # cr, key_run = get_cr_for_field_change(ts, fc)
+ # latest_cr, _ = get_cr_for_field_change(ts, fc, current=True)
+ # indicators.append(ChangeData(fc, cr, key_run, latest_cr))
+
+
+ ######
+ crs = []
+
+ form.field_changes.choices = list()
for regression in regression_indicators:
fc = regression.field_change
- cr, key_run = get_cr_for_field_change(ts, fc)
- latest_cr, _ = get_cr_for_field_change(ts, fc, current=True)
- indicators.append(ChangeData(fc, cr, key_run, latest_cr))
- form.field_changes.choices.append((regression.id, 1,))
- form.title.data = regression_info.title
- form.bug.data = regression_info.bug
+ if fc is None:
+ continue
+ if fc.old_value is None:
+ cr, key_run = get_cr_for_field_change(ts, fc)
+ else:
+ cr = PrecomputedCR(fc.old_value, fc.new_value, fc.field.bigger_is_better)
+ key_run = get_first_runs_of_fieldchange(ts, fc)
+ current_cr, _ = get_cr_for_field_change(ts, fc, current=True)
+ crs.append(ChangeData(fc, cr, key_run, current_cr))
+ form.field_changes.choices.append((fc.id, 1,))
return render_template("v4_regression_detail.html",
testsuite_name=g.testsuite_name,
- regression=regression_info, indicators=indicators,
+ regression=regression_info, changes=crs,
form=form, analysis=lnt.server.reporting.analysis)
Modified: lnt/trunk/lnt/server/ui/templates/layout.html
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/layout.html?rev=255954&r1=255953&r2=255954&view=diff
==============================================================================
--- lnt/trunk/lnt/server/ui/templates/layout.html (original)
+++ lnt/trunk/lnt/server/ui/templates/layout.html Thu Dec 17 19:22:12 2015
@@ -129,7 +129,14 @@
<li><a href="{{ v4_url_for('v4_daily_report_overview') }}">Daily Report</a></li>
<li><a href="{{ v4_url_for('v4_machines') }}">All Machines</a></li>
<li><a href="{{ v4_url_for('v4_new_regressions') }}">Triage</a></li>
- <li><a href="{{ v4_url_for('v4_regression_list') }}">Tracking</a></li>
+ <li><a href="{{ v4_url_for('v4_regression_list', state=0) }}">Detected</a></li>
+ <li><a href="{{ v4_url_for('v4_regression_list', state=1) }}">Staged</a></li>
+ <li><a href="{{ v4_url_for('v4_regression_list', state=10) }}">Active</a></li>
+ <li><a href="{{ v4_url_for('v4_regression_list', state=20) }}">NTBF</a></li>
+ <li><a href="{{ v4_url_for('v4_regression_list', state=21) }}">Ignored</a></li>
+ <li><a href="{{ v4_url_for('v4_regression_list', state=23) }}">Verify</a></li>
+ <li><a href="{{ v4_url_for('v4_regression_list', state=22) }}">Fixed</a></li>
+ <li><a href="{{ v4_url_for('v4_regression_list', state=-1) }}">All</a></li>
<li class="divider"></li>
<li class="disabled"><a href="#">Summary Report</a></li>
{#"{{ v4_url_for('v4_summary_report') }}"#}
Modified: lnt/trunk/lnt/server/ui/templates/v4_regression_detail.html
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/v4_regression_detail.html?rev=255954&r1=255953&r2=255954&view=diff
==============================================================================
--- lnt/trunk/lnt/server/ui/templates/v4_regression_detail.html (original)
+++ lnt/trunk/lnt/server/ui/templates/v4_regression_detail.html Thu Dec 17 19:22:12 2015
@@ -6,49 +6,260 @@
("Tracking", v4_url_for("v4_regression_list"))] %}
{% block title %}Regression Details{% endblock %}
+{% block head %}
+ <script src="{{ url_for('.static', filename='popup.js') }}"></script>
+ <script src="{{ url_for('.static', filename='sorttable.js') }}"></script>
+ <script language="javascript" type="text/javascript"
+ src="{{ url_for('.static',
+ filename='flot/jquery.flot.min.js') }}"> </script>
+ <script language="javascript" type="text/javascript"
+ src="{{ url_for('.static',
+ filename='flot/jquery.flot.errorbars.min.js') }}"> </script>
+ <script language="javascript" type="text/javascript"
+ src="{{ url_for('.static',
+ filename='flot/jquery.flot.navigate.min.js') }}"> </script>
+ <script language="javascript" type="text/javascript"
+ src="{{ url_for('.static',
+ filename='flot/jquery.flot.selection.min.js') }}"> </script>
+ <script language="javascript" type="text/javascript"
+ src="{{ url_for('.static',
+ filename='flot/jquery.flot.highlight.min.js') }}"></script>
+ <script src="{{ url_for('.static', filename='lnt_graph.js') }}"></script>
+{% endblock %}
+
+
+
+
+{% block javascript %}
+var g = {}
+{% set api_graph = "api/db_default/v4/" + testsuite_name + "/graph"%}
+var changes = [
+{% for form_change in form.field_changes%}
+ {% set fc = changes[loop.index -1] %}
+ {"url": "/{{api_graph}}/{{ fc.ri.machine.id}}/{{fc.ri.test.id}}/{{fc.ri.field.index}}",
+ "start": {{fc.ri.start_order.llvm_project_revision}},
+ "end": {{fc.ri.end_order.llvm_project_revision}}
+ },
+{% endfor %}
+];
+
+/* Bind events to the zoom bar buttons, so that
+ * the zoom buttons work, then position them
+ * over top of the main graph.
+ */
+function bind_zoom_bar(my_plot) {
+
+ $('#out').click(function (e) {
+ e.preventDefault();
+ my_plot.zoomOut();
+ });
+
+ $('#in').click(function (e) {
+ e.preventDefault();
+ my_plot.zoom();
+ });
+
+
+ // Now move the bottons onto the graph.
+ $('#zoombar').css('position', 'relative');
+ $('#zoombar').css('left', '40px');
+ $('#zoombar').css('top', '-235px');
+}
+$('#normalize').click(function (e) {
+ normalize = !normalize;
+ alert(normalize);
+ update_graph();
+});
+function init(data, start_highlight, end_highlight) {
+ // Set up the primary graph.
+ var graph = $("#graph");
+ var graph_plots = data;
+ var line_width = 1;
+ if (data.length > 0 && data[0]['data'].length < 50) {
+ line_width = 2;
+ }
+ var graph_options = {
+ series : {
+ lines : {
+ lineWidth : line_width },
+ shadowSize : 0
+ },
+ highlight : {
+
+ range: {"end": [end_highlight], "start": [start_highlight]},
+ alpha: "0.1",
+ stroke: false,
+
+ },
+ zoom : { interactive : false },
+ pan : { interactive : true,
+ frameRate: 60 },
+ grid : {
+ hoverable : true }
+ };
+
+ var main_plot = $.plot("#graph", graph_plots, graph_options);
+
+ // Add tooltips.
+ $("#graph").bind("plothover", function(e,p,i) {
+ update_tooltip(e, p, i, show_tooltip, graph_plots); });
+ bind_zoom_bar(main_plot);
+
+
+}
+
+// Show our overlay tooltip.
+g.current_tip_point = null;
+function show_tooltip(x, y, item, pos, graph_data) {
+
+ // Given the event handler item, get the graph metadata.
+ function extract_metadata(item, graph_data) {
+ var index = item.dataIndex;
+ var series_index = item.seriesIndex;
+ // Graph data is formatted as [x, y, meta_data].
+ var meta_data = item.series.data[series_index][2];
+ return meta_data;
+
+ }
+ var data = item.datapoint;
+ var meta_data = extract_metadata(item, graph_data);
+ var tip_body = '<div id="tooltip">';
+
+ if ("test_name" in meta_data) {
+ tip_body += "<b>Test:</b> " + meta_data.test_name + "<br>";
+ }
+
+ if ("label" in meta_data) {
+ tip_body += "<b>Revision:</b> " + meta_data.label + "<br>";
+ }
+ tip_body += "<b>Value:</b> " + data[1].toFixed(4) + "<br>";
+
+ if ("date" in meta_data) {
+ tip_body += "<b>Date:</b> " + meta_data.date;
+ }
+ tip_body += "</div>";
+ var tooltip_div = $(tip_body).css( {
+ position: 'absolute',
+ display: 'none',
+ top: y + 5,
+ left: x + 5,
+ border: '1px solid #fdd',
+ padding: '2px',
+ 'background-color': '#fee',
+ opacity: 0.80
+ }).appendTo("body").fadeIn(200);
+
+ // Now make sure the tool tip is on the graph canvas.
+ var tt_position = tooltip_div.position();
+ var tt_offset = tooltip_div.offset();
+
+ var graph_div = $("#graph");
+ var graph_position = graph_div.position();
+
+ // The right edge of the graph.
+ var max_width = graph_position.left + graph_div.width();
+ // The right edge of the tool tip.
+ var tt_right = tt_position.left + tooltip_div.width();
+
+ if (tt_right > max_width) {
+ var diff = tt_right - max_width
+ var GRAPH_BORDER = 10;
+ var VISUAL_APPEAL = 10;
+ tooltip_div.css({'left' : tt_position.left - diff
+ - GRAPH_BORDER - VISUAL_APPEAL});
+ }
+
+}
+
+// Event handler function to update the tooltop.
+function update_tooltip(event, pos, item, show_fn, graph_data) {
+ if (!item) {
+ $("#tooltip").remove();
+ g.current_tip_point = null;
+ return;
+ }
+
+ if (!g.current_tip_point || (g.current_tip_point[0] != item.datapoint[0] ||
+ g.current_tip_point[1] != item.datapoint[1])) {
+ $("#tooltip").remove();
+ g.current_tip_point = item.datapoint;
+ show_fn(pos.pageX, pos.pageY, item, pos, graph_data);
+ }
+}
+{% endblock %}
+
{% block body %}
<section id="Regression Detail" />
<h3>Regression: {{regression.title}}</h3>
+
+<div id="graph" style="height:250px"></div>
+<div id="zoombar" style="width:40px;z-index: 999;">
+ <button id="in" type="button" class="btn btn-default" style="width:100%;text-align:center;">+</button>
+ <br>
+ <button id="out" type="button" class="btn btn-default" style="width:100%; text-align:center;">-</button>
+ <br>
+ <button id="normalize" type="button" class="btn btn-default" style="width:100%; text-align:center;">%</button>
+</div>
+
<a href="{{regression.bug}}">{{regression.bug}}</a>
+
+
+
+
<form method="POST" action="">
-<table class="table table-striped table-hover table-condensed">
- <caption>This needs to be dynamically queried</caption>
+ {{ form.hidden_tag() }}
+<table id="changes_table" class="display">
+
<thead>
<tr>
<th>X</th>
<th>Machine</th>
<th>Metric</th>
<th>Test</th>
- <th>Detected</th>
- <th>Last Good Rev.</th>
- <th>First Bad Rev.</th>
- <th>Change</th>
- <th>Current</th>
+ <th>Good, Bad</th>
+ <th>Old</th><th>New</th>
+ <th>%Δ</th>
+ <th>Now</th>
+ <th>Curernt</th>
+ <th>Age</th>
</tr>
</thead>
<tbody>
+ {% set graph_base=v4_url_for('v4_graph') %}
+ {# Show the active submissions. #}
{% for form_change in form.field_changes%}
- {% set ind = indicators[loop.index -1] %}
+ {% set fc = changes[loop.index -1] %}
<tr>
- <td>{{form_change}}</td>
- {% set graph_base=v4_url_for('v4_graph', highlight_run=ind.run.id) %}
- <td>{{utils.render_machine(ind.ri.machine)}}</td>
- <td>{{ind.ri.field.name}}</td>
- <td><a href="{{graph_base}}&plot.{{ind.ri.test.id}}={{ ind.ri.machine.id}}.{{ind.ri.test.id}}.{{ind.ri.field.index}}">{{ ind.ri.test.name }}</a></td>
- <td><span class="reltime" data-toggle="tooltip" title="{{ind.run.end_time}}">{{ ind.run.end_time.isoformat() }}</td>
-
- <td>{{utils.render_order_link(ind.ri.start_order)}}</td>
- <td>{{utils.render_order_link(ind.ri.end_order)}}</td>
- {{utils.get_regression_cell_value(ind.cr, analysis)}}
- {{utils.get_regression_cell_value(ind.latest_cr, analysis)}}
+ <td>
+
+ <table>
+ <tr style="background:transparent;">
+ <td style="background:transparent;"></td><td>{{ form_change }}</td>
+ </tr>
+ </table>
+ <td>{{utils.render_machine(fc.ri.machine)}}</td>
+ <td> {{ fc.ri.field.name }} </td>
+ {% set graph_base=v4_url_for('v4_graph', highlight_run=fc.run.id) %}
+ <td><a href="{{graph_base}}&plot.{{fc.ri.test.id}}={{ fc.ri.machine.id}}.{{fc.ri.test.id}}.{{fc.ri.field.index}}">{{ fc.ri.test.name }}</a></td>
+ <td>m{{ fc.ri.start_order.llvm_project_revision }}, {{utils.render_order_link(fc.ri.end_order)}}</td>
+ <td>{{ fc.cr.previous }}</td><td>{{ fc.cr.current }}</td>
+ {{ utils.get_regression_cell_value(fc.cr, analysis)}}
+ <td>{{ fc.latest_cr.current }}</td>
+ {{ utils.get_regression_cell_value(fc.latest_cr, analysis)}}
+
+ <td><span class="reltime" data-toggle="tooltip" title="{{fc.run.end_time}}">{{ fc.run.end_time.isoformat() }}</td>
</tr>
{% endfor %}
</tbody>
</table>
+<button id="all" type="button" class="btn btn-default" onclick="all_checks()">Check Visable</button>
+<button id="clear" type="button" class="btn btn-default" onclick="clear_checks()">Clear Visable</button>
+
+
<!-- Button to trigger modal -->
<a href="#editRegressionModal" role="button" class="btn" data-toggle="modal">Edit</a>
@@ -63,6 +274,7 @@
<div class="modal-body">
<p>{{ form.title.label }}{{ form.title }}</p>
<p>{{ form.bug.label }}{{form.bug }}</p>
+ <p>{{ form.state.label }}{{form.state}}</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
@@ -91,5 +303,92 @@
</div>
</div>
+
+<!-- Button to trigger modal -->
+<a href="#deleteRegressionModal" role="button" class="btn" data-toggle="modal">Delete</a>
+
+<!-- Modal -->
+<div id="deleteRegressionModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="deleteRegressionModal" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">Ã</button>
+ <h3 id="editRegressionModal">Delete Regression</h3>
+ </div>
+
+ <div class="modal-body">
+ Remove all traces of this regression from the database. Are you sure?
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ <input name="save_btn" class="btn btn-primary" type="submit" value="Delete">
+
+ </div>
+</div>
</form>
+
+<script type="text/javascript">
+
+function clear_checks() {
+ $('input:checkbox').removeAttr('checked');
+ $('input:checkbox').trigger('change');
+}
+
+function all_checks() {
+ $('input:checkbox').prop('checked','checked');
+ $('input:checkbox').trigger('change');
+}
+
+function show_all() {
+ dt.page.len(-1).draw();
+}
+
+function register_checkboxes() {
+ $(':checkbox').change(function(){
+ var c = this.checked
+ var id = this.id;
+ var index = id.split("-")[1];
+ if (c) {
+ var color = color_codes[index % color_codes.length];
+ var prev_cell = $(this).closest('td').prev();
+ prev_cell.css("background-color", color);
+ add_data_to_graph(changes[index]["url"], index);
+ } else {
+ is_checked[index] = false;
+ var prev_cell = $(this).closest('td').prev();
+ prev_cell.css("background-color", "transparent");
+ update_graph();
+ }
+
+ });
+ $(':checkbox').css("-webkit-transform", "scale(2)");
+ }
+var dt = null;
+
+$(document).ready( function () {
+ dt = $('#changes_table').DataTable({
+ "dom": '<"top"if>rt<"bottom"Flp>',
+ "drawCallback": function( settings ) {
+ register_checkboxes();
+ },
+ "aLengthMenu": [
+ [25, 50, 100, 200, -1],
+ [25, 50, 100, 200, "All"]],
+});
+
+
+ for (var i = 0; i < changes.length; i++) {
+ is_checked[i] = false;
+ }
+
+ register_checkboxes();
+ all_checks();
+ $('#normalize').click(function (e) {
+ normalize = !normalize;
+ update_graph();
+ });
+ update_graph();
+
+
+} );
+</script>
+
{% endblock %}
Modified: lnt/trunk/lnt/server/ui/templates/v4_regression_list.html
URL: http://llvm.org/viewvc/llvm-project/lnt/trunk/lnt/server/ui/templates/v4_regression_list.html?rev=255954&r1=255953&r2=255954&view=diff
==============================================================================
--- lnt/trunk/lnt/server/ui/templates/v4_regression_list.html (original)
+++ lnt/trunk/lnt/server/ui/templates/v4_regression_list.html Thu Dec 17 19:22:12 2015
@@ -3,29 +3,76 @@
{% extends "layout.html" %}
{% set components = [(testsuite_name, v4_url_for("v4_recent_activity"))] %}
-{% block title %}Regression List{% endblock %}
+{% block title %}Regression List: {{title}}{% endblock %}
{% block body %}
<section id="Regressions" />
+<h3>Regressions List: {{title}}</h3>
-<table class="table table-striped table-hover table-condensed">
- <caption>This needs to be dynamically queried</caption>
+<form method="POST" action="{{ v4_url_for("v4_regression_list", state=10) }}">
+
+
+<table id="regression_list" class="table table-striped table-hover table-condensed">
+
<thead>
<tr>
+ <th>X</th>
<th>Title</th>
+ <th>State</th>
+ <th>Size</th>
+ <th>Old</th>
+ <th>New</th>
+ <th>%</th>
<th>Bug</th>
</tr>
</thead>
<tbody>
- {% for regress in regressions %}
+ {# Show the active submissions. #}
+ {% for form_regression in form.regression_checkboxes%}
+ {% set regress = regressions[loop.index -1] %}
+ {% set size = sizes[loop.index -1] %}
+ {% set impact = impacts[loop.index -1] %}
+
<tr>
+ <td>{{ form_regression }}</td>
<td>{{utils.render_regression(regress)}} {% if regress.id|int == highlight|int %} <span class="label label-success">Updated</span> {% endif %} </td>
+ <td>{{RegressionState.names.get(regress.state,"Missing")}}</td>
+ <th>{{ size }}</th>
+ <td>{{ impact.previous }}</td><td>{{ impact.current }}</td>
+ {{ utils.get_regression_cell_value(impact, analysis)}}
<td>{{utils.render_bug(regress.bug)}}</td>
</tr>
{% endfor %}
</tbody>
</table>
+<!-- Button to trigger modal -->
+<a href="#mergeRegressionModal" role="button" class="btn" data-toggle="modal">Merge</a>
+
+<!-- Modal -->
+<div id="mergeRegressionModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="mergeRegressionModal" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">Ã</button>
+ <h3 id="editRegressionModal">Merge Regression</h3>
+ </div>
+
+ <div class="modal-body">
+ Merge selected changes into new regression. Are you sure?
+ </div>
+ <div class="modal-footer">
+ <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
+ <input name="merge_btn" class="btn btn-primary" type="submit" value="Merge Regressions">
+ </div>
+ </div>
+</div>
+
+</form>
+
+<script type="text/javascript">
+$(document).ready( function () {
+ dt = $('#regression_list').DataTable();
+});
+</script>
{% endblock %}
More information about the llvm-commits
mailing list