@controleonline/ui-common 1.2.71 → 1.2.75
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/actions/workers/manager/action.yml +147 -0
- package/.github/actions/workers/qa/action.yml +44 -0
- package/.github/actions/workers/security/action.yml +44 -0
- package/.github/actions/workers/technical-documenter/action.yml +51 -0
- package/.github/workflows/manager-worker.yml +168 -0
- package/.github/workflows/publish-npm.yml +45 -0
- package/.gitmodules +3 -0
- package/AGENTS.md +6 -0
- package/README.md +14 -0
- package/package.json +3 -2
- package/src/api/fetch.js +1 -1
- package/src/api/index.js +92 -22
- package/src/react/components/AddImportModal.js +94 -110
- package/src/react/components/BottomNavigationBar.config.js +211 -231
- package/src/react/components/CategoryForm.js +52 -35
- package/src/react/components/DefaultProvider.native.js +131 -95
- package/src/react/components/DefaultProvider.web.js +148 -74
- package/src/react/components/NetworkPrinterPreviewModal.js +249 -0
- package/src/react/components/NetworkPrinterPreviewModal.styles.js +159 -0
- package/src/react/components/RuntimeInfoFooter.js +100 -36
- package/src/react/components/RuntimeInfoFooter.styles.js +3 -0
- package/src/react/components/UnifiedPaymentBar.js +7 -4
- package/src/react/components/UserAvatar.js +160 -0
- package/src/react/components/integrations/IntegrationHero/index.js +48 -0
- package/src/react/components/integrations/IntegrationHero/styles.js +57 -0
- package/src/react/components/integrations/IntegrationTabs/index.js +89 -0
- package/src/react/components/integrations/IntegrationTabs/styles.js +44 -0
- package/src/react/config/deviceConfigBootstrap.js +5 -3
- package/src/react/pages/Connections.js +229 -0
- package/src/react/pages/Connections.styles.js +222 -0
- package/src/react/pages/DeviceDetailPage.js +2814 -0
- package/src/react/pages/DeviceDetailPage.styles.js +308 -0
- package/src/react/pages/Devices/currentDevice.js +194 -0
- package/src/react/pages/Devices/deviceTypes/DeviceGroupCard.js +257 -0
- package/src/react/pages/Devices/deviceTypes/all.js +23 -0
- package/src/react/pages/Devices/deviceTypes/device.js +25 -0
- package/src/react/pages/Devices/deviceTypes/deviceListHelpers.js +178 -0
- package/src/react/pages/Devices/deviceTypes/display.js +26 -0
- package/src/react/pages/Devices/deviceTypes/index.js +145 -0
- package/src/react/pages/Devices/deviceTypes/ipCamera.js +35 -0
- package/src/react/pages/Devices/deviceTypes/pdv.js +88 -0
- package/src/react/pages/Devices/deviceTypes/printer.js +37 -0
- package/src/react/pages/Devices/deviceTypes/shared.js +453 -0
- package/src/react/pages/Devices/deviceTypes/useDeviceNetworkConnectivity.js +145 -0
- package/src/react/pages/Devices.js +183 -0
- package/src/react/pages/Devices.styles.js +353 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99CatalogTab.js +219 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99OverviewTab.js +134 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99PreviewModal.js +173 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99ProductCard.js +1 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99QuickWalletModal.js +181 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99SettingsTab.js +306 -0
- package/src/react/pages/Food99IntegrationPage/components/Food99StoreTab.js +417 -0
- package/src/react/pages/Food99IntegrationPage/index.js +1530 -0
- package/src/react/pages/Food99IntegrationPage/styles.js +792 -0
- package/src/react/pages/Food99IntegrationPage/utils.js +155 -0
- package/src/react/pages/Food99IntegrationPage.js +1 -0
- package/src/react/pages/Food99IntegrationPage.styles.js +1 -0
- package/src/react/pages/GenericLogPage.js +42 -167
- package/src/react/pages/IFoodIntegrationPage/components/IFoodCatalogTab.js +8 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOperationsTab.js +420 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodOverviewTab.js +118 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodPreviewModal.js +103 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodProductCard.js +1 -0
- package/src/react/pages/IFoodIntegrationPage/components/IFoodStoreTab.js +150 -0
- package/src/react/pages/IFoodIntegrationPage/index.js +1298 -0
- package/src/react/pages/IFoodIntegrationPage/styles.js +764 -0
- package/src/react/pages/IFoodIntegrationPage/utils.js +91 -0
- package/src/react/pages/IFoodIntegrationPage.js +1 -0
- package/src/react/pages/IFoodIntegrationPage.styles.js +1 -0
- package/src/react/pages/Imports.js +214 -166
- package/src/react/pages/IntegrationConfigPage.js +744 -0
- package/src/react/pages/IntegrationConfigPage.styles.js +269 -0
- package/src/react/pages/Integrations.js +299 -0
- package/src/react/pages/Integrations.styles.js +130 -0
- package/src/react/pages/ManagerOrderNotificationsPage.js +642 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/MarketplaceProductCard.js +205 -0
- package/src/react/pages/MarketplaceIntegrationPage/components/RemoteMarketplaceMenuTab.js +335 -0
- package/src/react/pages/MarketplaceIntegrationPage/index.js +60 -0
- package/src/react/pages/MarketplaceIntegrationPage/utils.js +137 -0
- package/src/react/pages/MercadoLivreIntegrationPage.js +538 -0
- package/src/react/pages/PrinterDeviceDetailPage.js +1916 -0
- package/src/react/pages/PrinterDeviceDetailPage.styles.js +223 -0
- package/src/react/pages/PrinterDeviceFormPage.js +521 -0
- package/src/react/pages/PrinterDeviceFormPage.styles.js +159 -0
- package/src/react/pages/WhatsAppConnectionPage.js +459 -0
- package/src/react/pages/WhatsAppConnectionPage.styles.js +284 -0
- package/src/react/pages/integrationsCatalog.js +399 -0
- package/src/react/services/Cielo/Cielo.js +193 -193
- package/src/react/utils/categoryContexts.js +46 -0
- package/src/react/utils/entityDisplay.js +222 -217
- package/src/react/utils/fileUrl.js +39 -20
- package/src/react/utils/integrationPage.js +16 -0
- package/src/react/utils/runtimeFooter.js +40 -22
- package/src/react/utils/runtimeLanguage.js +50 -9
- package/src/react/utils/runtimeMenu.js +191 -131
- package/src/react/utils/runtimeZoom.js +43 -0
- package/src/react/utils/shopConfig.js +27 -15
- package/src/react/utils/shopFranchises.js +126 -1
- package/src/react/utils/storeColumns.js +23 -4
- package/src/react/utils/userAvatar.js +104 -0
- package/src/store/categories/index.js +48 -20
- package/src/store/device_config/index.js +62 -21
- package/src/store/entity_log/index.js +22 -1
- package/src/store/imports/customActions.js +51 -0
- package/src/store/imports/index.js +89 -88
- package/src/store/status/index.js +11 -11
- package/src/store/themes/index.js +22 -0
- package/src/store/timezones/index.js +3 -1
- package/src/tests/browser/manager/connections.spec.js +143 -0
- package/src/tests/browser/manager/devices-current.spec.js +343 -0
- package/src/tests/browser/manager/mercado-livre-integration.spec.js +268 -0
- package/src/tests/react/api/deviceHeaders.test.js +114 -0
- package/src/tests/react/components/AddImportModal.test.js +166 -0
- package/src/tests/react/components/BottomNavigationBar.config.test.js +20 -0
- package/src/tests/react/components/UserAvatar.test.js +52 -0
- package/src/tests/react/pages/DevicePickerStyles.test.js +47 -0
- package/src/tests/react/pages/Devices/deviceListHelpers.test.js +39 -0
- package/src/tests/react/pages/DevicesCurrentDevice.test.js +198 -0
- package/src/tests/react/pages/connectionsHelpers.test.js +34 -0
- package/src/tests/react/pages/mercadoLivreIntegrationPageContract.test.mjs +16 -0
- package/src/tests/react/services/Cielo.test.js +190 -190
- package/src/tests/react/store/categoriesOrdering.test.js +26 -0
- package/src/tests/react/utils/appDomain.test.js +62 -0
- package/src/tests/react/utils/entityDisplay.test.js +2 -2
- package/src/tests/react/utils/fileUrl.test.js +3 -3
- package/src/tests/react/utils/formatter.test.mjs +33 -0
- package/src/tests/react/utils/runtimeFooter.test.js +29 -4
- package/src/tests/react/utils/runtimeLanguage.test.js +79 -9
- package/src/tests/react/utils/runtimeMenu.test.js +198 -134
- package/src/tests/react/utils/runtimeZoom.test.js +38 -0
- package/src/tests/react/utils/shopConfig.test.js +10 -9
- package/src/tests/react/utils/shopFranchises.test.js +43 -0
- package/src/tests/react/utils/translate.discovery.test.mjs +170 -0
- package/src/tests/react/utils/translate.test.helpers.mjs +152 -0
- package/src/tests/react/utils/translate.test.mjs +141 -349
- package/src/tests/react/utils/userAvatar.test.js +63 -0
- package/src/utils/appDomain.js +15 -4
- package/src/utils/formatter.js +104 -16
- package/src/utils/integrationConfigs.js +80 -80
- package/src/utils/translate.js +222 -438
- package/src/utils/translateDiscovery.js +96 -0
- package/src/utils/translateNormalize.js +33 -0
- package/src/utils/translatePending.js +92 -0
- package/src/utils/translateStorage.js +142 -0
- package/.github/agents/developer.agent.md +0 -30
- package/.github/agents/devops.agent.md +0 -30
- package/.github/agents/qa.agent.md +0 -30
- package/.github/agents/security.agent.md +0 -30
- package/.github/workflows/npmjs.yml +0 -35
package/src/api/index.js
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
import myFetch from '@controleonline/ui-common/src/api/fetch';
|
|
2
2
|
import axios from 'axios';
|
|
3
|
-
import { APP_ENV
|
|
3
|
+
import {env as APP_ENV} from '@env';
|
|
4
4
|
import { resolveAppDomain } from '@controleonline/ui-common/src/utils/appDomain';
|
|
5
5
|
import { resolveApiEntryPoint } from '@controleonline/ui-common/src/utils/apiEntryPoint';
|
|
6
6
|
|
|
7
7
|
const MIME_TYPE = 'application/ld+json';
|
|
8
|
+
const DOMAIN_QUERY_PARAM_KEYS = new Set(['app-domain', 'appdomain']);
|
|
9
|
+
|
|
10
|
+
function stripDomainQueryParams(uri) {
|
|
11
|
+
const value = String(uri || '');
|
|
12
|
+
const hashIndex = value.indexOf('#');
|
|
13
|
+
const withoutHash = hashIndex >= 0 ? value.slice(0, hashIndex) : value;
|
|
14
|
+
const hash = hashIndex >= 0 ? value.slice(hashIndex) : '';
|
|
15
|
+
const queryIndex = withoutHash.indexOf('?');
|
|
16
|
+
|
|
17
|
+
if (queryIndex < 0) {
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const path = withoutHash.slice(0, queryIndex);
|
|
22
|
+
const params = new URLSearchParams(withoutHash.slice(queryIndex + 1));
|
|
23
|
+
|
|
24
|
+
for (const key of [...params.keys()]) {
|
|
25
|
+
if (DOMAIN_QUERY_PARAM_KEYS.has(String(key || '').trim().toLowerCase())) {
|
|
26
|
+
params.delete(key);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const query = params.toString();
|
|
31
|
+
return `${path}${query ? `?${query}` : ''}${hash}`;
|
|
32
|
+
}
|
|
8
33
|
|
|
9
34
|
function encodeBasicAuth(user, password) {
|
|
10
35
|
const credentials = `${String(user || '').trim()}:${String(password || '').trim()}`;
|
|
@@ -36,13 +61,26 @@ function resolveApiRuntimeConfig(config = {}) {
|
|
|
36
61
|
function buildApiUrl(apiBaseUrl, path) {
|
|
37
62
|
const apiEntryPoint = resolveApiEntryPoint(apiBaseUrl);
|
|
38
63
|
const entryPoint = apiEntryPoint + (apiEntryPoint.endsWith('/') ? '' : '/');
|
|
39
|
-
const
|
|
64
|
+
const rawPath = String(path || '').startsWith('/')
|
|
40
65
|
? String(path || '').substring(1)
|
|
41
66
|
: String(path || '');
|
|
67
|
+
const normalizedPath = stripDomainQueryParams(rawPath);
|
|
42
68
|
|
|
43
69
|
return new URL(normalizedPath, entryPoint).href;
|
|
44
70
|
}
|
|
45
71
|
|
|
72
|
+
function resolveRequestDevice(masterDevice, device, bodyDeviceId) {
|
|
73
|
+
if (masterDevice?.id) {
|
|
74
|
+
return masterDevice;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (device?.id) {
|
|
78
|
+
return device;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return bodyDeviceId ? {id: bodyDeviceId} : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
46
84
|
async function readSmokeResponseBody(response, responseType) {
|
|
47
85
|
if (responseType === 'blob') {
|
|
48
86
|
return await response.blob();
|
|
@@ -242,9 +280,22 @@ export const api = {
|
|
|
242
280
|
}
|
|
243
281
|
}
|
|
244
282
|
|
|
245
|
-
const
|
|
246
|
-
this.masterDevice
|
|
247
|
-
|
|
283
|
+
const requestDevice = resolveRequestDevice(
|
|
284
|
+
this.masterDevice,
|
|
285
|
+
this.device,
|
|
286
|
+
bodyDeviceId,
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
if (requestDevice?.id) {
|
|
290
|
+
options.headers.set('DEVICE', requestDevice.id);
|
|
291
|
+
|
|
292
|
+
const requestDeviceType = String(requestDevice.type || '')
|
|
293
|
+
.trim()
|
|
294
|
+
.toUpperCase();
|
|
295
|
+
if (requestDeviceType !== '') {
|
|
296
|
+
options.headers.set('DEVICE-TYPE', requestDeviceType);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
248
299
|
if (options.responseType != 'text') {
|
|
249
300
|
options.headers.set('Content-Type', MIME_TYPE);
|
|
250
301
|
options.headers.set('Accept', MIME_TYPE);
|
|
@@ -254,9 +305,11 @@ export const api = {
|
|
|
254
305
|
if (options.body && typeof options.body != 'string') {
|
|
255
306
|
options.body = JSON.stringify(options.body);
|
|
256
307
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
308
|
+
uri = stripDomainQueryParams(uri);
|
|
309
|
+
|
|
310
|
+
if (options.params) {
|
|
311
|
+
uri = this.buildQueryString(uri, options);
|
|
312
|
+
}
|
|
260
313
|
return myFetch(uri, options).catch(e => {
|
|
261
314
|
throw e;
|
|
262
315
|
});
|
|
@@ -279,13 +332,18 @@ export const api = {
|
|
|
279
332
|
|
|
280
333
|
return session?.token || session?.api_key;
|
|
281
334
|
},
|
|
282
|
-
serialize(obj, prefix = '') {
|
|
283
|
-
const pairs = [];
|
|
284
|
-
|
|
285
|
-
for (const key in obj) {
|
|
286
|
-
if (obj.hasOwnProperty(key)) {
|
|
287
|
-
const
|
|
288
|
-
|
|
335
|
+
serialize(obj, prefix = '') {
|
|
336
|
+
const pairs = [];
|
|
337
|
+
|
|
338
|
+
for (const key in obj) {
|
|
339
|
+
if (obj.hasOwnProperty(key)) {
|
|
340
|
+
const normalizedKey = String(key || '').trim().toLowerCase();
|
|
341
|
+
if (DOMAIN_QUERY_PARAM_KEYS.has(normalizedKey)) {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const value = obj[key];
|
|
346
|
+
let fullKey = prefix ? `${prefix}.${key}` : key; // Usa ponto para objetos
|
|
289
347
|
|
|
290
348
|
if (value === null || value === undefined) {
|
|
291
349
|
pairs.push(`${fullKey}=`);
|
|
@@ -314,13 +372,25 @@ export const api = {
|
|
|
314
372
|
return pairs;
|
|
315
373
|
},
|
|
316
374
|
|
|
317
|
-
buildQueryString(uri, options) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
375
|
+
buildQueryString(uri, options) {
|
|
376
|
+
const safeUri = stripDomainQueryParams(uri);
|
|
377
|
+
|
|
378
|
+
if (options.params) {
|
|
379
|
+
const params = this.serialize(options.params);
|
|
380
|
+
if (params.length === 0) {
|
|
381
|
+
return safeUri;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const hashIndex = safeUri.indexOf('#');
|
|
385
|
+
const withoutHash = hashIndex >= 0 ? safeUri.slice(0, hashIndex) : safeUri;
|
|
386
|
+
const hash = hashIndex >= 0 ? safeUri.slice(hashIndex) : '';
|
|
387
|
+
const separator = withoutHash.includes('?') ? '&' : '?';
|
|
388
|
+
|
|
389
|
+
return `${withoutHash}${separator}${params.join('&')}${hash}`;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return safeUri;
|
|
393
|
+
},
|
|
324
394
|
post: async function (uri, body = {}) {
|
|
325
395
|
const options = {
|
|
326
396
|
method: 'POST',
|
|
@@ -1,108 +1,68 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {
|
|
3
|
-
View,
|
|
4
|
-
Text,
|
|
5
|
-
TouchableOpacity,
|
|
6
|
-
ScrollView,
|
|
7
|
-
ActivityIndicator,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
12
|
-
import * as DocumentPicker from 'expo-document-picker';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
TouchableOpacity,
|
|
6
|
+
ScrollView,
|
|
7
|
+
ActivityIndicator,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
|
|
10
|
+
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
13
11
|
import { useStore } from '@store';
|
|
14
12
|
import AnimatedModal from './AnimatedModal';
|
|
15
|
-
import { api } from '@controleonline/ui-common/src/api';
|
|
16
13
|
import { useMessage } from '@controleonline/ui-common/src/react/components/MessageService';
|
|
14
|
+
import DefaultUpload from '@controleonline/ui-default/src/react/components/upload/DefaultUpload';
|
|
17
15
|
import styles from './AddImportModal.styles';
|
|
18
|
-
|
|
19
|
-
const AddImportModal = ({ visible, onClose, onSuccess, context = {} }) => {
|
|
20
|
-
const { showError, showSuccess } = useMessage();
|
|
21
|
-
const peopleStore = useStore('people');
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const
|
|
16
|
+
|
|
17
|
+
const AddImportModal = ({ visible, onClose, onSuccess, context = {} }) => {
|
|
18
|
+
const { showError, showSuccess } = useMessage();
|
|
19
|
+
const peopleStore = useStore('people');
|
|
20
|
+
const importsStore = useStore('imports');
|
|
21
|
+
const themeStore = useStore('theme');
|
|
22
|
+
const getters = peopleStore.getters;
|
|
23
|
+
const { currentCompany } = getters;
|
|
24
|
+
const importActions = importsStore.actions || {};
|
|
25
|
+
const themeColors = themeStore?.getters?.colors || {};
|
|
26
|
+
const buttonPalette = {
|
|
27
|
+
buttonBackground: themeColors.buttonBackground,
|
|
28
|
+
buttonBorder: themeColors.buttonBorder,
|
|
29
|
+
buttonText: themeColors.buttonText,
|
|
30
|
+
buttonIcon: themeColors.buttonIcon || themeColors.buttonText,
|
|
31
|
+
};
|
|
32
|
+
|
|
27
33
|
const modalTitle = global.t?.t('imports', 'title', 'new_import');
|
|
28
34
|
const csvLabel = global.t?.t('imports', 'label', 'csv_file');
|
|
29
35
|
const selectFileLabel = global.t?.t('imports', 'button', 'select_file');
|
|
30
36
|
const cancelLabel = global.t?.t('imports', 'button', 'cancel');
|
|
31
|
-
const importLabel = global.t?.t('imports', 'button', 'import');
|
|
32
37
|
const csvOnlyLabel = global.t?.t('imports', 'message', 'only_csv_files_are_allowed');
|
|
33
|
-
const pickFileErrorLabel = global.t?.t('imports', 'error', 'error_selecting_file');
|
|
34
38
|
const importSuccessLabel = global.t?.t('imports', 'success', 'import_sent_successfully');
|
|
35
39
|
const importErrorLabel = global.t?.t('imports', 'error', 'error_sending_import');
|
|
36
|
-
const missingFileLabel = global.t?.t('imports', 'error', 'select_a_csv_file');
|
|
37
|
-
|
|
38
|
-
const handlePickFile = async () => {
|
|
39
|
-
try {
|
|
40
|
-
const result = await DocumentPicker.getDocumentAsync({
|
|
41
|
-
type: 'text/csv',
|
|
42
|
-
copyToCacheDirectory: true,
|
|
43
|
-
multiple: false,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
if (result.canceled) return;
|
|
47
|
-
|
|
48
|
-
const pickedFile = result.assets[0];
|
|
49
|
-
|
|
50
|
-
if (!pickedFile.name?.toLowerCase().endsWith('.csv')) {
|
|
51
|
-
showError(csvOnlyLabel);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
setFile(pickedFile);
|
|
56
|
-
} catch {
|
|
57
|
-
showError(pickFileErrorLabel);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
40
|
|
|
61
|
-
const
|
|
62
|
-
if (!file) {
|
|
63
|
-
|
|
64
|
-
return;
|
|
41
|
+
const handleUploadImportFile = async ({ file }) => {
|
|
42
|
+
if (!file?.name?.toLowerCase().endsWith('.csv')) {
|
|
43
|
+
throw new Error(csvOnlyLabel);
|
|
65
44
|
}
|
|
66
|
-
|
|
67
|
-
setLoading(true);
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
const formData = new FormData();
|
|
71
|
-
formData.append('importType', context.context);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
formData.append('people', String(currentCompany.id));
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (Platform.OS === 'web') {
|
|
78
|
-
const response = await fetch(file.uri);
|
|
79
|
-
const blob = await response.blob();
|
|
80
|
-
formData.append('file', blob, file.name || 'import.csv');
|
|
81
|
-
} else {
|
|
82
|
-
formData.append('file', {
|
|
83
|
-
uri: file.uri,
|
|
84
|
-
name: file.name || 'import.csv',
|
|
85
|
-
type: file.mimeType || 'text/csv',
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
45
|
|
|
89
|
-
|
|
46
|
+
try {
|
|
47
|
+
await importActions.uploadImportFile({
|
|
48
|
+
file,
|
|
49
|
+
importType: context.context,
|
|
50
|
+
peopleId: currentCompany.id,
|
|
51
|
+
});
|
|
90
52
|
showSuccess(importSuccessLabel);
|
|
91
53
|
if (onSuccess) onSuccess();
|
|
92
54
|
handleClose();
|
|
55
|
+
return file;
|
|
93
56
|
} catch {
|
|
94
|
-
|
|
95
|
-
} finally {
|
|
96
|
-
setLoading(false);
|
|
57
|
+
throw new Error(importErrorLabel);
|
|
97
58
|
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const handleClose = () => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return (
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handleClose = () => {
|
|
62
|
+
onClose();
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
106
66
|
<AnimatedModal
|
|
107
67
|
visible={visible}
|
|
108
68
|
onRequestClose={handleClose}
|
|
@@ -118,15 +78,50 @@ const AddImportModal = ({ visible, onClose, onSuccess, context = {} }) => {
|
|
|
118
78
|
|
|
119
79
|
<ScrollView style={styles.content}>
|
|
120
80
|
<Text style={styles.label}>{csvLabel}</Text>
|
|
121
|
-
<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
81
|
+
<DefaultUpload
|
|
82
|
+
relationStoreName="imports"
|
|
83
|
+
relationField="import"
|
|
84
|
+
relationResource="imports"
|
|
85
|
+
entityId={context.context || 'import'}
|
|
86
|
+
companyId={currentCompany.id}
|
|
87
|
+
context={`imports-${context.context || 'default'}`}
|
|
88
|
+
libraryContexts={[`imports-${context.context || 'default'}`]}
|
|
89
|
+
acceptedTypes="text/csv,.csv"
|
|
90
|
+
fileType=""
|
|
91
|
+
title={csvLabel}
|
|
92
|
+
triggerLabel={selectFileLabel}
|
|
93
|
+
managerTitle={modalTitle}
|
|
94
|
+
searchPlaceholder={selectFileLabel}
|
|
95
|
+
uploadButtonLabel={selectFileLabel}
|
|
96
|
+
emptyAttachmentLabel=""
|
|
97
|
+
emptyLibraryLabel={selectFileLabel}
|
|
98
|
+
showInlineContent={false}
|
|
99
|
+
uploadResultAlreadyAttached
|
|
100
|
+
requireEntity={false}
|
|
101
|
+
onUploadFile={handleUploadImportFile}
|
|
102
|
+
renderTrigger={({openManager, uploading}) => (
|
|
103
|
+
<TouchableOpacity
|
|
104
|
+
onPress={openManager}
|
|
105
|
+
disabled={uploading}
|
|
106
|
+
style={[
|
|
107
|
+
styles.filePicker,
|
|
108
|
+
{
|
|
109
|
+
backgroundColor: buttonPalette.buttonBackground,
|
|
110
|
+
borderColor: buttonPalette.buttonBorder,
|
|
111
|
+
},
|
|
112
|
+
]}
|
|
113
|
+
>
|
|
114
|
+
<Text numberOfLines={1} style={[styles.fileName, { color: buttonPalette.buttonText }]}>
|
|
115
|
+
{selectFileLabel}
|
|
116
|
+
</Text>
|
|
117
|
+
{uploading ? (
|
|
118
|
+
<ActivityIndicator color={buttonPalette.buttonIcon} />
|
|
119
|
+
) : (
|
|
120
|
+
<Icon name="upload-file" size={22} color={buttonPalette.buttonIcon} />
|
|
121
|
+
)}
|
|
122
|
+
</TouchableOpacity>
|
|
123
|
+
)}
|
|
124
|
+
/>
|
|
130
125
|
<Text style={styles.helperText}>
|
|
131
126
|
{csvOnlyLabel}
|
|
132
127
|
</Text>
|
|
@@ -136,22 +131,11 @@ const AddImportModal = ({ visible, onClose, onSuccess, context = {} }) => {
|
|
|
136
131
|
<TouchableOpacity onPress={handleClose} style={styles.secondaryButton}>
|
|
137
132
|
<Text>{cancelLabel}</Text>
|
|
138
133
|
</TouchableOpacity>
|
|
139
|
-
|
|
140
|
-
<TouchableOpacity
|
|
141
|
-
onPress={handleSave}
|
|
142
|
-
disabled={loading}
|
|
143
|
-
style={[
|
|
144
|
-
styles.primaryButton,
|
|
145
|
-
loading && styles.primaryButtonDisabled,
|
|
146
|
-
]}
|
|
147
|
-
>
|
|
148
|
-
{loading ? <ActivityIndicator color="#fff" /> : <Text style={styles.primaryButtonText}>{importLabel}</Text>}
|
|
149
|
-
</TouchableOpacity>
|
|
150
134
|
</View>
|
|
151
135
|
</View>
|
|
152
|
-
</AnimatedModal>
|
|
153
|
-
);
|
|
154
|
-
};
|
|
155
|
-
|
|
136
|
+
</AnimatedModal>
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
|
|
156
140
|
export default AddImportModal;
|
|
157
141
|
// TODO(store-first): quando este arquivo for mexido, mover a leitura para stores e evitar chamadas HTTP diretas quando o store ja resolver isso.
|