@eohjsc/react-native-smart-city 0.7.27 → 0.7.30

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 (67) hide show
  1. package/index.js +2 -0
  2. package/package.json +2 -1
  3. package/src/commons/Dashboard/MyDashboardDevice/__test__/index.test.js +68 -0
  4. package/src/commons/Dashboard/MyDashboardDevice/index.js +46 -11
  5. package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +43 -11
  6. package/src/commons/Dashboard/MyUnit/index.js +40 -32
  7. package/src/commons/ModalAlert/index.js +51 -0
  8. package/src/commons/ModalAlert/styles.js +54 -0
  9. package/src/commons/SubUnit/ShortDetail.js +20 -4
  10. package/src/commons/SubUnit/__test__/ShortDetail.test.js +46 -1
  11. package/src/configs/API.js +6 -0
  12. package/src/configs/AccessibilityLabel.js +1 -0
  13. package/src/configs/Constants.js +7 -0
  14. package/src/configs/SCConfig.js +6 -0
  15. package/src/context/SCContext.tsx +12 -1
  16. package/src/context/SCStore.ts +14 -0
  17. package/src/context/actionType.ts +10 -0
  18. package/src/context/mockStore.ts +30 -1
  19. package/src/context/reducer.ts +35 -0
  20. package/src/hooks/IoT/useRemoteControl.js +4 -1
  21. package/src/hooks/IoT/useWatchSharedChips.js +130 -0
  22. package/src/hooks/Review/__test__/useInAppReview.test.js +99 -0
  23. package/src/hooks/Review/useInAppReview.js +70 -0
  24. package/src/hooks/useMqtt.js +78 -27
  25. package/src/iot/Monitor.js +149 -26
  26. package/src/iot/UpdateStates.js +60 -0
  27. package/src/iot/mqtt.js +177 -22
  28. package/src/navigations/UnitStack.js +16 -0
  29. package/src/screens/ActivityLog/ItemLog.js +1 -0
  30. package/src/screens/AddNewGateway/RenameNewDevices.js +5 -0
  31. package/src/screens/AddNewGateway/__test__/RenameNewDevices.test.js +18 -0
  32. package/src/screens/Automate/AddNewAction/ReceiverSelect.js +208 -0
  33. package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +1 -1
  34. package/src/screens/Automate/AddNewAction/SetupScriptNotify.js +18 -28
  35. package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +22 -129
  36. package/src/screens/Automate/AddNewAction/SetupScriptReceiverNotify.js +59 -0
  37. package/src/screens/Automate/AddNewAction/SetupScriptReceiverSms.js +22 -129
  38. package/src/screens/Automate/AddNewAction/SetupScriptSms.js +1 -1
  39. package/src/screens/Automate/AddNewAction/Styles/{SetupScriptReceiverEmailStyles.js → ReceiverSelectStyles.js} +18 -1
  40. package/src/screens/Automate/AddNewAction/__test__/SetupScriptNotify.test.js +16 -33
  41. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +10 -8
  42. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverNotify.test.js +217 -0
  43. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverSms.test.js +10 -8
  44. package/src/screens/Automate/Components/InputName.js +5 -1
  45. package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +18 -0
  46. package/src/screens/Automate/ScriptDetail/index.js +6 -6
  47. package/src/screens/CreatePassword/__test__/index.test.js +133 -0
  48. package/src/screens/CreatePassword/index.js +134 -0
  49. package/src/screens/CreatePassword/styles.js +45 -0
  50. package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +447 -0
  51. package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +344 -0
  52. package/src/screens/Device/__test__/{mqttDetail.test.js → DeviceDetail-modbus.test.js} +287 -320
  53. package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +451 -0
  54. package/src/screens/Device/__test__/DeviceDetail.test.js +502 -0
  55. package/src/screens/Device/__test__/detail.test.js +61 -3
  56. package/src/screens/Device/__test__/sensorDisplayItem.test.js +28 -3
  57. package/src/screens/Device/detail.js +14 -6
  58. package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +3 -2
  59. package/src/screens/EnterPassword/__test__/EnterPassword.test.js +76 -1
  60. package/src/screens/EnterPassword/index.js +34 -4
  61. package/src/screens/EnterPassword/styles.js +1 -1
  62. package/src/utils/FactoryGateway.js +597 -0
  63. package/src/utils/I18n/translations/en.js +10 -0
  64. package/src/utils/I18n/translations/vi.js +10 -0
  65. package/src/utils/Route/index.js +3 -1
  66. package/src/utils/Validation.js +5 -0
  67. package/src/utils/store.js +5 -0
@@ -61,6 +61,7 @@ import { useReceiveNotifications } from '../../hooks';
61
61
  import useChipJsonConfiguration, {
62
62
  useConnectChipMqtt,
63
63
  } from '../../hooks/useMqtt';
64
+ import useWatchSharedChips from '../../hooks/IoT/useWatchSharedChips';
64
65
  import { useBluetoothDevice } from './components/BluetoothDevice';
65
66
 
