<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[196387] trunk/Websites/perf.webkit.org</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/196387">196387</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-02-10 13:07:52 -0800 (Wed, 10 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Analysis task page on v3 UI should show charts
https://bugs.webkit.org/show_bug.cgi?id=154057

Reviewed by Chris Dumez.

Extracted ChartPaneBase out of ChartPane and added an instance of its new subclass, AnalysisTaskChartPane,
to the analysis task page. The main difference is that ChartPaneBase doesn't depend on the presence of
this._chartsPage unlike ChartPane. It also doesn't have the header with toolbar (to show breakdown, etc...).

* public/v3/components/base.js:
(ComponentBase.prototype._constructShadowTree): Call htmlTemplate() and cssTemplate() with the right &quot;this&quot;.

* public/v3/components/chart-pane-base.js: Added.
(ChartPaneBase): Extracted from ChartPane.
(ChartPaneBase.prototype.configure): Extracted from the constructor. Separating this function allows the
component to be instantiated inside a HTML template.
(ChartPaneBase.prototype._fetchAnalysisTasks): Moved from ChartPane._fetchAnalysisTasks.
(ChartPaneBase.prototype.platformId): Ditto.
(ChartPaneBase.prototype.metricId): Ditto.
(ChartPaneBase.prototype.setOverviewDomain): Ditto.
(ChartPaneBase.prototype.setMainDomain): Ditto.
(ChartPaneBase.prototype._overviewSelectionDidChange): Extracted from the constructor. This is overridden in
ChartPane and unused in AnalysisTaskChartPane.
(ChartPaneBase.prototype._mainSelectionDidChange): Extracted from ChartPane._mainSelectionDidChange.
(ChartPaneBase.prototype._mainSelectionDidZoom): Extracted from ChartPane._mainSelectionDidZoom.
(ChartPaneBase.prototype._indicatorDidChange): Extracted from ChartPane._indicatorDidChange.
(ChartPaneBase.prototype._didFetchData): Moved from ChartPane._fetchAnalysisTasks.
(ChartPaneBase.prototype._openAnalysisTask): Ditto.
(ChartPaneBase.prototype._openCommitViewer): Ditto. Also fixed a bug that we don't show the spinner while
waiting for the data to be fetched by calling this.render() here.
(ChartPaneBase.prototype._keyup): Moved from ChartPane._keyup. Also fixed the bug that the revisions list
doesn't update by calling this.render() here.
(ChartPaneBase.prototype.render): Extracted from ChartPane.render.
(ChartPaneBase.htmlTemplate): Extracted from ChartPane.htmlTemplate.
(ChartPaneBase.paneHeaderTemplate): Added. This is overridden in ChartPane and unused in AnalysisTaskChartPane.
(ChartPaneBase.cssTemplate): Extracted from ChartPane.htmlTemplate.

* public/v3/components/chart-styles.js: Renamed from public/v3/pages/page-with-charts.js.
(PageWithCharts): Renamed from PageWithCharts since it no longer extends PageWithHeading.
(ChartStyles.createChartSourceList):

* public/v3/components/commit-log-viewer.js:
(CommitLogViewer.prototype.view): Set this._repository right away instead of waiting for the fetched data
so that spinner will be shown while the data is being fetched.

* public/v3/index.html:

* public/v3/pages/analysis-task-page.js:
(AnalysisTaskChartPane): Added extends ChartPaneBase.
(AnalysisTaskPage): Added. this._chartPane.
(AnalysisTaskPage.prototype._didFetchTask): Initialize this._chartPane with a domain.
(AnalysisTaskPage.prototype.render): Render this._chartPane.
(AnalysisTaskPage.htmlTemplate):

* public/v3/pages/chart-pane-status-view.js:
(ChartPaneStatusView): Removed the unused router from the argument list.
(ChartPaneStatusView.prototype.pointsRangeForAnalysis): Renamed from analyzeData() since it was ambiguous.
(ChartPaneStatusView.prototype.moveRepositoryWithNotification): Fixed the bug that we don't update the list
of the revisions here.
(ChartPaneStatusView.prototype.computeChartStatusLabels):

* public/v3/pages/chart-pane.js:
(ChartPane): Now extends ChartPaneBase. 
(ChartPane.prototype._overviewSelectionDidChange): Extracted from the constructor.
(ChartPane.prototype._mainSelectionDidChange): 
(ChartPane.prototype._mainSelectionDidZoom):
(ChartPane.prototype._indicatorDidChange):
(ChartPane.prototype.render):
(ChartPane.prototype._renderActionToolbar):
(ChartPane.paneHeaderTemplate): Extracted from htmlTemplate.
(ChartPane.cssTemplate):
(ChartPane.overviewOptions.selection.onchange): Deleted.
(ChartPane.prototype._fetchAnalysisTasks): Deleted.
(ChartPane.prototype.platformId): Deleted.
(ChartPane.prototype.metricId): Deleted.
(ChartPane.prototype.setOverviewDomain): Deleted.
(ChartPane.prototype.setMainDomain): Deleted.
(ChartPane.prototype._openCommitViewer): Deleted.
(ChartPane.prototype._didFetchData): Deleted.
(ChartPane.prototype._keyup): Deleted.

* public/v3/pages/charts-page.js:
(ChartsPage):
(ChartsPage.createDomainForAnalysisTask): Extracted by createDomainForAnalysisTask; used to set the domain
of the charts in the analysis task page.
(ChartsPage.createStateForAnalysisTask):

