| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** Information about a particular waterfall. */ | |
| 6 function WaterfallInfo(waterfallData) { | |
| 7 var waterfallName = waterfallData[0]; | |
| 8 var waterfallUrl = waterfallData[1]; | |
| 9 var waterfallShowsAllBots = waterfallData[2]; | |
| 10 | |
| 11 // Create a table cell that acts as a header for its bot section. | |
| 12 var linkElement = document.createElement('a'); | |
| 13 linkElement.href = waterfallUrl; | |
| 14 linkElement.innerHTML = waterfallName; | |
| 15 var thElement = document.createElement('th'); | |
| 16 thElement.colSpan = 15; | |
| 17 thElement.className = 'section-header'; | |
| 18 thElement.appendChild(linkElement); | |
| 19 | |
| 20 this.botInfo = {}; | |
| 21 this.inFlight = 0; | |
| 22 this.name = waterfallName; | |
| 23 this.showsAllBots = waterfallShowsAllBots; | |
| 24 this.thElement = thElement; | |
| 25 this.timeLastRequested = 0; | |
| 26 this.rootJsonUrl = waterfallUrl + 'json/'; | |
| 27 this.url = waterfallUrl; | |
| 28 } | |
| 29 | |
| 30 /** Global callbacks. */ | |
| 31 var gWaterfallInfoCallbacks = {counter: 0}; | |
| 32 | |
| 33 /** Send an asynchronous request to get the main waterfall's JSON. */ | |
| 34 WaterfallInfo.prototype.requestJson = function() { | |
| 35 if (this.inFlight) { | |
| 36 var elapsed = new Date().getTime() - this.timeLastRequested; | |
| 37 if (elapsed < MAX_MILLISECONDS_TO_WAIT) return; | |
| 38 | |
| 39 // A response was not received in a reasonable timeframe. Try again. | |
| 40 this.inFlight--; | |
| 41 gNumRequestsInFlight--; | |
| 42 gNumRequestsRetried++; | |
| 43 } | |
| 44 | |
| 45 this.inFlight++; | |
| 46 this.timeLastRequested = new Date().getTime(); | |
| 47 gNumRequestsInFlight++; | |
| 48 | |
| 49 // Create callback function. | |
| 50 var name = "fn" + gWaterfallInfoCallbacks.counter++; | |
| 51 var waterfallInfo = this; | |
| 52 gWaterfallInfoCallbacks[name] = function(json) { | |
| 53 delete gWaterfallInfoCallbacks[name]; | |
| 54 waterfallInfo.parseJSON(json); | |
| 55 } | |
| 56 | |
| 57 // Use JSONP to get data. | |
| 58 var head = document.head; | |
| 59 var script = document.createElement('script'); | |
| 60 script.type = 'text/javascript'; | |
| 61 script.setAttribute('src', this.url + | |
| 62 'json/builders/?callback=gWaterfallInfoCallbacks.' + name); | |
| 63 head.appendChild(script); | |
| 64 head.removeChild(script); | |
| 65 }; | |
| 66 | |
| 67 /** Parse out the data received about the waterfall. */ | |
| 68 WaterfallInfo.prototype.parseJSON = function(buildersJson) { | |
| 69 this.inFlight--; | |
| 70 gNumRequestsInFlight--; | |
| 71 | |
| 72 // Go through each builder on the waterfall and get the latest status. | |
| 73 var builderNames = Object.keys(buildersJson); | |
| 74 for (var i = 0; i < builderNames.length; ++i) { | |
| 75 var builderName = builderNames[i]; | |
| 76 | |
| 77 if (!this.showsAllBots && !this.shouldShowBot(builderName)) continue; | |
| 78 | |
| 79 // Prepare the bot info. | |
| 80 var builderJson = buildersJson[builderName]; | |
| 81 if (!this.botInfo[builderName]) { | |
| 82 this.botInfo[builderName] = new BotInfo(builderName, | |
| 83 builderJson.category); | |
| 84 } | |
| 85 this.botInfo[builderName].update(this.rootJsonUrl, builderJson); | |
| 86 gWaterfallDataIsDirty = true; | |
| 87 } | |
| 88 }; | |
| 89 | |
| 90 /** Override this function to filter out particular bots. */ | |
| 91 WaterfallInfo.prototype.shouldShowBot = function(builderName) { | |
| 92 return true; | |
| 93 }; | |
| 94 | |
| 95 /** Updates the HTML. */ | |
| 96 WaterfallInfo.prototype.updateWaterfallStatusHTML = function() { | |
| 97 var table = document.getElementById('build-info'); | |
| 98 | |
| 99 // Point at the waterfall. | |
| 100 var headerCell = this.thElement; | |
| 101 headerCell.className = | |
| 102 'section-header' + (this.inFlight > 0 ? ' in-flight' : ''); | |
| 103 var headerRow = table.insertRow(-1); | |
| 104 headerRow.appendChild(headerCell); | |
| 105 | |
| 106 // Print out useful bits about the bots. | |
| 107 var botNames = sortBotNamesByCategory(this.botInfo); | |
| 108 for (var i = 0; i < botNames.length; ++i) { | |
| 109 var botName = botNames[i]; | |
| 110 var botInfo = this.botInfo[botName]; | |
| 111 var waterfallBaseUrl = this.url + 'builders/'; | |
| 112 | |
| 113 var botRowElement = botInfo.createHtml(waterfallBaseUrl); | |
| 114 | |
| 115 // Determine whether we should apply keyword filter. | |
| 116 var filter = document.getElementById('text-filter').value.trim(); | |
| 117 if (filter.length > 0) { | |
| 118 var keywords = filter.split(' '); | |
| 119 var buildNumbers = Object.keys(botInfo.builds); | |
| 120 var matchesFilter = false; | |
| 121 | |
| 122 for (var x = 0; x < buildNumbers.length && !matchesFilter; ++x) { | |
| 123 var buildStatus = botInfo.builds[buildNumbers[x]].statusText; | |
| 124 for (var y = 0; y < keywords.length && !matchesFilter; ++y) { | |
| 125 if (buildStatus.indexOf(keywords[y]) >= 0) | |
| 126 matchesFilter = true; | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 if (!matchesFilter) | |
| 131 continue; | |
| 132 } | |
| 133 | |
| 134 // If the user doesn't want to see completely green bots, hide it. | |
| 135 var shouldHideStable = | |
| 136 document.getElementById('checkbox-hide-stable').checked; | |
| 137 if (shouldHideStable && botInfo.isSteadyGreen) | |
| 138 continue; | |
| 139 | |
| 140 table.appendChild(botRowElement); | |
| 141 } | |
| 142 }; | |
| OLD | NEW |