• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2021 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import * as m from 'mithril';
16import {isStackPivot} from '../common/pivot_table_common';
17
18import {globals} from './globals';
19import {hideModel} from './modal';
20import {
21  PivotTableHelper,
22} from './pivot_table_helper';
23
24interface PivotTableEditorAttrs {
25  helper: PivotTableHelper;
26}
27
28export class ColumnPicker implements m.ClassComponent<PivotTableEditorAttrs> {
29  view(vnode: m.Vnode<PivotTableEditorAttrs>) {
30    const {helper} = vnode.attrs;
31
32    // Fills available aggregations options in aggregation select.
33    const aggregationOptions = [];
34    for (const aggregation of helper.availableAggregations) {
35      aggregationOptions.push(
36          m('option', {value: aggregation, key: aggregation}, aggregation));
37    }
38
39    // Fills available columns options divided according to their table in
40    // column select.
41    const columnOptionGroup = [];
42    for (const {tableName, columns} of helper.availableColumns) {
43      const options = [];
44      for (const column of columns) {
45        // We can't aggregate a stack column.
46        const hidden = !helper.isPivot && isStackPivot(tableName, column);
47        options.push(m('option', {value: column, key: column, hidden}, column));
48      }
49      columnOptionGroup.push(m('optgroup', {label: tableName}, options));
50    }
51
52    return m(
53        'div',
54        m(
55            'section',
56            m('h2', 'Select column type: '),
57            // Pivot radio button.
58            m(
59                'span',
60                m(`input[type=radio][name=type][id=pivot]`, {
61                  checked: helper.isPivot,
62                  onchange: () => {
63                    helper.togglePivotSelection();
64                    globals.rafScheduler.scheduleFullRedraw();
65                  }
66                }),
67                m(`label[for=pivot]`, 'Pivot'),
68                ),
69            // Aggregation radio button.
70            m('span', m(`input[type=radio][name=type][id=aggregation]`, {
71                checked: !helper.isPivot,
72                onchange: () => {
73                  helper.togglePivotSelection();
74                  globals.rafScheduler.scheduleFullRedraw();
75                }
76              })),
77            m(`label[for=aggregation]`, 'Aggregation'),
78            ),
79        m(
80            'section',
81            m('h2', 'Select a column: '),
82            // Aggregation select.
83            m('select',
84              {
85                disabled: helper.isPivot,
86                selectedIndex: helper.selectedAggregationIndex,
87                onchange: (e: InputEvent) => {
88                  helper.setSelectedPivotTableAggregationIndex(
89                      (e.target as HTMLSelectElement).selectedIndex);
90                }
91              },
92              aggregationOptions),
93            ' ',
94            // Column select.
95            m('select',
96              {
97                selectedIndex: helper.selectedColumnIndex,
98                onchange: (e: InputEvent) => {
99                  helper.setSelectedPivotTableColumnIndex(
100                      (e.target as HTMLSelectElement).selectedIndex);
101                }
102              },
103              columnOptionGroup),
104            ),
105        m('section.button-group',
106          // Button to toggle selected column.
107          m('button',
108            {
109              onclick: () => {
110                helper.updatePivotTableColumnOnSelectedIndex();
111                globals.rafScheduler.scheduleFullRedraw();
112              }
113            },
114            'Add/Remove'),
115          // Button to clear table and all selected columns.
116          m('button',
117            {
118              onclick: () => {
119                helper.clearPivotTableColumns();
120                globals.rafScheduler.scheduleFullRedraw();
121              }
122            },
123            'Clear')));
124  }
125}
126
127export class ColumnDisplay implements m.ClassComponent<PivotTableEditorAttrs> {
128  view(vnode: m.Vnode<PivotTableEditorAttrs>) {
129    const {helper} = vnode.attrs;
130    const selectedPivotsDisplay = [];
131    const selectedAggregationsDisplay = [];
132
133    for (let i = 0; i < helper.selectedPivots.length; ++i) {
134      const columnAttrs = helper.selectedPivots[i];
135      selectedPivotsDisplay.push(m(
136          'tr',
137          m('td',
138            {
139              draggable: true,
140              ondragstart: (e: DragEvent) => {
141                helper.selectedColumnOnDrag(e, true, i);
142              },
143              ondrop: (e: DragEvent) => {
144                helper.removeHighlightFromDropLocation(e);
145                helper.selectedColumnOnDrop(e, true, i);
146                globals.rafScheduler.scheduleFullRedraw();
147              },
148              onclick: () => {
149                helper.selectPivotTableColumn(columnAttrs);
150                globals.rafScheduler.scheduleFullRedraw();
151              },
152              ondragenter: (e: DragEvent) => {
153                helper.highlightDropLocation(e, true);
154              },
155              ondragleave: (e: DragEvent) => {
156                helper.removeHighlightFromDropLocation(e);
157              }
158            },
159            m('i.material-icons',
160              {
161                onclick: () => {
162                  helper.updatePivotTableColumnOnColumnAttributes(columnAttrs);
163                  globals.rafScheduler.scheduleFullRedraw();
164                },
165              },
166              'remove'),
167            ' ',
168            `${columnAttrs.tableName} ${columnAttrs.columnName}`)));
169    }
170
171    for (let i = 0; i < helper.selectedAggregations.length; ++i) {
172      const columnAttrs = helper.selectedAggregations[i];
173      const sortIcon = helper.selectedAggregations[i].order === 'DESC' ?
174          'arrow_drop_down' :
175          'arrow_drop_up';
176      selectedAggregationsDisplay.push(m(
177          'tr',
178          m('td',
179            {
180              draggable: 'true',
181              ondragstart: (e: DragEvent) => {
182                helper.selectedColumnOnDrag(e, false, i);
183              },
184              ondrop: (e: DragEvent) => {
185                helper.removeHighlightFromDropLocation(e);
186                helper.selectedColumnOnDrop(e, false, i);
187                globals.rafScheduler.scheduleFullRedraw();
188              },
189              onclick: () => {
190                helper.selectPivotTableColumn(columnAttrs);
191                globals.rafScheduler.scheduleFullRedraw();
192              },
193              ondragenter: (e: DragEvent) => {
194                helper.highlightDropLocation(e, false);
195              },
196              ondragleave: (e: DragEvent) => {
197                helper.removeHighlightFromDropLocation(e);
198              }
199            },
200            m('i.material-icons',
201              {
202                onclick: () => {
203                  helper.updatePivotTableColumnOnColumnAttributes(columnAttrs);
204                  globals.rafScheduler.scheduleFullRedraw();
205                },
206              },
207              'remove'),
208            ' ',
209            `${columnAttrs.tableName} ${columnAttrs.columnName} (${
210                columnAttrs.aggregation})`,
211            m('i.material-icons',
212              {
213                onclick: () => {
214                  helper.togglePivotTableAggregationSorting(i);
215                  globals.rafScheduler.scheduleFullRedraw();
216                }
217              },
218              sortIcon))));
219    }
220
221    return m(
222        'div',
223        m('section.table-group',
224          // Table that displays selected pivots.
225          m('table',
226            m('thead', m('tr', m('th', 'Selected Pivots'))),
227            m('div.scroll', m('tbody', selectedPivotsDisplay))),
228          // Table that displays selected aggregations.
229          m('table',
230            m('thead', m('tr', m('th', 'Selected Aggregations'))),
231            m('div.scroll', m('tbody', selectedAggregationsDisplay)))),
232        m('section.button-group',
233          // Button to toggle selected column.
234          m('button',
235            {
236              onclick: () => {
237                helper.queryPivotTableChanges();
238                hideModel();
239              }
240            },
241            'Query'),
242          // Button to clear table and all selected columns.
243          m('button',
244            {
245              onclick: () => {
246                hideModel();
247              }
248            },
249            'Cancel')));
250  }
251}
252