blob: 2f3c7ba516bdb34dcf503049198f6ec267a47deb [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/perf_insights/function_handle.html">
<link rel="import" href="/perf_insights/mre/job.html">
<link rel="import" href="/perf_insights/mre/mre_result.html">
<link rel="import" href="/perf_insights/ui/generic_results_view.html">
<link rel="import" href="/perf_insights/ui/reports/pi_report.html">
<link rel="import" href="/tracing/base/xhr.html">
<link rel="import" href="/tracing/ui/base/dom_helpers.html">
<link rel="import" href="/tracing/ui/base/info_bar_group.html">
<link rel="import" href="/tracing/ui/base/polymer_utils.html">
<polymer-element name="pi-ui-pi-app-main">
<template>
<style>
:host {
display: flex;
flex-direction: column;
}
top-controls {
display: flex;
flex: 0 0 auto;
background-color: rgb(236, 236, 236);
border-bottom: 1px solid #8e8e8e;
padding: 4px;
}
top-controls > span.spacer {
flex: 1 1 auto;
}
top-left-controls {
display: flex;
}
top-right-controls {
display: flex;
}
report-container {
display: flex;
flex: 1 1 auto;
min-height: 0;
min-width: 0;
overflow: auto;
}
report-container > * {
flex: 1 1 auto;
}
</style>
<top-controls>
<top-left-controls id="top_left_controls"></top-left-controls>
<span class="spacer"></span>
<top-right-controls id="top_right_controls"></top-right-controls>
</top-controls>
<tr-ui-b-info-bar-group id="infobars"></tr-ui-b-info-bar-group>
<report-container id="report_container"></report-container>
</template>
</polymer-element>
<script>
'use strict';
tr.exportTo('pi.ui', function() {
function areMappingStatesSame(a, b) {
for (var k in a)
if (a[k] !== b[k])
return false;
return true;
}
Polymer('pi-ui-pi-app-main', {
created: function() {
// Non-mapping state.
this.mapTracesDrivers_ = undefined;
// Mapping state.
this.currentMapTracesDriver_ = undefined;
this.corpusQuery_ = undefined;
this.piReportElementName_ = undefined;
this.showRawResults_ = false;
},
ready: function() {
var topLeftControls = this.$.top_left_controls;
var topRightControls = this.$.top_right_controls;
var piDriverPolymerElementNames = tr.ui.b.getPolymerElementsThatSubclass(
'pi-driver-base');
var piDriverElementOptions = piDriverPolymerElementNames.map(
function(peTagName) {
var pe = tr.ui.b.getPolymerElementNamed(peTagName);
return {
label: pe.getAttribute('display-name'),
value: peTagName
};
});
var driverSelector = tr.ui.b.createSelector(
this, 'currentMapTracesDriver',
'pi.app_main.currentMapTracesDriver',
piDriverElementOptions[0].value,
piDriverElementOptions);
topLeftControls.appendChild(driverSelector);
var corpusSelections = [
{
'label': 'Deep Reports',
'value': 'https://performance-insights.appspot.com'
},
{
'label': 'Bulk Reports',
'value': 'https://performance-insights.appspot.com'
}
];
var corpusSelector = tr.ui.b.createSelector(
this, 'corpus',
'pi.app_main.corpus',
corpusSelections[0].value,
corpusSelections);
topLeftControls.appendChild(corpusSelector);
var corpusQuerySelector = tr.ui.b.createTextInput(
this, 'corpusQuery',
'pi.app_main.corpusQuery',
'MAX_TRACE_HANDLES=10');
var self = this;
function onQuerySelectorKeypress(e) {
var key = e.which || e.keyCode;
if (key === 13) { // 13 is enter
self.scheduleUpdateContents_();
self.fire('ui-state-changed');
}
}
corpusQuerySelector.addEventListener('keypress', onQuerySelectorKeypress);
corpusQuerySelector.style.width = '350px';
topLeftControls.appendChild(corpusQuerySelector);
var piReportPolymerElementNames = tr.ui.b.getPolymerElementsThatSubclass(
'pi-ui-r-pi-report');
var piReportElementOptions = piReportPolymerElementNames.map(
function(peTagName) {
return {
label: peTagName,
value: peTagName
};
});
var reportSelector = tr.ui.b.createSelector(
this, 'piReportElementName',
'pi.app_main.piReportElementName',
piReportElementOptions[0].value,
piReportElementOptions);
topLeftControls.appendChild(reportSelector);
var self = this;
function onProcessButton() {
self.scheduleUpdateContents_();
self.fire('ui-state-changed');
}
var processButton = tr.ui.b.createButton(
this, 'processButton',
'Process!', onProcessButton);
topLeftControls.appendChild(processButton);
var showRawResultsCheckbox = tr.ui.b.createCheckBox(
this, 'showRawResults',
'pi.app_main.showRawResults', false,
'Show raw results');
topRightControls.appendChild(showRawResultsCheckbox);
},
get mapTracesDrivers() {
return this.mapTracesDrivers_;
},
get mappingState() {
return {
currentMapTracesDriver: this.currentMapTracesDriver_,
corpusQuery: this.corpusQuery_,
piReportElementName: this.piReportElementName_,
showRawResults: this.showRawResults_
};
},
get currentMapTracesDriver() {
return this.currentMapTracesDriver_;
},
set currentMapTracesDriver(currentMapTracesDriver) {
this.currentMapTracesDriver_ = currentMapTracesDriver;
},
get corpusQuery() {
return this.corpusQuery_;
},
set corpusQuery(corpusQuery) {
this.corpusQuery_ = corpusQuery;
},
get piReportElementName() {
return this.piReportElementName_;
},
set piReportElementName(piReportElementName) {
this.piReportElementName_ = piReportElementName;
},
get mapClientSide() {
return this.mapClientSide_;
},
set mapClientSide(mapClientSide) {
this.mapClientSide_ = mapClientSide;
},
get showRawResults() {
return this.showRawResults_;
},
set showRawResults(showRawResults) {
this.showRawResults_ = showRawResults;
},
scheduleUpdateContents_: function() {
if (this.pendingUpdateContentsPromise_)
return;
var mappingState = this.mappingState;
var p = this.beginUpdatingContents_(mappingState);
p = p.catch(function(err) {
tr.showPanic('Something is wrong', err);
});
p = p.then(updateDone.bind(this));
function updateDone() {
this.pendingUpdateContentsPromise_ = undefined;
if (!areMappingStatesSame(this.mappingState, mappingState))
this.scheduleUpdateContents_();
}
this.pendingUpdateContentsPromise_ = p;
},
beginUpdatingContents_: function(mappingState) {
var pe = tr.ui.b.getPolymerElementNamed(mappingState.piReportElementName);
var reportContainer = this.$.report_container;
var infobars = this.$.infobars;
function clearInfobarsOrUpdateWithErrors(mapResults) {
infobars.clearMessages();
if (!mapResults) {
infobars.addMessage('Cannot map');
return mapResults;
}
if (!mapResults.some(function(r) { return r.hadFailures(); }))
return mapResults;
infobars.addMessage(
'Some traces that did not process.'
);
return mapResults;
}
var p = Promise.resolve();
p = p.then(function indicateThinking() {
infobars.clearMessages();
infobars.addMessage('... thinking...');
});
p = p.then(function doMapping() {
if (mappingState.currentMapTracesDriver === undefined ||
mappingState.piReportElementName === undefined ||
mappingState.corpusQuery === undefined) {
return undefined;
}
var mapFunctionName = pe.getAttribute('map-function-name');
var mapFunctionHref = pe.getAttribute('map-function-href');
var mapModuleToLoad = new pi.ModuleToLoad(mapFunctionHref);
var mapFunctionHandle = new pi.FunctionHandle(
[mapModuleToLoad], mapFunctionName);
var reduceFunctionName = pe.getAttribute('reduce-function-name');
var reduceFunctionHref = pe.getAttribute('reduce-function-href');
var reduceFunctionHandle;
if (reduceFunctionName && reduceFunctionHref) {
var reduceModuleToLoad = new pi.ModuleToLoad(reduceFunctionHref);
reduceFunctionHandle = new pi.FunctionHandle(
[reduceModuleToLoad], reduceFunctionName);
}
var job = new pi.mre.Job(mapFunctionHandle, reduceFunctionHandle);
if (mappingState.mapClientSide) {
throw new Error('Currently unsupported');
}
var peCurrentDriver = document.querySelector(
mappingState.currentMapTracesDriver);
return peCurrentDriver.runMapFunction(job, mappingState.corpusQuery);
});
p = p.then(function responseToResults(responseText) {
if (responseText === undefined)
return undefined;
var data = JSON.parse(responseText);
if (!data) {
return [];
} else {
return data.map(pi.mre.MreResult.fromDict);
}
});
p = p.then(clearInfobarsOrUpdateWithErrors);
p = p.then(function showMappingResults(mapResults) {
reportContainer.textContent = '';
if (mapResults === undefined)
return;
var reportEl;
if (mappingState.showRawResults) {
reportEl = document.createElement('pi-ui-generic-results-view');
} else {
reportEl = document.createElement(mappingState.piReportElementName);
}
reportEl.mapResults = mapResults;
reportContainer.appendChild(reportEl);
});
return p;
}
});
return {
};
});
</script>