@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.
- package/index.js +2 -0
- package/package.json +2 -1
- package/src/commons/Dashboard/MyDashboardDevice/__test__/index.test.js +68 -0
- package/src/commons/Dashboard/MyDashboardDevice/index.js +46 -11
- package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +43 -11
- package/src/commons/Dashboard/MyUnit/index.js +40 -32
- package/src/commons/ModalAlert/index.js +51 -0
- package/src/commons/ModalAlert/styles.js +54 -0
- package/src/commons/SubUnit/ShortDetail.js +20 -4
- package/src/commons/SubUnit/__test__/ShortDetail.test.js +46 -1
- package/src/configs/API.js +6 -0
- package/src/configs/AccessibilityLabel.js +1 -0
- package/src/configs/Constants.js +7 -0
- package/src/configs/SCConfig.js +6 -0
- package/src/context/SCContext.tsx +12 -1
- package/src/context/SCStore.ts +14 -0
- package/src/context/actionType.ts +10 -0
- package/src/context/mockStore.ts +30 -1
- package/src/context/reducer.ts +35 -0
- package/src/hooks/IoT/useRemoteControl.js +4 -1
- package/src/hooks/IoT/useWatchSharedChips.js +130 -0
- package/src/hooks/Review/__test__/useInAppReview.test.js +99 -0
- package/src/hooks/Review/useInAppReview.js +70 -0
- package/src/hooks/useMqtt.js +78 -27
- package/src/iot/Monitor.js +149 -26
- package/src/iot/UpdateStates.js +60 -0
- package/src/iot/mqtt.js +177 -22
- package/src/navigations/UnitStack.js +16 -0
- package/src/screens/ActivityLog/ItemLog.js +1 -0
- package/src/screens/AddNewGateway/RenameNewDevices.js +5 -0
- package/src/screens/AddNewGateway/__test__/RenameNewDevices.test.js +18 -0
- package/src/screens/Automate/AddNewAction/ReceiverSelect.js +208 -0
- package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +1 -1
- package/src/screens/Automate/AddNewAction/SetupScriptNotify.js +18 -28
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +22 -129
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverNotify.js +59 -0
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverSms.js +22 -129
- package/src/screens/Automate/AddNewAction/SetupScriptSms.js +1 -1
- package/src/screens/Automate/AddNewAction/Styles/{SetupScriptReceiverEmailStyles.js → ReceiverSelectStyles.js} +18 -1
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptNotify.test.js +16 -33
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +10 -8
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverNotify.test.js +217 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverSms.test.js +10 -8
- package/src/screens/Automate/Components/InputName.js +5 -1
- package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +18 -0
- package/src/screens/Automate/ScriptDetail/index.js +6 -6
- package/src/screens/CreatePassword/__test__/index.test.js +133 -0
- package/src/screens/CreatePassword/index.js +134 -0
- package/src/screens/CreatePassword/styles.js +45 -0
- package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +447 -0
- package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +344 -0
- package/src/screens/Device/__test__/{mqttDetail.test.js → DeviceDetail-modbus.test.js} +287 -320
- package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +451 -0
- package/src/screens/Device/__test__/DeviceDetail.test.js +502 -0
- package/src/screens/Device/__test__/detail.test.js +61 -3
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +28 -3
- package/src/screens/Device/detail.js +14 -6
- package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +3 -2
- package/src/screens/EnterPassword/__test__/EnterPassword.test.js +76 -1
- package/src/screens/EnterPassword/index.js +34 -4
- package/src/screens/EnterPassword/styles.js +1 -1
- package/src/utils/FactoryGateway.js +597 -0
- package/src/utils/I18n/translations/en.js +10 -0
- package/src/utils/I18n/translations/vi.js +10 -0
- package/src/utils/Route/index.js +3 -1
- package/src/utils/Validation.js +5 -0
- 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(
|
|
151
|
+
const { chips, isFetching } = useChipJsonConfiguration({
|
|
152
|
+
dashboardId: unit?.id,
|
|
153
|
+
});
|
|
151
154
|
|
|
152
|
-
const
|
|
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(
|
|
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(
|
|
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
|
};
|