| OLD | NEW |
| 1 <!DOCTYPE html><html><head><!-- | 1 <!DOCTYPE html><html><head><!-- |
| 2 @license | 2 @license |
| 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. | 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also | 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --><!-- | 9 --><!-- |
| 10 @license | 10 @license |
| (...skipping 14616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14627 <style> | 14627 <style> |
| 14628 * { | 14628 * { |
| 14629 font-family: sans-serif; | 14629 font-family: sans-serif; |
| 14630 } | 14630 } |
| 14631 /* Only style anchor tags that are actually linking somewhere.*/ | 14631 /* Only style anchor tags that are actually linking somewhere.*/ |
| 14632 a[href] { | 14632 a[href] { |
| 14633 color: #1F78B4; | 14633 color: #1F78B4; |
| 14634 } | 14634 } |
| 14635 </style> | 14635 </style> |
| 14636 </dom-module> | 14636 </dom-module> |
| 14637 | |
| 14638 <script> | |
| 14639 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; | |
| 14640 (function(){ | |
| 14641 // This behavior wraps up all the shared swarming functionality. | |
| 14642 SwarmingBehaviors.SwarmingBehavior = { | |
| 14643 | |
| 14644 _not: function(a) { | |
| 14645 return !a; | |
| 14646 }, | |
| 14647 | |
| 14648 _or: function() { | |
| 14649 var result = false; | |
| 14650 // can't use .foreach, as arguments isn't really an Array. | |
| 14651 for (var i = 0; i < arguments.length; i++) { | |
| 14652 result = result || arguments[i]; | |
| 14653 } | |
| 14654 return result; | |
| 14655 }, | |
| 14656 }; | |
| 14657 })(); | |
| 14658 </script> | |
| 14659 <dom-module id="swarming-index" assetpath="/res/imp/index/"> | 14637 <dom-module id="swarming-index" assetpath="/res/imp/index/"> |
| 14660 <template> | 14638 <template> |
| 14661 <style include="swarming-app-style"> | 14639 <style include="swarming-app-style"> |
| 14662 | 14640 |
| 14663 </style> | 14641 </style> |
| 14664 | 14642 |
| 14665 <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" name
="Swarming" busy="[[busy]]"> | 14643 <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" name
="Swarming" busy="[[busy]]"> |
| 14666 | 14644 |
| 14667 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers=
"[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{
{busy}}"> | 14645 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers=
"[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{
{busy}}"> |
| 14668 </iron-ajax> | 14646 </iron-ajax> |
| (...skipping 23 matching lines...) Expand all Loading... |
| 14692 type: String, | 14670 type: String, |
| 14693 } | 14671 } |
| 14694 }, | 14672 }, |
| 14695 | 14673 |
| 14696 signIn: function(){ | 14674 signIn: function(){ |
| 14697 this.$.request.generateRequest(); | 14675 this.$.request.generateRequest(); |
| 14698 }, | 14676 }, |
| 14699 | 14677 |
| 14700 }); | 14678 }); |
| 14701 </script> | 14679 </script> |
| 14702 </dom-module><dom-module id="dynamic-table-style" assetpath="/res/imp/common/"> | 14680 </dom-module><script> |
| 14681 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; |
| 14682 (function(){ |
| 14683 // This behavior wraps up all the shared swarming functionality. |
| 14684 SwarmingBehaviors.CommonBehavior = { |
| 14685 |
| 14686 _not: function(a) { |
| 14687 return !a; |
| 14688 }, |
| 14689 |
| 14690 _or: function() { |
| 14691 var result = false; |
| 14692 // can't use .foreach, as arguments isn't really an Array. |
| 14693 for (var i = 0; i < arguments.length; i++) { |
| 14694 result = result || arguments[i]; |
| 14695 } |
| 14696 return result; |
| 14697 }, |
| 14698 }; |
| 14699 })(); |
| 14700 </script> |
| 14701 <dom-module id="dynamic-table-style" assetpath="/res/imp/common/"> |
| 14703 <template> | 14702 <template> |
| 14704 <style> | 14703 <style> |
| 14705 table { | 14704 table { |
| 14706 border-collapse: collapse; | 14705 border-collapse: collapse; |
| 14707 margin-left: 5px; | 14706 margin-left: 5px; |
| 14708 } | 14707 } |
| 14709 td, th { | 14708 td, th { |
| 14710 border: 1px solid #DDD; | 14709 border: 1px solid #DDD; |
| 14711 padding: 5px; | 14710 padding: 5px; |
| 14712 } | 14711 } |
| 14713 th { | 14712 th { |
| 14714 position: relative; | 14713 position: relative; |
| 14715 } | 14714 } |
| 14716 sort-toggle { | 14715 sort-toggle { |
| 14717 position: absolute; | 14716 position: absolute; |
| 14718 right: 0; | 14717 right: 0; |
| 14719 top: 0.4em; | 14718 top: 0.4em; |
| 14720 } | 14719 } |
| 14721 </style> | 14720 </style> |
| 14722 | 14721 |
| 14723 </template> | 14722 </template> |
| 14724 </dom-module> | 14723 </dom-module> |
| 14725 | 14724 |
| 14726 <script> | 14725 <script> |
| 14727 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; | |
| 14728 (function(){ | 14726 (function(){ |
| 14729 // This behavior wraps up all the shared swarming functionality. | 14727 // This behavior wraps up all the shared swarming functionality. |
| 14730 SwarmingBehaviors.DynamicTableBehavior = { | 14728 SwarmingBehaviors.DynamicTableBehavior = [SwarmingBehaviors.CommonBehavior,
{ |
| 14731 | 14729 |
| 14732 properties: { | 14730 properties: { |
| 14733 | 14731 |
| 14734 _columns: { | 14732 _columns: { |
| 14735 type: Array, | 14733 type: Array, |
| 14736 }, | 14734 }, |
| 14737 | 14735 |
| 14738 _filter: { | 14736 _filter: { |
| 14739 type: Function, | 14737 type: Function, |
| 14740 }, | 14738 }, |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14848 }, | 14846 }, |
| 14849 // _stripSpecial removes the special columns and sorts the remaining | 14847 // _stripSpecial removes the special columns and sorts the remaining |
| 14850 // columns so they always appear in the same order, regardless of | 14848 // columns so they always appear in the same order, regardless of |
| 14851 // the order they are added. | 14849 // the order they are added. |
| 14852 _stripSpecial: function(){ | 14850 _stripSpecial: function(){ |
| 14853 return this._columns.filter(function(c) { | 14851 return this._columns.filter(function(c) { |
| 14854 return this._specialColumns.indexOf(c) === -1; | 14852 return this._specialColumns.indexOf(c) === -1; |
| 14855 }.bind(this)).sort(); | 14853 }.bind(this)).sort(); |
| 14856 }, | 14854 }, |
| 14857 | 14855 |
| 14858 }; | 14856 // Common columns shared between tasklist and botlist |
| 14857 _commonColumns: function() { |
| 14858 // return a fresh object so all elements have their own copy |
| 14859 return { |
| 14860 android_devices: function(bot) { |
| 14861 var devs = this._attribute(bot, "android_devices", "0"); |
| 14862 if (this._verbose) { |
| 14863 return devs.join(" | ") + " devices available"; |
| 14864 } |
| 14865 // max() works on strings as long as they can be coerced to Number. |
| 14866 return Math.max(...devs) + " devices available"; |
| 14867 }, |
| 14868 device_type: function(bot) { |
| 14869 var dt = this._attribute(bot, "device_type", "none"); |
| 14870 dt = dt[0]; |
| 14871 var alias = swarming.alias.android(dt); |
| 14872 if (alias === "unknown") { |
| 14873 return dt; |
| 14874 } |
| 14875 return swarming.alias.apply(dt, alias); |
| 14876 }, |
| 14877 gpu: function(bot){ |
| 14878 var gpus = this._attribute(bot, "gpu", "none"); |
| 14879 var verbose = [] |
| 14880 var named = []; |
| 14881 // non-verbose mode has only the top level GPU info "e.g. NVidia" |
| 14882 // which is found by looking for gpu ids w/o a colon. |
| 14883 gpus.forEach(function(g){ |
| 14884 var alias = swarming.alias.gpu(g); |
| 14885 if (alias === "unknown") { |
| 14886 verbose.push(g); |
| 14887 if (g.indexOf(":") === -1) { |
| 14888 named.push(g); |
| 14889 } |
| 14890 return; |
| 14891 } |
| 14892 verbose.push(swarming.alias.apply(g, alias)); |
| 14893 if (g.indexOf(":") === -1) { |
| 14894 named.push(swarming.alias.apply(g, alias)); |
| 14895 } |
| 14896 }.bind(this)) |
| 14897 if (this._verbose || !named.length) { |
| 14898 return verbose.join(" | "); |
| 14899 } |
| 14900 return named.join(" | "); |
| 14901 }, |
| 14902 pool: function(bot) { |
| 14903 var pool = this._attribute(bot, "pool"); |
| 14904 return pool.join(" | "); |
| 14905 }, |
| 14906 }; |
| 14907 }, |
| 14908 |
| 14909 |
| 14910 }]; |
| 14859 })(); | 14911 })(); |
| 14860 </script> | 14912 </script> |
| 14861 | 14913 |
| 14862 <script> | 14914 <script> |
| 14863 | 14915 |
| 14864 (function() { | 14916 (function() { |
| 14865 | 14917 |
| 14866 // monostate data | 14918 // monostate data |
| 14867 var metaDatas = {}; | 14919 var metaDatas = {}; |
| 14868 var metaArrays = {}; | 14920 var metaArrays = {}; |
| (...skipping 7990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22859 <script> | 22911 <script> |
| 22860 Polymer({ | 22912 Polymer({ |
| 22861 is: 'paper-input', | 22913 is: 'paper-input', |
| 22862 | 22914 |
| 22863 behaviors: [ | 22915 behaviors: [ |
| 22864 Polymer.IronFormElementBehavior, | 22916 Polymer.IronFormElementBehavior, |
| 22865 Polymer.PaperInputBehavior | 22917 Polymer.PaperInputBehavior |
| 22866 ] | 22918 ] |
| 22867 }); | 22919 }); |
| 22868 </script> | 22920 </script> |
| 22869 <script> | 22921 <dom-module id="query-column-filter-style" assetpath="/res/imp/common/"> |
| 22870 (function(){ | |
| 22871 var ANDROID_ALIASES = { | |
| 22872 "bullhead": "Nexus 5X", | |
| 22873 "flo": "Nexus 7 (2013)", | |
| 22874 "flounder": "Nexus 9", | |
| 22875 "foster": "NVIDIA Shield", | |
| 22876 "fugu": "Nexus Player", | |
| 22877 "grouper": "Nexus 7 (2012)", | |
| 22878 "hammerhead": "Nexus 5", | |
| 22879 "m0": "Galaxy S3", | |
| 22880 "mako": "Nexus 4", | |
| 22881 "manta": "Nexus 10", | |
| 22882 "shamu": "Nexus 6", | |
| 22883 "sprout": "Android One", | |
| 22884 }; | |
| 22885 // Taken from http://developer.android.com/reference/android/os/BatteryManag
er.html | |
| 22886 var BATTERY_HEALTH_UNKNOWN = 1; | |
| 22887 var BATTERY_HEALTH_GOOD = 2; | |
| 22888 var BATTERY_STATUS_CHARGING = 2; | |
| 22889 | |
| 22890 var UNAUTHENTICATED = "unauthenticated"; | |
| 22891 var AVAILABLE = "available"; | |
| 22892 var UNKNOWN = "unknown"; | |
| 22893 | |
| 22894 var GPU_ALIASES = { | |
| 22895 "1002": "AMD", | |
| 22896 "1002:6779": "AMD Radeon HD 6450/7450/8450", | |
| 22897 "1002:6821": "AMD Radeon HD 8870M", | |
| 22898 "1002:683d": "AMD Radeon HD 7770/8760", | |
| 22899 "1002:9830": "AMD Radeon HD 8400", | |
| 22900 "102b": "Matrox", | |
| 22901 "102b:0522": "Matrox MGA G200e", | |
| 22902 "102b:0532": "Matrox MGA G200eW", | |
| 22903 "102b:0534": "Matrox G200eR2", | |
| 22904 "10de": "NVIDIA", | |
| 22905 "10de:08a4": "NVIDIA GeForce 320M", | |
| 22906 "10de:08aa": "NVIDIA GeForce 320M", | |
| 22907 "10de:0fe9": "NVIDIA GeForce GT 750M Mac Edition", | |
| 22908 "10de:104a": "NVIDIA GeForce GT 610", | |
| 22909 "10de:11c0": "NVIDIA GeForce GTX 660", | |
| 22910 "10de:1244": "NVIDIA GeForce GTX 550 Ti", | |
| 22911 "10de:1401": "NVIDIA GeForce GTX 960", | |
| 22912 "8086": "Intel", | |
| 22913 "8086:0412": "Intel Haswell Integrated", | |
| 22914 "8086:041a": "Intel Xeon Integrated", | |
| 22915 "8086:0a2e": "Intel Haswell Integrated", | |
| 22916 "8086:0d26": "Intel Crystal Well Integrated", | |
| 22917 "8086:22b1": "Intel Braswell Integrated", | |
| 22918 } | |
| 22919 | |
| 22920 // For consistency, all aliases are displayed like: | |
| 22921 // Nexus 5X (bullhead) | |
| 22922 // This regex matches a string like "ALIAS (ORIG)", with ORIG as group 1. | |
| 22923 var ALIAS_REGEXP = /.+ \((.*)\)/; | |
| 22924 | |
| 22925 // This behavior wraps up all the shared bot-list functionality by | |
| 22926 // extending SwarmingBehaviors.SwarmingBehavior | |
| 22927 SwarmingBehaviors.BotListBehavior = [SwarmingBehaviors.SwarmingBehavior, { | |
| 22928 | |
| 22929 properties: { | |
| 22930 DIMENSIONS_WITH_ALIASES: { | |
| 22931 type: Array, | |
| 22932 value: function(){ | |
| 22933 return ["device_type", "gpu"]; | |
| 22934 }, | |
| 22935 }, | |
| 22936 BOT_PROPERTIES: { | |
| 22937 type: Array, | |
| 22938 value: function() { | |
| 22939 // TODO(kjlubick): Add more of these things from state, as they | |
| 22940 // needed/useful/requested. | |
| 22941 return ["disk_space", "task", "status"]; | |
| 22942 } | |
| 22943 }, | |
| 22944 }, | |
| 22945 | |
| 22946 _androidAlias: function(dt) { | |
| 22947 return ANDROID_ALIASES[dt] || UNKNOWN; | |
| 22948 }, | |
| 22949 | |
| 22950 // _applyAlias is the consistent way to modify a string to show its alias. | |
| 22951 _applyAlias: function(orig, alias) { | |
| 22952 return alias +" ("+orig+")"; | |
| 22953 }, | |
| 22954 | |
| 22955 // _attribute looks first in dimension and then in state for the | |
| 22956 // specified attribute. This will always return an array. If there is | |
| 22957 // no matching attribute, ["unknown"] will be returned. | |
| 22958 _attribute: function(bot, attr, none) { | |
| 22959 none = none || UNKNOWN; | |
| 22960 return this._dimension(bot, attr) || this._state(bot, attr) || [none]; | |
| 22961 }, | |
| 22962 | |
| 22963 _devices: function(bot) { | |
| 22964 var devices = []; | |
| 22965 var d = (bot && bot.state && bot.state.devices) || {}; | |
| 22966 // state.devices is like {Serial:Object}, so we need to keep the serial | |
| 22967 for (key in d) { | |
| 22968 var o = d[key]; | |
| 22969 o.serial = key; | |
| 22970 o.okay = (o.state === AVAILABLE); | |
| 22971 // It is easier to assume all devices on a bot are of the same type | |
| 22972 // than to pick through the (incomplete) device state and find it. | |
| 22973 o.device_type = this._attribute(bot, "device_type")[0]; | |
| 22974 devices.push(o); | |
| 22975 } | |
| 22976 return devices; | |
| 22977 }, | |
| 22978 | |
| 22979 // _deviceType returns the codename of a given Android device. | |
| 22980 _deviceType: function(device) { | |
| 22981 return device.device_type.toLowerCase(); | |
| 22982 }, | |
| 22983 | |
| 22984 // _dimension returns the given dimension of a bot. If it is defined, it | |
| 22985 // is an array of strings. | |
| 22986 _dimension: function(bot, dim) { | |
| 22987 if (!bot || !bot.dimensions || !dim) { | |
| 22988 return undefined; | |
| 22989 } | |
| 22990 for (var i = 0; i < bot.dimensions.length; i++) { | |
| 22991 if (bot.dimensions[i].key === dim) { | |
| 22992 return bot.dimensions[i].value; | |
| 22993 } | |
| 22994 } | |
| 22995 return undefined; | |
| 22996 }, | |
| 22997 | |
| 22998 _gpuAlias: function(gpu) { | |
| 22999 return GPU_ALIASES[gpu] || UNKNOWN; | |
| 23000 }, | |
| 23001 | |
| 23002 // _state returns the requested attribute from a bot's state. | |
| 23003 // For consistency with _dimension, if the attribute is not an array, | |
| 23004 // it is put as the only element in an array. | |
| 23005 _state: function(bot, attr) { | |
| 23006 if (!bot || !bot.state || !bot.state[attr]) { | |
| 23007 return undefined | |
| 23008 } | |
| 23009 var state = bot.state[attr]; | |
| 23010 if (Array.isArray(state)) { | |
| 23011 return state; | |
| 23012 } | |
| 23013 return [state]; | |
| 23014 }, | |
| 23015 | |
| 23016 _taskId: function(bot) { | |
| 23017 if (bot && bot.task_id) { | |
| 23018 return bot.task_id; | |
| 23019 } | |
| 23020 return "idle"; | |
| 23021 }, | |
| 23022 | |
| 23023 // _unalias will return the base dimension/state with its alias removed | |
| 23024 // if it had one. This is handy for sorting and filtering. | |
| 23025 _unalias: function(str) { | |
| 23026 var match = ALIAS_REGEXP.exec(str); | |
| 23027 if (match) { | |
| 23028 return match[1]; | |
| 23029 } | |
| 23030 return str; | |
| 23031 }, | |
| 23032 }]; | |
| 23033 })() | |
| 23034 </script> | |
| 23035 <dom-module id="bot-filters" assetpath="/res/imp/botlist/"> | |
| 23036 <template> | 22922 <template> |
| 23037 <style is="custom-style" include="iron-flex iron-flex-alignment iron-positio
ning"> | 22923 <style> |
| 23038 :host { | 22924 :host { |
| 23039 display: block; | 22925 display: block; |
| 23040 font-family: sans-serif; | 22926 font-family: sans-serif; |
| 23041 } | 22927 } |
| 23042 #filter { | 22928 #filter { |
| 23043 margin:0 5px; | 22929 margin:0 5px; |
| 23044 } | 22930 } |
| 23045 | 22931 |
| 23046 .container { | 22932 .container { |
| 23047 min-height: 120px; | 22933 min-height: 120px; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 23110 margin: 2px; | 22996 margin: 2px; |
| 23111 /* See https://sites.google.com/a/google.com/skia-infrastructure/design-
docs/general-design-guidance */ | 22997 /* See https://sites.google.com/a/google.com/skia-infrastructure/design-
docs/general-design-guidance */ |
| 23112 --paper-checkbox-checked-color: black; | 22998 --paper-checkbox-checked-color: black; |
| 23113 --paper-checkbox-checked-ink-color: black; | 22999 --paper-checkbox-checked-ink-color: black; |
| 23114 --paper-checkbox-unchecked-color: black; | 23000 --paper-checkbox-unchecked-color: black; |
| 23115 --paper-checkbox-unchecked-ink-color: black; | 23001 --paper-checkbox-unchecked-ink-color: black; |
| 23116 --paper-checkbox-label-color: black; | 23002 --paper-checkbox-label-color: black; |
| 23117 } | 23003 } |
| 23118 </style> | 23004 </style> |
| 23119 | 23005 |
| 23120 <url-param name="filters" value="{{_filters}}" default_values="[]" multi=""> | 23006 </template> |
| 23121 </url-param> | 23007 </dom-module> |
| 23122 <url-param name="columns" value="{{columns}}" default_values="["id"
;,"os","task","status"]" multi=""> | |
| 23123 </url-param> | |
| 23124 <url-param name="query" value="{{_query}}"> | |
| 23125 </url-param> | |
| 23126 <url-param name="verbose" value="{{verbose}}"> | |
| 23127 </url-param> | |
| 23128 <url-param name="limit" default_value="200" value="{{limit}}"> | |
| 23129 </url-param> | |
| 23130 | 23008 |
| 23131 <div class="container horizontal layout"> | 23009 <script> |
| 23132 | |
| 23133 | |
| 23134 <div class="narrow-down-selector"> | |
| 23135 <div> | |
| 23136 <paper-input id="filter" label="Search columns and filters" placeholde
r="gpu nvidia" value="{{_query}}"> | |
| 23137 </paper-input> | |
| 23138 </div> | |
| 23139 | |
| 23140 <div class="selector side-by-side" title="This shows all bot dimension n
ames and other interesting bot properties. Mark the check box to add as a column
. Select the row to see filter options."> | |
| 23141 <iron-selector attr-for-selected="label" selected="{{_primarySelected}
}"> | |
| 23142 <template is="dom-repeat" items="[[_primaryItems]]" as="item"> | |
| 23143 <div class="selectable item horizontal layout" label="[[item]]"> | |
| 23144 | |
| 23145 <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(ite
m,_query)]]</span>[[_afterBold(item,_query)]]</span> | |
| 23146 <span class="flex"></span> | |
| 23147 <paper-checkbox noink="" disabled$="[[_cantToggleColumn(item)]]"
checked="[[_columnState(item,columns.*)]]" on-change="_toggleColumn"> | |
| 23148 </paper-checkbox> | |
| 23149 </div> | |
| 23150 </template> | |
| 23151 </iron-selector> | |
| 23152 </div> | |
| 23153 | |
| 23154 <div class="selector side-by-side" title="These are all options (if any)
that the bot list can be filtered on."> | |
| 23155 <template is="dom-repeat" id="secondaryList" items="[[_secondaryItems]
]" as="item"> | |
| 23156 <div class="item horizontal layout" label="[[item]]"> | |
| 23157 | |
| 23158 <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(item,
_query)]]</span>[[_afterBold(item,_query)]]</span> | |
| 23159 <span class="flex"></span> | |
| 23160 <iron-icon class="icons" icon="icons:arrow-forward" hidden="[[_can
tAddFilter(_primarySelected,item,_filters.*)]]" on-tap="_addFilter"> | |
| 23161 </iron-icon> | |
| 23162 </div> | |
| 23163 </template> | |
| 23164 </div> | |
| 23165 | |
| 23166 <div class="selector side-by-side" title="These filters are AND'd togeth
er and applied to all bots in | |
| 23167 the fleet."> | |
| 23168 <template is="dom-repeat" items="[[_filters]]" as="fil"> | |
| 23169 <div class="item horizontal layout" label="[[fil]]"> | |
| 23170 <span>[[fil]]</span> | |
| 23171 <span class="flex"></span> | |
| 23172 <iron-icon class="icons" icon="icons:remove-circle-outline" hidden
="[[_cantRemoveFilter(fil,_filters.*)]]" on-tap="_removeFilter"> | |
| 23173 </iron-icon> | |
| 23174 </div> | |
| 23175 </template> | |
| 23176 </div> | |
| 23177 | |
| 23178 <div class="side-by-side"> | |
| 23179 <paper-checkbox checked="{{verbose}}">Verbose Entries</paper-checkbox> | |
| 23180 <paper-input id="limit" label="Limit Results" auto-validate="" min="0"
max="1000" pattern="[0-9]+" value="{{limit}}"> | |
| 23181 </paper-input> | |
| 23182 </div> | |
| 23183 </div> | |
| 23184 | |
| 23185 </div> | |
| 23186 | |
| 23187 </template> | |
| 23188 <script> | |
| 23189 (function(){ | 23010 (function(){ |
| 23190 var FILTER_SEP = ":"; | |
| 23191 // filterMap is a map of primary -> function. The function returns a | |
| 23192 // boolean "does the bot (first arg) match the second argument". These | |
| 23193 // functions will have "this" be the botlist, and will have access to all | |
| 23194 // functions defined in bot-list and bot-list-shared. If there is not | |
| 23195 // one provided, a default will be used, see _makeFilter(). | |
| 23196 var filterMap = { | |
| 23197 android_devices: function(bot, num) { | |
| 23198 var o = this._attribute(bot, "android_devices", "0"); | |
| 23199 return o.indexOf(num) !== -1; | |
| 23200 }, | |
| 23201 device_os: function(bot, os) { | |
| 23202 var o = this._attribute(bot, "device_os", "none"); | |
| 23203 return o.indexOf(os) !== -1; | |
| 23204 }, | |
| 23205 device_type: function(bot, dt) { | |
| 23206 var o = this._attribute(bot, "device_type", "none"); | |
| 23207 return o.indexOf(this._unalias(dt)) !== -1; | |
| 23208 }, | |
| 23209 disk_space: function(bot, space) { | |
| 23210 return true; | |
| 23211 }, | |
| 23212 gpu: function(bot, gpu) { | |
| 23213 var o = this._attribute(bot, "gpu", "none"); | |
| 23214 return o.indexOf(this._unalias(gpu)) !== -1; | |
| 23215 }, | |
| 23216 id: function(bot, id) { | |
| 23217 return true; | |
| 23218 }, | |
| 23219 status: function(bot, status) { | |
| 23220 if (status === "quarantined") { | |
| 23221 return bot.quarantined; | |
| 23222 } else if (status === "dead") { | |
| 23223 return bot.is_dead; | |
| 23224 } else { | |
| 23225 // Status must be "alive". | |
| 23226 return !bot.quarantined && !bot.is_dead; | |
| 23227 } | |
| 23228 }, | |
| 23229 task: function(bot, task) { | |
| 23230 if (task === "idle") { | |
| 23231 return this._taskId(bot) === "idle"; | |
| 23232 } | |
| 23233 // Task must be "busy". | |
| 23234 return this._taskId(bot) !== "idle"; | |
| 23235 } | |
| 23236 }; | |
| 23237 | |
| 23238 // Given a space separated list of queries, matchPartCaseInsensitive | 23011 // Given a space separated list of queries, matchPartCaseInsensitive |
| 23239 // returns an object of any query that matches a part of str, case | 23012 // returns an object of any query that matches a part of str, case |
| 23240 // insensitive. The object has an idx (index) and the part that matched. | 23013 // insensitive. The object has an idx (index) and the part that matched. |
| 23241 var matchPartCaseInsensitive = function(str, queries) { | 23014 var matchPartCaseInsensitive = function(str, queries) { |
| 23242 if (!queries) { | 23015 if (!queries) { |
| 23243 return { | 23016 return { |
| 23244 idx: 0, | 23017 idx: 0, |
| 23245 part: "", | 23018 part: "", |
| 23246 }; | 23019 }; |
| 23247 } | 23020 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23260 idx: idx, | 23033 idx: idx, |
| 23261 part: xq[i], | 23034 part: xq[i], |
| 23262 }; | 23035 }; |
| 23263 } | 23036 } |
| 23264 } | 23037 } |
| 23265 return { | 23038 return { |
| 23266 idx: -1, | 23039 idx: -1, |
| 23267 }; | 23040 }; |
| 23268 }; | 23041 }; |
| 23269 | 23042 |
| 23270 Polymer({ | 23043 // Extend the Aliases behavior |
| 23271 is: "bot-filters", | 23044 SwarmingBehaviors.QueryColumnFilter = [SwarmingBehaviors.CommonBehavior, { |
| 23272 | |
| 23273 behaviors: [SwarmingBehaviors.BotListBehavior], | |
| 23274 | 23045 |
| 23275 properties: { | 23046 properties: { |
| 23276 // input | 23047 // input |
| 23277 primary_map: { | 23048 primary_map: { |
| 23278 type: Object, | 23049 type: Object, |
| 23279 }, | 23050 }, |
| 23280 primary_arr: { | 23051 primary_arr: { |
| 23281 type: Array, | 23052 type: Array, |
| 23282 }, | 23053 }, |
| 23283 dimensions: { | 23054 dimensions: { |
| 23284 type: Array, | 23055 type: Array, |
| 23285 }, | 23056 }, |
| 23286 | |
| 23287 // output | 23057 // output |
| 23288 columns: { | |
| 23289 type: Array, | |
| 23290 notify: true, | |
| 23291 }, | |
| 23292 filter: { | 23058 filter: { |
| 23293 type: Function, | 23059 type: Function, |
| 23294 computed: "_makeFilter(_filters.*)", | 23060 computed: "_makeFilter(_filters.*)", |
| 23295 notify: true, | 23061 notify: true, |
| 23296 }, | 23062 }, |
| 23297 query_params: { | |
| 23298 type: Object, | |
| 23299 computed: "_extractQueryParams(dimensions.*,_filters.*, limit)", | |
| 23300 notify: true, | |
| 23301 }, | |
| 23302 verbose: { | |
| 23303 type: Boolean, | |
| 23304 notify: true, | |
| 23305 }, | |
| 23306 | 23063 |
| 23307 // private | 23064 // private |
| 23065 FILTER_SEP: { |
| 23066 type:String, |
| 23067 value: ":", |
| 23068 }, |
| 23308 _filters: { | 23069 _filters: { |
| 23309 type:Array, | 23070 type:Array, |
| 23310 }, | 23071 }, |
| 23311 _limit: { | 23072 _limit: { |
| 23312 type: Number, | 23073 type: Number, |
| 23313 }, | 23074 }, |
| 23314 _primaryItems: { | 23075 _primaryItems: { |
| 23315 type: Array, | 23076 type: Array, |
| 23316 computed: "_primary(_query, primary_map, primary_arr, columns.*)", | 23077 computed: "_primary(_query, primary_map, primary_arr, columns.*)", |
| 23317 }, | 23078 }, |
| 23318 _primarySelected: { | 23079 _primarySelected: { |
| 23319 type: String, | 23080 type: String, |
| 23320 value: "", | 23081 value: "", |
| 23321 }, | 23082 }, |
| 23322 // query is treated as a space separated list. | 23083 // query is treated as a space separated list. |
| 23323 _query: { | 23084 _query: { |
| 23324 type:String, | 23085 type:String, |
| 23325 }, | 23086 }, |
| 23326 _secondaryItems: { | 23087 _secondaryItems: { |
| 23327 type: Array, | 23088 type: Array, |
| 23328 computed: "_secondary(_primarySelected, _query, primary_map)", | 23089 computed: "_secondary(_primarySelected, _query, primary_map)", |
| 23329 }, | 23090 }, |
| 23091 }, |
| 23330 | 23092 |
| 23331 }, | |
| 23332 | 23093 |
| 23333 _addFilter: function(e) { | 23094 _addFilter: function(e) { |
| 23334 // e.model.foo is a way to get access to the "foo" inside a dom-repeat | 23095 // e.model.foo is a way to get access to the "foo" inside a dom-repeat |
| 23335 // that had the event (in our case, a tap) acted upon it. This name, | 23096 // that had the event (in our case, a tap) acted upon it. This name, |
| 23336 // "foo", is set by the dom-repeat above 'as="foo"' | 23097 // "foo", is set by the dom-repeat above 'as="foo"' |
| 23337 var filterItem = e.model.item; | 23098 var filterItem = e.model.item; |
| 23338 if (this._cantAddFilter(this._primarySelected, filterItem)) { | 23099 if (this._cantAddFilter(this._primarySelected, filterItem)) { |
| 23339 return; | 23100 return; |
| 23340 } | 23101 } |
| 23341 var filter = this._primarySelected + FILTER_SEP + filterItem; | 23102 var filter = this._primarySelected + this.FILTER_SEP + filterItem; |
| 23342 this.push("_filters", filter); | 23103 this.push("_filters", filter); |
| 23343 }, | 23104 }, |
| 23344 | 23105 |
| 23345 _removeFilter: function(e){ | 23106 _removeFilter: function(e){ |
| 23346 var filter = e.model.fil; | 23107 var filter = e.model.fil; |
| 23347 if (this._cantRemoveFilter(filter)){ | 23108 if (this._cantRemoveFilter(filter)){ |
| 23348 return; | 23109 return; |
| 23349 } | 23110 } |
| 23350 var idx = this._filters.indexOf(filter); | 23111 var idx = this._filters.indexOf(filter); |
| 23351 if (idx !== -1) { | 23112 if (idx !== -1) { |
| 23352 this.splice("_filters", idx, 1); | 23113 this.splice("_filters", idx, 1); |
| 23353 } | 23114 } |
| 23354 }, | 23115 }, |
| 23355 | 23116 |
| 23356 _cantAddFilter: function(primarySelected, filterItem) { | 23117 _cantAddFilter: function(primarySelected, filterItem) { |
| 23357 // Check that everything is selected and this filter isn't already in | 23118 // Check that everything is selected and this filter isn't already in |
| 23358 // the array. | 23119 // the array. |
| 23359 if (!primarySelected || !filterItem) { | 23120 if (!primarySelected || !filterItem) { |
| 23360 return true; | 23121 return true; |
| 23361 } | 23122 } |
| 23362 var filter = primarySelected + FILTER_SEP + filterItem; | 23123 var filter = primarySelected + this.FILTER_SEP + filterItem; |
| 23363 return this._filters.indexOf(filter) !== -1; | 23124 return this._filters.indexOf(filter) !== -1; |
| 23364 }, | 23125 }, |
| 23365 | 23126 |
| 23366 _cantRemoveFilter: function(filter) { | 23127 _cantRemoveFilter: function(filter) { |
| 23367 return !filter || this._filters.indexOf(filter) === -1; | 23128 return !filter || this._filters.indexOf(filter) === -1; |
| 23368 }, | 23129 }, |
| 23369 | 23130 |
| 23370 _toggleColumn: function(e) { | |
| 23371 var col = e.model.item; | |
| 23372 | |
| 23373 if (this._cantToggleColumn(col)) { | |
| 23374 return; | |
| 23375 } | |
| 23376 if (this._columnState(col)) { | |
| 23377 var idx = this.columns.indexOf(col); | |
| 23378 if (idx !== -1) { | |
| 23379 this.splice("columns", idx, 1); | |
| 23380 } | |
| 23381 return; | |
| 23382 } | |
| 23383 this.push("columns", col); | |
| 23384 }, | |
| 23385 | |
| 23386 _cantToggleColumn: function(col) { | |
| 23387 // Don't allow the id column to be removed, as the bot list is basically | |
| 23388 // meaningless without it. | |
| 23389 return !col || col === "id" ; | |
| 23390 }, | |
| 23391 | |
| 23392 _columnState: function(col) { | |
| 23393 if (!col) { | |
| 23394 return false; | |
| 23395 } | |
| 23396 return this.columns.indexOf(col) !== -1; | |
| 23397 }, | |
| 23398 | |
| 23399 _makeFilter: function() { | 23131 _makeFilter: function() { |
| 23400 // All filters will be AND'd together. | 23132 // All filters will be AND'd together. |
| 23401 // filterGroups will be a map of primary (i.e. column) -> array of | 23133 // filterGroups will be a map of primary (i.e. column) -> array of |
| 23402 // options that should be filtered to. | 23134 // options that should be filtered to. |
| 23403 // e.g. "os" -> ["Windows", "Linux"] | 23135 // e.g. "os" -> ["Windows", "Linux"] |
| 23404 // Since they will be or'd together, order doesn't matter. | 23136 // Since they will be or'd together, order doesn't matter. |
| 23405 var filterGroups = {}; | 23137 var filterGroups = {}; |
| 23406 this._filters.forEach(function(filterString){ | 23138 this._filters.forEach(function(filterString){ |
| 23407 var idx = filterString.indexOf(FILTER_SEP); | 23139 var idx = filterString.indexOf(this.FILTER_SEP); |
| 23408 var primary = filterString.slice(0, idx); | 23140 var primary = filterString.slice(0, idx); |
| 23409 var param = filterString.slice(idx + FILTER_SEP.length); | 23141 var param = filterString.slice(idx + this.FILTER_SEP.length); |
| 23410 var arr = filterGroups[primary] || []; | 23142 var arr = filterGroups[primary] || []; |
| 23411 arr.push(param); | 23143 arr.push(param); |
| 23412 filterGroups[primary] = arr; | 23144 filterGroups[primary] = arr; |
| 23413 }); | 23145 }.bind(this)); |
| 23146 var filterMap = this._filterMap || {}; |
| 23414 return function(bot){ | 23147 return function(bot){ |
| 23415 var retVal = true; | 23148 var retVal = true; |
| 23416 // Look up all the primary keys we are filter by, then look up how | 23149 // Look up all the primary keys we are filter by, then look up how |
| 23417 // to filter (in filterMap) and apply the filter for each filter | 23150 // to filter (in filterMap) and apply the filter for each filter |
| 23418 // option. | 23151 // option. |
| 23419 for (primary in filterGroups){ | 23152 for (primary in filterGroups){ |
| 23420 var params = filterGroups[primary]; | 23153 var params = filterGroups[primary]; |
| 23421 var filter = filterMap[primary]; | 23154 var filter = filterMap[primary]; |
| 23422 if (!filter) { | 23155 if (!filter) { |
| 23423 filter = function(bot, c) { | 23156 filter = function(bot, c) { |
| 23424 var o = this._attribute(bot, primary); | 23157 var o = this._attribute(bot, primary); |
| 23425 return o.indexOf(c) !== -1; | 23158 return o.indexOf(c) !== -1; |
| 23426 }.bind(this); | 23159 }.bind(this); |
| 23427 } | 23160 } |
| 23428 if (filter) { | 23161 if (filter) { |
| 23429 params.forEach(function(param){ | 23162 params.forEach(function(param){ |
| 23430 retVal = retVal && filter.bind(this)(bot,param); | 23163 retVal = retVal && filter.bind(this)(bot,param); |
| 23431 }.bind(this)); | 23164 }.bind(this)); |
| 23432 } | 23165 } |
| 23433 } | 23166 } |
| 23434 return retVal; | 23167 return retVal; |
| 23435 } | 23168 } |
| 23436 }, | 23169 }, |
| 23437 | 23170 |
| 23171 _toggleColumn: function(e) { |
| 23172 var col = e.model.item; |
| 23173 |
| 23174 if (this._cantToggleColumn(col)) { |
| 23175 return; |
| 23176 } |
| 23177 if (this._columnState(col)) { |
| 23178 var idx = this.columns.indexOf(col); |
| 23179 if (idx !== -1) { |
| 23180 this.splice("columns", idx, 1); |
| 23181 } |
| 23182 return; |
| 23183 } |
| 23184 this.push("columns", col); |
| 23185 }, |
| 23186 |
| 23187 _cantToggleColumn: function(col) { |
| 23188 // Clients can override this |
| 23189 return false; |
| 23190 }, |
| 23191 |
| 23192 _columnState: function(col) { |
| 23193 if (!col) { |
| 23194 return false; |
| 23195 } |
| 23196 return this.columns.indexOf(col) !== -1; |
| 23197 }, |
| 23198 |
| 23199 |
| 23438 _primary: function(query, primary_map, primary_arr) { | 23200 _primary: function(query, primary_map, primary_arr) { |
| 23439 // If the user has typed in a query, only show those primary keys that | 23201 // If the user has typed in a query, only show those primary keys that |
| 23440 // partially match the query or that have secondary values which | 23202 // partially match the query or that have secondary values which |
| 23441 // partially match. | 23203 // partially match. |
| 23442 var arr = this.primary_arr.filter(function(s){ | 23204 var arr = this.primary_arr.filter(function(s){ |
| 23443 if (matchPartCaseInsensitive(s, query).idx !== -1) { | 23205 if (matchPartCaseInsensitive(s, query).idx !== -1) { |
| 23444 return true; | 23206 return true; |
| 23445 } | 23207 } |
| 23446 var opts = primary_map[s]; | 23208 var opts = primary_map[s]; |
| 23447 for (var i = 0; i < opts.length; i++) { | 23209 for (var i = 0; i < opts.length; i++) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 23513 }, | 23275 }, |
| 23514 | 23276 |
| 23515 _afterBold: function(item, query) { | 23277 _afterBold: function(item, query) { |
| 23516 var match = matchPartCaseInsensitive(item, query); | 23278 var match = matchPartCaseInsensitive(item, query); |
| 23517 if (match.idx === -1) { | 23279 if (match.idx === -1) { |
| 23518 return ""; | 23280 return ""; |
| 23519 } | 23281 } |
| 23520 return item.substring(match.idx + match.part.length); | 23282 return item.substring(match.idx + match.part.length); |
| 23521 }, | 23283 }, |
| 23522 | 23284 |
| 23285 // Common filters shared between tasklist and botlist |
| 23286 _commonFilters: function() { |
| 23287 // return a fresh object so all elements have their own copy |
| 23288 return { |
| 23289 android_devices: function(bot, num) { |
| 23290 var o = this._attribute(bot, "android_devices", "0"); |
| 23291 return o.indexOf(num) !== -1; |
| 23292 }, |
| 23293 device_os: function(bot, os) { |
| 23294 var o = this._attribute(bot, "device_os", "none"); |
| 23295 return o.indexOf(os) !== -1; |
| 23296 }, |
| 23297 device_type: function(bot, dt) { |
| 23298 var o = this._attribute(bot, "device_type", "none"); |
| 23299 return o.indexOf(swarming.alias.unapply(dt)) !== -1; |
| 23300 }, |
| 23301 gpu: function(bot, gpu) { |
| 23302 var o = this._attribute(bot, "gpu", "none"); |
| 23303 return o.indexOf(swarming.alias.unapply(gpu)) !== -1; |
| 23304 }, |
| 23305 }; |
| 23306 }, |
| 23307 |
| 23308 }]; |
| 23309 })(); |
| 23310 </script> |
| 23311 <script> |
| 23312 (function(){ |
| 23313 // Taken from http://developer.android.com/reference/android/os/BatteryManag
er.html |
| 23314 var BATTERY_HEALTH_UNKNOWN = 1; |
| 23315 var BATTERY_HEALTH_GOOD = 2; |
| 23316 var BATTERY_STATUS_CHARGING = 2; |
| 23317 |
| 23318 var UNAUTHENTICATED = "unauthenticated"; |
| 23319 var AVAILABLE = "available"; |
| 23320 var UNKNOWN = "unknown"; |
| 23321 |
| 23322 // This behavior wraps up all the shared bot-list functionality by |
| 23323 // extending SwarmingBehaviors.CommonBehavior |
| 23324 SwarmingBehaviors.BotListBehavior = [SwarmingBehaviors.CommonBehavior, { |
| 23325 |
| 23326 properties: { |
| 23327 BOT_PROPERTIES: { |
| 23328 type: Array, |
| 23329 value: function() { |
| 23330 // TODO(kjlubick): Add more of these things from state, as they |
| 23331 // needed/useful/requested. |
| 23332 return ["disk_space", "task", "status"]; |
| 23333 } |
| 23334 }, |
| 23335 }, |
| 23336 |
| 23337 // _attribute looks first in dimension and then in state for the |
| 23338 // specified attribute. This will always return an array. If there is |
| 23339 // no matching attribute, ["unknown"] will be returned. |
| 23340 _attribute: function(bot, attr, none) { |
| 23341 none = none || UNKNOWN; |
| 23342 return this._dimension(bot, attr) || this._state(bot, attr) || [none]; |
| 23343 }, |
| 23344 |
| 23345 _devices: function(bot) { |
| 23346 var devices = []; |
| 23347 var d = (bot && bot.state && bot.state.devices) || {}; |
| 23348 // state.devices is like {Serial:Object}, so we need to keep the serial |
| 23349 for (key in d) { |
| 23350 var o = d[key]; |
| 23351 o.serial = key; |
| 23352 o.okay = (o.state === AVAILABLE); |
| 23353 // It is easier to assume all devices on a bot are of the same type |
| 23354 // than to pick through the (incomplete) device state and find it. |
| 23355 o.device_type = this._attribute(bot, "device_type")[0]; |
| 23356 devices.push(o); |
| 23357 } |
| 23358 return devices; |
| 23359 }, |
| 23360 |
| 23361 // _deviceType returns the codename of a given Android device. |
| 23362 _deviceType: function(device) { |
| 23363 return device.device_type.toLowerCase(); |
| 23364 }, |
| 23365 |
| 23366 // _dimension returns the given dimension of a bot. If it is defined, it |
| 23367 // is an array of strings. |
| 23368 _dimension: function(bot, dim) { |
| 23369 if (!bot || !bot.dimensions || !dim) { |
| 23370 return undefined; |
| 23371 } |
| 23372 for (var i = 0; i < bot.dimensions.length; i++) { |
| 23373 if (bot.dimensions[i].key === dim) { |
| 23374 return bot.dimensions[i].value; |
| 23375 } |
| 23376 } |
| 23377 return undefined; |
| 23378 }, |
| 23379 |
| 23380 // _state returns the requested attribute from a bot's state. |
| 23381 // For consistency with _dimension, if the attribute is not an array, |
| 23382 // it is put as the only element in an array. |
| 23383 _state: function(bot, attr) { |
| 23384 if (!bot || !bot.state || !bot.state[attr]) { |
| 23385 return undefined |
| 23386 } |
| 23387 var state = bot.state[attr]; |
| 23388 if (Array.isArray(state)) { |
| 23389 return state; |
| 23390 } |
| 23391 return [state]; |
| 23392 }, |
| 23393 |
| 23394 _taskId: function(bot) { |
| 23395 if (bot && bot.task_id) { |
| 23396 return bot.task_id; |
| 23397 } |
| 23398 return "idle"; |
| 23399 }, |
| 23400 |
| 23401 }]; |
| 23402 })() |
| 23403 </script> |
| 23404 <dom-module id="bot-filters" assetpath="/res/imp/botlist/"> |
| 23405 <template> |
| 23406 <style is="custom-style" include="iron-flex iron-flex-alignment iron-positio
ning query-column-filter-style"> |
| 23407 |
| 23408 </style> |
| 23409 |
| 23410 <url-param name="filters" value="{{_filters}}" default_values="[]" multi=""> |
| 23411 </url-param> |
| 23412 <url-param name="columns" value="{{columns}}" default_values="["id"
;,"os","task","status"]" multi=""> |
| 23413 </url-param> |
| 23414 <url-param name="query" value="{{_query}}" default_value=""> |
| 23415 </url-param> |
| 23416 <url-param name="verbose" value="{{verbose}}"> |
| 23417 </url-param> |
| 23418 <url-param name="limit" default_value="200" value="{{limit}}"> |
| 23419 </url-param> |
| 23420 |
| 23421 <div class="container horizontal layout"> |
| 23422 |
| 23423 |
| 23424 <div class="narrow-down-selector"> |
| 23425 <div> |
| 23426 <paper-input id="filter" label="Search columns and filters" placeholde
r="gpu nvidia" value="{{_query}}"> |
| 23427 </paper-input> |
| 23428 </div> |
| 23429 |
| 23430 <div class="selector side-by-side" title="This shows all bot dimension n
ames and other interesting bot properties. Mark the check box to add as a column
. Select the row to see filter options."> |
| 23431 <iron-selector attr-for-selected="label" selected="{{_primarySelected}
}"> |
| 23432 <template is="dom-repeat" items="[[_primaryItems]]" as="item"> |
| 23433 <div class="selectable item horizontal layout" label="[[item]]"> |
| 23434 |
| 23435 <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(ite
m,_query)]]</span>[[_afterBold(item,_query)]]</span> |
| 23436 <span class="flex"></span> |
| 23437 <paper-checkbox noink="" disabled$="[[_cantToggleColumn(item)]]"
checked="[[_columnState(item,columns.*)]]" on-change="_toggleColumn"> |
| 23438 </paper-checkbox> |
| 23439 </div> |
| 23440 </template> |
| 23441 </iron-selector> |
| 23442 </div> |
| 23443 |
| 23444 <div class="selector side-by-side" title="These are all options (if any)
that the bot list can be filtered on."> |
| 23445 <template is="dom-repeat" id="secondaryList" items="[[_secondaryItems]
]" as="item"> |
| 23446 <div class="item horizontal layout" label="[[item]]"> |
| 23447 |
| 23448 <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(item,
_query)]]</span>[[_afterBold(item,_query)]]</span> |
| 23449 <span class="flex"></span> |
| 23450 <iron-icon class="icons" icon="icons:arrow-forward" hidden="[[_can
tAddFilter(_primarySelected,item,_filters.*)]]" on-tap="_addFilter"> |
| 23451 </iron-icon> |
| 23452 </div> |
| 23453 </template> |
| 23454 </div> |
| 23455 |
| 23456 <div class="selector side-by-side" title="These filters are AND'd togeth
er and applied to all bots in |
| 23457 the fleet."> |
| 23458 <template is="dom-repeat" items="[[_filters]]" as="fil"> |
| 23459 <div class="item horizontal layout" label="[[fil]]"> |
| 23460 <span>[[fil]]</span> |
| 23461 <span class="flex"></span> |
| 23462 <iron-icon class="icons" icon="icons:remove-circle-outline" hidden
="[[_cantRemoveFilter(fil,_filters.*)]]" on-tap="_removeFilter"> |
| 23463 </iron-icon> |
| 23464 </div> |
| 23465 </template> |
| 23466 </div> |
| 23467 |
| 23468 <div class="side-by-side"> |
| 23469 <paper-checkbox checked="{{verbose}}">Verbose Entries</paper-checkbox> |
| 23470 <paper-input id="limit" label="Limit Results" auto-validate="" min="0"
max="1000" pattern="[0-9]+" value="{{limit}}"> |
| 23471 </paper-input> |
| 23472 </div> |
| 23473 </div> |
| 23474 |
| 23475 </div> |
| 23476 |
| 23477 </template> |
| 23478 <script> |
| 23479 (function(){ |
| 23480 // See query-column-filter for more documentation on these properties. |
| 23481 var filterMap = { |
| 23482 disk_space: function(bot, space) { |
| 23483 return true; |
| 23484 }, |
| 23485 id: function(bot, id) { |
| 23486 return true; |
| 23487 }, |
| 23488 status: function(bot, status) { |
| 23489 if (status === "quarantined") { |
| 23490 return bot.quarantined; |
| 23491 } else if (status === "dead") { |
| 23492 return bot.is_dead; |
| 23493 } else { |
| 23494 // Status must be "alive". |
| 23495 return !bot.quarantined && !bot.is_dead; |
| 23496 } |
| 23497 }, |
| 23498 task: function(bot, task) { |
| 23499 if (task === "idle") { |
| 23500 return this._taskId(bot) === "idle"; |
| 23501 } |
| 23502 // Task must be "busy". |
| 23503 return this._taskId(bot) !== "idle"; |
| 23504 } |
| 23505 }; |
| 23506 |
| 23507 Polymer({ |
| 23508 is: "bot-filters", |
| 23509 |
| 23510 behaviors: [ |
| 23511 SwarmingBehaviors.BotListBehavior, |
| 23512 SwarmingBehaviors.QueryColumnFilter, |
| 23513 ], |
| 23514 |
| 23515 properties: { |
| 23516 // url-param doesn't like columns to be defined in query_column-filter, |
| 23517 // so we define it here. |
| 23518 columns: { |
| 23519 type: Array, |
| 23520 notify: true, |
| 23521 }, |
| 23522 query_params: { |
| 23523 type: Object, |
| 23524 computed: "_extractQueryParams(dimensions.*,_filters.*, limit)", |
| 23525 notify: true, |
| 23526 }, |
| 23527 verbose: { |
| 23528 type: Boolean, |
| 23529 notify: true, |
| 23530 }, |
| 23531 |
| 23532 // for QueryColumnFilter |
| 23533 _filterMap: { |
| 23534 type: Object, |
| 23535 value: function() { |
| 23536 var base = this._commonFilters(); |
| 23537 for (var attr in filterMap) { |
| 23538 base[attr] = filterMap[attr]; |
| 23539 } |
| 23540 return base; |
| 23541 }, |
| 23542 } |
| 23543 }, |
| 23544 |
| 23545 _cantToggleColumn: function(col) { |
| 23546 // Don't allow the id column to be removed, as the bot list is basically |
| 23547 // meaningless without it. |
| 23548 return !col || col === "id" ; |
| 23549 }, |
| 23550 |
| 23523 _extractQueryParams: function() { | 23551 _extractQueryParams: function() { |
| 23524 var params = {}; | 23552 var params = {}; |
| 23525 var dims = []; | 23553 var dims = []; |
| 23526 this._filters.forEach(function(f) { | 23554 this._filters.forEach(function(f) { |
| 23527 var split = f.split(FILTER_SEP, 1) | 23555 var split = f.split(this.FILTER_SEP, 1) |
| 23528 var col = split[0]; | 23556 var col = split[0]; |
| 23529 if (this.dimensions.indexOf(col) !== -1) { | 23557 if (this.dimensions.indexOf(col) !== -1) { |
| 23530 var rest = f.substring(col.length + FILTER_SEP.length); | 23558 var rest = f.substring(col.length + this.FILTER_SEP.length); |
| 23531 dims.push(col + FILTER_SEP + this._unalias(rest)) | 23559 dims.push(col + this.FILTER_SEP + swarming.alias.unapply(rest)) |
| 23532 } else if (col === "status") { | 23560 } else if (col === "status") { |
| 23533 var rest = f.substring(col.length + FILTER_SEP.length); | 23561 var rest = f.substring(col.length + this.FILTER_SEP.length); |
| 23534 if (rest === "alive") { | 23562 if (rest === "alive") { |
| 23535 params["is_dead"] = "FALSE"; | 23563 params["is_dead"] = "FALSE"; |
| 23536 params["quarantined"] = "FALSE"; | 23564 params["quarantined"] = "FALSE"; |
| 23537 } else if (rest === "quarantined") { | 23565 } else if (rest === "quarantined") { |
| 23538 params["quarantined"] = "TRUE"; | 23566 params["quarantined"] = "TRUE"; |
| 23539 } else if (rest === "dead") { | 23567 } else if (rest === "dead") { |
| 23540 params["is_dead"] = "TRUE"; | 23568 params["is_dead"] = "TRUE"; |
| 23541 } | 23569 } |
| 23542 } | 23570 } |
| 23543 }.bind(this)); | 23571 }.bind(this)); |
| 23544 params["dimensions"] = dims; | 23572 params["dimensions"] = dims; |
| 23545 var lim = Math.floor(this.limit) | 23573 var lim = Math.floor(this.limit) |
| 23546 if (Number.isInteger(lim)) { | 23574 if (Number.isInteger(lim)) { |
| 23547 // Clamp the limit | 23575 // Clamp the limit |
| 23548 lim = Math.max(lim, 1); | 23576 lim = Math.max(lim, 1); |
| 23549 lim = Math.min(1000, lim); | 23577 lim = Math.min(1000, lim); |
| 23550 params["limit"] = lim; | 23578 params["limit"] = lim; |
| 23551 // not !-- because limit could be "900" | 23579 // not !== because limit could be a string, e.g. "900" |
| 23552 if (this.limit != lim) { | 23580 if (this.limit != lim) { |
| 23553 this.set("limit", lim); | 23581 this.set("limit", lim); |
| 23554 } | 23582 } |
| 23555 } | 23583 } |
| 23556 return params; | 23584 return params; |
| 23557 } | 23585 } |
| 23558 | 23586 |
| 23559 }); | 23587 }); |
| 23560 })(); | 23588 })(); |
| 23561 </script> | 23589 </script> |
| 23562 </dom-module><dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> | 23590 </dom-module><dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> |
| 23563 <template> | 23591 <template> |
| 23564 <iron-ajax id="botlist" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
_headers]]" params="[[query_params]]" handle-as="json" last-response="{{_list}}"
loading="{{_busy1}}"> | 23592 <iron-ajax id="botlist" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
_headers]]" params="[[query_params]]" handle-as="json" last-response="{{_list}}"
loading="{{_busy1}}"> |
| 23565 </iron-ajax> | 23593 </iron-ajax> |
| 23566 | 23594 |
| 23567 <iron-ajax id="dimensions" url="/_ah/api/swarming/v1/bots/dimensions" header
s="[[auth_headers]]" handle-as="json" last-response="{{_dimensions}}" loading="{
{_busy2}}"> | 23595 <iron-ajax id="dimensions" url="/_ah/api/swarming/v1/bots/dimensions" header
s="[[auth_headers]]" handle-as="json" last-response="{{_dimensions}}" loading="{
{_busy2}}"> |
| 23568 </iron-ajax> | 23596 </iron-ajax> |
| 23569 | 23597 |
| 23570 <iron-ajax id="fleet" url="/_ah/api/swarming/v1/bots/count" headers="[[auth_
headers]]" handle-as="json" last-response="{{_count}}" loading="{{_busy3}}"> | 23598 <iron-ajax id="fleet" url="/_ah/api/swarming/v1/bots/count" headers="[[auth_
headers]]" handle-as="json" last-response="{{_count}}" loading="{{_busy3}}"> |
| 23571 </iron-ajax> | 23599 </iron-ajax> |
| 23572 </template> | 23600 </template> |
| 23573 <script> | 23601 <script> |
| 23574 (function(){ | 23602 (function(){ |
| 23575 var BLACKLIST_DIMENSIONS = ["quarantined", "error"]; | 23603 var BLACKLIST_DIMENSIONS = ["quarantined", "error"]; |
| 23576 | 23604 |
| 23577 Polymer({ | 23605 Polymer({ |
| 23578 is: 'bot-list-data', | 23606 is: 'bot-list-data', |
| 23579 | 23607 |
| 23580 behaviors: [SwarmingBehaviors.BotListBehavior], | 23608 behaviors: [ |
| 23609 SwarmingBehaviors.BotListBehavior, |
| 23610 ], |
| 23581 | 23611 |
| 23582 properties: { | 23612 properties: { |
| 23583 // inputs | 23613 // inputs |
| 23584 auth_headers: { | 23614 auth_headers: { |
| 23585 type: Object, | 23615 type: Object, |
| 23586 observer: "signIn", | 23616 observer: "signIn", |
| 23587 }, | 23617 }, |
| 23588 query_params: { | 23618 query_params: { |
| 23589 type: Object, | 23619 type: Object, |
| 23590 }, | 23620 }, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 23604 type: Array, | 23634 type: Array, |
| 23605 computed: "_makeArray(_dimensions)", | 23635 computed: "_makeArray(_dimensions)", |
| 23606 notify: true, | 23636 notify: true, |
| 23607 }, | 23637 }, |
| 23608 fleet: { | 23638 fleet: { |
| 23609 type: Object, | 23639 type: Object, |
| 23610 computed: "_fleet(_count)", | 23640 computed: "_fleet(_count)", |
| 23611 notify: true, | 23641 notify: true, |
| 23612 }, | 23642 }, |
| 23613 primary_map: { | 23643 primary_map: { |
| 23614 type:Object, | 23644 type: Object, |
| 23615 computed: "_primaryMap(_dimensions)", | 23645 computed: "_primaryMap(_dimensions)", |
| 23616 notify: true, | 23646 notify: true, |
| 23617 }, | 23647 }, |
| 23618 primary_arr: { | 23648 primary_arr: { |
| 23619 type: Array, | 23649 type: Array, |
| 23620 //BOT_PROPERTIES is inherited from BotListBehavior | 23650 //BOT_PROPERTIES is inherited from BotListBehavior |
| 23621 computed: "_primaryArr(dimensions, BOT_PROPERTIES)", | 23651 computed: "_primaryArr(dimensions, BOT_PROPERTIES)", |
| 23622 notify: true, | 23652 notify: true, |
| 23623 }, | 23653 }, |
| 23624 | 23654 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 23691 _makeArray: function(dimObj) { | 23721 _makeArray: function(dimObj) { |
| 23692 if (!dimObj || !dimObj.bots_dimensions) { | 23722 if (!dimObj || !dimObj.bots_dimensions) { |
| 23693 return []; | 23723 return []; |
| 23694 } | 23724 } |
| 23695 var dims = []; | 23725 var dims = []; |
| 23696 dimObj.bots_dimensions.forEach(function(d){ | 23726 dimObj.bots_dimensions.forEach(function(d){ |
| 23697 if (BLACKLIST_DIMENSIONS.indexOf(d.key) === -1) { | 23727 if (BLACKLIST_DIMENSIONS.indexOf(d.key) === -1) { |
| 23698 dims.push(d.key); | 23728 dims.push(d.key); |
| 23699 } | 23729 } |
| 23700 }); | 23730 }); |
| 23731 dims.push("id"); |
| 23701 dims.sort(); | 23732 dims.sort(); |
| 23702 return dims; | 23733 return dims; |
| 23703 }, | 23734 }, |
| 23704 | 23735 |
| 23705 _primaryArr: function(dimensions, properties) { | 23736 _primaryArr: function(dimensions, properties) { |
| 23706 return dimensions.concat(properties); | 23737 return dimensions.concat(properties); |
| 23707 }, | 23738 }, |
| 23708 | 23739 |
| 23709 _primaryMap: function(dimensions){ | 23740 _primaryMap: function(dimensions){ |
| 23710 // pMap will have a list of columns to available values (primary key | 23741 // pMap will have a list of columns to available values (primary key |
| 23711 // to secondary values). This includes bot dimensions, but also | 23742 // to secondary values). This includes bot dimensions, but also |
| 23712 // includes state like disk_space, quarantined, busy, etc. | 23743 // includes state like disk_space, quarantined, busy, etc. |
| 23713 dimensions = dimensions.bots_dimensions; | 23744 dimensions = dimensions.bots_dimensions; |
| 23714 | 23745 |
| 23715 var pMap = {}; | 23746 var pMap = {}; |
| 23716 dimensions.forEach(function(d){ | 23747 dimensions.forEach(function(d){ |
| 23717 if (this.DIMENSIONS_WITH_ALIASES.indexOf(d.key) === -1) { | 23748 if (swarming.alias.DIMENSIONS_WITH_ALIASES.indexOf(d.key) === -1) { |
| 23718 // value is an array of all seen values for the dimension d.key | 23749 // value is an array of all seen values for the dimension d.key |
| 23719 pMap[d.key] = d.value; | 23750 pMap[d.key] = d.value; |
| 23720 } else if (d.key === "gpu") { | 23751 } else if (d.key === "gpu") { |
| 23721 var gpus = []; | 23752 var gpus = []; |
| 23722 d.value.forEach(function(g){ | 23753 d.value.forEach(function(g){ |
| 23723 var alias = this._gpuAlias(g); | 23754 var alias = swarming.alias.gpu(g); |
| 23724 if (alias !== "unknown") { | 23755 if (alias !== "unknown") { |
| 23725 gpus.push(this._applyAlias(g, alias)); | 23756 gpus.push(swarming.alias.apply(g, alias)); |
| 23726 } else { | 23757 } else { |
| 23727 gpus.push(g); | 23758 gpus.push(g); |
| 23728 } | 23759 } |
| 23729 }.bind(this)); | 23760 }.bind(this)); |
| 23730 pMap["gpu"] = gpus; | 23761 pMap["gpu"] = gpus; |
| 23731 } else if (d.key === "device_type") { | 23762 } else if (d.key === "device_type") { |
| 23732 var devs = []; | 23763 var devs = []; |
| 23733 d.value.forEach(function(dt){ | 23764 d.value.forEach(function(dt){ |
| 23734 var alias = this._androidAlias(dt); | 23765 var alias = swarming.alias.android(dt); |
| 23735 if (alias !== "unknown") { | 23766 if (alias !== "unknown") { |
| 23736 devs.push(this._applyAlias(dt, alias)); | 23767 devs.push(swarming.alias.apply(dt, alias)); |
| 23737 } else { | 23768 } else { |
| 23738 devs.push(dt); | 23769 devs.push(dt); |
| 23739 } | 23770 } |
| 23740 }.bind(this)); | 23771 }.bind(this)); |
| 23741 pMap["device_type"] = devs; | 23772 pMap["device_type"] = devs; |
| 23742 } else { | 23773 } else { |
| 23743 console.log("Unknown alias type: ", d); | 23774 console.log("Unknown alias type: ", d); |
| 23744 } | 23775 } |
| 23745 }.bind(this)); | 23776 }); |
| 23746 | 23777 |
| 23747 // Add some options that might not show up. | 23778 // Add some options that might not show up. |
| 23748 pMap["android_devices"].push("0"); | 23779 pMap["android_devices"].push("0"); |
| 23749 pMap["device_os"].push("none"); | 23780 pMap["device_os"].push("none"); |
| 23750 pMap["device_type"].push("none"); | 23781 pMap["device_type"].push("none"); |
| 23751 | 23782 |
| 23752 pMap["id"] = []; | 23783 pMap["id"] = []; |
| 23753 | 23784 |
| 23754 // Create custom filter options | 23785 // Create custom filter options |
| 23755 pMap["disk_space"] = []; | 23786 pMap["disk_space"] = []; |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 24095 "device_type": "Device Type", | 24126 "device_type": "Device Type", |
| 24096 "disk_space": "Free Space (MB)", | 24127 "disk_space": "Free Space (MB)", |
| 24097 "gpu": "GPU", | 24128 "gpu": "GPU", |
| 24098 "os": "OS", | 24129 "os": "OS", |
| 24099 "pool": "Pool", | 24130 "pool": "Pool", |
| 24100 "status": "Status", | 24131 "status": "Status", |
| 24101 "xcode_version": "XCode Version", | 24132 "xcode_version": "XCode Version", |
| 24102 }; | 24133 }; |
| 24103 | 24134 |
| 24104 var columnMap = { | 24135 var columnMap = { |
| 24105 android_devices: function(bot) { | |
| 24106 var devs = this._attribute(bot, "android_devices", "0"); | |
| 24107 if (this._verbose) { | |
| 24108 return devs.join(" | ") + " devices available"; | |
| 24109 } | |
| 24110 // max() works on strings as long as they can be coerced to Number. | |
| 24111 return Math.max(...devs) + " devices available"; | |
| 24112 }, | |
| 24113 device_type: function(bot) { | |
| 24114 var dt = this._attribute(bot, "device_type", "none"); | |
| 24115 dt = dt[0]; | |
| 24116 var alias = this._androidAlias(dt); | |
| 24117 if (alias === "unknown") { | |
| 24118 return dt; | |
| 24119 } | |
| 24120 return this._applyAlias(dt, alias); | |
| 24121 }, | |
| 24122 disk_space: function(bot) { | 24136 disk_space: function(bot) { |
| 24123 var aliased = []; | 24137 var aliased = []; |
| 24124 bot.disks.forEach(function(disk){ | 24138 bot.disks.forEach(function(disk){ |
| 24125 var alias = sk.human.bytes(disk.mb, swarming.MB); | 24139 var alias = sk.human.bytes(disk.mb, swarming.MB); |
| 24126 aliased.push(this._applyAlias(disk.mb, disk.id + " "+ alias)); | 24140 aliased.push(swarming.alias.apply(disk.mb, disk.id + " "+ alias)); |
| 24127 }.bind(this)); | 24141 }.bind(this)); |
| 24128 if (this._verbose) { | 24142 if (this._verbose) { |
| 24129 return aliased.join(" | "); | 24143 return aliased.join(" | "); |
| 24130 } | 24144 } |
| 24131 return aliased[0]; | 24145 return aliased[0]; |
| 24132 }, | 24146 }, |
| 24133 gpu: function(bot){ | |
| 24134 var gpus = this._attribute(bot, "gpu", "none") | |
| 24135 var verbose = [] | |
| 24136 var named = []; | |
| 24137 // non-verbose mode has only the top level GPU info "e.g. NVidia" | |
| 24138 // which is found by looking for gpu ids w/o a colon. | |
| 24139 gpus.forEach(function(g){ | |
| 24140 var alias = this._gpuAlias(g); | |
| 24141 if (alias === "unknown") { | |
| 24142 verbose.push(g); | |
| 24143 if (g.indexOf(":") === -1) { | |
| 24144 named.push(g); | |
| 24145 } | |
| 24146 return; | |
| 24147 } | |
| 24148 verbose.push(this._applyAlias(g, alias)); | |
| 24149 if (g.indexOf(":") === -1) { | |
| 24150 named.push(this._applyAlias(g, alias)); | |
| 24151 } | |
| 24152 }.bind(this)) | |
| 24153 if (this._verbose) { | |
| 24154 return verbose.join(" | "); | |
| 24155 } | |
| 24156 return named.join(" | "); | |
| 24157 }, | |
| 24158 id: function(bot) { | 24147 id: function(bot) { |
| 24159 return bot.bot_id; | 24148 return bot.bot_id; |
| 24160 }, | 24149 }, |
| 24161 pool: function(bot) { | |
| 24162 var pool = this._attribute(bot, "pool"); | |
| 24163 return pool.join(" | "); | |
| 24164 }, | |
| 24165 status: function(bot) { | 24150 status: function(bot) { |
| 24166 // If a bot is both dead and quarantined, show the deadness over the | 24151 // If a bot is both dead and quarantined, show the deadness over the |
| 24167 // quarentinedness. | 24152 // quarentinedness. |
| 24168 if (bot.is_dead) { | 24153 if (bot.is_dead) { |
| 24169 return "Dead. Last seen " + sk.human.diffDate(bot.last_seen_ts) + | 24154 return "Dead. Last seen " + sk.human.diffDate(bot.last_seen_ts) + |
| 24170 " ago"; | 24155 " ago"; |
| 24171 } | 24156 } |
| 24172 if (bot.quarantined) { | 24157 if (bot.quarantined) { |
| 24173 return "Quarantined: " + this._attribute(bot, "quarantined"); | 24158 var msg = this._state(bot, "quarantined")[0]; |
| 24159 // Sometimes, the quarantined message is actually in "error". This |
| 24160 // happens when the bot code has thrown an exception. |
| 24161 if (msg === "unknown" || msg === "true" || msg === true) { |
| 24162 msg = this._attribute(bot, "error"); |
| 24163 } |
| 24164 return "Quarantined: " + msg; |
| 24174 } | 24165 } |
| 24175 return "Alive"; | 24166 return "Alive"; |
| 24176 }, | 24167 }, |
| 24177 task: function(bot){ | 24168 task: function(bot){ |
| 24178 return this._taskId(bot); | 24169 return this._taskId(bot); |
| 24179 }, | 24170 }, |
| 24180 }; | 24171 }; |
| 24181 | 24172 |
| 24182 var deviceColumnMap = { | 24173 var deviceColumnMap = { |
| 24183 android_devices: function(device) { | 24174 android_devices: function(device) { |
| 24184 var str = this._androidAliasDevice(device); | 24175 var str = this._androidAliasDevice(device); |
| 24185 if (device.okay) { | 24176 if (device.okay) { |
| 24186 str = this._applyAlias(this._deviceType(device), str); | 24177 str = swarming.alias.apply(this._deviceType(device), str); |
| 24187 } | 24178 } |
| 24188 str += " S/N:"; | 24179 str += " S/N:"; |
| 24189 str += device.serial; | 24180 str += device.serial; |
| 24190 return str; | 24181 return str; |
| 24191 }, | 24182 }, |
| 24192 device_os: function(device) { | 24183 device_os: function(device) { |
| 24193 if (device.build) { | 24184 if (device.build) { |
| 24194 return device.build["build.id"]; | 24185 return device.build["build.id"]; |
| 24195 } | 24186 } |
| 24196 return "unknown"; | 24187 return "unknown"; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 24213 disk_space: function(dir, botA, botB) { | 24204 disk_space: function(dir, botA, botB) { |
| 24214 // We sort based on the raw number of MB of the first disk. | 24205 // We sort based on the raw number of MB of the first disk. |
| 24215 var botACol = botA.disks[0].mb; | 24206 var botACol = botA.disks[0].mb; |
| 24216 var botBCol = botB.disks[0].mb;; | 24207 var botBCol = botB.disks[0].mb;; |
| 24217 return dir * swarming.naturalCompare(botACol, botBCol); | 24208 return dir * swarming.naturalCompare(botACol, botBCol); |
| 24218 }, | 24209 }, |
| 24219 }; | 24210 }; |
| 24220 | 24211 |
| 24221 Polymer({ | 24212 Polymer({ |
| 24222 is: 'bot-list', | 24213 is: 'bot-list', |
| 24223 behaviors: [SwarmingBehaviors.BotListBehavior, | 24214 |
| 24224 SwarmingBehaviors.DynamicTableBehavior], | 24215 // The order behaviors are applied in matters - later ones overwrite |
| 24216 // attributes of earlier ones |
| 24217 behaviors: [ |
| 24218 SwarmingBehaviors.BotListBehavior, |
| 24219 SwarmingBehaviors.DynamicTableBehavior, |
| 24220 ], |
| 24225 | 24221 |
| 24226 properties: { | 24222 properties: { |
| 24227 client_id: { | 24223 client_id: { |
| 24228 type: String, | 24224 type: String, |
| 24229 }, | 24225 }, |
| 24230 | 24226 |
| 24231 // For dynamic table. | 24227 // For dynamic table. |
| 24232 _columnMap: { | 24228 _columnMap: { |
| 24233 type: Object, | 24229 type: Object, |
| 24234 value: columnMap, | 24230 value: function() { |
| 24231 var base = this._commonColumns(); |
| 24232 for (var attr in columnMap) { |
| 24233 base[attr] = columnMap[attr]; |
| 24234 } |
| 24235 return base; |
| 24236 }, |
| 24235 }, | 24237 }, |
| 24236 _headerMap: { | 24238 _headerMap: { |
| 24237 type: Object, | 24239 type: Object, |
| 24238 value: headerMap, | 24240 value: headerMap, |
| 24239 }, | 24241 }, |
| 24240 _specialColumns: { | 24242 _specialColumns: { |
| 24241 type: Array, | 24243 type: Array, |
| 24242 value: specialColumns, | 24244 value: specialColumns, |
| 24243 }, | 24245 }, |
| 24244 _specialSort: { | 24246 _specialSort: { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 24261 _botLink: function(id) { | 24263 _botLink: function(id) { |
| 24262 // TODO(kjlubick) Make this point to /newui/ when appropriate. | 24264 // TODO(kjlubick) Make this point to /newui/ when appropriate. |
| 24263 return "/restricted/bot/"+id; | 24265 return "/restricted/bot/"+id; |
| 24264 }, | 24266 }, |
| 24265 | 24267 |
| 24266 | 24268 |
| 24267 _androidAliasDevice: function(device) { | 24269 _androidAliasDevice: function(device) { |
| 24268 if (device.notReady) { | 24270 if (device.notReady) { |
| 24269 return UNAUTHENTICATED.toUpperCase(); | 24271 return UNAUTHENTICATED.toUpperCase(); |
| 24270 } | 24272 } |
| 24271 return this._androidAlias(this._deviceType(device)); | 24273 return swarming.alias.android(this._deviceType(device)); |
| 24272 }, | 24274 }, |
| 24273 | 24275 |
| 24274 _deviceColumn: function(col, device) { | 24276 _deviceColumn: function(col, device) { |
| 24275 var f = deviceColumnMap[col]; | 24277 var f = deviceColumnMap[col]; |
| 24276 if (!f || !device) { | 24278 if (!f || !device) { |
| 24277 return ""; | 24279 return ""; |
| 24278 } | 24280 } |
| 24279 return f.bind(this)(device); | 24281 return f.bind(this)(device); |
| 24280 }, | 24282 }, |
| 24281 | 24283 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 24346 <iron-ajax id="tasklist" url="/_ah/api/swarming/v1/tasks/list" headers="[[au
th_headers]]" params="[[query_params]]" handle-as="json" last-response="{{_list}
}" loading="{{_busy1}}"> | 24348 <iron-ajax id="tasklist" url="/_ah/api/swarming/v1/tasks/list" headers="[[au
th_headers]]" params="[[query_params]]" handle-as="json" last-response="{{_list}
}" loading="{{_busy1}}"> |
| 24347 </iron-ajax> | 24349 </iron-ajax> |
| 24348 | 24350 |
| 24349 | 24351 |
| 24350 </template> | 24352 </template> |
| 24351 <script> | 24353 <script> |
| 24352 (function(){ | 24354 (function(){ |
| 24353 Polymer({ | 24355 Polymer({ |
| 24354 is: 'task-list-data', | 24356 is: 'task-list-data', |
| 24355 | 24357 |
| 24356 behaviors: [SwarmingBehaviors.SwarmingBehavior], | 24358 behaviors: [SwarmingBehaviors.CommonBehavior], |
| 24357 | 24359 |
| 24358 properties: { | 24360 properties: { |
| 24359 // inputs | 24361 // inputs |
| 24360 auth_headers: { | 24362 auth_headers: { |
| 24361 type: Object, | 24363 type: Object, |
| 24362 observer: "signIn", | 24364 observer: "signIn", |
| 24363 }, | 24365 }, |
| 24364 query_params: { | 24366 query_params: { |
| 24365 type: Object, | 24367 type: Object, |
| 24366 }, | 24368 }, |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 24483 var specialColumns = ["name", "state"]; | 24485 var specialColumns = ["name", "state"]; |
| 24484 var columnMap = {}; | 24486 var columnMap = {}; |
| 24485 var headerMap = { | 24487 var headerMap = { |
| 24486 "user": "Requesting User", | 24488 "user": "Requesting User", |
| 24487 }; | 24489 }; |
| 24488 var specialSort = {}; | 24490 var specialSort = {}; |
| 24489 | 24491 |
| 24490 Polymer({ | 24492 Polymer({ |
| 24491 is: 'task-list', | 24493 is: 'task-list', |
| 24492 behaviors: [ | 24494 behaviors: [ |
| 24493 SwarmingBehaviors.SwarmingBehavior, | |
| 24494 SwarmingBehaviors.DynamicTableBehavior, | 24495 SwarmingBehaviors.DynamicTableBehavior, |
| 24495 ], | 24496 ], |
| 24496 | 24497 |
| 24497 properties: { | 24498 properties: { |
| 24498 client_id: { | 24499 client_id: { |
| 24499 type: String, | 24500 type: String, |
| 24500 }, | 24501 }, |
| 24501 | 24502 |
| 24502 // For dynamic table. | 24503 // For dynamic table. |
| 24503 _columnMap: { | 24504 _columnMap: { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 24533 | 24534 |
| 24534 _taskClass: function(task) { | 24535 _taskClass: function(task) { |
| 24535 // TODO(kjlubick): Color tasks? | 24536 // TODO(kjlubick): Color tasks? |
| 24536 return ""; | 24537 return ""; |
| 24537 } | 24538 } |
| 24538 | 24539 |
| 24539 }); | 24540 }); |
| 24540 })(); | 24541 })(); |
| 24541 </script> | 24542 </script> |
| 24542 </dom-module></div></body></html> | 24543 </dom-module></div></body></html> |
| OLD | NEW |