@controleonline/ui-default 1.0.269 → 1.0.272
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/integration-source-gate.yml +68 -0
- package/.github/workflows/manager-worker.yml +19 -0
- package/AGENTS.md +46 -50
- package/docs/technical/Contrato-de-colunas.md +67 -0
- package/docs/technical/Default-Components.md +76 -0
- package/docs/technical/DefaultForm.md +80 -0
- package/docs/technical/DefaultInput-e-DefaultSelect.md +73 -0
- package/docs/technical/DefaultTable.md +203 -0
- package/docs/wiki.md +1 -0
- package/package.json +22 -21
- package/scripts/validate-wiki-pointer.cjs +13 -0
- package/src/react/components/address/DefaultAddress.js +435 -0
- package/src/react/components/address/DefaultAddress.styles.js +133 -0
- package/src/react/components/address/DefaultAddressMapPane.js +55 -0
- package/src/react/components/address/LatLonReadonlyFields.js +51 -0
- package/src/react/components/address/defaultAddressHelpers.js +163 -0
- package/src/react/components/address/defaultAddressStyles.js +136 -0
- package/src/react/components/address/defaultAddressUtils.js +129 -0
- package/src/react/components/extra-data/DefaultExtraData.js +152 -0
- package/src/react/components/extra-data/DefaultExtraData.styles.js +61 -0
- package/src/react/components/files/DefaultFile.js +231 -46
- package/src/react/components/files/DefaultFileColumn.js +123 -0
- package/src/react/components/files/DefaultFileColumn.styles.js +52 -0
- package/src/react/components/files/DefaultFileColumn.utils.js +104 -0
- package/src/react/components/filters/CompactFilterSelector.js +51 -35
- package/src/react/components/filters/DefaultColumnFilter.js +58 -41
- package/src/react/components/filters/DefaultExternalFilters.js +331 -265
- package/src/react/components/form/DefaultForm.js +99 -79
- package/src/react/components/help/DefaultTooltip.js +59 -33
- package/src/react/components/help/DefaultTooltip.styles.js +23 -3
- package/src/react/components/inputs/DefaultColorInput.js +153 -0
- package/src/react/components/inputs/DefaultFeatherIconPicker.js +146 -0
- package/src/react/components/inputs/DefaultFeatherIconPicker.styles.js +113 -0
- package/src/react/components/inputs/DefaultInput.js +69 -5
- package/src/react/components/inputs/DefaultInput.styles.js +26 -0
- package/src/react/components/inputs/DefaultSelect.js +134 -123
- package/src/react/components/inputs/defaultInputUtils.js +69 -43
- package/src/react/components/map/DefaultGoogleMap.styles.js +9 -2
- package/src/react/components/map/DefaultGoogleMap.web.js +49 -28
- package/src/react/components/map/DefaultMap.native.js +73 -73
- package/src/react/components/map/DefaultMap.shared.js +911 -762
- package/src/react/components/map/DefaultMap.web.js +124 -68
- package/src/react/components/table/DefaultColumnMenu.js +109 -108
- package/src/react/components/table/DefaultDebug.js +45 -38
- package/src/react/components/table/DefaultSearchModal.js +9 -1
- package/src/react/components/table/DefaultTable.grouping.js +98 -0
- package/src/react/components/table/DefaultTable.js +215 -109
- package/src/react/components/table/DefaultTable.styles.js +367 -314
- package/src/react/components/table/DefaultTableBody.js +13 -8
- package/src/react/components/table/DefaultTableCards.js +20 -1
- package/src/react/components/table/DefaultTableControls.js +180 -205
- package/src/react/components/table/DefaultTableImportModal.js +108 -0
- package/src/react/components/table/DefaultTableInput.js +1 -0
- package/src/react/components/table/DefaultTableRowActions.js +1 -1
- package/src/react/components/table/DefaultTableRows.js +224 -363
- package/src/react/components/table/DefaultTableSearch.js +28 -5
- package/src/react/components/table/DefaultTableToolbar.js +92 -3
- package/src/react/components/table/useDefaultTablePagination.js +56 -7
- package/src/react/components/table/useDefaultTableStoreSync.js +164 -0
- package/src/react/components/upload/DefaultUpload.js +436 -0
- package/src/react/components/upload/DefaultUpload.styles.js +153 -0
- package/src/react/components/upload/DefaultUploadAttachmentsList.js +138 -0
- package/src/react/components/upload/DefaultUploadManagerModal.js +247 -0
- package/src/react/components/upload/defaultUploadHelpers.js +108 -0
- package/src/react/components/upload/defaultUploadLibrary.js +248 -0
- package/src/react/components/upload/fileUpload.js +93 -0
- package/src/react/hooks/usePostalCodeLookup.js +145 -0
- package/src/react/index.js +6 -0
- package/src/react/services/addressFormUtils.js +196 -0
- package/src/react/services/addressGeo.js +227 -0
- package/src/react/utils/tableVisibleColumnsPreferences.js +29 -12
- package/src/tests/react/components/address/defaultAddressHelpers.test.js +104 -0
- package/src/tests/react/components/files/DefaultFile.test.js +6 -6
- package/src/tests/react/components/form/DefaultForm.test.js +123 -0
- package/src/tests/react/components/inputs/DefaultSelect.test.js +108 -79
- package/src/tests/react/components/table/DefaultTable.grouping.test.js +49 -0
- package/src/tests/react/components/table/DefaultTable.test.js +54 -2
- package/src/tests/react/components/table/DefaultTableControls.filters.test.mjs +21 -0
- package/src/tests/react/components/table/resolveRowBackgroundColor.test.mjs +45 -0
- package/src/tests/react/components/table/useDefaultTableStoreSync.test.js +161 -0
- package/src/tests/react/components/upload/DefaultUpload.test.js +353 -0
- package/src/tests/react/components/upload/defaultUploadLibrary.test.js +82 -0
- package/src/tests/react/components/upload/peopleMediaLibraryPreview.test.mjs +57 -0
- package/src/tests/react/hooks/usePostalCodeLookup.test.js +40 -0
- package/src/tests/react/services/SMOKE-637-cep-hydrate.md +45 -0
- package/src/tests/react/services/addressFormUtils.test.js +176 -0
- package/src/tests/react/services/addressGeoLookup.async.test.js +104 -0
- package/src/tests/react/services/addressGeoLookup.test.js +105 -0
- package/src/tests/react/services/smoke-637/form-cep-12941040.png +0 -0
- package/src/tests/react/services/smoke-637/index.html +132 -0
- package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +84 -48
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import {
|
|
3
3
|
Modal,
|
|
4
4
|
Image,
|
|
5
5
|
ScrollView,
|
|
6
|
-
Text,
|
|
7
|
-
TextInput,
|
|
8
|
-
TouchableOpacity,
|
|
9
|
-
View,
|
|
10
|
-
} from 'react-native';
|
|
6
|
+
Text,
|
|
7
|
+
TextInput,
|
|
8
|
+
TouchableOpacity,
|
|
9
|
+
View,
|
|
10
|
+
} from 'react-native';
|
|
11
11
|
import Icon from 'react-native-vector-icons/Feather';
|
|
12
12
|
import { getAllStores, useStore } from '@store';
|
|
13
13
|
import {
|
|
@@ -71,11 +71,13 @@ const resolveColumnListLoadParams = ({
|
|
|
71
71
|
column,
|
|
72
72
|
currentCompanyId,
|
|
73
73
|
requestParams = {},
|
|
74
|
+
row = {},
|
|
74
75
|
searchValue = '',
|
|
76
|
+
variant = 'cell',
|
|
75
77
|
}) => {
|
|
76
78
|
const listStoreName = resolveStoreNameFromList(column?.list);
|
|
77
79
|
const resolvedCustomParams = typeof column?.listRequestParams === 'function'
|
|
78
|
-
? column.listRequestParams({ currentCompanyId, requestParams })
|
|
80
|
+
? column.listRequestParams({ currentCompanyId, requestParams, row, variant })
|
|
79
81
|
: column?.listRequestParams;
|
|
80
82
|
const customParams =
|
|
81
83
|
resolvedCustomParams &&
|
|
@@ -92,31 +94,31 @@ const resolveColumnListLoadParams = ({
|
|
|
92
94
|
: {}),
|
|
93
95
|
};
|
|
94
96
|
};
|
|
95
|
-
|
|
96
|
-
const DefaultSelect = ({
|
|
97
|
-
accentColor = '#2563EB',
|
|
98
|
-
autoSave = true,
|
|
99
|
-
column,
|
|
100
|
-
columns = [],
|
|
101
|
-
containerStyle = null,
|
|
102
|
-
displayValue,
|
|
103
|
-
editing = false,
|
|
104
|
-
getOptionsForColumn = null,
|
|
105
|
-
label = '',
|
|
106
|
-
numberOfLines = 1,
|
|
107
|
-
onBeforeOpen = null,
|
|
97
|
+
|
|
98
|
+
const DefaultSelect = ({
|
|
99
|
+
accentColor = '#2563EB',
|
|
100
|
+
autoSave = true,
|
|
101
|
+
column,
|
|
102
|
+
columns = [],
|
|
103
|
+
containerStyle = null,
|
|
104
|
+
displayValue,
|
|
105
|
+
editing = false,
|
|
106
|
+
getOptionsForColumn = null,
|
|
107
|
+
label = '',
|
|
108
|
+
numberOfLines = 1,
|
|
109
|
+
onBeforeOpen = null,
|
|
108
110
|
onCancelEditing = null,
|
|
109
111
|
onChangeValue = null,
|
|
110
112
|
onSave = null,
|
|
111
113
|
onSearchChange = null,
|
|
112
114
|
onStartEditing = null,
|
|
113
|
-
readTextStyle = null,
|
|
114
|
-
row = {},
|
|
115
|
-
saving = false,
|
|
116
|
-
showLabel = false,
|
|
117
|
-
storeName = '',
|
|
118
|
-
value,
|
|
119
|
-
variant = 'cell',
|
|
115
|
+
readTextStyle = null,
|
|
116
|
+
row = {},
|
|
117
|
+
saving = false,
|
|
118
|
+
showLabel = false,
|
|
119
|
+
storeName = '',
|
|
120
|
+
value,
|
|
121
|
+
variant = 'cell',
|
|
120
122
|
}) => {
|
|
121
123
|
const peopleStore = useStore('people');
|
|
122
124
|
const ownerStore = useStore(storeName);
|
|
@@ -126,9 +128,9 @@ const DefaultSelect = ({
|
|
|
126
128
|
const [searchText, setSearchText] = useState('');
|
|
127
129
|
const currentCompanyId = peopleStore?.getters?.currentCompany?.id;
|
|
128
130
|
const requestParams = ownerStore?.getters?.configs?.requestParams || {};
|
|
129
|
-
|
|
130
|
-
const fieldName = getColumnKey(column);
|
|
131
|
-
const selectedKey = normalizeOptionKey(value ?? resolveEditValue(column, row));
|
|
131
|
+
|
|
132
|
+
const fieldName = getColumnKey(column);
|
|
133
|
+
const selectedKey = normalizeOptionKey(value ?? resolveEditValue(column, row));
|
|
132
134
|
const options = useMemo(() => {
|
|
133
135
|
const localOptions = buildOptionsFromColumn(column, getOptionsForColumn, storeName);
|
|
134
136
|
const remoteOptions = mapOptions(column, loadedItems, storeName);
|
|
@@ -143,7 +145,8 @@ const DefaultSelect = ({
|
|
|
143
145
|
...localOptions.filter(option => !seenKeys.has(option.key)),
|
|
144
146
|
];
|
|
145
147
|
}, [column, getOptionsForColumn, loadedItems, storeName]);
|
|
146
|
-
const selected = options.find(option => option.key === selectedKey);
|
|
148
|
+
const selected = options.find(option => option.key === selectedKey);
|
|
149
|
+
const resolvedFieldLabel = label || column?.formLabel || column?.label || fieldName;
|
|
147
150
|
const resolvedLabel =
|
|
148
151
|
displayValue ??
|
|
149
152
|
selected?.label ??
|
|
@@ -175,9 +178,9 @@ const DefaultSelect = ({
|
|
|
175
178
|
const query = normalizeText(searchText).toLowerCase();
|
|
176
179
|
if (!query || onSearchChange) return options;
|
|
177
180
|
return options.filter(option =>
|
|
178
|
-
normalizeText(option.label).toLowerCase().includes(query) ||
|
|
179
|
-
normalizeText(option.key).toLowerCase().includes(query),
|
|
180
|
-
);
|
|
181
|
+
normalizeText(option.label).toLowerCase().includes(query) ||
|
|
182
|
+
normalizeText(option.key).toLowerCase().includes(query),
|
|
183
|
+
);
|
|
181
184
|
}, [options, searchText]);
|
|
182
185
|
|
|
183
186
|
const applyLoadedItems = useCallback(value => {
|
|
@@ -187,6 +190,12 @@ const DefaultSelect = ({
|
|
|
187
190
|
}
|
|
188
191
|
}, []);
|
|
189
192
|
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
loadedListKeysRef.current.clear();
|
|
195
|
+
setLoadedItems([]);
|
|
196
|
+
setSearchText('');
|
|
197
|
+
}, [currentCompanyId, fieldName, row]);
|
|
198
|
+
|
|
190
199
|
const loadRemoteOptions = useCallback((searchValue = '') => {
|
|
191
200
|
const listStoreName = resolveStoreNameFromList(column?.list);
|
|
192
201
|
const actionName = resolveListActionName(column?.list);
|
|
@@ -202,7 +211,9 @@ const DefaultSelect = ({
|
|
|
202
211
|
column,
|
|
203
212
|
currentCompanyId,
|
|
204
213
|
requestParams,
|
|
214
|
+
row,
|
|
205
215
|
searchValue,
|
|
216
|
+
variant,
|
|
206
217
|
});
|
|
207
218
|
const loadKey = `${getColumnKey(column)}:${listStoreName}:${actionName}:${stableSerialize(listLoadParams)}`;
|
|
208
219
|
|
|
@@ -235,7 +246,7 @@ const DefaultSelect = ({
|
|
|
235
246
|
loadedListKeysRef.current.delete(loadKey);
|
|
236
247
|
throw error;
|
|
237
248
|
});
|
|
238
|
-
}, [applyLoadedItems, column, currentCompanyId, loadedItems, requestParams]);
|
|
249
|
+
}, [applyLoadedItems, column, currentCompanyId, loadedItems, requestParams, row, variant]);
|
|
239
250
|
|
|
240
251
|
const handleSearchChange = useCallback(value => {
|
|
241
252
|
setSearchText(value);
|
|
@@ -247,43 +258,43 @@ const DefaultSelect = ({
|
|
|
247
258
|
|
|
248
259
|
applyLoadedItems(maybeLoad);
|
|
249
260
|
}, [applyLoadedItems, loadRemoteOptions, onSearchChange]);
|
|
250
|
-
|
|
251
|
-
const close = () => {
|
|
252
|
-
setIsOpen(false);
|
|
253
|
-
setSearchText('');
|
|
254
|
-
if (autoSave) onCancelEditing?.();
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
const selectOption = option => {
|
|
258
|
-
setIsOpen(false);
|
|
259
|
-
setSearchText('');
|
|
260
|
-
|
|
261
|
-
if (autoSave) {
|
|
262
|
-
onSave?.({
|
|
263
|
-
value: option.key,
|
|
264
|
-
label: option.label,
|
|
265
|
-
object: option.raw,
|
|
266
|
-
});
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
onChangeValue?.(option.key, {
|
|
271
|
-
value: option.key,
|
|
272
|
-
label: option.label,
|
|
273
|
-
object: option.raw,
|
|
274
|
-
});
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const open = async () => {
|
|
278
|
-
if (!canEdit && !isForm) return;
|
|
279
|
-
try {
|
|
280
|
-
if (!editing && !isForm) {
|
|
281
|
-
const maybePromise = onStartEditing?.();
|
|
282
|
-
if (maybePromise && typeof maybePromise.then === 'function') {
|
|
283
|
-
await maybePromise;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
261
|
+
|
|
262
|
+
const close = () => {
|
|
263
|
+
setIsOpen(false);
|
|
264
|
+
setSearchText('');
|
|
265
|
+
if (autoSave) onCancelEditing?.();
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const selectOption = option => {
|
|
269
|
+
setIsOpen(false);
|
|
270
|
+
setSearchText('');
|
|
271
|
+
|
|
272
|
+
if (autoSave) {
|
|
273
|
+
onSave?.({
|
|
274
|
+
value: option.key,
|
|
275
|
+
label: option.label,
|
|
276
|
+
object: option.raw,
|
|
277
|
+
});
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
onChangeValue?.(option.key, {
|
|
282
|
+
value: option.key,
|
|
283
|
+
label: option.label,
|
|
284
|
+
object: option.raw,
|
|
285
|
+
});
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const open = async () => {
|
|
289
|
+
if (!canEdit && !isForm) return;
|
|
290
|
+
try {
|
|
291
|
+
if (!editing && !isForm) {
|
|
292
|
+
const maybePromise = onStartEditing?.();
|
|
293
|
+
if (maybePromise && typeof maybePromise.then === 'function') {
|
|
294
|
+
await maybePromise;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
287
298
|
const maybeLoad = onBeforeOpen?.();
|
|
288
299
|
if (maybeLoad && typeof maybeLoad.then === 'function') {
|
|
289
300
|
applyLoadedItems(await maybeLoad);
|
|
@@ -296,11 +307,11 @@ const DefaultSelect = ({
|
|
|
296
307
|
setIsOpen(true);
|
|
297
308
|
loadRemoteOptions().catch(() => {});
|
|
298
309
|
};
|
|
299
|
-
|
|
300
|
-
return (
|
|
301
|
-
<View style={[inputStyles.wrap, containerStyle]}>
|
|
302
|
-
{showLabel ? <Text style={inputStyles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
|
|
303
|
-
|
|
310
|
+
|
|
311
|
+
return (
|
|
312
|
+
<View style={[inputStyles.wrap, containerStyle]}>
|
|
313
|
+
{showLabel ? <Text style={inputStyles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
|
|
314
|
+
|
|
304
315
|
<TouchableOpacity
|
|
305
316
|
style={[inputStyles.readButton, isForm ? inputStyles.readButtonForm : null]}
|
|
306
317
|
activeOpacity={canEdit || isForm ? 0.78 : 1}
|
|
@@ -359,33 +370,33 @@ const DefaultSelect = ({
|
|
|
359
370
|
{saving ? (
|
|
360
371
|
<Text style={[inputStyles.savingText, { color: accentColor }]}>Salvando</Text>
|
|
361
372
|
) : canEdit || isForm ? (
|
|
362
|
-
<Icon style={inputStyles.editIcon} name="chevron-down" size={14} color="#64748B" />
|
|
363
|
-
) : null}
|
|
364
|
-
</TouchableOpacity>
|
|
365
|
-
|
|
366
|
-
<Modal visible={isOpen} transparent animationType="fade" onRequestClose={close}>
|
|
367
|
-
<View style={styles.overlay}>
|
|
368
|
-
<View style={styles.modalCard}>
|
|
369
|
-
<View style={styles.modalHeader}>
|
|
370
|
-
<Text style={styles.modalTitle} numberOfLines={1}>
|
|
371
|
-
{
|
|
372
|
-
</Text>
|
|
373
|
-
<TouchableOpacity style={inputStyles.cancelButton} onPress={close}>
|
|
374
|
-
<Icon name="x" size={16} color="#64748B" />
|
|
375
|
-
</TouchableOpacity>
|
|
376
|
-
</View>
|
|
377
|
-
|
|
378
|
-
<View style={styles.searchBox}>
|
|
379
|
-
<TextInput
|
|
373
|
+
<Icon style={inputStyles.editIcon} name="chevron-down" size={14} color="#64748B" />
|
|
374
|
+
) : null}
|
|
375
|
+
</TouchableOpacity>
|
|
376
|
+
|
|
377
|
+
<Modal visible={isOpen} transparent animationType="fade" onRequestClose={close}>
|
|
378
|
+
<View style={styles.overlay}>
|
|
379
|
+
<View style={styles.modalCard}>
|
|
380
|
+
<View style={styles.modalHeader}>
|
|
381
|
+
<Text style={styles.modalTitle} numberOfLines={1}>
|
|
382
|
+
{resolvedFieldLabel}
|
|
383
|
+
</Text>
|
|
384
|
+
<TouchableOpacity style={inputStyles.cancelButton} onPress={close}>
|
|
385
|
+
<Icon name="x" size={16} color="#64748B" />
|
|
386
|
+
</TouchableOpacity>
|
|
387
|
+
</View>
|
|
388
|
+
|
|
389
|
+
<View style={styles.searchBox}>
|
|
390
|
+
<TextInput
|
|
380
391
|
style={[inputStyles.input, inputStyles.formInput]}
|
|
381
392
|
value={searchText}
|
|
382
|
-
placeholder={global.t?.t(storeName, 'input', column?.searchParam || 'search')}
|
|
393
|
+
placeholder={resolvedFieldLabel || global.t?.t(storeName, 'input', column?.searchParam || 'search')}
|
|
383
394
|
onChangeText={handleSearchChange}
|
|
384
395
|
/>
|
|
385
|
-
</View>
|
|
386
|
-
|
|
387
|
-
<ScrollView keyboardShouldPersistTaps="handled">
|
|
388
|
-
{filteredOptions.length > 0 ? (
|
|
396
|
+
</View>
|
|
397
|
+
|
|
398
|
+
<ScrollView keyboardShouldPersistTaps="handled">
|
|
399
|
+
{filteredOptions.length > 0 ? (
|
|
389
400
|
filteredOptions.map(option => {
|
|
390
401
|
const isSelected = option.key === selectedKey;
|
|
391
402
|
const optionColor = normalizeText(option.color);
|
|
@@ -401,10 +412,10 @@ const DefaultSelect = ({
|
|
|
401
412
|
return (
|
|
402
413
|
<TouchableOpacity
|
|
403
414
|
key={`${option.key}_${option.label}`}
|
|
404
|
-
style={styles.optionRow}
|
|
405
|
-
activeOpacity={0.78}
|
|
406
|
-
onPress={() => selectOption(option)}
|
|
407
|
-
>
|
|
415
|
+
style={styles.optionRow}
|
|
416
|
+
activeOpacity={0.78}
|
|
417
|
+
onPress={() => selectOption(option)}
|
|
418
|
+
>
|
|
408
419
|
{option.image ? (
|
|
409
420
|
<Image
|
|
410
421
|
source={option.image}
|
|
@@ -429,21 +440,21 @@ const DefaultSelect = ({
|
|
|
429
440
|
{option.label}
|
|
430
441
|
</Text>
|
|
431
442
|
</TouchableOpacity>
|
|
432
|
-
);
|
|
433
|
-
})
|
|
434
|
-
) : (
|
|
435
|
-
<View style={styles.emptyBox}>
|
|
436
|
-
<Text style={styles.emptyText}>
|
|
437
|
-
Nenhum resultado encontrado
|
|
438
|
-
</Text>
|
|
439
|
-
</View>
|
|
440
|
-
)}
|
|
441
|
-
</ScrollView>
|
|
442
|
-
</View>
|
|
443
|
-
</View>
|
|
444
|
-
</Modal>
|
|
445
|
-
</View>
|
|
446
|
-
);
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
export default DefaultSelect;
|
|
443
|
+
);
|
|
444
|
+
})
|
|
445
|
+
) : (
|
|
446
|
+
<View style={styles.emptyBox}>
|
|
447
|
+
<Text style={styles.emptyText}>
|
|
448
|
+
Nenhum resultado encontrado
|
|
449
|
+
</Text>
|
|
450
|
+
</View>
|
|
451
|
+
)}
|
|
452
|
+
</ScrollView>
|
|
453
|
+
</View>
|
|
454
|
+
</View>
|
|
455
|
+
</Modal>
|
|
456
|
+
</View>
|
|
457
|
+
);
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
export default DefaultSelect;
|
|
@@ -39,9 +39,40 @@ export const isDateRangeColumn = column =>
|
|
|
39
39
|
|
|
40
40
|
export const isDateLikeColumn = column =>
|
|
41
41
|
isDateColumn(column) || isDateRangeColumn(column);
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
42
|
+
|
|
43
|
+
export const isColorColumn = column => {
|
|
44
|
+
const fieldName = normalizeColumnKey(getColumnKey(column));
|
|
45
|
+
const inputType = normalizeColumnKey(column?.inputType || column?.type);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
inputType === 'color' ||
|
|
49
|
+
inputType === 'hexcolor' ||
|
|
50
|
+
fieldName === 'color' ||
|
|
51
|
+
fieldName === 'bgcolor' ||
|
|
52
|
+
fieldName === 'backgroundcolor' ||
|
|
53
|
+
fieldName === 'bordercolor'
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const isFileColumn = column => {
|
|
58
|
+
const inputType = normalizeColumnKey(column?.inputType || column?.type);
|
|
59
|
+
|
|
60
|
+
return [
|
|
61
|
+
'document',
|
|
62
|
+
'documents',
|
|
63
|
+
'file',
|
|
64
|
+
'files',
|
|
65
|
+
'image',
|
|
66
|
+
'images',
|
|
67
|
+
'pdf',
|
|
68
|
+
].includes(inputType);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const isExtraDataColumn = column =>
|
|
72
|
+
normalizeColumnKey(column?.inputType || column?.type) === 'extradata';
|
|
73
|
+
|
|
74
|
+
const normalizeColumnKey = value =>
|
|
75
|
+
normalizeText(value)
|
|
45
76
|
.replace(/[^a-zA-Z0-9]/g, '')
|
|
46
77
|
.toLowerCase();
|
|
47
78
|
|
|
@@ -70,14 +101,14 @@ export const normalizeId = value => {
|
|
|
70
101
|
return normalizeId(value?.id || value?.['@id'] || '');
|
|
71
102
|
};
|
|
72
103
|
|
|
73
|
-
export const isEditableColumn = column =>
|
|
74
|
-
column?.editable !== false &&
|
|
75
|
-
!column?.isIdentity &&
|
|
76
|
-
column?.inputType !== 'increase' &&
|
|
77
|
-
column
|
|
78
|
-
!String(getColumnKey(column)).includes('.');
|
|
104
|
+
export const isEditableColumn = column =>
|
|
105
|
+
column?.editable !== false &&
|
|
106
|
+
!column?.isIdentity &&
|
|
107
|
+
column?.inputType !== 'increase' &&
|
|
108
|
+
!isFileColumn(column) &&
|
|
109
|
+
!String(getColumnKey(column)).includes('.');
|
|
79
110
|
|
|
80
|
-
export const normalizeOptionKey = option => {
|
|
111
|
+
export const normalizeOptionKey = option => {
|
|
81
112
|
if (!option) return '';
|
|
82
113
|
if (typeof option !== 'object') return normalizeId(option) || normalizeText(option);
|
|
83
114
|
return normalizeText(
|
|
@@ -153,6 +184,29 @@ const filterItemsByListRequestParams = (items = [], column = null) => {
|
|
|
153
184
|
);
|
|
154
185
|
};
|
|
155
186
|
|
|
187
|
+
export const resolveColorToken = (value, themeColors = {}) => {
|
|
188
|
+
const normalized = normalizeText(value);
|
|
189
|
+
if (!normalized) return '';
|
|
190
|
+
|
|
191
|
+
if (normalized.startsWith('$')) {
|
|
192
|
+
return normalizeText(themeColors?.[normalized.slice(1)]);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const cssVarMatch = normalized.match(/^var\([^,]+,\s*(#[0-9a-fA-F]{3,8})\s*\)$/);
|
|
196
|
+
if (cssVarMatch?.[1]) return cssVarMatch[1];
|
|
197
|
+
|
|
198
|
+
return normalized;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export const resolveDefaultColorValue = (column, themeColors = {}, fallbackColor = '') =>
|
|
202
|
+
resolveColorToken(
|
|
203
|
+
column?.defaultColor ??
|
|
204
|
+
column?.defaultColour ??
|
|
205
|
+
column?.defaultValue ??
|
|
206
|
+
fallbackColor,
|
|
207
|
+
themeColors,
|
|
208
|
+
);
|
|
209
|
+
|
|
156
210
|
const normalizeObject = value =>
|
|
157
211
|
value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
158
212
|
|
|
@@ -174,18 +228,8 @@ export const mapOptions = (column, items = [], storeName = '') => {
|
|
|
174
228
|
const formattedMeta = normalizeObject(formatted);
|
|
175
229
|
const itemMeta = normalizeObject(item);
|
|
176
230
|
const color = formattedMeta.color ?? itemMeta.color;
|
|
177
|
-
const icon =
|
|
178
|
-
|
|
179
|
-
formattedMeta.iconName ??
|
|
180
|
-
itemMeta.icon ??
|
|
181
|
-
itemMeta.iconName;
|
|
182
|
-
const image =
|
|
183
|
-
formattedMeta.image ??
|
|
184
|
-
formattedMeta.logo ??
|
|
185
|
-
formattedMeta.source ??
|
|
186
|
-
itemMeta.image ??
|
|
187
|
-
itemMeta.logo ??
|
|
188
|
-
itemMeta.source;
|
|
231
|
+
const icon = formattedMeta.icon ?? itemMeta.icon;
|
|
232
|
+
const image = formattedMeta.image ?? itemMeta.image;
|
|
189
233
|
|
|
190
234
|
options.push({
|
|
191
235
|
...(color ? { color } : {}),
|
|
@@ -286,12 +330,8 @@ export const resolveCellPresentation = ({
|
|
|
286
330
|
backgroundColor:
|
|
287
331
|
formattedValueMeta.backgroundColor ??
|
|
288
332
|
formattedMeta.backgroundColor ??
|
|
289
|
-
formattedValueMeta.bgColor ??
|
|
290
|
-
formattedMeta.bgColor ??
|
|
291
333
|
rawMeta.backgroundColor ??
|
|
292
|
-
|
|
293
|
-
styleMeta.backgroundColor ??
|
|
294
|
-
styleMeta.bgColor,
|
|
334
|
+
styleMeta.backgroundColor,
|
|
295
335
|
borderColor:
|
|
296
336
|
formattedValueMeta.borderColor ??
|
|
297
337
|
formattedMeta.borderColor ??
|
|
@@ -301,31 +341,17 @@ export const resolveCellPresentation = ({
|
|
|
301
341
|
formattedValueMeta.color ??
|
|
302
342
|
formattedMeta.color ??
|
|
303
343
|
rawMeta.color ??
|
|
304
|
-
rawMeta.statusColor ??
|
|
305
|
-
rawMeta.categoryColor ??
|
|
306
344
|
styleMeta.color,
|
|
307
345
|
icon:
|
|
308
346
|
formattedValueMeta.icon ??
|
|
309
|
-
formattedValueMeta.iconName ??
|
|
310
347
|
formattedMeta.icon ??
|
|
311
|
-
formattedMeta.iconName ??
|
|
312
348
|
rawMeta.icon ??
|
|
313
|
-
|
|
314
|
-
styleMeta.icon ??
|
|
315
|
-
styleMeta.iconName,
|
|
349
|
+
styleMeta.icon,
|
|
316
350
|
image:
|
|
317
351
|
formattedValueMeta.image ??
|
|
318
|
-
formattedValueMeta.logo ??
|
|
319
|
-
formattedValueMeta.source ??
|
|
320
352
|
formattedMeta.image ??
|
|
321
|
-
formattedMeta.logo ??
|
|
322
|
-
formattedMeta.source ??
|
|
323
353
|
rawMeta.image ??
|
|
324
|
-
|
|
325
|
-
rawMeta.source ??
|
|
326
|
-
styleMeta.image ??
|
|
327
|
-
styleMeta.logo ??
|
|
328
|
-
styleMeta.source,
|
|
354
|
+
styleMeta.image,
|
|
329
355
|
label,
|
|
330
356
|
};
|
|
331
357
|
};
|
|
@@ -38,8 +38,8 @@ export default StyleSheet.create({
|
|
|
38
38
|
},
|
|
39
39
|
popupLogoWrap: {
|
|
40
40
|
width: 58,
|
|
41
|
-
height:
|
|
42
|
-
borderRadius:
|
|
41
|
+
height: 54,
|
|
42
|
+
borderRadius: 10,
|
|
43
43
|
overflow: 'hidden',
|
|
44
44
|
borderWidth: 1,
|
|
45
45
|
alignItems: 'center',
|
|
@@ -52,6 +52,13 @@ export default StyleSheet.create({
|
|
|
52
52
|
width: '100%',
|
|
53
53
|
height: '100%',
|
|
54
54
|
},
|
|
55
|
+
popupLogoFallback: {
|
|
56
|
+
fontSize: 24,
|
|
57
|
+
lineHeight: 26,
|
|
58
|
+
fontWeight: '900',
|
|
59
|
+
letterSpacing: 0.04,
|
|
60
|
+
textTransform: 'uppercase',
|
|
61
|
+
},
|
|
55
62
|
popupTitleWrap: {
|
|
56
63
|
flex: 1,
|
|
57
64
|
minWidth: 0,
|
|
@@ -110,8 +110,20 @@ const extractCoordinates = address => {
|
|
|
110
110
|
return {latitude, longitude};
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
-
const buildPopupTitle = item =>
|
|
114
|
-
item?.unitAlias || item?.alias || item?.companyName || item?.title || 'Unidade';
|
|
113
|
+
const buildPopupTitle = item =>
|
|
114
|
+
item?.unitAlias || item?.alias || item?.companyName || item?.title || 'Unidade';
|
|
115
|
+
|
|
116
|
+
const buildLogoFallback = item => {
|
|
117
|
+
const title = buildPopupTitle(item);
|
|
118
|
+
|
|
119
|
+
return String(title || 'CO')
|
|
120
|
+
.trim()
|
|
121
|
+
.split(/\s+/)
|
|
122
|
+
.slice(0, 2)
|
|
123
|
+
.map(chunk => chunk[0] || '')
|
|
124
|
+
.join('')
|
|
125
|
+
.toUpperCase();
|
|
126
|
+
};
|
|
115
127
|
|
|
116
128
|
const loadGoogleMapsApi = apiKey => {
|
|
117
129
|
if (Platform.OS !== 'web' || typeof window === 'undefined') {
|
|
@@ -654,11 +666,12 @@ export default function DefaultGoogleMap({
|
|
|
654
666
|
return null;
|
|
655
667
|
}
|
|
656
668
|
|
|
657
|
-
const selectedTitle = buildPopupTitle(selectedMarker);
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
669
|
+
const selectedTitle = buildPopupTitle(selectedMarker);
|
|
670
|
+
const selectedLogoFallback = buildLogoFallback(selectedMarker);
|
|
671
|
+
const selectedTravelSummary = buildPopupTravelSummaryText(
|
|
672
|
+
selectedMarker,
|
|
673
|
+
selectedRouteSummary,
|
|
674
|
+
);
|
|
662
675
|
const selectedNavigationPosition = selectedMarker
|
|
663
676
|
? {
|
|
664
677
|
latitude: Number(selectedMarker.latitude),
|
|
@@ -688,19 +701,27 @@ export default function DefaultGoogleMap({
|
|
|
688
701
|
},
|
|
689
702
|
]}>
|
|
690
703
|
<View style={styles.popupHeaderRow}>
|
|
691
|
-
<View
|
|
692
|
-
style={[
|
|
693
|
-
styles.popupLogoWrap,
|
|
694
|
-
{borderColor: resolvedPopupTheme.dividerBorder},
|
|
695
|
-
]}>
|
|
696
|
-
{selectedMarker.companyLogoUrl ? (
|
|
697
|
-
<Image
|
|
698
|
-
source={{uri: selectedMarker.companyLogoUrl}}
|
|
699
|
-
style={styles.popupLogoImage}
|
|
700
|
-
resizeMode="cover"
|
|
701
|
-
/>
|
|
702
|
-
) :
|
|
703
|
-
|
|
704
|
+
<View
|
|
705
|
+
style={[
|
|
706
|
+
styles.popupLogoWrap,
|
|
707
|
+
{borderColor: resolvedPopupTheme.dividerBorder},
|
|
708
|
+
]}>
|
|
709
|
+
{selectedMarker.companyLogoUrl ? (
|
|
710
|
+
<Image
|
|
711
|
+
source={{uri: selectedMarker.companyLogoUrl}}
|
|
712
|
+
style={styles.popupLogoImage}
|
|
713
|
+
resizeMode="cover"
|
|
714
|
+
/>
|
|
715
|
+
) : (
|
|
716
|
+
<Text
|
|
717
|
+
style={[
|
|
718
|
+
styles.popupLogoFallback,
|
|
719
|
+
{color: resolvedPopupTheme.buttonBackground},
|
|
720
|
+
]}>
|
|
721
|
+
{selectedLogoFallback}
|
|
722
|
+
</Text>
|
|
723
|
+
)}
|
|
724
|
+
</View>
|
|
704
725
|
<View style={styles.popupTitleWrap}>
|
|
705
726
|
<Text
|
|
706
727
|
numberOfLines={1}
|
|
@@ -780,14 +801,14 @@ export default function DefaultGoogleMap({
|
|
|
780
801
|
styles.popupActionButton,
|
|
781
802
|
{backgroundColor: resolvedPopupTheme.buttonBackground},
|
|
782
803
|
]}>
|
|
783
|
-
<Text
|
|
784
|
-
style={[
|
|
785
|
-
styles.popupActionText,
|
|
786
|
-
{color: resolvedPopupTheme.buttonText},
|
|
787
|
-
]}>
|
|
788
|
-
Abrir no Maps
|
|
789
|
-
</Text>
|
|
790
|
-
</TouchableOpacity>
|
|
804
|
+
<Text
|
|
805
|
+
style={[
|
|
806
|
+
styles.popupActionText,
|
|
807
|
+
{color: resolvedPopupTheme.buttonText},
|
|
808
|
+
]}>
|
|
809
|
+
Abrir no Maps
|
|
810
|
+
</Text>
|
|
811
|
+
</TouchableOpacity>
|
|
791
812
|
<TouchableOpacity
|
|
792
813
|
activeOpacity={0.85}
|
|
793
814
|
onPress={() => openExternalUrl(selectedWazeUrl)}
|