Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Side by Side Diff: appengine/swarming/elements/build/elements.html

Issue 2241413002: Refactor out reusable pieces from new Botlist (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@master
Patch Set: Address comments Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 14614 matching lines...) Expand 10 before | Expand all | Expand 10 after
14625 <dom-module id="swarming-app-style" assetpath="/res/imp/common/"> 14625 <dom-module id="swarming-app-style" assetpath="/res/imp/common/">
14626 <style> 14626 <style>
14627 * { 14627 * {
14628 font-family: sans-serif; 14628 font-family: sans-serif;
14629 } 14629 }
14630 /* Only style anchor tags that are actually linking somewhere.*/ 14630 /* Only style anchor tags that are actually linking somewhere.*/
14631 a[href] { 14631 a[href] {
14632 color: #1F78B4; 14632 color: #1F78B4;
14633 } 14633 }
14634 </style> 14634 </style>
14635 </dom-module><dom-module id="swarming-index" assetpath="/res/imp/index/"> 14635 </dom-module>
14636
14637 <script>
14638 window.SwarmingBehaviors = window.SwarmingBehaviors || {};
14639 (function(){
14640 // This behavior wraps up all the shared swarming functionality.
14641 SwarmingBehaviors.SwarmingBehavior = {
14642
14643 _not: function(a) {
14644 return !a;
14645 },
14646
14647 _or: function() {
14648 var result = false;
14649 // can't use .foreach, as arguments isn't really a function.
14650 for (var i = 0; i < arguments.length; i++) {
14651 result = result || arguments[i];
14652 }
14653 return result;
14654 },
14655 };
14656 })();
14657 </script>
14658 <dom-module id="swarming-index" assetpath="/res/imp/index/">
14636 <template> 14659 <template>
14637 <style include="swarming-app-style"> 14660 <style include="swarming-app-style">
14638 14661
14639 </style> 14662 </style>
14640 14663
14641 <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" name ="Swarming" busy="[[busy]]"> 14664 <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" name ="Swarming" busy="[[busy]]">
14642 14665
14643 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers= "[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{ {busy}}"> 14666 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers= "[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{ {busy}}">
14644 </iron-ajax> 14667 </iron-ajax>
14645 14668
(...skipping 22 matching lines...) Expand all
14668 type: String, 14691 type: String,
14669 } 14692 }
14670 }, 14693 },
14671 14694
14672 signIn: function(){ 14695 signIn: function(){
14673 this.$.request.generateRequest(); 14696 this.$.request.generateRequest();
14674 }, 14697 },
14675 14698
14676 }); 14699 });
14677 </script> 14700 </script>
14701 </dom-module><dom-module id="dynamic-table-style" assetpath="/res/imp/common/">
14702 <template>
14703 <style>
14704 table {
14705 border-collapse: collapse;
14706 margin-left: 5px;
14707 }
14708 td, th {
14709 border: 1px solid #DDD;
14710 padding: 5px;
14711 }
14712 th {
14713 position: relative;
14714 }
14715 sort-toggle {
14716 position: absolute;
14717 right: 0;
14718 top: 0.4em;
14719 }
14720 </style>
14721
14722 </template>
14678 </dom-module> 14723 </dom-module>
14679 14724
14680 <script> 14725 <script>
14726 window.SwarmingBehaviors = window.SwarmingBehaviors || {};
14727 (function(){
14728 // This behavior wraps up all the shared swarming functionality.
14729 SwarmingBehaviors.DynamicTableBehavior = {
14730
14731 properties: {
14732
14733 _columns: {
14734 type: Array,
14735 },
14736
14737 _filter: {
14738 type: Function,
14739 },
14740
14741 _filteredSortedItems: {
14742 type: Array,
14743 computed: "_filterAndSort(_items,_filter.*,_sort.*)"
14744 },
14745
14746 _items: {
14747 type: Array,
14748 },
14749
14750 _plainColumns: {
14751 type: Array,
14752 computed: "_stripSpecial(_columns.*)",
14753 },
14754
14755 // _sort is an Object {name:String, direction:String}.
14756 _sort: {
14757 type: Object,
14758 computed: "_makeSortObject(_sortstr)",
14759 },
14760
14761 _sortstr: {
14762 type: String,
14763 },
14764
14765 _verbose: {
14766 type: Boolean,
14767 }
14768 },
14769
14770 _column: function(col, key) {
14771 var f = this._columnMap[col];
14772 if (!f) {
14773 f = function(key) {
14774 var c = this._attribute(key, col, "none");
14775 if (this._verbose) {
14776 return c.join(" | ");
14777 }
14778 return c[0];
14779 }
14780 }
14781 return f.bind(this)(key);
14782 },
14783
14784 _compare: function(a, b) {
14785 if (!this._sort) {
14786 return 0;
14787 }
14788 var dir = 1;
14789 if (this._sort.direction === "desc") {
14790 dir = -1;
14791 }
14792 var sort = this._specialSort[this._sort.name];
14793 if (sort) {
14794 return sort.bind(this)(dir, a, b);
14795 }
14796 // Default to a natural compare of the columns.
14797 var aCol = this._column(this._sort.name, a);
14798 var bCol = this._column(this._sort.name, b);
14799
14800 return dir * swarming.naturalCompare(aCol, bCol);
14801 },
14802
14803 _filterAndSort: function() {
14804 // We intentionally sort this._items (and not a copy) to allow users to
14805 // "chain" sorts, that is, sort by one thing and then another, and
14806 // have both orderings properly impact the list.
14807 swarming.stableSort(this._items, this._compare.bind(this));
14808 var items = this._items;
14809 if (this._filter) {
14810 items = items.filter(this._filter.bind(this));
14811 }
14812
14813 return items;
14814 },
14815
14816 _header: function(col){
14817 return this._headerMap[col] || col;
14818 },
14819
14820 _hide: function(col) {
14821 return this._columns.indexOf(col) === -1;
14822 },
14823
14824 _makeSortObject: function(sortstr){
14825 if (!sortstr) {
14826 return undefined;
14827 }
14828 var pieces = sortstr.split(":");
14829 if (pieces.length != 2) {
14830 // fail safe
14831 return {name: "id", direction: "asc"};
14832 }
14833 return {
14834 name: pieces[0],
14835 direction: pieces[1],
14836 }
14837 },
14838
14839 _sortChange: function(e) {
14840 // The event we get from sort-toggle tells us the name of what needs
14841 // to be sorting and how to sort it.
14842 if (!(e && e.detail && e.detail.name)) {
14843 return;
14844 }
14845 // should trigger the computation of _sort and __filterAndSort
14846 this.set("_sortstr", e.detail.name +":"+e.detail.direction);
14847 },
14848 // _stripSpecial removes the special columns and sorts the remaining
14849 // columns so they always appear in the same order, regardless of
14850 // the order they are added.
14851 _stripSpecial: function(){
14852 return this._columns.filter(function(c){
14853 return this._specialColumns.indexOf(c) === -1;
14854 }.bind(this)).sort();
14855 },
14856
14857 };
14858 })();
14859 </script>
14860
14861 <script>
14681 14862
14682 (function() { 14863 (function() {
14683 14864
14684 // monostate data 14865 // monostate data
14685 var metaDatas = {}; 14866 var metaDatas = {};
14686 var metaArrays = {}; 14867 var metaArrays = {};
14687 var singleton = null; 14868 var singleton = null;
14688 14869
14689 Polymer.IronMeta = Polymer({ 14870 Polymer.IronMeta = Polymer({
14690 14871
(...skipping 7987 matching lines...) Expand 10 before | Expand all | Expand 10 after
22678 Polymer({ 22859 Polymer({
22679 is: 'paper-input', 22860 is: 'paper-input',
22680 22861
22681 behaviors: [ 22862 behaviors: [
22682 Polymer.IronFormElementBehavior, 22863 Polymer.IronFormElementBehavior,
22683 Polymer.PaperInputBehavior 22864 Polymer.PaperInputBehavior
22684 ] 22865 ]
22685 }); 22866 });
22686 </script> 22867 </script>
22687 <script> 22868 <script>
22688
22689 window.SwarmingBehaviors = window.SwarmingBehaviors || {};
22690 (function(){ 22869 (function(){
22691 var ANDROID_ALIASES = { 22870 var ANDROID_ALIASES = {
22692 "bullhead": "Nexus 5X", 22871 "bullhead": "Nexus 5X",
22693 "flo": "Nexus 7 (2013)", 22872 "flo": "Nexus 7 (2013)",
22694 "flounder": "Nexus 9", 22873 "flounder": "Nexus 9",
22695 "foster": "NVIDIA Shield", 22874 "foster": "NVIDIA Shield",
22696 "fugu": "Nexus Player", 22875 "fugu": "Nexus Player",
22697 "grouper": "Nexus 7 (2012)", 22876 "grouper": "Nexus 7 (2012)",
22698 "hammerhead": "Nexus 5", 22877 "hammerhead": "Nexus 5",
22699 "m0": "Galaxy S3", 22878 "m0": "Galaxy S3",
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
22735 "8086:0a2e": "Intel Haswell Integrated", 22914 "8086:0a2e": "Intel Haswell Integrated",
22736 "8086:0d26": "Intel Crystal Well Integrated", 22915 "8086:0d26": "Intel Crystal Well Integrated",
22737 "8086:22b1": "Intel Braswell Integrated", 22916 "8086:22b1": "Intel Braswell Integrated",
22738 } 22917 }
22739 22918
22740 // For consistency, all aliases are displayed like: 22919 // For consistency, all aliases are displayed like:
22741 // Nexus 5X (bullhead) 22920 // Nexus 5X (bullhead)
22742 // This regex matches a string like "ALIAS (ORIG)", with ORIG as group 1. 22921 // This regex matches a string like "ALIAS (ORIG)", with ORIG as group 1.
22743 var ALIAS_REGEXP = /.+ \((.*)\)/; 22922 var ALIAS_REGEXP = /.+ \((.*)\)/;
22744 22923
22745 // This behavior wraps up all the shared bot-list functionality. 22924 // This behavior wraps up all the shared bot-list functionality by
22746 SwarmingBehaviors.BotListBehavior = { 22925 // extending SwarmingBehaviors.SwarmingBehavior
22926 SwarmingBehaviors.BotListBehavior = [SwarmingBehaviors.SwarmingBehavior, {
22747 22927
22748 properties: { 22928 properties: {
22749 DIMENSIONS_WITH_ALIASES: { 22929 DIMENSIONS_WITH_ALIASES: {
22750 type: Array, 22930 type: Array,
22751 value: function(){ 22931 value: function(){
22752 return ["device_type", "gpu"]; 22932 return ["device_type", "gpu"];
22753 }, 22933 },
22754 }, 22934 },
22755 BOT_PROPERTIES: { 22935 BOT_PROPERTIES: {
22756 type: Array, 22936 type: Array,
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
22811 return bot.dimensions[i].value; 22991 return bot.dimensions[i].value;
22812 } 22992 }
22813 } 22993 }
22814 return undefined; 22994 return undefined;
22815 }, 22995 },
22816 22996
22817 _gpuAlias: function(gpu) { 22997 _gpuAlias: function(gpu) {
22818 return GPU_ALIASES[gpu] || UNKNOWN; 22998 return GPU_ALIASES[gpu] || UNKNOWN;
22819 }, 22999 },
22820 23000
22821 _not: function(a) {
22822 return !a;
22823 },
22824
22825 _or: function() {
22826 var result = false;
22827 // can't use .foreach, as arguments isn't really a function.
22828 for (var i = 0; i < arguments.length; i++) {
22829 result = result || arguments[i];
22830 }
22831 return result;
22832 },
22833
22834 // _state returns the requested attribute from a bot's state. 23001 // _state returns the requested attribute from a bot's state.
22835 // For consistency with _dimension, if the attribute is not an array, 23002 // For consistency with _dimension, if the attribute is not an array,
22836 // it is put as the only element in an array. 23003 // it is put as the only element in an array.
22837 _state: function(bot, attr) { 23004 _state: function(bot, attr) {
22838 if (!bot || !bot.state || !bot.state[attr]) { 23005 if (!bot || !bot.state || !bot.state[attr]) {
22839 return undefined 23006 return undefined
22840 } 23007 }
22841 var state = bot.state[attr]; 23008 var state = bot.state[attr];
22842 if (Array.isArray(state)) { 23009 if (Array.isArray(state)) {
22843 return state; 23010 return state;
(...skipping 10 matching lines...) Expand all
22854 23021
22855 // _unalias will return the base dimension/state with its alias removed 23022 // _unalias will return the base dimension/state with its alias removed
22856 // if it had one. This is handy for sorting and filtering. 23023 // if it had one. This is handy for sorting and filtering.
22857 _unalias: function(str) { 23024 _unalias: function(str) {
22858 var match = ALIAS_REGEXP.exec(str); 23025 var match = ALIAS_REGEXP.exec(str);
22859 if (match) { 23026 if (match) {
22860 return match[1]; 23027 return match[1];
22861 } 23028 }
22862 return str; 23029 return str;
22863 }, 23030 },
22864 } 23031 }];
22865 })() 23032 })()
22866 </script> 23033 </script>
22867 <dom-module id="bot-filters" assetpath="/res/imp/botlist/"> 23034 <dom-module id="bot-filters" assetpath="/res/imp/botlist/">
22868 <template> 23035 <template>
22869 <style is="custom-style" include="iron-flex iron-flex-alignment iron-positio ning"> 23036 <style is="custom-style" include="iron-flex iron-flex-alignment iron-positio ning">
22870 :host { 23037 :host {
22871 display: block; 23038 display: block;
22872 font-family: sans-serif; 23039 font-family: sans-serif;
22873 } 23040 }
22874 #filter { 23041 #filter {
(...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after
23799 curr.alive++; 23966 curr.alive++;
23800 } 23967 }
23801 curr.all++; 23968 curr.all++;
23802 }.bind(this)); 23969 }.bind(this));
23803 this.set("_currently_showing", curr); 23970 this.set("_currently_showing", curr);
23804 } 23971 }
23805 }); 23972 });
23806 </script> 23973 </script>
23807 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/"> 23974 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/">
23808 <template> 23975 <template>
23809 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app- style"> 23976 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app- style dynamic-table-style">
23810 bot-filters, bot-list-summary { 23977 bot-filters, bot-list-summary {
23811 margin-bottom: 8px; 23978 margin-bottom: 8px;
23812 margin-right: 10px; 23979 margin-right: 10px;
23813 } 23980 }
23814 .bot {
23815 margin:5px;
23816 max-width:400px;
23817 min-height:100px;
23818 min-width:300px;
23819 }
23820 table {
23821 border-collapse: collapse;
23822 margin-left: 5px;
23823 }
23824 td, th {
23825 border: 1px solid #DDD;
23826 padding: 5px;
23827 }
23828
23829 .quarantined, .bad-device { 23981 .quarantined, .bad-device {
23830 background-color: #ffdddd; 23982 background-color: #ffdddd;
23831 } 23983 }
23832 .dead { 23984 .dead {
23833 background-color: #cccccc; 23985 background-color: #cccccc;
23834 } 23986 }
23835
23836 th {
23837 position: relative;
23838 }
23839 sort-toggle {
23840 position: absolute;
23841 right: 0;
23842 top: 0.4em;
23843 }
23844 .bot-list th > span { 23987 .bot-list th > span {
23845 /* Leave space for sort-toggle*/ 23988 /* Leave space for sort-toggle*/
23846 padding-right: 30px; 23989 padding-right: 30px;
23847 } 23990 }
23848 </style> 23991 </style>
23849 23992
23850 <url-param name="sort" value="{{_sortstr}}" default_value="id:asc"> 23993 <url-param name="sort" value="{{_sortstr}}" default_value="id:asc">
23851 </url-param> 23994 </url-param>
23852 23995
23853 <swarming-app client_id="[[client_id]]" auth_headers="{{_auth_headers}}" sig ned_in="{{_signed_in}}" busy="[[_busy]]" name="Swarming Bot List"> 23996 <swarming-app client_id="[[client_id]]" auth_headers="{{_auth_headers}}" sig ned_in="{{_signed_in}}" busy="[[_busy]]" name="Swarming Bot List">
23854 23997
23855 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> 23998 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2>
23856 23999
23857 <div hidden$="[[_not(_signed_in)]]"> 24000 <div hidden$="[[_not(_signed_in)]]">
23858 24001
23859 <div class="horizontal layout"> 24002 <div class="horizontal layout">
23860 24003
23861 <bot-filters dimensions="[[_dimensions]]" primary_map="[[_primary_map] ]" primary_arr="[[_primary_arr]]" columns="{{_columns}}" query_params="{{_query_ params}}" filter="{{_filter}}" verbose="{{_verbose}}"> 24004 <bot-filters dimensions="[[_dimensions]]" primary_map="[[_primary_map] ]" primary_arr="[[_primary_arr]]" columns="{{_columns}}" query_params="{{_query_ params}}" filter="{{_filter}}" verbose="{{_verbose}}">
23862 </bot-filters> 24005 </bot-filters>
23863 24006
23864 <bot-list-summary columns="[[_columns]]" fleet="[[_fleet]]" filtered_b ots="[[_filteredSortedBots]]" sort="[[_sortstr]]" verbose="[[_verbose]]"> 24007 <bot-list-summary columns="[[_columns]]" fleet="[[_fleet]]" filtered_b ots="[[_filteredSortedItems]]" sort="[[_sortstr]]" verbose="[[_verbose]]">
23865 </bot-list-summary> 24008 </bot-list-summary>
23866 24009
23867 </div> 24010 </div>
23868 24011
23869 <bot-list-data auth_headers="[[_auth_headers]]" query_params="[[_query_p arams]]" bots="{{_bots}}" busy="{{_busy}}" dimensions="{{_dimensions}}" fleet="{ {_fleet}}" primary_map="{{_primary_map}}" primary_arr="{{_primary_arr}}"> 24012 <bot-list-data auth_headers="[[_auth_headers]]" query_params="[[_query_p arams]]" bots="{{_items}}" busy="{{_busy}}" dimensions="{{_dimensions}}" fleet=" {{_fleet}}" primary_map="{{_primary_map}}" primary_arr="{{_primary_arr}}">
23870 </bot-list-data> 24013 </bot-list-data>
23871 24014
23872 <table class="bot-list"> 24015 <table class="bot-list">
23873 <thead on-sort_change="_sortChange"> 24016 <thead on-sort_change="_sortChange">
23874 24017
23875 <tr> 24018 <tr>
23876 <th> 24019 <th>
23877 <span>Bot Id</span> 24020 <span>Bot Id</span>
23878 <sort-toggle name="id" current="[[_sort]]"> 24021 <sort-toggle name="id" current="[[_sort]]">
23879 </sort-toggle> 24022 </sort-toggle>
23880 </th> 24023 </th>
23881 24024
23882 <th hidden$="[[_hide('task', _columns.*)]]"> 24025 <th hidden$="[[_hide('task', _columns.*)]]">
23883 <span>Current Task</span> 24026 <span>Current Task</span>
23884 <sort-toggle name="task" current="[[_sort]]"> 24027 <sort-toggle name="task" current="[[_sort]]">
23885 </sort-toggle> 24028 </sort-toggle>
23886 </th> 24029 </th>
23887 24030
23888 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> 24031 <template is="dom-repeat" items="[[_plainColumns]]" as="c">
23889 <th hidden$="[[_hide(c)]]"> 24032 <th hidden$="[[_hide(c)]]">
23890 <span>[[_header(c)]]</span> 24033 <span>[[_header(c)]]</span>
23891 <sort-toggle name="[[c]]" current="[[_sort]]"> 24034 <sort-toggle name="[[c]]" current="[[_sort]]">
23892 </sort-toggle> 24035 </sort-toggle>
23893 </th> 24036 </th>
23894 </template> 24037 </template>
23895 </tr> 24038 </tr>
23896 </thead> 24039 </thead>
23897 <tbody> 24040 <tbody>
23898 <template id="bot_table" is="dom-repeat" items="[[_filteredSortedBot s]]" as="bot" initial-count="50"> 24041 <template id="bot_table" is="dom-repeat" items="[[_filteredSortedIte ms]]" as="bot" initial-count="50">
23899 24042
23900 <tr class$="[[_botClass(bot)]]"> 24043 <tr class$="[[_botClass(bot)]]">
23901 <td> 24044 <td>
23902 <a class="center" href$="[[_botLink(bot.bot_id)]]" target="_bl ank"> 24045 <a class="center" href$="[[_botLink(bot.bot_id)]]" target="_bl ank">
23903 [[bot.bot_id]] 24046 [[bot.bot_id]]
23904 </a> 24047 </a>
23905 </td> 24048 </td>
23906 <td hidden$="[[_hide('task', _columns.*)]]"> 24049 <td hidden$="[[_hide('task', _columns.*)]]">
23907 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a> 24050 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a>
23908 </td> 24051 </td>
23909 24052
23910 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> 24053 <template is="dom-repeat" items="[[_plainColumns]]" as="c">
23911 <td hidden$="[[_hide(c)]]"> 24054 <td hidden$="[[_hide(c)]]">
23912 [[_column(c, bot, _verbose)]] 24055 [[_column(c, bot, _verbose)]]
23913 </td> 24056 </td>
23914 </template> 24057 </template>
23915 24058
23916 </tr> 24059 </tr>
23917 <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> 24060 <template is="dom-repeat" items="[[_devices(bot)]]" as="device">
23918 <tr hidden$="[[_hide('android_devices', _columns.*)]]" class$="[ [_deviceClass(device)]]"> 24061 <tr hidden$="[[_hide('android_devices', _columns.*)]]" class$="[ [_deviceClass(device)]]">
23919 <td></td> 24062 <td></td>
23920 <td hidden$="[[_hide('task', _columns.*)]]"></td> 24063 <td hidden$="[[_hide('task', _columns.*)]]"></td>
23921 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> 24064 <template is="dom-repeat" items="[[_plainColumns]]" as="c">
23922 <td hidden$="[[_hide(c)]]"> 24065 <td hidden$="[[_hide(c)]]">
23923 [[_deviceColumn(c, device, _verbose)]] 24066 [[_deviceColumn(c, device, _verbose)]]
23924 </td> 24067 </td>
23925 </template> 24068 </template>
23926 </tr> 24069 </tr>
23927 </template> 24070 </template>
23928 </template> 24071 </template>
23929 </tbody> 24072 </tbody>
23930 </table> 24073 </table>
23931 </div> 24074 </div>
23932 24075
23933 </swarming-app> 24076 </swarming-app>
23934 24077
23935 </template> 24078 </template>
23936 <script> 24079 <script>
23937 (function(){ 24080 (function(){
23938 var special_columns = ["id", "task"]; 24081 // see dynamic-table for more information on specialColumns, headerMap,
24082 // columnMap, and specialSort
24083 var specialColumns = ["id", "task"];
23939 24084
23940 var headerMap = { 24085 var headerMap = {
23941 // "id" and "task" are special, so they don't go here and have their 24086 // "id" and "task" are special, so they don't go here. They have their
23942 // headers hard-coded below. 24087 // headers hard-coded above.
23943 "android_devices": "Android Devices", 24088 "android_devices": "Android Devices",
23944 "cores": "Cores", 24089 "cores": "Cores",
23945 "cpu": "CPU", 24090 "cpu": "CPU",
23946 "device": "Non-android Device", 24091 "device": "Non-android Device",
23947 "device_os": "Device OS", 24092 "device_os": "Device OS",
23948 "device_type": "Device Type", 24093 "device_type": "Device Type",
23949 "disk_space": "Free Space (MB)", 24094 "disk_space": "Free Space (MB)",
23950 "gpu": "GPU", 24095 "gpu": "GPU",
23951 "os": "OS", 24096 "os": "OS",
23952 "pool": "Pool", 24097 "pool": "Pool",
23953 "status": "Status", 24098 "status": "Status",
23954 "xcode_version": "XCode Version", 24099 "xcode_version": "XCode Version",
23955 }; 24100 };
23956 24101
23957 // This maps column name to a function that will return the content for a
23958 // given bot. These functions are bound to this element, and have access
23959 // to all functions defined here and in bot-list-shared. If a column
23960 // is not listed here, a sane default will be used (see _column()).
23961 var columnMap = { 24102 var columnMap = {
23962 android_devices: function(bot) { 24103 android_devices: function(bot) {
23963 var devs = this._attribute(bot, "android_devices", "0"); 24104 var devs = this._attribute(bot, "android_devices", "0");
23964 if (this._verbose) { 24105 if (this._verbose) {
23965 return devs.join(" | ") + " devices available"; 24106 return devs.join(" | ") + " devices available";
23966 } 24107 }
23967 // max() works on strings as long as they can be coerced to Number. 24108 // max() works on strings as long as they can be coerced to Number.
23968 return Math.max(...devs) + " devices available"; 24109 return Math.max(...devs) + " devices available";
23969 }, 24110 },
23970 device_type: function(bot) { 24111 device_type: function(bot) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
24050 if (device.build) { 24191 if (device.build) {
24051 return device.build["build.id"]; 24192 return device.build["build.id"];
24052 } 24193 }
24053 return "unknown"; 24194 return "unknown";
24054 }, 24195 },
24055 status: function(device) { 24196 status: function(device) {
24056 return device.state; 24197 return device.state;
24057 } 24198 }
24058 } 24199 }
24059 24200
24060 // specialSort defines any custom sorting rules. By default, a
24061 // naturalCompare of the column content is done.
24062 var specialSort = { 24201 var specialSort = {
24063 android_devices: function(dir, botA, botB) { 24202 android_devices: function(dir, botA, botB) {
24064 // We sort on the number of attached devices. Note that this 24203 // We sort on the number of attached devices. Note that this
24065 // may not be the same as android_devices, because _devices().length 24204 // may not be the same as android_devices, because _devices().length
24066 // counts all devices plugged into the bot, whereas android_devices 24205 // counts all devices plugged into the bot, whereas android_devices
24067 // counts just devices ready for work. 24206 // counts just devices ready for work.
24068 var botACol = this._devices(botA).length; 24207 var botACol = this._devices(botA).length;
24069 var botBCol = this._devices(botB).length; 24208 var botBCol = this._devices(botB).length;
24070 return dir * swarming.naturalCompare(botACol, botBCol); 24209 return dir * swarming.naturalCompare(botACol, botBCol);
24071 }, 24210 },
24072 disk_space: function(dir, botA, botB) { 24211 disk_space: function(dir, botA, botB) {
24073 // We sort based on the raw number of MB of the first disk. 24212 // We sort based on the raw number of MB of the first disk.
24074 var botACol = botA.disks[0].mb; 24213 var botACol = botA.disks[0].mb;
24075 var botBCol = botB.disks[0].mb;; 24214 var botBCol = botB.disks[0].mb;;
24076 return dir * swarming.naturalCompare(botACol, botBCol); 24215 return dir * swarming.naturalCompare(botACol, botBCol);
24077 }, 24216 },
24078 }; 24217 };
24079 24218
24080 Polymer({ 24219 Polymer({
24081 is: 'bot-list', 24220 is: 'bot-list',
24082 behaviors: [SwarmingBehaviors.BotListBehavior], 24221 behaviors: [SwarmingBehaviors.BotListBehavior,
24222 SwarmingBehaviors.DynamicTableBehavior],
24083 24223
24084 properties: { 24224 properties: {
24085 24225
24086 client_id: { 24226 client_id: {
24087 type: String, 24227 type: String,
24088 }, 24228 },
24089 24229
24090 _bots: { 24230 // for dynamic table
24231 _columnMap: {
24232 type: Object,
24233 value: function() {
24234 return columnMap;
24235 }
24236 },
24237 _headerMap: {
24238 type: Object,
24239 value: function() {
24240 return headerMap;
24241 },
24242 },
24243 // special columns contain html. non-special (i.e. normal colunns) just
24244 // contain text.
24245 _specialColumns: {
24091 type: Array, 24246 type: Array,
24247 value: function() {
24248 return specialColumns;
24249 }
24250 },
24251 _specialSort: {
24252 type: Object,
24253 value: function() {
24254 return specialSort;
24255 }
24092 }, 24256 },
24093 24257
24094 _columns: {
24095 type: Array,
24096 },
24097
24098 _filter: {
24099 type: Function,
24100 value: function() {
24101 return true;
24102 },
24103 },
24104
24105 _filteredSortedBots: {
24106 type: Array,
24107 computed: "_filterAndSort(_bots,_filter.*,_sort.*)"
24108 },
24109
24110 _plain_columns: {
24111 type: Array,
24112 computed: "_stripSpecial(_columns.*)",
24113 },
24114
24115 // _sort is an Object {name:String, direction:String}.
24116 _sort: {
24117 type: Object,
24118 computed: "_makeObject(_sortstr)",
24119 },
24120
24121 _verbose: {
24122 type: Boolean,
24123 }
24124 }, 24258 },
24125 24259
24126 _botClass: function(bot) { 24260 _botClass: function(bot) {
24127 if (bot.is_dead) { 24261 if (bot.is_dead) {
24128 return "dead"; 24262 return "dead";
24129 } 24263 }
24130 if (bot.quarantined) { 24264 if (bot.quarantined) {
24131 return "quarantined"; 24265 return "quarantined";
24132 } 24266 }
24133 return ""; 24267 return "";
24134 }, 24268 },
24135 24269
24136 _botLink: function(id) { 24270 _botLink: function(id) {
24137 // TODO(kjlubick) Make this point to /newui/ when appropriate. 24271 // TODO(kjlubick) Make this point to /newui/ when appropriate.
24138 return "/restricted/bot/"+id; 24272 return "/restricted/bot/"+id;
24139 }, 24273 },
24140 24274
24141 24275
24142 _column: function(col, bot) {
24143 var f = columnMap[col];
24144 if (!f) {
24145 f = function(bot) {
24146 var c = this._attribute(bot, col, "none");
24147 if (this._verbose) {
24148 return c.join(" | ");
24149 }
24150 return c[0];
24151 }
24152 }
24153 return f.bind(this)(bot);
24154 },
24155
24156 _androidAliasDevice: function(device) { 24276 _androidAliasDevice: function(device) {
24157 if (device.notReady) { 24277 if (device.notReady) {
24158 return UNAUTHENTICATED.toUpperCase(); 24278 return UNAUTHENTICATED.toUpperCase();
24159 } 24279 }
24160 return this._androidAlias(this._deviceType(device)); 24280 return this._androidAlias(this._deviceType(device));
24161 }, 24281 },
24162 24282
24163 _deviceColumn: function(col, device) { 24283 _deviceColumn: function(col, device) {
24164 var f = deviceColumnMap[col]; 24284 var f = deviceColumnMap[col];
24165 if (!f || !device) { 24285 if (!f || !device) {
24166 return ""; 24286 return "";
24167 } 24287 }
24168 return f.bind(this)(device); 24288 return f.bind(this)(device);
24169 }, 24289 },
24170 24290
24171 _deviceClass: function(device) { 24291 _deviceClass: function(device) {
24172 if (!device.okay) { 24292 if (!device.okay) {
24173 return "bad-device"; 24293 return "bad-device";
24174 } 24294 }
24175 return ""; 24295 return "";
24176 }, 24296 },
24177 24297
24178 _filterAndSort: function(a,b,c) {
24179 // We intentionally sort this._bots (and not a copy) to allow users to
24180 // "chain" sorts, that is, sort by one thing and then another, and
24181 // have both orderings properly impact the list.
24182 swarming.stableSort(this._bots, this._sortBotTable.bind(this));
24183 var bots = this._bots;
24184 if (this._filter) {
24185 bots = bots.filter(this._filter.bind(this));
24186 }
24187
24188 return bots;
24189 },
24190
24191 _header: function(col){
24192 return headerMap[col] || col;
24193 },
24194
24195 _hide: function(col) {
24196 return this._columns.indexOf(col) === -1;
24197 },
24198
24199 _makeObject: function(sortstr){
24200 if (!sortstr) {
24201 return undefined;
24202 }
24203 var pieces = sortstr.split(":");
24204 if (pieces.length != 2) {
24205 // fail safe
24206 return {name: "id", direction:"desc"};
24207 }
24208 return {
24209 name: pieces[0],
24210 direction: pieces[1],
24211 }
24212 },
24213
24214 _reRender: function(filter, sort) {
24215 this.$.bot_table.render();
24216 },
24217
24218 _sortBotTable: function(botA, botB) {
24219 if (!this._sort) {
24220 return 0;
24221 }
24222 var dir = 1;
24223 if (this._sort.direction === "desc") {
24224 dir = -1;
24225 }
24226 var sort = specialSort[this._sort.name];
24227 if (sort) {
24228 return sort.bind(this)(dir, botA, botB);
24229 }
24230 // Default to a natural compare of the columns.
24231 var botACol = this._column(this._sort.name, botA);
24232 var botBCol = this._column(this._sort.name, botB);
24233
24234 return dir * swarming.naturalCompare(botACol, botBCol);
24235 },
24236
24237 _sortChange: function(e) {
24238 // The event we get from sort-toggle tells us the name of what needs
24239 // to be sorting and how to sort it.
24240 if (!(e && e.detail && e.detail.name)) {
24241 return;
24242 }
24243 // should trigger the computation of _sort and __filterAndSort
24244 this.set("_sortstr", e.detail.name +":"+e.detail.direction);
24245 },
24246
24247 // _stripSpecial removes the special columns and sorts the remaining
24248 // columns so they always appear in the same order, regardless of
24249 // the order they are added.
24250 _stripSpecial: function(){
24251 return this._columns.filter(function(c){
24252 return special_columns.indexOf(c) === -1;
24253 }).sort();
24254 },
24255
24256 _taskLink: function(data) { 24298 _taskLink: function(data) {
24257 if (data && data.task_id) { 24299 if (data && data.task_id) {
24258 return "/user/task/" + data.task_id; 24300 return "/user/task/" + data.task_id;
24259 } 24301 }
24260 return undefined; 24302 return undefined;
24261 } 24303 }
24262 24304
24263 }); 24305 });
24264 })(); 24306 })();
24265 </script> 24307 </script>
24266 </dom-module></div></body></html> 24308 </dom-module></div></body></html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698