1 <!-- 2 Copyright 2014 The Chromium Authors. All rights reserved. 3 Use of this source code is governed by a BSD-style license that can be 4 found in the LICENSE file. 5 --> 6 7 <link rel="import" href="../lib/sugar.html"> 8 <script src="../scripts/results.js"></script> 9 10 <link rel="import" href="../bower_components/core-animated-pages/core-animated-pages.html"> 11 <link rel="import" href="../bower_components/core-animated-pages/transitions/slide-from-right.html"> 12 <link rel="import" href="../lib/ct-scheduled-updater.html"> 13 <link rel="import" href="../model/ct-commit-log.html"> 14 <link rel="import" href="../model/ct-failures.html"> 15 <link rel="import" href="../model/ct-tree-list.html"> 16 <link rel="import" href="ct-results-panel.html"> 17 <link rel="import" href="ct-tree-select.html"> 18 <link rel="import" href="ct-unexpected-failures.html"> 19 20 <polymer-element name="ct-sheriff-o-matic"> 21 <template> 22 <style> 23 :host { 24 display: flex; 25 flex-direction: column; 26 height: 100%; 27 } 28 header { 29 -webkit-user-select: none; 30 align-items: center; 31 background-color: #212121; 32 color: white; 33 cursor: default; 34 display: flex; 35 flex-wrap: wrap; 36 justify-content: space-between; 37 font-size: 1.1em; 38 padding: 0 5px; 39 white-space: nowrap; 40 } 41 header a, header span { 42 color: white; 43 display: inline-block; 44 padding: 0.25em 4px; 45 text-decoration: none; 46 } 47 #right-toolbar { 48 display: flex; 49 flex-wrap: wrap; 50 align-items: center; 51 } 52 ct-last-updated { 53 margin: 0 5px; 54 } 55 core-animated-pages { 56 flex: 1; 57 } 58 core-animated-pages > * { 59 overflow: auto; 60 } 61 </style> 62 63 <header> 64 <div> 65 <template if="{{ selected == 0 }}"> 66 <img src="../favicon.ico"> <span>Sheriff-o-matic</span> 67 </template> 68 <template if="{{ selected == 1 }}"> 69 <a on-click="{{ onBack }}" href=""> 70 << Go back 71 </a> 72 </template> 73 </div> 74 <div id="right-toolbar"> 75 <ct-last-updated date="{{ failures.lastUpdateDate }}"></ct-last-updated> 76 <ct-tree-select tree="{{ tree }}" treeList="{{ treeList }}"></ct-tree-select> 77 </div> 78 </header> 79 80 <core-animated-pages selected="{{ selected }}" transitions="slide-from-right"> 81 <ct-unexpected-failures id="unexpected" tree="{{ tree }}" commitLog="{{ commitLog }}" failures="{{ failures }}" on-ct-examine-failures="{{ onExamine }}"></ct-unexpected-failures> 82 <ct-results-panel group="{{ examinedFailureGroup }}"></ct-results-panel> 83 </core-animated-pages> 84 </template> 85 <script> 86 var kUpdateFrequency = 1000 * 30; 87 88 Polymer({ 89 tree: '', 90 treeList: null, 91 selected: 0, 92 examinedFailureGroup: null, 93 _pendingFailureGroupKey: '', 94 95 updateFromHistoryState: function(state) { 96 this._pendingFailureGroupKey = state.examinedFailureGroupKey; 97 if ('selected' in state) 98 this.selected = state.selected; 99 }, 100 101 onPopState: function(e) { 102 this.updateFromHistoryState(e.state); 103 }, 104 105 onBack: function(event) { 106 if (event.button == 0) { 107 window.history.back(); 108 event.preventDefault(); 109 } 110 }, 111 112 onExamine: function(event) { 113 window.history.pushState({ 114 examinedFailureGroupKey: event.detail.key, 115 selected: 1, 116 }); 117 118 119 this.examinedFailureGroup = event.detail; 120 this.selected = 1; 121 }, 122 123 created: function() { 124 this.treeList = new CTTreeList(); 125 this.tree = this.treeList.defaultValue(); 126 this.commitLog = new CTCommitLog(); 127 this.failures = new CTFailures(this.commitLog); 128 this._updater = new CTScheduledUpdater(this.update.bind(this), kUpdateFrequency); 129 130 // History API handling: 131 // If we have a current state, we should make sure the view is shown 132 // accordingly. 133 // Otherwise, we should inject a state using replaceState() so we can 134 // handle history navigation cleanly. 135 // Either way, the object will react to popstate events. 136 if (window.history.state) { 137 // Will be a no-op if the current state is already being used. 138 this.updateFromHistoryState(window.history.state); 139 } else { 140 window.history.replaceState({ 141 selected: 0, 142 }); 143 } 144 145 window.addEventListener('popstate', this.onPopState.bind(this)); 146 }, 147 148 ready: function() { 149 this.update(); 150 }, 151 152 update: function() { 153 if (this._promise) 154 return; 155 this._promise = Promise.all( 156 [this.commitLog.update(), 157 this.failures.update()]).then(this._updateCompleted.bind(this)); 158 }, 159 160 _updateCompleted: function() { 161 this._promise = null; 162 this.$.unexpected.update(); 163 if (!this.failures.failures) 164 return; 165 if (!this._pendingFailureGroupKey) 166 return; 167 this.examinedFailureGroup = this.failures.failures[this.tree].find(function(group) { 168 return group.key == this._pendingFailureGroupKey; 169 }.bind(this)); 170 this._pendingFailureGroupKey = ''; 171 }, 172 173 }); 174 </script> 175 </polymer-element> 176