66
67
  const DeviceDetail = ({ route }) => {
@@ -147,14 +148,21 @@ const DeviceDetail = ({ route }) => {
147
148
 
148
149
  useDisconnectedDevice(sensorName, isDeviceHasBle, serverDown);
149
150
 
150
- const { chips } = useChipJsonConfiguration(unit?.id);
151
+ const { chips, isFetching } = useChipJsonConfiguration({
152
+ dashboardId: unit?.id,
153
+ });
151
154
 
152
- const chipFiltered = useMemo(() => {
155
+ const listChipsMqtt = useMemo(() => {
153
156
  return chips?.filter((item) => item?.id === device?.chip_id);
154
157
  }, [chips, device?.chip_id]);
155
158
 
156
- const { mqttConfigs } = useConnectChipMqtt(chipFiltered);
157
- useDeviceWatchConfigControl(device, display, mqttConfigs);
159
+ const { mqttConfigs } = useConnectChipMqtt(listChipsMqtt);
160
+ useDeviceWatchConfigControl(device, display, mqttConfigs, isFetching);
161
+ useWatchSharedChips({
162
+ dashboardId: unit?.id,
163
+ filterChipIds: [device?.chip_id],
164
+ ready: !!device?.chip_id,
165
+ });
158
166
 
159
167
  const isShowSetupEmergencyContact = useMemo(
160
168
  () =>
@@ -592,7 +600,7 @@ const DeviceDetail = ({ route }) => {
592
600
 
593
601
  let configIds = Array.from(configIdsSet);
594
602
  configIds = configIds.filter(Boolean);
595
- configIdsTemp.current = configIds;
603
+ configIdsTemp.current = configIds.filter((id) => !mqttConfigs[id]);
596
604
 
597
605
  configIds.map((id) => {
598
606
  params.append('config', id);
@@ -685,7 +693,7 @@ const DeviceDetail = ({ route }) => {
685
693
  }, [])
686
694
  );
687
695
 
688
- useWatchConfigs(chipFiltered.length ? [] : configIdsTemp.current);
696
+ useWatchConfigs(isFetching ? [] : configIdsTemp.current);
689
697
 
690
698
  const isShowEmergencyResolve =
691
699
  display.items.filter(
@@ -6,7 +6,8 @@ import { useWatchConfigs } from '../../../hooks/IoT';
6
6
  export const useDeviceWatchConfigControl = (
7
7
  device,
8
8
  display,
9
- mqttConfigs = {}
9
+ mqttConfigs = {},
10
+ isFetching
10
11
  ) => {
11
12
  const { is_managed_by_backend, device_type } = device;
12
13
  const configsNeedWatching = useMemo(() => {
@@ -24,5 +25,5 @@ export const useDeviceWatchConfigControl = (
24
25
  }
25
26
  return configsControl;
26
27
  }, [is_managed_by_backend, device_type, display, mqttConfigs]);
27
- useWatchConfigs(configsNeedWatching);
28
+ useWatchConfigs(isFetching ? [] : configsNeedWatching);
28
29
  };
@@ -8,7 +8,9 @@ import { API } from '../../../configs';
8
8
  import { AccessibilityLabel } from '../../../configs/Constants';
9
9
  import { SCProvider } from '../../../context';
10
10
  import { mockSCStore } from '../../../context/mockStore';
11
+ import ModalAlert from '../../../commons/ModalAlert';
11
12
  import api from '../../../utils/Apis/axios';
13
+ import Routes from '../../../utils/Route';
12
14
  import EnterPassword from '../index';
13
15
 
14
16
  const mock = new MockAdapter(api.axiosInstance);
@@ -21,7 +23,20 @@ const wrapComponent = (route) => (
21
23
 
22
24
  describe('Test EnterPassword', () => {
23
25
  let tree;
24
- const { navigate } = useNavigation();
26
+ const { navigate, goBack } = useNavigation();
27
+
28
+ beforeEach(() => {
29
+ jest.useFakeTimers();
30
+ mock.reset();
31
+ mock
32
+ .onGet(API.ACCOUNTS.USABLE_PASSWORD)
33
+ .reply(200, { has_usable_password: true });
34
+ });
35
+
36
+ afterEach(() => {
37
+ jest.useRealTimers();
38
+ });
39
+
25
40
  const buttonDone = (instance) => {
26
41
  return instance.findAll(
27
42
  (el) =>
@@ -41,6 +56,66 @@ describe('Test EnterPassword', () => {
41
56
  const instance = tree.root;
42
57
  const button = buttonDone(instance);
43
58
  expect(button).toHaveLength(1);
59
+
60
+ await act(async () => {
61
+ jest.runAllTimers();
62
+ });
63
+ const alert = instance.findByType(ModalAlert);
64
+ expect(alert.props.isVisible).toBeFalsy();
65
+ });
66
+
67
+ it('test render EnterPassword not has usable password', async () => {
68
+ const route = {
69
+ params: { dataParams: {}, type: '' },
70
+ };
71
+ mock
72
+ .onGet(API.ACCOUNTS.USABLE_PASSWORD)
73
+ .reply(200, { has_usable_password: false });
74
+ await act(async () => {
75
+ tree = await create(wrapComponent(route));
76
+ });
77
+ const instance = tree.root;
78
+ const button = buttonDone(instance);
79
+ expect(button).toHaveLength(1);
80
+
81
+ await act(async () => {
82
+ jest.runAllTimers();
83
+ });
84
+ const alert = instance.findByType(ModalAlert);
85
+ expect(alert.props.isVisible).toBeTruthy();
86
+
87
+ await act(async () => {
88
+ alert.props.onRight();
89
+ });
90
+ expect(alert.props.isVisible).toBeFalsy();
91
+ expect(navigate).toHaveBeenCalledWith(Routes.CreatePassword);
92
+ });
93
+
94
+ it('test render EnterPassword not has usable password and cancel alert', async () => {
95
+ const route = {
96
+ params: { dataParams: {}, type: '' },
97
+ };
98
+ mock
99
+ .onGet(API.ACCOUNTS.USABLE_PASSWORD)
100
+ .reply(200, { has_usable_password: false });
101
+ await act(async () => {
102
+ tree = await create(wrapComponent(route));
103
+ });
104
+ const instance = tree.root;
105
+ const button = buttonDone(instance);
106
+ expect(button).toHaveLength(1);
107
+
108
+ await act(async () => {
109
+ jest.runAllTimers();
110
+ });
111
+ const alert = instance.findByType(ModalAlert);
112
+ expect(alert.props.isVisible).toBeTruthy();
113
+
114
+ await act(async () => {
115
+ alert.props.onLeft();
116
+ });
117
+ expect(navigate).not.toHaveBeenCalled();
118
+ expect(goBack).toHaveBeenCalled();
44
119
  });
45
120
 
46
121
  it('test render EnterPassword has not params', async () => {
@@ -1,10 +1,11 @@
1
- import React, { useCallback, useState } from 'react';
2
- import { useNavigation } from '@react-navigation/native';
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import { useNavigation, useIsFocused } from '@react-navigation/native';
3
3
  import { TouchableOpacity, View } from 'react-native';
4
4
  import { HeaderCustom } from '../../commons/Header';
5
+ import ModalAlert from '../../commons/ModalAlert';
5
6
  import { useTranslations } from '../../hooks/Common/useTranslations';
6
7
  import _TextInputPassword from '../../commons/Form/TextInputPassword';
7
- import { axiosPut } from '../../utils/Apis/axios';
8
+ import { axiosPut, axiosGet } from '../../utils/Apis/axios';
8
9
  import Text from '../../commons/Text';
9
10
  import { Colors, API } from '../../configs';
10
11
  import { FullLoading } from '../../commons';
@@ -19,9 +20,11 @@ const EnterPassword = ({ route }) => {
19
20
  type: '',
20
21
  };
21
22
  const t = useTranslations();
22
- const { navigate } = useNavigation();
23
+ const { navigate, goBack } = useNavigation();
24
+ const isFocused = useIsFocused();
23
25
  const [loading, setLoading] = useState(false);
24
26
  const [password, setPassword] = useState('');
27
+ const [showCreatePassword, setShowCreatePassword] = useState(false);
25
28
 
26
29
  const handleDone = useCallback(async () => {
27
30
  setLoading(true);
@@ -46,6 +49,24 @@ const EnterPassword = ({ route }) => {
46
49
  setLoading(false);
47
50
  }, [dataParams?.member?.id, dataParams?.unit_id, navigate, password, type]);
48
51
 
52
+ const goToCreatePassword = useCallback(() => {
53
+ setShowCreatePassword(false);
54
+ navigate(Routes.CreatePassword);
55
+ }, [navigate]);
56
+
57
+ const getUsablePassword = useCallback(async () => {
58
+ const { success, data } = await axiosGet(API.ACCOUNTS.USABLE_PASSWORD);
59
+ if (success) {
60
+ setTimeout(() => {
61
+ setShowCreatePassword(!data.has_usable_password);
62
+ }, 500);
63
+ }
64
+ }, []);
65
+
66
+ useEffect(() => {
67
+ isFocused && getUsablePassword();
68
+ }, [isFocused, getUsablePassword]);
69
+
49
70
  return (
50
71
  <View style={styles.wrap}>
51
72
  <HeaderCustom />
@@ -79,6 +100,15 @@ const EnterPassword = ({ route }) => {
79
100
  </TouchableOpacity>
80
101
  </View>
81
102
  {!!loading && <FullLoading />}
103
+ <ModalAlert
104
+ title={t('update_your_password')}
105
+ description={t('you_need_to_update_password')}
106
+ isVisible={showCreatePassword}
107
+ leftText={t('cancel')}
108
+ rightText={t('update')}
109
+ onLeft={goBack}
110
+ onRight={goToCreatePassword}
111
+ />
82
112
  </View>
83
113
  );
84
114
  };
@@ -29,7 +29,7 @@ export default StyleSheet.create({
29
29
  justifyContent: 'center',
30
30
  alignItems: 'center',
31
31
  marginTop: 32,
32
- paddingVertical: 8,
32
+ paddingVertical: 12,
33
33
  borderRadius: 30,
34
34
  backgroundColor: Colors.Primary,
35
35
  },