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 |