@controleonline/ui-common 1.2.100 → 1.2.101
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/.release/rc-manifest.json +7 -7
- package/docs/homepage-1056.md +5 -1
- package/package.json +1 -1
- package/src/api/index.js +54 -40
- package/src/react/components/AnimatedModal.js +1 -6
- package/src/react/components/BottomNavigationBar.js +5 -6
- package/src/react/components/BottomNavigationBar.soft.styles.js +4 -5
- package/src/react/components/ProductCatalogCacheService.js +45 -53
- package/src/react/components/RuntimeBottomNavigationBar.js +4 -11
- package/src/react/components/UserAvatar.js +13 -2
- package/src/react/pages/Devices/deviceTypes/DeviceGroupCard.js +4 -6
- package/src/react/pages/Devices/deviceTypes/shared.js +4 -9
- package/src/react/pages/Devices.js +183 -184
- package/src/react/pages/IntegrationConfigPage.js +13 -59
- package/src/react/pages/IntegrationConfigPage.utils.js +0 -17
- package/src/react/pages/integrationsCatalog.js +0 -71
- package/src/tests/react/utils/runtimeFooter.test.js +189 -189
- package/src/utils/integrationConfigs.js +0 -23
- package/src/react/hooks/useBottomNavigationPreference.js +0 -49
- package/src/react/utils/productCatalogCacheRevision.js +0 -13
- package/src/tests/react/utils/storedSessionToken.test.js +0 -22
- package/src/utils/storedSessionToken.js +0 -18
|
@@ -1,184 +1,183 @@
|
|
|
1
|
-
import React, {useEffect, useMemo, useState} from 'react';
|
|
2
|
-
import {Text, TouchableOpacity, View} from 'react-native';
|
|
3
|
-
import {SafeAreaView} from 'react-native-safe-area-context';
|
|
4
|
-
import {useNavigation} from '@react-navigation/native';
|
|
5
|
-
import {useStore} from '@store';
|
|
6
|
-
import {resolveThemePalette} from '@controleonline/../../src/styles/branding';
|
|
7
|
-
import {colors} from '@controleonline/../../src/styles/colors';
|
|
8
|
-
import CompactFilterSelector from '@controleonline/ui-default/src/react/components/filters/CompactFilterSelector';
|
|
9
|
-
import {PDV_DEVICE_TYPE} from '@controleonline/ui-common/src/react/utils/printerDevices';
|
|
10
|
-
import Icon from 'react-native-vector-icons/Feather';
|
|
11
|
-
import {
|
|
12
|
-
ALL_DEVICE_FILTER,
|
|
13
|
-
getDeviceCreationAction,
|
|
14
|
-
getDeviceFilterAccent,
|
|
15
|
-
getDeviceFilterDefinition,
|
|
16
|
-
getDeviceFilterIcon,
|
|
17
|
-
getDeviceFilterOptions,
|
|
18
|
-
getPdvSubfilterOptions,
|
|
19
|
-
hasRegisteredDeviceFilter,
|
|
20
|
-
isPdvSubfilter,
|
|
21
|
-
} from './Devices/deviceTypes';
|
|
22
|
-
import { createStyles } from './Devices.styles';
|
|
23
|
-
|
|
24
|
-
const tt = (type, key) => global.t?.t('configs', type, key);
|
|
25
|
-
|
|
26
|
-
const Devices = (
|
|
27
|
-
const navigation = useNavigation();
|
|
28
|
-
const peopleStore = useStore('people');
|
|
29
|
-
const themeStore = useStore('theme');
|
|
30
|
-
|
|
31
|
-
const {currentCompany} = peopleStore.getters;
|
|
32
|
-
const {colors: themeColors} = themeStore.getters;
|
|
33
|
-
|
|
34
|
-
const [activeFilter, setActiveFilter] = useState(ALL_DEVICE_FILTER);
|
|
35
|
-
|
|
36
|
-
const brandColors = useMemo(
|
|
37
|
-
() =>
|
|
38
|
-
|
|
39
|
-
{...themeColors, ...(currentCompany?.theme?.colors || {})},
|
|
40
|
-
colors,
|
|
41
|
-
),
|
|
42
|
-
[
|
|
43
|
-
);
|
|
44
|
-
const styles = useMemo(() => createStyles(brandColors), [brandColors]);
|
|
45
|
-
const accentPalette = useMemo(
|
|
46
|
-
() => ({
|
|
47
|
-
primary: brandColors.info,
|
|
48
|
-
success: brandColors.success,
|
|
49
|
-
danger: brandColors.error,
|
|
50
|
-
warning: brandColors.warning,
|
|
51
|
-
}),
|
|
52
|
-
[brandColors.error, brandColors.info, brandColors.success, brandColors.warning],
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
const filterOptions = useMemo(() => getDeviceFilterOptions(), []);
|
|
56
|
-
const pdvSubfilterOptions = useMemo(() => getPdvSubfilterOptions(), []);
|
|
57
|
-
const activeFilterDefinition = useMemo(
|
|
58
|
-
() => getDeviceFilterDefinition(activeFilter),
|
|
59
|
-
[activeFilter],
|
|
60
|
-
);
|
|
61
|
-
const topLevelActiveFilter = useMemo(
|
|
62
|
-
() => (isPdvSubfilter(activeFilter) ? PDV_DEVICE_TYPE : activeFilter),
|
|
63
|
-
[activeFilter],
|
|
64
|
-
);
|
|
65
|
-
const activeFilterAction = useMemo(
|
|
66
|
-
() => getDeviceCreationAction(topLevelActiveFilter),
|
|
67
|
-
[topLevelActiveFilter],
|
|
68
|
-
);
|
|
69
|
-
const deviceTypeSelectorOptions = useMemo(
|
|
70
|
-
() => filterOptions.map(option => ({
|
|
71
|
-
key: option.key,
|
|
72
|
-
label: option.label,
|
|
73
|
-
})),
|
|
74
|
-
[filterOptions],
|
|
75
|
-
);
|
|
76
|
-
const pdvGatewaySelectorOptions = useMemo(
|
|
77
|
-
() => [
|
|
78
|
-
{key: PDV_DEVICE_TYPE, label: tt('device_filter', 'all') || 'Todos'},
|
|
79
|
-
...pdvSubfilterOptions.map(option => ({
|
|
80
|
-
key: option.key,
|
|
81
|
-
label: option.label,
|
|
82
|
-
})),
|
|
83
|
-
],
|
|
84
|
-
[pdvSubfilterOptions],
|
|
85
|
-
);
|
|
86
|
-
const selectedDeviceTypeLabel = useMemo(
|
|
87
|
-
() =>
|
|
88
|
-
deviceTypeSelectorOptions.find(option => option.key === topLevelActiveFilter)?.label ||
|
|
89
|
-
tt('device_filter', 'allTypes') ||
|
|
90
|
-
'Todos os tipos',
|
|
91
|
-
[deviceTypeSelectorOptions, topLevelActiveFilter],
|
|
92
|
-
);
|
|
93
|
-
const selectedPdvGatewayLabel = useMemo(
|
|
94
|
-
() =>
|
|
95
|
-
pdvGatewaySelectorOptions.find(option => option.key === activeFilter)?.label ||
|
|
96
|
-
tt('device_filter', 'all') ||
|
|
97
|
-
'Todos',
|
|
98
|
-
[activeFilter, pdvGatewaySelectorOptions],
|
|
99
|
-
);
|
|
100
|
-
const ActiveTabComponent = activeFilterDefinition.TabComponent;
|
|
101
|
-
|
|
102
|
-
useEffect(() => {
|
|
103
|
-
if (!hasRegisteredDeviceFilter(activeFilter)) {
|
|
104
|
-
setActiveFilter(ALL_DEVICE_FILTER);
|
|
105
|
-
}
|
|
106
|
-
}, [activeFilter]);
|
|
107
|
-
|
|
108
|
-
return (
|
|
109
|
-
<SafeAreaView
|
|
110
|
-
style={[styles.container, {backgroundColor: brandColors.background}]}>
|
|
111
|
-
<View style={styles.filtersBlock}>
|
|
112
|
-
<Text style={styles.filtersLabel}>{tt('device_filter', 'filterByType') || 'Filtrar por tipo'}</Text>
|
|
113
|
-
<CompactFilterSelector
|
|
114
|
-
icon={getDeviceFilterIcon(topLevelActiveFilter)}
|
|
115
|
-
label={selectedDeviceTypeLabel}
|
|
116
|
-
title={tt('device_filter', 'filterByType') || 'Filtrar por tipo'}
|
|
117
|
-
accentColor={getDeviceFilterAccent(topLevelActiveFilter, {
|
|
118
|
-
brandColors,
|
|
119
|
-
hex: accentPalette,
|
|
120
|
-
})}
|
|
121
|
-
active={topLevelActiveFilter !== ALL_DEVICE_FILTER}
|
|
122
|
-
options={deviceTypeSelectorOptions}
|
|
123
|
-
selectedKey={topLevelActiveFilter}
|
|
124
|
-
onSelect={optionKey => {
|
|
125
|
-
setActiveFilter(optionKey);
|
|
126
|
-
return true;
|
|
127
|
-
}}
|
|
128
|
-
/>
|
|
129
|
-
</View>
|
|
130
|
-
|
|
131
|
-
{topLevelActiveFilter === PDV_DEVICE_TYPE && pdvSubfilterOptions.length > 0 ? (
|
|
132
|
-
<View style={styles.filtersBlock}>
|
|
133
|
-
<Text style={styles.filtersLabel}>{tt('device_filter', 'pdvGateway') || 'Gateway do PDV'}</Text>
|
|
134
|
-
<CompactFilterSelector
|
|
135
|
-
icon={getDeviceFilterIcon(activeFilter)}
|
|
136
|
-
label={selectedPdvGatewayLabel}
|
|
137
|
-
title={tt('device_filter', 'pdvGateway') || 'Gateway do PDV'}
|
|
138
|
-
accentColor={getDeviceFilterAccent(activeFilter, {
|
|
139
|
-
brandColors,
|
|
140
|
-
hex: accentPalette,
|
|
141
|
-
})}
|
|
142
|
-
active={activeFilter !== PDV_DEVICE_TYPE}
|
|
143
|
-
options={pdvGatewaySelectorOptions}
|
|
144
|
-
selectedKey={activeFilter}
|
|
145
|
-
onSelect={optionKey => {
|
|
146
|
-
setActiveFilter(optionKey);
|
|
147
|
-
return true;
|
|
148
|
-
}}
|
|
149
|
-
/>
|
|
150
|
-
</View>
|
|
151
|
-
) : null}
|
|
152
|
-
|
|
153
|
-
{activeFilterAction ? (
|
|
154
|
-
<View style={styles.printerActionBlock}>
|
|
155
|
-
<TouchableOpacity
|
|
156
|
-
style={[
|
|
157
|
-
styles.createPrinterBtn,
|
|
158
|
-
{backgroundColor: brandColors.primary},
|
|
159
|
-
]}
|
|
160
|
-
activeOpacity={0.86}
|
|
161
|
-
onPress={() => navigation.navigate(activeFilterAction.routeName)}>
|
|
162
|
-
<Icon name="plus-circle" size={16} color={brandColors.white} />
|
|
163
|
-
<Text style={styles.createPrinterBtnText}>
|
|
164
|
-
{activeFilterAction.label}
|
|
165
|
-
</Text>
|
|
166
|
-
</TouchableOpacity>
|
|
167
|
-
|
|
168
|
-
<Text style={styles.helperText}>
|
|
169
|
-
{activeFilterAction.helperText}
|
|
170
|
-
</Text>
|
|
171
|
-
</View>
|
|
172
|
-
) : null}
|
|
173
|
-
|
|
174
|
-
{ActiveTabComponent ? (
|
|
175
|
-
<ActiveTabComponent
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
export default Devices;
|
|
1
|
+
import React, {useEffect, useMemo, useState} from 'react';
|
|
2
|
+
import {Text, TouchableOpacity, View} from 'react-native';
|
|
3
|
+
import {SafeAreaView} from 'react-native-safe-area-context';
|
|
4
|
+
import {useNavigation} from '@react-navigation/native';
|
|
5
|
+
import {useStore} from '@store';
|
|
6
|
+
import {resolveThemePalette} from '@controleonline/../../src/styles/branding';
|
|
7
|
+
import {colors} from '@controleonline/../../src/styles/colors';
|
|
8
|
+
import CompactFilterSelector from '@controleonline/ui-default/src/react/components/filters/CompactFilterSelector';
|
|
9
|
+
import {PDV_DEVICE_TYPE} from '@controleonline/ui-common/src/react/utils/printerDevices';
|
|
10
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
11
|
+
import {
|
|
12
|
+
ALL_DEVICE_FILTER,
|
|
13
|
+
getDeviceCreationAction,
|
|
14
|
+
getDeviceFilterAccent,
|
|
15
|
+
getDeviceFilterDefinition,
|
|
16
|
+
getDeviceFilterIcon,
|
|
17
|
+
getDeviceFilterOptions,
|
|
18
|
+
getPdvSubfilterOptions,
|
|
19
|
+
hasRegisteredDeviceFilter,
|
|
20
|
+
isPdvSubfilter,
|
|
21
|
+
} from './Devices/deviceTypes';
|
|
22
|
+
import { createStyles } from './Devices.styles';
|
|
23
|
+
|
|
24
|
+
const tt = (type, key) => global.t?.t('configs', type, key);
|
|
25
|
+
|
|
26
|
+
const Devices = () => {
|
|
27
|
+
const navigation = useNavigation();
|
|
28
|
+
const peopleStore = useStore('people');
|
|
29
|
+
const themeStore = useStore('theme');
|
|
30
|
+
|
|
31
|
+
const {currentCompany} = peopleStore.getters;
|
|
32
|
+
const {colors: themeColors} = themeStore.getters;
|
|
33
|
+
|
|
34
|
+
const [activeFilter, setActiveFilter] = useState(ALL_DEVICE_FILTER);
|
|
35
|
+
|
|
36
|
+
const brandColors = useMemo(
|
|
37
|
+
() =>
|
|
38
|
+
resolveThemePalette(
|
|
39
|
+
{...themeColors, ...(currentCompany?.theme?.colors || {})},
|
|
40
|
+
colors,
|
|
41
|
+
),
|
|
42
|
+
[themeColors, currentCompany?.id],
|
|
43
|
+
);
|
|
44
|
+
const styles = useMemo(() => createStyles(brandColors), [brandColors]);
|
|
45
|
+
const accentPalette = useMemo(
|
|
46
|
+
() => ({
|
|
47
|
+
primary: brandColors.info,
|
|
48
|
+
success: brandColors.success,
|
|
49
|
+
danger: brandColors.error,
|
|
50
|
+
warning: brandColors.warning,
|
|
51
|
+
}),
|
|
52
|
+
[brandColors.error, brandColors.info, brandColors.success, brandColors.warning],
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const filterOptions = useMemo(() => getDeviceFilterOptions(), []);
|
|
56
|
+
const pdvSubfilterOptions = useMemo(() => getPdvSubfilterOptions(), []);
|
|
57
|
+
const activeFilterDefinition = useMemo(
|
|
58
|
+
() => getDeviceFilterDefinition(activeFilter),
|
|
59
|
+
[activeFilter],
|
|
60
|
+
);
|
|
61
|
+
const topLevelActiveFilter = useMemo(
|
|
62
|
+
() => (isPdvSubfilter(activeFilter) ? PDV_DEVICE_TYPE : activeFilter),
|
|
63
|
+
[activeFilter],
|
|
64
|
+
);
|
|
65
|
+
const activeFilterAction = useMemo(
|
|
66
|
+
() => getDeviceCreationAction(topLevelActiveFilter),
|
|
67
|
+
[topLevelActiveFilter],
|
|
68
|
+
);
|
|
69
|
+
const deviceTypeSelectorOptions = useMemo(
|
|
70
|
+
() => filterOptions.map(option => ({
|
|
71
|
+
key: option.key,
|
|
72
|
+
label: option.label,
|
|
73
|
+
})),
|
|
74
|
+
[filterOptions],
|
|
75
|
+
);
|
|
76
|
+
const pdvGatewaySelectorOptions = useMemo(
|
|
77
|
+
() => [
|
|
78
|
+
{key: PDV_DEVICE_TYPE, label: tt('device_filter', 'all') || 'Todos'},
|
|
79
|
+
...pdvSubfilterOptions.map(option => ({
|
|
80
|
+
key: option.key,
|
|
81
|
+
label: option.label,
|
|
82
|
+
})),
|
|
83
|
+
],
|
|
84
|
+
[pdvSubfilterOptions],
|
|
85
|
+
);
|
|
86
|
+
const selectedDeviceTypeLabel = useMemo(
|
|
87
|
+
() =>
|
|
88
|
+
deviceTypeSelectorOptions.find(option => option.key === topLevelActiveFilter)?.label ||
|
|
89
|
+
tt('device_filter', 'allTypes') ||
|
|
90
|
+
'Todos os tipos',
|
|
91
|
+
[deviceTypeSelectorOptions, topLevelActiveFilter],
|
|
92
|
+
);
|
|
93
|
+
const selectedPdvGatewayLabel = useMemo(
|
|
94
|
+
() =>
|
|
95
|
+
pdvGatewaySelectorOptions.find(option => option.key === activeFilter)?.label ||
|
|
96
|
+
tt('device_filter', 'all') ||
|
|
97
|
+
'Todos',
|
|
98
|
+
[activeFilter, pdvGatewaySelectorOptions],
|
|
99
|
+
);
|
|
100
|
+
const ActiveTabComponent = activeFilterDefinition.TabComponent;
|
|
101
|
+
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (!hasRegisteredDeviceFilter(activeFilter)) {
|
|
104
|
+
setActiveFilter(ALL_DEVICE_FILTER);
|
|
105
|
+
}
|
|
106
|
+
}, [activeFilter]);
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<SafeAreaView
|
|
110
|
+
style={[styles.container, {backgroundColor: brandColors.background}]}>
|
|
111
|
+
<View style={styles.filtersBlock}>
|
|
112
|
+
<Text style={styles.filtersLabel}>{tt('device_filter', 'filterByType') || 'Filtrar por tipo'}</Text>
|
|
113
|
+
<CompactFilterSelector
|
|
114
|
+
icon={getDeviceFilterIcon(topLevelActiveFilter)}
|
|
115
|
+
label={selectedDeviceTypeLabel}
|
|
116
|
+
title={tt('device_filter', 'filterByType') || 'Filtrar por tipo'}
|
|
117
|
+
accentColor={getDeviceFilterAccent(topLevelActiveFilter, {
|
|
118
|
+
brandColors,
|
|
119
|
+
hex: accentPalette,
|
|
120
|
+
})}
|
|
121
|
+
active={topLevelActiveFilter !== ALL_DEVICE_FILTER}
|
|
122
|
+
options={deviceTypeSelectorOptions}
|
|
123
|
+
selectedKey={topLevelActiveFilter}
|
|
124
|
+
onSelect={optionKey => {
|
|
125
|
+
setActiveFilter(optionKey);
|
|
126
|
+
return true;
|
|
127
|
+
}}
|
|
128
|
+
/>
|
|
129
|
+
</View>
|
|
130
|
+
|
|
131
|
+
{topLevelActiveFilter === PDV_DEVICE_TYPE && pdvSubfilterOptions.length > 0 ? (
|
|
132
|
+
<View style={styles.filtersBlock}>
|
|
133
|
+
<Text style={styles.filtersLabel}>{tt('device_filter', 'pdvGateway') || 'Gateway do PDV'}</Text>
|
|
134
|
+
<CompactFilterSelector
|
|
135
|
+
icon={getDeviceFilterIcon(activeFilter)}
|
|
136
|
+
label={selectedPdvGatewayLabel}
|
|
137
|
+
title={tt('device_filter', 'pdvGateway') || 'Gateway do PDV'}
|
|
138
|
+
accentColor={getDeviceFilterAccent(activeFilter, {
|
|
139
|
+
brandColors,
|
|
140
|
+
hex: accentPalette,
|
|
141
|
+
})}
|
|
142
|
+
active={activeFilter !== PDV_DEVICE_TYPE}
|
|
143
|
+
options={pdvGatewaySelectorOptions}
|
|
144
|
+
selectedKey={activeFilter}
|
|
145
|
+
onSelect={optionKey => {
|
|
146
|
+
setActiveFilter(optionKey);
|
|
147
|
+
return true;
|
|
148
|
+
}}
|
|
149
|
+
/>
|
|
150
|
+
</View>
|
|
151
|
+
) : null}
|
|
152
|
+
|
|
153
|
+
{activeFilterAction ? (
|
|
154
|
+
<View style={styles.printerActionBlock}>
|
|
155
|
+
<TouchableOpacity
|
|
156
|
+
style={[
|
|
157
|
+
styles.createPrinterBtn,
|
|
158
|
+
{backgroundColor: brandColors.primary},
|
|
159
|
+
]}
|
|
160
|
+
activeOpacity={0.86}
|
|
161
|
+
onPress={() => navigation.navigate(activeFilterAction.routeName)}>
|
|
162
|
+
<Icon name="plus-circle" size={16} color={brandColors.white} />
|
|
163
|
+
<Text style={styles.createPrinterBtnText}>
|
|
164
|
+
{activeFilterAction.label}
|
|
165
|
+
</Text>
|
|
166
|
+
</TouchableOpacity>
|
|
167
|
+
|
|
168
|
+
<Text style={styles.helperText}>
|
|
169
|
+
{activeFilterAction.helperText}
|
|
170
|
+
</Text>
|
|
171
|
+
</View>
|
|
172
|
+
) : null}
|
|
173
|
+
|
|
174
|
+
{ActiveTabComponent ? (
|
|
175
|
+
<ActiveTabComponent
|
|
176
|
+
key={`${activeFilter}-${currentCompany?.id || 'company'}`}
|
|
177
|
+
/>
|
|
178
|
+
) : null}
|
|
179
|
+
</SafeAreaView>
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export default Devices;
|
|
@@ -14,7 +14,6 @@ import { fetchPeopleConfigs } from './fetchPeopleConfigs';
|
|
|
14
14
|
import IntegrationConfigFields from './IntegrationConfigFields';
|
|
15
15
|
import {
|
|
16
16
|
ROUTE_PROVIDER_MAP,
|
|
17
|
-
expandBundledConfig,
|
|
18
17
|
extractAuthorizationUrl,
|
|
19
18
|
formatApiError,
|
|
20
19
|
formatUberOAuthError,
|
|
@@ -113,8 +112,6 @@ export default function IntegrationConfigPage({ route, embedded = false, fiscalT
|
|
|
113
112
|
const allFieldKeysSig = useMemo(() => allFieldKeys.join('|'), [allFieldKeys]);
|
|
114
113
|
// Pure config providers (e.g. receita-federal) do not use marketplace/integrations.
|
|
115
114
|
const needsMarketplaceIntegration = Boolean(providerConfig?.oauthConnect);
|
|
116
|
-
const bundleKey = normalizeTextValue(providerConfig?.bundleKey);
|
|
117
|
-
const configVisibility = normalizeTextValue(providerConfig?.visibility) || 'public';
|
|
118
115
|
|
|
119
116
|
useEffect(() => {
|
|
120
117
|
setConfigValues({});
|
|
@@ -138,28 +135,14 @@ export default function IntegrationConfigPage({ route, embedded = false, fiscalT
|
|
|
138
135
|
}
|
|
139
136
|
if (showLoading) setLoading(true);
|
|
140
137
|
try {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
configKeys: [bundleKey],
|
|
145
|
-
});
|
|
146
|
-
const bundled = configItems.find(
|
|
147
|
-
item => String(item?.configKey || '').trim() === bundleKey,
|
|
148
|
-
);
|
|
149
|
-
const mergeFields = allConfigFields.length ? allConfigFields : visibleFields;
|
|
150
|
-
setConfigValues(current =>
|
|
151
|
-
expandBundledConfig(mergeFields, bundled?.configValue, current),
|
|
152
|
-
);
|
|
153
|
-
} else {
|
|
154
|
-
const keys = allFieldKeys.length
|
|
155
|
-
? allFieldKeys
|
|
156
|
-
: visibleFields.map(field => field.key).filter(Boolean);
|
|
138
|
+
const keys = allFieldKeys.length
|
|
139
|
+
? allFieldKeys
|
|
140
|
+
: visibleFields.map(field => field.key).filter(Boolean);
|
|
157
141
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
142
|
+
if (keys.length) {
|
|
143
|
+
const configItems = await fetchPeopleConfigs({ peopleIri: providerIri, configKeys: keys });
|
|
144
|
+
const mergeFields = allConfigFields.length ? allConfigFields : visibleFields;
|
|
145
|
+
setConfigValues(current => mergeTabValues(mergeFields, configItems, current));
|
|
163
146
|
}
|
|
164
147
|
|
|
165
148
|
if (needsMarketplaceIntegration) {
|
|
@@ -187,7 +170,6 @@ export default function IntegrationConfigPage({ route, embedded = false, fiscalT
|
|
|
187
170
|
allConfigFields,
|
|
188
171
|
allFieldKeys,
|
|
189
172
|
allFieldKeysSig,
|
|
190
|
-
bundleKey,
|
|
191
173
|
needsMarketplaceIntegration,
|
|
192
174
|
providerConfig,
|
|
193
175
|
providerIri,
|
|
@@ -264,44 +246,16 @@ export default function IntegrationConfigPage({ route, embedded = false, fiscalT
|
|
|
264
246
|
showError('Nao foi possivel identificar a integracao selecionada.');
|
|
265
247
|
return;
|
|
266
248
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
(visibleFields || []).forEach(field => {
|
|
272
|
-
payloadObject[field.key] = normalizeTextValue(configValues[field.key]);
|
|
273
|
-
});
|
|
274
|
-
configs = [
|
|
275
|
-
{
|
|
276
|
-
configKey: bundleKey,
|
|
277
|
-
configValue: toConfigRequestValue(payloadObject),
|
|
278
|
-
},
|
|
279
|
-
];
|
|
280
|
-
} else {
|
|
281
|
-
configs = visibleFields.map(field => ({
|
|
282
|
-
configKey: field.key,
|
|
283
|
-
configValue: toConfigRequestValue(normalizeTextValue(configValues[field.key])),
|
|
284
|
-
}));
|
|
285
|
-
}
|
|
286
|
-
|
|
249
|
+
const configs = visibleFields.map(field => ({
|
|
250
|
+
configKey: field.key,
|
|
251
|
+
configValue: toConfigRequestValue(normalizeTextValue(configValues[field.key])),
|
|
252
|
+
}));
|
|
287
253
|
try {
|
|
288
|
-
await persistConfigs({ configs, people: providerIri, module: 4, visibility:
|
|
254
|
+
await persistConfigs({ configs, people: providerIri, module: 4, visibility: 'public' });
|
|
289
255
|
showSuccess(`${activeTabDef?.label || providerConfig.label} salvo com sucesso.`);
|
|
290
256
|
await loadPageData({ showLoading: false });
|
|
291
257
|
} catch (error) { showError(error?.message || 'Nao foi possivel salvar a integracao.'); }
|
|
292
|
-
}, [
|
|
293
|
-
activeTabDef,
|
|
294
|
-
bundleKey,
|
|
295
|
-
configValues,
|
|
296
|
-
configVisibility,
|
|
297
|
-
loadPageData,
|
|
298
|
-
persistConfigs,
|
|
299
|
-
providerConfig,
|
|
300
|
-
providerIri,
|
|
301
|
-
showError,
|
|
302
|
-
showSuccess,
|
|
303
|
-
visibleFields,
|
|
304
|
-
]);
|
|
258
|
+
}, [activeTabDef, configValues, loadPageData, persistConfigs, providerConfig, providerIri, showError, showSuccess, visibleFields]);
|
|
305
259
|
|
|
306
260
|
if (!providerConfig) return <CenterState icon="alert-triangle" iconColor="#e67e22" title="Integracao indisponivel" text="A tela solicitada nao possui configuracao cadastrada." />;
|
|
307
261
|
if (!providerId) return <CenterState icon="building" iconColor="#94A3B8" title="Empresa nao identificada" text="Abra a ficha da empresa para gravar as configuracoes fiscais nela." />;
|
|
@@ -5,7 +5,6 @@ export const ROUTE_PROVIDER_MAP = {
|
|
|
5
5
|
AsaasIntegrationPage: 'asaas',
|
|
6
6
|
ClickSignIntegrationPage: 'clicksign',
|
|
7
7
|
ReceitaFederalIntegrationPage: 'receita-federal',
|
|
8
|
-
SemPararIntegrationPage: 'sem-parar',
|
|
9
8
|
};
|
|
10
9
|
|
|
11
10
|
export const routeNameToPath = routeName =>
|
|
@@ -54,22 +53,6 @@ export const mergeTabValues = (fields, source, current = {}) => {
|
|
|
54
53
|
return next;
|
|
55
54
|
};
|
|
56
55
|
|
|
57
|
-
/** Expand a single JSON config (bundleKey) into flat field values. */
|
|
58
|
-
export const expandBundledConfig = (fields, rawValue, current = {}) => {
|
|
59
|
-
let parsed = rawValue;
|
|
60
|
-
if (typeof rawValue === 'string') {
|
|
61
|
-
try {
|
|
62
|
-
parsed = JSON.parse(rawValue);
|
|
63
|
-
} catch {
|
|
64
|
-
parsed = {};
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
68
|
-
parsed = {};
|
|
69
|
-
}
|
|
70
|
-
return mergeTabValues(fields, parsed, current);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
56
|
export const buildFieldValues = (providerConfig, source) =>
|
|
74
57
|
mergeTabValues(getConfigFields(providerConfig), source, {});
|
|
75
58
|
|
|
@@ -70,16 +70,6 @@ export const INTEGRATION_LIST = [
|
|
|
70
70
|
accent: '#166534',
|
|
71
71
|
icon: 'file-text',
|
|
72
72
|
},
|
|
73
|
-
{
|
|
74
|
-
key: 'sem-parar',
|
|
75
|
-
label: 'Sem Parar',
|
|
76
|
-
route: 'IntegrationConfigPage',
|
|
77
|
-
routeParams: {
|
|
78
|
-
providerKey: 'sem-parar',
|
|
79
|
-
},
|
|
80
|
-
accent: '#0EA5E9',
|
|
81
|
-
icon: 'truck',
|
|
82
|
-
},
|
|
83
73
|
];
|
|
84
74
|
|
|
85
75
|
export const INTEGRATION_CONFIGS = {
|
|
@@ -267,67 +257,6 @@ export const INTEGRATION_CONFIGS = {
|
|
|
267
257
|
],
|
|
268
258
|
fields: [],
|
|
269
259
|
},
|
|
270
|
-
|
|
271
|
-
'sem-parar': {
|
|
272
|
-
key: 'sem-parar',
|
|
273
|
-
label: 'Sem Parar',
|
|
274
|
-
accent: '#0EA5E9',
|
|
275
|
-
icon: 'truck',
|
|
276
|
-
description:
|
|
277
|
-
'Credenciais da empresa para emissao de vale-pedagio via Sem Parar.',
|
|
278
|
-
saveLabel: 'Salvar Sem Parar',
|
|
279
|
-
// Backend (api-platform-integration SemPararConfig) reads a single private JSON key.
|
|
280
|
-
bundleKey: 'SEM_PARAR',
|
|
281
|
-
visibility: 'private',
|
|
282
|
-
requiredKeys: ['ENABLED', 'CLIENT_ID', 'CLIENT_SECRET', 'USERNAME', 'PASSWORD'],
|
|
283
|
-
fields: [
|
|
284
|
-
{
|
|
285
|
-
key: 'ENABLED',
|
|
286
|
-
label: 'Ativo',
|
|
287
|
-
type: 'select',
|
|
288
|
-
options: [
|
|
289
|
-
{value: '1', label: 'Sim'},
|
|
290
|
-
{value: '0', label: 'Nao'},
|
|
291
|
-
],
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
key: 'ENVIRONMENT',
|
|
295
|
-
label: 'Ambiente',
|
|
296
|
-
type: 'select',
|
|
297
|
-
options: [
|
|
298
|
-
{value: 'sandbox', label: 'Sandbox'},
|
|
299
|
-
{value: 'production', label: 'Producao'},
|
|
300
|
-
],
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
key: 'CLIENT_ID',
|
|
304
|
-
label: 'Client ID',
|
|
305
|
-
placeholder: 'Client ID Sem Parar',
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
key: 'CLIENT_SECRET',
|
|
309
|
-
label: 'Client secret',
|
|
310
|
-
placeholder: 'Client secret Sem Parar',
|
|
311
|
-
secureTextEntry: true,
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
key: 'USERNAME',
|
|
315
|
-
label: 'Usuario',
|
|
316
|
-
placeholder: 'Usuario da API',
|
|
317
|
-
},
|
|
318
|
-
{
|
|
319
|
-
key: 'PASSWORD',
|
|
320
|
-
label: 'Senha',
|
|
321
|
-
placeholder: 'Senha da API',
|
|
322
|
-
secureTextEntry: true,
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
key: 'CONVENIADO',
|
|
326
|
-
label: 'Conveniado',
|
|
327
|
-
placeholder: 'Codigo do conveniado (se aplicavel)',
|
|
328
|
-
},
|
|
329
|
-
],
|
|
330
|
-
},
|
|
331
260
|
};
|
|
332
261
|
|
|
333
262
|
export const getIntegrationListItem = key =>
|