@neovici/cosmoz-omnitable 7.1.0 → 8.0.0-beta.1
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.
- package/README.md +23 -0
- package/cosmoz-omnitable-column-amount.js +89 -320
- package/cosmoz-omnitable-column-autocomplete.js +36 -47
- package/cosmoz-omnitable-column-boolean.js +107 -209
- package/cosmoz-omnitable-column-date.js +89 -102
- package/cosmoz-omnitable-column-datetime.js +86 -119
- package/cosmoz-omnitable-column-list-data.js +4 -1
- package/cosmoz-omnitable-column-list-horizontal.js +20 -38
- package/cosmoz-omnitable-column-list-mixin.js +133 -140
- package/cosmoz-omnitable-column-list.js +19 -28
- package/cosmoz-omnitable-column-mixin.js +69 -447
- package/cosmoz-omnitable-column-number.js +91 -183
- package/cosmoz-omnitable-column-time.js +77 -162
- package/cosmoz-omnitable-column.js +49 -93
- package/cosmoz-omnitable-group-row.js +8 -87
- package/cosmoz-omnitable-header-row.js +9 -6
- package/cosmoz-omnitable-item-expand.js +0 -3
- package/cosmoz-omnitable-item-row.js +18 -127
- package/cosmoz-omnitable-styles.js +22 -5
- package/cosmoz-omnitable.js +73 -811
- package/lib/cosmoz-omnitable-amount-range-input.js +295 -0
- package/{cosmoz-omnitable-column-date-mixin.js → lib/cosmoz-omnitable-date-input-mixin.js} +4 -26
- package/lib/cosmoz-omnitable-date-range-input.js +81 -0
- package/lib/cosmoz-omnitable-datetime-range-input.js +75 -0
- package/lib/cosmoz-omnitable-number-range-input.js +159 -0
- package/{cosmoz-omnitable-column-range-mixin.js → lib/cosmoz-omnitable-range-input-mixin.js} +45 -129
- package/lib/cosmoz-omnitable-settings.js +22 -4
- package/lib/cosmoz-omnitable-time-range-input.js +130 -0
- package/lib/generic-sorter.js +35 -0
- package/lib/invoke.js +1 -0
- package/lib/memoize.js +54 -0
- package/lib/polymer-haunted-render-mixin.js +19 -0
- package/lib/save-as-csv-action.js +32 -0
- package/lib/save-as-xlsx-action.js +25 -0
- package/lib/use-canvas-width.js +1 -1
- package/lib/use-dom-columns.js +133 -0
- package/lib/use-hash-state.js +59 -0
- package/lib/use-layout.js +1 -1
- package/lib/use-omnitable.js +31 -4
- package/lib/use-processed-items.js +132 -0
- package/lib/use-saved-settings.js +12 -3
- package/lib/use-sort-and-group-options.js +30 -0
- package/lib/utils-amount.js +147 -0
- package/lib/utils-data.js +36 -0
- package/lib/utils-date.js +204 -0
- package/lib/utils-datetime.js +71 -0
- package/lib/utils-number.js +112 -0
- package/lib/utils-time.js +115 -0
- package/package.json +1 -1
- package/cosmoz-omnitable-repeater-mixin.js +0 -294
- package/lib/use-force-render.js +0 -8
- package/lib/use-render-on-column-updates.js +0 -18
|
@@ -3,161 +3,128 @@ import '@polymer/paper-dropdown-menu/paper-dropdown-menu';
|
|
|
3
3
|
import '@neovici/cosmoz-datetime-input';
|
|
4
4
|
import './ui-helpers/cosmoz-clear-button';
|
|
5
5
|
|
|
6
|
-
import { dateColumnMixin } from './cosmoz-omnitable-column-date-mixin';
|
|
7
6
|
import { columnMixin } from './cosmoz-omnitable-column-mixin';
|
|
8
|
-
import {
|
|
9
|
-
translatable, _
|
|
10
|
-
} from '@neovici/cosmoz-i18next';
|
|
11
7
|
import { PolymerElement } from '@polymer/polymer/polymer-element';
|
|
12
8
|
import { html } from 'lit-html';
|
|
13
|
-
import {
|
|
14
|
-
|
|
9
|
+
import { fromHashString, getString, toHashString, toXlsxValue } from './lib/utils-datetime';
|
|
10
|
+
import { applySingleFilter, fromInputString, getComparableValue, toDate } from './lib/utils-date';
|
|
11
|
+
import { valuesFrom } from './lib/utils-data';
|
|
12
|
+
import './lib/cosmoz-omnitable-datetime-range-input';
|
|
15
13
|
|
|
16
14
|
/**
|
|
17
15
|
* @polymer
|
|
18
16
|
* @customElement
|
|
19
|
-
* @appliesMixin dateColumnMixin
|
|
20
17
|
* @appliesMixin columnMixin
|
|
21
18
|
*/
|
|
22
|
-
class OmnitableColumnDatetime extends
|
|
23
|
-
dateColumnMixin(
|
|
24
|
-
columnMixin(
|
|
25
|
-
translatable(PolymerElement)
|
|
26
|
-
)
|
|
27
|
-
) {
|
|
19
|
+
class OmnitableColumnDatetime extends columnMixin(PolymerElement) {
|
|
28
20
|
static get is() {
|
|
29
21
|
return 'cosmoz-omnitable-column-datetime';
|
|
30
22
|
}
|
|
31
23
|
|
|
32
24
|
static get properties() {
|
|
33
25
|
return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
editWidth: {
|
|
45
|
-
type: String,
|
|
46
|
-
value: '320px'
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
minWidth: {
|
|
50
|
-
type: String,
|
|
51
|
-
value: '128px'
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
editMinWidth: {
|
|
55
|
-
type: String,
|
|
56
|
-
value: '128px'
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
headerCellClass: {
|
|
60
|
-
type: String,
|
|
61
|
-
value: 'datetime-header-cell'
|
|
62
|
-
}
|
|
26
|
+
min: { type: Number, value: null, notify: true },
|
|
27
|
+
max: { type: Number, value: null, notify: true },
|
|
28
|
+
locale: { type: String, value: null, notify: true },
|
|
29
|
+
headerCellClass: { type: String, value: 'datetime-header-cell' },
|
|
30
|
+
width: { type: String, value: '210px' },
|
|
31
|
+
minWidth: { type: String, value: '128px' },
|
|
32
|
+
flex: { type: String, value: '0' },
|
|
33
|
+
filterStep: { type: Number, value: 1 }
|
|
63
34
|
};
|
|
64
35
|
}
|
|
65
36
|
|
|
66
|
-
|
|
67
|
-
|
|
37
|
+
getFilterFn(column, filter) {
|
|
38
|
+
const
|
|
39
|
+
min = getComparableValue(filter, 'min', column),
|
|
40
|
+
max = getComparableValue(filter, 'max', column);
|
|
41
|
+
|
|
42
|
+
if (min == null && max == null) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
return applySingleFilter(column, filter);
|
|
68
46
|
}
|
|
69
47
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return column._dateValueChanged(event);
|
|
74
|
-
};
|
|
48
|
+
getString(column, item) {
|
|
49
|
+
return getString(column, item);
|
|
50
|
+
}
|
|
75
51
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
@value-changed=${ onChange }
|
|
79
|
-
.value=${ column.getInputString(item, column.valuePath) }
|
|
80
|
-
></cosmoz-datetime-input>`;
|
|
52
|
+
toXlsxValue(column, item) {
|
|
53
|
+
return toXlsxValue(column, item);
|
|
81
54
|
}
|
|
82
55
|
|
|
83
|
-
|
|
84
|
-
return
|
|
85
|
-
<cosmoz-clear-button @click=${ event => column.resetFilter(event) } ?visible=${ column.hasFilter() }></cosmoz-clear-button>
|
|
86
|
-
<paper-dropdown-menu
|
|
87
|
-
label=${ column.title }
|
|
88
|
-
placeholder=${ ifDefined(column._filterText) }
|
|
89
|
-
class="external-values-${ column.externalValues }"
|
|
90
|
-
title=${ column._tooltip }
|
|
91
|
-
horizontal-align=${ column.preferredDropdownHorizontalAlign }
|
|
92
|
-
?opened=${ column.headerFocused }
|
|
93
|
-
@opened-changed=${ event => column.headerFocused = event.detail.value }>
|
|
94
|
-
<div class="dropdown-content" slot="dropdown-content" style="padding: 15px; min-width: 100px;">
|
|
95
|
-
<h3 style="margin: 0;">${ column.title }</h3>
|
|
96
|
-
<cosmoz-datetime-input
|
|
97
|
-
date-label=${ _('From date') }
|
|
98
|
-
time-label=${ _('From time') }
|
|
99
|
-
min=${ column._toInputString(column._limit.fromMin) }
|
|
100
|
-
max=${ column._toInputString(column._limit.fromMax) }
|
|
101
|
-
step=${ column.filterStep }
|
|
102
|
-
.value=${ column._filterInput.min }
|
|
103
|
-
@value-changed=${ event => column.set('_filterInput.min', event.detail.value) }
|
|
104
|
-
></cosmoz-datetime-input>
|
|
105
|
-
<cosmoz-datetime-input
|
|
106
|
-
date-label=${ _('To date') }
|
|
107
|
-
time-label=${ _('To time') }
|
|
108
|
-
min=${ column._toInputString(column._limit.toMin) }
|
|
109
|
-
max=${ column._toInputString(column._limit.toMax) }
|
|
110
|
-
step=${ column.filterStep }
|
|
111
|
-
.value=${ column._filterInput.max }
|
|
112
|
-
@value-changed=${ event => column.set('_filterInput.max', event.detail.value) }
|
|
113
|
-
></cosmoz-datetime-input>
|
|
114
|
-
</div>
|
|
115
|
-
</paper-dropdown-menu>
|
|
116
|
-
`;
|
|
56
|
+
cellTitleFn(column, item) {
|
|
57
|
+
return getString(column, item);
|
|
117
58
|
}
|
|
118
59
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (date == null) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
return this._toLocalISOString(date).slice(0, 19);
|
|
60
|
+
getComparableValue(item, valuePath, column) {
|
|
61
|
+
return getComparableValue(item, valuePath, column);
|
|
125
62
|
}
|
|
126
63
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return '';
|
|
64
|
+
serializeFilter(column, filter) {
|
|
65
|
+
if (filter == null) {
|
|
66
|
+
return;
|
|
131
67
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
68
|
+
const min = toDate(filter.min),
|
|
69
|
+
max = toDate(filter.max);
|
|
135
70
|
|
|
136
|
-
|
|
137
|
-
if (value == null || value === '') {
|
|
71
|
+
if (min == null && max == null) {
|
|
138
72
|
return;
|
|
139
73
|
}
|
|
140
|
-
|
|
141
|
-
return this.toValue(value.replace(/\./gu, ':') + 'Z');
|
|
74
|
+
return toHashString(min) + '~' + toHashString(max);
|
|
142
75
|
}
|
|
143
76
|
|
|
144
|
-
|
|
145
|
-
if (
|
|
146
|
-
return
|
|
77
|
+
deserializeFilter(column, filter) {
|
|
78
|
+
if (filter == null || filter === '') {
|
|
79
|
+
return null;
|
|
147
80
|
}
|
|
148
|
-
|
|
149
|
-
}
|
|
81
|
+
const matches = filter.match(/^([^~]+)?~([^~]+)?/iu);
|
|
150
82
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
minute: 'numeric'
|
|
83
|
+
if (!Array.isArray(matches)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
min: fromHashString(matches[1]),
|
|
89
|
+
max: fromHashString(matches[2])
|
|
159
90
|
};
|
|
160
|
-
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
renderCell(column, { item }) {
|
|
94
|
+
return getString(column, item);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
renderEditCell(column, { item }, onItemChange) {
|
|
98
|
+
const onChange = event => onItemChange(fromInputString(event.target.value));
|
|
99
|
+
return html`<paper-input no-label-float type="text" @change=${ onChange } .value=${ getString(column, item) }></paper-input>`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// eslint-disable-next-line max-lines-per-function
|
|
103
|
+
renderHeader(
|
|
104
|
+
{ title,
|
|
105
|
+
min,
|
|
106
|
+
max,
|
|
107
|
+
locale,
|
|
108
|
+
filterStep },
|
|
109
|
+
{ filter },
|
|
110
|
+
setState,
|
|
111
|
+
source
|
|
112
|
+
) {
|
|
113
|
+
return html`<cosmoz-omnitable-datetime-range-input
|
|
114
|
+
.title=${ title }
|
|
115
|
+
.filter=${ filter }
|
|
116
|
+
.values=${ source }
|
|
117
|
+
.min=${ min }
|
|
118
|
+
.max=${ max }
|
|
119
|
+
.locale=${ locale }
|
|
120
|
+
.filterStep=${ filterStep }
|
|
121
|
+
@filter-changed=${ ({ detail: { value }}) => setState(state => ({ ...state, filter: value })) }
|
|
122
|
+
@header-focused-changed=${ ({ detail: { value }}) => setState(state => ({ ...state, headerFocused: value })) }
|
|
123
|
+
></cosmoz-omnitable-datetime-range-input>`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
computeSource({ valuePath }, data) {
|
|
127
|
+
return valuesFrom(data, valuePath);
|
|
161
128
|
}
|
|
162
129
|
}
|
|
163
130
|
|
|
@@ -66,7 +66,10 @@ class OmnitableColumnListData extends translatable(mixin(Template, PolymerElemen
|
|
|
66
66
|
static get properties() {
|
|
67
67
|
return {
|
|
68
68
|
items: {
|
|
69
|
-
type: Array
|
|
69
|
+
type: Array,
|
|
70
|
+
observer() {
|
|
71
|
+
this.dispatchEvent(new CustomEvent('iron-resize', { bubbles: true }));
|
|
72
|
+
}
|
|
70
73
|
},
|
|
71
74
|
|
|
72
75
|
_expanded: {
|
|
@@ -5,9 +5,8 @@ import {
|
|
|
5
5
|
html, nothing
|
|
6
6
|
} from 'lit-html';
|
|
7
7
|
|
|
8
|
-
import { translatable } from '@neovici/cosmoz-i18next';
|
|
9
8
|
import { columnMixin } from './cosmoz-omnitable-column-mixin';
|
|
10
|
-
import { listColumnMixin } from './cosmoz-omnitable-column-list-mixin';
|
|
9
|
+
import { getTexts, listColumnMixin, onChange, onFocus, onText } from './cosmoz-omnitable-column-list-mixin';
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* @polymer
|
|
@@ -15,23 +14,14 @@ import { listColumnMixin } from './cosmoz-omnitable-column-list-mixin';
|
|
|
15
14
|
* @appliesMixin listColumnMixin
|
|
16
15
|
* @appliesMixin columnMixin
|
|
17
16
|
*/
|
|
18
|
-
class OmnitableColumnListHorizontal extends listColumnMixin(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
PolymerElement
|
|
22
|
-
)
|
|
23
|
-
)
|
|
24
|
-
) {
|
|
25
|
-
static get is() {
|
|
26
|
-
return 'cosmoz-omnitable-column-list-horizontal';
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
renderCell(column, { item }) {
|
|
30
|
-
const list = column.getTexts(item, column.valuePath, column.textProperty).map(item => html`<li>${ item }</li>`);
|
|
17
|
+
class OmnitableColumnListHorizontal extends listColumnMixin(columnMixin(PolymerElement)) {
|
|
18
|
+
renderCell({ valuePath, textProperty }, { item }) {
|
|
19
|
+
const list = getTexts(item, valuePath, textProperty).map(item => html`<li>${ item }</li>`);
|
|
31
20
|
|
|
32
21
|
return html`
|
|
33
22
|
<style>
|
|
34
23
|
ul {
|
|
24
|
+
padding: 0;
|
|
35
25
|
display: inline;
|
|
36
26
|
list-style: none;
|
|
37
27
|
}
|
|
@@ -45,41 +35,33 @@ class OmnitableColumnListHorizontal extends listColumnMixin(
|
|
|
45
35
|
content: "";
|
|
46
36
|
}
|
|
47
37
|
</style>
|
|
48
|
-
<ul>${ list }</ul>
|
|
38
|
+
<ul>${ list }</ul>
|
|
49
39
|
`;
|
|
50
40
|
}
|
|
51
41
|
|
|
52
|
-
renderEditCell(
|
|
53
|
-
|
|
54
|
-
event.model = { item };
|
|
55
|
-
return column._valueChanged(event);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
return html`<paper-input no-label-float type="text" @change=${ onChange } .value=${ column.getString(item, column.valuePath) }></paper-input>`;
|
|
42
|
+
renderEditCell() {
|
|
43
|
+
return 'not implemented';
|
|
59
44
|
}
|
|
60
45
|
|
|
61
|
-
renderHeader(column) {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
46
|
+
renderHeader(column, { filter, query }, setState, source) {
|
|
47
|
+
const
|
|
48
|
+
spinner = column.loading
|
|
49
|
+
? html`<paper-spinner-lite style="width: 20px; height: 20px;" suffix slot="suffix" active></paper-spinner-lite>`
|
|
50
|
+
: nothing;
|
|
66
51
|
return html`<cosmoz-autocomplete-ui
|
|
67
52
|
class="external-values-${ column.externalValues }"
|
|
68
53
|
.label=${ column.title }
|
|
69
|
-
.source=${
|
|
54
|
+
.source=${ source }
|
|
70
55
|
.textProperty=${ column.textProperty }
|
|
71
|
-
.value=${
|
|
72
|
-
.text=${
|
|
73
|
-
.onChange=${
|
|
74
|
-
.onFocus=${
|
|
75
|
-
.onText=${
|
|
56
|
+
.value=${ filter }
|
|
57
|
+
.text=${ query }
|
|
58
|
+
.onChange=${ onChange(setState) }
|
|
59
|
+
.onFocus=${ onFocus(setState) }
|
|
60
|
+
.onText=${ onText(setState) }
|
|
76
61
|
>${ spinner }</cosmoz-autocomplete-ui>
|
|
77
62
|
`;
|
|
78
63
|
}
|
|
79
64
|
|
|
80
65
|
}
|
|
81
66
|
|
|
82
|
-
customElements.define(
|
|
83
|
-
OmnitableColumnListHorizontal.is,
|
|
84
|
-
OmnitableColumnListHorizontal
|
|
85
|
-
);
|
|
67
|
+
customElements.define('cosmoz-omnitable-column-list-horizontal', OmnitableColumnListHorizontal);
|
|
@@ -1,113 +1,54 @@
|
|
|
1
|
-
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin';
|
|
2
1
|
import {
|
|
3
2
|
prop, array
|
|
4
3
|
} from '@neovici/cosmoz-autocomplete/lib/utils';
|
|
4
|
+
import { get } from '@polymer/polymer/lib/utils/path';
|
|
5
|
+
import { valuesFrom } from './lib/utils-data';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
readOnly: true,
|
|
20
|
-
value: true
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
filter: {
|
|
24
|
-
type: Array,
|
|
25
|
-
notify: true,
|
|
26
|
-
value() {
|
|
27
|
-
return this._getDefaultFilter();
|
|
7
|
+
const
|
|
8
|
+
unique = (values, valueProperty) => {
|
|
9
|
+
if (!Array.isArray(values)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const used = [];
|
|
13
|
+
return values
|
|
14
|
+
.reduce((acc, cur) => {
|
|
15
|
+
if (Array.isArray(cur)) {
|
|
16
|
+
cur.forEach(subcur => {
|
|
17
|
+
acc.push(subcur);
|
|
18
|
+
});
|
|
19
|
+
return acc;
|
|
28
20
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
constructor() {
|
|
58
|
-
super();
|
|
59
|
-
this._onFocus = this._onFocus.bind(this);
|
|
60
|
-
this._onChange = this._onChange.bind(this);
|
|
61
|
-
this._onText = this._onText.bind(this);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
getString(item, valuePath = this.valuePath, textProperty = this.textProperty) {
|
|
65
|
-
return this.getTexts(item, valuePath, textProperty)
|
|
66
|
-
.filter(i => i != null)
|
|
67
|
-
.join(', ');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getTexts(item, valuePath = this.valuePath, textProperty = this.textProperty) {
|
|
71
|
-
return array(valuePath && this.get(valuePath, item)).map(prop(textProperty));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
toXlsxValue(item, valuePath = this.valuePath) {
|
|
75
|
-
return this.getString(item, valuePath);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Get the comparable value of an item.
|
|
80
|
-
*
|
|
81
|
-
* @param {Object} item Item to be processed
|
|
82
|
-
* @param {String} valuePath Property path
|
|
83
|
-
* @returns {String|void} Valid value or void
|
|
84
|
-
*/
|
|
85
|
-
getComparableValue(item, valuePath = this.valuePath) {
|
|
86
|
-
const value = super.getComparableValue(item, valuePath);
|
|
87
|
-
if (this.valueProperty == null) {
|
|
88
|
-
return value;
|
|
21
|
+
acc.push(cur);
|
|
22
|
+
return acc;
|
|
23
|
+
}, [])
|
|
24
|
+
.filter((item, index, array) => {
|
|
25
|
+
if (array.indexOf(item) !== index) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (valueProperty) {
|
|
29
|
+
const value = get(item, valueProperty);
|
|
30
|
+
if (used.indexOf(value) !== -1) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
used.push(value);
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
toAutocompleteSource = (values, valueProperty, textProperty) => {
|
|
40
|
+
if (values == null) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (Array.isArray(values)) {
|
|
45
|
+
return unique(values, valueProperty);
|
|
89
46
|
}
|
|
90
|
-
const subValues = array(value).reduce((acc, subItem) => {
|
|
91
|
-
acc.push(this.get(this.valueProperty, subItem));
|
|
92
|
-
return acc;
|
|
93
|
-
}, []);
|
|
94
|
-
return subValues.sort().join(' ');
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
_getDefaultFilter() {
|
|
98
|
-
return [];
|
|
99
|
-
}
|
|
100
47
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
48
|
+
if (typeof values === 'object') {
|
|
49
|
+
const
|
|
50
|
+
valProp = valueProperty ?? 'id',
|
|
104
51
|
textProp = textProperty ?? 'label';
|
|
105
|
-
if (valueProperty == null) {
|
|
106
|
-
this.valueProperty = valProp;
|
|
107
|
-
}
|
|
108
|
-
if (textProperty == null) {
|
|
109
|
-
this.textProperty = textProp;
|
|
110
|
-
}
|
|
111
52
|
return Object
|
|
112
53
|
.entries(values)
|
|
113
54
|
.map(([id, label]) => ({
|
|
@@ -124,51 +65,103 @@ export const listColumnMixin = dedupingMixin(base => class extends base {
|
|
|
124
65
|
return 0;
|
|
125
66
|
});
|
|
126
67
|
}
|
|
127
|
-
return this._unique(values, valueProperty) || [];
|
|
128
|
-
}
|
|
129
68
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
69
|
+
return [];
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
getTexts = (item, valuePath, textProperty) =>
|
|
73
|
+
array(valuePath && get(item, valuePath)).map(prop(textProperty)),
|
|
74
|
+
|
|
75
|
+
getString = ({ valuePath, textProperty }, item) => {
|
|
76
|
+
return getTexts(item, valuePath, textProperty)
|
|
77
|
+
.filter(i => i != null)
|
|
78
|
+
.join(', ');
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
toXlsxValue = getString,
|
|
82
|
+
|
|
83
|
+
applyMultiFilter = ({ valueProperty, valuePath, emptyValue }, filters) => item => {
|
|
84
|
+
const val = prop(valueProperty),
|
|
85
|
+
values = array(get(item, valuePath));
|
|
86
|
+
return filters.some(filter =>
|
|
87
|
+
values.length === 0 && val(filter) === emptyValue || values.some(value => val(value) === val(filter))
|
|
88
|
+
);
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
onChange = setState => value => setState(state => ({ ...state, filter: value })),
|
|
92
|
+
onFocus = setState => focused => setState(state => ({ ...state, headerFocused: focused })),
|
|
93
|
+
onText = setState => text => setState(state => ({ ...state, query: text })),
|
|
94
|
+
|
|
95
|
+
computeSource = (
|
|
96
|
+
{ valuePath, valueProperty, textProperty, emptyLabel, emptyValue },
|
|
97
|
+
data
|
|
98
|
+
) => {
|
|
99
|
+
const values = valuesFrom(data, valuePath),
|
|
100
|
+
source = toAutocompleteSource(values, valueProperty, textProperty);
|
|
134
101
|
|
|
135
|
-
|
|
136
|
-
if (!emptyLabel || emptyValue === undefined || source.length < 0) {
|
|
102
|
+
if (!emptyLabel || emptyValue === undefined || !textProperty || !valueProperty || source.length < 0) {
|
|
137
103
|
return source;
|
|
138
104
|
}
|
|
139
105
|
return [{
|
|
140
|
-
[
|
|
141
|
-
[
|
|
106
|
+
[textProperty]: emptyLabel,
|
|
107
|
+
[valueProperty]: emptyValue
|
|
142
108
|
}, ...source];
|
|
143
|
-
}
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
listColumnMixin = base => class extends base {
|
|
112
|
+
static get properties() {
|
|
113
|
+
return {
|
|
114
|
+
textProperty: { type: String },
|
|
115
|
+
valueProperty: { type: String },
|
|
116
|
+
emptyLabel: { type: String },
|
|
117
|
+
emptyValue: { type: Object }
|
|
118
|
+
};
|
|
119
|
+
}
|
|
144
120
|
|
|
121
|
+
getString(column, item) {
|
|
122
|
+
return getString(column, item);
|
|
123
|
+
}
|
|
145
124
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return filters.some(
|
|
150
|
-
filter => values.length === 0 && val(filter) === this.emptyValue || values.some(value => val(value) === val(filter))
|
|
151
|
-
);
|
|
152
|
-
}
|
|
125
|
+
toXlsxValue(column, item) {
|
|
126
|
+
return toXlsxValue(column, item);
|
|
127
|
+
}
|
|
153
128
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return;
|
|
129
|
+
cellTitleFn(column, item) {
|
|
130
|
+
return getString(column, item);
|
|
157
131
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
132
|
+
|
|
133
|
+
getComparableValue(item, valuePath, { valueProperty }) {
|
|
134
|
+
const value = get(item, valuePath);
|
|
135
|
+
if (valueProperty == null) {
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
const subValues = array(value).reduce((acc, subItem) => {
|
|
139
|
+
acc.push(get(subItem, valueProperty));
|
|
140
|
+
return acc;
|
|
141
|
+
}, []);
|
|
142
|
+
return subValues.sort().join(' ');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
getFilterFn(column, filters) {
|
|
146
|
+
if (!filters || !Array.isArray(filters) || filters.length === 0) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return applyMultiFilter(column, filters);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
serializeFilter(column, filter) {
|
|
154
|
+
// TODO: drop the double-encoding
|
|
155
|
+
return filter.length === 0 ? null : encodeURIComponent(JSON.stringify(filter));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
deserializeFilter(column, filter) {
|
|
159
|
+
return JSON.parse(decodeURIComponent(filter));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
computeSource(column, data) {
|
|
163
|
+
return computeSource(column, data);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export { unique, getTexts, getString, toXlsxValue, applyMultiFilter, onChange, onFocus, onText, computeSource, toAutocompleteSource, listColumnMixin };
|