@eohjsc/react-native-smart-city 0.2.94 → 0.2.97
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/package.json +16 -4
- package/src/Images/Common/member.svg +4 -0
- package/src/Images/Common/owner.svg +3 -0
- package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +5 -1
- package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +5 -1
- package/src/commons/ActionGroup/__test__/OptionsDropdownTemplate.test.js +2 -2
- package/src/commons/Connecting/__test__/Connecting.test.js +23 -0
- package/src/commons/Connecting/index.js +67 -0
- package/src/commons/Connecting/styles.js +28 -0
- package/src/commons/ConnectingProcess/index.js +3 -54
- package/src/commons/Device/HistoryChart.js +2 -2
- package/src/commons/MenuActionMore/index.js +10 -16
- package/src/commons/PreventAccess/index.js +59 -0
- package/src/commons/PreventAccess/styles.js +33 -0
- package/src/commons/Sharing/MemberList.js +5 -10
- package/src/commons/Sharing/RowMember.js +128 -38
- package/src/commons/Sharing/__test__/MemberList.test.js +3 -3
- package/src/commons/Sharing/__test__/RowMember.test.js +4 -4
- package/src/configs/API.js +12 -2
- package/src/configs/Constants.js +10 -0
- package/src/hooks/Common/useSensorsStatus.js +33 -23
- package/src/iot/RemoteControl/GoogleHome.js +24 -11
- package/src/iot/RemoteControl/__test__/GoogleHome.test.js +32 -0
- package/src/navigations/UnitStack.js +16 -0
- package/src/screens/AddNewAction/SelectSensorDevices.js +6 -1
- package/src/screens/AddNewAction/__test__/SelectSensorDevices.test.js +34 -92
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +12 -3
- package/src/screens/AddNewGateway/PlugAndPlay/FirstWarning.js +5 -1
- package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +9 -1
- package/src/screens/Device/detail.js +16 -3
- package/src/screens/EditActionsList/Styles/indexStyles.js +1 -0
- package/src/screens/EmergencyContacts/EmergencyContactsList.js +1 -1
- package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +29 -11
- package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +1 -0
- package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +56 -0
- package/src/screens/EnterPassword/__test__/EnterPassword.test.js +124 -0
- package/src/screens/EnterPassword/index.js +84 -0
- package/src/screens/EnterPassword/styles.js +36 -0
- package/src/screens/Sharing/Components/ItemChangeRole.js +43 -0
- package/src/screens/Sharing/Components/SensorItem.js +7 -1
- package/src/screens/Sharing/Components/Styles/ItemChangeRoleStyles.js +35 -0
- package/src/screens/Sharing/Components/__test__/ItemChangeRole.test.js +37 -0
- package/src/screens/Sharing/Components/__test__/SensorItem.test.js +53 -0
- package/src/screens/Sharing/InfoMemberUnit.js +274 -0
- package/src/screens/Sharing/MemberList.js +50 -53
- package/src/screens/Sharing/SelectPermission.js +93 -12
- package/src/screens/Sharing/Styles/inforMemberUnitStyles.js +92 -0
- package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +121 -0
- package/src/screens/Sharing/__test__/MemberList.test.js +9 -24
- package/src/screens/Sharing/__test__/SelectPermission.test.js +53 -0
- package/src/screens/Sharing/hooks/index.js +76 -32
- package/src/screens/Unit/Detail.js +28 -13
- package/src/screens/Unit/ManageUnit.js +5 -5
- package/src/screens/Unit/ManageUnitStyles.js +1 -0
- package/src/screens/Unit/__test__/Detail.test.js +25 -5
- package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +1 -1
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +1 -1
- package/src/utils/I18n/translations/en.json +16 -1
- package/src/utils/I18n/translations/vi.json +14 -1
- package/src/utils/Route/index.js +2 -0
- package/src/utils/Utils.js +21 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
|
-
import { StyleSheet, View } from 'react-native';
|
|
3
|
-
import { IconOutline } from '@ant-design/icons-react-native';
|
|
2
|
+
import { StyleSheet, View, TouchableOpacity, Image } from 'react-native';
|
|
4
3
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
5
|
-
|
|
6
4
|
import { Colors } from '../../configs';
|
|
7
5
|
import Text from '../../commons/Text';
|
|
8
6
|
import { shortEmailName } from '../../utils/Utils';
|
|
9
|
-
|
|
10
|
-
import
|
|
7
|
+
import { CircleView } from '../CircleView';
|
|
8
|
+
import { useNavigation } from '@react-navigation/native';
|
|
9
|
+
import Routes from '../../utils/Route';
|
|
11
10
|
|
|
12
11
|
const arrColor = [
|
|
13
12
|
Colors.GeekBlue3,
|
|
@@ -19,46 +18,88 @@ const arrColor = [
|
|
|
19
18
|
Colors.Cyan2,
|
|
20
19
|
];
|
|
21
20
|
const RowMember = memo(
|
|
22
|
-
({
|
|
21
|
+
({
|
|
22
|
+
member,
|
|
23
|
+
index,
|
|
24
|
+
ownerId,
|
|
25
|
+
unit,
|
|
26
|
+
currentUserId,
|
|
27
|
+
type,
|
|
28
|
+
leftIcon = true,
|
|
29
|
+
rightComponent = true,
|
|
30
|
+
}) => {
|
|
23
31
|
const t = useTranslations();
|
|
24
|
-
const
|
|
25
|
-
() => ownerId === currentUserId && member.id !== ownerId,
|
|
26
|
-
[currentUserId, member.id, ownerId]
|
|
27
|
-
);
|
|
32
|
+
const { navigate } = useNavigation();
|
|
28
33
|
const [role, roleColor] = useMemo(
|
|
29
34
|
() =>
|
|
30
|
-
member
|
|
35
|
+
member?.id === ownerId
|
|
31
36
|
? [t('owner'), Colors.Primary]
|
|
32
|
-
: member
|
|
33
|
-
? [t('me'), Colors.
|
|
34
|
-
: ['',
|
|
35
|
-
[currentUserId, member
|
|
37
|
+
: member?.id === currentUserId
|
|
38
|
+
? [t('me'), Colors.Primary]
|
|
39
|
+
: [t('member'), Colors.Gray6],
|
|
40
|
+
[currentUserId, member?.id, ownerId, t]
|
|
36
41
|
);
|
|
37
|
-
const
|
|
42
|
+
const firstWordsInName = useMemo(() => {
|
|
43
|
+
const wordTemp = member?.name || shortEmailName(member?.email) || '';
|
|
44
|
+
return wordTemp?.charAt();
|
|
45
|
+
}, [member?.email, member?.name]);
|
|
46
|
+
|
|
38
47
|
if (member?.id === ownerId && member?.share_id) {
|
|
39
48
|
return null;
|
|
40
49
|
}
|
|
50
|
+
const circleColorTypes = {
|
|
51
|
+
primary: 'primary',
|
|
52
|
+
disable: 'disable',
|
|
53
|
+
noneBG: 'none',
|
|
54
|
+
};
|
|
55
|
+
const circleColor = type
|
|
56
|
+
? circleColorTypes[type]
|
|
57
|
+
: arrColor[index % arrColor.length];
|
|
58
|
+
|
|
59
|
+
const onPressInfo = () => {
|
|
60
|
+
navigate(Routes.UnitMemberInformation, {
|
|
61
|
+
member,
|
|
62
|
+
ownerId,
|
|
63
|
+
unit,
|
|
64
|
+
});
|
|
65
|
+
};
|
|
41
66
|
return (
|
|
42
67
|
<View style={styles.rowContainer}>
|
|
43
|
-
<
|
|
44
|
-
style={
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
<TouchableOpacity onPress={onPressInfo} disabled={type === 'disable'}>
|
|
69
|
+
<View style={styles.Border}>
|
|
70
|
+
{!!leftIcon && (
|
|
71
|
+
<View style={styles.paddingLeft16}>
|
|
72
|
+
{member?.avatar ? (
|
|
73
|
+
<Image
|
|
74
|
+
source={{ uri: member?.avatar }}
|
|
75
|
+
style={styles.avatar}
|
|
76
|
+
/>
|
|
77
|
+
) : (
|
|
78
|
+
<CircleView size={40} backgroundColor={circleColor} center>
|
|
79
|
+
<Text color={Colors.White}>{firstWordsInName}</Text>
|
|
80
|
+
</CircleView>
|
|
81
|
+
)}
|
|
82
|
+
</View>
|
|
83
|
+
)}
|
|
84
|
+
<View style={styles.columnFlex}>
|
|
85
|
+
<Text style={styles.titleName}>
|
|
86
|
+
{member?.name || shortEmailName(member?.email) || ''}
|
|
87
|
+
</Text>
|
|
88
|
+
{member?.phone_number && (
|
|
89
|
+
<Text style={styles.status}> {member?.phone_number}</Text>
|
|
90
|
+
)}
|
|
91
|
+
</View>
|
|
92
|
+
{!!rightComponent && (
|
|
93
|
+
<View style={styles.endFlex}>
|
|
94
|
+
{!!role && (
|
|
95
|
+
<Text style={[styles.textRole, { color: roleColor }]}>
|
|
96
|
+
{role}
|
|
97
|
+
</Text>
|
|
98
|
+
)}
|
|
99
|
+
</View>
|
|
100
|
+
)}
|
|
101
|
+
</View>
|
|
102
|
+
</TouchableOpacity>
|
|
62
103
|
</View>
|
|
63
104
|
);
|
|
64
105
|
}
|
|
@@ -68,9 +109,7 @@ export default RowMember;
|
|
|
68
109
|
|
|
69
110
|
const styles = StyleSheet.create({
|
|
70
111
|
rowContainer: {
|
|
71
|
-
|
|
72
|
-
alignItems: 'center',
|
|
73
|
-
paddingHorizontal: 16,
|
|
112
|
+
flex: 1,
|
|
74
113
|
},
|
|
75
114
|
iconContainer: {
|
|
76
115
|
alignItems: 'center',
|
|
@@ -107,4 +146,55 @@ const styles = StyleSheet.create({
|
|
|
107
146
|
textCenter: {
|
|
108
147
|
alignSelf: 'center',
|
|
109
148
|
},
|
|
149
|
+
columnFlex: {
|
|
150
|
+
paddingLeft: 16,
|
|
151
|
+
justifyContent: 'center',
|
|
152
|
+
flexDirection: 'column',
|
|
153
|
+
},
|
|
154
|
+
rowFlex: {
|
|
155
|
+
flexDirection: 'row',
|
|
156
|
+
},
|
|
157
|
+
endFlex: {
|
|
158
|
+
flex: 1,
|
|
159
|
+
justifyContent: 'flex-start',
|
|
160
|
+
alignItems: 'flex-end',
|
|
161
|
+
paddingRight: 16,
|
|
162
|
+
},
|
|
163
|
+
Border: {
|
|
164
|
+
display: 'flex',
|
|
165
|
+
width: '100%',
|
|
166
|
+
borderWidth: 0,
|
|
167
|
+
borderColor: Colors.Gray4,
|
|
168
|
+
borderBottomWidth: 1,
|
|
169
|
+
borderStyle: 'solid',
|
|
170
|
+
flexDirection: 'row',
|
|
171
|
+
paddingTop: 16,
|
|
172
|
+
paddingBottom: 16,
|
|
173
|
+
},
|
|
174
|
+
titleName: {
|
|
175
|
+
fontSize: 16,
|
|
176
|
+
lineHeight: 24,
|
|
177
|
+
fontStyle: 'normal',
|
|
178
|
+
fontWeight: '400',
|
|
179
|
+
color: Colors.Gray9,
|
|
180
|
+
},
|
|
181
|
+
status: {
|
|
182
|
+
fontSize: 12,
|
|
183
|
+
lineHeight: 20,
|
|
184
|
+
fontStyle: 'normal',
|
|
185
|
+
fontWeight: '400',
|
|
186
|
+
color: Colors.Gray7,
|
|
187
|
+
},
|
|
188
|
+
container: {
|
|
189
|
+
paddingTop: 0,
|
|
190
|
+
},
|
|
191
|
+
paddingLeft16: {
|
|
192
|
+
paddingLeft: 16,
|
|
193
|
+
},
|
|
194
|
+
avatar: {
|
|
195
|
+
height: 40,
|
|
196
|
+
width: 40,
|
|
197
|
+
borderRadius: 40,
|
|
198
|
+
backgroundColor: Colors.Primary,
|
|
199
|
+
},
|
|
110
200
|
});
|
|
@@ -27,7 +27,7 @@ describe('MemberList', () => {
|
|
|
27
27
|
});
|
|
28
28
|
const instance = tree.root;
|
|
29
29
|
const textInputs = instance.findAllByType(Text);
|
|
30
|
-
expect(textInputs.length).toBe(
|
|
30
|
+
expect(textInputs.length).toBe(5);
|
|
31
31
|
});
|
|
32
32
|
test('MemberList snapshot id dataMember !== ownerId', () => {
|
|
33
33
|
const dataMember = [{ id: 1, name: 'CEO' }];
|
|
@@ -36,7 +36,7 @@ describe('MemberList', () => {
|
|
|
36
36
|
});
|
|
37
37
|
const instance = tree.root;
|
|
38
38
|
const textInputs = instance.findAllByType(Text);
|
|
39
|
-
expect(textInputs.length).toBe(
|
|
39
|
+
expect(textInputs.length).toBe(5);
|
|
40
40
|
});
|
|
41
41
|
test('MemberList snapshot id dataMember === currentUserId', () => {
|
|
42
42
|
const dataMember = [{ id: 1, name: 'CEO' }];
|
|
@@ -45,7 +45,7 @@ describe('MemberList', () => {
|
|
|
45
45
|
});
|
|
46
46
|
const instance = tree.root;
|
|
47
47
|
const textInputs = instance.findAllByType(Text);
|
|
48
|
-
expect(textInputs.length).toBe(
|
|
48
|
+
expect(textInputs.length).toBe(5);
|
|
49
49
|
});
|
|
50
50
|
test('MemberList dataMember null', () => {
|
|
51
51
|
const dataMember = [];
|
|
@@ -26,8 +26,8 @@ describe('RowMember', () => {
|
|
|
26
26
|
});
|
|
27
27
|
const instance = tree.root;
|
|
28
28
|
const textInputs = instance.findAllByType(Text);
|
|
29
|
-
expect(textInputs.length).toBe(
|
|
30
|
-
expect(textInputs[
|
|
29
|
+
expect(textInputs.length).toBe(5);
|
|
30
|
+
expect(textInputs[1].props.children).toEqual('CEO');
|
|
31
31
|
});
|
|
32
32
|
test('RowMember owner dont have name show start of email ', () => {
|
|
33
33
|
const dataMember = { id: 1, name: '', email: 'abc@gmail.com' };
|
|
@@ -36,7 +36,7 @@ describe('RowMember', () => {
|
|
|
36
36
|
});
|
|
37
37
|
const instance = tree.root;
|
|
38
38
|
const textInputs = instance.findAllByType(Text);
|
|
39
|
-
expect(textInputs.length).toBe(
|
|
40
|
-
expect(textInputs[
|
|
39
|
+
expect(textInputs.length).toBe(5);
|
|
40
|
+
expect(textInputs[1].props.children).toEqual('abc');
|
|
41
41
|
});
|
|
42
42
|
});
|
package/src/configs/API.js
CHANGED
|
@@ -39,6 +39,8 @@ const API = {
|
|
|
39
39
|
SCConfig.apiRoot + `/property_manager/units/${id}/add_gateway/`,
|
|
40
40
|
SENSORS_STATUS: (id) =>
|
|
41
41
|
SCConfig.apiRoot + `/property_manager/units/${id}/sensors_status/`,
|
|
42
|
+
CHANGE_OWNER: (id) =>
|
|
43
|
+
SCConfig.apiRoot + `/property_manager/units/${id}/change_owner/`,
|
|
42
44
|
FAVOURITE_DEVICES: (id) =>
|
|
43
45
|
SCConfig.apiRoot + `/property_manager/units/${id}/favourite_devices/`,
|
|
44
46
|
},
|
|
@@ -137,9 +139,9 @@ const API = {
|
|
|
137
139
|
CHECK_SEND_EMAIL: () =>
|
|
138
140
|
SCConfig.apiRoot + '/connection_manager/googlehome/check_send_email/',
|
|
139
141
|
},
|
|
140
|
-
|
|
142
|
+
VALUE_CONSUME: {
|
|
141
143
|
DISPLAY_HISTORY: () =>
|
|
142
|
-
SCConfig.apiRoot + '/property_manager/
|
|
144
|
+
SCConfig.apiRoot + '/property_manager/value_consume/display_history/',
|
|
143
145
|
},
|
|
144
146
|
SHARE: {
|
|
145
147
|
UNITS: () => SCConfig.apiRoot + '/property_manager/sharing/units/',
|
|
@@ -150,6 +152,12 @@ const API = {
|
|
|
150
152
|
UNITS_MEMBER_DETAIL: (id, shareId) =>
|
|
151
153
|
SCConfig.apiRoot +
|
|
152
154
|
`/property_manager/sharing/units/${id}/members/${shareId}/`,
|
|
155
|
+
UNIT_MEMBER_INFO: (unit_id, member_id) =>
|
|
156
|
+
SCConfig.apiRoot +
|
|
157
|
+
`/property_manager/sharing/units/${unit_id}/member/${member_id}/information/`,
|
|
158
|
+
UNIT_MEMBER_SHARE_DEVICE: (unit_id, member_id) =>
|
|
159
|
+
SCConfig.apiRoot +
|
|
160
|
+
`/property_manager/sharing/units/${unit_id}/member/${member_id}/shared_devices/`,
|
|
153
161
|
SHARE: () => SCConfig.apiRoot + '/property_manager/sharing/share/',
|
|
154
162
|
},
|
|
155
163
|
EMERGENCY: {
|
|
@@ -157,6 +165,8 @@ const API = {
|
|
|
157
165
|
},
|
|
158
166
|
EMERGENCY_BUTTON: {
|
|
159
167
|
CREATE_CONTACT: () => SCConfig.apiRoot + '/emergency_button/contacts/',
|
|
168
|
+
CREATE_BATCH: () =>
|
|
169
|
+
SCConfig.apiRoot + '/emergency_button/contacts/create_batch/',
|
|
160
170
|
CONTACTS: () => SCConfig.apiRoot + '/emergency_button/contacts/',
|
|
161
171
|
REMOVE_CONTACTS: (id) =>
|
|
162
172
|
SCConfig.apiRoot + `/emergency_button/contacts/${id}/`,
|
package/src/configs/Constants.js
CHANGED
|
@@ -217,6 +217,10 @@ export const TESTID = {
|
|
|
217
217
|
MY_UNIT_NO_UNIT: 'MY_UNIT_NO_UNIT',
|
|
218
218
|
ITEM_UNIT: 'ITEM_UNIT',
|
|
219
219
|
|
|
220
|
+
//member list
|
|
221
|
+
SHARING_MEMBER: 'SHARING_MEMBER',
|
|
222
|
+
REMOVE_MEMBER: 'REMOVE_MEMBER',
|
|
223
|
+
|
|
220
224
|
// SmartTiviTemplate
|
|
221
225
|
SMART_TIVI_TEMPLATE: {
|
|
222
226
|
BIG_BUTTON: 'BIG_BUTTON',
|
|
@@ -309,6 +313,10 @@ export const TESTID = {
|
|
|
309
313
|
BUTTON_SELECT_VISA: 'BUTTON_SELECT_VISA',
|
|
310
314
|
BUTTON_SELECT_MASTER_CARD: 'BUTTON_SELECT_MASTER_CARD',
|
|
311
315
|
|
|
316
|
+
//Enter Password
|
|
317
|
+
ENTER_PASSWORD_TEXT_INPUT_PASSWORD: 'ENTER_PASSWORD_TEXT_INPUT_PASSWORD',
|
|
318
|
+
ENTER_PASSWORD_BUTTON_DONE: 'ENTER_PASSWORD_BUTTON_DONE',
|
|
319
|
+
|
|
312
320
|
// Map Dashboard
|
|
313
321
|
PARKING_MARKER: 'PARKING_MARKER',
|
|
314
322
|
|
|
@@ -424,6 +432,8 @@ export const TESTID = {
|
|
|
424
432
|
ITEM_QUICK_ACTION_PRESS: 'ITEM_QUICK_ACTION_PRESS',
|
|
425
433
|
TIME_COUNT_DOWN_TEXT: 'TIME_COUNT_DOWN_TEXT',
|
|
426
434
|
ACTION_ITEM: 'ACTION_ITEM',
|
|
435
|
+
// Sensor Item
|
|
436
|
+
TEXT_SENSOR_ITEM: 'TEXT_SENSOR_ITEM',
|
|
427
437
|
|
|
428
438
|
// DeviceInfo
|
|
429
439
|
DEVICE_INFO_BATTERY: 'DEVICE_INFO_BATTERY',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { useState, useEffect, useRef } from 'react';
|
|
1
|
+
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
2
2
|
import { useIsFocused } from '@react-navigation/native';
|
|
3
|
+
import { throttle } from 'lodash';
|
|
3
4
|
import { axiosGet } from '../../utils/Apis/axios';
|
|
4
5
|
import { API } from '../../configs';
|
|
5
6
|
|
|
@@ -9,35 +10,44 @@ const useSensorsStatus = (unit, sensors) => {
|
|
|
9
10
|
const [sensorsStatus, setSensorsStatus] = useState([]);
|
|
10
11
|
const [serverDown, setServerDown] = useState(false);
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
);
|
|
26
|
-
if (success) {
|
|
27
|
-
setSensorsStatus(data);
|
|
28
|
-
setServerDown(false);
|
|
29
|
-
} else if (resp_status >= 500) {
|
|
30
|
-
setServerDown(true);
|
|
13
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
14
|
+
const getSensorsStatus = useCallback(
|
|
15
|
+
throttle(async (unit, sensors) => {
|
|
16
|
+
const params = new URLSearchParams();
|
|
17
|
+
if (sensors?.length > 0) {
|
|
18
|
+
sensors.forEach((sensor) => {
|
|
19
|
+
params.append('sensors', sensor.id);
|
|
20
|
+
});
|
|
21
|
+
const { success, data, resp_status } = await axiosGet(
|
|
22
|
+
API.UNIT.SENSORS_STATUS(unit.id),
|
|
23
|
+
{
|
|
24
|
+
params: params,
|
|
31
25
|
}
|
|
26
|
+
);
|
|
27
|
+
if (success) {
|
|
28
|
+
setSensorsStatus(data);
|
|
29
|
+
setServerDown(false);
|
|
30
|
+
} else if (resp_status > 500) {
|
|
31
|
+
setServerDown(true);
|
|
32
32
|
}
|
|
33
|
-
}
|
|
34
|
-
|
|
33
|
+
}
|
|
34
|
+
}, 3000),
|
|
35
|
+
[]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (isFocused) {
|
|
40
|
+
getSensorsStatus(unit, sensors);
|
|
41
|
+
const updateInterval = setInterval(
|
|
42
|
+
() => getSensorsStatus(unit, sensors),
|
|
43
|
+
5000
|
|
44
|
+
);
|
|
35
45
|
intervalSensorStatus.current = updateInterval;
|
|
36
46
|
return () => clearInterval(updateInterval);
|
|
37
47
|
} else {
|
|
38
48
|
clearInterval(intervalSensorStatus.current);
|
|
39
49
|
}
|
|
40
|
-
}, [isFocused,
|
|
50
|
+
}, [isFocused, getSensorsStatus, unit, sensors]);
|
|
41
51
|
|
|
42
52
|
const getStatus = (sensor) => {
|
|
43
53
|
sensorsStatus.find((s) => s.id === sensor.id);
|
|
@@ -201,8 +201,22 @@ function getServiceName(message) {
|
|
|
201
201
|
return serviceSplit.join('_');
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
async function sendCommandSingleAction(connection, ghAction, data) {
|
|
205
|
+
const { message } = ghAction || {};
|
|
206
|
+
const name = getServiceName(message);
|
|
207
|
+
|
|
208
|
+
if (name && data) {
|
|
209
|
+
message.service_data[name] = data;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
await connection.sendMessagePromise(message);
|
|
213
|
+
}
|
|
214
|
+
|
|
204
215
|
export async function sendCommandOverGoogleHome(sensor, action, data) {
|
|
205
|
-
if (
|
|
216
|
+
if (
|
|
217
|
+
!(action.googlehome_actions && action.googlehome_actions.length) &&
|
|
218
|
+
!action.googlehome_action
|
|
219
|
+
) {
|
|
206
220
|
return;
|
|
207
221
|
}
|
|
208
222
|
|
|
@@ -212,20 +226,19 @@ export async function sendCommandOverGoogleHome(sensor, action, data) {
|
|
|
212
226
|
return;
|
|
213
227
|
}
|
|
214
228
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
229
|
+
if (action.googlehome_actions) {
|
|
230
|
+
for (let i = 0; i < action.googlehome_actions.length; i++) {
|
|
231
|
+
await sendCommandSingleAction(
|
|
232
|
+
connection,
|
|
233
|
+
action.googlehome_actions[i],
|
|
234
|
+
data
|
|
235
|
+
);
|
|
222
236
|
}
|
|
223
|
-
|
|
224
|
-
await connection.
|
|
237
|
+
} else if (action.googlehome_action) {
|
|
238
|
+
await sendCommandSingleAction(connection, action.googlehome_action, data);
|
|
225
239
|
}
|
|
226
240
|
|
|
227
241
|
const { success } = await axiosPost(API.SENSOR.ACTIVITY_LOG(), {
|
|
228
|
-
sensor_id: sensor.id,
|
|
229
242
|
action_id: action.id,
|
|
230
243
|
message: 'Trigger by user action with google home',
|
|
231
244
|
});
|
|
@@ -75,6 +75,9 @@ describe('Remote Control Google Home', () => {
|
|
|
75
75
|
message: 'message',
|
|
76
76
|
},
|
|
77
77
|
],
|
|
78
|
+
googlehome_action: {
|
|
79
|
+
message: 'message',
|
|
80
|
+
},
|
|
78
81
|
};
|
|
79
82
|
|
|
80
83
|
const response = {
|
|
@@ -223,6 +226,35 @@ describe('Remote Control Google Home', () => {
|
|
|
223
226
|
});
|
|
224
227
|
});
|
|
225
228
|
|
|
229
|
+
it('Send command over google home action googlehome_action one to one', async () => {
|
|
230
|
+
action.googlehome_actions = null;
|
|
231
|
+
action.googlehome_action.message = {
|
|
232
|
+
type: 'call_service',
|
|
233
|
+
domain: 'climate',
|
|
234
|
+
service: 'set_temperature',
|
|
235
|
+
service_data: {
|
|
236
|
+
temperature: 0,
|
|
237
|
+
entity_id: 'climate.dqsmart_0108f6cdde',
|
|
238
|
+
},
|
|
239
|
+
id: 20,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
axios.post.mockImplementation(async () => {
|
|
243
|
+
return response;
|
|
244
|
+
});
|
|
245
|
+
await googleHomeConnect(options);
|
|
246
|
+
await sendCommandOverGoogleHome(sensor, action, 19);
|
|
247
|
+
|
|
248
|
+
action.googlehome_action.message.service_data.temperature = 19;
|
|
249
|
+
expect(connection.sendMessagePromise).toBeCalledWith(
|
|
250
|
+
action.googlehome_action.message
|
|
251
|
+
);
|
|
252
|
+
expect(axios.post).toHaveBeenCalledWith(API.SENSOR.ACTIVITY_LOG(), {
|
|
253
|
+
action_id: 1,
|
|
254
|
+
message: 'Trigger by user action with google home',
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
226
258
|
it('Send command over google home that not connected', async () => {
|
|
227
259
|
await googleHomeConnect(options);
|
|
228
260
|
await sendCommandOverGoogleHome({ chip_id: 2 }, action);
|
|
@@ -49,6 +49,8 @@ import SetUpSensor from '../screens/AddNewAction/SetupSensor';
|
|
|
49
49
|
import EditDevice from '../screens/Device/EditDevice/index';
|
|
50
50
|
import EmergencySetting from '../screens/EmergencySetting';
|
|
51
51
|
import ConfirmUnitDeletion from '../screens/ConfirmUnitDeletion';
|
|
52
|
+
import InfoMemberUnit from '../screens/Sharing/InfoMemberUnit';
|
|
53
|
+
import EnterPassword from '../screens/EnterPassword';
|
|
52
54
|
import { HanetCameraStack } from './HanetCameraStack';
|
|
53
55
|
|
|
54
56
|
import { axiosGet } from '../utils/Apis/axios';
|
|
@@ -268,6 +270,20 @@ export const UnitStack = memo((props) => {
|
|
|
268
270
|
headerShown: false,
|
|
269
271
|
}}
|
|
270
272
|
/>
|
|
273
|
+
<Stack.Screen
|
|
274
|
+
name={Route.UnitMemberInformation}
|
|
275
|
+
component={InfoMemberUnit}
|
|
276
|
+
options={{
|
|
277
|
+
headerShown: false,
|
|
278
|
+
}}
|
|
279
|
+
/>
|
|
280
|
+
<Stack.Screen
|
|
281
|
+
name={Route.EnterPassword}
|
|
282
|
+
component={EnterPassword}
|
|
283
|
+
options={{
|
|
284
|
+
headerShown: false,
|
|
285
|
+
}}
|
|
286
|
+
/>
|
|
271
287
|
<Stack.Screen
|
|
272
288
|
name={Route.DeviceInfo}
|
|
273
289
|
component={DeviceInfo}
|
|
@@ -37,6 +37,7 @@ const SelectSensorDevices = memo(({ route }) => {
|
|
|
37
37
|
const [selectedDevice, setSelectedDevice] = useState();
|
|
38
38
|
const { navigate, dispatch, goBack } = useNavigation();
|
|
39
39
|
const isSelectSensor = title === AUTOMATE_SELECT.SELECT_SENSOR;
|
|
40
|
+
const [loading, setLoading] = useState(true);
|
|
40
41
|
|
|
41
42
|
const onSnapToItem = useCallback(
|
|
42
43
|
(item, index) => {
|
|
@@ -83,6 +84,7 @@ const SelectSensorDevices = memo(({ route }) => {
|
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
);
|
|
87
|
+
setLoading(false);
|
|
86
88
|
}, [automate.sensor_id, isSelectSensor, unit]);
|
|
87
89
|
|
|
88
90
|
useEffect(() => {
|
|
@@ -162,6 +164,9 @@ const SelectSensorDevices = memo(({ route }) => {
|
|
|
162
164
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
163
165
|
[route.params]
|
|
164
166
|
);
|
|
167
|
+
if (loading) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
165
170
|
|
|
166
171
|
return (
|
|
167
172
|
<View style={styles.wrap}>
|
|
@@ -175,7 +180,7 @@ const SelectSensorDevices = memo(({ route }) => {
|
|
|
175
180
|
{t(title)}
|
|
176
181
|
</Text>
|
|
177
182
|
|
|
178
|
-
{listStation ? (
|
|
183
|
+
{listStation.length ? (
|
|
179
184
|
<NavBar
|
|
180
185
|
listStation={listStation}
|
|
181
186
|
listMenuItem={listMenuItem}
|