@controleonline/ui-common 1.2.89 → 1.2.91

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.
Files changed (24) hide show
  1. package/docs/compact-order-history-1047.md +25 -0
  2. package/package.json +1 -1
  3. package/src/react/components/CopyDeviceConfigModal.js +7 -4
  4. package/src/react/components/DefaultProvider.native.configuration.js +275 -0
  5. package/src/react/components/DefaultProvider.native.js +24 -534
  6. package/src/react/components/DefaultProvider.native.lifecycle.js +323 -0
  7. package/src/react/components/DefaultProvider.web.configuration.js +327 -0
  8. package/src/react/components/DefaultProvider.web.js +23 -603
  9. package/src/react/components/DefaultProvider.web.lifecycle.js +336 -0
  10. package/src/react/components/resolveDomainThemeColors.js +5 -0
  11. package/src/react/pages/Connections.js +5 -7
  12. package/src/react/pages/MercadoLivreIntegrationPage.js +5 -75
  13. package/src/react/pages/mercadoLivreIntegrationHelpers.js +79 -0
  14. package/src/tests/browser/manager/bottom-navigation-role-toolbar.spec.js +14 -0
  15. package/src/tests/browser/manager/connections.spec.js +18 -0
  16. package/src/tests/browser/manager/device-detail-alias-save.spec.js +3 -1
  17. package/src/tests/browser/manager/device-detail-copy-config.spec.js +6 -0
  18. package/src/tests/browser/manager/device-detail-pdv-current-company.spec.js +3 -1
  19. package/src/tests/browser/manager/devices-current.spec.js +345 -343
  20. package/src/tests/browser/manager/devices-type-filters.spec.js +2 -0
  21. package/src/tests/browser/manager/managerSession.fixture.js +28 -0
  22. package/src/tests/react/components/DefaultProviderAuthority.test.js +4 -1
  23. package/src/tests/react/components/providerEffects.fingerprint.json +47 -0
  24. package/src/tests/react/components/providerEffects.test.js +24 -0
