@bennerinformatics/ember-fw-table 2.0.19 → 2.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/addon/classes/Row.js +74 -74
  2. package/addon/classes/Table.js +147 -147
  3. package/addon/components/fw-cell-action.js +15 -15
  4. package/addon/components/fw-cell-boolean.js +12 -12
  5. package/addon/components/fw-cell-nullable.js +12 -12
  6. package/addon/components/fw-cell-permission-icon.js +12 -12
  7. package/addon/components/fw-column-title.js +13 -13
  8. package/addon/components/fw-delete-modal.js +61 -61
  9. package/addon/components/fw-pagination-wrapper.js +681 -681
  10. package/addon/components/fw-row-toggle-index.js +14 -14
  11. package/addon/components/fw-table-expanded-row.js +24 -24
  12. package/addon/components/fw-table-resort.js +3 -3
  13. package/addon/components/fw-table-sortable.js +398 -389
  14. package/addon/documentation.js +98 -98
  15. package/addon/templates/components/fw-delete-modal.hbs +2 -7
  16. package/addon/templates/components/fw-pagination-wrapper.hbs +45 -74
  17. package/addon/templates/components/fw-table-expanded-row.hbs +23 -23
  18. package/addon/templates/components/fw-table-expanded-rows.hbs +1 -1
  19. package/addon/templates/components/fw-table-resort.hbs +4 -4
  20. package/addon/templates/components/fw-table-sortable.hbs +9 -31
  21. package/addon/utils/base-cells.js +40 -40
  22. package/addon/utils/export.js +76 -76
  23. package/addon/utils/formats.js +46 -46
  24. package/addon/utils/table.js +35 -35
  25. package/app/breakpoints.js +1 -1
  26. package/app/components/fw-cell-permission-icon.js +1 -1
  27. package/app/initializers/responsive.js +1 -1
  28. package/bitbucket-helpers-override.js +240 -240
  29. package/codemods.log +16 -0
  30. package/index.js +9 -10
  31. package/package.json +67 -67
  32. package/yuidoc.json +21 -21
