| <!-- |
| The <newsearch-page-sk> custom element declaration. |
| |
| Shows the results of a search request. |
| It sends the query string as a JSON request to the |
| search entpoint ('/json/search') and renders the result. |
| |
| It assumes to the be part of a client site routed system |
| of views and therefore offers the 'pageSelected' and 'pageUnselected' |
| functions. These need to be called whenever the page goes |
| in and out of view. |
| |
| Attributes: |
| None |
| |
| Methods: |
| pageSelected(ctx) - Called by the router when the view becomes visible. |
| ctx is the context provided in the route dispatch of page.js. |
| |
| pageDeselected - Called by the router when the view is no longer visible. |
| |
| Events: |
| None |
| |
| Mailboxes: |
| None |
| --> |
| |
| <link rel="import" href="bower_components/polymer/polymer.html"> |
| <link rel="import" href="bower_components/iron-flex-layout/iron-flex-layout-classes.html"> |
| <link rel="import" href="bower_components/iron-icons/iron-icons.html"> |
| <link rel="import" href="bower_components/paper-dialog/paper-dialog.html"> |
| <link rel="import" href="bower_components/paper-button/paper-button.html"> |
| <link rel="import" href="bower_components/paper-menu-button/paper-menu-button.html"> |
| |
| <link rel="import" href="activity-sk.html"> |
| <link rel=import href="detail-list-sk.html"> |
| <link rel=import href="newdigest-details-sk.html"> |
| <link rel=import href="search-controls-sk.html"> |
| <link rel=import href="trybot-controls-sk.html"> |
| <link rel="import" href="../common/imp/triage-sk.html"> |
| |
| <dom-module id="newsearch-page-sk"> |
| <template> |
| <style include="iron-flex iron-flex-alignment"></style> |
| <style include="shared-styles"> |
| newdigest-details-sk { |
| display: block; |
| box-shadow: 3px 3px 6px 1px rgba(133,133,133,1); |
| margin-top: 1em; |
| margin-bottom: 1em; |
| margin-left: 0; |
| margin-right: 0; |
| padding-left: 1em; |
| padding-top: 1em; |
| padding-bottom: 1em; |
| padding-right: 0; |
| } |
| |
| newdigest-details-sk[data-focus] { |
| box-shadow: 3px 3px 6px 5px #FF7F00; |
| } |
| |
| #missing { |
| padding-top: 2em; |
| } |
| |
| .searchPageWrapper { |
| padding-left: 1em; |
| padding-top: 1em; |
| margin-left:1em; |
| margin-right: 3em; |
| } |
| |
| #triggerSearchButton { |
| font-size: 18px; |
| } |
| |
| .helpIconContainer { |
| padding-left: 3em; |
| } |
| |
| paper-button { |
| min-width: 2em; |
| margin: 5px; |
| background: #eee; |
| } |
| |
| .actionMenu { |
| max-width: 10em; |
| margin-left: 10em; |
| } |
| |
| .actionButton { |
| color: green; |
| }; |
| |
| #closestButton[raised] > iron-icon { |
| color: #bbb; |
| } |
| |
| #closestButton[raised] { |
| background: #fff; |
| } |
| |
| #closestButton:hover, |
| #closestButton[raised]:hover { |
| background: #ddd; |
| } |
| |
| .searchResponse { |
| padding: 1em; |
| margin: 1em 1em 1em 0; |
| border: 1px solid #555555; |
| } |
| </style> |
| |
| <div class="searchPageWrapper layout vertical"> |
| <activity-sk id="activityBar" busy="{{_hideAll}}"></activity-sk> |
| <div class="layout horizontal"> |
| <search-controls-sk id="searchControls" beta></search-controls-sk> |
| <div> |
| <paper-button id="triggerSearchButton" raised disabled="[[_hideAll]]">Search</paper-button> |
| </div> |
| |
| <paper-menu-button close-on-activate no-animations class="actionMenu"> |
| <paper-button class="dropdown-trigger actionButton" raised>Actions</paper-button> |
| <paper-menu class="dropdown-content"> |
| <paper-item id="actionTestView">Switch To Test View</paper-item> |
| <paper-item id="actionBulkTriage">Bulk Triage</paper-item> |
| <paper-item id="actionLegacySearch">Legacy Search</paper-item> |
| <paper-item id="actionHelpDialog">Help</paper-item> |
| </paper-menu> |
| </paper-menu-button> |
| </div> |
| |
| <div class="searchResponse" hidden$="[[_noResult(_allData)]]"> |
| Displaying: [[_allData.size]] / [[_allData.digests.length]] @ [[_allData.offset]]<br> |
| UniqueTests: [[_uniqueTests.length]] <br> |
| UniqueTests All: [[_uniqueTestsAll.length]]<br> |
| </div> |
| <trybot-controls-sk id="trybotControls"></trybot-controls-sk> |
| |
| <div hidden$="[[_hideAll]]"> |
| <div id="missing" hidden$="[[_nonEmptyResult(data)]]"> |
| No digests match your query. |
| </div> |
| <div hidden$="[[_emptyResult(data)]]"> |
| <detail-list-sk id="detailList"> |
| <template is="dom-repeat" items="[[data.digests]]"> |
| <newdigest-details-sk |
| id$="[[_entryId(item)]]" |
| mode="list" |
| triage |
| details="[[item]]" |
| commits="[[data.commits]]" |
| metric="[[_state.metric]]"> |
| </newdigest-details-sk> |
| </template> |
| </detail-list-sk> |
| </div> |
| </div> |
| </div> |
| <paper-dialog id="bulkDialog" with-backdrop> |
| <h2>Bulk Triage</h2> |
| <p>Assign the status to all images on this page at once.</p> |
| <div class="layout horizontal"> |
| <triage-sk value="{{_bulkStatus}}" id="triageControls"></triage-sk> |
| <paper-button id="closestButton" on-tap="_handleClosestButton" title="Assign status of closest image"> |
| <iron-icon icon="icons:view-agenda"></iron-icon> |
| </paper-button> |
| </div> |
| <div> |
| </div> |
| <div class="buttons"> |
| "{{_bulkStatus}}" |
| <paper-button raise dialog-dismiss>Cancel</paper-button> |
| <paper-button raise dialog-dismiss on-tap="_doBulkTriage" disabled="[[!_bulkStatus]]">Triage</paper-button> |
| </div> |
| </paper-dialog> |
| |
| </template> |
| <script> |
| Polymer({ |
| is: "newsearch-page-sk", |
| |
| behaviors: [gold.PageStateBehavior], |
| |
| properties: { |
| data: { |
| type: Object, |
| value: function() { return {}; } |
| }, |
| |
| _bulkStatus: { |
| type: String, |
| value: "", |
| observer: "_handleBulkStatusChanged" |
| } |
| }, |
| |
| ready: function() { |
| this.listen(this.$.searchControls, 'state-change', '_handleStateChange'); |
| this.listen(this.$.triggerSearchButton, 'tap', '_handleSearchButton'); |
| this.listen(this.$.actionTestView, 'tap', '_handleSwitchToByTest'); |
| this.listen(this.$.actionBulkTriage, 'tap', '_handleBulkButton'); |
| this.listen(this.$.actionLegacySearch, 'tap', '_handleLegacySearchButton'); |
| this.listen(this.$.actionHelpDialog, 'tap', '_openHelpDialog'); |
| this._setDefaultState(gold.defaultSearchState, false); |
| }, |
| |
| pageSelected: function(ctx) { |
| this.set('data', {}); |
| this.set('_allData', {}); |
| this.$.detailList.startUse(); |
| |
| // Initialize the state and set values of the controls. |
| this._initState(ctx, this._getDefaultStateWithCorpus()); |
| this.$.searchControls.setState(this._state); |
| |
| // _loadParamset will also trigger loading the data. |
| this._loadParamset(); |
| }, |
| |
| pageDeselected: function() { |
| this.$.detailList.endUse(); |
| }, |
| |
| _handleSearchButton: function(ev) { |
| // Reload the page with the current state of the controls. |
| this._redirectToState(this.$.searchControls.state); |
| }, |
| |
| _handleStateChange: function(ev) { |
| // Reload the page with the new state in the query parameters. |
| this._redirectToState(ev.detail); |
| }, |
| |
| _handleSwitchToByTest: function() { |
| this._redirectToState({}, "/list"); |
| }, |
| |
| _openHelpDialog: function(ev) { |
| this.$.detailList.openHelpDialog(); |
| }, |
| |
| _handleBulkButton: function(ev) { |
| this.set("_bulkStatus", ""); |
| this.$.bulkDialog.open(); |
| }, |
| |
| _handleLegacySearchButton: function(ev) { |
| this._redirectToState({}, "/search"); |
| }, |
| |
| _handleClosestButton: function(ev) { |
| this.set("_bulkStatus", '='); |
| }, |
| |
| _handleBulkStatusChanged: function(newVal) { |
| if (newVal === '=') { |
| Polymer.dom(this.$.closestButton).removeAttribute('raised'); |
| } else { |
| Polymer.dom(this.$.closestButton).setAttribute('raised', ''); |
| } |
| }, |
| |
| _doBulkTriage: function(ev) { |
| var targetStatus = this.$.triageControls.value; |
| var digests = this.data.digests; |
| var triageList = []; |
| if (targetStatus === '=') { |
| for(var i=0; i < digests.length; i++) { |
| var element= this.$$('#' + this._entryId(digests[i])); |
| if (element) { |
| var status = element.statusClosest(); |
| if (status) { |
| triageList.push([digests[i].test, digests[i].digest, status]); |
| } |
| } |
| } |
| } else { |
| for(var i=0; i < digests.length; i++) { |
| triageList.push([digests[i].test, digests[i].digest, targetStatus]); |
| } |
| } |
| var query = gold.makeTriageQuery(triageList); |
| this.$.activityBar.startSpinner("Triaging ..."); |
| sk.post('/json/triage', JSON.stringify(query)).then(function() { |
| this.$.activityBar.stopSpinner(); |
| }.bind(this)).catch(function(e) { |
| this.$.activityBar.stopSpinner(); |
| sk.errorMessage(e); |
| }.bind(this)); |
| }, |
| |
| _load: function() { |
| var q = window.location.search; |
| sk.get("/json/newsearch" + q).then(JSON.parse).then(function (json) { |
| // Split out the digests that are being displayed and keep a copy |
| // of all digests that matched the query. |
| var displayData = sk.object.shallowCopy(json); |
| displayData.digests = displayData.digests.slice(json.offset, json.offset+json.size); |
| this.set('_allData', json); |
| |
| this.set('_uniqueTestsAll', this._getUniqueTests(json.digests)); |
| this.set('_uniqueTests', this._getUniqueTests(displayData.digests)); |
| |
| this.set('data', displayData); |
| this.$.trybotControls.setIssue(json.issue); |
| this.$.activityBar.stopSpinner(); |
| }.bind(this)).catch(function(e) { |
| this.$.activityBar.stopSpinner(); |
| sk.errorMessage(e); |
| }.bind(this)); |
| }, |
| |
| _getUniqueTests: function(digests) { |
| var unique = {}; |
| for(var i=0; i < digests.length; i++) { |
| unique[digests[i].test] = true; |
| } |
| return Object.keys(unique); |
| }, |
| |
| _loadParamset: function() { |
| this.$.activityBar.startSpinner("Loading ..."); |
| |
| // If we already have a paramset then trigger load right away. |
| // TODO(stephana): Improve this so that we load the paramset with the |
| // data. |
| var loadTriggered = false; |
| if (this._paramSet) { |
| this._load(); |
| loadTriggered = true; |
| } |
| |
| sk.get("/json/paramset").then(JSON.parse).then(function (json) { |
| this.$.searchControls.setParamSet(json); |
| this._paramSet = json; |
| if (!loadTriggered) { |
| this._load(); |
| } |
| }.bind(this)).catch(sk.errorMessage); |
| }, |
| |
| _entryId: function(item) { |
| // Make sure it's a valid selector. |
| return (item.test + '_' + item.digest).replace(/[^_A-Za-z0-9]/g, '_'); |
| }, |
| |
| // Returns true if there was a query and result is not empty. |
| _nonEmptyResult: function(data) { |
| return !data.digests || data.digests.length > 0; |
| }, |
| |
| // Returns true if there was a query and the result is empty. |
| _emptyResult: function(data) { |
| return !data.digests || data.digests.length === 0; |
| }, |
| |
| _noResult: function(data) { |
| return !data.digests; |
| } |
| }); |
| </script> |
| </dom-module> |