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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: appengine/swarming/elements/build/elements.html
diff --git a/appengine/swarming/elements/build/elements.html b/appengine/swarming/elements/build/elements.html
index 553de914fc68e5c3da1c13716d8efdeca67b3554..c741b96f7fd0b716d6c41169e9cb96940fe95f3e 100644
--- a/appengine/swarming/elements/build/elements.html
+++ b/appengine/swarming/elements/build/elements.html
@@ -14632,7 +14632,30 @@ You can bind to `isAuthorized` property to monitor authorization state.
color: #1F78B4;
}
</style>
-</dom-module><dom-module id="swarming-index" assetpath="/res/imp/index/">
+</dom-module>
+
+<script>
+ window.SwarmingBehaviors = window.SwarmingBehaviors || {};
+ (function(){
+ // This behavior wraps up all the shared swarming functionality.
+ SwarmingBehaviors.SwarmingBehavior = {
+
+ _not: function(a) {
+ return !a;
+ },
+
+ _or: function() {
+ var result = false;
+ // can't use .foreach, as arguments isn't really a function.
+ for (var i = 0; i < arguments.length; i++) {
+ result = result || arguments[i];
+ }
+ return result;
+ },
+ };
+ })();
+</script>
+<dom-module id="swarming-index" assetpath="/res/imp/index/">
<template>
<style include="swarming-app-style">
@@ -14675,9 +14698,167 @@ You can bind to `isAuthorized` property to monitor authorization state.
});
</script>
+</dom-module><dom-module id="dynamic-table-style" assetpath="/res/imp/common/">
+ <template>
+ <style>
+ table {
+ border-collapse: collapse;
+ margin-left: 5px;
+ }
+ td, th {
+ border: 1px solid #DDD;
+ padding: 5px;
+ }
+ th {
+ position: relative;
+ }
+ sort-toggle {
+ position: absolute;
+ right: 0;
+ top: 0.4em;
+ }
+ </style>
+
+ </template>
</dom-module>
<script>
+ window.SwarmingBehaviors = window.SwarmingBehaviors || {};
+ (function(){
+ // This behavior wraps up all the shared swarming functionality.
+ SwarmingBehaviors.DynamicTableBehavior = {
+
+ properties: {
+
+ _columns: {
+ type: Array,
+ },
+
+ _filter: {
+ type: Function,
+ },
+
+ _filteredSortedItems: {
+ type: Array,
+ computed: "_filterAndSort(_items,_filter.*,_sort.*)"
+ },
+
+ _items: {
+ type: Array,
+ },
+
+ _plainColumns: {
+ type: Array,
+ computed: "_stripSpecial(_columns.*)",
+ },
+
+ // _sort is an Object {name:String, direction:String}.
+ _sort: {
+ type: Object,
+ computed: "_makeSortObject(_sortstr)",
+ },
+
+ _sortstr: {
+ type: String,
+ },
+
+ _verbose: {
+ type: Boolean,
+ }
+ },
+
+ _column: function(col, key) {
+ var f = this._columnMap[col];
+ if (!f) {
+ f = function(key) {
+ var c = this._attribute(key, col, "none");
+ if (this._verbose) {
+ return c.join(" | ");
+ }
+ return c[0];
+ }
+ }
+ return f.bind(this)(key);
+ },
+
+ _compare: function(a, b) {
+ if (!this._sort) {
+ return 0;
+ }
+ var dir = 1;
+ if (this._sort.direction === "desc") {
+ dir = -1;
+ }
+ var sort = this._specialSort[this._sort.name];
+ if (sort) {
+ return sort.bind(this)(dir, a, b);
+ }
+ // Default to a natural compare of the columns.
+ var aCol = this._column(this._sort.name, a);
+ var bCol = this._column(this._sort.name, b);
+
+ return dir * swarming.naturalCompare(aCol, bCol);
+ },
+
+ _filterAndSort: function() {
+ // We intentionally sort this._items (and not a copy) to allow users to
+ // "chain" sorts, that is, sort by one thing and then another, and
+ // have both orderings properly impact the list.
+ swarming.stableSort(this._items, this._compare.bind(this));
+ var items = this._items;
+ if (this._filter) {
+ items = items.filter(this._filter.bind(this));
+ }
+
+ return items;
+ },
+
+ _header: function(col){
+ return this._headerMap[col] || col;
+ },
+
+ _hide: function(col) {
+ return this._columns.indexOf(col) === -1;
+ },
+
+ _makeSortObject: function(sortstr){
+ if (!sortstr) {
+ return undefined;
+ }
+ var pieces = sortstr.split(":");
+ if (pieces.length != 2) {
+ // fail safe
+ return {name: "id", direction: "asc"};
+ }
+ return {
+ name: pieces[0],
+ direction: pieces[1],
+ }
+ },
+
+ _sortChange: function(e) {
+ // The event we get from sort-toggle tells us the name of what needs
+ // to be sorting and how to sort it.
+ if (!(e && e.detail && e.detail.name)) {
+ return;
+ }
+ // should trigger the computation of _sort and __filterAndSort
+ this.set("_sortstr", e.detail.name +":"+e.detail.direction);
+ },
+ // _stripSpecial removes the special columns and sorts the remaining
+ // columns so they always appear in the same order, regardless of
+ // the order they are added.
+ _stripSpecial: function(){
+ return this._columns.filter(function(c){
+ return this._specialColumns.indexOf(c) === -1;
+ }.bind(this)).sort();
+ },
+
+ };
+ })();
+</script>
+
+<script>
(function() {
@@ -22685,8 +22866,6 @@ is separate from validation, and `allowed-pattern` does not affect how the input
});
</script>
<script>
-
- window.SwarmingBehaviors = window.SwarmingBehaviors || {};
(function(){
var ANDROID_ALIASES = {
"bullhead": "Nexus 5X",
@@ -22742,8 +22921,9 @@ is separate from validation, and `allowed-pattern` does not affect how the input
// This regex matches a string like "ALIAS (ORIG)", with ORIG as group 1.
var ALIAS_REGEXP = /.+ \((.*)\)/;
- // This behavior wraps up all the shared bot-list functionality.
- SwarmingBehaviors.BotListBehavior = {
+ // This behavior wraps up all the shared bot-list functionality by
+ // extending SwarmingBehaviors.SwarmingBehavior
+ SwarmingBehaviors.BotListBehavior = [SwarmingBehaviors.SwarmingBehavior, {
properties: {
DIMENSIONS_WITH_ALIASES: {
@@ -22818,19 +22998,6 @@ is separate from validation, and `allowed-pattern` does not affect how the input
return GPU_ALIASES[gpu] || UNKNOWN;
},
- _not: function(a) {
- return !a;
- },
-
- _or: function() {
- var result = false;
- // can't use .foreach, as arguments isn't really a function.
- for (var i = 0; i < arguments.length; i++) {
- result = result || arguments[i];
- }
- return result;
- },
-
// _state returns the requested attribute from a bot's state.
// For consistency with _dimension, if the attribute is not an array,
// it is put as the only element in an array.
@@ -22861,7 +23028,7 @@ is separate from validation, and `allowed-pattern` does not affect how the input
}
return str;
},
- }
+ }];
})()
</script>
<dom-module id="bot-filters" assetpath="/res/imp/botlist/">
@@ -23806,41 +23973,17 @@ the fleet.">
</script>
</dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/">
<template>
- <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-style">
+ <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-style dynamic-table-style">
bot-filters, bot-list-summary {
margin-bottom: 8px;
margin-right: 10px;
}
- .bot {
- margin:5px;
- max-width:400px;
- min-height:100px;
- min-width:300px;
- }
- table {
- border-collapse: collapse;
- margin-left: 5px;
- }
- td, th {
- border: 1px solid #DDD;
- padding: 5px;
- }
-
.quarantined, .bad-device {
background-color: #ffdddd;
}
.dead {
background-color: #cccccc;
}
-
- th {
- position: relative;
- }
- sort-toggle {
- position: absolute;
- right: 0;
- top: 0.4em;
- }
.bot-list th > span {
/* Leave space for sort-toggle*/
padding-right: 30px;
@@ -23861,12 +24004,12 @@ the fleet.">
<bot-filters dimensions="[[_dimensions]]" primary_map="[[_primary_map]]" primary_arr="[[_primary_arr]]" columns="{{_columns}}" query_params="{{_query_params}}" filter="{{_filter}}" verbose="{{_verbose}}">
</bot-filters>
- <bot-list-summary columns="[[_columns]]" fleet="[[_fleet]]" filtered_bots="[[_filteredSortedBots]]" sort="[[_sortstr]]" verbose="[[_verbose]]">
+ <bot-list-summary columns="[[_columns]]" fleet="[[_fleet]]" filtered_bots="[[_filteredSortedItems]]" sort="[[_sortstr]]" verbose="[[_verbose]]">
</bot-list-summary>
</div>
- <bot-list-data auth_headers="[[_auth_headers]]" query_params="[[_query_params]]" bots="{{_bots}}" busy="{{_busy}}" dimensions="{{_dimensions}}" fleet="{{_fleet}}" primary_map="{{_primary_map}}" primary_arr="{{_primary_arr}}">
+ <bot-list-data auth_headers="[[_auth_headers]]" query_params="[[_query_params]]" bots="{{_items}}" busy="{{_busy}}" dimensions="{{_dimensions}}" fleet="{{_fleet}}" primary_map="{{_primary_map}}" primary_arr="{{_primary_arr}}">
</bot-list-data>
<table class="bot-list">
@@ -23885,7 +24028,7 @@ the fleet.">
</sort-toggle>
</th>
- <template is="dom-repeat" items="[[_plain_columns]]" as="c">
+ <template is="dom-repeat" items="[[_plainColumns]]" as="c">
<th hidden$="[[_hide(c)]]">
<span>[[_header(c)]]</span>
<sort-toggle name="[[c]]" current="[[_sort]]">
@@ -23895,7 +24038,7 @@ the fleet.">
</tr>
</thead>
<tbody>
- <template id="bot_table" is="dom-repeat" items="[[_filteredSortedBots]]" as="bot" initial-count="50">
+ <template id="bot_table" is="dom-repeat" items="[[_filteredSortedItems]]" as="bot" initial-count="50">
<tr class$="[[_botClass(bot)]]">
<td>
@@ -23907,7 +24050,7 @@ the fleet.">
<a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a>
</td>
- <template is="dom-repeat" items="[[_plain_columns]]" as="c">
+ <template is="dom-repeat" items="[[_plainColumns]]" as="c">
<td hidden$="[[_hide(c)]]">
[[_column(c, bot, _verbose)]]
</td>
@@ -23918,7 +24061,7 @@ the fleet.">
<tr hidden$="[[_hide('android_devices', _columns.*)]]" class$="[[_deviceClass(device)]]">
<td></td>
<td hidden$="[[_hide('task', _columns.*)]]"></td>
- <template is="dom-repeat" items="[[_plain_columns]]" as="c">
+ <template is="dom-repeat" items="[[_plainColumns]]" as="c">
<td hidden$="[[_hide(c)]]">
[[_deviceColumn(c, device, _verbose)]]
</td>
@@ -23935,11 +24078,13 @@ the fleet.">
</template>
<script>
(function(){
- var special_columns = ["id", "task"];
+ // see dynamic-table for more information on specialColumns, headerMap,
+ // columnMap, and specialSort
+ var specialColumns = ["id", "task"];
var headerMap = {
- // "id" and "task" are special, so they don't go here and have their
- // headers hard-coded below.
+ // "id" and "task" are special, so they don't go here. They have their
+ // headers hard-coded above.
"android_devices": "Android Devices",
"cores": "Cores",
"cpu": "CPU",
@@ -23954,10 +24099,6 @@ the fleet.">
"xcode_version": "XCode Version",
};
- // This maps column name to a function that will return the content for a
- // given bot. These functions are bound to this element, and have access
- // to all functions defined here and in bot-list-shared. If a column
- // is not listed here, a sane default will be used (see _column()).
var columnMap = {
android_devices: function(bot) {
var devs = this._attribute(bot, "android_devices", "0");
@@ -24057,8 +24198,6 @@ the fleet.">
}
}
- // specialSort defines any custom sorting rules. By default, a
- // naturalCompare of the column content is done.
var specialSort = {
android_devices: function(dir, botA, botB) {
// We sort on the number of attached devices. Note that this
@@ -24079,7 +24218,8 @@ the fleet.">
Polymer({
is: 'bot-list',
- behaviors: [SwarmingBehaviors.BotListBehavior],
+ behaviors: [SwarmingBehaviors.BotListBehavior,
+ SwarmingBehaviors.DynamicTableBehavior],
properties: {
@@ -24087,40 +24227,34 @@ the fleet.">
type: String,
},
- _bots: {
- type: Array,
- },
-
- _columns: {
- type: Array,
+ // for dynamic table
+ _columnMap: {
+ type: Object,
+ value: function() {
+ return columnMap;
+ }
},
-
- _filter: {
- type: Function,
+ _headerMap: {
+ type: Object,
value: function() {
- return true;
+ return headerMap;
},
},
-
- _filteredSortedBots: {
+ // special columns contain html. non-special (i.e. normal colunns) just
+ // contain text.
+ _specialColumns: {
type: Array,
- computed: "_filterAndSort(_bots,_filter.*,_sort.*)"
+ value: function() {
+ return specialColumns;
+ }
},
-
- _plain_columns: {
- type: Array,
- computed: "_stripSpecial(_columns.*)",
- },
-
- // _sort is an Object {name:String, direction:String}.
- _sort: {
+ _specialSort: {
type: Object,
- computed: "_makeObject(_sortstr)",
+ value: function() {
+ return specialSort;
+ }
},
- _verbose: {
- type: Boolean,
- }
},
_botClass: function(bot) {
@@ -24139,20 +24273,6 @@ the fleet.">
},
- _column: function(col, bot) {
- var f = columnMap[col];
- if (!f) {
- f = function(bot) {
- var c = this._attribute(bot, col, "none");
- if (this._verbose) {
- return c.join(" | ");
- }
- return c[0];
- }
- }
- return f.bind(this)(bot);
- },
-
_androidAliasDevice: function(device) {
if (device.notReady) {
return UNAUTHENTICATED.toUpperCase();
@@ -24175,84 +24295,6 @@ the fleet.">
return "";
},
- _filterAndSort: function(a,b,c) {
- // We intentionally sort this._bots (and not a copy) to allow users to
- // "chain" sorts, that is, sort by one thing and then another, and
- // have both orderings properly impact the list.
- swarming.stableSort(this._bots, this._sortBotTable.bind(this));
- var bots = this._bots;
- if (this._filter) {
- bots = bots.filter(this._filter.bind(this));
- }
-
- return bots;
- },
-
- _header: function(col){
- return headerMap[col] || col;
- },
-
- _hide: function(col) {
- return this._columns.indexOf(col) === -1;
- },
-
- _makeObject: function(sortstr){
- if (!sortstr) {
- return undefined;
- }
- var pieces = sortstr.split(":");
- if (pieces.length != 2) {
- // fail safe
- return {name: "id", direction:"desc"};
- }
- return {
- name: pieces[0],
- direction: pieces[1],
- }
- },
-
- _reRender: function(filter, sort) {
- this.$.bot_table.render();
- },
-
- _sortBotTable: function(botA, botB) {
- if (!this._sort) {
- return 0;
- }
- var dir = 1;
- if (this._sort.direction === "desc") {
- dir = -1;
- }
- var sort = specialSort[this._sort.name];
- if (sort) {
- return sort.bind(this)(dir, botA, botB);
- }
- // Default to a natural compare of the columns.
- var botACol = this._column(this._sort.name, botA);
- var botBCol = this._column(this._sort.name, botB);
-
- return dir * swarming.naturalCompare(botACol, botBCol);
- },
-
- _sortChange: function(e) {
- // The event we get from sort-toggle tells us the name of what needs
- // to be sorting and how to sort it.
- if (!(e && e.detail && e.detail.name)) {
- return;
- }
- // should trigger the computation of _sort and __filterAndSort
- this.set("_sortstr", e.detail.name +":"+e.detail.direction);
- },
-
- // _stripSpecial removes the special columns and sorts the remaining
- // columns so they always appear in the same order, regardless of
- // the order they are added.
- _stripSpecial: function(){
- return this._columns.filter(function(c){
- return special_columns.indexOf(c) === -1;
- }).sort();
- },
-
_taskLink: function(data) {
if (data && data.task_id) {
return "/user/task/" + data.task_id;

Powered by Google App Engine
This is Rietveld 408576698