* public/v3/pages/dashboard-page.js:
(DashboardPage):
(DashboardPage.prototype._createChartForCell):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgChangeLog">trunk/Websites/perf.webkit.org/ChangeLog</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3componentsbasejs">trunk/Websites/perf.webkit.org/public/v3/components/base.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3componentscommitlogviewerjs">trunk/Websites/perf.webkit.org/public/v3/components/commit-log-viewer.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3indexhtml">trunk/Websites/perf.webkit.org/public/v3/index.html</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3pagesanalysistaskpagejs">trunk/Websites/perf.webkit.org/public/v3/pages/analysis-task-page.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3pageschartpanestatusviewjs">trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane-status-view.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3pageschartpanejs">trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3pageschartspagejs">trunk/Websites/perf.webkit.org/public/v3/pages/charts-page.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3pagesdashboardpagejs">trunk/Websites/perf.webkit.org/public/v3/pages/dashboard-page.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3componentschartpanebasejs">trunk/Websites/perf.webkit.org/public/v3/components/chart-pane-base.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3componentschartstylesjs">trunk/Websites/perf.webkit.org/public/v3/components/chart-styles.js</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgpublicv3pagespagewithchartsjs">trunk/Websites/perf.webkit.org/public/v3/pages/page-with-charts.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkWebsitesperfwebkitorgChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/ChangeLog (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/ChangeLog        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/ChangeLog        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -1,3 +1,96 @@
</span><ins>+2016-02-09  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Analysis task page on v3 UI should show charts
+        https://bugs.webkit.org/show_bug.cgi?id=154057
+
+        Reviewed by Chris Dumez.
+
+        Extracted ChartPaneBase out of ChartPane and added an instance of its new subclass, AnalysisTaskChartPane,
+        to the analysis task page. The main difference is that ChartPaneBase doesn't depend on the presence of
+        this._chartsPage unlike ChartPane. It also doesn't have the header with toolbar (to show breakdown, etc...).
+
+        * public/v3/components/base.js:
+        (ComponentBase.prototype._constructShadowTree): Call htmlTemplate() and cssTemplate() with the right &quot;this&quot;.
+
+        * public/v3/components/chart-pane-base.js: Added.
+        (ChartPaneBase): Extracted from ChartPane.
+        (ChartPaneBase.prototype.configure): Extracted from the constructor. Separating this function allows the
+        component to be instantiated inside a HTML template.
+        (ChartPaneBase.prototype._fetchAnalysisTasks): Moved from ChartPane._fetchAnalysisTasks.
+        (ChartPaneBase.prototype.platformId): Ditto.
+        (ChartPaneBase.prototype.metricId): Ditto.
+        (ChartPaneBase.prototype.setOverviewDomain): Ditto.
+        (ChartPaneBase.prototype.setMainDomain): Ditto.
+        (ChartPaneBase.prototype._overviewSelectionDidChange): Extracted from the constructor. This is overridden in
+        ChartPane and unused in AnalysisTaskChartPane.
+        (ChartPaneBase.prototype._mainSelectionDidChange): Extracted from ChartPane._mainSelectionDidChange.
+        (ChartPaneBase.prototype._mainSelectionDidZoom): Extracted from ChartPane._mainSelectionDidZoom.
+        (ChartPaneBase.prototype._indicatorDidChange): Extracted from ChartPane._indicatorDidChange.
+        (ChartPaneBase.prototype._didFetchData): Moved from ChartPane._fetchAnalysisTasks.
+        (ChartPaneBase.prototype._openAnalysisTask): Ditto.
+        (ChartPaneBase.prototype._openCommitViewer): Ditto. Also fixed a bug that we don't show the spinner while
+        waiting for the data to be fetched by calling this.render() here.
+        (ChartPaneBase.prototype._keyup): Moved from ChartPane._keyup. Also fixed the bug that the revisions list
+        doesn't update by calling this.render() here.
+        (ChartPaneBase.prototype.render): Extracted from ChartPane.render.
+        (ChartPaneBase.htmlTemplate): Extracted from ChartPane.htmlTemplate.
+        (ChartPaneBase.paneHeaderTemplate): Added. This is overridden in ChartPane and unused in AnalysisTaskChartPane.
+        (ChartPaneBase.cssTemplate): Extracted from ChartPane.htmlTemplate.
+
+        * public/v3/components/chart-styles.js: Renamed from public/v3/pages/page-with-charts.js.
+        (PageWithCharts): Renamed from PageWithCharts since it no longer extends PageWithHeading.
+        (ChartStyles.createChartSourceList):
+
+        * public/v3/components/commit-log-viewer.js:
+        (CommitLogViewer.prototype.view): Set this._repository right away instead of waiting for the fetched data
+        so that spinner will be shown while the data is being fetched.
+
+        * public/v3/index.html:
+
+        * public/v3/pages/analysis-task-page.js:
+        (AnalysisTaskChartPane): Added extends ChartPaneBase.
+        (AnalysisTaskPage): Added. this._chartPane.
+        (AnalysisTaskPage.prototype._didFetchTask): Initialize this._chartPane with a domain.
+        (AnalysisTaskPage.prototype.render): Render this._chartPane.
+        (AnalysisTaskPage.htmlTemplate):
+
+        * public/v3/pages/chart-pane-status-view.js:
+        (ChartPaneStatusView): Removed the unused router from the argument list.
+        (ChartPaneStatusView.prototype.pointsRangeForAnalysis): Renamed from analyzeData() since it was ambiguous.
+        (ChartPaneStatusView.prototype.moveRepositoryWithNotification): Fixed the bug that we don't update the list
+        of the revisions here.
+        (ChartPaneStatusView.prototype.computeChartStatusLabels):
+
+        * public/v3/pages/chart-pane.js:
+        (ChartPane): Now extends ChartPaneBase. 
+        (ChartPane.prototype._overviewSelectionDidChange): Extracted from the constructor.
+        (ChartPane.prototype._mainSelectionDidChange): 
+        (ChartPane.prototype._mainSelectionDidZoom):
+        (ChartPane.prototype._indicatorDidChange):
+        (ChartPane.prototype.render):
+        (ChartPane.prototype._renderActionToolbar):
+        (ChartPane.paneHeaderTemplate): Extracted from htmlTemplate.
+        (ChartPane.cssTemplate):
+        (ChartPane.overviewOptions.selection.onchange): Deleted.
+        (ChartPane.prototype._fetchAnalysisTasks): Deleted.
+        (ChartPane.prototype.platformId): Deleted.
+        (ChartPane.prototype.metricId): Deleted.
+        (ChartPane.prototype.setOverviewDomain): Deleted.
+        (ChartPane.prototype.setMainDomain): Deleted.
+        (ChartPane.prototype._openCommitViewer): Deleted.
+        (ChartPane.prototype._didFetchData): Deleted.
+        (ChartPane.prototype._keyup): Deleted.
+
+        * public/v3/pages/charts-page.js:
+        (ChartsPage):
+        (ChartsPage.createDomainForAnalysisTask): Extracted by createDomainForAnalysisTask; used to set the domain
+        of the charts in the analysis task page.
+        (ChartsPage.createStateForAnalysisTask):
+
+        * public/v3/pages/dashboard-page.js:
+        (DashboardPage):
+        (DashboardPage.prototype._createChartForCell):
+
</ins><span class="cx"> 2016-02-10  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Add the support for maintenance mode
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3componentsbasejs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/v3/components/base.js (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/components/base.js        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/components/base.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -39,14 +39,14 @@
</span><span class="cx"> 
</span><span class="cx">         if (htmlTemplate) {
</span><span class="cx">             var template = document.createElement('template');
</span><del>-            template.innerHTML = htmlTemplate();
</del><ins>+            template.innerHTML = newTarget.htmlTemplate();
</ins><span class="cx">             shadow.appendChild(template.content.cloneNode(true));
</span><span class="cx">             this._recursivelyReplaceUnknownElementsByComponents(shadow);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (cssTemplate) {
</span><span class="cx">             var style = document.createElement('style');
</span><del>-            style.textContent = cssTemplate();
</del><ins>+            style.textContent = newTarget.cssTemplate();
</ins><span class="cx">             shadow.appendChild(style);
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3componentschartpanebasejs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v3/components/chart-pane-base.js (0 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/components/chart-pane-base.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v3/components/chart-pane-base.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -0,0 +1,612 @@
</span><ins>+
+class ChartPaneBase extends ComponentBase {
+
+    constructor(name)
+    {
+        super(name);
+
+        this._errorMessage = null;
+        this._platformId = null;
+        this._metricId = null;
+        this._platform = null;
+        this._metric = null;
+
+        this._overviewChart = null;
+        this._mainChart = null;
+        this._mainChartStatus = null;
+        this._commitLogViewer = null;
+    }
+
+    configure(platformId, metricId)
+    {
+        var result = ChartStyles.createChartSourceList(platformId, metricId);
+        this._errorMessage = result.error;
+        this._platformId = platformId;
+        this._metricId = metricId;
+        this._platform = result.platform;
+        this._metric = result.metric;
+
+        this._overviewChart = null;
+        this._mainChart = null;
+        this._mainChartStatus = null;
+
+        this._commitLogViewer = this.content().querySelector('commit-log-viewer').component();
+
+        if (result.error)
+            return;
+
+        var formatter = result.metric.makeFormatter(4);
+        var self = this;
+
+        var overviewOptions = ChartStyles.overviewChartOptions(formatter);
+        overviewOptions.selection.onchange = this._overviewSelectionDidChange.bind(this);
+
+        this._overviewChart = new InteractiveTimeSeriesChart(result.sourceList, overviewOptions);
+        this.renderReplace(this.content().querySelector('.chart-pane-overview'), this._overviewChart);
+
+        var mainOptions = ChartStyles.mainChartOptions(formatter);
+        mainOptions.indicator.onchange = this._indicatorDidChange.bind(this);
+        mainOptions.selection.onchange = this._mainSelectionDidChange.bind(this);
+        mainOptions.selection.onzoom = this._mainSelectionDidZoom.bind(this);
+        mainOptions.annotations.onclick = this._openAnalysisTask.bind(this);
+        mainOptions.ondata = this._didFetchData.bind(this);
+        this._mainChart = new InteractiveTimeSeriesChart(result.sourceList, mainOptions);
+        this.renderReplace(this.content().querySelector('.chart-pane-main'), this._mainChart);
+
+        this._mainChartStatus = new ChartPaneStatusView(result.metric, this._mainChart, this._openCommitViewer.bind(this));
+        this.renderReplace(this.content().querySelector('.chart-pane-details'), this._mainChartStatus);
+
+        this.content().querySelector('.chart-pane').addEventListener('keyup', this._keyup.bind(this));
+
+        this._fetchAnalysisTasks(platformId, metricId);
+    }
+
+    _fetchAnalysisTasks(platformId, metricId)
+    {
+        var self = this;
+        AnalysisTask.fetchByPlatformAndMetric(platformId, metricId).then(function (tasks) {
+            self._mainChart.setAnnotations(tasks.map(function (task) {
+                var fillStyle = '#fc6';
+                switch (task.changeType()) {
+                case 'inconclusive':
+                    fillStyle = '#fcc';
+                case 'progression':
+                    fillStyle = '#39f';
+                    break;
+                case 'regression':
+                    fillStyle = '#c60';
+                    break;
+                case 'unchanged':
+                    fillStyle = '#ccc';
+                    break;
+                }
+
+                return {
+                    task: task,
+                    startTime: task.startTime(),
+                    endTime: task.endTime(),
+                    label: task.label(),
+                    fillStyle: fillStyle,
+                };
+            }));
+        });
+    }
+
+    platformId() { return this._platformId; }
+    metricId() { return this._metricId; }
+
+    setOverviewDomain(startTime, endTime)
+    {
+        if (this._overviewChart)
+            this._overviewChart.setDomain(startTime, endTime);
+    }
+
+    setMainDomain(startTime, endTime)
+    {
+        if (this._mainChart)
+            this._mainChart.setDomain(startTime, endTime);
+    }
+
+    _overviewSelectionDidChange(domain, didEndDrag) { }
+
+    _mainSelectionDidChange(selection, didEndDrag)
+    {
+        this.render();
+    }
+
+    _mainSelectionDidZoom(selection)
+    {
+        this._overviewChart.setSelection(selection, this);
+        this._mainChart.setSelection(null);
+        this.render();
+    }
+
+    _indicatorDidChange(indicatorID, isLocked)
+    {
+        this._mainChartStatus.updateRevisionListWithNotification();
+        this.render();
+    }
+
+    _didFetchData()
+    {
+        this._mainChartStatus.updateRevisionListWithNotification();
+        this.render();
+    }
+
+    _openAnalysisTask()
+    { }
+
+    _openCommitViewer(repository, from, to)
+    {
+        this._mainChartStatus.setCurrentRepository(repository);
+        this._commitLogViewer.view(repository, from, to).then(this.render.bind(this));
+        this.render();
+    }
+
+    _keyup(event)
+    {
+        switch (event.keyCode) {
+        case 37: // Left
+            if (!this._mainChart.moveLockedIndicatorWithNotification(false))
+                return;
+            break;
+        case 39: // Right
+            if (!this._mainChart.moveLockedIndicatorWithNotification(true))
+                return;
+            break;
+        case 38: // Up
+            if (!this._mainChartStatus.moveRepositoryWithNotification(false))
+                return;
+        case 40: // Down
+            if (!this._mainChartStatus.moveRepositoryWithNotification(true))
+                return;
+        default:
+            return;
+        }
+
+        this.render();
+
+        event.preventDefault();
+        event.stopPropagation();
+    }
+
+    render()
+    {
+        Instrumentation.startMeasuringTime('ChartPane', 'render');
+
+        super.render();
+
+        if (this._errorMessage) {
+            this.renderReplace(this.content().querySelector('.chart-pane-main'), this._errorMessage);
+            return;
+        }
+
+        if (this._mainChartStatus)
+            this._mainChartStatus.render();
+
+        var body = this.content().querySelector('.chart-pane-body');
+        if (this._commitLogViewer &amp;&amp; this._commitLogViewer.currentRepository()) {
+            body.classList.add('has-second-sidebar');
+            this._commitLogViewer.render();
+        } else
+            body.classList.remove('has-second-sidebar');
+
+        Instrumentation.endMeasuringTime('ChartPane', 'render');
+    }
+
+    static htmlTemplate()
+    {
+        return `
+            &lt;section class=&quot;chart-pane&quot; tabindex=&quot;0&quot;&gt;
+                ${this.paneHeaderTemplate()}
+                &lt;div class=&quot;chart-pane-body&quot;&gt;
+                    &lt;div class=&quot;chart-pane-main&quot;&gt;&lt;/div&gt;
+                    &lt;div class=&quot;chart-pane-sidebar&quot;&gt;
+                        &lt;div class=&quot;chart-pane-overview&quot;&gt;&lt;/div&gt;
+                        &lt;div class=&quot;chart-pane-details&quot;&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class=&quot;chart-pane-second-sidebar&quot;&gt;
+                        &lt;commit-log-viewer&gt;&lt;/commit-log-viewer&gt;
+                    &lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/section&gt;
+        `;
+    }
+
+    static paneHeaderTemplate() { return ''; }
+
+    static cssTemplate()
+    {
+        return Toolbar.cssTemplate() + `
+            .chart-pane {
+                margin: 1rem;
+                margin-bottom: 2rem;
+                padding: 0rem;
+                height: 18rem;
+                outline: none;
+            }
+
+            .chart-pane:focus .chart-pane-header {
+                background: rgba(204, 153, 51, 0.1);
+            }
+
+            .chart-pane-body {
+                position: relative;
+                width: 100%;
+                height: 100%;
+            }
+
+            .chart-pane-main {
+                padding-right: 20rem;
+                height: 100%;
+                margin: 0;
+                vertical-align: middle;
+                text-align: center;
+            }
+
+            .has-second-sidebar .chart-pane-main {
+                padding-right: 40rem;
+            }
+
+            .chart-pane-main &gt; * {
+                width: 100%;
+                height: 100%;
+            }
+
+            .chart-pane-sidebar,
+            .chart-pane-second-sidebar {
+                position: absolute;
+                right: 0;
+                top: 0;
+                width: 0;
+                border-left: solid 1px #ccc;
+                height: 100%;
+            }
+
+            :not(.has-second-sidebar) &gt; .chart-pane-second-sidebar {
+                border-left: 0;
+            }
+
+            .chart-pane-sidebar {
+                width: 20rem;
+            }
+
+            .has-second-sidebar .chart-pane-sidebar {
+                right: 20rem;
+            }
+
+            .has-second-sidebar .chart-pane-second-sidebar {
+                width: 20rem;
+            }
+
+            .chart-pane-overview {
+                width: 100%;
+                height: 5rem;
+                border-bottom: solid 1px #ccc;
+            }
+
+            .chart-pane-overview &gt; * {
+                display: block;
+                width: 100%;
+                height: 100%;
+            }
+
+            .chart-pane-details {
+                position: relative;
+                display: block;
+                height: calc(100% - 5.5rem - 2px);
+                overflow-y: scroll;
+                padding-top: 0.5rem;
+            }
+        `;
+    }
+
+}
+
+class ChartPaneBase extends ComponentBase {
+
+    constructor(name)
+    {
+        super(name);
+
+        this._errorMessage = null;
+        this._platformId = null;
+        this._metricId = null;
+        this._platform = null;
+        this._metric = null;
+
+        this._overviewChart = null;
+        this._mainChart = null;
+        this._mainChartStatus = null;
+        this._commitLogViewer = null;
+    }
+
+    configure(platformId, metricId)
+    {
+        var result = ChartStyles.createChartSourceList(platformId, metricId);
+        this._errorMessage = result.error;
+        this._platformId = platformId;
+        this._metricId = metricId;
+        this._platform = result.platform;
+        this._metric = result.metric;
+
+        this._overviewChart = null;
+        this._mainChart = null;
+        this._mainChartStatus = null;
+
+        this._commitLogViewer = this.content().querySelector('commit-log-viewer').component();
+
+        if (result.error)
+            return;
+
+        var formatter = result.metric.makeFormatter(4);
+        var self = this;
+
+        var overviewOptions = ChartStyles.overviewChartOptions(formatter);
+        overviewOptions.selection.onchange = this._overviewSelectionDidChange.bind(this);
+
+        this._overviewChart = new InteractiveTimeSeriesChart(result.sourceList, overviewOptions);
+        this.renderReplace(this.content().querySelector('.chart-pane-overview'), this._overviewChart);
+
+        var mainOptions = ChartStyles.mainChartOptions(formatter);
+        mainOptions.indicator.onchange = this._indicatorDidChange.bind(this);
+        mainOptions.selection.onchange = this._mainSelectionDidChange.bind(this);
+        mainOptions.selection.onzoom = this._mainSelectionDidZoom.bind(this);
+        mainOptions.annotations.onclick = this._openAnalysisTask.bind(this);
+        mainOptions.ondata = this._didFetchData.bind(this);
+        this._mainChart = new InteractiveTimeSeriesChart(result.sourceList, mainOptions);
+        this.renderReplace(this.content().querySelector('.chart-pane-main'), this._mainChart);
+
+        this._mainChartStatus = new ChartPaneStatusView(result.metric, this._mainChart, this._openCommitViewer.bind(this));
+        this.renderReplace(this.content().querySelector('.chart-pane-details'), this._mainChartStatus);
+
+        this.content().querySelector('.chart-pane').addEventListener('keyup', this._keyup.bind(this));
+
+        this._fetchAnalysisTasks(platformId, metricId);
+    }
+
+    _fetchAnalysisTasks(platformId, metricId)
+    {
+        var self = this;
+        AnalysisTask.fetchByPlatformAndMetric(platformId, metricId).then(function (tasks) {
+            self._mainChart.setAnnotations(tasks.map(function (task) {
+                var fillStyle = '#fc6';
+                switch (task.changeType()) {
+                case 'inconclusive':
+                    fillStyle = '#fcc';
+                case 'progression':
+                    fillStyle = '#39f';
+                    break;
+                case 'regression':
+                    fillStyle = '#c60';
+                    break;
+                case 'unchanged':
+                    fillStyle = '#ccc';
+                    break;
+                }
+
+                return {
+                    task: task,
+                    startTime: task.startTime(),
+                    endTime: task.endTime(),
+                    label: task.label(),
+                    fillStyle: fillStyle,
+                };
+            }));
+        });
+    }
+
+    platformId() { return this._platformId; }
+    metricId() { return this._metricId; }
+
+    setOverviewDomain(startTime, endTime)
+    {
+        if (this._overviewChart)
+            this._overviewChart.setDomain(startTime, endTime);
+    }
+
+    setMainDomain(startTime, endTime)
+    {
+        if (this._mainChart)
+            this._mainChart.setDomain(startTime, endTime);
+    }
+
+    _overviewSelectionDidChange(domain, didEndDrag) { }
+
+    _mainSelectionDidChange(selection, didEndDrag)
+    {
+        this.render();
+    }
+
+    _mainSelectionDidZoom(selection)
+    {
+        this._overviewChart.setSelection(selection, this);
+        this._mainChart.setSelection(null);
+        this.render();
+    }
+
+    _indicatorDidChange(indicatorID, isLocked)
+    {
+        this._mainChartStatus.updateRevisionListWithNotification();
+        this.render();
+    }
+
+    _didFetchData()
+    {
+        this._mainChartStatus.updateRevisionListWithNotification();
+        this.render();
+    }
+
+    _openAnalysisTask()
+    { }
+
+    _openCommitViewer(repository, from, to)
+    {
+        this._mainChartStatus.setCurrentRepository(repository);
+        this._commitLogViewer.view(repository, from, to).then(this.render.bind(this));
+        this.render();
+    }
+
+    _keyup(event)
+    {
+        switch (event.keyCode) {
+        case 37: // Left
+            if (!this._mainChart.moveLockedIndicatorWithNotification(false))
+                return;
+            break;
+        case 39: // Right
+            if (!this._mainChart.moveLockedIndicatorWithNotification(true))
+                return;
+            break;
+        case 38: // Up
+            if (!this._mainChartStatus.moveRepositoryWithNotification(false))
+                return;
+        case 40: // Down
+            if (!this._mainChartStatus.moveRepositoryWithNotification(true))
+                return;
+        default:
+            return;
+        }
+
+        this.render();
+
+        event.preventDefault();
+        event.stopPropagation();
+    }
+
+    render()
+    {
+        Instrumentation.startMeasuringTime('ChartPane', 'render');
+
+        super.render();
+
+        if (this._errorMessage) {
+            this.renderReplace(this.content().querySelector('.chart-pane-main'), this._errorMessage);
+            return;
+        }
+
+        if (this._mainChartStatus) {
+            this._mainChartStatus.render();
+            this._renderActionToolbar();
+        }
+
+        var body = this.content().querySelector('.chart-pane-body');
+        if (this._commitLogViewer &amp;&amp; this._commitLogViewer.currentRepository()) {
+            body.classList.add('has-second-sidebar');
+            this._commitLogViewer.render();
+        } else
+            body.classList.remove('has-second-sidebar');
+
+        Instrumentation.endMeasuringTime('ChartPane', 'render');
+    }
+    
+    _renderActionToolbar() { }
+
+    static htmlTemplate()
+    {
+        return `
+            &lt;section class=&quot;chart-pane&quot; tabindex=&quot;0&quot;&gt;
+                ${this.paneHeaderTemplate()}
+                &lt;div class=&quot;chart-pane-body&quot;&gt;
+                    &lt;div class=&quot;chart-pane-main&quot;&gt;&lt;/div&gt;
+                    &lt;div class=&quot;chart-pane-sidebar&quot;&gt;
+                        &lt;div class=&quot;chart-pane-overview&quot;&gt;&lt;/div&gt;
+                        &lt;div class=&quot;chart-pane-details&quot;&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class=&quot;chart-pane-second-sidebar&quot;&gt;
+                        &lt;commit-log-viewer&gt;&lt;/commit-log-viewer&gt;
+                    &lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/section&gt;
+        `;
+    }
+
+    static paneHeaderTemplate() { return ''; }
+
+    static cssTemplate()
+    {
+        return Toolbar.cssTemplate() + `
+            .chart-pane {
+                margin: 1rem;
+                margin-bottom: 2rem;
+                padding: 0rem;
+                height: 18rem;
+                outline: none;
+            }
+
+            .chart-pane:focus .chart-pane-header {
+                background: rgba(204, 153, 51, 0.1);
+            }
+
+            .chart-pane-body {
+                position: relative;
+                width: 100%;
+                height: 100%;
+            }
+
+            .chart-pane-main {
+                padding-right: 20rem;
+                height: 100%;
+                margin: 0;
+                vertical-align: middle;
+                text-align: center;
+            }
+
+            .has-second-sidebar .chart-pane-main {
+                padding-right: 40rem;
+            }
+
+            .chart-pane-main &gt; * {
+                width: 100%;
+                height: 100%;
+            }
+
+            .chart-pane-sidebar,
+            .chart-pane-second-sidebar {
+                position: absolute;
+                right: 0;
+                top: 0;
+                width: 0;
+                border-left: solid 1px #ccc;
+                height: 100%;
+            }
+
+            :not(.has-second-sidebar) &gt; .chart-pane-second-sidebar {
+                border-left: 0;
+            }
+
+            .chart-pane-sidebar {
+                width: 20rem;
+            }
+
+            .has-second-sidebar .chart-pane-sidebar {
+                right: 20rem;
+            }
+
+            .has-second-sidebar .chart-pane-second-sidebar {
+                width: 20rem;
+            }
+
+            .chart-pane-overview {
+                width: 100%;
+                height: 5rem;
+                border-bottom: solid 1px #ccc;
+            }
+
+            .chart-pane-overview &gt; * {
+                display: block;
+                width: 100%;
+                height: 100%;
+            }
+
+            .chart-pane-details {
+                position: relative;
+                display: block;
+                height: calc(100% - 5.5rem - 2px);
+                overflow-y: scroll;
+                padding-top: 0.5rem;
+            }
+        `;
+    }
+
+}
</ins></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3componentschartstylesjsfromrev196350trunkWebsitesperfwebkitorgpublicv3pagespagewithchartsjs"></a>
<div class="copfile"><h4>Copied: trunk/Websites/perf.webkit.org/public/v3/components/chart-styles.js (from rev 196350, trunk/Websites/perf.webkit.org/public/v3/pages/page-with-charts.js) (0 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/components/chart-styles.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v3/components/chart-styles.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -0,0 +1,126 @@
</span><ins>+
+class ChartStyles {
+    static createChartSourceList(platformId, metricId)
+    {
+        var platform = Platform.findById(platformId);
+        var metric = Metric.findById(metricId);
+        if (!platform || !metric)
+            return {error: `Invalid platform or metric: ${platformId} and ${metricId}`};
+
+        var lastModified = platform.lastModified(metric);
+        if (!lastModified)
+            return {platform: platform, metric: metric, error: `No results on ${platform.name()}`};
+
+        var measurementSet = MeasurementSet.findSet(platform.id(), metric.id(), lastModified);
+        var sourceList = [
+            this.baselineStyle(measurementSet, 'baseline'),
+            this.targetStyle(measurementSet, 'target'),
+            this.currentStyle(measurementSet, 'current'),
+        ];
+
+        return {
+            platform: platform,
+            metric: metric,
+            sourceList: sourceList,
+        };
+    }
+
+    static baselineStyle(measurementSet)
+    {
+        return {
+            measurementSet: measurementSet,
+            extendToFuture: true,
+            sampleData: true,
+            type: 'baseline',
+            pointStyle: '#f33',
+            pointRadius: 2,
+            lineStyle: '#f99',
+            lineWidth: 1.5,
+            intervalStyle: '#fdd',
+            intervalWidth: 2,
+        };
+    }
+
+    static targetStyle(measurementSet)
+    {
+        return {
+            measurementSet: measurementSet,
+            extendToFuture: true,
+            sampleData: true,
+            type: 'target',
+            pointStyle: '#33f',
+            pointRadius: 2,
+            lineStyle: '#99f',
+            lineWidth: 1.5,
+            intervalStyle: '#ddf',
+            intervalWidth: 2,
+        };
+    }
+
+    static currentStyle(measurementSet)
+    {
+        return {
+            measurementSet: measurementSet,
+            sampleData: true,
+            type: 'current',
+            pointStyle: '#333',
+            pointRadius: 2,
+            lineStyle: '#999',
+            lineWidth: 1.5,
+            intervalStyle: '#ddd',
+            intervalWidth: 2,
+            interactive: true,
+        };
+    }
+
+    static dashboardOptions(valueFormatter)
+    {
+        return {
+            updateOnRequestAnimationFrame: true,
+            axis: {
+                yAxisWidth: 4, // rem
+                xAxisHeight: 2, // rem
+                gridStyle: '#ddd',
+                fontSize: 0.8, // rem
+                valueFormatter: valueFormatter,
+            },
+        };
+    }
+
+    static overviewChartOptions(valueFormatter)
+    {
+        var options = this.dashboardOptions(valueFormatter);
+        options.axis.yAxisWidth = 0; // rem
+        options.selection = {
+            lineStyle: '#f93',
+            lineWidth: 2,
+            fillStyle: 'rgba(153, 204, 102, .125)',
+        }
+        return options;
+    }
+
+    static mainChartOptions(valueFormatter)
+    {
+        var options = this.dashboardOptions(valueFormatter);
+        options.axis.xAxisEndPadding = 5;
+        options.axis.yAxisWidth = 5;
+        options.selection = {
+            lineStyle: '#f93',
+            lineWidth: 2,
+            fillStyle: 'rgba(153, 204, 102, .125)',
+        }
+        options.indicator = {
+            lineStyle: '#f93',
+            lineWidth: 2,
+            pointRadius: 3,
+        };
+        options.annotations = {
+            textStyle: '#000',
+            textBackground: '#fff',
+            minWidth: 3,
+            barHeight: 7,
+            barSpacing: 2,
+        };
+        return options;
+    }
+}
</ins></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3componentscommitlogviewerjs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/v3/components/commit-log-viewer.js (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/components/commit-log-viewer.js        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/components/commit-log-viewer.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx">         var promise = CommitLog.fetchBetweenRevisions(repository, from || to, to);
</span><span class="cx"> 
</span><ins>+        this._repository = repository;
</ins><span class="cx">         this._fetchingPromise = promise;
</span><span class="cx"> 
</span><span class="cx">         var self = this;
</span><span class="lines">@@ -39,7 +40,6 @@
</span><span class="cx">             clearTimeout(spinnerTimer);
</span><span class="cx">             if (self._fetchingPromise != promise)
</span><span class="cx">                 return;
</span><del>-            self._repository = repository;
</del><span class="cx">             self._fetchingPromise = null;
</span><span class="cx">             self._commits = commits;
</span><span class="cx">         });
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3indexhtml"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/v3/index.html (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/index.html        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/index.html        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -74,12 +74,13 @@
</span><span class="cx">         &lt;script src=&quot;components/results-table.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">         &lt;script src=&quot;components/analysis-results-viewer.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">         &lt;script src=&quot;components/test-group-results-table.js&quot;&gt;&lt;/script&gt;
</span><ins>+        &lt;script src=&quot;components/chart-styles.js&quot;&gt;&lt;/script&gt;
+        &lt;script src=&quot;components/chart-pane-base.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">         &lt;script src=&quot;pages/page.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">         &lt;script src=&quot;pages/page-router.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">         &lt;script src=&quot;pages/heading.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">         &lt;script src=&quot;pages/toolbar.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">         &lt;script src=&quot;pages/page-with-heading.js&quot;&gt;&lt;/script&gt;
</span><del>-        &lt;script src=&quot;pages/page-with-charts.js&quot;&gt;&lt;/script&gt;
</del><span class="cx">         &lt;script src=&quot;pages/domain-control-toolbar.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">         &lt;script src=&quot;pages/dashboard-toolbar.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">         &lt;script src=&quot;pages/dashboard-page.js&quot;&gt;&lt;/script&gt;
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3pagesanalysistaskpagejs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/v3/pages/analysis-task-page.js (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/pages/analysis-task-page.js        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/analysis-task-page.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -1,4 +1,10 @@
</span><span class="cx"> 
</span><ins>+class AnalysisTaskChartPane extends ChartPaneBase {
+    constructor() { super('analysis-task-chart-pane'); }
+}
+
+ComponentBase.defineElement('analysis-task-chart-pane', AnalysisTaskChartPane);
+
</ins><span class="cx"> class AnalysisTaskPage extends PageWithHeading {
</span><span class="cx">     constructor()
</span><span class="cx">     {
</span><span class="lines">@@ -14,6 +20,7 @@
</span><span class="cx">         this._endPoint = null;
</span><span class="cx">         this._errorMessage = null;
</span><span class="cx">         this._currentTestGroup = null;
</span><ins>+        this._chartPane = this.content().querySelector('analysis-task-chart-pane').component();
</ins><span class="cx">         this._analysisResultsViewer = this.content().querySelector('analysis-results-viewer').component();
</span><span class="cx">         this._analysisResultsViewer.setTestGroupCallback(this._showTestGroup.bind(this));
</span><span class="cx">         this._testGroupResultsTable = this.content().querySelector('test-group-results-table').component();
</span><span class="lines">@@ -62,6 +69,12 @@
</span><span class="cx">         this._analysisResultsViewer.setSmallerIsBetter(metric.isSmallerBetter());
</span><span class="cx">         this._testGroupResultsTable.setValueFormatter(formatter);
</span><span class="cx"> 
</span><ins>+        this._chartPane.configure(platform.id(), metric.id());
+
+        var domain = ChartsPage.createDomainForAnalysisTask(task);
+        this._chartPane.setOverviewDomain(domain[0], domain[1]);
+        this._chartPane.setMainDomain(domain[0], domain[1]);
+
</ins><span class="cx">         this.render();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -128,6 +141,8 @@
</span><span class="cx">         this.content().querySelector('.error-message').innerHTML +=
</span><span class="cx">             `&lt;p&gt;This page is read only for now. To schedule a new A/B testing job, use &lt;a href=&quot;${v2URL}&quot;&gt;v2 page&lt;/a&gt;.&lt;/p&gt;`;
</span><span class="cx"> 
</span><ins>+         this._chartPane.render();
+
</ins><span class="cx">         if (this._task) {
</span><span class="cx">             this.renderReplace(this.content().querySelector('.analysis-task-name'), this._task.name());
</span><span class="cx">             var platform = this._task.platform();
</span><span class="lines">@@ -187,7 +202,7 @@
</span><span class="cx">                 &lt;h2 class=&quot;analysis-task-name&quot;&gt;&lt;/h2&gt;
</span><span class="cx">                 &lt;h3 class=&quot;platform-metric-names&quot;&gt;&lt;a href=&quot;&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
</span><span class="cx">                 &lt;p class=&quot;error-message&quot;&gt;&lt;/p&gt;
</span><del>-                &lt;div class=&quot;overview-chart&quot;&gt;&lt;/div&gt;
</del><ins>+                &lt;div class=&quot;overview-chart&quot;&gt;&lt;analysis-task-chart-pane&gt;&lt;/analysis-task-chart-pane&gt;&lt;/div&gt;
</ins><span class="cx">                 &lt;section class=&quot;analysis-results-view&quot;&gt;
</span><span class="cx">                     &lt;analysis-results-viewer&gt;&lt;/analysis-results-viewer&gt;
</span><span class="cx">                 &lt;/section&gt;
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3pageschartpanestatusviewjs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane-status-view.js (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane-status-view.js        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane-status-view.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -1,19 +1,17 @@
</span><span class="cx"> 
</span><span class="cx"> class ChartPaneStatusView extends ChartStatusView {
</span><span class="cx">     
</span><del>-    constructor(metric, chart, router, revisionCallback)
</del><ins>+    constructor(metric, chart, revisionCallback)
</ins><span class="cx">     {
</span><span class="cx">         super(metric, chart);
</span><span class="cx"> 
</span><del>-        this._router = router;
-
</del><span class="cx">         this._buildLabel = null;
</span><span class="cx">         this._buildUrl = null;
</span><span class="cx"> 
</span><span class="cx">         this._revisionList = [];
</span><span class="cx">         this._currentRepository = null;
</span><span class="cx">         this._revisionCallback = revisionCallback;
</span><del>-        this._analyzeData = null;
</del><ins>+        this._pointsRangeForAnalysis = null;
</ins><span class="cx"> 
</span><span class="cx">         this._renderedRevisionList = null;
</span><span class="cx">         this._renderedRepository = null;
</span><span class="lines">@@ -21,7 +19,7 @@
</span><span class="cx">         this._usedRevisionRange = null;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    analyzeData() { return this._analyzeData; }
</del><ins>+    pointsRangeForAnalysis() { return this._pointsRangeForAnalysis; }
</ins><span class="cx"> 
</span><span class="cx">     render()
</span><span class="cx">     {
</span><span class="lines">@@ -101,6 +99,7 @@
</span><span class="cx"> 
</span><span class="cx">         var info = this._revisionList[newIndex];
</span><span class="cx">         this.setCurrentRepository(info.repository);
</span><ins>+        this.updateRevisionListWithNotification();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     updateRevisionListWithNotification()
</span><span class="lines">@@ -126,7 +125,7 @@
</span><span class="cx"> 
</span><span class="cx">         this._buildInfo = null;
</span><span class="cx">         this._revisionList = [];
</span><del>-        this._analyzeData = null;
</del><ins>+        this._pointsRangeForAnalysis = null;
</ins><span class="cx"> 
</span><span class="cx">         if (!currentPoint)
</span><span class="cx">             return;
</span><span class="lines">@@ -139,7 +138,7 @@
</span><span class="cx">             this._buildInfo = currentMeasurement;
</span><span class="cx"> 
</span><span class="cx">         if (currentPoint &amp;&amp; previousPoint &amp;&amp; this._chart.currentSelection()) {
</span><del>-            this._analyzeData = {
</del><ins>+            this._pointsRangeForAnalysis = {
</ins><span class="cx">                 startPointId: previousPoint.id,
</span><span class="cx">                 endPointId: currentPoint.id,
</span><span class="cx">             };
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3pageschartpanejs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane.js (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane.js        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/chart-pane.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -1,95 +1,18 @@
</span><span class="cx"> 
</span><del>-class ChartPane extends ComponentBase {
</del><ins>+class ChartPane extends ChartPaneBase {
</ins><span class="cx">     constructor(chartsPage, platformId, metricId)
</span><span class="cx">     {
</span><span class="cx">         super('chart-pane');
</span><span class="cx"> 
</span><del>-        this._chartsPage = chartsPage;
-        this._platformId = platformId;
-        this._metricId = metricId;
-
-        var result = ChartsPage.createChartSourceList(platformId, metricId);
-        this._errorMessage = result.error;
-        this._platform = result.platform;
-        this._metric = result.metric;
-
-        this._overviewChart = null;
-        this._mainChart = null;
-        this._mainChartStatus = null;
-        this._mainSelection = null;
</del><span class="cx">         this._mainChartIndicatorWasLocked = false;
</span><del>-        this._status = null;
-        this._revisions = null;
-
</del><ins>+        this._chartsPage = chartsPage;
</ins><span class="cx">         this._paneOpenedByClick = null;
</span><span class="cx"> 
</span><del>-        this._commitLogViewer = this.content().querySelector('commit-log-viewer').component();
</del><span class="cx">         this.content().querySelector('close-button').component().setCallback(chartsPage.closePane.bind(chartsPage, this));
</span><span class="cx"> 
</span><del>-        if (result.error)
-            return;
-
-        var formatter = result.metric.makeFormatter(4);
-        var self = this;
-
-        var overviewOptions = ChartsPage.overviewChartOptions(formatter);
-        overviewOptions.selection.onchange = function (domain, didEndDrag) {
-            self._chartsPage.setMainDomainFromOverviewSelection(domain, self, didEndDrag);
-        }
-
-        this._overviewChart = new InteractiveTimeSeriesChart(result.sourceList, overviewOptions);
-        this.renderReplace(this.content().querySelector('.chart-pane-overview'), this._overviewChart);
-
-        var mainOptions = ChartsPage.mainChartOptions(formatter);
-        mainOptions.indicator.onchange = this._indicatorDidChange.bind(this);
-        mainOptions.selection.onchange = this._mainSelectionDidChange.bind(this);
-        mainOptions.selection.onzoom = this._mainSelectionDidZoom.bind(this);
-        mainOptions.annotations.onclick = this._openAnalysisTask.bind(this);
-        mainOptions.ondata = this._didFetchData.bind(this);
-        this._mainChart = new InteractiveTimeSeriesChart(result.sourceList, mainOptions);
-        this.renderReplace(this.content().querySelector('.chart-pane-main'), this._mainChart);
-
-        this._mainChartStatus = new ChartPaneStatusView(result.metric, this._mainChart, chartsPage.router(), this._openCommitViewer.bind(this));
-        this.renderReplace(this.content().querySelector('.chart-pane-details'), this._mainChartStatus);
-
-        this.content().querySelector('.chart-pane').addEventListener('keyup', this._keyup.bind(this));
-        this._fetchAnalysisTasks();
</del><ins>+        this.configure(platformId, metricId);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    _fetchAnalysisTasks()
-    {
-        var self = this;
-        AnalysisTask.fetchByPlatformAndMetric(this._platformId, this._metricId).then(function (tasks) {
-            self._mainChart.setAnnotations(tasks.map(function (task) {
-                var fillStyle = '#fc6';
-                switch (task.changeType()) {
-                case 'inconclusive':
-                    fillStyle = '#fcc';
-                case 'progression':
-                    fillStyle = '#39f';
-                    break;
-                case 'regression':
-                    fillStyle = '#c60';
-                    break;
-                case 'unchanged':
-                    fillStyle = '#ccc';
-                    break;
-                }
-
-                return {
-                    task: task,
-                    startTime: task.startTime(),
-                    endTime: task.endTime(),
-                    label: task.label(),
-                    fillStyle: fillStyle,
-                };
-            }));
-        });
-    }
-
-    platformId() { return this._platformId; }
-    metricId() { return this._metricId; }
-
</del><span class="cx">     serializeState()
</span><span class="cx">     {
</span><span class="cx">         var selection = this._mainChart ? this._mainChart.currentSelection() : null;
</span><span class="lines">@@ -116,36 +39,28 @@
</span><span class="cx">             this._mainChart.setIndicator(null, false);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    setOverviewDomain(startTime, endTime)
-    {
-        if (this._overviewChart)
-            this._overviewChart.setDomain(startTime, endTime);
-    }
-
</del><span class="cx">     setOverviewSelection(selection)
</span><span class="cx">     {
</span><span class="cx">         if (this._overviewChart)
</span><span class="cx">             this._overviewChart.setSelection(selection);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    setMainDomain(startTime, endTime)
</del><ins>+    _overviewSelectionDidChange(domain, didEndDrag)
</ins><span class="cx">     {
</span><del>-        if (this._mainChart)
-            this._mainChart.setDomain(startTime, endTime);
</del><ins>+        super._overviewSelectionDidChange(domain, didEndDrag);
+        this._chartsPage.setMainDomainFromOverviewSelection(domain, this, didEndDrag);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _mainSelectionDidChange(selection, didEndDrag)
</span><span class="cx">     {
</span><ins>+        super._mainSelectionDidChange(selection, didEndDrag);
</ins><span class="cx">         this._chartsPage.mainChartSelectionDidChange(this, didEndDrag);
</span><del>-        this.render();
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _mainSelectionDidZoom(selection)
</span><span class="cx">     {
</span><del>-        this._overviewChart.setSelection(selection, this);
-        this._mainChart.setSelection(null);
</del><ins>+        super._mainSelectionDidZoom(selection);
</ins><span class="cx">         this._chartsPage.setMainDomainFromZoom(selection, this);
</span><del>-        this.render();
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _openAnalysisTask(annotation)
</span><span class="lines">@@ -155,58 +70,13 @@
</span><span class="cx"> 
</span><span class="cx">     _indicatorDidChange(indicatorID, isLocked)
</span><span class="cx">     {
</span><del>-        this._chartsPage.mainChartIndicatorDidChange(this, isLocked || this._mainChartIndicatorWasLocked);
</del><span class="cx">         this._mainChartIndicatorWasLocked = isLocked;
</span><del>-        this._mainChartStatus.updateRevisionListWithNotification();
-        this.render();
</del><ins>+        this._chartsPage.mainChartIndicatorDidChange(this, isLocked || this._mainChartIndicatorWasLocked);
+        super._indicatorDidChange(indicatorID, isLocked);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    _openCommitViewer(repository, from, to)
-    {
-        var self = this;
-        this._commitLogViewer.view(repository, from, to).then(function () {
-            self._mainChartStatus.setCurrentRepository(self._commitLogViewer.currentRepository());
-            self.render();
-        });
-    }
-    
-    _didFetchData()
-    {
-        this._mainChartStatus.updateRevisionListWithNotification();
-        this.render();
-    }
-
-    _keyup(event)
-    {
-        switch (event.keyCode) {
-        case 37: // Left
-            if (!this._mainChart.moveLockedIndicatorWithNotification(false))
-                return;
-            break;
-        case 39: // Right
-            if (!this._mainChart.moveLockedIndicatorWithNotification(true))
-                return;
-            break;
-        case 38: // Up
-            if (!this._mainChartStatus.moveRepositoryWithNotification(false))
-                return;
-        case 40: // Down
-            if (!this._mainChartStatus.moveRepositoryWithNotification(true))
-                return;
-        default:
-            return;
-        }
-
-        event.preventDefault();
-        event.stopPropagation();
-    }
-
</del><span class="cx">     render()
</span><span class="cx">     {
</span><del>-        Instrumentation.startMeasuringTime('ChartPane', 'render');
-
-        super.render();
-
</del><span class="cx">         if (this._platform &amp;&amp; this._metric) {
</span><span class="cx">             var metric = this._metric;
</span><span class="cx">             var platform = this._platform;
</span><span class="lines">@@ -215,27 +85,13 @@
</span><span class="cx">                 metric.fullName() + ' on ' + platform.name());
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (this._errorMessage) {
-            this.renderReplace(this.content().querySelector('.chart-pane-main'), this._errorMessage);
-            return;
-        }
</del><ins>+        if (this._mainChartStatus)
+            this._renderActionToolbar();
</ins><span class="cx"> 
</span><del>-        if (this._mainChartStatus) {
-            this._mainChartStatus.render();
-            this._renderActionToolbar(this._mainChartStatus.analyzeData());
-        }
-
-        var body = this.content().querySelector('.chart-pane-body');
-        if (this._commitLogViewer.currentRepository()) {
-            body.classList.add('has-second-sidebar');
-            this._commitLogViewer.render();
-        } else
-            body.classList.remove('has-second-sidebar');
-
-        Instrumentation.endMeasuringTime('ChartPane', 'render');
</del><ins>+        super.render();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    _renderActionToolbar(analyzeData)
</del><ins>+    _renderActionToolbar()
</ins><span class="cx">     {
</span><span class="cx">         var actions = [];
</span><span class="cx">         var platform = this._platform;
</span><span class="lines">@@ -267,7 +123,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         var analyzePane = this.content().querySelector('.chart-pane-analyze-pane');
</span><del>-        if (analyzeData) {
</del><ins>+        var pointsRangeForAnalysis = this._mainChartStatus.pointsRangeForAnalysis();
+        if (pointsRangeForAnalysis) {
</ins><span class="cx">             actions.push(element('li', {class: this._paneOpenedByClick == analyzePane ? 'selected' : ''},
</span><span class="cx">                 this._makeAnchorToOpenPane(analyzePane, 'Analyze', false)));
</span><span class="cx"> 
</span><span class="lines">@@ -277,7 +134,7 @@
</span><span class="cx">                 var newWindow = window.open(router.url('analysis/task/create'), '_blank');
</span><span class="cx"> 
</span><span class="cx">                 var name = analyzePane.querySelector('input').value;
</span><del>-                AnalysisTask.create(name, analyzeData.startPointId, analyzeData.endPointId).then(function (data) {
</del><ins>+                AnalysisTask.create(name, pointsRangeForAnalysis.startPointId, pointsRangeForAnalysis.endPointId).then(function (data) {
</ins><span class="cx">                     newWindow.location.href = router.url('analysis/task/' + data['taskId']);
</span><span class="cx">                     // FIXME: Refetch the list of analysis tasks.
</span><span class="cx">                 }, function (error) {
</span><span class="lines">@@ -359,53 +216,36 @@
</span><span class="cx">         return anchor;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static htmlTemplate()
</del><ins>+    static paneHeaderTemplate()
</ins><span class="cx">     {
</span><span class="cx">         return `
</span><del>-            &lt;section class=&quot;chart-pane&quot; tabindex=&quot;0&quot;&gt;
-                &lt;header class=&quot;chart-pane-header&quot;&gt;
-                    &lt;h2 class=&quot;chart-pane-title&quot;&gt;-&lt;/h2&gt;
-                    &lt;nav class=&quot;chart-pane-actions&quot;&gt;
-                        &lt;ul&gt;
-                            &lt;li class=&quot;close&quot;&gt;&lt;close-button&gt;&lt;/close-button&gt;&lt;/li&gt;
-                        &lt;/ul&gt;
-                        &lt;ul class=&quot;chart-pane-action-buttons buttoned-toolbar&quot;&gt;&lt;/ul&gt;
-                        &lt;ul class=&quot;chart-pane-alternative-platforms&quot; style=&quot;display:none&quot;&gt;&lt;/ul&gt;
-                        &lt;form class=&quot;chart-pane-analyze-pane&quot; style=&quot;display:none&quot;&gt;
-                            &lt;input type=&quot;text&quot; required&gt;
-                            &lt;button&gt;Create&lt;/button&gt;
-                        &lt;/form&gt;
-                    &lt;/nav&gt;
-                &lt;/header&gt;
-                &lt;div class=&quot;chart-pane-body&quot;&gt;
-                    &lt;div class=&quot;chart-pane-main&quot;&gt;&lt;/div&gt;
-                    &lt;div class=&quot;chart-pane-sidebar&quot;&gt;
-                        &lt;div class=&quot;chart-pane-overview&quot;&gt;&lt;/div&gt;
-                        &lt;div class=&quot;chart-pane-details&quot;&gt;&lt;/div&gt;
-                    &lt;/div&gt;
-                    &lt;div class=&quot;chart-pane-second-sidebar&quot;&gt;
-                        &lt;commit-log-viewer&gt;&lt;/commit-log-viewer&gt;
-                    &lt;/div&gt;
-                &lt;/div&gt;
-            &lt;/section&gt;
-`;
</del><ins>+            &lt;header class=&quot;chart-pane-header&quot;&gt;
+                &lt;h2 class=&quot;chart-pane-title&quot;&gt;-&lt;/h2&gt;
+                &lt;nav class=&quot;chart-pane-actions&quot;&gt;
+                    &lt;ul&gt;
+                        &lt;li class=&quot;close&quot;&gt;&lt;close-button&gt;&lt;/close-button&gt;&lt;/li&gt;
+                    &lt;/ul&gt;
+                    &lt;ul class=&quot;chart-pane-action-buttons buttoned-toolbar&quot;&gt;&lt;/ul&gt;
+                    &lt;ul class=&quot;chart-pane-alternative-platforms&quot; style=&quot;display:none&quot;&gt;&lt;/ul&gt;
+                    &lt;form class=&quot;chart-pane-analyze-pane&quot; style=&quot;display:none&quot;&gt;
+                        &lt;input type=&quot;text&quot; required&gt;
+                        &lt;button&gt;Create&lt;/button&gt;
+                    &lt;/form&gt;
+                &lt;/nav&gt;
+            &lt;/header&gt;
+        `;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static cssTemplate()
</span><span class="cx">     {
</span><del>-        return Toolbar.cssTemplate() + `
</del><ins>+        return ChartPaneBase.cssTemplate() + `
</ins><span class="cx">             .chart-pane {
</span><del>-                margin: 1rem;
-                margin-bottom: 2rem;
-                padding: 0rem;
-                height: 18rem;
</del><span class="cx">                 border: solid 1px #ccc;
</span><span class="cx">                 border-radius: 0.5rem;
</span><del>-                outline: none;
</del><span class="cx">             }
</span><span class="cx"> 
</span><del>-            .chart-pane:focus .chart-pane-header {
-                background: rgba(204, 153, 51, 0.1);
</del><ins>+            .chart-pane-body {
+                height: calc(100% - 2rem);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             .chart-pane-header {
</span><span class="lines">@@ -494,75 +334,6 @@
</span><span class="cx">                 outline: none;
</span><span class="cx">                 border: solid 1px #ccc;
</span><span class="cx">             }
</span><del>-
-            .chart-pane-body {
-                position: relative;
-                width: 100%;
-                height: calc(100% - 2rem);
-            }
-
-            .chart-pane-main {
-                padding-right: 20rem;
-                height: 100%;
-                margin: 0;
-                vertical-align: middle;
-                text-align: center;
-            }
-
-            .has-second-sidebar .chart-pane-main {
-                padding-right: 40rem;
-            }
-
-            .chart-pane-main &gt; * {
-                width: 100%;
-                height: 100%;
-            }
-
-            .chart-pane-sidebar,
-            .chart-pane-second-sidebar {
-                position: absolute;
-                right: 0;
-                top: 0;
-                width: 0;
-                border-left: solid 1px #ccc;
-                height: 100%;
-            }
-
-            :not(.has-second-sidebar) &gt; .chart-pane-second-sidebar {
-                border-left: 0;
-            }
-
-            .chart-pane-sidebar {
-                width: 20rem;
-            }
-
-            .has-second-sidebar .chart-pane-sidebar {
-                right: 20rem;
-            }
-
-            .has-second-sidebar .chart-pane-second-sidebar {
-                width: 20rem;
-            }
-
-            .chart-pane-overview {
-                width: 100%;
-                height: 5rem;
-                border-bottom: solid 1px #ccc;
-            }
-
-            .chart-pane-overview &gt; * {
-                display: block;
-                width: 100%;
-                height: 100%;
-            }
-
-            .chart-pane-details {
-                position: relative;
-                display: block;
-                height: calc(100% - 5.5rem - 2px);
-                overflow-y: scroll;
-                padding-top: 0.5rem;
-            }
</del><span class="cx"> `;
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3pageschartspagejs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/v3/pages/charts-page.js (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/pages/charts-page.js        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/charts-page.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> 
</span><del>-class ChartsPage extends PageWithCharts {
</del><ins>+class ChartsPage extends PageWithHeading {
</ins><span class="cx">     constructor(toolbar)
</span><span class="cx">     {
</span><span class="cx">         console.assert(toolbar instanceof ChartsToolbar);
</span><span class="lines">@@ -19,13 +19,19 @@
</span><span class="cx">         return state;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static createDomainForAnalysisTask(task)
+    {
+        var diff = (task.endTime() - task.startTime()) * 0.1;
+        return [task.startTime() - diff, task.endTime() + diff];
+    }
+
</ins><span class="cx">     static createStateForAnalysisTask(task)
</span><span class="cx">     {
</span><del>-        var diff = (task.endTime() - task.startTime()) * 0.1;
</del><ins>+        var domain = this.createDomainForAnalysisTask(task);
</ins><span class="cx">         var state = {
</span><span class="cx">             paneList: [[task.platform().id(), task.metric().id()]],
</span><span class="cx">             since: Math.round(task.startTime() - (Date.now() - task.startTime()) * 0.1),
</span><del>-            zoom: [task.startTime() - diff, task.endTime() + diff],
</del><ins>+            zoom: domain,
</ins><span class="cx">         };
</span><span class="cx">         return state;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3pagesdashboardpagejs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/public/v3/pages/dashboard-page.js (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/pages/dashboard-page.js        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/dashboard-page.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -1,10 +1,11 @@
</span><span class="cx"> 
</span><del>-class DashboardPage extends PageWithCharts {
</del><ins>+class DashboardPage extends PageWithHeading {
</ins><span class="cx">     constructor(name, table, toolbar)
</span><span class="cx">     {
</span><span class="cx">         console.assert(toolbar instanceof DashboardToolbar);
</span><span class="cx">         super(name, toolbar);
</span><span class="cx">         this._table = table;
</span><ins>+        this._charts = [];
</ins><span class="cx">         this._needsTableConstruction = true;
</span><span class="cx">         this._needsStatusUpdate = true;
</span><span class="cx">         this._statusViews = [];
</span><span class="lines">@@ -124,11 +125,11 @@
</span><span class="cx">         if (!platformId || !metricId)
</span><span class="cx">             return '';
</span><span class="cx"> 
</span><del>-        var result = DashboardPage.createChartSourceList(platformId, metricId);
</del><ins>+        var result = ChartStyles.createChartSourceList(platformId, metricId);
</ins><span class="cx">         if (result.error)
</span><span class="cx">             return result.error;
</span><span class="cx"> 
</span><del>-        var options = DashboardPage.dashboardOptions(result.metric.makeFormatter(3));
</del><ins>+        var options = ChartStyles.dashboardOptions(result.metric.makeFormatter(3));
</ins><span class="cx">         options.ondata = this._fetchedData.bind(this);
</span><span class="cx">         var chart = new TimeSeriesChart(result.sourceList, options);
</span><span class="cx">         this._charts.push(chart);
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv3pagespagewithchartsjs"></a>
<div class="delfile"><h4>Deleted: trunk/Websites/perf.webkit.org/public/v3/pages/page-with-charts.js (196386 => 196387)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v3/pages/page-with-charts.js        2016-02-10 21:05:37 UTC (rev 196386)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/page-with-charts.js        2016-02-10 21:07:52 UTC (rev 196387)
</span><span class="lines">@@ -1,132 +0,0 @@
</span><del>-
-class PageWithCharts extends PageWithHeading {
-    constructor(name, toolbar)
-    {
-        super(name, toolbar);
-        this._charts = [];
-    }
-
-    static createChartSourceList(platformId, metricId)
-    {
-        var platform = Platform.findById(platformId);
-        var metric = Metric.findById(metricId);
-        if (!platform || !metric)
-            return {error: `Invalid platform or metric: ${platformId} and ${metricId}`};
-
-        var lastModified = platform.lastModified(metric);
-        if (!lastModified)
-            return {platform: platform, metric: metric, error: `No results on ${platform.name()}`};
-
-        var measurementSet = MeasurementSet.findSet(platform.id(), metric.id(), lastModified);
-        var sourceList = [
-            this.baselineStyle(measurementSet, 'baseline'),
-            this.targetStyle(measurementSet, 'target'),
-            this.currentStyle(measurementSet, 'current'),
-        ];
-
-        return {
-            platform: platform,
-            metric: metric,
-            sourceList: sourceList,
-        };
-    }
-
-    static baselineStyle(measurementSet)
-    {
-        return {
-            measurementSet: measurementSet,
-            extendToFuture: true,
-            sampleData: true,
-            type: 'baseline',
-            pointStyle: '#f33',
-            pointRadius: 2,
-            lineStyle: '#f99',
-            lineWidth: 1.5,
-            intervalStyle: '#fdd',
-            intervalWidth: 2,
-        };
-    }
-
-    static targetStyle(measurementSet)
-    {
-        return {
-            measurementSet: measurementSet,
-            extendToFuture: true,
-            sampleData: true,
-            type: 'target',
-            pointStyle: '#33f',
-            pointRadius: 2,
-            lineStyle: '#99f',
-            lineWidth: 1.5,
-            intervalStyle: '#ddf',
-            intervalWidth: 2,
-        };
-    }
-
-    static currentStyle(measurementSet)
-    {
-        return {
-            measurementSet: measurementSet,
-            sampleData: true,
-            type: 'current',
-            pointStyle: '#333',
-            pointRadius: 2,
-            lineStyle: '#999',
-            lineWidth: 1.5,
-            intervalStyle: '#ddd',
-            intervalWidth: 2,
-            interactive: true,
-        };
-    }
-
-    static dashboardOptions(valueFormatter)
-    {
-        return {
-            updateOnRequestAnimationFrame: true,
-            axis: {
-                yAxisWidth: 4, // rem
-                xAxisHeight: 2, // rem
-                gridStyle: '#ddd',
-                fontSize: 0.8, // rem
-                valueFormatter: valueFormatter,
-            },
-        };
-    }
-
-    static overviewChartOptions(valueFormatter)
-    {
-        var options = this.dashboardOptions(valueFormatter);
-        options.axis.yAxisWidth = 0; // rem
-        options.selection = {
-            lineStyle: '#f93',
-            lineWidth: 2,
-            fillStyle: 'rgba(153, 204, 102, .125)',
-        }
-        return options;
-    }
-
-    static mainChartOptions(valueFormatter)
-    {
-        var options = this.dashboardOptions(valueFormatter);
-        options.axis.xAxisEndPadding = 5;
-        options.axis.yAxisWidth = 5;
-        options.selection = {
-            lineStyle: '#f93',
-            lineWidth: 2,
-            fillStyle: 'rgba(153, 204, 102, .125)',
-        }
-        options.indicator = {
-            lineStyle: '#f93',
-            lineWidth: 2,
-            pointRadius: 3,
-        };
-        options.annotations = {
-            textStyle: '#000',
-            textBackground: '#fff',
-            minWidth: 3,
-            barHeight: 7,
-            barSpacing: 2,
-        };
-        return options;
-    }
-}
</del></span></pre>
</div>
</div>

</body>
</html>