[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