@@ -1,389 +1,398 @@
1
- import {isArray} from '@ember/array';
2
- import Component from '@ember/component';
3
- import {computed, observer} from '@ember/object';
4
- import {sort} from '@ember/object/computed';
5
- import {isEmpty, isNone} from '@ember/utils';
6
- import newTable from '../classes/Table';
7
- import exportTable from '../utils/export';
8
- import layout from '../templates/components/fw-table-sortable';
9
- import RSVP from 'rsvp';
10
-
11
- /**
12
- * This table contains logic to show a table as a panel in an app. This table features sorting rows can be expanded
13
- * to show hidden data
14
- * ```handlebars
15
- * {{fw-table-sortable data columns title='Table'}}
16
- * ```
17
- *
18
- * If used in a block format instead, it is possible to fully define the title area, replacing the title parameter. The export action is passed as a yield parameter to redefine the export button
19
- * ```handlebars
20
- * {{#fw-table-sortable data columns as |export|}}
21
- * <strong class='panel-title'>Table</strong>
22
- * {{/fw-table-sortable}}
23
- * ```
24
- *
25
- * In addition to the usual properties in columns, fw-table-sortable supports adding an additional `sortKey` property
26
- * If defined, clicking that column will sort by that property instead of valuePath
27
- *
28
- * It also supports a showExpanded property, which is set to a value which will cause this row to show in the expanded view if hidden.
29
- * Alternatively, setting this to `true` or `false` will force the state regardless of a property.
30
- * By default will show if the property from `valuePath` is not null
31
- *
32
- * @class FW-Table-Sortable
33
- * @extends EmberLightTable
34
- * @public
35
- */
36
- const TableSortable = Component.extend({
37
- layout,
38
- classNames: ['panel', 'panel-default'],
39
-
40
- /**
41
- * Table rows
42
- *
43
- * @public
44
- * @property data
45
- * @type {Array}
46
- */
47
-
48
- /**
49
- * Table columns. See ember-light-table docs for more information
50
- *
51
- * @public
52
- * @property columns
53
- * @type {Array}
54
- */
55
- columns: null,
56
-
57
- /**
58
- * Additional class names for the table
59
- *
60
- * @public
61
- * @property tableClassNames
62
- * @type {Hash}
63
- */
64
- tableClassNames: '',
65
-
66
- /**
67
- * Hash of maximum columns based on responsive size
68
- *
69
- * @public
70
- * @property breakpoints
71
- * @type {Hash}
72
- */
73
-
74
- /**
75
- * Hash of actions to pass into the table for use in components
76
- *
77
- * @public
78
- * @property tableActions
79
- * @type {Hash}
80
- */
81
-
82
- /**
83
- * Title to display in the panel above the table
84
- *
85
- * @public
86
- * @property title
87
- * @type {String}
88
- */
89
-
90
- /**
91
- * Text to display when the table is empty
92
- *
93
- * @public
94
- * @property empty
95
- * @type {String}
96
- */
97
-
98
- /**
99
- * Action called when sorting the table
100
- *
101
- * @public
102
- * @property onSort
103
- * @type {Action}
104
- */
105
- onSort: () => RSVP.resolve(),
106
-
107
- /**
108
- * Set to false to make the table not show the header if empty
109
- *
110
- * @public
111
- * @property headerEmpty
112
- * @type {Boolean}
113
- */
114
- headerEmpty: true,
115
- /**
116
- * Sets the table to a fixed height, and adds a scroll bar to see the hidden rows
117
- *
118
- * @public
119
- * @property fixedHeight
120
- * @type {String}
121
- */
122
- fixedHeight: null,
123
- /**
124
- * Makes the table responsive to the screen width. The table is slightly more efficient if false when responsive is not used
125
- *
126
- * @public
127
- * @property responsive
128
- * @type {Boolean}
129
- */
130
- responsive: false,
131
-
132
- /**
133
- * Allows exporting the current contents of the table using an export button. Note that this sets a default title of "Table", so setting a separate one is recommended
134
- *
135
- * When enabled, columns have some additional values defined:
136
- * * `canExport`: if true (default), the column will be included in the export. Set to false to skip exporting the column.
137
- * * `exportOnly`: if true, the column will not show in the table, but will still be exported.
138
- *
139
- * Additionally, the value `export` is set to true in `format`'s context
140
- * @public
141
- * @property canExport
142
- * @type {Boolean}
143
- */
144
- canExport: false,
145
-
146
- /**
147
- * If true, uses the table block data for the header
148
- *
149
- * @public
150
- * @property showHeader
151
- * @type {Boolean}
152
- */
153
- showHeader: true,
154
-
155
- /**
156
- * If true, uses the table block data for the footer
157
- *
158
- * @public
159
- * @property showFooter
160
- * @type {Boolean}
161
- */
162
- showFooter: false,
163
-
164
- /**
165
- * Default sort order for the table. Can be a string for a single property, or an array to fallback
166
- *
167
- * @public
168
- * @property defaultSort
169
- * @type {String|Array}
170
- */
171
- defaultSort: null,
172
-
173
- /**
174
- * Private copy of defaultSort, made an array if its not
175
- *
176
- * @private
177
- * @property _defaultSort
178
- * @type {Array}
179
- */
180
- _defaultSort: computed('defaultSort', function() {
181
- let defaultSort = this.get('defaultSort');
182
- if (isNone(defaultSort)) {
183
- return [];
184
- }
185
- if (!isArray(defaultSort)) {
186
- return [defaultSort];
187
- }
188
- return defaultSort;
189
- }),
190
-
191
- /**
192
- * Sort column set by clicking a column to sort
193
- *
194
- * @private
195
- * @property sortColumn
196
- * @type {String}
197
- */
198
- sortColumn: null,
199
-
200
- /**
201
- * Internal sort order. Calculated from sortColumn and _defaultSort
202
- *
203
- * @private
204
- * @property sortOrder
205
- * @type {Array}
206
- */
207
- sortOrder: computed('_defaultSort.[]', 'sortColumn', function() {
208
- let sortColumn = this.get('sortColumn');
209
- if (sortColumn) {
210
- return [sortColumn].pushObjects(this.get('_defaultSort'));
211
- }
212
- return this.get('_defaultSort');
213
- }),
214
-
215
- /**
216
- * Passed in table data after sorting.
217
- *
218
- * @private
219
- * @property sortedData
220
- * @type {Array}
221
- */
222
- sortedData: sort('data', 'sortOrder'),
223
-
224
- /**
225
- * Internal table instance, in general changes to the table should be done to columns or data so they update propery
226
- *
227
- * @protected
228
- * @property table
229
- * @type {Table}
230
- */
231
- table: null,
232
-
233
- /**
234
- * Computed table title based on whether a boolean true is passed or a title
235
- *
236
- * @private
237
- * @property exportTitle
238
- * @type {String}
239
- */
240
- exportTitle: computed('canExport', function() {
241
- let canExport = this.get('canExport');
242
- if (canExport === true) {
243
- return 'Export';
244
- }
245
- return canExport || '';
246
- }),
247
-
248
- /**
249
- * Called to delete the full page of entries
250
- */
251
- deleteTable: undefined,
252
-
253
- /**
254
- * Determines title for delete function
255
- */
256
- deleteOverrideTitle: null,
257
-
258
- deleteTitle: computed('deleteTable', 'deleteOverrideTitle', function() {
259
- if (!this.get('deleteTable')) {
260
- return null;
261
- } else {
262
- return this.get('deleteOverrideTitle') ? this.get('deleteOverrideTitle') : 'Delete All';
263
- }
264
- }),
265
-
266
- /**
267
- * Determines if the current user has permission to delete the table (usually has-role helper will be used to determine this)
268
- * example: deleteTablePermission=(has-role 'admin')
269
- * @type {Boolean}
270
- * @default true
271
- */
272
- deleteTablePermission: true,
273
-
274
- /**
275
- * Callback to update the table rows whenever the data is changed, generally from sorting
276
- *
277
- * @private
278
- * @method updateTableRows
279
- */
280
- // eslint-disable-next-line ember/no-observers
281
- updateTableRows: observer('sortedData', function() {
282
- if (this.get('table')) {
283
- this.get('table').setRows(this.get('sortedData'));
284
- }
285
- }),
286
-
287
- /**
288
- * Callback to update the table columns whenever they change. Unlikely, but still a case worth covering
289
- *
290
- * @private
291
- * @method updateTableColumns
292
- */
293
- // eslint-disable-next-line ember/no-observers
294
- updateTableColumns: observer('columns', function() {
295
- if (this.get('table')) {
296
- this.get('table').setColumns(this.get('columns'));
297
- }
298
- }),
299
-
300
- /**
301
- * Initializes the component and loads the modal path.
302
- *
303
- * @private
304
- * @method didReceiveAttrs
305
- */
306
- didReceiveAttrs() {
307
- this._super(...arguments);
308
- // first, determine our sorting
309
- let defaultSort = this.get('_defaultSort');
310
- let columns = this.get('columns') || [];
311
- if (!isEmpty(defaultSort)) {
312
- // make a map of key to ascending
313
- let [mainKey] = defaultSort;
314
- let ascending = true;
315
- if (mainKey.endsWith(':desc')) {
316
- ascending = false;
317
- mainKey = mainKey.substring(0, mainKey.length - 5);
318
- }
319
- columns = columns.map((column) => {
320
- let key = column.sortKey || column.valuePath;
321
- return key === mainKey ? Object.assign({}, column, {sorted: true, ascending}) : column;
322
- });
323
- }
324
- this.set('table', newTable(columns, this.get('sortedData')));
325
-
326
- if (this.get('noPanel')) {
327
- this.set('classNames', null);
328
- }
329
- },
330
-
331
- actions: {
332
- /**
333
- * Called when clicking aa column header to sort the current row
334
- * @param {Column} column Column clicked
335
- */
336
- sort(column) {
337
- if (!column.sortable) {
338
- return;
339
- }
340
-
341
- // modify the sort state, this is ported from the default code to properly set ascending to true on sort
342
- if (column.sorted) {
343
- column.toggleProperty('ascending');
344
- } else {
345
- this.get('table.sortedColumns').setEach('sorted', false);
346
- column.set('sorted', true);
347
- column.set('ascending', true);
348
- }
349
-
350
- // determine how we are sorting
351
- let sortKey = column.sortKey || column.valuePath;
352
-
353
- // if the column is now decending, sort decending
354
- if (!column.ascending) {
355
- sortKey = `${sortKey}:desc`;
356
- }
357
-
358
- // call the sort logic
359
- this.onSort(column, sortKey).then(() => {
360
- this.set('sortColumn', sortKey);
361
- });
362
- },
363
-
364
- /**
365
- * Called when clicking a row to expand it and show more information
366
- * @param {Row} row Row clicked
367
- */
368
- expand(row) {
369
- let expand = row.get('canExpand') ? !row.get('expanded') : false;
370
- if (expand) {
371
- this.get('table.expandedRows').setEach('expanded', false);
372
- }
373
- row.set('expanded', expand);
374
- },
375
-
376
- /**
377
- * Called by the export button to export the current table data to CSV
378
- */
379
- export() {
380
- exportTable(this.get('table'), this.get('title'));
381
- }
382
- }
383
- });
384
-
385
- TableSortable.reopenClass({
386
- positionalParams: ['data', 'columns']
387
- });
388
-
389
- export default TableSortable;
1
+ import {isArray} from '@ember/array';
2
+ import Component from '@ember/component';
3
+ import {computed, observer} from '@ember/object';
4
+ import {sort} from '@ember/object/computed';
5
+ import {isEmpty, isNone} from '@ember/utils';
6
+ import newTable from '../classes/Table';
7
+ import exportTable from '../utils/export';
8
+ import layout from '../templates/components/fw-table-sortable';
9
+ import RSVP from 'rsvp';
10
+
11
+ /**
12
+ * This table contains logic to show a table as a panel in an app. This table features sorting rows can be expanded
13
+ * to show hidden data
14
+ * ```handlebars
15
+ * <FwTableSortable @data={{data}} @columns={{columns}} @title='Table' />
16
+ * ```
17
+ *
18
+ * If used in a block format instead, it is possible to fully define the title area, replacing the title parameter. The export action is passed as a yield parameter to redefine the export button
19
+ * ```handlebars
20
+ * <FwTableSortable @data={{data}} @columns={{columns}} as |export|>
21
+ * <strong class='panel-title'>Table</strong>
22
+ * </FwTableSortable>
23
+ * ```
24
+ *
25
+ * In addition to the usual properties in columns, fw-table-sortable supports adding an additional `sortKey` property
26
+ * If defined, clicking that column will sort by that property instead of valuePath
27
+ *
28
+ * It also supports a showExpanded property, which is set to a value which will cause this row to show in the expanded view if hidden.
29
+ * Alternatively, setting this to `true` or `false` will force the state regardless of a property.
30
+ * By default will show if the property from `valuePath` is not null
31
+ *
32
+ * @class FW-Table-Sortable
33
+ * @extends EmberLightTable
34
+ * @public
35
+ */
36
+ const TableSortable = Component.extend({
37
+ layout,
38
+ classNames: ['panel', 'panel-default'],
39
+
40
+ /**
41
+ * Table rows
42
+ *
43
+ * @public
44
+ * @property data
45
+ * @type {Array}
46
+ */
47
+
48
+ /**
49
+ * Table columns. See ember-light-table docs for more information
50
+ *
51
+ * @public
52
+ * @property columns
53
+ * @type {Array}
54
+ */
55
+ columns: null,
56
+
57
+ /**
58
+ * Additional class names for the table
59
+ *
60
+ * @public
61
+ * @property tableClassNames
62
+ * @type {Hash}
63
+ */
64
+ tableClassNames: '',
65
+
66
+ /**
67
+ * Hash of maximum columns based on responsive size
68
+ *
69
+ * @public
70
+ * @property breakpoints
71
+ * @type {Hash}
72
+ */
73
+
74
+ /**
75
+ * Hash of actions to pass into the table for use in components
76
+ *
77
+ * @public
78
+ * @property tableActions
79
+ * @type {Hash}
80
+ */
81
+
82
+ /**
83
+ * Title to display in the panel above the table
84
+ *
85
+ * @public
86
+ * @property title
87
+ * @type {String}
88
+ */
89
+
90
+ /**
91
+ * Text to display when the table is empty
92
+ *
93
+ * @public
94
+ * @property empty
95
+ * @type {String}
96
+ */
97
+
98
+ /**
99
+ * Action called when sorting the table
100
+ *
101
+ * @public
102
+ * @property onSort
103
+ * @type {Action}
104
+ */
105
+ onSort: () => RSVP.resolve(),
106
+
107
+ /**
108
+ * Set to false to make the table not show the header if empty
109
+ *
110
+ * @public
111
+ * @property headerEmpty
112
+ * @type {Boolean}
113
+ */
114
+ headerEmpty: true,
115
+ /**
116
+ * Sets the table to a fixed height, and adds a scroll bar to see the hidden rows
117
+ *
118
+ * @public
119
+ * @property fixedHeight
120
+ * @type {String}
121
+ */
122
+ fixedHeight: null,
123
+ /**
124
+ * Makes the table responsive to the screen width. The table is slightly more efficient if false when responsive is not used
125
+ *
126
+ * @public
127
+ * @property responsive
128
+ * @type {Boolean}
129
+ */
130
+ responsive: false,
131
+
132
+ /**
133
+ * Makes the headers able to be dragged to resize. You will still need to put `resizable: true` in each column you want to be able to resize.
134
+ * @public
135
+ * @property resizeOnDrag
136
+ * @type {Boolean}
137
+ * @default false
138
+ */
139
+
140
+ resizeOnDrag: false,
141
+ /**
142
+ * Allows exporting the current contents of the table using an export button. Note that this sets a default title of "Table", so setting a separate one is recommended
143
+ *
144
+ * When enabled, columns have some additional values defined:
145
+ * * `canExport`: if true (default), the column will be included in the export. Set to false to skip exporting the column.
146
+ * * `exportOnly`: if true, the column will not show in the table, but will still be exported.
147
+ *
148
+ * Additionally, the value `export` is set to true in `format`'s context
149
+ * @public
150
+ * @property canExport
151
+ * @type {Boolean}
152
+ */
153
+ canExport: false,
154
+
155
+ /**
156
+ * If true, uses the table block data for the header
157
+ *
158
+ * @public
159
+ * @property showHeader
160
+ * @type {Boolean}
161
+ */
162
+ showHeader: true,
163
+
164
+ /**
165
+ * If true, uses the table block data for the footer
166
+ *
167
+ * @public
168
+ * @property showFooter
169
+ * @type {Boolean}
170
+ */
171
+ showFooter: false,
172
+
173
+ /**
174
+ * Default sort order for the table. Can be a string for a single property, or an array to fallback
175
+ *
176
+ * @public
177
+ * @property defaultSort
178
+ * @type {String|Array}
179
+ */
180
+ defaultSort: null,
181
+
182
+ /**
183
+ * Private copy of defaultSort, made an array if its not
184
+ *
185
+ * @private
186
+ * @property _defaultSort
187
+ * @type {Array}
188
+ */
189
+ _defaultSort: computed('defaultSort', function() {
190
+ let defaultSort = this.get('defaultSort');
191
+ if (isNone(defaultSort)) {
192
+ return [];
193
+ }
194
+ if (!isArray(defaultSort)) {
195
+ return [defaultSort];
196
+ }
197
+ return defaultSort;
198
+ }),
199
+
200
+ /**
201
+ * Sort column set by clicking a column to sort
202
+ *
203
+ * @private
204
+ * @property sortColumn
205
+ * @type {String}
206
+ */
207
+ sortColumn: null,
208
+
209
+ /**
210
+ * Internal sort order. Calculated from sortColumn and _defaultSort
211
+ *
212
+ * @private
213
+ * @property sortOrder
214
+ * @type {Array}
215
+ */
216
+ sortOrder: computed('_defaultSort.[]', 'sortColumn', function() {
217
+ let sortColumn = this.get('sortColumn');
218
+ if (sortColumn) {
219
+ return [sortColumn].pushObjects(this.get('_defaultSort'));
220
+ }
221
+ return this.get('_defaultSort');
222
+ }),
223
+
224
+ /**
225
+ * Passed in table data after sorting.
226
+ *
227
+ * @private
228
+ * @property sortedData
229
+ * @type {Array}
230
+ */
231
+ sortedData: sort('data', 'sortOrder'),
232
+
233
+ /**
234
+ * Internal table instance, in general changes to the table should be done to columns or data so they update propery
235
+ *
236
+ * @protected
237
+ * @property table
238
+ * @type {Table}
239
+ */
240
+ table: null,
241
+
242
+ /**
243
+ * Computed table title based on whether a boolean true is passed or a title
244
+ *
245
+ * @private
246
+ * @property exportTitle
247
+ * @type {String}
248
+ */
249
+ exportTitle: computed('canExport', function() {
250
+ let canExport = this.get('canExport');
251
+ if (canExport === true) {
252
+ return 'Export';
253
+ }
254
+ return canExport || '';
255
+ }),
256
+
257
+ /**
258
+ * Called to delete the full page of entries
259
+ */
260
+ deleteTable: undefined,
261
+
262
+ /**
263
+ * Determines title for delete function
264
+ */
265
+ deleteOverrideTitle: null,
266
+
267
+ deleteTitle: computed('deleteTable', 'deleteOverrideTitle', function() {
268
+ if (!this.get('deleteTable')) {
269
+ return null;
270
+ } else {
271
+ return this.get('deleteOverrideTitle') ? this.get('deleteOverrideTitle') : 'Delete All';
272
+ }
273
+ }),
274
+
275
+ /**
276
+ * Determines if the current user has permission to delete the table (usually has-role helper will be used to determine this)
277
+ * example: deleteTablePermission=(has-role 'admin')
278
+ * @type {Boolean}
279
+ * @default true
280
+ */
281
+ deleteTablePermission: true,
282
+
283
+ /**
284
+ * Callback to update the table rows whenever the data is changed, generally from sorting
285
+ *
286
+ * @private
287
+ * @method updateTableRows
288
+ */
289
+ // eslint-disable-next-line ember/no-observers
290
+ updateTableRows: observer('sortedData', function() {
291
+ if (this.get('table')) {
292
+ this.get('table').setRows(this.get('sortedData'));
293
+ }
294
+ }),
295
+
296
+ /**
297
+ * Callback to update the table columns whenever they change. Unlikely, but still a case worth covering
298
+ *
299
+ * @private
300
+ * @method updateTableColumns
301
+ */
302
+ // eslint-disable-next-line ember/no-observers
303
+ updateTableColumns: observer('columns', function() {
304
+ if (this.get('table')) {
305
+ this.get('table').setColumns(this.get('columns'));
306
+ }
307
+ }),
308
+
309
+ /**
310
+ * Initializes the component and loads the modal path.
311
+ *
312
+ * @private
313
+ * @method didReceiveAttrs
314
+ */
315
+ didReceiveAttrs() {
316
+ this._super(...arguments);
317
+ // first, determine our sorting
318
+ let defaultSort = this.get('_defaultSort');
319
+ let columns = this.get('columns') || [];
320
+ if (!isEmpty(defaultSort)) {
321
+ // make a map of key to ascending
322
+ let [mainKey] = defaultSort;
323
+ let ascending = true;
324
+ if (mainKey.endsWith(':desc')) {
325
+ ascending = false;
326
+ mainKey = mainKey.substring(0, mainKey.length - 5);
327
+ }
328
+ columns = columns.map((column) => {
329
+ let key = column.sortKey || column.valuePath;
330
+ return key === mainKey ? Object.assign({}, column, {sorted: true, ascending}) : column;
331
+ });
332
+ }
333
+ this.set('table', newTable(columns, this.get('sortedData')));
334
+
335
+ if (this.get('noPanel')) {
336
+ this.set('classNames', null);
337
+ }
338
+ },
339
+
340
+ actions: {
341
+ /**
342
+ * Called when clicking aa column header to sort the current row
343
+ * @param {Column} column Column clicked
344
+ */
345
+ sort(column) {
346
+ if (!column.sortable) {
347
+ return;
348
+ }
349
+
350
+ // modify the sort state, this is ported from the default code to properly set ascending to true on sort
351
+ if (column.sorted) {
352
+ column.toggleProperty('ascending');
353
+ } else {
354
+ this.get('table.sortedColumns').setEach('sorted', false);
355
+ column.set('sorted', true);
356
+ column.set('ascending', true);
357
+ }
358
+
359
+ // determine how we are sorting
360
+ let sortKey = column.sortKey || column.valuePath;
361
+
362
+ // if the column is now decending, sort decending
363
+ if (!column.ascending) {
364
+ sortKey = `${sortKey}:desc`;
365
+ }
366
+
367
+ // call the sort logic
368
+ this.onSort(column, sortKey).then(() => {
369
+ this.set('sortColumn', sortKey);
370
+ });
371
+ },
372
+
373
+ /**
374
+ * Called when clicking a row to expand it and show more information
375
+ * @param {Row} row Row clicked
376
+ */
377
+ expand(row) {
378
+ let expand = row.get('canExpand') ? !row.get('expanded') : false;
379
+ if (expand) {
380
+ this.get('table.expandedRows').setEach('expanded', false);
381
+ }
382
+ row.set('expanded', expand);
383
+ },
384
+
385
+ /**
386
+ * Called by the export button to export the current table data to CSV
387
+ */
388
+ export() {
389
+ exportTable(this.get('table'), this.get('title'));
390
+ }
391
+ }
392
+ });
393
+
394
+ TableSortable.reopenClass({
395
+ positionalParams: ['data', 'columns']
396
+ });
397
+
398
+ export default TableSortable;