@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,68 +1,124 @@
|
|
|
1
|
-
import React, {useMemo} from 'react';
|
|
2
|
-
import {View} from 'react-native';
|
|
3
|
-
|
|
4
|
-
import DefaultGoogleMap from './DefaultGoogleMap.web';
|
|
5
|
-
|
|
6
|
-
import styles from './DefaultMap.styles';
|
|
7
|
-
import {
|
|
8
|
-
buildOpenStreetMapHtml,
|
|
9
|
-
resolveDefaultMapPayload,
|
|
10
|
-
} from './DefaultMap.shared';
|
|
11
|
-
|
|
12
|
-
export default function DefaultMap({
|
|
13
|
-
config = null,
|
|
14
|
-
addresses = null,
|
|
15
|
-
markerPayloads = [],
|
|
16
|
-
paths = [],
|
|
17
|
-
userCoordinates = null,
|
|
18
|
-
apiKey = '',
|
|
19
|
-
popupTheme = null,
|
|
20
|
-
}) {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
import React, {useEffect, useMemo, useRef} from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
|
|
4
|
+
import DefaultGoogleMap from './DefaultGoogleMap.web';
|
|
5
|
+
|
|
6
|
+
import styles from './DefaultMap.styles';
|
|
7
|
+
import {
|
|
8
|
+
buildOpenStreetMapHtml,
|
|
9
|
+
resolveDefaultMapPayload,
|
|
10
|
+
} from './DefaultMap.shared';
|
|
11
|
+
|
|
12
|
+
export default function DefaultMap({
|
|
13
|
+
config = null,
|
|
14
|
+
addresses = null,
|
|
15
|
+
markerPayloads = [],
|
|
16
|
+
paths = [],
|
|
17
|
+
userCoordinates = null,
|
|
18
|
+
apiKey = '',
|
|
19
|
+
popupTheme = null,
|
|
20
|
+
}) {
|
|
21
|
+
const iframeRef = useRef(null);
|
|
22
|
+
const resolvedPayload = useMemo(
|
|
23
|
+
() =>
|
|
24
|
+
resolveDefaultMapPayload({
|
|
25
|
+
config,
|
|
26
|
+
addresses,
|
|
27
|
+
markerPayloads,
|
|
28
|
+
paths,
|
|
29
|
+
userCoordinates,
|
|
30
|
+
apiKey,
|
|
31
|
+
}),
|
|
32
|
+
[apiKey, addresses, config, markerPayloads, paths, userCoordinates],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const mapKey = useMemo(() => {
|
|
36
|
+
const markers = resolvedPayload.markerPayloads || [];
|
|
37
|
+
const first = markers[0] || {};
|
|
38
|
+
const user = resolvedPayload.userCoordinates || {};
|
|
39
|
+
return [
|
|
40
|
+
first.latitude,
|
|
41
|
+
first.longitude,
|
|
42
|
+
first.geocodeQuery || first.addressLine || '',
|
|
43
|
+
user.latitude,
|
|
44
|
+
user.longitude,
|
|
45
|
+
markers.length,
|
|
46
|
+
(resolvedPayload.paths || []).length,
|
|
47
|
+
].join('|');
|
|
48
|
+
}, [resolvedPayload]);
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const el = iframeRef.current;
|
|
52
|
+
if (!el) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const bump = () => {
|
|
57
|
+
try {
|
|
58
|
+
const win = el.contentWindow;
|
|
59
|
+
if (win && typeof win.dispatchEvent === 'function') {
|
|
60
|
+
win.dispatchEvent(new Event('resize'));
|
|
61
|
+
}
|
|
62
|
+
} catch (e) {
|
|
63
|
+
// empty srcDoc during mount
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const onLoad = () => {
|
|
68
|
+
bump();
|
|
69
|
+
setTimeout(bump, 50);
|
|
70
|
+
setTimeout(bump, 250);
|
|
71
|
+
setTimeout(bump, 800);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
el.addEventListener('load', onLoad);
|
|
75
|
+
return () => el.removeEventListener('load', onLoad);
|
|
76
|
+
}, [mapKey]);
|
|
77
|
+
|
|
78
|
+
if (
|
|
79
|
+
resolvedPayload.markerPayloads.length === 0 &&
|
|
80
|
+
!resolvedPayload.userCoordinates &&
|
|
81
|
+
resolvedPayload.paths.length === 0
|
|
82
|
+
) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (resolvedPayload.apiKey) {
|
|
87
|
+
return (
|
|
88
|
+
<DefaultGoogleMap
|
|
89
|
+
apiKey={resolvedPayload.apiKey}
|
|
90
|
+
markerPayloads={resolvedPayload.markerPayloads}
|
|
91
|
+
userCoordinates={resolvedPayload.userCoordinates}
|
|
92
|
+
paths={resolvedPayload.paths}
|
|
93
|
+
popupTheme={popupTheme}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const html = buildOpenStreetMapHtml({
|
|
99
|
+
markerPayloads: resolvedPayload.markerPayloads,
|
|
100
|
+
paths: resolvedPayload.paths,
|
|
101
|
+
userCoordinates: resolvedPayload.userCoordinates,
|
|
102
|
+
routeColor: '#0EA5E9',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<View style={[styles.mapContainer, {height: '100%', minHeight: 220, width: '100%', flex: 1}]}>
|
|
107
|
+
<iframe
|
|
108
|
+
ref={iframeRef}
|
|
109
|
+
key={mapKey}
|
|
110
|
+
title="Mapa"
|
|
111
|
+
srcDoc={html}
|
|
112
|
+
style={{
|
|
113
|
+
width: '100%',
|
|
114
|
+
height: '100%',
|
|
115
|
+
minHeight: 220,
|
|
116
|
+
border: 0,
|
|
117
|
+
display: 'block',
|
|
118
|
+
}}
|
|
119
|
+
loading="eager"
|
|
120
|
+
referrerPolicy="no-referrer-when-downgrade"
|
|
121
|
+
/>
|
|
122
|
+
</View>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
@@ -1,108 +1,109 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Modal, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
-
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
-
import { useStore } from '@store';
|
|
5
|
-
import { formatStoreColumnLabel } from '@controleonline/ui-common/src/react/utils/storeColumns';
|
|
6
|
-
import { getColumnKey } from '../inputs/defaultInputUtils';
|
|
7
|
-
import {
|
|
8
|
-
persistVisibleColumnsPreference,
|
|
9
|
-
resolveDefaultTablePreferenceScope,
|
|
10
|
-
sanitizeVisibleColumnsPreference,
|
|
11
|
-
} from '../../utils/tableVisibleColumnsPreferences';
|
|
12
|
-
import styles from './DefaultTable.styles';
|
|
13
|
-
import { shouldIncludeColumn } from './DefaultTable.utils';
|
|
14
|
-
import useDefaultTableTheme from './useDefaultTableTheme';
|
|
15
|
-
|
|
16
|
-
const DefaultColumnMenu = ({ storeName, visible = false, onClose }) => {
|
|
17
|
-
const store = useStore(storeName);
|
|
18
|
-
const columns = Array.isArray(store?.getters?.columns) ? store.getters.columns : [];
|
|
19
|
-
const visibleColumns = store?.getters?.visibleColumns || {};
|
|
20
|
-
const configs = store?.getters?.configs || {};
|
|
21
|
-
const tablePreferenceScope =
|
|
22
|
-
configs.tablePreferenceScope ||
|
|
23
|
-
resolveDefaultTablePreferenceScope({ storeName });
|
|
24
|
-
const availableColumns = columns.filter(column => shouldIncludeColumn(column));
|
|
25
|
-
const {
|
|
26
|
-
checkboxBorderColor: resolvedCheckboxBorderColor,
|
|
27
|
-
checkboxSelectedMarkColor: resolvedCheckboxSelectedMarkColor,
|
|
28
|
-
modalColors,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Modal, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
+
import { useStore } from '@store';
|
|
5
|
+
import { formatStoreColumnLabel } from '@controleonline/ui-common/src/react/utils/storeColumns';
|
|
6
|
+
import { getColumnKey } from '../inputs/defaultInputUtils';
|
|
7
|
+
import {
|
|
8
|
+
persistVisibleColumnsPreference,
|
|
9
|
+
resolveDefaultTablePreferenceScope,
|
|
10
|
+
sanitizeVisibleColumnsPreference,
|
|
11
|
+
} from '../../utils/tableVisibleColumnsPreferences';
|
|
12
|
+
import styles from './DefaultTable.styles';
|
|
13
|
+
import { shouldIncludeColumn } from './DefaultTable.utils';
|
|
14
|
+
import useDefaultTableTheme from './useDefaultTableTheme';
|
|
15
|
+
|
|
16
|
+
const DefaultColumnMenu = ({ storeName, visible = false, onClose }) => {
|
|
17
|
+
const store = useStore(storeName);
|
|
18
|
+
const columns = Array.isArray(store?.getters?.columns) ? store.getters.columns : [];
|
|
19
|
+
const visibleColumns = store?.getters?.visibleColumns || {};
|
|
20
|
+
const configs = store?.getters?.configs || {};
|
|
21
|
+
const tablePreferenceScope =
|
|
22
|
+
configs.tablePreferenceScope ||
|
|
23
|
+
resolveDefaultTablePreferenceScope({ storeName });
|
|
24
|
+
const availableColumns = columns.filter(column => shouldIncludeColumn(column));
|
|
25
|
+
const {
|
|
26
|
+
checkboxBorderColor: resolvedCheckboxBorderColor,
|
|
27
|
+
checkboxSelectedMarkColor: resolvedCheckboxSelectedMarkColor,
|
|
28
|
+
modalColors,
|
|
29
|
+
themeColors,
|
|
30
|
+
} = useDefaultTableTheme();
|
|
31
|
+
if (!visible) return null;
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
backgroundColor,
|
|
35
|
+
borderColor,
|
|
36
|
+
closeIconColor,
|
|
37
|
+
headerTextColor,
|
|
38
|
+
overlayColor,
|
|
39
|
+
textColor,
|
|
40
|
+
} = modalColors;
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Modal visible transparent animationType="fade" onRequestClose={onClose}>
|
|
44
|
+
<View style={[styles.modalOverlay, { backgroundColor: overlayColor }]}>
|
|
45
|
+
<View style={[styles.modalCard, styles.columnMenuModalCard, { borderColor, backgroundColor }]}>
|
|
46
|
+
<View style={[styles.modalHeader, { borderBottomColor: borderColor }]}>
|
|
47
|
+
<Text style={[styles.modalTitle, { color: headerTextColor }]} numberOfLines={1}>
|
|
48
|
+
{global.t?.t(storeName, 'label', 'columns')}
|
|
49
|
+
</Text>
|
|
50
|
+
<TouchableOpacity
|
|
51
|
+
style={[styles.modalCloseButton, { borderColor, backgroundColor }]}
|
|
52
|
+
activeOpacity={0.82}
|
|
53
|
+
onPress={onClose}
|
|
54
|
+
>
|
|
55
|
+
<Icon name="x" size={16} color={themeColors.iconWarning || closeIconColor} />
|
|
56
|
+
</TouchableOpacity>
|
|
57
|
+
</View>
|
|
58
|
+
<ScrollView style={styles.columnMenuModalBody} contentContainerStyle={styles.columnMenuModalList}>
|
|
59
|
+
{availableColumns.map(column => {
|
|
60
|
+
const fieldName = getColumnKey(column);
|
|
61
|
+
const label = formatStoreColumnLabel({
|
|
62
|
+
columns,
|
|
63
|
+
fieldName,
|
|
64
|
+
fallbackLabel: column?.label || fieldName,
|
|
65
|
+
storeName,
|
|
66
|
+
});
|
|
67
|
+
const checked = visibleColumns[fieldName] !== false;
|
|
68
|
+
const toggleColumn = () => {
|
|
69
|
+
const nextVisibleColumns = sanitizeVisibleColumnsPreference({
|
|
70
|
+
columns,
|
|
71
|
+
visibleColumns: {
|
|
72
|
+
...visibleColumns,
|
|
73
|
+
[fieldName]: visibleColumns[fieldName] === false,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
persistVisibleColumnsPreference(tablePreferenceScope, nextVisibleColumns);
|
|
78
|
+
|
|
79
|
+
if (typeof store?.actions?.setVisibleColumns === 'function') {
|
|
80
|
+
store.actions.setVisibleColumns(nextVisibleColumns);
|
|
81
|
+
} else if (store?.getters) {
|
|
82
|
+
store.getters.visibleColumns = nextVisibleColumns;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<TouchableOpacity
|
|
88
|
+
key={fieldName}
|
|
89
|
+
style={styles.columnMenuItem}
|
|
90
|
+
activeOpacity={0.82}
|
|
91
|
+
onPress={toggleColumn}
|
|
92
|
+
>
|
|
93
|
+
<Icon
|
|
94
|
+
name={checked ? 'check-square' : 'square'}
|
|
95
|
+
size={16}
|
|
96
|
+
color={checked ? resolvedCheckboxSelectedMarkColor : resolvedCheckboxBorderColor}
|
|
97
|
+
/>
|
|
98
|
+
<Text style={[styles.columnMenuText, { color: textColor }]} numberOfLines={1}>{label}</Text>
|
|
99
|
+
</TouchableOpacity>
|
|
100
|
+
);
|
|
101
|
+
})}
|
|
102
|
+
</ScrollView>
|
|
103
|
+
</View>
|
|
104
|
+
</View>
|
|
105
|
+
</Modal>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export default DefaultColumnMenu;
|
|
@@ -70,7 +70,7 @@ const DefaultDebug = ({
|
|
|
70
70
|
const [isOpen, setIsOpen] = useState(false);
|
|
71
71
|
const store = useStore(storeName);
|
|
72
72
|
const configs = store?.getters?.configs || {};
|
|
73
|
-
const { showError, showSuccess } = useMessage();
|
|
73
|
+
const { showError, showSuccess } = useMessage() || {};
|
|
74
74
|
const { modalColors, resolvedAccentColor, tableButtonColors } = useDefaultTableTheme();
|
|
75
75
|
|
|
76
76
|
const resolvedDebug = isObject(store?.getters?.debug) ? store.getters.debug : {};
|
|
@@ -82,11 +82,12 @@ const DefaultDebug = ({
|
|
|
82
82
|
const debugParameters = isObject(resolvedDebug?.parameters)
|
|
83
83
|
? resolvedDebug.parameters
|
|
84
84
|
: configs.debugFallbackParameters || null;
|
|
85
|
-
const debugParametersText = useMemo(
|
|
86
|
-
() => formatDebugValue(debugParameters),
|
|
87
|
-
[debugParameters],
|
|
88
|
-
);
|
|
89
|
-
const
|
|
85
|
+
const debugParametersText = useMemo(
|
|
86
|
+
() => formatDebugValue(debugParameters),
|
|
87
|
+
[debugParameters],
|
|
88
|
+
);
|
|
89
|
+
const hasDebugParameters = debugParametersText !== '';
|
|
90
|
+
const debugCopyText = useMemo(
|
|
90
91
|
() =>
|
|
91
92
|
[
|
|
92
93
|
'Query:',
|
|
@@ -118,9 +119,9 @@ const DefaultDebug = ({
|
|
|
118
119
|
[showError, showSuccess],
|
|
119
120
|
);
|
|
120
121
|
|
|
121
|
-
if (!hasDebugQuery) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
122
|
+
if (!hasDebugQuery && !hasDebugParameters && !debugFilledQuery) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
124
125
|
|
|
125
126
|
const {
|
|
126
127
|
backgroundColor,
|
|
@@ -176,35 +177,41 @@ const DefaultDebug = ({
|
|
|
176
177
|
</View>
|
|
177
178
|
|
|
178
179
|
<ScrollView style={styles.debugModalBody} contentContainerStyle={styles.debugModalContent}>
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
180
|
+
{hasDebugQuery ? (
|
|
181
|
+
<DebugSection
|
|
182
|
+
borderColor={borderColor}
|
|
183
|
+
copyText={debugQuery}
|
|
184
|
+
onCopy={requestCopyText}
|
|
185
|
+
textColor={textColor}
|
|
186
|
+
title="Query"
|
|
187
|
+
>
|
|
188
|
+
{debugQuery}
|
|
189
|
+
</DebugSection>
|
|
190
|
+
) : null}
|
|
191
|
+
|
|
192
|
+
{hasDebugParameters ? (
|
|
193
|
+
<DebugSection
|
|
194
|
+
borderColor={borderColor}
|
|
195
|
+
copyText={debugParametersText}
|
|
196
|
+
onCopy={requestCopyText}
|
|
197
|
+
textColor={textColor}
|
|
198
|
+
title="Parametros"
|
|
199
|
+
>
|
|
200
|
+
{debugParametersText}
|
|
201
|
+
</DebugSection>
|
|
202
|
+
) : null}
|
|
203
|
+
|
|
204
|
+
{debugFilledQuery ? (
|
|
205
|
+
<DebugSection
|
|
206
|
+
borderColor={borderColor}
|
|
207
|
+
copyText={debugFilledQuery}
|
|
208
|
+
onCopy={requestCopyText}
|
|
209
|
+
textColor={textColor}
|
|
210
|
+
title="Query preenchida"
|
|
211
|
+
>
|
|
212
|
+
{debugFilledQuery}
|
|
213
|
+
</DebugSection>
|
|
214
|
+
) : null}
|
|
208
215
|
</ScrollView>
|
|
209
216
|
|
|
210
217
|
<View style={[styles.modalActions, { borderTopColor: borderColor }]}>
|
|
@@ -5,7 +5,13 @@ import DefaultSearch from '../filters/DefaultSearch';
|
|
|
5
5
|
import styles from './DefaultTable.styles';
|
|
6
6
|
import useDefaultTableTheme from './useDefaultTableTheme';
|
|
7
7
|
|
|
8
|
-
const DefaultSearchModal = ({
|
|
8
|
+
const DefaultSearchModal = ({
|
|
9
|
+
searchKey = 'search',
|
|
10
|
+
searchPlaceholder = '',
|
|
11
|
+
storeName,
|
|
12
|
+
visible = false,
|
|
13
|
+
onClose,
|
|
14
|
+
}) => {
|
|
9
15
|
const { modalColors } = useDefaultTableTheme();
|
|
10
16
|
if (!visible) return null;
|
|
11
17
|
|
|
@@ -36,6 +42,8 @@ const DefaultSearchModal = ({ storeName, visible = false, onClose }) => {
|
|
|
36
42
|
<View style={styles.searchModalBody}>
|
|
37
43
|
<DefaultSearch
|
|
38
44
|
autoFocus
|
|
45
|
+
placeholder={searchPlaceholder}
|
|
46
|
+
searchKey={searchKey}
|
|
39
47
|
storeName={storeName}
|
|
40
48
|
onSearch={onClose}
|
|
41
49
|
/>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { getColumnKey } from '../inputs/defaultInputUtils';
|
|
2
|
+
import { getRowKey } from './DefaultTable.utils';
|
|
3
|
+
|
|
4
|
+
export const isGroupingColumn = column => column?.grouping === true;
|
|
5
|
+
|
|
6
|
+
export const getGroupingColumns = columns =>
|
|
7
|
+
(Array.isArray(columns) ? columns : []).filter(isGroupingColumn);
|
|
8
|
+
|
|
9
|
+
export const getRowFieldValue = (row, column) => {
|
|
10
|
+
const fieldName = typeof column === 'string' ? column : getColumnKey(column);
|
|
11
|
+
if (!fieldName) return '';
|
|
12
|
+
const value = row?.[fieldName];
|
|
13
|
+
if (value && typeof value === 'object') {
|
|
14
|
+
return String(value.label ?? value.name ?? value.alias ?? value.id ?? '').trim();
|
|
15
|
+
}
|
|
16
|
+
return String(value ?? '').trim();
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const buildGroupKey = (row, groupingColumns) =>
|
|
20
|
+
getGroupingColumns(groupingColumns)
|
|
21
|
+
.map(column => getRowFieldValue(row, column) || 'none')
|
|
22
|
+
.join(':');
|
|
23
|
+
|
|
24
|
+
export const buildGroupLabel = (row, groupingColumns) =>
|
|
25
|
+
getGroupingColumns(groupingColumns)
|
|
26
|
+
.map(column => getRowFieldValue(row, column) || column?.label || getColumnKey(column))
|
|
27
|
+
.filter(Boolean)
|
|
28
|
+
.join(' · ');
|
|
29
|
+
|
|
30
|
+
export const groupTableRows = (rows, columns) => {
|
|
31
|
+
const groupingColumns = getGroupingColumns(columns);
|
|
32
|
+
const items = Array.isArray(rows) ? rows : [];
|
|
33
|
+
if (!groupingColumns.length) {
|
|
34
|
+
return [{ id: 'all', key: 'all', label: '', rows: items, count: items.length }];
|
|
35
|
+
}
|
|
36
|
+
const groups = new Map();
|
|
37
|
+
items.forEach(row => {
|
|
38
|
+
const key = buildGroupKey(row, groupingColumns);
|
|
39
|
+
if (!groups.has(key)) {
|
|
40
|
+
groups.set(key, { id: key, key, label: buildGroupLabel(row, groupingColumns), rows: [], count: 0 });
|
|
41
|
+
}
|
|
42
|
+
const group = groups.get(key);
|
|
43
|
+
group.rows.push(row);
|
|
44
|
+
group.count += 1;
|
|
45
|
+
});
|
|
46
|
+
return Array.from(groups.values());
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const flattenGroupedTableItems = (rows, columns) => {
|
|
50
|
+
const groupingColumns = getGroupingColumns(columns);
|
|
51
|
+
const items = Array.isArray(rows) ? rows : [];
|
|
52
|
+
if (!groupingColumns.length) {
|
|
53
|
+
return items.map((row, index) => ({ type: 'row', id: `row:${getRowKey(row, index)}`, row }));
|
|
54
|
+
}
|
|
55
|
+
return groupTableRows(items, groupingColumns).flatMap(group => [
|
|
56
|
+
{ type: 'group', id: `group:${group.id}`, group },
|
|
57
|
+
...group.rows.map((row, index) => ({ type: 'row', id: `row:${group.id}:${getRowKey(row, index)}`, group, row })),
|
|
58
|
+
]);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const normalizeSelectedIds = selectedIds =>
|
|
62
|
+
Array.from(new Set((Array.isArray(selectedIds) ? selectedIds : []).map(id => String(id))));
|
|
63
|
+
|
|
64
|
+
export const resolveStoreSelectedIds = store =>
|
|
65
|
+
normalizeSelectedIds(store?.getters?.selected);
|
|
66
|
+
|
|
67
|
+
export const isRowSelected = (row, selectedIds, index = 0) =>
|
|
68
|
+
normalizeSelectedIds(selectedIds).includes(String(getRowKey(row, index)));
|
|
69
|
+
|
|
70
|
+
export const toggleSelectedId = (selectedIds, row, index = 0) => {
|
|
71
|
+
const current = normalizeSelectedIds(selectedIds);
|
|
72
|
+
const id = String(getRowKey(row, index));
|
|
73
|
+
return current.includes(id) ? current.filter(item => item !== id) : [...current, id];
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const toggleGroupSelection = (selectedIds, groupRows) => {
|
|
77
|
+
const current = normalizeSelectedIds(selectedIds);
|
|
78
|
+
const ids = (Array.isArray(groupRows) ? groupRows : []).map(row => String(getRowKey(row)));
|
|
79
|
+
const allSelected = ids.length > 0 && ids.every(id => current.includes(id));
|
|
80
|
+
if (allSelected) return current.filter(id => !ids.includes(id));
|
|
81
|
+
return normalizeSelectedIds([...current, ...ids]);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const persistStoreSelection = (store, nextIds, rows, columns) => {
|
|
85
|
+
const selected = normalizeSelectedIds(nextIds);
|
|
86
|
+
store?.actions?.setSelected?.(selected);
|
|
87
|
+
const items = (Array.isArray(rows) ? rows : []).filter(row => selected.includes(String(getRowKey(row))));
|
|
88
|
+
const groups = groupTableRows(items, columns).filter(group => group.rows.length > 0);
|
|
89
|
+
const totalValue = items.reduce((sum, row) => {
|
|
90
|
+
const amount = Number(row?.invoiceTotal ?? row?.total ?? row?.value ?? 0);
|
|
91
|
+
return sum + (Number.isFinite(amount) ? amount : 0);
|
|
92
|
+
}, 0);
|
|
93
|
+
store?.actions?.setSummary?.({
|
|
94
|
+
count: { invoices: items.length, groups: groups.length },
|
|
95
|
+
sum: { invoiceTotal: Number(totalValue.toFixed(2)) },
|
|
96
|
+
});
|
|
97
|
+
return selected;
|
|
98
|
+
};
|