@@ -1,3 +1,6 @@
1
+ import {useNativeTranslationRefresh, useNativeTranslationReset, useNativeAppLifecycle, useNativeNativeVersion, useNativeNativeDeviceIdentity, useNativeMainCompany, useNativeDeviceConfigReset, useNativeDeviceRegistration, useNativePrinters, useNativePaymentTypes, useNativeDeviceConfigFetch} from './DefaultProvider.native.lifecycle';
2
+ import {useNativeDeviceConfigSync, useNativeMainConfigReset, useNativeMainConfigDiscovery, useNativeMainConfigSeed, useNativeTranslationBootstrap, useNativeBootstrapReady, useNativeCompanies, useNativeMenus, useNativeThemeFetch, useNativeThemePalette} from './DefaultProvider.native.configuration';
3
+ import {resolveDomainThemeColors} from './resolveDomainThemeColors';
1
4
  import React, {
2
5
  createContext,
3
6
  useCallback,
@@ -268,43 +271,11 @@ export const DefaultProvider = ({
268
271
  </>
269
272
  );
270
273
 
271
- useEffect(() => {
272
- global.refreshTranslationsUI = () => {
273
- setTranslateVersion(version => version + 1);
274
- };
275
-
276
- return () => {
277
- if (global.refreshTranslationsUI) {
278
- delete global.refreshTranslationsUI;
279
- }
280
- };
281
- }, []);
282
-
283
- useEffect(() => {
284
- if (isLogged && !isPublicRouteActive) {
285
- return;
286
- }
287
-
288
- setTranslateReady(true);
289
- setActiveTranslateBootstrapKey('');
290
- translateBootstrapKeyRef.current = '';
291
- translateActions.setMessages({});
292
- translateActions.setPendingMessages?.({});
293
-
294
- if (global.t) {
295
- delete global.t;
296
- }
297
- }, [isLogged, isPublicRouteActive, translateActions]);
274
+ useNativeTranslationRefresh({setTranslateVersion});
298
275
 
299
- useEffect(() => {
300
- const subscription = AppState.addEventListener('change', nextState => {
301
- setAppState(nextState || 'active');
302
- });
276
+ useNativeTranslationReset({isLogged, isPublicRouteActive, setTranslateReady, setActiveTranslateBootstrapKey, translateBootstrapKeyRef, translateActions});
303
277
 
304
- return () => {
305
- subscription?.remove?.();
306
- };
307
- }, []);
278
+ useNativeAppLifecycle({AppState, setAppState});
308
279
 
309
280
  const fetchDeviceId = async () => {
310
281
  const uniqueId = await DeviceInfo.getUniqueId();
@@ -345,524 +316,43 @@ export const DefaultProvider = ({
345
316
  }, 300);
346
317
  }
347
318
  };
348
- useEffect(() => {
349
- const checkVersion = async () => {
350
- const appVersion = await DeviceInfo.getVersion();
351
- if (
352
- device &&
353
- ((device.appVersion && device.appVersion != appVersion) || !device.appName)
354
- ) {
355
- fetchDeviceId();
356
- }
357
- };
358
- checkVersion();
359
- }, [device]);
319
+ useNativeNativeVersion({DeviceInfo, device, fetchDeviceId});
360
320
 
361
- useEffect(() => {
362
- if (!device || !device.id) {
363
- fetchDeviceId();
364
- } else {
365
- deviceActions.setItem(device);
366
- }
367
- }, [device]);
321
+ useNativeNativeDeviceIdentity({device, fetchDeviceId, deviceActions});
368
322
 
369
- useEffect(() => {
370
- if (device && device.id) {
371
- peopleActions.mainCompany();
372
- }
373
- }, [device?.id]);
374
-
375
- useEffect(() => {
376
- if (
377
- !deviceConfigPeopleIri ||
378
- lastDeviceConfigPeopleIriRef.current === deviceConfigPeopleIri
379
- ) {
380
- return;
381
- }
323
+ useNativeMainCompany({device, peopleActions});
382
324
 
383
- lastDeviceConfigPeopleIriRef.current = deviceConfigPeopleIri;
384
- setDeviceConfigFetched(false);
385
- setDeviceRuntimeConfigSynced(false);
386
- deviceConfigsActions.setItem({});
387
- }, [deviceConfigPeopleIri, deviceConfigsActions]);
325
+ useNativeDeviceConfigReset({deviceConfigPeopleIri, lastDeviceConfigPeopleIriRef, setDeviceConfigFetched, setDeviceRuntimeConfigSynced, deviceConfigsActions});
388
326
 
389
- useEffect(() => {
390
- if (!sessionChecked || !isLogged || !deviceConfigPeopleIri || !device?.id || deviceConfigFetched) {
391
- return;
392
- }
327
+ useNativeDeviceRegistration({sessionChecked, isLogged, deviceConfigPeopleIri, device, deviceConfigFetched, currentCompany, canAdministerCompany, mainCompany, user, deviceActions, runtimeDeviceType, buildDeviceRegistrationPayload, app_type, hasDeviceRecordChanges, setDevice});
393
328
 
394
- // Device registration changes tenant context and is not valid without an
395
- // active company or administrative authority for that company.
396
- if (
397
- !currentCompany?.id ||
398
- !canAdministerCompany({company: currentCompany, mainCompany, user})
399
- ) {
400
- return;
401
- }
329
+ useNativePrinters({isShopClientApp, sessionChecked, isLogged, currentCompany, printerActions});
402
330
 
403
- let cancelled = false;
331
+ useNativePaymentTypes({isShopClientApp, companyConfigs, currentCompany, device_config, paymentTypeActions, mainConfigsDiscovered, api, selectPosWalletPaymentTypes, getPaymentGateway});
404
332
 
405
- const syncDeviceRegistration = async () => {
406
- const items = await deviceActions.getItems({
407
- device: device.id,
408
- people: deviceConfigPeopleIri,
409
- type: runtimeDeviceType,
410
- });
333
+ useNativeDeviceConfigFetch({device, isLogged, currentCompany, setDeviceConfigFetched, setDeviceRuntimeConfigSynced, deviceConfigsActions, runtimeDeviceType, parseConfigsObject});
411
334
 
412
- if (cancelled) {
413
- return;
414
- }
335
+ useNativeDeviceConfigSync({deviceConfigFetched, isLogged, deviceConfigPeopleIri, device, deviceRuntimeConfigSynced, runtimeDeviceType, device_config, buildDefaultDeviceConfigs, buildProviderManagedDeviceConfigs, appVersion, setDeviceRuntimeConfigSynced, deviceConfigsActions, user});
415
336
 
416
- const existingDevice =
417
- Array.isArray(items) && items.length > 0 ? items[0] : null;
418
- const nextDevice = buildDeviceRegistrationPayload({
419
- deviceInfo: device,
420
- appType: app_type,
421
- existingDevice,
422
- });
423
-
424
- if (!hasDeviceRecordChanges({existingDevice, nextDevice})) {
425
- const nextLocalDevice = {
426
- ...device,
427
- entityId: existingDevice?.id || device?.entityId || null,
428
- entityIri:
429
- existingDevice?.['@id'] ||
430
- device?.entityIri ||
431
- (existingDevice?.id ? `/devices/${existingDevice.id}` : null),
432
- alias: existingDevice?.alias || nextDevice.alias,
433
- type: device?.type || runtimeDeviceType,
434
- metadata: {
435
- ...(existingDevice?.metadata || {}),
436
- ...(nextDevice.metadata || {}),
437
- },
438
- };
439
-
440
- if (JSON.stringify(nextLocalDevice) !== JSON.stringify(device)) {
441
- setDevice(nextLocalDevice);
442
- localStorage.setItem('device', JSON.stringify(nextLocalDevice));
443
- deviceActions.setItem(nextLocalDevice);
444
- }
445
- return;
446
- }
447
-
448
- const savedDevice = await deviceActions.save(nextDevice);
449
- if (cancelled || !savedDevice) {
450
- return;
451
- }
452
-
453
- const nextLocalDevice = {
454
- ...device,
455
- entityId: savedDevice?.id || device?.entityId || null,
456
- entityIri:
457
- savedDevice?.['@id'] ||
458
- device?.entityIri ||
459
- (savedDevice?.id ? `/devices/${savedDevice.id}` : null),
460
- alias: savedDevice.alias || nextDevice.alias,
461
- type: device?.type || runtimeDeviceType,
462
- metadata: {
463
- ...(savedDevice?.metadata || {}),
464
- ...(nextDevice.metadata || {}),
465
- },
466
- };
467
-
468
- if (JSON.stringify(nextLocalDevice) !== JSON.stringify(device)) {
469
- setDevice(nextLocalDevice);
470
- localStorage.setItem('device', JSON.stringify(nextLocalDevice));
471
- deviceActions.setItem(nextLocalDevice);
472
- }
473
- };
337
+ useNativeMainConfigReset({isLogged, currentCompany, device, setMainConfigsDiscovered});
474
338
 
475
- syncDeviceRegistration().catch(() => {});
339
+ useNativeMainConfigDiscovery({isLogged, currentCompany, device, mainConfigsDiscovered, configActions, setMainConfigsDiscovered});
476
340
 
477
- return () => {
478
- cancelled = true;
479
- };
480
- }, [
481
- device?.appVersion,
482
- device?.batteryLevel,
483
- device?.buildNumber,
484
- device?.deviceType,
485
- device?.id,
486
- device?.metadata,
487
- device?.manufacturer,
488
- device?.model,
489
- device?.systemVersion,
490
- deviceConfigFetched,
491
- deviceConfigPeopleIri,
492
- isLogged,
493
- currentCompany,
494
- mainCompany,
495
- sessionChecked,
496
- runtimeDeviceType,
497
- user,
498
- ]);
341
+ useNativeMainConfigSeed({isLogged, currentCompany, mainConfigsDiscovered, configActions});
499
342
 
500
- useEffect(() => {
501
- if (isShopClientApp || !sessionChecked || !isLogged || !currentCompany?.id) {
502
- return;
503
- }
343
+ useNativeTranslationBootstrap({currentRouteName, isPublicRouteActive, isLogged, hasCurrentCompany, deviceConfigFetched, expectedTranslateBootstrapKey, translateBootstrapKeyRef, companies, currentCompany, mainCompany, setActiveTranslateBootstrapKey, setTranslateReady, configuredTranslationLanguage, Translate, stores, translateStore});
504
344
 
505
- printerActions
506
- .ensureCompanyPrintersLoaded({people: currentCompany.id})
507
- .catch(() => {});
508
- }, [currentCompany?.id, isLogged, isShopClientApp, printerActions, sessionChecked]);
509
-
510
- useEffect(() => {
511
- const paymentConfigSource = isShopClientApp
512
- ? Object.keys(companyConfigs || {}).length > 0
513
- ? companyConfigs
514
- : currentCompany?.configs
515
- : device_config?.configs;
516
-
517
- if (!currentCompany?.id || !paymentConfigSource) {
518
- paymentTypeActions.setItems([]);
519
- return;
520
- }
521
345
 
522
- if (!isShopClientApp && !mainConfigsDiscovered) {
523
- return;
524
- }
346
+ useNativeBootstrapReady({isLogged, hasCurrentCompany, currentRouteName, isTranslateBootstrapReady, onBootstrapReady});
525
347
 
526
- let isMounted = true;
527
348
 
528
- api
529
- .fetch('wallet_payment_types', {
530
- params: {
531
- people: `/people/${currentCompany.id}`,
532
- },
533
- })
534
- .then(response => {
535
- if (!isMounted) {
536
- return;
537
- }
538
-
539
- const walletPaymentTypes = Array.isArray(response?.member)
540
- ? response.member
541
- : Array.isArray(response?.['hydra:member'])
542
- ? response['hydra:member']
543
- : Array.isArray(response)
544
- ? response
545
- : [];
546
- paymentTypeActions.setItems(
547
- selectPosWalletPaymentTypes({
548
- walletPaymentTypes,
549
- deviceConfigs: paymentConfigSource,
550
- companyConfigs,
551
- gateway: getPaymentGateway(device_config || paymentConfigSource),
552
- }),
553
- );
554
- })
555
- .catch(() => {
556
- if (isMounted) {
557
- paymentTypeActions.setItems([]);
558
- }
559
- });
349
+ useNativeCompanies({device, isLogged, peopleActions});
560
350
 
561
- return () => {
562
- isMounted = false;
563
- };
564
- }, [
565
- companyConfigs,
566
- currentCompany?.configs,
567
- currentCompany?.id,
568
- device_config?.configs,
569
- isShopClientApp,
570
- paymentTypeActions,
571
- ]);
572
-
573
- useEffect(() => {
574
- if (
575
- device &&
576
- device.id &&
577
- isLogged &&
578
- currentCompany &&
579
- Object.entries(currentCompany).length > 0
580
- ) {
581
- setDeviceConfigFetched(false);
582
- setDeviceRuntimeConfigSynced(false);
583
- deviceConfigsActions
584
- .getItems({
585
- 'device.device': device.id,
586
- people: '/people/' + currentCompany.id,
587
- type: runtimeDeviceType,
588
- })
589
- .then(data => {
590
- if (Array.isArray(data) && data.length > 0) {
591
- const nextItem = {
592
- ...data[0],
593
- configs: parseConfigsObject(data[0]?.configs),
594
- };
595
- deviceConfigsActions.setItem(nextItem);
596
- return;
597
- }
598
-
599
- deviceConfigsActions.setItem({});
600
- })
601
- .catch(() => {})
602
- .finally(() => {
603
- setDeviceConfigFetched(true);
604
- });
605
- }
606
- }, [currentCompany?.id, isLogged, device?.id, runtimeDeviceType]);
607
-
608
- useEffect(() => {
609
- if (
610
- !deviceConfigFetched ||
611
- !isLogged ||
612
- !deviceConfigPeopleIri ||
613
- !device?.id ||
614
- deviceRuntimeConfigSynced
615
- ) {
616
- return;
617
- }
618
-
619
- const isNewPdvConfig =
620
- runtimeDeviceType === 'PDV' &&
621
- !device_config?.id &&
622
- !device_config?.['@id'];
623
- const buildDeviceConfigs = isNewPdvConfig
624
- ? buildDefaultDeviceConfigs
625
- : buildProviderManagedDeviceConfigs;
626
- const {nextConfigs, needsUpdate} = buildDeviceConfigs({
627
- configs: device_config?.configs,
628
- appVersion,
629
- deviceInfo: device,
630
- });
631
-
632
- if (!needsUpdate) {
633
- setDeviceRuntimeConfigSynced(true);
634
- return;
635
- }
636
-
637
- // app-community#821: never auto-persist device_config from global bootstrap.
638
- // Provider-managed fields stay in memory only; API mutations only from
639
- // explicit device settings UI (avoids 403 on order-history / PDV|MANAGER).
640
- const currentItem = device_config || {};
641
- deviceConfigsActions.setItem({
642
- ...currentItem,
643
- configs: nextConfigs,
644
- device: currentItem.device || device.id,
645
- people: currentItem.people || deviceConfigPeopleIri,
646
- type: currentItem.type || runtimeDeviceType,
647
- });
648
- setDeviceRuntimeConfigSynced(true);
649
- }, [
650
- appVersion,
651
- device?.id,
652
- device?.manufacturer,
653
- device?.isEmulator,
654
- deviceConfigFetched,
655
- deviceConfigPeopleIri,
656
- deviceRuntimeConfigSynced,
657
- deviceConfigsActions,
658
- device_config,
659
- isLogged,
660
- runtimeDeviceType,
661
- user,
662
- ]);
663
-
664
- useEffect(() => {
665
- if (!isLogged || !currentCompany?.id || !device?.id) {
666
- return;
667
- }
668
-
669
- setMainConfigsDiscovered(false);
670
- }, [isLogged, currentCompany?.id, device?.id]);
671
-
672
- useEffect(() => {
673
- if (
674
- !isLogged ||
675
- !currentCompany?.id ||
676
- !device?.id ||
677
- mainConfigsDiscovered
678
- ) {
679
- return;
680
- }
681
-
682
- configActions
683
- .discoveryMainConfigs({
684
- people: '/people/' + currentCompany.id,
685
- })
686
- .catch(() => {})
687
- .finally(() => {
688
- setMainConfigsDiscovered(true);
689
- });
690
- }, [configActions, currentCompany?.id, device?.id, isLogged, mainConfigsDiscovered]);
691
-
692
- useEffect(() => {
693
- if (
694
- isLogged &&
695
- currentCompany &&
696
- Object.entries(currentCompany).length > 0 &&
697
- !mainConfigsDiscovered
698
- ) {
699
- configActions.setItems(currentCompany.configs);
700
- }
701
- }, [currentCompany, isLogged, mainConfigsDiscovered]);
702
-
703
- useEffect(() => {
704
- if (!currentRouteName || isPublicRouteActive) {
705
- return;
706
- }
707
-
708
- if (
709
- !isLogged ||
710
- !hasCurrentCompany ||
711
- !deviceConfigFetched ||
712
- !expectedTranslateBootstrapKey
713
- ) {
714
- return;
715
- }
716
-
717
- const currentConfig = JSON.parse(localStorage.getItem('config') || '{}');
718
-
719
- if (
720
- translateBootstrapKeyRef.current === expectedTranslateBootstrapKey &&
721
- global.t
722
- ) {
723
- global.t.companies = companies;
724
- global.t.currentCompany = currentCompany;
725
- global.t.mainCompany = mainCompany;
726
- setActiveTranslateBootstrapKey(expectedTranslateBootstrapKey);
727
- setTranslateReady(true);
728
-
729
- return;
730
- }
731
-
732
- setTranslateReady(false);
733
-
734
- if (currentConfig.language !== configuredTranslationLanguage) {
735
- const nextConfig = {
736
- ...currentConfig,
737
- language: configuredTranslationLanguage,
738
- };
739
- localStorage.setItem(
740
- 'config',
741
- JSON.stringify(nextConfig),
742
- );
743
- }
744
-
745
- translateBootstrapKeyRef.current = expectedTranslateBootstrapKey;
746
- global.t = new Translate(
747
- companies,
748
- mainCompany,
749
- currentCompany,
750
- Object.keys(stores),
751
- translateStore,
752
- );
753
- setActiveTranslateBootstrapKey(expectedTranslateBootstrapKey);
754
- setTranslateReady(true);
755
- global.refreshTranslationsUI?.();
756
- }, [
757
- companies,
758
- configuredTranslationLanguage,
759
- currentCompany,
760
- currentRouteName,
761
- mainCompany,
762
- deviceConfigFetched,
763
- expectedTranslateBootstrapKey,
764
- hasCurrentCompany,
765
- isLogged,
766
- isPublicRouteActive,
767
- translateStore,
768
- ]);
769
-
770
-
771
- useEffect(() => {
772
- if (
773
- !isLogged ||
774
- !hasCurrentCompany ||
775
- (currentRouteName && isTranslateBootstrapReady)
776
- ) {
777
- onBootstrapReady?.();
778
- }
779
- }, [
780
- currentRouteName,
781
- hasCurrentCompany,
782
- isLogged,
783
- isTranslateBootstrapReady,
784
- onBootstrapReady,
785
- ]);
786
-
787
-
788
- useEffect(() => {
789
- if (
790
- device &&
791
- device.id &&
792
- isLogged
793
- ) {
794
- peopleActions.myCompanies();
795
- }
796
- }, [isLogged, device?.id]);
797
-
798
- useEffect(() => {
799
- if (!isLogged || !currentCompany?.id) {
800
- actions.setMenus([]);
801
- return undefined;
802
- }
803
-
804
- let cancelled = false;
805
-
806
- api
807
- .fetch('menus-people', {
808
- params: {
809
- myCompany: currentCompany.id,
810
- appType,
811
- menuType: 'home',
812
- },
813
- })
814
- .then(result => {
815
- if (!cancelled) {
816
- actions.setMenus(normalizeRuntimeMenuResponse(result, {appType}));
817
- }
818
- })
819
- .catch(() => {
820
- if (!cancelled) {
821
- actions.setMenus(normalizeRuntimeMenuResponse(null, {appType}));
822
- }
823
- });
824
-
825
- return () => {
826
- cancelled = true;
827
- };
828
- }, [actions, appType, currentCompany?.id, isLogged]);
829
-
830
- useEffect(() => {
831
- const fetchColors = async () => {
832
- try {
833
- const cssText = await api.fetch('themes-colors.css', {
834
- responseType: 'text',
835
- });
836
- const parsedColors = parseThemeCss(cssText);
837
- setBaseThemeColors(parsedColors);
838
- actions.setColors(parsedColors);
839
- } catch {
840
- setBaseThemeColors({});
841
- }
842
- };
843
-
844
- if (device?.id) {
845
- fetchColors();
846
- }
847
- }, [actions, currentCompany?.id, mainCompany?.id, device?.id]);
848
-
849
- useEffect(() => {
850
- const companyThemeColors =
851
- currentCompany?.theme?.colors || mainCompany?.theme?.colors || {};
852
- const mergedThemeColors = {
853
- ...(baseThemeColors || {}),
854
- ...(companyThemeColors || {}),
855
- };
351
+ useNativeMenus({isLogged, currentCompany, actions, api, appType, normalizeRuntimeMenuResponse});
856
352
 
857
- const palette = resolveThemePalette(mergedThemeColors, runtimeColors);
858
- applyPaletteToRuntimeColors(palette, runtimeColors);
859
- applyThemeCssVariables({
860
- themeColors: mergedThemeColors,
861
- palette,
862
- });
353
+ useNativeThemeFetch({api, parseThemeCss, setBaseThemeColors, actions, device, currentCompany, mainCompany});
863
354
 
864
- actions.setColors(mergedThemeColors);
865
- }, [actions, baseThemeColors, currentCompany?.id, currentCompany?.theme?.colors]);
355
+ useNativeThemePalette({resolveDomainThemeColors, baseThemeColors, mainCompany, resolveThemePalette, runtimeColors, applyPaletteToRuntimeColors, applyThemeCssVariables, actions, currentCompany});
866
356
 
867
357
  if (requiresTranslateBootstrap && !isTranslateBootstrapReady) {
868
358
  return <View style={providerStyles.loadingContainer} />;