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

Side by Side Diff: appengine/swarming/elements/polymer05/stats-dimension-filter.html

Issue 2408743002: Move elements/ to ui/ (Closed)
Patch Set: rebase again Created 4 years, 2 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 2015 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 -->
7
8 <!--
9 @group Swarming Elements
10
11 `stats-dimension-filter' is a control that filters dimension list. It takes a
12 list of available dimension objects as its `dimensions` attribute.
13 dimensions = [
14 {"cpu":"x86-64","gpu":"none","os":"Mac","pool":"Chrome"},
15 {"cpu":"x86-64","gpu":"none","os":"Windows","pool":"Chrome"},
16 {"os":"Linux"},
17 {"os":"Mac"},
18 {"os":"Windows"}
19 ]
20 A dimension object may have a number of properties such as `cpu` and `gpu`. For
21 each unique property this control will create a dropdown menu for user to filter
22 by that property.
23
24 When more than one dimensions are available after applying a filter, one is
25 picked to shown while other field menus are shrinked.
26
27 This control exposes a `value` attribute denotes the current dimension selected.
28 A null `value` indicates no dimension is selected.
29
30 Example:
31 <stats-dimension-filter
32 dimensions='[{"cpu":"x86-64", "os":"Mac"}, {"os":"Linux"}]'>
33 </stats-dimension-filter>
34
35 @element stats-dimension-filter
36 -->
37
38 <link rel="import" href="bower_components/polymer/polymer.html">
39 <link rel="import" href="bower_components/core-label/core-label.html">
40 <link rel="import" href="bower_components/core-menu/core-menu.html">
41 <link rel="import" href="bower_components/paper-button/paper-button.html">
42 <link rel="import" href="bower_components/core-dropdown/core-dropdown.html">
43 <link rel="import" href="bower_components/core-dropdown-menu/core-dropdown-menu. html">
44 <link rel="import" href="bower_components/core-item/core-item.html">
45 <link rel="import" href="bower_components/core-selector/core-selector.html">
46
47 <polymer-element name="stats-dimension-filter" attributes="dimensions value" lay out vertical>
48 <template>
49 <style>
50 core-dropdown {
51 background-color: #fff;
52 border: 1px solid #ccc;
53 border-radius: 4px;
54 box-shadow: 0 6px 12px rgba(0,0,0,.175);
55 margin: 2px 0 0;
56 min-width: 160px;
57 padding: 5px 0;
58 top: 100%;
59 }
60
61 core-dropdown-menu {
62 background-color: #fff;
63 border: 1px solid transparent;
64 border-color: #ccc;
65 border-radius: 4px;
66 color: #333;
67 cursor: pointer;
68 padding: 6px 12px;
69 }
70
71 core-dropdown-menu:hover {
72 background-color: #eee;
73 }
74
75 core-item {
76 color: #333;
77 padding: 3px 20px;
78 white-space: nowrap;
79 }
80
81 h4 {
82 margin: 5px 0px;
83 }
84
85 paper-button {
86 text-transform: none;
87 font-size: 14px;
88 }
89
90 .dimension-selector a {
91 color: blue;
92 cursor: pointer;
93 }
94
95 .dimension-selector li {
96 list-style-type: none;
97 }
98 </style>
99 <div layout horizontal center>
100 <h4>Filters:</h4>
101 <template repeat="{{f in filters | filtersArray(filters, count)}}">
102 <paper-button class="custom" on-tap="{{onFilterUnchecked}}" prop="{{f.pr op}}">
103 <core-icon icon="clear"></core-icon>
104 {{f.prop}}: {{f.value}}
105 </paper-button>
106 </template>
107 </div>
108 <div>
109 <template repeat="{{prop in props | propPickerFilter(filters, count)}}">
110 <core-dropdown-menu label="{{prop}}" on-core-select="{{propSelected}}">
111 <core-dropdown class="dropdown">
112 <core-selector class="menu">
113 <template repeat="{{v in values[prop] | propValueFilter(dimensions , filters, prop, count)}}">
114 <core-item name="{{v}}">{{v}}</core-item>
115 </template>
116 </core-selector>
117 </core-dropdown>
118 </core-dropdown-menu>
119 </template>
120 </div>
121 <h4>Resolved Dimension:</h4>
122 <div>
123 <template if="{{value}}">
124 <paper-button class="custom" on-tap="{{onClearDimension}}">
125 <core-icon icon="clear"></core-icon>
126 {{stringify(value)}}
127 </paper-button>
128 </template>
129 <template if="{{!value}}">
130 No dimension selected
131 </template>
132 <h4>Dimensions:</h4>
133 <ul class="dimension-selector">
134 <template repeat="{{d in dimensions | dimensionFilter(filters, count)}}">
135 <li><a on-tap="{{selectDimension}}">{{stringify(d)}}</a></li>
136 </template>
137 </ul>
138 </template>
139 <script>
140 Polymer('stats-dimension-filter', {
141 count: 0,
142 dimensions: [],
143 filters: {},
144 props: [],
145 value: null,
146 values: {},
147
148 stringify: function(d) {
149 return JSON.stringify(d);
150 },
151
152 // Update this.props and this.values
153 dimensionsChanged: function() {
154 var ds = this.dimensions;
155 var attrs = {}, values = {};
156 var props = [];
157 for (var i = 0; i < ds.length; ++i) {
158 var d = ds[i];
159 if (typeof d === "object") {
160 for (var attr in d) {
161 if (!attrs[attr]) {
162 attrs[attr] = {};
163 }
164 attrs[attr][d[attr]] = true;
165 }
166 } else {
167 console.error('dimension should be an object');
168 }
169 }
170 for (var attr in attrs) {
171 props.push(attr);
172 if (!values[attr]) {
173 values[attr] = [];
174 }
175 for (var i in attrs[attr]) {
176 values[attr].push(i);
177 }
178 }
179 this.props = props;
180 this.values = values;
181 },
182
183 dimensionFilter: function(dimensions, filters, count) {
184 var hasFilter = false;
185 var arr = dimensions.filter(function(d) {
186 for (var prop in filters) {
187 hasFilter = true;
188 if (d[prop] !== filters[prop]) {
189 return false;
190 }
191 }
192 return true;
193 });
194 if (hasFilter) {
195 this.value = JSON.stringify(arr[0]);
196 }
197 return arr;
198 },
199
200 propPickerFilter: function(props, filters, count) {
201 return props.filter(function(prop) {
202 for (var p in filters) {
203 if (prop === p) {
204 return false;
205 }
206 }
207 return true;
208 });
209 },
210
211 filtersArray: function(filters, count) {
212 var arr = [];
213 for (var prop in filters) {
214 arr.push({
215 prop: prop,
216 value: filters[prop]
217 });
218 }
219 return arr;
220 },
221
222 // HACK: this is to trigger the dimensionFilter due to a bug in Polymer
223 // https://github.com/Polymer/polymer/issues/1082
224 filtersChanged: function() {
225 this.count++;
226 },
227
228 propSelected: function(event, detail, sender) {
229 var prop = sender.label;
230 var v = sender.selectedItemLabel;
231 if (v) {
232 this.filters[prop] = v;
233 }
234 // TODO: use observer pattern
235 this.filtersChanged();
236 },
237
238 propValueFilter: function(values, dimensions, filters, prop) {
239 var ds = this.dimensionFilter(dimensions, filters);
240 var selection = {};
241 for (var i = 0; i < ds.length; ++i) {
242 if (ds[i].hasOwnProperty(prop)) {
243 selection[ds[i][prop]] = true;
244 }
245 }
246 var ret = [];
247 for (var i in selection) {
248 ret.push(i);
249 }
250 return ret;
251 },
252
253 onFilterUnchecked: function(event, detail, sender) {
254 delete this.filters[sender.getAttribute('prop')];
255 // TODO: use observer pattern
256 this.filtersChanged();
257 },
258
259 selectDimension: function(event, detail, sender) {
260 this.value = sender.innerHTML;
261 },
262
263 onClearDimension: function(event, detail, sender) {
264 this.value = null;
265 }
266 });
267 </script>
268 </polymer-element>
OLDNEW
« no previous file with comments | « appengine/swarming/elements/polymer05/stats-chart-base.html ('k') | appengine/swarming/elements/polymer05/stats-overview.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698