| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 1 | <!DOCTYPE html> |
| 2 | |
| epoger@google.com | 542b65f | 2013-10-15 20:10:33 +0000 | [diff] [blame] | 3 | <html ng-app="Loader" ng-controller="Loader.Controller"> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 4 | |
| 5 | <head> |
| epoger@google.com | 542b65f | 2013-10-15 20:10:33 +0000 | [diff] [blame] | 6 | <title ng-bind="windowTitle"></title> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 7 | <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script> |
| 8 | <script src="loader.js"></script> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 9 | <link rel="stylesheet" href="view.css"> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 10 | </head> |
| 11 | |
| 12 | <body> |
| epoger@google.com | dcb4e65 | 2013-10-11 18:45:33 +0000 | [diff] [blame] | 13 | <em> |
| 14 | {{loadingMessage}} |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 15 | </em> |
| epoger@google.com | afaad3d | 2013-09-30 15:06:25 +0000 | [diff] [blame] | 16 | |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 17 | <div ng-hide="!categories"><!-- everything: hide until data is loaded --> |
| 18 | |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 19 | <div class="warning-div" |
| 20 | ng-hide="!(header.isEditable && header.isExported)"> |
| epoger@google.com | 9fb6c8a | 2013-10-09 18:05:58 +0000 | [diff] [blame] | 21 | WARNING! These results are editable and exported, so any user |
| 22 | who can connect to this server over the network can modify them. |
| 23 | </div> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 24 | |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 25 | <div class="todo-div"><!-- TODOs --> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 26 | <p> |
| 27 | TODO(epoger): |
| epoger@google.com | 055e3b5 | 2013-10-26 14:31:11 +0000 | [diff] [blame^] | 28 | <input type="checkbox" ng-model="showTodos"> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 29 | show |
| 30 | <ul ng-hide="!showTodos"> |
| 31 | <li> |
| 32 | If server was run with --reload flag, automatically check for |
| 33 | new results and tell the user when new results are available |
| 34 | (the user can reload the page if he wants to see them). |
| 35 | </li><li> |
| 36 | Add ability to filter builder and test names |
| 37 | (using a free-form text field, with partial string match) |
| 38 | </li><li> |
| epoger@google.com | 055e3b5 | 2013-10-26 14:31:11 +0000 | [diff] [blame^] | 39 | Add pixel diffs, and sorting by percentage of different pixels |
| 40 | </li><li> |
| 41 | Add ability to sort/filter by reviewed-by-human. Depends on |
| 42 | <a href="https://code.google.com/p/skia/issues/detail?id=1758"> |
| 43 | bug 1758 |
| 44 | </a> |
| 45 | ('rebaseline_server: make the "categories" struct passed from server to client a list instead of a dict') |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 46 | </li><li> |
| 47 | Improve the column sorting, as per |
| 48 | <a href="http://jsfiddle.net/vojtajina/js64b/14/"> |
| 49 | http://jsfiddle.net/vojtajina/js64b/14/ |
| 50 | </a> |
| 51 | </li><li> |
| 52 | Right now, if you change which column is used to |
| 53 | sort the data, the column widths may fluctuate based on the |
| 54 | longest string <i>currently visible</i> within the top {{displayLimit}} |
| 55 | results. Can we fix the column widths to be wide enough to hold |
| 56 | any result, even the currently hidden results? |
| 57 | </li> |
| 58 | </ul> |
| 59 | </div><!-- TODOs --> |
| 60 | |
| epoger@google.com | 542b65f | 2013-10-15 20:10:33 +0000 | [diff] [blame] | 61 | <div ng-hide="!(header.timeUpdated)"> |
| 62 | Results current as of {{localTimeString(header.timeUpdated)}} |
| 63 | </div> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 64 | |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 65 | <div><!-- tabs --> |
| 66 | <div class="tab-spacer" ng-repeat="tab in tabs"> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 67 | <div class="tab-{{tab == viewingTab}}" |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 68 | ng-click="setViewingTab(tab)"> |
| 69 | {{tab}} ({{numResultsPerTab[tab]}}) |
| 70 | </div> |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 71 | <div class="tab-spacer"> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 72 | |
| 73 | </div> |
| 74 | </div> |
| 75 | </div><!-- tabs --> |
| 76 | |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 77 | <div class="tab-main"><!-- main display area of selected tab --> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 78 | |
| 79 | <br> |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 80 | <!-- We only show the filters/settings table on the Unfiled tab. --> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 81 | <table ng-hide="viewingTab != defaultTab" border="1"> |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 82 | <tr> |
| 83 | <th colspan="2"> |
| 84 | Filters |
| 85 | </th> |
| 86 | <th> |
| 87 | Settings |
| 88 | </th> |
| 89 | </tr> |
| 90 | <tr valign="top"> |
| epoger@google.com | 055e3b5 | 2013-10-26 14:31:11 +0000 | [diff] [blame^] | 91 | <!-- TODO(epoger): make this an ng-repeat over resultType, config, etc? --> |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 92 | <td> |
| 93 | resultType<br> |
| 94 | <label ng-repeat="(resultType, count) in categories['resultType']"> |
| 95 | <input type="checkbox" |
| 96 | name="resultTypes" |
| 97 | value="{{resultType}}" |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 98 | ng-checked="!isValueInSet(resultType, hiddenResultTypes)" |
| 99 | ng-click="toggleValueInSet(resultType, hiddenResultTypes); setUpdatesPending(true)"> |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 100 | {{resultType}} ({{count}})<br> |
| 101 | </label> |
| 102 | </td> |
| 103 | <td> |
| 104 | config<br> |
| 105 | <label ng-repeat="(config, count) in categories['config']"> |
| 106 | <input type="checkbox" |
| 107 | name="configs" |
| 108 | value="{{config}}" |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 109 | ng-checked="!isValueInSet(config, hiddenConfigs)" |
| 110 | ng-click="toggleValueInSet(config, hiddenConfigs); setUpdatesPending(true)"> |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 111 | {{config}} ({{count}})<br> |
| 112 | </label> |
| 113 | </td> |
| 114 | <td><table> |
| 115 | <tr><td> |
| 116 | Image size |
| 117 | <input type="text" ng-model="imageSizePending" |
| 118 | ng-init="imageSizePending=100" |
| 119 | ng-change="areUpdatesPending = true" |
| 120 | maxlength="4"/> |
| 121 | </td></tr> |
| 122 | <tr><td> |
| 123 | Max records to display |
| 124 | <input type="text" ng-model="displayLimitPending" |
| 125 | ng-init="displayLimitPending=50" |
| 126 | ng-change="areUpdatesPending = true" |
| 127 | maxlength="4"/> |
| 128 | </td></tr> |
| 129 | <tr><td> |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 130 | <button class="update-results-button" |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 131 | ng-click="updateResults()" |
| 132 | ng-disabled="!areUpdatesPending"> |
| 133 | Update Results |
| 134 | </button> |
| 135 | </td></tr> |
| 136 | </tr></table></td> |
| 137 | </tr> |
| 138 | </table> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 139 | |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 140 | <p> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 141 | |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 142 | <!-- Submission UI that we only show in the Pending Approval tab. --> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 143 | <div ng-hide="'Pending Approval' != viewingTab"> |
| 144 | <div style="display:inline-block"> |
| 145 | <button style="font-size:20px" |
| 146 | ng-click="submitApprovals(filteredTestData)" |
| 147 | ng-disabled="submitPending || (filteredTestData.length == 0)"> |
| 148 | Update these {{filteredTestData.length}} expectations on the server |
| 149 | </button> |
| 150 | </div> |
| 151 | <div style="display:inline-block"> |
| 152 | <div style="font-size:20px" |
| 153 | ng-hide="!submitPending"> |
| 154 | Submitting, please wait... |
| 155 | </div> |
| 156 | </div> |
| epoger@google.com | 055e3b5 | 2013-10-26 14:31:11 +0000 | [diff] [blame^] | 157 | <div> |
| 158 | Advanced settings... |
| 159 | <input type="checkbox" ng-model="showSubmitAdvancedSettings"> |
| 160 | show |
| 161 | <ul ng-hide="!showSubmitAdvancedSettings"> |
| 162 | <li ng-repeat="setting in ['reviewed-by-human', 'ignore-failures']"> |
| 163 | {{setting}} |
| 164 | <input type="checkbox" ng-model="submitAdvancedSettings[setting]"> |
| 165 | </li> |
| 166 | <li ng-repeat="setting in ['bug']"> |
| 167 | {{setting}} |
| 168 | <input type="text" ng-model="submitAdvancedSettings[setting]"> |
| 169 | </li> |
| 170 | </ul> |
| 171 | </div> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 172 | </div> |
| 173 | |
| 174 | <p> |
| 175 | |
| 176 | <div> |
| 177 | <div style="float:left"> |
| 178 | Found {{filteredTestData.length}} matches; |
| 179 | <span ng-hide="filteredTestData.length <= limitedTestData.length"> |
| 180 | displaying the first {{limitedTestData.length}} |
| 181 | </span> |
| 182 | <span ng-hide="filteredTestData.length > limitedTestData.length"> |
| 183 | displaying them all |
| 184 | </span> |
| 185 | <br> |
| 186 | (click on the column header radio buttons to re-sort by that column) |
| 187 | </div> |
| 188 | <div style="float:right"> |
| epoger@google.com | 055e3b5 | 2013-10-26 14:31:11 +0000 | [diff] [blame^] | 189 | <div> |
| 190 | all tests shown: |
| 191 | <button ng-click="selectAllItems()"> |
| 192 | select |
| 193 | </button> |
| 194 | <button ng-click="clearAllItems()"> |
| 195 | clear |
| 196 | </button> |
| 197 | <button ng-click="toggleAllItems()"> |
| 198 | toggle |
| 199 | </button> |
| 200 | </div> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 201 | <div ng-repeat="otherTab in tabs"> |
| 202 | <button ng-click="moveSelectedItemsToTab(otherTab)" |
| 203 | ng-disabled="selectedItems.length == 0" |
| 204 | ng-hide="otherTab == viewingTab"> |
| epoger@google.com | 055e3b5 | 2013-10-26 14:31:11 +0000 | [diff] [blame^] | 205 | move {{selectedItems.length}} selected tests to {{otherTab}} tab |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 206 | </button> |
| 207 | </div> |
| 208 | </div> |
| 209 | <div style="clear:both"> |
| 210 | </div> |
| 211 | </div> |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 212 | <br> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 213 | |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 214 | <table border="1"> |
| 215 | <tr> |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 216 | <!-- Most column headers are displayed in a common fashion... --> |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 217 | <th ng-repeat="categoryName in ['resultType', 'builder', 'test', 'config']"> |
| 218 | <input type="radio" |
| 219 | name="sortColumnRadio" |
| 220 | value="{{categoryName}}" |
| 221 | ng-checked="(sortColumn == categoryName)" |
| 222 | ng-click="sortResultsBy(categoryName)"> |
| 223 | {{categoryName}} |
| 224 | </th> |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 225 | <!-- ... but there are a few columns where we display things differently. --> |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 226 | <th> |
| 227 | <input type="radio" |
| 228 | name="sortColumnRadio" |
| epoger@google.com | 055e3b5 | 2013-10-26 14:31:11 +0000 | [diff] [blame^] | 229 | value="bugs" |
| 230 | ng-checked="(sortColumn == 'bugs')" |
| 231 | ng-click="sortResultsBy('bugs')"> |
| 232 | bugs |
| 233 | </th> |
| 234 | <th> |
| 235 | <input type="radio" |
| 236 | name="sortColumnRadio" |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 237 | value="expectedHashDigest" |
| 238 | ng-checked="(sortColumn == 'expectedHashDigest')" |
| 239 | ng-click="sortResultsBy('expectedHashDigest')"> |
| 240 | expected image |
| 241 | </th> |
| 242 | <th> |
| 243 | <input type="radio" |
| 244 | name="sortColumnRadio" |
| 245 | value="actualHashDigest" |
| 246 | ng-checked="(sortColumn == 'actualHashDigest')" |
| 247 | ng-click="sortResultsBy('actualHashDigest')"> |
| 248 | actual image |
| 249 | </th> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 250 | <th> |
| epoger@google.com | 9fb6c8a | 2013-10-09 18:05:58 +0000 | [diff] [blame] | 251 | <!-- item-selection checkbox column --> |
| epoger@google.com | 9fb6c8a | 2013-10-09 18:05:58 +0000 | [diff] [blame] | 252 | </th> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 253 | </tr> |
| epoger@google.com | 5f2bb00 | 2013-10-02 18:57:48 +0000 | [diff] [blame] | 254 | <tr ng-repeat="result in limitedTestData"> |
| epoger@google.com | 055e3b5 | 2013-10-26 14:31:11 +0000 | [diff] [blame^] | 255 | <td ng-repeat="categoryName in ['resultType', 'builder', 'test', 'config']"> |
| 256 | {{result[categoryName]}} |
| 257 | </td> |
| 258 | <td> |
| 259 | <a ng-repeat="bug in result['bugs']" |
| 260 | href="https://code.google.com/p/skia/issues/detail?id={{bug}}" |
| 261 | target="_blank"> |
| 262 | {{bug}} |
| 263 | </a> |
| 264 | </td> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 265 | <td> |
| epoger@google.com | dcb4e65 | 2013-10-11 18:45:33 +0000 | [diff] [blame] | 266 | <a target="_blank" href="http://chromium-skia-gm.commondatastorage.googleapis.com/gm/{{result.expectedHashType}}/{{result.test}}/{{result.expectedHashDigest}}.png"> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 267 | <img width="{{imageSize}}" src="http://chromium-skia-gm.commondatastorage.googleapis.com/gm/{{result.expectedHashType}}/{{result.test}}/{{result.expectedHashDigest}}.png"/> |
| 268 | </a> |
| 269 | </td> |
| 270 | <td> |
| epoger@google.com | dcb4e65 | 2013-10-11 18:45:33 +0000 | [diff] [blame] | 271 | <a target="_blank" href="http://chromium-skia-gm.commondatastorage.googleapis.com/gm/{{result.actualHashType}}/{{result.test}}/{{result.actualHashDigest}}.png"> |
| 272 | <img width="{{imageSize}}" src="http://chromium-skia-gm.commondatastorage.googleapis.com/gm/{{result.actualHashType}}/{{result.test}}/{{result.actualHashDigest}}.png"/> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 273 | </a> |
| 274 | </td> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 275 | <td> |
| epoger@google.com | 9fb6c8a | 2013-10-09 18:05:58 +0000 | [diff] [blame] | 276 | <input type="checkbox" |
| 277 | name="rowSelect" |
| 278 | value="{{result.index}}" |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 279 | ng-checked="isValueInArray(result.index, selectedItems)" |
| 280 | ng-click="toggleValueInArray(result.index, selectedItems)"> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 281 | </tr> |
| 282 | </table> |
| epoger@google.com | ad0e552 | 2013-10-24 15:38:27 +0000 | [diff] [blame] | 283 | </div><!-- main display area of selected tab --> |
| epoger@google.com | eb83259 | 2013-10-23 15:07:26 +0000 | [diff] [blame] | 284 | </div><!-- everything: hide until data is loaded --> |
| epoger@google.com | f9d134d | 2013-09-27 15:02:44 +0000 | [diff] [blame] | 285 | |
| 286 | <!-- TODO(epoger): Can we get the base URLs (commondatastorage and |
| 287 | issues list) from |
| 288 | http://skia.googlecode.com/svn/buildbot/site_config/global_variables.json |
| 289 | ? I tried importing the |
| 290 | http://skia.googlecode.com/svn/buildbot/skia_tools.js script and using |
| 291 | that to do so, but I got Access-Control-Allow-Origin errors. |
| 292 | --> |
| 293 | |
| 294 | </body> |
| 295 | </html> |