@controleonline/ui-default 1.0.272 → 1.0.274
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/.github/workflows/publish-npm.yml +91 -0
- package/AGENTS.md +1 -1
- package/docs/technical/DefaultTable.md +70 -1
- package/package.json +22 -22
- package/src/react/components/address/DefaultAddress.js +20 -9
- package/src/react/components/address/DefaultAddressCoordFields.js +59 -0
- package/src/react/components/address/LatLonReadonlyFields.js +2 -2
- package/src/react/components/address/defaultAddressStyles.js +13 -1
- package/src/react/components/files/DefaultFile.js +2 -2
- package/src/react/components/files/DefaultFileColumn.js +1 -1
- package/src/react/components/filters/DefaultColumnFilter.js +2 -7
- package/src/react/components/filters/DefaultExternalFilters.js +4 -11
- package/src/react/components/filters/filterValue.js +65 -0
- package/src/react/components/help/DefaultTooltip.js +73 -63
- package/src/react/components/help/DefaultTooltip.styles.js +23 -23
- package/src/react/components/inputs/DefaultInput.js +301 -210
- package/src/react/components/inputs/defaultInputUtils.js +193 -170
- package/src/react/components/table/DefaultColumnMenu.js +127 -109
- package/src/react/components/table/DefaultTable.js +43 -92
- package/src/react/components/table/DefaultTable.styles.js +10 -4
- package/src/react/components/table/DefaultTable.utils.js +38 -4
- package/src/react/components/table/DefaultTableRows.js +324 -153
- package/src/react/components/table/DefaultTableToolbar.js +17 -7
- package/src/react/components/table/DefaultTableView.js +118 -0
- package/src/react/components/upload/DefaultUpload.js +6 -36
- package/src/react/components/upload/DefaultUpload.styles.js +5 -5
- package/src/react/components/upload/DefaultUploadAttachmentsList.js +11 -3
- package/src/react/hooks/usePostalCodeLookup.js +15 -1
- package/src/react/services/addressFormUtils.js +104 -38
- package/src/react/services/addressGeo.js +6 -3
- package/src/react/utils/tableVisibleColumnsPreferences.js +84 -3
- package/src/tests/react/components/files/DefaultFile.test.js +16 -0
- package/src/tests/react/components/files/DefaultFileColumn.company.test.js +24 -0
- package/src/tests/react/components/help/DefaultTooltip.test.js +93 -0
- package/src/tests/react/components/table/DefaultTable.test.js +37 -0
- package/src/tests/react/components/table/DefaultTable.utils.test.js +10 -0
- package/src/tests/react/components/table/DefaultTableRowActions.test.js +23 -0
- package/src/tests/react/components/table/DefaultTableRows.rowActions.test.js +152 -0
- package/src/tests/react/components/table/DefaultTableToolbar.waiter.test.js +42 -0
- package/src/tests/react/components/upload/defaultUploadLibrary.test.js +31 -9
- package/src/tests/react/filters/filterValue.test.js +46 -0
- package/src/tests/react/hooks/usePostalCodeLookup.test.js +67 -0
- package/src/tests/react/inputs/defaultInputUtils.test.js +9 -1
- package/src/tests/react/services/addressFormUtils.test.js +6 -3
- package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +12 -1
|
@@ -2,31 +2,31 @@ import { getAllStores } from '@store';
|
|
|
2
2
|
import Formatter from '@controleonline/ui-common/src/utils/formatter.js';
|
|
3
3
|
import { formatStoreColumnValue } from '@controleonline/ui-common/src/react/utils/storeColumns';
|
|
4
4
|
import FeatherGlyphMap from 'react-native-vector-icons/glyphmaps/Feather.json';
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
export const normalizeText = value => String(value ?? '').trim();
|
|
7
7
|
export const isValidFeatherIcon = icon => Boolean(FeatherGlyphMap[normalizeText(icon)]);
|
|
8
8
|
const formatHumanLabel = value =>
|
|
9
|
-
normalizeText(value)
|
|
10
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
11
|
-
.replace(/[_-]+/g, ' ')
|
|
12
|
-
.replace(/^\w/, letter => letter.toUpperCase());
|
|
13
|
-
const DEFAULT_TRANSLATABLE_FIELDS = new Set([
|
|
14
|
-
'active',
|
|
15
|
-
'app',
|
|
16
|
-
'channel',
|
|
17
|
-
'displaytype',
|
|
18
|
-
'featured',
|
|
19
|
-
'frequency',
|
|
20
|
-
'invoicetype',
|
|
21
|
-
'installments',
|
|
22
|
-
'ordertype',
|
|
23
|
-
'peopletype',
|
|
24
|
-
'pricecalculation',
|
|
25
|
-
'productcondition',
|
|
26
|
-
'realstatus',
|
|
27
|
-
'status',
|
|
28
|
-
]);
|
|
29
|
-
|
|
9
|
+
normalizeText(value)
|
|
10
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
11
|
+
.replace(/[_-]+/g, ' ')
|
|
12
|
+
.replace(/^\w/, letter => letter.toUpperCase());
|
|
13
|
+
const DEFAULT_TRANSLATABLE_FIELDS = new Set([
|
|
14
|
+
'active',
|
|
15
|
+
'app',
|
|
16
|
+
'channel',
|
|
17
|
+
'displaytype',
|
|
18
|
+
'featured',
|
|
19
|
+
'frequency',
|
|
20
|
+
'invoicetype',
|
|
21
|
+
'installments',
|
|
22
|
+
'ordertype',
|
|
23
|
+
'peopletype',
|
|
24
|
+
'pricecalculation',
|
|
25
|
+
'productcondition',
|
|
26
|
+
'realstatus',
|
|
27
|
+
'status',
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
30
|
export const getColumnKey = column => column?.key || column?.name || '';
|
|
31
31
|
|
|
32
32
|
export const isDateColumn = column =>
|
|
@@ -54,6 +54,13 @@ export const isColorColumn = column => {
|
|
|
54
54
|
);
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
+
export const isIconColumn = column => {
|
|
58
|
+
const fieldName = normalizeColumnKey(getColumnKey(column));
|
|
59
|
+
const inputType = normalizeColumnKey(column?.inputType || column?.type);
|
|
60
|
+
|
|
61
|
+
return inputType === 'icon' || fieldName === 'icon';
|
|
62
|
+
};
|
|
63
|
+
|
|
57
64
|
export const isFileColumn = column => {
|
|
58
65
|
const inputType = normalizeColumnKey(column?.inputType || column?.type);
|
|
59
66
|
|
|
@@ -73,114 +80,130 @@ export const isExtraDataColumn = column =>
|
|
|
73
80
|
|
|
74
81
|
const normalizeColumnKey = value =>
|
|
75
82
|
normalizeText(value)
|
|
76
|
-
.replace(/[^a-zA-Z0-9]/g, '')
|
|
77
|
-
.toLowerCase();
|
|
78
|
-
|
|
79
|
-
const shouldTranslateOptionLabel = (column, storeName, rawLabel) => {
|
|
80
|
-
if (column?.translate === false || !normalizeText(rawLabel) || !normalizeText(storeName)) {
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (column?.translate === true || Array.isArray(column?.list)) {
|
|
85
|
-
return true;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return [column?.key, column?.name, column?.label]
|
|
89
|
-
.map(normalizeColumnKey)
|
|
90
|
-
.filter(Boolean)
|
|
91
|
-
.some(candidate => DEFAULT_TRANSLATABLE_FIELDS.has(candidate));
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export const normalizeId = value => {
|
|
95
|
-
if (!value) return '';
|
|
96
|
-
if (typeof value === 'number') return String(value);
|
|
97
|
-
if (typeof value === 'string') {
|
|
98
|
-
const match = value.match(/\d+/g);
|
|
99
|
-
return match ? match[match.length - 1] : value;
|
|
100
|
-
}
|
|
101
|
-
return normalizeId(value?.id || value?.['@id'] || '');
|
|
102
|
-
};
|
|
103
|
-
|
|
83
|
+
.replace(/[^a-zA-Z0-9]/g, '')
|
|
84
|
+
.toLowerCase();
|
|
85
|
+
|
|
86
|
+
const shouldTranslateOptionLabel = (column, storeName, rawLabel) => {
|
|
87
|
+
if (column?.translate === false || !normalizeText(rawLabel) || !normalizeText(storeName)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (column?.translate === true || Array.isArray(column?.list)) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return [column?.key, column?.name, column?.label]
|
|
96
|
+
.map(normalizeColumnKey)
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.some(candidate => DEFAULT_TRANSLATABLE_FIELDS.has(candidate));
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const normalizeId = value => {
|
|
102
|
+
if (!value) return '';
|
|
103
|
+
if (typeof value === 'number') return String(value);
|
|
104
|
+
if (typeof value === 'string') {
|
|
105
|
+
const match = value.match(/\d+/g);
|
|
106
|
+
return match ? match[match.length - 1] : value;
|
|
107
|
+
}
|
|
108
|
+
return normalizeId(value?.id || value?.['@id'] || '');
|
|
109
|
+
};
|
|
110
|
+
|
|
104
111
|
export const isEditableColumn = column =>
|
|
105
112
|
column?.editable !== false &&
|
|
106
113
|
!column?.isIdentity &&
|
|
107
114
|
column?.inputType !== 'increase' &&
|
|
108
115
|
!isFileColumn(column) &&
|
|
109
116
|
!String(getColumnKey(column)).includes('.');
|
|
110
|
-
|
|
117
|
+
|
|
111
118
|
export const normalizeOptionKey = option => {
|
|
112
|
-
if (!option) return '';
|
|
113
|
-
if (typeof option !== 'object') return normalizeId(option) || normalizeText(option);
|
|
114
|
-
return normalizeText(
|
|
115
|
-
option.value ??
|
|
116
|
-
option.id ??
|
|
117
|
-
normalizeId(option['@id']) ??
|
|
118
|
-
option.key ??
|
|
119
|
-
'',
|
|
120
|
-
);
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
export const resolveOptionLabel = (column, option, storeName = '') => {
|
|
124
|
-
if (!option) return '';
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
119
|
+
if (!option) return '';
|
|
120
|
+
if (typeof option !== 'object') return normalizeId(option) || normalizeText(option);
|
|
121
|
+
return normalizeText(
|
|
122
|
+
option.value ??
|
|
123
|
+
option.id ??
|
|
124
|
+
normalizeId(option['@id']) ??
|
|
125
|
+
option.key ??
|
|
126
|
+
'',
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const resolveOptionLabel = (column, option, storeName = '') => {
|
|
131
|
+
if (!option) return '';
|
|
132
|
+
|
|
133
|
+
const STATUS_DISPLAY_PT = {
|
|
134
|
+
paid: 'Pago',
|
|
135
|
+
'waiting payment': 'Aguardando pagamento',
|
|
136
|
+
waiting_payment: 'Aguardando pagamento',
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const translateOptionLabel = rawLabel => {
|
|
140
|
+
const normalizedLabel = normalizeText(rawLabel);
|
|
141
|
+
const statusFallback = STATUS_DISPLAY_PT[normalizedLabel.toLowerCase()] || '';
|
|
142
|
+
if (!shouldTranslateOptionLabel(column, storeName, normalizedLabel)) {
|
|
143
|
+
return statusFallback || normalizedLabel;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const translated = global.t?.t(storeName, 'label', normalizedLabel) || normalizedLabel;
|
|
147
|
+
const translatedText = normalizeText(translated);
|
|
148
|
+
if (
|
|
149
|
+
statusFallback &&
|
|
150
|
+
(!translatedText ||
|
|
151
|
+
translatedText.toLowerCase() === normalizedLabel.toLowerCase() ||
|
|
152
|
+
translatedText === formatHumanLabel(normalizedLabel))
|
|
153
|
+
) {
|
|
154
|
+
return statusFallback;
|
|
155
|
+
}
|
|
156
|
+
return translatedText === formatHumanLabel(normalizedLabel)
|
|
157
|
+
? normalizedLabel
|
|
158
|
+
: translated;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
if (typeof column?.formatList === 'function') {
|
|
162
|
+
const formatted = column.formatList(option, null, column);
|
|
163
|
+
if (formatted && typeof formatted === 'object') {
|
|
164
|
+
return translateOptionLabel(formatted.label ?? formatted.value);
|
|
165
|
+
}
|
|
166
|
+
if (formatted) return translateOptionLabel(formatted);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const rawLabel = normalizeText(
|
|
170
|
+
option.label ??
|
|
171
|
+
option[column?.searchParam] ??
|
|
172
|
+
option[column?.name] ??
|
|
173
|
+
option.name ??
|
|
174
|
+
option.status ??
|
|
175
|
+
option.wallet ??
|
|
176
|
+
option.paymentType ??
|
|
177
|
+
option.alias ??
|
|
178
|
+
option.id,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
return translateOptionLabel(rawLabel);
|
|
182
|
+
};
|
|
183
|
+
|
|
161
184
|
export const resolveStoreNameFromList = list =>
|
|
162
185
|
typeof list === 'string' ? normalizeText(list).split('/')[0] || '' : '';
|
|
163
|
-
|
|
186
|
+
|
|
164
187
|
const filterItemsByListRequestParams = (items = [], column = null) => {
|
|
165
|
-
const requestParams =
|
|
166
|
-
column?.listRequestParams &&
|
|
167
|
-
typeof column.listRequestParams === 'object' &&
|
|
168
|
-
!Array.isArray(column.listRequestParams)
|
|
169
|
-
? column.listRequestParams
|
|
170
|
-
: null;
|
|
171
|
-
|
|
172
|
-
if (!requestParams || Object.keys(requestParams).length === 0) {
|
|
173
|
-
return Array.isArray(items) ? items : [];
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return (Array.isArray(items) ? items : []).filter(item =>
|
|
177
|
-
Object.entries(requestParams).every(([key, expectedValue]) => {
|
|
178
|
-
if (expectedValue === undefined || expectedValue === null || expectedValue === '') {
|
|
179
|
-
return true;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return normalizeText(item?.[key]) === normalizeText(expectedValue);
|
|
183
|
-
}),
|
|
188
|
+
const requestParams =
|
|
189
|
+
column?.listRequestParams &&
|
|
190
|
+
typeof column.listRequestParams === 'object' &&
|
|
191
|
+
!Array.isArray(column.listRequestParams)
|
|
192
|
+
? column.listRequestParams
|
|
193
|
+
: null;
|
|
194
|
+
|
|
195
|
+
if (!requestParams || Object.keys(requestParams).length === 0) {
|
|
196
|
+
return Array.isArray(items) ? items : [];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return (Array.isArray(items) ? items : []).filter(item =>
|
|
200
|
+
Object.entries(requestParams).every(([key, expectedValue]) => {
|
|
201
|
+
if (expectedValue === undefined || expectedValue === null || expectedValue === '') {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return normalizeText(item?.[key]) === normalizeText(expectedValue);
|
|
206
|
+
}),
|
|
184
207
|
);
|
|
185
208
|
};
|
|
186
209
|
|
|
@@ -215,16 +238,16 @@ export const mapOptions = (column, items = [], storeName = '') => {
|
|
|
215
238
|
const options = [];
|
|
216
239
|
|
|
217
240
|
(Array.isArray(items) ? items : []).forEach(item => {
|
|
218
|
-
const formatted =
|
|
219
|
-
typeof column?.formatList === 'function'
|
|
220
|
-
? column.formatList(item, null, column)
|
|
221
|
-
: item;
|
|
222
|
-
const key = normalizeOptionKey(formatted) || normalizeOptionKey(item);
|
|
223
|
-
const dedupeKey = key || normalizeText(resolveOptionLabel(column, item, storeName)).toLowerCase();
|
|
224
|
-
|
|
225
|
-
if (dedupeKey && seenKeys.has(dedupeKey)) return;
|
|
226
|
-
if (dedupeKey) seenKeys.add(dedupeKey);
|
|
227
|
-
|
|
241
|
+
const formatted =
|
|
242
|
+
typeof column?.formatList === 'function'
|
|
243
|
+
? column.formatList(item, null, column)
|
|
244
|
+
: item;
|
|
245
|
+
const key = normalizeOptionKey(formatted) || normalizeOptionKey(item);
|
|
246
|
+
const dedupeKey = key || normalizeText(resolveOptionLabel(column, item, storeName)).toLowerCase();
|
|
247
|
+
|
|
248
|
+
if (dedupeKey && seenKeys.has(dedupeKey)) return;
|
|
249
|
+
if (dedupeKey) seenKeys.add(dedupeKey);
|
|
250
|
+
|
|
228
251
|
const formattedMeta = normalizeObject(formatted);
|
|
229
252
|
const itemMeta = normalizeObject(item);
|
|
230
253
|
const color = formattedMeta.color ?? itemMeta.color;
|
|
@@ -240,10 +263,10 @@ export const mapOptions = (column, items = [], storeName = '') => {
|
|
|
240
263
|
raw: item,
|
|
241
264
|
});
|
|
242
265
|
});
|
|
243
|
-
|
|
244
|
-
return options;
|
|
245
|
-
};
|
|
246
|
-
|
|
266
|
+
|
|
267
|
+
return options;
|
|
268
|
+
};
|
|
269
|
+
|
|
247
270
|
export const buildOptionsFromColumn = (column, getOptionsForColumn = null, storeName = '') => {
|
|
248
271
|
const explicitOptions = getOptionsForColumn?.(column);
|
|
249
272
|
if (Array.isArray(explicitOptions) && explicitOptions.length > 0) {
|
|
@@ -255,26 +278,26 @@ export const buildOptionsFromColumn = (column, getOptionsForColumn = null, store
|
|
|
255
278
|
}
|
|
256
279
|
|
|
257
280
|
const listStoreName = resolveStoreNameFromList(column?.list);
|
|
258
|
-
if (!listStoreName) return [];
|
|
259
|
-
|
|
260
|
-
const listStore = getAllStores()?.[listStoreName];
|
|
261
|
-
return mapOptions(
|
|
262
|
-
column,
|
|
263
|
-
filterItemsByListRequestParams(listStore?.getters?.items || [], column),
|
|
264
|
-
storeName,
|
|
265
|
-
);
|
|
266
|
-
};
|
|
267
|
-
|
|
281
|
+
if (!listStoreName) return [];
|
|
282
|
+
|
|
283
|
+
const listStore = getAllStores()?.[listStoreName];
|
|
284
|
+
return mapOptions(
|
|
285
|
+
column,
|
|
286
|
+
filterItemsByListRequestParams(listStore?.getters?.items || [], column),
|
|
287
|
+
storeName,
|
|
288
|
+
);
|
|
289
|
+
};
|
|
290
|
+
|
|
268
291
|
export const resolveCellText = ({ column, columns = [], row, storeName, value }) => {
|
|
269
292
|
const fieldName = getColumnKey(column);
|
|
270
293
|
const rawValue = value ?? row?.[fieldName];
|
|
271
294
|
const formattedValue = formatStoreColumnValue({
|
|
272
|
-
columns: columns.length ? columns : [column],
|
|
273
|
-
fieldName,
|
|
274
|
-
row,
|
|
275
|
-
storeName,
|
|
276
|
-
value: rawValue,
|
|
277
|
-
});
|
|
295
|
+
columns: columns.length ? columns : [column],
|
|
296
|
+
fieldName,
|
|
297
|
+
row,
|
|
298
|
+
storeName,
|
|
299
|
+
value: rawValue,
|
|
300
|
+
});
|
|
278
301
|
|
|
279
302
|
return normalizeText(formattedValue) || '-';
|
|
280
303
|
};
|
|
@@ -408,29 +431,29 @@ export const buildReadPresentationStyles = presentation => {
|
|
|
408
431
|
export const resolveEditValue = (column, row, value) => {
|
|
409
432
|
const rawValue = value ?? row?.[getColumnKey(column)];
|
|
410
433
|
if (column?.list) {
|
|
411
|
-
return normalizeOptionKey(
|
|
412
|
-
typeof column?.formatList === 'function'
|
|
413
|
-
? column.formatList(rawValue, row, column)
|
|
414
|
-
: rawValue,
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
if (typeof column?.editFormat === 'function') {
|
|
419
|
-
return normalizeText(column.editFormat(rawValue, column, row, true));
|
|
420
|
-
}
|
|
421
|
-
|
|
434
|
+
return normalizeOptionKey(
|
|
435
|
+
typeof column?.formatList === 'function'
|
|
436
|
+
? column.formatList(rawValue, row, column)
|
|
437
|
+
: rawValue,
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (typeof column?.editFormat === 'function') {
|
|
442
|
+
return normalizeText(column.editFormat(rawValue, column, row, true));
|
|
443
|
+
}
|
|
444
|
+
|
|
422
445
|
if (isDateLikeColumn(column) && rawValue) {
|
|
423
446
|
return normalizeText(Formatter.formatDateYmdTodmY(rawValue));
|
|
424
447
|
}
|
|
425
|
-
|
|
426
|
-
return normalizeText(rawValue);
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
export const formatSaveValue = (column, value, row) => {
|
|
430
|
-
if (typeof column?.saveFormat === 'function') {
|
|
431
|
-
return column.saveFormat(value, column, row);
|
|
432
|
-
}
|
|
433
|
-
|
|
448
|
+
|
|
449
|
+
return normalizeText(rawValue);
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
export const formatSaveValue = (column, value, row) => {
|
|
453
|
+
if (typeof column?.saveFormat === 'function') {
|
|
454
|
+
return column.saveFormat(value, column, row);
|
|
455
|
+
}
|
|
456
|
+
|
|
434
457
|
if (value && typeof value === 'object') {
|
|
435
458
|
if (value.value) return Number.isNaN(Number(value.value)) ? value.value : Number(value.value);
|
|
436
459
|
if (value['@id']) return value['@id'];
|
|
@@ -1,109 +1,127 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Modal, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
-
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
-
import { useStore } from '@store';
|
|
5
|
-
import { formatStoreColumnLabel } from '@controleonline/ui-common/src/react/utils/storeColumns';
|
|
6
|
-
import { getColumnKey } from '../inputs/defaultInputUtils';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Modal, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
+
import { useStore } from '@store';
|
|
5
|
+
import { formatStoreColumnLabel } from '@controleonline/ui-common/src/react/utils/storeColumns';
|
|
6
|
+
import { getColumnKey } from '../inputs/defaultInputUtils';
|
|
7
|
+
import {
|
|
8
|
+
canHideVisibleColumn,
|
|
9
|
+
isRequiredVisibleColumn,
|
|
10
|
+
persistVisibleColumnsPreference,
|
|
11
|
+
resolveDefaultTablePreferenceScope,
|
|
12
|
+
sanitizeVisibleColumnsPreference,
|
|
13
|
+
} from '../../utils/tableVisibleColumnsPreferences';
|
|
14
|
+
import styles from './DefaultTable.styles';
|
|
15
|
+
import { shouldIncludeColumn } from './DefaultTable.utils';
|
|
16
|
+
import useDefaultTableTheme from './useDefaultTableTheme';
|
|
17
|
+
|
|
18
|
+
const DefaultColumnMenu = ({ storeName, visible = false, onClose }) => {
|
|
19
|
+
const store = useStore(storeName);
|
|
20
|
+
const columns = Array.isArray(store?.getters?.columns) ? store.getters.columns : [];
|
|
21
|
+
const visibleColumns = store?.getters?.visibleColumns || {};
|
|
22
|
+
const configs = store?.getters?.configs || {};
|
|
23
|
+
const tablePreferenceScope =
|
|
24
|
+
configs.tablePreferenceScope ||
|
|
25
|
+
resolveDefaultTablePreferenceScope({ storeName });
|
|
26
|
+
const availableColumns = columns.filter(column => shouldIncludeColumn(column));
|
|
27
|
+
const {
|
|
28
|
+
checkboxBorderColor: resolvedCheckboxBorderColor,
|
|
29
|
+
checkboxSelectedMarkColor: resolvedCheckboxSelectedMarkColor,
|
|
30
|
+
modalColors,
|
|
31
|
+
themeColors,
|
|
32
|
+
} = useDefaultTableTheme();
|
|
33
|
+
if (!visible) return null;
|
|
34
|
+
|
|
35
|
+
const {
|
|
36
|
+
backgroundColor,
|
|
37
|
+
borderColor,
|
|
38
|
+
closeIconColor,
|
|
39
|
+
headerTextColor,
|
|
40
|
+
overlayColor,
|
|
41
|
+
textColor,
|
|
42
|
+
} = modalColors;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Modal visible transparent animationType="fade" onRequestClose={onClose}>
|
|
46
|
+
<View style={[styles.modalOverlay, { backgroundColor: overlayColor }]}>
|
|
47
|
+
<View style={[styles.modalCard, styles.columnMenuModalCard, { borderColor, backgroundColor }]}>
|
|
48
|
+
<View style={[styles.modalHeader, { borderBottomColor: borderColor }]}>
|
|
49
|
+
<Text style={[styles.modalTitle, { color: headerTextColor }]} numberOfLines={1}>
|
|
50
|
+
{global.t?.t(storeName, 'label', 'columns')}
|
|
51
|
+
</Text>
|
|
52
|
+
<TouchableOpacity
|
|
53
|
+
style={[styles.modalCloseButton, { borderColor, backgroundColor }]}
|
|
54
|
+
activeOpacity={0.82}
|
|
55
|
+
onPress={onClose}
|
|
56
|
+
>
|
|
57
|
+
<Icon name="x" size={16} color={themeColors.iconWarning || closeIconColor} />
|
|
58
|
+
</TouchableOpacity>
|
|
59
|
+
</View>
|
|
60
|
+
<ScrollView style={styles.columnMenuModalBody} contentContainerStyle={styles.columnMenuModalList}>
|
|
61
|
+
{availableColumns.map(column => {
|
|
62
|
+
const fieldName = getColumnKey(column);
|
|
63
|
+
const label = formatStoreColumnLabel({
|
|
64
|
+
columns,
|
|
65
|
+
fieldName,
|
|
66
|
+
fallbackLabel: column?.label || fieldName,
|
|
67
|
+
storeName,
|
|
68
|
+
});
|
|
69
|
+
const checked = visibleColumns[fieldName] !== false;
|
|
70
|
+
const required = isRequiredVisibleColumn(column);
|
|
71
|
+
const locked =
|
|
72
|
+
required ||
|
|
73
|
+
(checked &&
|
|
74
|
+
!canHideVisibleColumn({
|
|
75
|
+
columns,
|
|
76
|
+
fieldName,
|
|
77
|
+
visibleColumns,
|
|
78
|
+
}));
|
|
79
|
+
const toggleColumn = () => {
|
|
80
|
+
if (locked && checked) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const nextVisibleColumns = sanitizeVisibleColumnsPreference({
|
|
85
|
+
columns,
|
|
86
|
+
visibleColumns: {
|
|
87
|
+
...visibleColumns,
|
|
88
|
+
[fieldName]: visibleColumns[fieldName] === false,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
persistVisibleColumnsPreference(tablePreferenceScope, nextVisibleColumns);
|
|
93
|
+
|
|
94
|
+
if (typeof store?.actions?.setVisibleColumns === 'function') {
|
|
95
|
+
store.actions.setVisibleColumns(nextVisibleColumns);
|
|
96
|
+
} else if (store?.getters) {
|
|
97
|
+
store.getters.visibleColumns = nextVisibleColumns;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<TouchableOpacity
|
|
103
|
+
key={fieldName}
|
|
104
|
+
style={styles.columnMenuItem}
|
|
105
|
+
activeOpacity={locked ? 1 : 0.82}
|
|
106
|
+
disabled={locked && checked}
|
|
107
|
+
onPress={toggleColumn}
|
|
108
|
+
>
|
|
109
|
+
<Icon
|
|
110
|
+
name={checked ? 'check-square' : 'square'}
|
|
111
|
+
size={16}
|
|
112
|
+
color={checked ? resolvedCheckboxSelectedMarkColor : resolvedCheckboxBorderColor}
|
|
113
|
+
/>
|
|
114
|
+
<Text style={[styles.columnMenuText, { color: textColor }]} numberOfLines={1}>
|
|
115
|
+
{required ? `${label} *` : label}
|
|
116
|
+
</Text>
|
|
117
|
+
</TouchableOpacity>
|
|
118
|
+
);
|
|
119
|
+
})}
|
|
120
|
+
</ScrollView>
|
|
121
|
+
</View>
|
|
122
|
+
</View>
|
|
123
|
+
</Modal>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export default DefaultColumnMenu;
|