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

Side by Side Diff: appengine/swarming/elements/res/imp/common/dynamic-table-behavior.html

Issue 2269643002: Extract shared filters and aliasing code (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@master
Patch Set: Address nit 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
(Empty)
1 <!--
2 Copyright 2016 The LUCI Authors. All rights reserved.
3 Use of this source code is governed under the Apache License, Version 2.0
4 that can be found in the LICENSE file.
5
6 This file contains most of the logic needed to create a dynamic table. It is b roken up into two
7 parts, a style dom-module called "dynamic-table-style" and a behavior called
8 SwarmingBehaviors.DynamicTableBehavior. This behavior ties together filtering, sorting and column
9 content. It also offers a few utilities to make creating the table easier. A c lient of these two
10 parts needs to create the templates to actually draw the <table>,<tr> and so o n. See
11 bot-list.html and task-list.html for examples.
12
13 A client should use the provided style set as follows:
14
15 <link rel="import" href="/res/imp/common/dynamic-table-behavior.html">
16 ...
17 <template>
18 <style include="dynamic-table-style">
19 ...
20
21 This behavior has already defined the following properties, which a client sho uld bind to:
22 _columns, Array<String>, The columns that should be shown.
23 _items, Array<Object>, Those elements that may be displayed and/or sorted, d epending on the
24 settings.
25 _filter, Function, Given an element from _items, return a boolean if the ite m should be shown.
26 This function will be bound to this element.
27 _sortstr, String, A String representation of the current state of sorting li ke
28 [name]:["asc", "desc"].
29 _verbose, Boolean, If the verbose contents of the table should be shown.
30
31 A client must define the following properties:
32 _columnMap: Object, a mapping of column name to a function that will return the content for a
33 given bot. These functions are bound to this element. If a column is not listed here, a sane
34 default will be used (see _column()).
35 _headerMap: Object, a mapping of column name to the displayed text for a col umn.
36 _specialColumns, Array<String> A list of "special" column names, that is, co lumns which will
37 have html in them, provided by the client. non-special (i.e. plain colun ns) just contain
38 text and will have their content provided by _attribute (see below).
39 _specialSort, Object, A mapping of column name to a function that implements custom sorting
40 rules. The function will be given (dir, a, b) and is expected to return an int, as a normal
41 sort comparison function would. Otherwise, natural comparison of a and b is used
42 (see _compare()).
43
44 A client must define the following methods:
45 _attribute(i, col, default): Given the item i, return an array of values for the column "col",
46 or an array containting just the default, if not. This is only used as a default when a
47 column does not appear in _columnMap.
48
49 This behavior provides the following properties:
50 _filteredSortedItems, Array<Object>, The list of items that should shown, af ter filtering and
51 sorting.
52 _plainColumns, Array<String>, the list of columns with any special columns s tripped out.
53
54 This behavior provides the following methods:
55 _column(col, item): Return the text content of item for a column.
56 _header(col): Return the header for a column, defaulting to the column name.
57 _hide(col): Return a boolean based on whether to hide this column.
58 _sortChange(event): Update the sorting based on an event created by sort-tog gle.
59 -->
60 <link rel="import" href="common-behavior.html">
61 <dom-module id="dynamic-table-style">
62 <template>
63 <style>
64 table {
65 border-collapse: collapse;
66 margin-left: 5px;
67 }
68 td, th {
69 border: 1px solid #DDD;
70 padding: 5px;
71 }
72 th {
73 position: relative;
74 }
75 sort-toggle {
76 position: absolute;
77 right: 0;
78 top: 0.4em;
79 }
80 </style>
81
82 </template>
83 </dom-module>
84
85 <script>
86 (function(){
87 // This behavior wraps up all the shared swarming functionality.
88 SwarmingBehaviors.DynamicTableBehavior = [SwarmingBehaviors.CommonBehavior, {
89
90 properties: {
91
92 _columns: {
93 type: Array,
94 },
95
96 _filter: {
97 type: Function,
98 },
99
100 _filteredSortedItems: {
101 type: Array,
102 computed: "_filterAndSort(_items,_filter.*,_sort.*)"
103 },
104
105 _items: {
106 type: Array,
107 },
108
109 _plainColumns: {
110 type: Array,
111 computed: "_stripSpecial(_columns.*)",
112 },
113
114 // _sort is an Object {name:String, direction:String}.
115 _sort: {
116 type: Object,
117 computed: "_makeSortObject(_sortstr)",
118 },
119
120 _sortstr: {
121 type: String,
122 },
123
124 _verbose: {
125 type: Boolean,
126 }
127 },
128
129 _column: function(col, key) {
130 var f = this._columnMap[col];
131 if (!f) {
132 f = function(key) {
133 var c = this._attribute(key, col, "none");
134 if (this._verbose) {
135 return c.join(" | ");
136 }
137 return c[0];
138 }
139 }
140 return f.bind(this)(key);
141 },
142
143 _compare: function(a, b) {
144 if (!this._sort) {
145 return 0;
146 }
147 var dir = 1;
148 if (this._sort.direction === "desc") {
149 dir = -1;
150 }
151 var sort = this._specialSort[this._sort.name];
152 if (sort) {
153 return sort.bind(this)(dir, a, b);
154 }
155 // Default to a natural compare of the columns.
156 var aCol = this._column(this._sort.name, a);
157 var bCol = this._column(this._sort.name, b);
158
159 return dir * swarming.naturalCompare(aCol, bCol);
160 },
161
162 _filterAndSort: function() {
163 // We intentionally sort this._items (and not a copy) to allow users to
164 // "chain" sorts, that is, sort by one thing and then another, and
165 // have both orderings properly impact the list.
166 swarming.stableSort(this._items, this._compare.bind(this));
167 var items = this._items;
168 if (this._filter) {
169 items = items.filter(this._filter.bind(this));
170 }
171
172 return items;
173 },
174
175 _header: function(col){
176 return this._headerMap[col] || col;
177 },
178
179 _hide: function(col) {
180 return this._columns.indexOf(col) === -1;
181 },
182
183 _makeSortObject: function(sortstr){
184 if (!sortstr) {
185 return undefined;
186 }
187 var pieces = sortstr.split(":");
188 if (pieces.length != 2) {
189 // fail safe
190 return {name: "id", direction: "asc"};
191 }
192 return {
193 name: pieces[0],
194 direction: pieces[1],
195 }
196 },
197
198 _sortChange: function(e) {
199 // The event we get from sort-toggle tells us the name of what needs
200 // to be sorting and how to sort it.
201 if (!(e && e.detail && e.detail.name)) {
202 return;
203 }
204 // should trigger the computation of _sort and __filterAndSort
205 this.set("_sortstr", e.detail.name + ":" + e.detail.direction);
206 },
207 // _stripSpecial removes the special columns and sorts the remaining
208 // columns so they always appear in the same order, regardless of
209 // the order they are added.
210 _stripSpecial: function(){
211 return this._columns.filter(function(c) {
212 return this._specialColumns.indexOf(c) === -1;
213 }.bind(this)).sort();
214 },
215
216 // Common columns shared between tasklist and botlist
217 _commonColumns: function() {
218 // return a fresh object so all elements have their own copy
219 return {
220 android_devices: function(bot) {
221 var devs = this._attribute(bot, "android_devices", "0");
222 if (this._verbose) {
223 return devs.join(" | ") + " devices available";
224 }
225 // max() works on strings as long as they can be coerced to Number.
226 return Math.max(...devs) + " devices available";
227 },
228 device_type: function(bot) {
229 var dt = this._attribute(bot, "device_type", "none");
230 dt = dt[0];
231 var alias = swarming.alias.android(dt);
232 if (alias === "unknown") {
233 return dt;
234 }
235 return swarming.alias.apply(dt, alias);
236 },
237 gpu: function(bot){
238 var gpus = this._attribute(bot, "gpu", "none");
239 var verbose = []
240 var named = [];
241 // non-verbose mode has only the top level GPU info "e.g. NVidia"
242 // which is found by looking for gpu ids w/o a colon.
243 gpus.forEach(function(g){
244 var alias = swarming.alias.gpu(g);
245 if (alias === "unknown") {
246 verbose.push(g);
247 if (g.indexOf(":") === -1) {
248 named.push(g);
249 }
250 return;
251 }
252 verbose.push(swarming.alias.apply(g, alias));
253 if (g.indexOf(":") === -1) {
254 named.push(swarming.alias.apply(g, alias));
255 }
256 }.bind(this))
257 if (this._verbose || !named.length) {
258 return verbose.join(" | ");
259 }
260 return named.join(" | ");
261 },
262 pool: function(bot) {
263 var pool = this._attribute(bot, "pool");
264 return pool.join(" | ");
265 },
266 };
267 },
268
269
270 }];
271 })();
272 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698