1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 var ui = ui || {}; 27 ui.perf = ui.perf || {}; 28 29 (function(){ 30 31 ui.perf.Picker = base.extends('select', { 32 init: function(items, onChange, opt_values) 33 { 34 this.onchange = onChange; 35 this._values = opt_values; 36 items.forEach(this._appendItem.bind(this)); 37 }, 38 _appendItem: function(item, index) 39 { 40 var option = document.createElement('option'); 41 option.innerHTML = item; 42 if (this._values) 43 option.value = this._values[index]; 44 this.appendChild(option); 45 } 46 }); 47 48 ui.perf.View = base.extends('div', { 49 init: function() 50 { 51 this.id = 'perf-view'; 52 builders.perfBuilders(this.loadGraphs.bind(this)); 53 54 var stream = new ui.notifications.Stream(); 55 var notifications = document.createElement() 56 this._notification = ui.notifications.Info("Loading list of perf dashboards..."); 57 stream.appendChild(this._notification); 58 this.appendChild(stream); 59 }, 60 loadGraphs: function(graphData) 61 { 62 this._notification.dismiss(); 63 64 // FIXME: Add next/previous buttons for easy navigation through all the graphs. 65 // FIXME: Also, show the list of failing perf builders along with which steps are failing. 66 this._data = graphData; 67 68 this._titleBar = document.createElement('div'); 69 this._titleBar.className = 'title-bar'; 70 this.appendChild(this._titleBar); 71 72 var testSuites = Object.keys(graphData); 73 var suitePicker = new ui.perf.Picker(testSuites, this._onChangeSuite.bind(this)); 74 this._titleBar.appendChild(suitePicker); 75 76 this._titleBar.appendChild(new ui.actions.List([new ui.actions.Previous(), new ui.actions.Next()])); 77 78 $(this).bind('next', this._nextGraph.bind(this)); 79 $(this).bind('previous', this._previousGraph.bind(this)); 80 81 this._suitePicker = suitePicker; 82 this._onChangeSuite(); 83 }, 84 _onChangeSuite: function() 85 { 86 this._updateBuilderPicker(); 87 this._displayGraph(); 88 }, 89 _updateBuilderPicker: function() 90 { 91 if (this._builderPicker) 92 this._titleBar.removeChild(this._builderPicker); 93 94 if (!this._suitePicker.length) 95 return; 96 var selectedSuite = this._suitePicker[this._suitePicker.selectedIndex].text; 97 var builders = []; 98 var urls = []; 99 this._data[selectedSuite].forEach(function(config) { 100 builders.push(config.builder); 101 urls.push(config.url); 102 }); 103 this._builderPicker = new ui.perf.Picker(builders, this._displayGraph.bind(this), urls); 104 this._titleBar.appendChild(this._builderPicker); 105 }, 106 _displayGraph: function() 107 { 108 var popOutLink = this.querySelector('.pop-out'); 109 if (!popOutLink) { 110 popOutLink = document.createElement('a'); 111 popOutLink.className = 'pop-out'; 112 popOutLink.textContent = 'Pop out'; 113 popOutLink.target = '_blank'; 114 this._titleBar.appendChild(popOutLink); 115 } 116 117 var graph = this.querySelector('iframe'); 118 if (!graph) { 119 graph = document.createElement('iframe'); 120 this.appendChild(graph); 121 } 122 123 if (!this._builderPicker || !this._builderPicker.length) 124 return; 125 126 var url = this._builderPicker[this._builderPicker.selectedIndex].value; 127 popOutLink.href = url; 128 graph.src = url; 129 }, 130 _nextGraph: function() 131 { 132 if (!this._builderPicker) 133 return; 134 135 if (this._builderPicker.selectedIndex < this._builderPicker.length - 1) { 136 this._builderPicker.selectedIndex++; 137 this._displayGraph(); 138 return; 139 } 140 141 if (this._suitePicker.selectedIndex < this._suitePicker.length - 1) { 142 this._suitePicker.selectedIndex++; 143 this._onChangeSuite(); 144 } 145 }, 146 _previousGraph: function() 147 { 148 if (!this._builderPicker) 149 return; 150 151 if (this._builderPicker.selectedIndex > 0) { 152 this._builderPicker.selectedIndex--; 153 this._displayGraph(); 154 return; 155 } 156 157 if (this._suitePicker.selectedIndex > 0) { 158 this._suitePicker.selectedIndex--; 159 this._updateBuilderPicker(); 160 this._builderPicker.selectedIndex = this._builderPicker.length - 1; 161 this._displayGraph(); 162 } 163 } 164 }); 165 166 })(); 167