@controleonline/ui-default 1.0.264 → 1.0.265
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/AGENTS.md +3 -2
- package/package.json +21 -18
- package/src/react/components/errors/DefaultErrors.js +64 -82
- package/src/react/components/filters/CompactFilterSelector.js +58 -23
- package/src/react/components/filters/CompactFilterSelector.styles.js +17 -5
- package/src/react/components/filters/DefaultColumnFilter.js +177 -45
- package/src/react/components/filters/DefaultExternalFilters.js +201 -143
- package/src/react/components/filters/DefaultSearch.js +27 -25
- package/src/react/components/form/DefaultForm.js +72 -53
- package/src/react/components/form/DefaultForm.styles.js +71 -66
- package/src/react/components/inputs/DefaultDateInput.js +150 -0
- package/src/react/components/inputs/DefaultInput.js +44 -11
- package/src/react/components/inputs/DefaultInput.styles.js +6 -0
- package/src/react/components/inputs/DefaultSelect.js +200 -43
- package/src/react/components/inputs/defaultInputUtils.js +40 -19
- package/src/react/components/table/DefaultColumnMenu.js +108 -0
- package/src/react/components/table/DefaultDebug.js +233 -0
- package/src/react/components/table/DefaultFiltersModal.js +142 -0
- package/src/react/components/table/DefaultModalButton.js +18 -0
- package/src/react/components/table/DefaultSearchModal.js +49 -0
- package/src/react/components/table/DefaultTable.js +350 -2025
- package/src/react/components/table/DefaultTable.styles.js +217 -97
- package/src/react/components/table/DefaultTable.utils.js +502 -0
- package/src/react/components/table/DefaultTableBody.js +26 -0
- package/src/react/components/table/DefaultTableCards.js +171 -0
- package/src/react/components/table/DefaultTableControls.js +208 -0
- package/src/react/components/table/DefaultTableEmptyState.js +22 -0
- package/src/react/components/table/DefaultTableFooter.js +172 -0
- package/src/react/components/table/DefaultTableInput.js +145 -0
- package/src/react/components/table/DefaultTableRows.js +340 -0
- package/src/react/components/table/DefaultTableSearch.js +100 -0
- package/src/react/components/table/DefaultTableToolbar.js +98 -0
- package/src/react/components/table/DefaultToolbarAction.js +56 -0
- package/src/react/components/table/useDefaultTablePagination.js +370 -0
- package/src/react/components/table/useDefaultTableSorting.js +126 -0
- package/src/react/components/table/useDefaultTableTheme.js +58 -0
- package/src/react/utils/tableVisibleColumnsPreferences.js +239 -211
- package/src/store/default/actions.js +51 -13
- package/src/store/default/getters.js +10 -8
- package/src/store/default/mutation_types.js +4 -2
- package/src/store/default/mutations.js +10 -1
- package/src/tests/react/components/form/DefaultForm.test.js +81 -0
- package/src/tests/react/components/inputs/DefaultSelect.test.js +106 -14
- package/src/tests/react/components/table/DefaultTable.test.js +945 -96
- package/src/tests/react/store/defaultActions.test.js +59 -0
- package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +247 -168
|
@@ -1,2069 +1,394 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
TouchableOpacity,
|
|
9
|
-
View,
|
|
10
|
-
useWindowDimensions,
|
|
11
|
-
} from 'react-native';
|
|
12
|
-
import { useIsFocused } from '@react-navigation/native';
|
|
13
|
-
import Icon from 'react-native-vector-icons/Feather';
|
|
14
|
-
import { getAllStores, useStore } from '@store';
|
|
15
|
-
import { useMessage } from '@controleonline/ui-common/src/react/components/MessageService';
|
|
16
|
-
import Formatter from '@controleonline/ui-common/src/utils/formatter.js';
|
|
17
|
-
import StateStore from '@controleonline/ui-layout/src/react/components/StateStore';
|
|
18
|
-
import { getDateRange } from '@controleonline/ui-common/src/react/utils/dateRangeFilter';
|
|
19
|
-
import { formatStoreColumnLabel } from '@controleonline/ui-common/src/react/utils/storeColumns';
|
|
20
|
-
import { resolveThemePalette } from '@controleonline/../../src/styles/branding';
|
|
21
|
-
import { colors } from '@controleonline/../../src/styles/colors';
|
|
22
|
-
import DefaultColumnFilter from '../filters/DefaultColumnFilter';
|
|
23
|
-
import DefaultSearch from '../filters/DefaultSearch';
|
|
24
|
-
import DefaultForm from '../form/DefaultForm';
|
|
25
|
-
import DefaultInput from '../inputs/DefaultInput';
|
|
1
|
+
import React, { useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { View, useWindowDimensions } from 'react-native';
|
|
3
|
+
import { useIsFocused, useRoute } from '@react-navigation/native';
|
|
4
|
+
import { useStore } from '@store';
|
|
5
|
+
import { useMessage } from '@controleonline/ui-common/src/react/components/MessageService';
|
|
6
|
+
import { normalizeText } from '../inputs/defaultInputUtils';
|
|
7
|
+
import { DEFAULT_COMPACT_BREAKPOINT, isObject, stableSerialize } from './DefaultTable.utils';
|
|
26
8
|
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
import {
|
|
38
|
-
persistTableSortPreference,
|
|
39
|
-
persistTableViewModePreference,
|
|
40
|
-
persistVisibleColumnsPreference,
|
|
41
|
-
resolveStoredTableSortPreference,
|
|
42
|
-
resolveStoredTableViewModePreference,
|
|
43
|
-
resolveStoredVisibleColumnsPreference,
|
|
44
|
-
sanitizeVisibleColumnsPreference,
|
|
45
|
-
} from '../../utils/tableVisibleColumnsPreferences';
|
|
9
|
+
resolveDefaultTablePreferenceScope,
|
|
10
|
+
resolveStoredTableFiltersPreference,
|
|
11
|
+
resolveStoredTableViewModePreference,
|
|
12
|
+
resolveStoredVisibleColumnsPreference,
|
|
13
|
+
sanitizeTableFiltersPreference,
|
|
14
|
+
sanitizeVisibleColumnsPreference,
|
|
15
|
+
} from '../../utils/tableVisibleColumnsPreferences';
|
|
16
|
+
import DefaultTableBody from './DefaultTableBody';
|
|
17
|
+
import DefaultTableFooter from './DefaultTableFooter';
|
|
18
|
+
import DefaultTableToolbar from './DefaultTableToolbar';
|
|
46
19
|
import styles from './DefaultTable.styles';
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
normalizeText(list).split('/')[1] || 'getItems';
|
|
65
|
-
|
|
66
|
-
const COMPANY_SCOPED_LIST_STORES = new Set([
|
|
67
|
-
'categories',
|
|
68
|
-
'paymentType',
|
|
69
|
-
'wallet',
|
|
70
|
-
]);
|
|
71
|
-
|
|
72
|
-
const resolveListLoadParams = ({currentCompanyId, listStoreName}) => {
|
|
73
|
-
if (!currentCompanyId || !COMPANY_SCOPED_LIST_STORES.has(listStoreName)) {
|
|
74
|
-
return {};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return listStoreName === 'categories'
|
|
78
|
-
? {company: currentCompanyId}
|
|
79
|
-
: {people: currentCompanyId};
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export const resolveColumnListLoadParams = ({
|
|
83
|
-
column,
|
|
84
|
-
currentCompanyId,
|
|
85
|
-
requestParams = {},
|
|
86
|
-
}) => {
|
|
87
|
-
const listStoreName = resolveStoreNameFromList(column?.list);
|
|
88
|
-
const companyScopedParams = resolveListLoadParams({
|
|
89
|
-
currentCompanyId,
|
|
90
|
-
listStoreName,
|
|
91
|
-
});
|
|
92
|
-
const resolvedCustomParams = typeof column?.listRequestParams === 'function'
|
|
93
|
-
? column.listRequestParams({currentCompanyId, requestParams})
|
|
94
|
-
: column?.listRequestParams;
|
|
95
|
-
const customParams =
|
|
96
|
-
resolvedCustomParams &&
|
|
97
|
-
typeof resolvedCustomParams === 'object' &&
|
|
98
|
-
!Array.isArray(resolvedCustomParams)
|
|
99
|
-
? resolvedCustomParams
|
|
100
|
-
: {};
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
...companyScopedParams,
|
|
104
|
-
...customParams,
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const isObject = value =>
|
|
109
|
-
value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
110
|
-
|
|
111
|
-
const getRowKey = (row, index = 0) =>
|
|
112
|
-
String(row?.['@id'] || row?.id || index);
|
|
113
|
-
|
|
114
|
-
const stableSerialize = value => {
|
|
115
|
-
if (value === null || value === undefined) {
|
|
116
|
-
return 'null';
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (Array.isArray(value)) {
|
|
120
|
-
return `[${value.map(item => stableSerialize(item)).join(',')}]`;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (value instanceof Date) {
|
|
124
|
-
return JSON.stringify(value.toISOString());
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (isObject(value)) {
|
|
128
|
-
return `{${Object.keys(value)
|
|
129
|
-
.sort()
|
|
130
|
-
.map(key => `${JSON.stringify(key)}:${stableSerialize(value[key])}`)
|
|
131
|
-
.join(',')}}`;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return JSON.stringify(value);
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const resolveDateRangeQuery = value => {
|
|
138
|
-
if (!value || typeof value !== 'object') {
|
|
139
|
-
return {};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const shortcut = value.shortcut || value.value || 'all';
|
|
143
|
-
const customRange = value.customRange || { from: '', to: '' };
|
|
144
|
-
const dateRange = getDateRange(shortcut, customRange, {
|
|
145
|
-
relativeMode: 'rolling',
|
|
146
|
-
useCurrentMoment: true,
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
return {
|
|
150
|
-
after: dateRange?.after || '',
|
|
151
|
-
before: dateRange?.before || '',
|
|
152
|
-
};
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const resolveFilterQueryValue = value => {
|
|
156
|
-
if (Array.isArray(value)) {
|
|
157
|
-
return value
|
|
158
|
-
.map(item => resolveFilterQueryValue(item))
|
|
159
|
-
.filter(item => item !== '' && item !== null && item !== undefined);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (value && typeof value === 'object') {
|
|
163
|
-
return resolveFilterQueryValue(
|
|
164
|
-
value.value ?? value.id ?? value['@id'] ?? value.key ?? '',
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return normalizeText(value);
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const normalizeCollectionItems = response => {
|
|
172
|
-
if (Array.isArray(response)) return response;
|
|
173
|
-
if (Array.isArray(response?.member)) return response.member;
|
|
174
|
-
if (Array.isArray(response?.['hydra:member'])) return response['hydra:member'];
|
|
175
|
-
|
|
176
|
-
return [];
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const resolveHasMore = ({ hasMore, dataLength, totalItems }) => {
|
|
180
|
-
if (hasMore !== null && hasMore !== undefined) {
|
|
181
|
-
return hasMore;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const resolvedTotalItems = Number(totalItems);
|
|
185
|
-
if (!Number.isFinite(resolvedTotalItems)) {
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return dataLength < resolvedTotalItems;
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
const humanizeSummaryLabel = value =>
|
|
193
|
-
normalizeText(value)
|
|
194
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
195
|
-
.replace(/[._-]+/g, ' ')
|
|
196
|
-
.replace(/\s+/g, ' ')
|
|
197
|
-
.trim();
|
|
198
|
-
|
|
199
|
-
const isMoneySummaryPath = path =>
|
|
200
|
-
/(amount|price|total|value|paid|open|receivable|payable|pending)/i.test(
|
|
201
|
-
Array.isArray(path) ? path.join('.') : normalizeText(path),
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
const normalizeSummaryMoneyValue = value => {
|
|
205
|
-
if (typeof value === 'number') return Number.isFinite(value) ? value : 0;
|
|
206
|
-
|
|
207
|
-
const rawValue = normalizeText(value).replace(/[^0-9,.-]/g, '');
|
|
208
|
-
if (!rawValue) return 0;
|
|
209
|
-
|
|
210
|
-
const normalizedValue = rawValue.includes(',')
|
|
211
|
-
? rawValue.replace(/\./g, '').replace(',', '.')
|
|
212
|
-
: rawValue;
|
|
213
|
-
const parsedValue = Number(normalizedValue);
|
|
214
|
-
|
|
215
|
-
return Number.isFinite(parsedValue) ? parsedValue : 0;
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
const getSummaryOperations = column => {
|
|
219
|
-
if (typeof column?.summary === 'string') return [column.summary];
|
|
220
|
-
if (Array.isArray(column?.summary)) return column.summary;
|
|
221
|
-
if (isObject(column?.summary)) {
|
|
222
|
-
return Object.entries(column.summary)
|
|
223
|
-
.filter(([, value]) => value)
|
|
224
|
-
.map(([operation]) => operation);
|
|
20
|
+
import { useDefaultTablePagination } from './useDefaultTablePagination';
|
|
21
|
+
import {
|
|
22
|
+
useDefaultTableSortedData,
|
|
23
|
+
useDefaultTableSortState,
|
|
24
|
+
} from './useDefaultTableSorting';
|
|
25
|
+
import useDefaultTableTheme from './useDefaultTableTheme';
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
mergeSortedDataWithLiveItems,
|
|
29
|
+
resolveColumnListLoadParams,
|
|
30
|
+
shouldTriggerEndReachedFromScroll,
|
|
31
|
+
} from './DefaultTable.utils';
|
|
32
|
+
|
|
33
|
+
const publishStoreValue = (store, actionName, value, getterName) => {
|
|
34
|
+
if (typeof store?.actions?.[actionName] === 'function') {
|
|
35
|
+
store.actions[actionName](value);
|
|
36
|
+
return;
|
|
225
37
|
}
|
|
226
38
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const getSummaryField = (column, operation) => {
|
|
231
|
-
if (isObject(column?.summary)) {
|
|
232
|
-
const summaryField = column.summary[operation];
|
|
233
|
-
if (typeof summaryField === 'string') return summaryField;
|
|
39
|
+
if (store?.getters) {
|
|
40
|
+
store.getters[getterName] = value;
|
|
234
41
|
}
|
|
235
|
-
|
|
236
|
-
return getColumnKey(column);
|
|
237
42
|
};
|
|
238
43
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (shouldFormatMoney) {
|
|
244
|
-
return Formatter.formatMoney(normalizeSummaryMoneyValue(value));
|
|
44
|
+
const assignGetterValue = (store, getterName, value) => {
|
|
45
|
+
if (store?.getters) {
|
|
46
|
+
store.getters[getterName] = value;
|
|
245
47
|
}
|
|
246
|
-
|
|
247
|
-
if (column) {
|
|
248
|
-
return resolveCellText({
|
|
249
|
-
column,
|
|
250
|
-
columns,
|
|
251
|
-
row: { [columnKey]: value },
|
|
252
|
-
storeName,
|
|
253
|
-
value,
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return normalizeText(value);
|
|
258
48
|
};
|
|
259
49
|
|
|
260
|
-
const
|
|
261
|
-
|
|
50
|
+
const DefaultTable = ({
|
|
51
|
+
accentColor = null,
|
|
52
|
+
actions = {},
|
|
53
|
+
add = null,
|
|
54
|
+
compactBreakpoint = DEFAULT_COMPACT_BREAKPOINT,
|
|
55
|
+
columns = [],
|
|
56
|
+
data = undefined,
|
|
57
|
+
filters = {},
|
|
58
|
+
footerComponent = null,
|
|
59
|
+
forceCardsOnCompact = true,
|
|
60
|
+
getOptionsForColumn = null,
|
|
61
|
+
hasMore = null,
|
|
62
|
+
initialViewMode = 'table',
|
|
63
|
+
isLoading = false,
|
|
64
|
+
onAdd = null,
|
|
65
|
+
onDataLoaded = null,
|
|
66
|
+
onEditRow = null,
|
|
67
|
+
onEndReached = null,
|
|
68
|
+
onFilterChange = null,
|
|
69
|
+
onMomentumScrollBegin = null,
|
|
70
|
+
onRowPress = null,
|
|
71
|
+
onSaved = null,
|
|
72
|
+
onScrollBeginDrag = null,
|
|
73
|
+
onSortChange = null,
|
|
74
|
+
pageSize = null,
|
|
75
|
+
renderCard = null,
|
|
76
|
+
requestParams = {},
|
|
77
|
+
rowActionsComponent = null,
|
|
78
|
+
rowStyle = null,
|
|
79
|
+
showColumnFiltersButton = true,
|
|
80
|
+
showRowActions = true,
|
|
81
|
+
showTotalItemsInCompactToolbar = false,
|
|
82
|
+
showTotalItemsInFooter = true,
|
|
83
|
+
sort = null,
|
|
84
|
+
storeName = '',
|
|
85
|
+
summary = undefined,
|
|
262
86
|
summaryLabels = {},
|
|
263
|
-
|
|
264
|
-
|
|
87
|
+
toolbarActions = [],
|
|
88
|
+
visibleColumnsPreferenceKey = '',
|
|
265
89
|
}) => {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return Object.entries(value).flatMap(([key, childValue]) =>
|
|
281
|
-
flattenSummaryEntries({
|
|
282
|
-
path: [...path, key],
|
|
283
|
-
summaryLabels,
|
|
284
|
-
usedPaths,
|
|
285
|
-
value: childValue,
|
|
286
|
-
}),
|
|
287
|
-
);
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
const isSortableColumn = column => column?.sortable === true;
|
|
291
|
-
|
|
292
|
-
const getSortField = column => column?.sortField || getColumnKey(column);
|
|
293
|
-
|
|
294
|
-
const resolveDefaultSort = columns => {
|
|
295
|
-
if (!Array.isArray(columns)) {
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
for (const column of columns) {
|
|
300
|
-
if (!column || column?.defaultSort === undefined || column?.defaultSort === null || column?.defaultSort === false) {
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const field = getSortField(column);
|
|
305
|
-
const defaultSort = column.defaultSort;
|
|
306
|
-
|
|
307
|
-
if (defaultSort && typeof defaultSort === 'object' && !Array.isArray(defaultSort)) {
|
|
308
|
-
const resolvedDirection = normalizeText(defaultSort.direction || defaultSort.order || 'desc').toLowerCase();
|
|
309
|
-
const resolvedField = normalizeText(
|
|
310
|
-
defaultSort.field || defaultSort.sortField || defaultSort.key || defaultSort.name || field,
|
|
311
|
-
);
|
|
312
|
-
|
|
313
|
-
return {
|
|
314
|
-
direction: resolvedDirection === 'asc' ? 'asc' : 'desc',
|
|
315
|
-
field: resolvedField || field,
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
if (typeof defaultSort === 'string') {
|
|
320
|
-
const normalizedSort = normalizeText(defaultSort).toLowerCase();
|
|
321
|
-
if (normalizedSort === 'asc' || normalizedSort === 'desc') {
|
|
322
|
-
return {
|
|
323
|
-
direction: normalizedSort,
|
|
324
|
-
field,
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return {
|
|
329
|
-
direction: 'desc',
|
|
330
|
-
field: normalizeText(defaultSort) || field,
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (defaultSort === true) {
|
|
335
|
-
return {
|
|
336
|
-
direction: 'asc',
|
|
337
|
-
field,
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
return null;
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
const sanitizeStoredSortPreference = ({
|
|
346
|
-
columns = [],
|
|
347
|
-
fallbackSort = null,
|
|
348
|
-
sort = null,
|
|
349
|
-
}) => {
|
|
350
|
-
const normalizedFallback =
|
|
351
|
-
fallbackSort &&
|
|
352
|
-
typeof fallbackSort === 'object' &&
|
|
353
|
-
typeof fallbackSort.field === 'string' &&
|
|
354
|
-
fallbackSort.field.trim()
|
|
355
|
-
? {
|
|
356
|
-
direction: fallbackSort.direction === 'asc' ? 'asc' : 'desc',
|
|
357
|
-
field: fallbackSort.field.trim(),
|
|
358
|
-
}
|
|
359
|
-
: null;
|
|
360
|
-
|
|
361
|
-
if (
|
|
362
|
-
!sort ||
|
|
363
|
-
typeof sort !== 'object' ||
|
|
364
|
-
typeof sort.field !== 'string' ||
|
|
365
|
-
!sort.field.trim()
|
|
366
|
-
) {
|
|
367
|
-
return normalizedFallback;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
const normalizedDirection = sort.direction === 'asc' ? 'asc' : 'desc';
|
|
371
|
-
const normalizedField = sort.field.trim();
|
|
372
|
-
const sortableFields = new Set(
|
|
373
|
-
(Array.isArray(columns) ? columns : [])
|
|
374
|
-
.filter(isSortableColumn)
|
|
375
|
-
.map(column => getSortField(column))
|
|
376
|
-
.filter(Boolean),
|
|
377
|
-
);
|
|
378
|
-
|
|
379
|
-
if (!sortableFields.has(normalizedField)) {
|
|
380
|
-
return normalizedFallback;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return {
|
|
384
|
-
direction: normalizedDirection,
|
|
385
|
-
field: normalizedField,
|
|
386
|
-
};
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
const readValueByPath = (object, path) => {
|
|
390
|
-
if (!object || !path) return object;
|
|
391
|
-
|
|
392
|
-
return String(path)
|
|
393
|
-
.split('.')
|
|
394
|
-
.reduce((currentValue, key) => {
|
|
395
|
-
if (currentValue === null || currentValue === undefined) return currentValue;
|
|
396
|
-
return currentValue?.[key];
|
|
397
|
-
}, object);
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
const normalizeSortText = value =>
|
|
401
|
-
normalizeText(value)
|
|
402
|
-
.normalize('NFD')
|
|
403
|
-
.replace(/[\u0300-\u036f]/g, '')
|
|
404
|
-
.toLowerCase();
|
|
405
|
-
|
|
406
|
-
const isDateLikeColumn = column =>
|
|
407
|
-
column?.inputType === 'date' ||
|
|
408
|
-
column?.inputType === 'date-range' ||
|
|
409
|
-
column?.type === 'date' ||
|
|
410
|
-
column?.type === 'range-date' ||
|
|
411
|
-
/date/i.test(getColumnKey(column));
|
|
412
|
-
|
|
413
|
-
const resolveSortComparable = ({ column, row, storeName, columns }) => {
|
|
414
|
-
const fieldName = getColumnKey(column);
|
|
415
|
-
const sortField = getSortField(column);
|
|
416
|
-
const rawValue = sortField === fieldName ? row?.[fieldName] : readValueByPath(row, sortField);
|
|
417
|
-
|
|
418
|
-
if (isDateLikeColumn(column)) {
|
|
419
|
-
const dateValue =
|
|
420
|
-
rawValue && typeof rawValue === 'object'
|
|
421
|
-
? rawValue?.value ??
|
|
422
|
-
rawValue?.date ??
|
|
423
|
-
rawValue?.createdAt ??
|
|
424
|
-
rawValue?.updatedAt ??
|
|
425
|
-
rawValue?.['@id'] ??
|
|
426
|
-
rawValue?.[fieldName] ??
|
|
427
|
-
rawValue
|
|
428
|
-
: rawValue;
|
|
429
|
-
const parsedDate = Date.parse(dateValue);
|
|
430
|
-
return Number.isFinite(parsedDate) ? parsedDate : Number.NEGATIVE_INFINITY;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
const resolvedValue = sortField === fieldName
|
|
434
|
-
? resolveCellText({
|
|
435
|
-
column,
|
|
436
|
-
columns,
|
|
437
|
-
row,
|
|
438
|
-
storeName,
|
|
439
|
-
})
|
|
440
|
-
: normalizeText(rawValue ?? resolveCellText({
|
|
441
|
-
column,
|
|
442
|
-
columns,
|
|
443
|
-
row,
|
|
90
|
+
const { width } = useWindowDimensions();
|
|
91
|
+
const route = useRoute?.();
|
|
92
|
+
const store = useStore(storeName);
|
|
93
|
+
const isFocused = useIsFocused();
|
|
94
|
+
const configsSignatureRef = useRef('');
|
|
95
|
+
const { showError } = useMessage() || {};
|
|
96
|
+
const { themeColors } = useDefaultTableTheme(accentColor);
|
|
97
|
+
const tablePreferenceScope = useMemo(
|
|
98
|
+
() =>
|
|
99
|
+
resolveDefaultTablePreferenceScope({
|
|
100
|
+
preferenceKey: visibleColumnsPreferenceKey,
|
|
101
|
+
route,
|
|
444
102
|
storeName,
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
const normalizedNumber = Number(
|
|
448
|
-
String(resolvedValue).replace(/[^0-9,.-]/g, '').replace(',', '.'),
|
|
103
|
+
}),
|
|
104
|
+
[route?.key, route?.name, storeName, visibleColumnsPreferenceKey],
|
|
449
105
|
);
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
106
|
+
const storedViewMode = useMemo(
|
|
107
|
+
() => resolveStoredTableViewModePreference(tablePreferenceScope, null),
|
|
108
|
+
[initialViewMode, tablePreferenceScope],
|
|
109
|
+
);
|
|
110
|
+
const resolvedActions = useMemo(
|
|
111
|
+
() => ({
|
|
112
|
+
...(store?.actions || {}),
|
|
113
|
+
...(actions || {}),
|
|
114
|
+
}),
|
|
115
|
+
[actions, store?.actions],
|
|
116
|
+
);
|
|
117
|
+
const autoMode = data === undefined && normalizeText(storeName) !== '';
|
|
118
|
+
const storeColumns = Array.isArray(store?.getters?.columns) ? store.getters.columns : [];
|
|
119
|
+
const columnsForTable = storeColumns.length > 0 ? storeColumns : columns;
|
|
120
|
+
const storeFilters = isObject(store?.getters?.filters) ? store.getters.filters : {};
|
|
121
|
+
const requestParamsSeed = isObject(requestParams) ? requestParams : {};
|
|
122
|
+
const resolvedTotalItems = store?.getters?.totalItems;
|
|
123
|
+
const currentConfigs = store?.getters?.configs || {};
|
|
124
|
+
const isCompactView = width > 0 && width <= compactBreakpoint;
|
|
125
|
+
|
|
126
|
+
if (storeColumns.length === 0 && Array.isArray(columns) && columns.length > 0) {
|
|
127
|
+
assignGetterValue(store, 'columns', columns);
|
|
453
128
|
}
|
|
454
129
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
const getColumnStyle = column => {
|
|
459
|
-
const key = getColumnKey(column);
|
|
460
|
-
if (column?.isIdentity) return [styles.cell, styles.identityCell];
|
|
461
|
-
if (['price', 'total', 'amount', 'value'].includes(key)) {
|
|
462
|
-
return [styles.cell, styles.moneyCell];
|
|
130
|
+
if (data !== undefined && Array.isArray(data)) {
|
|
131
|
+
assignGetterValue(store, 'items', data);
|
|
463
132
|
}
|
|
464
|
-
return styles.cell;
|
|
465
|
-
};
|
|
466
133
|
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
134
|
+
const { requestSort, resolvedSort } = useDefaultTableSortState({
|
|
135
|
+
autoMode,
|
|
136
|
+
columnsForTable,
|
|
137
|
+
onSortChange,
|
|
138
|
+
sort,
|
|
139
|
+
tablePreferenceScope,
|
|
140
|
+
});
|
|
141
|
+
const {
|
|
142
|
+
buildRequestQuery,
|
|
143
|
+
currentPage,
|
|
144
|
+
handleEndReached,
|
|
145
|
+
resolvedData,
|
|
146
|
+
} = useDefaultTablePagination({
|
|
147
|
+
autoMode,
|
|
148
|
+
columnsForTable,
|
|
149
|
+
data,
|
|
150
|
+
filters: storeFilters,
|
|
151
|
+
hasMore,
|
|
152
|
+
isFocused,
|
|
153
|
+
isLoading,
|
|
154
|
+
onEndReached,
|
|
155
|
+
pageSize,
|
|
156
|
+
requestParams: requestParamsSeed,
|
|
157
|
+
resolvedActions,
|
|
158
|
+
resolvedSort,
|
|
159
|
+
resolvedTotalItems,
|
|
160
|
+
showError,
|
|
161
|
+
store,
|
|
162
|
+
storeName,
|
|
163
|
+
});
|
|
164
|
+
const sortedData = useDefaultTableSortedData({
|
|
165
|
+
resolvedData,
|
|
166
|
+
resolvedSort,
|
|
167
|
+
storeName,
|
|
168
|
+
tableColumns: columnsForTable,
|
|
169
|
+
});
|
|
170
|
+
const debugFallbackParameters = useMemo(() => {
|
|
171
|
+
if (autoMode) {
|
|
172
|
+
return buildRequestQuery(currentPage || 1, false);
|
|
173
|
+
}
|
|
475
174
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
175
|
+
return {
|
|
176
|
+
filters: storeFilters,
|
|
177
|
+
requestParams: requestParamsSeed,
|
|
178
|
+
sort: resolvedSort || null,
|
|
179
|
+
};
|
|
180
|
+
}, [autoMode, buildRequestQuery, currentPage, requestParamsSeed, resolvedSort, storeFilters]);
|
|
181
|
+
const effectiveViewMode =
|
|
182
|
+
currentConfigs.viewMode ||
|
|
183
|
+
storedViewMode ||
|
|
184
|
+
(isCompactView && forceCardsOnCompact !== false ? 'cards' : initialViewMode);
|
|
185
|
+
const tableFiltersVisible = Boolean(currentConfigs.tableFiltersVisible);
|
|
186
|
+
const defaultTableConfigs = useMemo(
|
|
187
|
+
() => ({
|
|
188
|
+
add,
|
|
189
|
+
compactBreakpoint,
|
|
190
|
+
debugFallbackParameters,
|
|
191
|
+
effectiveViewMode,
|
|
192
|
+
filters,
|
|
193
|
+
footerComponent,
|
|
194
|
+
forceCardsOnCompact,
|
|
195
|
+
getOptionsForColumn,
|
|
196
|
+
initialViewMode,
|
|
197
|
+
onAdd,
|
|
198
|
+
onDataLoaded,
|
|
199
|
+
onEditRow,
|
|
200
|
+
onEndReached: handleEndReached,
|
|
201
|
+
onFilterChange,
|
|
202
|
+
onMomentumScrollBegin,
|
|
203
|
+
onRowPress,
|
|
204
|
+
onSaved,
|
|
205
|
+
onScrollBeginDrag,
|
|
206
|
+
renderCard,
|
|
207
|
+
requestParams: requestParamsSeed,
|
|
208
|
+
requestSort,
|
|
209
|
+
resolvedSort,
|
|
210
|
+
rowActionsComponent,
|
|
211
|
+
rowStyle,
|
|
212
|
+
showColumnFiltersButton,
|
|
213
|
+
showRowActions,
|
|
214
|
+
showTotalItemsInCompactToolbar,
|
|
215
|
+
showTotalItemsInFooter,
|
|
216
|
+
sortedData,
|
|
217
|
+
summary,
|
|
218
|
+
summaryLabels,
|
|
219
|
+
tableFiltersVisible,
|
|
220
|
+
tablePreferenceScope,
|
|
221
|
+
toolbarActions,
|
|
222
|
+
viewMode: effectiveViewMode,
|
|
223
|
+
}),
|
|
224
|
+
[
|
|
225
|
+
add,
|
|
226
|
+
compactBreakpoint,
|
|
227
|
+
debugFallbackParameters,
|
|
228
|
+
effectiveViewMode,
|
|
229
|
+
filters,
|
|
230
|
+
footerComponent,
|
|
231
|
+
forceCardsOnCompact,
|
|
232
|
+
getOptionsForColumn,
|
|
233
|
+
handleEndReached,
|
|
234
|
+
initialViewMode,
|
|
235
|
+
onAdd,
|
|
236
|
+
onDataLoaded,
|
|
237
|
+
onEditRow,
|
|
238
|
+
onFilterChange,
|
|
239
|
+
onMomentumScrollBegin,
|
|
240
|
+
onRowPress,
|
|
241
|
+
onSaved,
|
|
242
|
+
onScrollBeginDrag,
|
|
243
|
+
renderCard,
|
|
244
|
+
requestParamsSeed,
|
|
245
|
+
requestSort,
|
|
246
|
+
resolvedSort,
|
|
247
|
+
rowActionsComponent,
|
|
248
|
+
rowStyle,
|
|
249
|
+
showColumnFiltersButton,
|
|
250
|
+
showRowActions,
|
|
251
|
+
showTotalItemsInCompactToolbar,
|
|
252
|
+
showTotalItemsInFooter,
|
|
253
|
+
sortedData,
|
|
254
|
+
summary,
|
|
255
|
+
summaryLabels,
|
|
256
|
+
tableFiltersVisible,
|
|
257
|
+
tablePreferenceScope,
|
|
258
|
+
toolbarActions,
|
|
259
|
+
],
|
|
260
|
+
);
|
|
261
|
+
const defaultTableConfigsSignature = useMemo(
|
|
553
262
|
() =>
|
|
554
|
-
|
|
555
|
-
|
|
263
|
+
stableSerialize({
|
|
264
|
+
add,
|
|
265
|
+
compactBreakpoint,
|
|
266
|
+
debugFallbackParameters,
|
|
267
|
+
effectiveViewMode,
|
|
268
|
+
filters,
|
|
269
|
+
forceCardsOnCompact,
|
|
556
270
|
initialViewMode,
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
[
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
const modalCloseIconColor = themeColors.modalCloseIcon;
|
|
586
|
-
const modalHeaderTextColor = themeColors.modalHeaderText;
|
|
587
|
-
const modalOverlayColor = themeColors.modalOverlay;
|
|
588
|
-
const modalTextColor = themeColors.modalText;
|
|
589
|
-
const checkboxBorderColor = themeColors.checkboxBorder;
|
|
590
|
-
const checkboxSelectedMarkColor = themeColors.checkboxSelectedMark;
|
|
591
|
-
const toolbarBackgroundColor = themeColors.toolbarBackground;
|
|
592
|
-
const toolbarBorderColor = themeColors.toolbarBorder;
|
|
593
|
-
const toolbarCountBackgroundColor = themeColors.badgeBackground;
|
|
594
|
-
const toolbarCountTextColor = themeColors.badgeText;
|
|
595
|
-
const tableActionBackgroundColor = themeColors.tableActionBackground;
|
|
596
|
-
const tableActionBorderColor = themeColors.tableActionBorder;
|
|
597
|
-
const tableActionTextColor = themeColors.tableActionIcon;
|
|
598
|
-
const tableButtonBackgroundColor = themeColors.buttonBackground;
|
|
599
|
-
const tableButtonBorderColor = themeColors.buttonBorder;
|
|
600
|
-
const tableButtonIconColor = themeColors.buttonIcon;
|
|
601
|
-
const tableButtonPressedBackgroundColor = themeColors.buttonPressedBackground;
|
|
602
|
-
const tableButtonPressedBorderColor = themeColors.buttonPressedBorder;
|
|
603
|
-
const tableButtonPressedIconColor = themeColors.buttonPressedIcon;
|
|
604
|
-
const tableButtonTextColor = themeColors.buttonText;
|
|
605
|
-
const tableFilterBackgroundColor = themeColors.tableFilterBackground;
|
|
606
|
-
const tableFilterBorderColor = themeColors.tableFilterBorder;
|
|
607
|
-
const tableFilterTextColor = themeColors.tableFilterText;
|
|
608
|
-
const isFocused = useIsFocused();
|
|
609
|
-
const {showError} = useMessage() || {};
|
|
610
|
-
const autoMode = data === undefined && normalizeText(storeName) !== '';
|
|
611
|
-
const searchKey = searchProps?.searchKey || 'search';
|
|
612
|
-
const storeActions = store?.actions || {};
|
|
613
|
-
const resolvedActions = useMemo(
|
|
614
|
-
() => ({
|
|
615
|
-
...storeActions,
|
|
616
|
-
...(actions || {}),
|
|
617
|
-
}),
|
|
618
|
-
[actions, storeActions],
|
|
619
|
-
);
|
|
620
|
-
const storeColumns = Array.isArray(store?.getters?.columns) ? store.getters.columns : [];
|
|
621
|
-
const columnsForTable = storeColumns.length > 0 ? storeColumns : columns;
|
|
622
|
-
const storeFilters = isObject(store?.getters?.filters) ? store.getters.filters : {};
|
|
623
|
-
const requestParamsSeed = isObject(requestParams) ? requestParams : {};
|
|
624
|
-
const initialFiltersSeed = autoMode
|
|
625
|
-
? (Object.keys(filters || {}).length > 0 ? filters : storeFilters)
|
|
626
|
-
: (isObject(filters) ? filters : {});
|
|
627
|
-
const [autoFilters, setAutoFilters] = useState(() => initialFiltersSeed);
|
|
628
|
-
const defaultSortSeed = useMemo(
|
|
629
|
-
() => resolveDefaultSort(columnsForTable),
|
|
630
|
-
[columnsForTable],
|
|
631
|
-
);
|
|
632
|
-
const storedSortSeed = useMemo(
|
|
633
|
-
() =>
|
|
634
|
-
sanitizeStoredSortPreference({
|
|
635
|
-
columns: columnsForTable,
|
|
636
|
-
fallbackSort: sort || defaultSortSeed || null,
|
|
637
|
-
sort: resolveStoredTableSortPreference(visibleColumnsPreferenceKey),
|
|
638
|
-
}),
|
|
639
|
-
[columnsForTable, defaultSortSeed, sort, visibleColumnsPreferenceKey],
|
|
640
|
-
);
|
|
641
|
-
const [autoSort, setAutoSort] = useState(() => storedSortSeed);
|
|
642
|
-
const [autoHasLoaded, setAutoHasLoaded] = useState(false);
|
|
643
|
-
const [autoLoading, setAutoLoading] = useState(false);
|
|
644
|
-
const [autoLoadingMore, setAutoLoadingMore] = useState(false);
|
|
645
|
-
const [autoLastPageCount, setAutoLastPageCount] = useState(0);
|
|
646
|
-
const autoRequestIdRef = useRef(0);
|
|
647
|
-
const autoLoadedQueryKeyRef = useRef('');
|
|
648
|
-
const autoErroredQueryKeyRef = useRef('');
|
|
649
|
-
const autoPageRef = useRef(0);
|
|
650
|
-
const pageSizeNumber = Number(requestParamsSeed.itemsPerPage || pageSize || 50) || 50;
|
|
651
|
-
const resolvedSort = autoMode ? autoSort : sort;
|
|
652
|
-
const resolvedFilters = autoMode ? autoFilters : (filters || {});
|
|
653
|
-
const resolvedSearchValue = normalizeText(resolvedFilters?.[searchKey]);
|
|
654
|
-
const resolvedGetOptionsForColumn = useCallback(
|
|
655
|
-
column => {
|
|
656
|
-
const explicitOptions = getOptionsForColumn?.(column);
|
|
657
|
-
if (Array.isArray(explicitOptions)) return explicitOptions;
|
|
658
|
-
|
|
659
|
-
const columnKey = getColumnKey(column);
|
|
660
|
-
return Array.isArray(listOptionsByColumn[columnKey])
|
|
661
|
-
? listOptionsByColumn[columnKey]
|
|
662
|
-
: undefined;
|
|
663
|
-
},
|
|
664
|
-
[getOptionsForColumn, listOptionsByColumn],
|
|
665
|
-
);
|
|
666
|
-
|
|
667
|
-
useEffect(() => {
|
|
668
|
-
setListOptionsByColumn({});
|
|
669
|
-
loadedListStoresRef.current.clear();
|
|
670
|
-
}, [currentCompany?.id]);
|
|
671
|
-
|
|
672
|
-
const loadListOptionsForColumns = useCallback(
|
|
673
|
-
(targetColumns = []) => {
|
|
674
|
-
const columnsToLoad = (Array.isArray(targetColumns) ? targetColumns : []).filter(
|
|
675
|
-
column => normalizeText(column?.list),
|
|
676
|
-
);
|
|
677
|
-
|
|
678
|
-
if (columnsToLoad.length === 0) {
|
|
679
|
-
return Promise.resolve([]);
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
const stores = getAllStores?.() || {};
|
|
683
|
-
const loadPromises = [];
|
|
684
|
-
|
|
685
|
-
columnsToLoad.forEach(column => {
|
|
686
|
-
const explicitOptions = getOptionsForColumn?.(column);
|
|
687
|
-
if (Array.isArray(explicitOptions)) {
|
|
688
|
-
return;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
const listStoreName = resolveStoreNameFromList(column.list);
|
|
692
|
-
const actionName = resolveListActionName(column.list);
|
|
693
|
-
const listStore = stores?.[listStoreName];
|
|
694
|
-
const listAction = listStore?.actions?.[actionName];
|
|
695
|
-
|
|
696
|
-
const listLoadParams = resolveColumnListLoadParams({
|
|
697
|
-
column,
|
|
698
|
-
currentCompanyId: currentCompany?.id,
|
|
699
|
-
requestParams: requestParamsSeed,
|
|
700
|
-
});
|
|
701
|
-
const isCompanyScopedList = Object.keys(listLoadParams).length > 0;
|
|
702
|
-
|
|
703
|
-
if (!listStoreName || typeof listAction !== 'function') {
|
|
704
|
-
return;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
if (
|
|
708
|
-
!isCompanyScopedList &&
|
|
709
|
-
Array.isArray(listStore?.getters?.items) &&
|
|
710
|
-
listStore.getters.items.length > 0
|
|
711
|
-
) {
|
|
712
|
-
const columnKey = getColumnKey(column);
|
|
713
|
-
setListOptionsByColumn(current => ({
|
|
714
|
-
...current,
|
|
715
|
-
[columnKey]: normalizeCollectionItems(listStore.getters.items),
|
|
716
|
-
}));
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
const columnKey = getColumnKey(column);
|
|
721
|
-
const loadKey = `${columnKey}:${listStoreName}:${actionName}:${stableSerialize(listLoadParams)}`;
|
|
722
|
-
if (loadedListStoresRef.current.has(loadKey)) {
|
|
723
|
-
return;
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
loadedListStoresRef.current.add(loadKey);
|
|
727
|
-
loadPromises.push(
|
|
728
|
-
Promise.resolve(
|
|
729
|
-
listAction({
|
|
730
|
-
...listLoadParams,
|
|
731
|
-
itemsPerPage: LIST_OPTIONS_PAGE_SIZE,
|
|
732
|
-
__storeMeta: {
|
|
733
|
-
dedupeKey: `default-table-list-options:${loadKey}`,
|
|
734
|
-
skipSystemError: true,
|
|
735
|
-
},
|
|
736
|
-
}),
|
|
737
|
-
)
|
|
738
|
-
.then(response => ({columnKey, items: normalizeCollectionItems(response)}))
|
|
739
|
-
.catch(() => {
|
|
740
|
-
loadedListStoresRef.current.delete(loadKey);
|
|
741
|
-
return {columnKey, items: []};
|
|
742
|
-
}),
|
|
743
|
-
);
|
|
744
|
-
});
|
|
745
|
-
|
|
746
|
-
if (loadPromises.length === 0) {
|
|
747
|
-
return Promise.resolve([]);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
return Promise.all(loadPromises).then(results => {
|
|
751
|
-
const nextOptionsByColumn = Object.fromEntries(
|
|
752
|
-
results.map(result => [result.columnKey, result.items]),
|
|
753
|
-
);
|
|
754
|
-
|
|
755
|
-
if (Object.keys(nextOptionsByColumn).length > 0) {
|
|
756
|
-
setListOptionsByColumn(current => ({
|
|
757
|
-
...current,
|
|
758
|
-
...nextOptionsByColumn,
|
|
759
|
-
}));
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
return results;
|
|
763
|
-
});
|
|
764
|
-
},
|
|
765
|
-
[currentCompany?.id, getOptionsForColumn, requestParamsSeed],
|
|
766
|
-
);
|
|
767
|
-
|
|
768
|
-
const buildRequestQuery = useCallback(
|
|
769
|
-
(page, append = false) => {
|
|
770
|
-
const query = {
|
|
771
|
-
...requestParamsSeed,
|
|
772
|
-
itemsPerPage: pageSizeNumber,
|
|
773
|
-
page,
|
|
774
|
-
};
|
|
775
|
-
|
|
776
|
-
if (autoSort?.field && autoSort?.direction) {
|
|
777
|
-
query[`order[${autoSort.field}]`] = autoSort.direction;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
Object.entries(autoFilters || {}).forEach(([fieldName, value]) => {
|
|
781
|
-
if (!fieldName) return;
|
|
782
|
-
|
|
783
|
-
if (fieldName === searchKey) {
|
|
784
|
-
const normalizedSearch = normalizeText(value).replace(/^#/, '');
|
|
785
|
-
if (normalizedSearch) {
|
|
786
|
-
query.search = normalizedSearch;
|
|
787
|
-
if (searchKey !== 'search') {
|
|
788
|
-
query[searchKey] = normalizedSearch;
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
return;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
const column = columnsForTable.find(item => getColumnKey(item) === fieldName);
|
|
795
|
-
|
|
796
|
-
if (column?.inputType === 'date-range' || column?.type === 'range-date') {
|
|
797
|
-
const dateRange = resolveDateRangeQuery(value);
|
|
798
|
-
if (dateRange.after) {
|
|
799
|
-
query[`${fieldName}[after]`] = dateRange.after;
|
|
800
|
-
}
|
|
801
|
-
if (dateRange.before) {
|
|
802
|
-
query[`${fieldName}[before]`] = dateRange.before;
|
|
803
|
-
}
|
|
804
|
-
return;
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
const normalizedValue = resolveFilterQueryValue(value);
|
|
808
|
-
if (Array.isArray(normalizedValue)) {
|
|
809
|
-
if (normalizedValue.length > 0) {
|
|
810
|
-
query[fieldName] = normalizedValue;
|
|
811
|
-
}
|
|
812
|
-
return;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
if (normalizedValue !== '') {
|
|
816
|
-
query[fieldName] = normalizedValue;
|
|
817
|
-
}
|
|
818
|
-
});
|
|
819
|
-
|
|
820
|
-
if (append) {
|
|
821
|
-
query.append = true;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
return query;
|
|
825
|
-
},
|
|
826
|
-
[autoFilters, autoSort?.direction, autoSort?.field, columnsForTable, pageSizeNumber, requestParamsSeed, searchKey],
|
|
827
|
-
);
|
|
828
|
-
const autoQuerySignature = useMemo(
|
|
829
|
-
() =>
|
|
830
|
-
stableSerialize({
|
|
831
|
-
filters: autoFilters,
|
|
832
|
-
pageSize: pageSizeNumber,
|
|
833
|
-
requestParams: requestParamsSeed,
|
|
834
|
-
searchKey,
|
|
835
|
-
sort: autoSort,
|
|
836
|
-
}),
|
|
837
|
-
[autoFilters, autoSort, pageSizeNumber, requestParamsSeed, searchKey],
|
|
838
|
-
);
|
|
839
|
-
|
|
840
|
-
const loadAutoPage = useCallback(
|
|
841
|
-
(page, { append = false } = {}) => {
|
|
842
|
-
if (!autoMode || typeof resolvedActions.getItems !== 'function') {
|
|
843
|
-
return Promise.resolve([]);
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
const requestId = autoRequestIdRef.current + 1;
|
|
847
|
-
autoRequestIdRef.current = requestId;
|
|
848
|
-
|
|
849
|
-
if (append) {
|
|
850
|
-
setAutoLoadingMore(true);
|
|
851
|
-
} else {
|
|
852
|
-
setAutoLoading(true);
|
|
853
|
-
setAutoHasLoaded(false);
|
|
854
|
-
setAutoLastPageCount(0);
|
|
855
|
-
autoPageRef.current = 0;
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
const query = buildRequestQuery(page, append);
|
|
859
|
-
|
|
860
|
-
return Promise.resolve(resolvedActions.getItems(query))
|
|
861
|
-
.then(response => {
|
|
862
|
-
if (autoRequestIdRef.current !== requestId) {
|
|
863
|
-
return response;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
const pageItems = normalizeCollectionItems(response);
|
|
867
|
-
autoPageRef.current = page;
|
|
868
|
-
autoLoadedQueryKeyRef.current = autoQuerySignature;
|
|
869
|
-
autoErroredQueryKeyRef.current = '';
|
|
870
|
-
setAutoHasLoaded(true);
|
|
871
|
-
setAutoLastPageCount(pageItems.length);
|
|
872
|
-
return pageItems;
|
|
873
|
-
})
|
|
874
|
-
.catch(error => {
|
|
875
|
-
if (autoRequestIdRef.current === requestId) {
|
|
876
|
-
autoErroredQueryKeyRef.current = autoQuerySignature;
|
|
877
|
-
showError?.(error?.message || 'Nao foi possivel carregar os registros.');
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
return [];
|
|
881
|
-
})
|
|
882
|
-
.finally(() => {
|
|
883
|
-
if (autoRequestIdRef.current === requestId) {
|
|
884
|
-
setAutoLoading(false);
|
|
885
|
-
setAutoLoadingMore(false);
|
|
886
|
-
endReachedLockRef.current = false;
|
|
887
|
-
}
|
|
888
|
-
});
|
|
889
|
-
},
|
|
890
|
-
[autoMode, autoQuerySignature, buildRequestQuery, resolvedActions, showError],
|
|
891
|
-
);
|
|
892
|
-
|
|
893
|
-
const availableColumns = useMemo(
|
|
894
|
-
() => columnsForTable.filter(column => shouldIncludeColumn(column)),
|
|
895
|
-
[columnsForTable],
|
|
896
|
-
);
|
|
897
|
-
|
|
898
|
-
useEffect(() => {
|
|
899
|
-
setVisibleColumns(prev =>
|
|
900
|
-
stableSerialize(prev) === stableSerialize(visibleColumnsSeed)
|
|
901
|
-
? prev
|
|
902
|
-
: visibleColumnsSeed
|
|
903
|
-
);
|
|
904
|
-
}, [visibleColumnsSeed]);
|
|
905
|
-
|
|
906
|
-
useEffect(() => {
|
|
907
|
-
setViewMode(viewModeSeed);
|
|
908
|
-
}, [viewModeSeed]);
|
|
909
|
-
|
|
910
|
-
useEffect(() => {
|
|
911
|
-
if (!autoMode) return;
|
|
912
|
-
|
|
913
|
-
setAutoSort(prev =>
|
|
914
|
-
stableSerialize(prev) === stableSerialize(storedSortSeed)
|
|
915
|
-
? prev
|
|
916
|
-
: storedSortSeed,
|
|
917
|
-
);
|
|
918
|
-
}, [autoMode, storedSortSeed]);
|
|
919
|
-
|
|
920
|
-
useEffect(() => {
|
|
921
|
-
if (!autoMode) return;
|
|
922
|
-
|
|
923
|
-
setAutoFilters(prev => {
|
|
924
|
-
if (stableSerialize(prev) === stableSerialize(storeFilters)) {
|
|
925
|
-
return prev;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
return storeFilters;
|
|
929
|
-
});
|
|
930
|
-
}, [autoMode, storeFilters]);
|
|
931
|
-
|
|
932
|
-
useEffect(() => {
|
|
933
|
-
if (!autoMode || !isFocused) return;
|
|
934
|
-
if (typeof resolvedActions.getItems !== 'function') return;
|
|
935
|
-
if (
|
|
936
|
-
autoLoading ||
|
|
937
|
-
autoLoadingMore ||
|
|
938
|
-
autoLoadedQueryKeyRef.current === autoQuerySignature ||
|
|
939
|
-
autoErroredQueryKeyRef.current === autoQuerySignature
|
|
940
|
-
) {
|
|
941
|
-
return;
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
endReachedLockRef.current = false;
|
|
945
|
-
loadAutoPage(1, { append: false });
|
|
946
|
-
}, [
|
|
947
|
-
autoLoading,
|
|
948
|
-
autoLoadingMore,
|
|
949
|
-
autoMode,
|
|
950
|
-
autoQuerySignature,
|
|
951
|
-
isFocused,
|
|
952
|
-
loadAutoPage,
|
|
953
|
-
resolvedActions,
|
|
954
|
-
]);
|
|
955
|
-
|
|
956
|
-
const tableColumns = useMemo(
|
|
957
|
-
() => columnsForTable.filter(column => shouldIncludeColumn(column) && visibleColumns[getColumnKey(column)] !== false),
|
|
958
|
-
[columnsForTable, visibleColumns],
|
|
959
|
-
);
|
|
960
|
-
|
|
961
|
-
const editableColumns = useMemo(
|
|
962
|
-
() => tableColumns.filter(isEditableColumn),
|
|
963
|
-
[tableColumns],
|
|
964
|
-
);
|
|
965
|
-
|
|
966
|
-
const activeFilterCount = useMemo(
|
|
967
|
-
() => Object.values(resolvedFilters || {}).filter(value => normalizeText(value) !== '').length,
|
|
968
|
-
[resolvedFilters],
|
|
969
|
-
);
|
|
970
|
-
const hasRowActions =
|
|
971
|
-
showRowActions !== false &&
|
|
972
|
-
(editableColumns.length > 0 || typeof onEditRow === 'function');
|
|
973
|
-
const storeAddConfig = store?.getters?.add;
|
|
974
|
-
const addConfig = add !== null && add !== undefined ? add : storeAddConfig;
|
|
975
|
-
const hasAddInstruction = addConfig === true || (isObject(addConfig) && addConfig.enabled !== false);
|
|
976
|
-
const shouldRenderAddButton =
|
|
977
|
-
hasAddInstruction &&
|
|
978
|
-
(typeof onAdd === 'function' || typeof resolvedActions.save === 'function');
|
|
979
|
-
const resolvedIsLoading = autoMode ? (autoLoading || autoLoadingMore) : Boolean(isLoading);
|
|
980
|
-
const resolvedData = autoMode
|
|
981
|
-
? (autoHasLoaded && Array.isArray(store?.getters?.items) ? store.getters.items : [])
|
|
982
|
-
: (Array.isArray(data) ? data : []);
|
|
983
|
-
const tableMinimumWidth = useMemo(
|
|
984
|
-
() =>
|
|
985
|
-
tableColumns.reduce(
|
|
986
|
-
(totalWidth, column) => totalWidth + getColumnMinWidth(column),
|
|
987
|
-
hasRowActions ? ACTIONS_CELL_WIDTH : 0,
|
|
988
|
-
),
|
|
989
|
-
[hasRowActions, tableColumns],
|
|
271
|
+
resolvedSort,
|
|
272
|
+
showColumnFiltersButton,
|
|
273
|
+
showRowActions,
|
|
274
|
+
showTotalItemsInCompactToolbar,
|
|
275
|
+
showTotalItemsInFooter,
|
|
276
|
+
storedViewMode,
|
|
277
|
+
tableFiltersVisible,
|
|
278
|
+
sortedDataLength: sortedData.length,
|
|
279
|
+
toolbarActionsLength: Array.isArray(toolbarActions) ? toolbarActions.length : 0,
|
|
280
|
+
}),
|
|
281
|
+
[
|
|
282
|
+
add,
|
|
283
|
+
compactBreakpoint,
|
|
284
|
+
debugFallbackParameters,
|
|
285
|
+
effectiveViewMode,
|
|
286
|
+
filters,
|
|
287
|
+
forceCardsOnCompact,
|
|
288
|
+
initialViewMode,
|
|
289
|
+
resolvedSort,
|
|
290
|
+
showColumnFiltersButton,
|
|
291
|
+
showRowActions,
|
|
292
|
+
showTotalItemsInCompactToolbar,
|
|
293
|
+
showTotalItemsInFooter,
|
|
294
|
+
storedViewMode,
|
|
295
|
+
tableFiltersVisible,
|
|
296
|
+
sortedData.length,
|
|
297
|
+
toolbarActions,
|
|
298
|
+
],
|
|
990
299
|
);
|
|
991
|
-
const tableWidth = Math.max(tableContainerWidth, tableMinimumWidth);
|
|
992
|
-
const tableLayoutStyle = useMemo(
|
|
993
|
-
() => (tableWidth > 0 ? { minWidth: tableWidth, width: tableWidth } : null),
|
|
994
|
-
[tableWidth],
|
|
995
|
-
);
|
|
996
|
-
const isCompactView = width > 0 && width <= compactBreakpoint;
|
|
997
|
-
const shouldForceCardsOnCompact = forceCardsOnCompact !== false;
|
|
998
|
-
const effectiveViewMode =
|
|
999
|
-
isCompactView && shouldForceCardsOnCompact
|
|
1000
|
-
? (compactViewMode || 'cards')
|
|
1001
|
-
: viewMode;
|
|
1002
|
-
useEffect(() => {
|
|
1003
|
-
if (!shouldForceCardsOnCompact) {
|
|
1004
|
-
setCompactViewMode(null);
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
if (isCompactView) {
|
|
1009
|
-
setCompactViewMode('cards');
|
|
1010
|
-
return;
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
setCompactViewMode(null);
|
|
1014
|
-
}, [isCompactView, shouldForceCardsOnCompact]);
|
|
1015
|
-
const emptyStateLabel = resolvedIsLoading
|
|
1016
|
-
? global.t?.t(storeName, 'label', 'loading') || 'Carregando...'
|
|
1017
|
-
: 'Nenhum registro encontrado';
|
|
1018
|
-
const storeTotalItems = store?.getters?.totalItems;
|
|
1019
|
-
const resolvedTotalItems = totalItems !== null && totalItems !== undefined
|
|
1020
|
-
? totalItems
|
|
1021
|
-
: storeTotalItems;
|
|
1022
|
-
const totalItemsNumber = Number(resolvedTotalItems);
|
|
1023
|
-
const shouldRenderTotalItems =
|
|
1024
|
-
resolvedTotalItems !== null &&
|
|
1025
|
-
resolvedTotalItems !== undefined &&
|
|
1026
|
-
Number.isFinite(totalItemsNumber);
|
|
1027
|
-
const shouldRenderFooterTotalItems =
|
|
1028
|
-
shouldRenderTotalItems &&
|
|
1029
|
-
showTotalItemsInFooter !== false;
|
|
1030
|
-
const shouldRenderCompactToolbarTotalItems =
|
|
1031
|
-
showTotalItemsInCompactToolbar === true &&
|
|
1032
|
-
isCompactView &&
|
|
1033
|
-
shouldRenderTotalItems;
|
|
1034
|
-
const resolvedTotalItemsText =
|
|
1035
|
-
normalizeText(totalItemsText) !== ''
|
|
1036
|
-
? totalItemsText
|
|
1037
|
-
: shouldRenderTotalItems
|
|
1038
|
-
? `${totalItemsNumber} ${totalItemsLabel || global.t?.t(storeName, 'label', 'items') || 'registros'}`
|
|
1039
|
-
: '';
|
|
1040
|
-
const storeSummary = store?.getters?.summary;
|
|
1041
|
-
const resolvedSummary = summary !== null && summary !== undefined ? summary : storeSummary;
|
|
1042
|
-
const shouldReadSummary = resolvedSummary !== false && isObject(resolvedSummary);
|
|
1043
|
-
const summaryEntries = useMemo(() => {
|
|
1044
|
-
if (!shouldReadSummary) return [];
|
|
1045
|
-
|
|
1046
|
-
const labels = summaryLabels || {};
|
|
1047
|
-
const usedPaths = new Set();
|
|
1048
|
-
const columnEntries = tableColumns.flatMap(column => {
|
|
1049
|
-
const operations = getSummaryOperations(column);
|
|
1050
|
-
if (!operations.length) return [];
|
|
1051
|
-
|
|
1052
|
-
const columnLabel = formatStoreColumnLabel({
|
|
1053
|
-
columns: columnsForTable,
|
|
1054
|
-
fieldName: getColumnKey(column),
|
|
1055
|
-
fallbackLabel: column?.label || getColumnKey(column),
|
|
1056
|
-
storeName,
|
|
1057
|
-
});
|
|
1058
|
-
|
|
1059
|
-
return operations.map(operation => {
|
|
1060
|
-
const fieldName = getSummaryField(column, operation);
|
|
1061
|
-
const path = [operation, fieldName];
|
|
1062
|
-
const pathKey = path.join('.');
|
|
1063
|
-
const value = resolvedSummary?.[operation]?.[fieldName];
|
|
1064
|
-
if (value === undefined) return null;
|
|
1065
300
|
|
|
1066
|
-
|
|
301
|
+
if (store?.getters) {
|
|
302
|
+
assignGetterValue(store, 'configs', defaultTableConfigs);
|
|
303
|
+
}
|
|
1067
304
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
value,
|
|
1073
|
-
column,
|
|
1074
|
-
};
|
|
1075
|
-
}).filter(Boolean);
|
|
1076
|
-
});
|
|
305
|
+
useEffect(() => {
|
|
306
|
+
if (storeColumns.length > 0 || !Array.isArray(columns) || columns.length === 0) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
1077
309
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
usedPaths,
|
|
1081
|
-
value: resolvedSummary,
|
|
1082
|
-
});
|
|
310
|
+
publishStoreValue(store, 'setColumns', columns, 'columns');
|
|
311
|
+
}, [columns, store, storeColumns.length]);
|
|
1083
312
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
);
|
|
1089
|
-
}, [columnsForTable, resolvedSummary, shouldReadSummary, storeName, summaryLabels, tableColumns]);
|
|
1090
|
-
const shouldRenderFooterBar =
|
|
1091
|
-
(shouldRenderFooterTotalItems && !shouldRenderCompactToolbarTotalItems) ||
|
|
1092
|
-
summaryEntries.length > 0;
|
|
1093
|
-
const footerProps = {
|
|
1094
|
-
columns: columnsForTable,
|
|
1095
|
-
resolvedAccentColor,
|
|
1096
|
-
resolvedTotalItemsText,
|
|
1097
|
-
shouldRenderCompactToolbarTotalItems,
|
|
1098
|
-
shouldRenderFooterTotalItems,
|
|
1099
|
-
storeName,
|
|
1100
|
-
summaryEntries,
|
|
1101
|
-
summaryLabels,
|
|
1102
|
-
tableBorderColor,
|
|
1103
|
-
tableMutedColor,
|
|
1104
|
-
tableSurfaceColor,
|
|
1105
|
-
tableTextColor,
|
|
1106
|
-
toolbarCountBackgroundColor,
|
|
1107
|
-
toolbarCountTextColor,
|
|
1108
|
-
};
|
|
1109
|
-
|
|
1110
|
-
const sortedData = useMemo(() => {
|
|
1111
|
-
const items = Array.isArray(resolvedData) ? [...resolvedData] : [];
|
|
1112
|
-
const sortField = resolvedSort?.field;
|
|
1113
|
-
const sortDirection = resolvedSort?.direction === 'desc' ? 'desc' : 'asc';
|
|
1114
|
-
const sortColumn = tableColumns.find(column => getSortField(column) === sortField);
|
|
313
|
+
useEffect(() => {
|
|
314
|
+
if (data === undefined || !Array.isArray(data)) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
1115
317
|
|
|
1116
|
-
|
|
318
|
+
publishStoreValue(store, 'setItems', data, 'items');
|
|
319
|
+
}, [data, store]);
|
|
1117
320
|
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
row: left,
|
|
1123
|
-
storeName,
|
|
1124
|
-
});
|
|
1125
|
-
const rightValue = resolveSortComparable({
|
|
1126
|
-
column: sortColumn,
|
|
1127
|
-
columns: tableColumns,
|
|
1128
|
-
row: right,
|
|
1129
|
-
storeName,
|
|
1130
|
-
});
|
|
321
|
+
useEffect(() => {
|
|
322
|
+
if (!columnsForTable.length) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
1131
325
|
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
326
|
+
const storedVisibleColumns = resolveStoredVisibleColumnsPreference(tablePreferenceScope);
|
|
327
|
+
if (!storedVisibleColumns) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
1136
330
|
|
|
1137
|
-
|
|
331
|
+
const nextVisibleColumns = sanitizeVisibleColumnsPreference({
|
|
332
|
+
columns: columnsForTable,
|
|
333
|
+
visibleColumns: storedVisibleColumns,
|
|
1138
334
|
});
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
const resolvedHasMore = useMemo(
|
|
1142
|
-
() => {
|
|
1143
|
-
if (autoMode) {
|
|
1144
|
-
if (Number.isFinite(Number(resolvedTotalItems)) && Number(resolvedTotalItems) > 0) {
|
|
1145
|
-
return sortedData.length < Number(resolvedTotalItems);
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
return autoLastPageCount >= pageSizeNumber && sortedData.length > 0;
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
return resolveHasMore({
|
|
1152
|
-
hasMore,
|
|
1153
|
-
dataLength: sortedData.length,
|
|
1154
|
-
totalItems: resolvedTotalItems,
|
|
1155
|
-
});
|
|
1156
|
-
},
|
|
1157
|
-
[autoLastPageCount, autoMode, hasMore, pageSizeNumber, resolvedTotalItems, sortedData.length],
|
|
1158
|
-
);
|
|
1159
|
-
|
|
1160
|
-
useEffect(() => {
|
|
1161
|
-
const nextPaginationState = {
|
|
1162
|
-
dataLength: sortedData.length,
|
|
1163
|
-
filtersKey: stableSerialize(resolvedFilters || {}),
|
|
1164
|
-
sortDirection: resolvedSort?.direction,
|
|
1165
|
-
sortField: resolvedSort?.field,
|
|
1166
|
-
};
|
|
1167
|
-
|
|
1168
|
-
const previousPaginationState = previousPaginationStateRef.current;
|
|
1169
|
-
const didPaginationStateChange =
|
|
1170
|
-
previousPaginationState.dataLength !== nextPaginationState.dataLength ||
|
|
1171
|
-
previousPaginationState.filtersKey !== nextPaginationState.filtersKey ||
|
|
1172
|
-
previousPaginationState.sortDirection !== nextPaginationState.sortDirection ||
|
|
1173
|
-
previousPaginationState.sortField !== nextPaginationState.sortField;
|
|
1174
|
-
|
|
1175
|
-
if (didPaginationStateChange) {
|
|
1176
|
-
endReachedLockRef.current = false;
|
|
1177
|
-
previousPaginationStateRef.current = nextPaginationState;
|
|
1178
|
-
}
|
|
1179
|
-
}, [resolvedFilters, resolvedSort?.direction, resolvedSort?.field, sortedData]);
|
|
1180
|
-
|
|
1181
|
-
useEffect(() => {
|
|
1182
|
-
if (typeof onDataLoaded !== 'function') {
|
|
1183
|
-
return;
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
onDataLoaded(sortedData);
|
|
1187
|
-
}, [onDataLoaded, sortedData]);
|
|
1188
|
-
|
|
1189
|
-
const beginEdit = useCallback((row, column) => {
|
|
1190
|
-
if (!isEditableColumn(column)) return;
|
|
1191
|
-
setEditingCell(`${row?.id || row?.['@id']}:${getColumnKey(column)}`);
|
|
1192
|
-
}, []);
|
|
335
|
+
const currentVisibleColumns = store?.getters?.visibleColumns || {};
|
|
1193
336
|
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
}, []);
|
|
1197
|
-
|
|
1198
|
-
const saveCell = useCallback((row, column, nextValue) => {
|
|
1199
|
-
const fieldName = getColumnKey(column);
|
|
1200
|
-
if (!fieldName || typeof resolvedActions.save !== 'function') {
|
|
1201
|
-
clearEdit();
|
|
1202
|
-
return Promise.resolve(null);
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
const currentValue = resolveEditValue(column, row);
|
|
1206
|
-
const normalizedNextValue = nextValue && typeof nextValue === 'object'
|
|
1207
|
-
? normalizeOptionKey(nextValue)
|
|
1208
|
-
: normalizeText(nextValue);
|
|
1209
|
-
|
|
1210
|
-
if (normalizeText(currentValue) === normalizeText(normalizedNextValue)) {
|
|
1211
|
-
clearEdit();
|
|
1212
|
-
return Promise.resolve(null);
|
|
337
|
+
if (stableSerialize(currentVisibleColumns) === stableSerialize(nextVisibleColumns)) {
|
|
338
|
+
return;
|
|
1213
339
|
}
|
|
1214
340
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
id: normalizeId(row?.['@id'] || row?.id),
|
|
1218
|
-
[fieldName]: formatSaveValue(column, nextValue, row),
|
|
1219
|
-
};
|
|
1220
|
-
|
|
1221
|
-
setSavingCell(cellKey);
|
|
1222
|
-
|
|
1223
|
-
return resolvedActions.save(payload)
|
|
1224
|
-
.then(savedItem => {
|
|
1225
|
-
onSaved?.(savedItem || { ...row, [fieldName]: nextValue }, row);
|
|
1226
|
-
return savedItem;
|
|
1227
|
-
})
|
|
1228
|
-
.catch(error => {
|
|
1229
|
-
console.error(error);
|
|
1230
|
-
return null;
|
|
1231
|
-
})
|
|
1232
|
-
.finally(() => {
|
|
1233
|
-
setSavingCell(null);
|
|
1234
|
-
clearEdit();
|
|
1235
|
-
});
|
|
1236
|
-
}, [clearEdit, onSaved, resolvedActions]);
|
|
1237
|
-
|
|
1238
|
-
const requestSort = useCallback(column => {
|
|
1239
|
-
if (!isSortableColumn(column)) return;
|
|
1240
|
-
|
|
1241
|
-
const fieldName = getSortField(column);
|
|
1242
|
-
const nextDirection =
|
|
1243
|
-
resolvedSort?.field === fieldName && resolvedSort?.direction === 'asc'
|
|
1244
|
-
? 'desc'
|
|
1245
|
-
: 'asc';
|
|
1246
|
-
const nextSort = {
|
|
1247
|
-
direction: nextDirection,
|
|
1248
|
-
field: fieldName,
|
|
1249
|
-
};
|
|
1250
|
-
|
|
1251
|
-
if (visibleColumnsPreferenceKey) {
|
|
1252
|
-
persistTableSortPreference(
|
|
1253
|
-
visibleColumnsPreferenceKey,
|
|
1254
|
-
nextSort,
|
|
1255
|
-
);
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
if (autoMode) {
|
|
1259
|
-
setAutoSort(nextSort);
|
|
1260
|
-
return;
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
onSortChange?.(nextSort);
|
|
1264
|
-
}, [
|
|
1265
|
-
autoMode,
|
|
1266
|
-
onSortChange,
|
|
1267
|
-
resolvedSort?.direction,
|
|
1268
|
-
resolvedSort?.field,
|
|
1269
|
-
visibleColumnsPreferenceKey,
|
|
1270
|
-
]);
|
|
341
|
+
publishStoreValue(store, 'setVisibleColumns', nextVisibleColumns, 'visibleColumns');
|
|
342
|
+
}, [columnsForTable, store, tablePreferenceScope]);
|
|
1271
343
|
|
|
1272
|
-
|
|
1273
|
-
if (
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
setFormMode('edit');
|
|
1279
|
-
setEditingRow(row);
|
|
1280
|
-
}, [onEditRow]);
|
|
1281
|
-
|
|
1282
|
-
const openAddForm = useCallback(() => {
|
|
1283
|
-
if (typeof onAdd === 'function') {
|
|
1284
|
-
onAdd();
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
if (typeof resolvedActions.save !== 'function') return;
|
|
1289
|
-
|
|
1290
|
-
setFormMode('create');
|
|
1291
|
-
setEditingRow({});
|
|
1292
|
-
}, [onAdd, resolvedActions]);
|
|
1293
|
-
|
|
1294
|
-
const closeEditModal = useCallback(() => {
|
|
1295
|
-
setEditingRow(null);
|
|
1296
|
-
setFormMode('edit');
|
|
1297
|
-
}, []);
|
|
1298
|
-
|
|
1299
|
-
const commitFilters = useCallback(nextFilters => {
|
|
1300
|
-
const resolvedNextFilters = isObject(nextFilters) ? nextFilters : {};
|
|
1301
|
-
|
|
1302
|
-
if (autoMode) {
|
|
1303
|
-
setAutoFilters(resolvedNextFilters);
|
|
1304
|
-
resolvedActions.setFilters?.(resolvedNextFilters);
|
|
1305
|
-
return;
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
onFilterChange?.(resolvedNextFilters);
|
|
1309
|
-
}, [autoMode, onFilterChange, resolvedActions]);
|
|
1310
|
-
|
|
1311
|
-
const updateFilter = useCallback((fieldName, value) => {
|
|
1312
|
-
const nextFilters = { ...(resolvedFilters || {}) };
|
|
1313
|
-
const isEmpty =
|
|
1314
|
-
value === null ||
|
|
1315
|
-
value === undefined ||
|
|
1316
|
-
normalizeText(value) === '' ||
|
|
1317
|
-
(Array.isArray(value) && value.length === 0);
|
|
1318
|
-
|
|
1319
|
-
if (isEmpty) delete nextFilters[fieldName];
|
|
1320
|
-
else nextFilters[fieldName] = value;
|
|
1321
|
-
|
|
1322
|
-
commitFilters(nextFilters);
|
|
1323
|
-
}, [commitFilters, resolvedFilters]);
|
|
1324
|
-
|
|
1325
|
-
const toggleColumn = useCallback(column => {
|
|
1326
|
-
const fieldName = getColumnKey(column);
|
|
1327
|
-
if (!fieldName) return;
|
|
1328
|
-
|
|
1329
|
-
setVisibleColumns(prev => {
|
|
1330
|
-
const next = {
|
|
1331
|
-
...sanitizeVisibleColumnsPreference({
|
|
1332
|
-
columns: columnsForTable,
|
|
1333
|
-
visibleColumns: prev,
|
|
1334
|
-
}),
|
|
1335
|
-
[fieldName]: prev[fieldName] === false,
|
|
1336
|
-
};
|
|
1337
|
-
|
|
1338
|
-
resolvedActions?.setVisibleColumns?.(next);
|
|
1339
|
-
if (visibleColumnsStorageKey) {
|
|
1340
|
-
persistVisibleColumnsPreference(
|
|
1341
|
-
visibleColumnsStorageKey,
|
|
1342
|
-
next,
|
|
1343
|
-
);
|
|
1344
|
-
}
|
|
1345
|
-
return next;
|
|
1346
|
-
});
|
|
1347
|
-
}, [
|
|
1348
|
-
resolvedActions,
|
|
1349
|
-
columnsForTable,
|
|
1350
|
-
visibleColumnsStorageKey,
|
|
1351
|
-
]);
|
|
1352
|
-
|
|
1353
|
-
const toggleViewMode = useCallback(() => {
|
|
1354
|
-
const currentViewMode =
|
|
1355
|
-
isCompactView && shouldForceCardsOnCompact
|
|
1356
|
-
? (compactViewMode || 'cards')
|
|
1357
|
-
: viewMode;
|
|
1358
|
-
const nextViewMode = currentViewMode === 'table' ? 'cards' : 'table';
|
|
1359
|
-
|
|
1360
|
-
if (isCompactView && shouldForceCardsOnCompact) {
|
|
1361
|
-
setCompactViewMode(nextViewMode);
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
setViewMode(nextViewMode);
|
|
1365
|
-
|
|
1366
|
-
if (!visibleColumnsPreferenceKey) {
|
|
1367
|
-
return;
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
persistTableViewModePreference(
|
|
1371
|
-
visibleColumnsPreferenceKey,
|
|
1372
|
-
nextViewMode,
|
|
1373
|
-
);
|
|
1374
|
-
}, [
|
|
1375
|
-
compactViewMode,
|
|
1376
|
-
isCompactView,
|
|
1377
|
-
shouldForceCardsOnCompact,
|
|
1378
|
-
viewMode,
|
|
1379
|
-
visibleColumnsPreferenceKey,
|
|
1380
|
-
]);
|
|
1381
|
-
|
|
1382
|
-
const handleEndReached = useCallback(() => {
|
|
1383
|
-
if (
|
|
1384
|
-
!resolvedHasMore ||
|
|
1385
|
-
resolvedIsLoading ||
|
|
1386
|
-
endReachedLockRef.current === true
|
|
1387
|
-
) {
|
|
1388
|
-
return;
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
endReachedLockRef.current = true;
|
|
1392
|
-
|
|
1393
|
-
if (autoMode) {
|
|
1394
|
-
const nextPage = autoPageRef.current + 1;
|
|
1395
|
-
loadAutoPage(nextPage, { append: true });
|
|
1396
|
-
return;
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
if (typeof onEndReached === 'function') {
|
|
1400
|
-
onEndReached();
|
|
1401
|
-
}
|
|
1402
|
-
}, [autoMode, loadAutoPage, onEndReached, resolvedHasMore, resolvedIsLoading]);
|
|
1403
|
-
|
|
1404
|
-
const handleLayout = useCallback(event => {
|
|
1405
|
-
const nextWidth = Math.floor(event?.nativeEvent?.layout?.width || 0);
|
|
1406
|
-
if (nextWidth > 0) setTableContainerWidth(nextWidth);
|
|
1407
|
-
}, []);
|
|
1408
|
-
|
|
1409
|
-
const renderEditableCell = (row, column) => {
|
|
1410
|
-
const fieldName = getColumnKey(column);
|
|
1411
|
-
const cellKey = `${row?.id || row?.['@id']}:${fieldName}`;
|
|
1412
|
-
const isEditing = editingCell === cellKey;
|
|
1413
|
-
const isSaving = savingCell === cellKey;
|
|
1414
|
-
const shouldDelegatePress =
|
|
1415
|
-
typeof onRowPress === 'function' &&
|
|
1416
|
-
!isEditableColumn(column);
|
|
1417
|
-
|
|
1418
|
-
return (
|
|
1419
|
-
<View
|
|
1420
|
-
style={[getColumnStyle(column), isEditing ? styles.editingCell : null]}
|
|
1421
|
-
pointerEvents={shouldDelegatePress ? 'none' : 'auto'}
|
|
1422
|
-
>
|
|
1423
|
-
<DefaultInput
|
|
1424
|
-
accentColor={resolvedAccentColor}
|
|
1425
|
-
column={column}
|
|
1426
|
-
columns={columnsForTable}
|
|
1427
|
-
editing={isEditing}
|
|
1428
|
-
getOptionsForColumn={resolvedGetOptionsForColumn}
|
|
1429
|
-
onBeforeOpen={() => loadListOptionsForColumns([column])}
|
|
1430
|
-
onCancelEditing={clearEdit}
|
|
1431
|
-
onSave={value => saveCell(row, column, value)}
|
|
1432
|
-
onStartEditing={() => beginEdit(row, column)}
|
|
1433
|
-
row={row}
|
|
1434
|
-
saving={isSaving}
|
|
1435
|
-
storeName={storeName}
|
|
1436
|
-
variant="cell"
|
|
1437
|
-
/>
|
|
1438
|
-
</View>
|
|
1439
|
-
);
|
|
1440
|
-
};
|
|
1441
|
-
|
|
1442
|
-
const renderColumnFilter = column => {
|
|
1443
|
-
return (
|
|
1444
|
-
<DefaultColumnFilter
|
|
1445
|
-
accentColor={resolvedAccentColor}
|
|
1446
|
-
column={column}
|
|
1447
|
-
filters={resolvedFilters}
|
|
1448
|
-
onBeforeOpen={column?.list ? () => loadListOptionsForColumns([column]) : null}
|
|
1449
|
-
getOptionsForColumn={resolvedGetOptionsForColumn}
|
|
1450
|
-
onChange={updateFilter}
|
|
1451
|
-
storeName={storeName}
|
|
1452
|
-
style={getColumnStyle(column)}
|
|
1453
|
-
/>
|
|
1454
|
-
);
|
|
1455
|
-
};
|
|
1456
|
-
|
|
1457
|
-
const renderToolbarAction = action => {
|
|
1458
|
-
if (!action || action.hidden) return null;
|
|
1459
|
-
|
|
1460
|
-
const isActive = action.active === true;
|
|
1461
|
-
const hasLabel = normalizeText(action.label) !== '';
|
|
1462
|
-
const actionColor = action.color || tableActionTextColor;
|
|
1463
|
-
|
|
1464
|
-
return (
|
|
1465
|
-
<TouchableOpacity
|
|
1466
|
-
key={action.key || action.icon || action.label}
|
|
1467
|
-
accessibilityRole="button"
|
|
1468
|
-
accessibilityLabel={action.accessibilityLabel || action.label || action.key || action.icon}
|
|
1469
|
-
style={[
|
|
1470
|
-
styles.toolbarButton,
|
|
1471
|
-
{ backgroundColor: tableActionBackgroundColor, borderColor: tableActionBorderColor },
|
|
1472
|
-
action.style,
|
|
1473
|
-
]}
|
|
1474
|
-
activeOpacity={0.82}
|
|
1475
|
-
disabled={action.disabled === true}
|
|
1476
|
-
onPress={action.onPress}
|
|
1477
|
-
>
|
|
1478
|
-
{action.icon ? (
|
|
1479
|
-
<Icon
|
|
1480
|
-
name={action.icon}
|
|
1481
|
-
size={action.iconSize || 14}
|
|
1482
|
-
color={actionColor}
|
|
1483
|
-
/>
|
|
1484
|
-
) : null}
|
|
1485
|
-
{hasLabel ? (
|
|
1486
|
-
<Text style={[styles.toolbarActionLabel, { color: actionColor }, action.labelStyle]} numberOfLines={1}>
|
|
1487
|
-
{action.label}
|
|
1488
|
-
</Text>
|
|
1489
|
-
) : null}
|
|
1490
|
-
{action.badge !== undefined && action.badge !== null ? (
|
|
1491
|
-
<Text style={[styles.toolbarBadgeText, { color: action.badgeColor || tableActionTextColor }]}>
|
|
1492
|
-
{action.badge}
|
|
1493
|
-
</Text>
|
|
1494
|
-
) : null}
|
|
1495
|
-
</TouchableOpacity>
|
|
1496
|
-
);
|
|
1497
|
-
};
|
|
1498
|
-
|
|
1499
|
-
const renderToolbarActions = () =>
|
|
1500
|
-
Array.isArray(toolbarActions) && toolbarActions.length > 0 ? (
|
|
1501
|
-
<View style={styles.toolbarActionGroup}>{toolbarActions.map(renderToolbarAction)}</View>
|
|
1502
|
-
) : null;
|
|
1503
|
-
|
|
1504
|
-
const getColumnByField = useCallback(
|
|
1505
|
-
fieldName => columnsForTable.find(column => getColumnKey(column) === fieldName),
|
|
1506
|
-
[columnsForTable],
|
|
1507
|
-
);
|
|
1508
|
-
|
|
1509
|
-
const buildRowHelpers = useCallback(
|
|
1510
|
-
row => {
|
|
1511
|
-
const openEdit = () => openEditModal(row);
|
|
1512
|
-
const openRow = typeof onRowPress === 'function' ? () => onRowPress(row) : null;
|
|
1513
|
-
const renderValue = (fieldName, fallback = '-') => {
|
|
1514
|
-
const column = getColumnByField(fieldName);
|
|
1515
|
-
if (!column) return fallback;
|
|
1516
|
-
return resolveCellText({ column, columns: columnsForTable, row, storeName });
|
|
1517
|
-
};
|
|
1518
|
-
const renderField = (fieldName, options = {}) => {
|
|
1519
|
-
const column = getColumnByField(fieldName);
|
|
1520
|
-
if (!column) return null;
|
|
1521
|
-
|
|
1522
|
-
const cellKey = `${row?.id || row?.['@id']}:${fieldName}`;
|
|
1523
|
-
const isEditing = editingCell === cellKey;
|
|
1524
|
-
const isSaving = savingCell === cellKey;
|
|
1525
|
-
|
|
1526
|
-
return (
|
|
1527
|
-
<DefaultInput
|
|
1528
|
-
accentColor={options.accentColor || resolvedAccentColor}
|
|
1529
|
-
column={column}
|
|
1530
|
-
columns={columnsForTable}
|
|
1531
|
-
containerStyle={options.containerStyle}
|
|
1532
|
-
displayValue={options.displayValue}
|
|
1533
|
-
editing={isEditing}
|
|
1534
|
-
getOptionsForColumn={resolvedGetOptionsForColumn}
|
|
1535
|
-
inputStyle={options.inputStyle}
|
|
1536
|
-
label={options.label}
|
|
1537
|
-
numberOfLines={options.numberOfLines}
|
|
1538
|
-
onBeforeOpen={() => loadListOptionsForColumns([column])}
|
|
1539
|
-
onCancelEditing={clearEdit}
|
|
1540
|
-
onSave={value => saveCell(row, column, value)}
|
|
1541
|
-
onStartEditing={() => beginEdit(row, column)}
|
|
1542
|
-
readTextStyle={options.readTextStyle || options.textStyle}
|
|
1543
|
-
row={row}
|
|
1544
|
-
saving={isSaving}
|
|
1545
|
-
showLabel={options.showLabel}
|
|
1546
|
-
storeName={storeName}
|
|
1547
|
-
variant={options.variant || 'card'}
|
|
1548
|
-
/>
|
|
1549
|
-
);
|
|
1550
|
-
};
|
|
1551
|
-
|
|
1552
|
-
return {
|
|
1553
|
-
openEdit,
|
|
1554
|
-
openRow,
|
|
1555
|
-
renderField,
|
|
1556
|
-
renderValue,
|
|
1557
|
-
};
|
|
1558
|
-
},
|
|
1559
|
-
[
|
|
1560
|
-
resolvedAccentColor,
|
|
1561
|
-
beginEdit,
|
|
1562
|
-
clearEdit,
|
|
1563
|
-
columnsForTable,
|
|
1564
|
-
editingCell,
|
|
1565
|
-
getColumnByField,
|
|
1566
|
-
resolvedGetOptionsForColumn,
|
|
1567
|
-
openEditModal,
|
|
1568
|
-
onRowPress,
|
|
1569
|
-
saveCell,
|
|
1570
|
-
savingCell,
|
|
1571
|
-
storeName,
|
|
1572
|
-
],
|
|
1573
|
-
);
|
|
1574
|
-
|
|
1575
|
-
const resolveRowStyle = useCallback(
|
|
1576
|
-
(row, index) => {
|
|
1577
|
-
if (typeof rowStyle === 'function') {
|
|
1578
|
-
return rowStyle(row, index);
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
return rowStyle;
|
|
1582
|
-
},
|
|
1583
|
-
[rowStyle],
|
|
1584
|
-
);
|
|
1585
|
-
|
|
1586
|
-
const renderCardItem = (row, index = 0) => {
|
|
1587
|
-
const helpers = buildRowHelpers(row);
|
|
1588
|
-
const rowStyleValue = resolveRowStyle(row, index);
|
|
1589
|
-
|
|
1590
|
-
if (typeof renderCard === 'function') {
|
|
1591
|
-
return (
|
|
1592
|
-
<View key={row?.['@id'] || row?.id} style={[styles.cardItem, rowStyleValue]}>
|
|
1593
|
-
{renderCard({
|
|
1594
|
-
item: row,
|
|
1595
|
-
openEdit: helpers.openEdit,
|
|
1596
|
-
openRow: helpers.openRow,
|
|
1597
|
-
renderField: helpers.renderField,
|
|
1598
|
-
renderValue: helpers.renderValue,
|
|
1599
|
-
row,
|
|
1600
|
-
})}
|
|
1601
|
-
{hasRowActions ? (
|
|
1602
|
-
<View style={styles.cardActions}>
|
|
1603
|
-
<TouchableOpacity
|
|
1604
|
-
style={[styles.iconButton, { borderColor: tableBorderColor, backgroundColor: tableSurfaceColor }]}
|
|
1605
|
-
activeOpacity={0.82}
|
|
1606
|
-
onPress={helpers.openEdit}>
|
|
1607
|
-
<Icon name="edit-2" size={14} color={tableMutedColor} />
|
|
1608
|
-
</TouchableOpacity>
|
|
1609
|
-
</View>
|
|
1610
|
-
) : null}
|
|
1611
|
-
</View>
|
|
1612
|
-
);
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
return (
|
|
1616
|
-
<View
|
|
1617
|
-
key={row?.['@id'] || row?.id}
|
|
1618
|
-
style={[
|
|
1619
|
-
styles.defaultCard,
|
|
1620
|
-
{ backgroundColor: tableSurfaceColor, borderColor: tableBorderColor },
|
|
1621
|
-
rowStyleValue,
|
|
1622
|
-
]}
|
|
1623
|
-
>
|
|
1624
|
-
{tableColumns.map(column => (
|
|
1625
|
-
<View key={getColumnKey(column)} style={styles.defaultCardLine}>
|
|
1626
|
-
<Text style={[styles.defaultCardLabel, { color: tableMutedColor }]}>
|
|
1627
|
-
{formatStoreColumnLabel({
|
|
1628
|
-
columns: columnsForTable,
|
|
1629
|
-
fieldName: getColumnKey(column),
|
|
1630
|
-
fallbackLabel: column?.label || getColumnKey(column),
|
|
1631
|
-
storeName,
|
|
1632
|
-
})}
|
|
1633
|
-
</Text>
|
|
1634
|
-
{helpers.renderField(getColumnKey(column), {
|
|
1635
|
-
readTextStyle: [styles.defaultCardValue, { color: tableTextColor }],
|
|
1636
|
-
numberOfLines: 1,
|
|
1637
|
-
})}
|
|
1638
|
-
</View>
|
|
1639
|
-
))}
|
|
1640
|
-
{hasRowActions ? (
|
|
1641
|
-
<TouchableOpacity
|
|
1642
|
-
style={[styles.cardEditButton, { borderColor: tableBorderColor, backgroundColor: tableSurfaceColor }]}
|
|
1643
|
-
activeOpacity={0.82}
|
|
1644
|
-
onPress={helpers.openEdit}>
|
|
1645
|
-
<Icon name="edit-2" size={14} color={tableMutedColor} />
|
|
1646
|
-
</TouchableOpacity>
|
|
1647
|
-
) : null}
|
|
1648
|
-
</View>
|
|
1649
|
-
);
|
|
1650
|
-
};
|
|
1651
|
-
|
|
1652
|
-
const renderEmptyState = isTable => {
|
|
1653
|
-
return (
|
|
1654
|
-
<View style={[styles.emptyBox, isTable ? tableLayoutStyle : null]}>
|
|
1655
|
-
{resolvedIsLoading ? (
|
|
1656
|
-
<StateStore compact loading={emptyStateLabel} />
|
|
1657
|
-
) : (
|
|
1658
|
-
<Text style={[styles.emptyText, { color: tableMutedColor }]}>{emptyStateLabel}</Text>
|
|
1659
|
-
)}
|
|
1660
|
-
</View>
|
|
1661
|
-
);
|
|
1662
|
-
};
|
|
1663
|
-
|
|
1664
|
-
const renderLoadingOverlay = () => {
|
|
1665
|
-
if (!resolvedIsLoading || sortedData.length === 0) {
|
|
1666
|
-
return null;
|
|
1667
|
-
}
|
|
1668
|
-
|
|
1669
|
-
return (
|
|
1670
|
-
<View pointerEvents="none" style={styles.loadingOverlay}>
|
|
1671
|
-
<View
|
|
1672
|
-
style={[
|
|
1673
|
-
styles.loadingOverlayCard,
|
|
1674
|
-
{ borderColor: tableBorderColor, backgroundColor: tableSurfaceColor },
|
|
1675
|
-
]}
|
|
1676
|
-
>
|
|
1677
|
-
<StateStore compact loading="Carregando mais registros..." />
|
|
1678
|
-
</View>
|
|
1679
|
-
</View>
|
|
1680
|
-
);
|
|
1681
|
-
};
|
|
1682
|
-
|
|
1683
|
-
const renderTableItem = ({ item: row, index }) => {
|
|
1684
|
-
const hasRowPress = typeof onRowPress === 'function';
|
|
1685
|
-
const RowComponent = hasRowPress ? TouchableOpacity : View;
|
|
1686
|
-
const rowStyleValue = resolveRowStyle(row, index);
|
|
1687
|
-
const rowPressProps = hasRowPress
|
|
1688
|
-
? {
|
|
1689
|
-
activeOpacity: 0.84,
|
|
1690
|
-
onPress: () => onRowPress(row),
|
|
1691
|
-
}
|
|
1692
|
-
: {};
|
|
1693
|
-
const rowBackgroundColor = index % 2 === 0 ? tableOddColor : tableEvenColor;
|
|
1694
|
-
|
|
1695
|
-
return (
|
|
1696
|
-
<RowComponent
|
|
1697
|
-
key={getRowKey(row)}
|
|
1698
|
-
style={[
|
|
1699
|
-
styles.row,
|
|
1700
|
-
tableLayoutStyle,
|
|
1701
|
-
{ backgroundColor: rowBackgroundColor, borderBottomColor: tableBorderColor },
|
|
1702
|
-
rowStyleValue,
|
|
1703
|
-
]}
|
|
1704
|
-
{...rowPressProps}
|
|
1705
|
-
>
|
|
1706
|
-
{tableColumns.map(column => (
|
|
1707
|
-
<React.Fragment key={getColumnKey(column)}>
|
|
1708
|
-
{renderEditableCell(row, column)}
|
|
1709
|
-
</React.Fragment>
|
|
1710
|
-
))}
|
|
1711
|
-
{hasRowActions ? (
|
|
1712
|
-
<View style={[styles.cell, styles.actionsCell]}>
|
|
1713
|
-
<TouchableOpacity
|
|
1714
|
-
style={[styles.iconButton, { borderColor: tableBorderColor, backgroundColor: tableSurfaceColor }]}
|
|
1715
|
-
activeOpacity={0.82}
|
|
1716
|
-
onPress={() => openEditModal(row)}>
|
|
1717
|
-
<Icon name="edit-2" size={14} color={tableMutedColor} />
|
|
1718
|
-
</TouchableOpacity>
|
|
1719
|
-
</View>
|
|
1720
|
-
) : null}
|
|
1721
|
-
</RowComponent>
|
|
1722
|
-
);
|
|
1723
|
-
};
|
|
1724
|
-
|
|
1725
|
-
const renderEditModal = () => {
|
|
1726
|
-
const isCreate = formMode === 'create';
|
|
1727
|
-
|
|
1728
|
-
return (
|
|
1729
|
-
<Modal visible={Boolean(editingRow)} transparent animationType="fade" onRequestClose={closeEditModal}>
|
|
1730
|
-
<View style={[styles.modalOverlay, { backgroundColor: modalOverlayColor }]}>
|
|
1731
|
-
<View style={[styles.modalCard, { borderColor: modalBorderColor, backgroundColor: modalBackgroundColor }]}>
|
|
1732
|
-
<View style={[styles.modalHeader, { borderBottomColor: modalBorderColor }]}>
|
|
1733
|
-
<Text style={[styles.modalTitle, { color: modalHeaderTextColor }]}>
|
|
1734
|
-
{isCreate
|
|
1735
|
-
? global.t?.t(storeName, 'button', 'add') || 'Adicionar'
|
|
1736
|
-
: global.t?.t(storeName, 'button', 'edit') || 'Editar'}
|
|
1737
|
-
</Text>
|
|
1738
|
-
<TouchableOpacity
|
|
1739
|
-
style={[styles.modalCloseButton, { borderColor: modalBorderColor, backgroundColor: modalBackgroundColor }]}
|
|
1740
|
-
onPress={closeEditModal}>
|
|
1741
|
-
<Icon name="x" size={18} color={modalCloseIconColor} />
|
|
1742
|
-
</TouchableOpacity>
|
|
1743
|
-
</View>
|
|
1744
|
-
|
|
1745
|
-
<DefaultForm
|
|
1746
|
-
accentColor={resolvedAccentColor}
|
|
1747
|
-
actions={resolvedActions}
|
|
1748
|
-
columns={isCreate ? columnsForTable : editableColumns}
|
|
1749
|
-
getOptionsForColumn={resolvedGetOptionsForColumn}
|
|
1750
|
-
mode={formMode}
|
|
1751
|
-
onBeforeOpen={column => loadListOptionsForColumns([column])}
|
|
1752
|
-
onCancel={closeEditModal}
|
|
1753
|
-
onSaved={(savedItem, originalRow) => {
|
|
1754
|
-
onSaved?.(savedItem, originalRow);
|
|
1755
|
-
closeEditModal();
|
|
1756
|
-
}}
|
|
1757
|
-
row={editingRow || {}}
|
|
1758
|
-
storeName={storeName}
|
|
1759
|
-
/>
|
|
1760
|
-
</View>
|
|
1761
|
-
</View>
|
|
1762
|
-
</Modal>
|
|
1763
|
-
);
|
|
1764
|
-
};
|
|
1765
|
-
|
|
1766
|
-
const renderColumnMenuModal = () => {
|
|
1767
|
-
if (!isColumnMenuOpen) return null;
|
|
1768
|
-
|
|
1769
|
-
return (
|
|
1770
|
-
<Modal visible transparent animationType="fade" onRequestClose={() => setIsColumnMenuOpen(false)}>
|
|
1771
|
-
<View style={[styles.modalOverlay, { backgroundColor: modalOverlayColor }]}>
|
|
1772
|
-
<View style={[styles.modalCard, styles.columnMenuModalCard, { borderColor: modalBorderColor, backgroundColor: modalBackgroundColor }]}>
|
|
1773
|
-
<View style={[styles.modalHeader, { borderBottomColor: modalBorderColor }]}>
|
|
1774
|
-
<Text style={[styles.modalTitle, { color: modalHeaderTextColor }]} numberOfLines={1}>
|
|
1775
|
-
Colunas
|
|
1776
|
-
</Text>
|
|
1777
|
-
<TouchableOpacity
|
|
1778
|
-
style={[styles.modalCloseButton, { borderColor: modalBorderColor, backgroundColor: modalBackgroundColor }]}
|
|
1779
|
-
activeOpacity={0.82}
|
|
1780
|
-
onPress={() => setIsColumnMenuOpen(false)}
|
|
1781
|
-
>
|
|
1782
|
-
<Icon name="x" size={16} color={modalCloseIconColor} />
|
|
1783
|
-
</TouchableOpacity>
|
|
1784
|
-
</View>
|
|
1785
|
-
<ScrollView style={styles.columnMenuModalBody} contentContainerStyle={styles.columnMenuModalList}>
|
|
1786
|
-
{availableColumns.map(column => {
|
|
1787
|
-
const fieldName = getColumnKey(column);
|
|
1788
|
-
const label = formatStoreColumnLabel({
|
|
1789
|
-
columns: columnsForTable,
|
|
1790
|
-
fieldName,
|
|
1791
|
-
fallbackLabel: column?.label || fieldName,
|
|
1792
|
-
storeName,
|
|
1793
|
-
});
|
|
1794
|
-
const checked = visibleColumns[fieldName] !== false;
|
|
1795
|
-
|
|
1796
|
-
return (
|
|
1797
|
-
<TouchableOpacity key={fieldName} style={styles.columnMenuItem} activeOpacity={0.82} onPress={() => toggleColumn(column)}>
|
|
1798
|
-
<Icon name={checked ? 'check-square' : 'square'} size={16} color={checked ? checkboxSelectedMarkColor : checkboxBorderColor} />
|
|
1799
|
-
<Text style={[styles.columnMenuText, { color: modalTextColor }]} numberOfLines={1}>{label}</Text>
|
|
1800
|
-
</TouchableOpacity>
|
|
1801
|
-
);
|
|
1802
|
-
})}
|
|
1803
|
-
</ScrollView>
|
|
1804
|
-
</View>
|
|
1805
|
-
</View>
|
|
1806
|
-
</Modal>
|
|
1807
|
-
);
|
|
1808
|
-
};
|
|
1809
|
-
|
|
1810
|
-
return (
|
|
1811
|
-
<View style={[styles.wrap, { borderColor: panelBorderColor, backgroundColor: panelBackgroundColor }]} onLayout={handleLayout}>
|
|
1812
|
-
<View style={[styles.toolbar, { borderBottomColor: toolbarBorderColor, backgroundColor: toolbarBackgroundColor }]}>
|
|
1813
|
-
{shouldRenderCompactToolbarTotalItems ? (
|
|
1814
|
-
<View style={styles.toolbarCompactLead}>
|
|
1815
|
-
<View style={[styles.toolbarCountPill, { backgroundColor: toolbarCountBackgroundColor }]}>
|
|
1816
|
-
<Text
|
|
1817
|
-
style={[styles.toolbarCountText, { color: toolbarCountTextColor }]}
|
|
1818
|
-
numberOfLines={1}
|
|
1819
|
-
adjustsFontSizeToFit
|
|
1820
|
-
minimumFontScale={0.82}
|
|
1821
|
-
>
|
|
1822
|
-
{resolvedTotalItemsText}
|
|
1823
|
-
</Text>
|
|
1824
|
-
</View>
|
|
1825
|
-
{searchProps ? (
|
|
1826
|
-
<DefaultSearch
|
|
1827
|
-
accentColor={resolvedAccentColor}
|
|
1828
|
-
compact
|
|
1829
|
-
storeName={storeName}
|
|
1830
|
-
{...searchProps}
|
|
1831
|
-
filters={autoMode ? resolvedFilters : searchProps?.filters}
|
|
1832
|
-
onChangeFilters={autoMode ? commitFilters : searchProps?.onChangeFilters}
|
|
1833
|
-
value={autoMode ? resolvedSearchValue : searchProps?.value}
|
|
1834
|
-
style={[styles.toolbarSearch, styles.toolbarCompactSearch, searchProps?.style]}
|
|
1835
|
-
/>
|
|
1836
|
-
) : null}
|
|
1837
|
-
{renderToolbarActions()}
|
|
1838
|
-
</View>
|
|
1839
|
-
) : null}
|
|
1840
|
-
|
|
1841
|
-
<View style={shouldRenderCompactToolbarTotalItems ? styles.toolbarCompactActions : styles.toolbarLeft}>
|
|
1842
|
-
{!shouldRenderCompactToolbarTotalItems && searchProps ? (
|
|
1843
|
-
<DefaultSearch
|
|
1844
|
-
accentColor={resolvedAccentColor}
|
|
1845
|
-
compact
|
|
1846
|
-
storeName={storeName}
|
|
1847
|
-
{...searchProps}
|
|
1848
|
-
filters={autoMode ? resolvedFilters : searchProps?.filters}
|
|
1849
|
-
onChangeFilters={autoMode ? commitFilters : searchProps?.onChangeFilters}
|
|
1850
|
-
value={autoMode ? resolvedSearchValue : searchProps?.value}
|
|
1851
|
-
style={[styles.toolbarSearch, searchProps?.style]}
|
|
1852
|
-
/>
|
|
1853
|
-
) : null}
|
|
1854
|
-
{!shouldRenderCompactToolbarTotalItems ? renderToolbarActions() : null}
|
|
1855
|
-
{showColumnFiltersButton ? (
|
|
1856
|
-
<TouchableOpacity
|
|
1857
|
-
style={[
|
|
1858
|
-
styles.toolbarButton,
|
|
1859
|
-
{ borderColor: tableButtonBorderColor, backgroundColor: tableButtonBackgroundColor },
|
|
1860
|
-
showColumnFilters
|
|
1861
|
-
? { backgroundColor: tableButtonPressedBackgroundColor, borderColor: tableButtonPressedBorderColor }
|
|
1862
|
-
: null,
|
|
1863
|
-
]}
|
|
1864
|
-
activeOpacity={0.82}
|
|
1865
|
-
onPress={() => setShowColumnFilters(prev => !prev)}
|
|
1866
|
-
>
|
|
1867
|
-
<Icon
|
|
1868
|
-
name="filter"
|
|
1869
|
-
size={14}
|
|
1870
|
-
color={showColumnFilters ? tableButtonPressedIconColor : tableButtonIconColor}
|
|
1871
|
-
/>
|
|
1872
|
-
{activeFilterCount > 0 ? (
|
|
1873
|
-
<Text
|
|
1874
|
-
style={[
|
|
1875
|
-
styles.toolbarBadgeText,
|
|
1876
|
-
{ color: showColumnFilters ? tableButtonPressedIconColor : tableButtonIconColor },
|
|
1877
|
-
]}>
|
|
1878
|
-
{activeFilterCount}
|
|
1879
|
-
</Text>
|
|
1880
|
-
) : null}
|
|
1881
|
-
</TouchableOpacity>
|
|
1882
|
-
) : null}
|
|
1883
|
-
<TouchableOpacity
|
|
1884
|
-
style={[
|
|
1885
|
-
styles.toolbarButton,
|
|
1886
|
-
{ borderColor: tableButtonBorderColor, backgroundColor: tableButtonBackgroundColor },
|
|
1887
|
-
effectiveViewMode !== 'table'
|
|
1888
|
-
? { backgroundColor: tableButtonPressedBackgroundColor, borderColor: tableButtonPressedBorderColor }
|
|
1889
|
-
: null,
|
|
1890
|
-
]}
|
|
1891
|
-
activeOpacity={0.82}
|
|
1892
|
-
onPress={toggleViewMode}
|
|
1893
|
-
>
|
|
1894
|
-
<Icon
|
|
1895
|
-
name={effectiveViewMode === 'table' ? 'list' : 'grid'}
|
|
1896
|
-
size={14}
|
|
1897
|
-
color={effectiveViewMode !== 'table' ? tableButtonPressedIconColor : tableButtonIconColor}
|
|
1898
|
-
/>
|
|
1899
|
-
</TouchableOpacity>
|
|
1900
|
-
<TouchableOpacity
|
|
1901
|
-
style={[styles.toolbarButton, { borderColor: tableButtonBorderColor, backgroundColor: tableButtonBackgroundColor }]}
|
|
1902
|
-
activeOpacity={0.82}
|
|
1903
|
-
onPress={() => setIsColumnMenuOpen(prev => !prev)}>
|
|
1904
|
-
<Icon name="columns" size={14} color={tableButtonTextColor} />
|
|
1905
|
-
</TouchableOpacity>
|
|
1906
|
-
{shouldRenderAddButton ? (
|
|
1907
|
-
<TouchableOpacity
|
|
1908
|
-
style={[
|
|
1909
|
-
styles.toolbarButton,
|
|
1910
|
-
styles.toolbarAddButton,
|
|
1911
|
-
{ backgroundColor: tableButtonBackgroundColor, borderColor: tableButtonBackgroundColor },
|
|
1912
|
-
]}
|
|
1913
|
-
activeOpacity={0.85}
|
|
1914
|
-
onPress={openAddForm}
|
|
1915
|
-
>
|
|
1916
|
-
<Icon name="plus" size={16} color={tableButtonTextColor} />
|
|
1917
|
-
</TouchableOpacity>
|
|
1918
|
-
) : null}
|
|
1919
|
-
</View>
|
|
1920
|
-
|
|
1921
|
-
</View>
|
|
1922
|
-
|
|
1923
|
-
{effectiveViewMode === 'cards' ? (
|
|
1924
|
-
<FlatList
|
|
1925
|
-
data={sortedData}
|
|
1926
|
-
keyExtractor={getRowKey}
|
|
1927
|
-
renderItem={({ item, index }) => renderCardItem(item, index)}
|
|
1928
|
-
style={styles.cardsScroll}
|
|
1929
|
-
contentContainerStyle={styles.cardsGrid}
|
|
1930
|
-
ListEmptyComponent={renderEmptyState(false)}
|
|
1931
|
-
ListFooterComponent={null}
|
|
1932
|
-
nestedScrollEnabled
|
|
1933
|
-
onMomentumScrollBegin={onMomentumScrollBegin || undefined}
|
|
1934
|
-
onScrollBeginDrag={onScrollBeginDrag || undefined}
|
|
1935
|
-
onEndReached={handleEndReached}
|
|
1936
|
-
onEndReachedThreshold={END_REACHED_THRESHOLD}
|
|
1937
|
-
showsVerticalScrollIndicator={false}
|
|
1938
|
-
/>
|
|
1939
|
-
) : (
|
|
1940
|
-
<ScrollView horizontal style={styles.scroll}>
|
|
1941
|
-
<View style={[styles.content, tableLayoutStyle]}>
|
|
1942
|
-
<View style={[styles.headerRow, tableLayoutStyle, { backgroundColor: tableHeaderColor, borderBottomColor: tableBorderColor }]}>
|
|
1943
|
-
{tableColumns.map(column => {
|
|
1944
|
-
const fieldName = getColumnKey(column);
|
|
1945
|
-
const label = formatStoreColumnLabel({
|
|
1946
|
-
columns: columnsForTable,
|
|
1947
|
-
fieldName,
|
|
1948
|
-
fallbackLabel: column?.label || fieldName,
|
|
1949
|
-
storeName,
|
|
1950
|
-
});
|
|
344
|
+
useEffect(() => {
|
|
345
|
+
if (!columnsForTable.length || Object.keys(storeFilters).length > 0) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
1951
348
|
|
|
1952
|
-
|
|
349
|
+
const storedFilters = resolveStoredTableFiltersPreference(tablePreferenceScope);
|
|
350
|
+
if (!storedFilters) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
1953
353
|
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
activeOpacity={isSortableColumn(column) ? 0.8 : 1}
|
|
1959
|
-
onPress={() => requestSort(column)}
|
|
1960
|
-
>
|
|
1961
|
-
<View style={styles.sortableHeader}>
|
|
1962
|
-
<Text style={[styles.headerText, { color: tableTextColor }]} numberOfLines={1}>{label}</Text>
|
|
1963
|
-
{isSortableColumn(column) && resolvedSort?.field === sortFieldName ? (
|
|
1964
|
-
<Icon name={resolvedSort?.direction === 'desc' ? 'chevron-down' : 'chevron-up'} size={12} color={tableTextColor} />
|
|
1965
|
-
) : isSortableColumn(column) ? (
|
|
1966
|
-
<Icon name="chevrons-up" size={12} color={tableBorderColor} />
|
|
1967
|
-
) : null}
|
|
1968
|
-
{resolvedFilters?.[fieldName] ? <Icon name="filter" size={11} color={tableTextColor} /> : null}
|
|
1969
|
-
</View>
|
|
1970
|
-
</TouchableOpacity>
|
|
1971
|
-
);
|
|
1972
|
-
})}
|
|
1973
|
-
{hasRowActions ? (
|
|
1974
|
-
<View style={[styles.cell, styles.actionsCell]}>
|
|
1975
|
-
<Text style={[styles.headerText, { color: tableTextColor }]}>Acoes</Text>
|
|
1976
|
-
</View>
|
|
1977
|
-
) : null}
|
|
1978
|
-
</View>
|
|
354
|
+
const nextFilters = sanitizeTableFiltersPreference({
|
|
355
|
+
columns: columnsForTable,
|
|
356
|
+
filters: storedFilters,
|
|
357
|
+
});
|
|
1979
358
|
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
<React.Fragment key={getColumnKey(column)}>
|
|
1984
|
-
{renderColumnFilter(column)}
|
|
1985
|
-
</React.Fragment>
|
|
1986
|
-
))}
|
|
1987
|
-
{hasRowActions ? <View style={[styles.cell, styles.actionsCell]} /> : null}
|
|
1988
|
-
</View>
|
|
1989
|
-
) : null}
|
|
359
|
+
if (Object.keys(nextFilters).length === 0) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
1990
362
|
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
keyExtractor={getRowKey}
|
|
1994
|
-
renderItem={renderTableItem}
|
|
1995
|
-
style={styles.tableList}
|
|
1996
|
-
contentContainerStyle={styles.tableListContent}
|
|
1997
|
-
ListEmptyComponent={renderEmptyState(true)}
|
|
1998
|
-
ListFooterComponent={null}
|
|
1999
|
-
nestedScrollEnabled
|
|
2000
|
-
onMomentumScrollBegin={onMomentumScrollBegin || undefined}
|
|
2001
|
-
onScrollBeginDrag={onScrollBeginDrag || undefined}
|
|
2002
|
-
onEndReached={handleEndReached}
|
|
2003
|
-
onEndReachedThreshold={END_REACHED_THRESHOLD}
|
|
2004
|
-
showsVerticalScrollIndicator={false}
|
|
2005
|
-
/>
|
|
2006
|
-
</View>
|
|
2007
|
-
</ScrollView>
|
|
2008
|
-
)}
|
|
363
|
+
publishStoreValue(store, 'setFilters', nextFilters, 'filters');
|
|
364
|
+
}, [columnsForTable, store, storeFilters, tablePreferenceScope]);
|
|
2009
365
|
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
footerComponent
|
|
2015
|
-
) : (
|
|
2016
|
-
React.createElement(footerComponent, footerProps)
|
|
2017
|
-
)
|
|
2018
|
-
) : shouldRenderFooterBar ? (
|
|
2019
|
-
<View style={[styles.footerBar, { backgroundColor: tableSurfaceColor, borderTopColor: tableBorderColor }]}>
|
|
2020
|
-
{summaryEntries.length > 0 ? (
|
|
2021
|
-
<View style={styles.footerSummaryList}>
|
|
2022
|
-
{summaryEntries.map(entry => (
|
|
2023
|
-
<View key={entry.key} style={styles.footerSummaryItem}>
|
|
2024
|
-
<Text style={[styles.footerSummaryLabel, { color: tableMutedColor }]} numberOfLines={1}>
|
|
2025
|
-
{entry.label}
|
|
2026
|
-
</Text>
|
|
2027
|
-
<Text
|
|
2028
|
-
style={[
|
|
2029
|
-
styles.footerSummaryValue,
|
|
2030
|
-
entry.path?.[0] === 'sum' || isMoneySummaryPath(entry.path)
|
|
2031
|
-
? { color: resolvedAccentColor }
|
|
2032
|
-
: { color: tableTextColor },
|
|
2033
|
-
]}
|
|
2034
|
-
numberOfLines={1}
|
|
2035
|
-
adjustsFontSizeToFit
|
|
2036
|
-
minimumFontScale={0.78}
|
|
2037
|
-
>
|
|
2038
|
-
{formatSummaryValue({
|
|
2039
|
-
column: entry.column,
|
|
2040
|
-
columns: columnsForTable,
|
|
2041
|
-
path: entry.path,
|
|
2042
|
-
storeName,
|
|
2043
|
-
value: entry.value,
|
|
2044
|
-
})}
|
|
2045
|
-
</Text>
|
|
2046
|
-
</View>
|
|
2047
|
-
))}
|
|
2048
|
-
</View>
|
|
2049
|
-
) : null}
|
|
2050
|
-
{shouldRenderFooterTotalItems && !shouldRenderCompactToolbarTotalItems ? (
|
|
2051
|
-
<View style={[styles.footerCountPill, { backgroundColor: toolbarCountBackgroundColor }]}>
|
|
2052
|
-
<Text
|
|
2053
|
-
style={[styles.footerCountText, { color: toolbarCountTextColor }]}
|
|
2054
|
-
numberOfLines={1}
|
|
2055
|
-
adjustsFontSizeToFit
|
|
2056
|
-
minimumFontScale={0.82}
|
|
2057
|
-
>
|
|
2058
|
-
{resolvedTotalItemsText}
|
|
2059
|
-
</Text>
|
|
2060
|
-
</View>
|
|
2061
|
-
) : null}
|
|
2062
|
-
</View>
|
|
2063
|
-
) : null}
|
|
366
|
+
useEffect(() => {
|
|
367
|
+
if (configsSignatureRef.current === defaultTableConfigsSignature) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
2064
370
|
|
|
2065
|
-
|
|
2066
|
-
|
|
371
|
+
configsSignatureRef.current = defaultTableConfigsSignature;
|
|
372
|
+
publishStoreValue(store, 'setConfigs', defaultTableConfigs, 'configs');
|
|
373
|
+
}, [defaultTableConfigs, defaultTableConfigsSignature, store]);
|
|
374
|
+
|
|
375
|
+
useEffect(() => {
|
|
376
|
+
onDataLoaded?.(sortedData);
|
|
377
|
+
}, [onDataLoaded, sortedData]);
|
|
378
|
+
|
|
379
|
+
return (
|
|
380
|
+
<View
|
|
381
|
+
style={[
|
|
382
|
+
styles.wrap,
|
|
383
|
+
{
|
|
384
|
+
borderColor: themeColors.panelBorder,
|
|
385
|
+
backgroundColor: themeColors.panelBackground,
|
|
386
|
+
},
|
|
387
|
+
]}
|
|
388
|
+
>
|
|
389
|
+
<DefaultTableToolbar storeName={storeName} />
|
|
390
|
+
<DefaultTableBody storeName={storeName} />
|
|
391
|
+
<DefaultTableFooter storeName={storeName} />
|
|
2067
392
|
</View>
|
|
2068
393
|
);
|
|
2069
394
|
};
|