| <!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> |
| |