@eohjsc/react-native-smart-city 0.2.79 → 0.2.83
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 +4 -4
- package/src/commons/ActionGroup/CurtainButtonTemplate.js +32 -21
- package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +8 -6
- package/src/commons/ActionGroup/OnOffTemplate/index.js +11 -3
- package/src/commons/ActionGroup/OneBigButtonTemplate.js +10 -7
- package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +5 -2
- package/src/commons/ActionGroup/StatesGridActionTemplate.js +7 -3
- package/src/commons/ActionGroup/ThreeButtonTemplate.js +33 -24
- package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +18 -6
- package/src/commons/ActionGroup/__test__/OneBigButtonTemplate.test.js +9 -1
- package/src/commons/ActionGroup/__test__/OptionsDropdownTemplate.test.js +25 -13
- package/src/commons/ActionGroup/__test__/index.test.js +48 -14
- package/src/commons/Device/HorizontalBarChart.js +8 -2
- package/src/commons/Device/ItemDevice.js +8 -5
- package/src/commons/Device/LinearChart.js +1 -1
- package/src/commons/EmergencyButton/AlertSendConfirm.js +2 -2
- package/src/commons/EmergencyButton/AlertSent.js +2 -2
- package/src/commons/ImagePicker/__test__/ImagePicker.test.js +24 -3
- package/src/commons/MediaPlayerDetail/index.js +1 -0
- package/src/commons/SubUnit/Favorites/index.js +2 -0
- package/src/commons/SubUnit/ShortDetail.js +7 -1
- package/src/configs/API.js +2 -4
- package/src/configs/Constants.js +5 -0
- package/src/iot/RemoteControl/Internet.js +8 -1
- package/src/iot/RemoteControl/index.js +4 -2
- package/src/screens/AddCommon/SelectSubUnit.js +6 -0
- package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +52 -0
- package/src/screens/AllCamera/index.js +76 -44
- package/src/screens/Device/EditDevice/__test__/EditDevice.test.js +2 -2
- package/src/screens/Device/EditDevice/index.js +2 -2
- package/src/screens/Device/__test__/detail.test.js +18 -11
- package/src/screens/Device/components/SensorConnectStatusViewHeader.js +2 -2
- package/src/screens/Device/components/SensorDisplayItem.js +2 -2
- package/src/screens/Device/detail.js +58 -20
- package/src/screens/Notification/__test__/NotificationItem.test.js +186 -14
- package/src/screens/Notification/components/NotificationItem.js +147 -3
- package/src/screens/Notification/index.js +4 -1
- package/src/screens/Notification/styles/NotificationItemStyles.js +3 -3
- package/src/screens/Sharing/SelectUser.js +17 -10
- package/src/screens/Sharing/__test__/SelectUser.test.js +73 -0
- package/src/screens/SubUnit/AddSubUnit.js +4 -1
- package/src/screens/SubUnit/__test__/AddSubUnit.test.js +148 -0
- package/src/screens/Unit/Detail.js +28 -4
- package/src/screens/Unit/ManageUnit.js +88 -32
- package/src/screens/Unit/ManageUnitStyles.js +20 -0
- package/src/screens/Unit/SmartAccount.js +6 -2
- package/src/screens/Unit/Summaries.js +2 -2
- package/src/screens/Unit/__test__/CheckSendEmail.test.js +10 -0
- package/src/screens/Unit/__test__/Detail.test.js +53 -0
- package/src/screens/Unit/__test__/ManageUnit.test.js +69 -0
- package/src/screens/Unit/__test__/SmartAccount.test.js +37 -8
- package/src/screens/Unit/components/__test__/SharedUnit.test.js +21 -2
- package/src/screens/Unit/hook/useStateAlertRemove.js +1 -1
- package/src/screens/UnitSummary/__test__/index.test.js +3 -3
- package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +2 -2
- package/src/screens/UnitSummary/index.js +52 -9
- package/src/utils/Apis/axios.js +7 -2
- package/src/utils/I18n/translations/en.json +10 -1
- package/src/utils/I18n/translations/vi.json +10 -1
- package/src/{screens/Notification → utils}/Monitor.js +1 -1
|
@@ -199,4 +199,152 @@ describe('Test AddSubUnit', () => {
|
|
|
199
199
|
visibilityTime: 1000,
|
|
200
200
|
});
|
|
201
201
|
});
|
|
202
|
+
|
|
203
|
+
test('test create Unit', async () => {
|
|
204
|
+
const response = {
|
|
205
|
+
success: true,
|
|
206
|
+
status: 200,
|
|
207
|
+
data: {
|
|
208
|
+
id: 2,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
route.params = {
|
|
212
|
+
...route.params,
|
|
213
|
+
location: 'Unit address',
|
|
214
|
+
isAddUnit: true,
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
axios.post.mockImplementation(async () => {
|
|
218
|
+
return response;
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
await act(async () => {
|
|
222
|
+
tree = await create(wrapComponent(route));
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const instance = tree.root;
|
|
226
|
+
const viewButtonBottom = await makeValidateData(instance);
|
|
227
|
+
|
|
228
|
+
await act(async () => {
|
|
229
|
+
await viewButtonBottom.props.onRightClick();
|
|
230
|
+
});
|
|
231
|
+
expect(axios.post).toHaveBeenCalled();
|
|
232
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.UnitStack, {
|
|
233
|
+
screen: Routes.UnitDetail,
|
|
234
|
+
params: {
|
|
235
|
+
unitId: response.data.id,
|
|
236
|
+
routeName: Routes.DashboardStack,
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test('test choose Location', async () => {
|
|
242
|
+
route.params = {
|
|
243
|
+
...route.params,
|
|
244
|
+
location: '',
|
|
245
|
+
isAddUnit: true,
|
|
246
|
+
};
|
|
247
|
+
await act(async () => {
|
|
248
|
+
tree = await create(wrapComponent(route));
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const instance = tree.root;
|
|
252
|
+
const buttonChooseLocation = instance.find(
|
|
253
|
+
(el) => el.props.testID === TESTID.ADD_SUB_UNIT_BUTTON_CHOOSE_LOCATION
|
|
254
|
+
);
|
|
255
|
+
act(() => {
|
|
256
|
+
buttonChooseLocation.props.onPress();
|
|
257
|
+
});
|
|
258
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddLocationMaps);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test('test create Unit Fail', async () => {
|
|
262
|
+
const response = {
|
|
263
|
+
success: false,
|
|
264
|
+
status: 400,
|
|
265
|
+
};
|
|
266
|
+
route.params = {
|
|
267
|
+
...route.params,
|
|
268
|
+
location: 'Unit address',
|
|
269
|
+
isAddUnit: true,
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
axios.post.mockImplementation(async () => {
|
|
273
|
+
return response;
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
await act(async () => {
|
|
277
|
+
tree = await create(wrapComponent(route));
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const instance = tree.root;
|
|
281
|
+
const viewButtonBottom = await makeValidateData(instance);
|
|
282
|
+
|
|
283
|
+
await act(async () => {
|
|
284
|
+
await viewButtonBottom.props.onRightClick();
|
|
285
|
+
});
|
|
286
|
+
expect(axios.post).toHaveBeenCalled();
|
|
287
|
+
expect(Toast.show).toHaveBeenCalledWith({
|
|
288
|
+
type: 'error',
|
|
289
|
+
position: 'bottom',
|
|
290
|
+
text1: getTranslate('en', 'text_create_unit_fail'),
|
|
291
|
+
visibilityTime: 1000,
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test('test create sub-unit type AddHassiDevice', async () => {
|
|
296
|
+
const response = {
|
|
297
|
+
status: 200,
|
|
298
|
+
success: true,
|
|
299
|
+
data: {},
|
|
300
|
+
};
|
|
301
|
+
route.params = {
|
|
302
|
+
...route.params,
|
|
303
|
+
addType: 'AddHassiDevice',
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
axios.post.mockImplementation(async () => {
|
|
307
|
+
return response;
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
await act(async () => {
|
|
311
|
+
tree = await create(wrapComponent(route));
|
|
312
|
+
});
|
|
313
|
+
const instance = tree.root;
|
|
314
|
+
const viewButtonBottom = await makeValidateData(instance);
|
|
315
|
+
await act(async () => {
|
|
316
|
+
await viewButtonBottom.props.onRightClick();
|
|
317
|
+
});
|
|
318
|
+
expect(axios.post).toHaveBeenCalled();
|
|
319
|
+
expect(mockedGoBack).toHaveBeenCalled();
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
test('test create sub-unit type AddNewGateway', async () => {
|
|
323
|
+
const response = {
|
|
324
|
+
status: 200,
|
|
325
|
+
success: true,
|
|
326
|
+
data: {},
|
|
327
|
+
};
|
|
328
|
+
route.params = {
|
|
329
|
+
...route.params,
|
|
330
|
+
addType: 'AddNewGateway',
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
axios.post.mockImplementation(async () => {
|
|
334
|
+
return response;
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
await act(async () => {
|
|
338
|
+
tree = await create(wrapComponent(route));
|
|
339
|
+
});
|
|
340
|
+
const instance = tree.root;
|
|
341
|
+
const viewButtonBottom = await makeValidateData(instance);
|
|
342
|
+
await act(async () => {
|
|
343
|
+
await viewButtonBottom.props.onRightClick();
|
|
344
|
+
});
|
|
345
|
+
expect(axios.post).toHaveBeenCalled();
|
|
346
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddCommonSelectSubUnit, {
|
|
347
|
+
...route.params,
|
|
348
|
+
});
|
|
349
|
+
});
|
|
202
350
|
});
|
|
@@ -2,6 +2,7 @@ import React, { useCallback, useContext, useEffect, useState } from 'react';
|
|
|
2
2
|
import { AppState, RefreshControl, View } from 'react-native';
|
|
3
3
|
import { useIsFocused } from '@react-navigation/native';
|
|
4
4
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
5
|
+
import { useNetInfo } from '@react-native-community/netinfo';
|
|
5
6
|
|
|
6
7
|
import styles from './styles';
|
|
7
8
|
import AddMenu from './AddMenu';
|
|
@@ -26,7 +27,11 @@ import { useNavigation } from '@react-navigation/native';
|
|
|
26
27
|
import Routes from '../../utils/Route';
|
|
27
28
|
import SubUnitAutomate from '../../commons/SubUnit/OneTap';
|
|
28
29
|
import SubUnitFavorites from '../../commons/SubUnit/Favorites';
|
|
29
|
-
import { AUTOMATE_TYPE } from '../../configs/Constants';
|
|
30
|
+
import { AUTOMATE_TYPE, NOTIFICATION_TYPES } from '../../configs/Constants';
|
|
31
|
+
import {
|
|
32
|
+
watchNotificationData,
|
|
33
|
+
unwatchNotificationData,
|
|
34
|
+
} from '../../utils/Monitor';
|
|
30
35
|
|
|
31
36
|
const UnitDetail = ({ route }) => {
|
|
32
37
|
const t = useTranslations();
|
|
@@ -43,6 +48,7 @@ const UnitDetail = ({ route }) => {
|
|
|
43
48
|
const isFocused = useIsFocused();
|
|
44
49
|
const { stateData, setAction } = useContext(SCContext);
|
|
45
50
|
const { navigate } = useNavigation();
|
|
51
|
+
const user = useSCContextSelector((state) => state?.auth?.account?.user);
|
|
46
52
|
const isLavidaSource = useSCContextSelector(
|
|
47
53
|
(state) => state.app.isLavidaSource
|
|
48
54
|
);
|
|
@@ -57,6 +63,7 @@ const UnitDetail = ({ route }) => {
|
|
|
57
63
|
automates: [],
|
|
58
64
|
});
|
|
59
65
|
const [isGGHomeConnected, setIsGGHomeConnected] = useState(false);
|
|
66
|
+
const [isNetworkConnected, setIsNetworkConnected] = useState(true);
|
|
60
67
|
const [station, setStation] = useState({});
|
|
61
68
|
const [indexStation, setIndexStation] = useState(0);
|
|
62
69
|
const [showAdd, setShowAdd, setHideAdd] = useBoolean();
|
|
@@ -68,6 +75,8 @@ const UnitDetail = ({ route }) => {
|
|
|
68
75
|
|
|
69
76
|
const { isOwner } = useIsOwnerOfUnit(unit.user_id);
|
|
70
77
|
|
|
78
|
+
const netInfo = useNetInfo();
|
|
79
|
+
|
|
71
80
|
const handleFullScreen = (data) => {
|
|
72
81
|
setIsFullScreen(!isFullScreen);
|
|
73
82
|
setDataFullScreen(data);
|
|
@@ -144,9 +153,13 @@ const UnitDetail = ({ route }) => {
|
|
|
144
153
|
);
|
|
145
154
|
}, [t, unitId]);
|
|
146
155
|
|
|
147
|
-
const onRefresh = useCallback(
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
const onRefresh = useCallback(
|
|
157
|
+
(data = { content_code: NOTIFICATION_TYPES.NOTIFY_RENAME_UNIT }) => {
|
|
158
|
+
data.content_code === NOTIFICATION_TYPES.NOTIFY_RENAME_UNIT &&
|
|
159
|
+
fetchDetails();
|
|
160
|
+
},
|
|
161
|
+
[fetchDetails]
|
|
162
|
+
);
|
|
150
163
|
|
|
151
164
|
const handleAppStateChange = useCallback(
|
|
152
165
|
(nextAppState) => {
|
|
@@ -166,6 +179,10 @@ const UnitDetail = ({ route }) => {
|
|
|
166
179
|
};
|
|
167
180
|
}, [handleAppStateChange]);
|
|
168
181
|
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
setIsNetworkConnected(netInfo.isConnected);
|
|
184
|
+
}, [netInfo.isConnected]);
|
|
185
|
+
|
|
169
186
|
const handleGoogleHomeConnect = useCallback(
|
|
170
187
|
async (options) => {
|
|
171
188
|
let isConnected = await googleHomeConnect(options); // this may wrong if have multiple connection
|
|
@@ -272,6 +289,7 @@ const UnitDetail = ({ route }) => {
|
|
|
272
289
|
isOwner={isOwner}
|
|
273
290
|
favorites={favorites}
|
|
274
291
|
wrapItemStyle={styles.wrapItemStyle}
|
|
292
|
+
isNetworkConnected={isNetworkConnected}
|
|
275
293
|
isGGHomeConnected={isGGHomeConnected}
|
|
276
294
|
/>
|
|
277
295
|
);
|
|
@@ -298,6 +316,7 @@ const UnitDetail = ({ route }) => {
|
|
|
298
316
|
<ShortDetailSubUnit
|
|
299
317
|
unit={unit}
|
|
300
318
|
station={station}
|
|
319
|
+
isNetworkConnected={isNetworkConnected}
|
|
301
320
|
isGGHomeConnected={isGGHomeConnected}
|
|
302
321
|
/>
|
|
303
322
|
);
|
|
@@ -312,6 +331,11 @@ const UnitDetail = ({ route }) => {
|
|
|
312
331
|
navigate(isLavidaSource ? Routes.SmartHomeDashboard : Routes.Dashboard);
|
|
313
332
|
}, [isLavidaSource, navigate]);
|
|
314
333
|
|
|
334
|
+
useEffect(() => {
|
|
335
|
+
watchNotificationData(user, onRefresh);
|
|
336
|
+
return () => unwatchNotificationData(user);
|
|
337
|
+
}, [user, onRefresh]);
|
|
338
|
+
|
|
315
339
|
return (
|
|
316
340
|
<WrapParallaxScrollView
|
|
317
341
|
uriImg={unit.background}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useCallback, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useCallback, useEffect, useMemo } from 'react';
|
|
2
2
|
import { View, TouchableOpacity, Image, Platform } from 'react-native';
|
|
3
3
|
import Animated from 'react-native-reanimated';
|
|
4
4
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
@@ -21,6 +21,7 @@ import { IconOutline } from '@ant-design/icons-react-native';
|
|
|
21
21
|
import styles from './ManageUnitStyles';
|
|
22
22
|
import { useNavigation } from '@react-navigation/native';
|
|
23
23
|
import { ModalCustom } from '../../commons/Modal';
|
|
24
|
+
import { Icon } from '@ant-design/react-native';
|
|
24
25
|
|
|
25
26
|
const ButtonWrapper = ({
|
|
26
27
|
onPress,
|
|
@@ -29,17 +30,26 @@ const ButtonWrapper = ({
|
|
|
29
30
|
value,
|
|
30
31
|
valueColor,
|
|
31
32
|
children,
|
|
33
|
+
icon,
|
|
32
34
|
}) => {
|
|
33
35
|
return (
|
|
34
36
|
<TouchableOpacity
|
|
35
37
|
onPress={onPress}
|
|
36
38
|
testID={testId}
|
|
37
|
-
style={styles.buttonWrapper}
|
|
39
|
+
style={!icon ? styles.buttonWrapper : styles.buttonWrapperAvatar}
|
|
38
40
|
>
|
|
39
41
|
<View style={styles.buttonInfo}>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
{!icon ? (
|
|
43
|
+
<Text type="H4" semibold>
|
|
44
|
+
{title}
|
|
45
|
+
</Text>
|
|
46
|
+
) : (
|
|
47
|
+
(icon && <Image source={{ uri: icon }} style={styles.avatar} />) || (
|
|
48
|
+
<View style={styles.avatar}>
|
|
49
|
+
<Icon name={'user'} size={27} />
|
|
50
|
+
</View>
|
|
51
|
+
)
|
|
52
|
+
)}
|
|
43
53
|
<View style={styles.buttonValue}>
|
|
44
54
|
<Text
|
|
45
55
|
type="Body"
|
|
@@ -66,15 +76,29 @@ const ManageUnit = ({ route }) => {
|
|
|
66
76
|
name: unit.name,
|
|
67
77
|
address: unit.address,
|
|
68
78
|
background: unit.background,
|
|
79
|
+
icon: unit.icon,
|
|
69
80
|
});
|
|
70
81
|
|
|
71
82
|
const [unitName, setUnitName] = useState(unit.name);
|
|
72
|
-
const [
|
|
83
|
+
const [imageUrlBackground, setImageUrlBackground] = useState('');
|
|
84
|
+
const [imageUrlIcon, setImageUrlIcon] = useState('');
|
|
85
|
+
const [checkSelectImage, setCheckSelectImage] = useState('');
|
|
73
86
|
const [showImagePicker, setShowImagePicker] = useState(false);
|
|
74
87
|
|
|
88
|
+
const onUpdateImage = useCallback(
|
|
89
|
+
async (data) => {
|
|
90
|
+
if (checkSelectImage === 'background') {
|
|
91
|
+
setImageUrlBackground(data);
|
|
92
|
+
} else {
|
|
93
|
+
setImageUrlIcon(data);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
[checkSelectImage]
|
|
97
|
+
);
|
|
98
|
+
|
|
75
99
|
const updateUnit = useCallback(
|
|
76
|
-
async (bodyData, headers) => {
|
|
77
|
-
const formData = createFormData(bodyData, [
|
|
100
|
+
async (bodyData, headers, dataInput) => {
|
|
101
|
+
const formData = createFormData(bodyData, [dataInput]);
|
|
78
102
|
|
|
79
103
|
const { success, data } = await axiosPatch(
|
|
80
104
|
API.UNIT.MANAGE_UNIT(unit.id),
|
|
@@ -110,20 +134,37 @@ const ManageUnit = ({ route }) => {
|
|
|
110
134
|
setHideEdit(true);
|
|
111
135
|
}, [unitName, setHideEdit, updateUnit]);
|
|
112
136
|
|
|
113
|
-
const handleChoosePhoto = useCallback(
|
|
114
|
-
|
|
115
|
-
|
|
137
|
+
const handleChoosePhoto = useCallback(
|
|
138
|
+
(text) => {
|
|
139
|
+
setCheckSelectImage(text);
|
|
140
|
+
setShowImagePicker(true);
|
|
141
|
+
},
|
|
142
|
+
[setShowImagePicker]
|
|
143
|
+
);
|
|
116
144
|
|
|
117
145
|
useEffect(() => {
|
|
118
|
-
if (
|
|
146
|
+
if (imageUrlBackground) {
|
|
119
147
|
updateUnit(
|
|
120
|
-
{ background:
|
|
148
|
+
{ background: imageUrlBackground },
|
|
121
149
|
{
|
|
122
150
|
headers: { 'Content-Type': 'multipart/form-data' },
|
|
123
|
-
}
|
|
151
|
+
},
|
|
152
|
+
'background'
|
|
124
153
|
);
|
|
125
154
|
}
|
|
126
|
-
}, [
|
|
155
|
+
}, [imageUrlBackground, updateUnit]);
|
|
156
|
+
|
|
157
|
+
useEffect(() => {
|
|
158
|
+
if (imageUrlIcon) {
|
|
159
|
+
updateUnit(
|
|
160
|
+
{ icon: imageUrlIcon },
|
|
161
|
+
{
|
|
162
|
+
headers: { 'Content-Type': 'multipart/form-data' },
|
|
163
|
+
},
|
|
164
|
+
'icon'
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}, [imageUrlIcon, updateUnit]);
|
|
127
168
|
|
|
128
169
|
const [showRemove, setshowRemove, setHideRemove] = useBoolean();
|
|
129
170
|
const goRemove = useCallback(async () => {
|
|
@@ -160,6 +201,12 @@ const ManageUnit = ({ route }) => {
|
|
|
160
201
|
compressImageQuality: 0.8,
|
|
161
202
|
};
|
|
162
203
|
|
|
204
|
+
const SensorNumbers = useMemo(() => {
|
|
205
|
+
const stations = unit?.stations || [];
|
|
206
|
+
return stations.filter((item) => !item.isFavorites && !item.isOneTap)
|
|
207
|
+
.length;
|
|
208
|
+
}, [unit.stations]);
|
|
209
|
+
|
|
163
210
|
return (
|
|
164
211
|
<>
|
|
165
212
|
<WrapHeaderScrollable
|
|
@@ -169,6 +216,12 @@ const ManageUnit = ({ route }) => {
|
|
|
169
216
|
<View style={styles.wraper}>
|
|
170
217
|
{isOwner && (
|
|
171
218
|
<>
|
|
219
|
+
<ButtonWrapper
|
|
220
|
+
onPress={() => handleChoosePhoto('avatar')}
|
|
221
|
+
value={t('icon_unit')}
|
|
222
|
+
icon={unitData.icon}
|
|
223
|
+
testID={TESTID.MANAGE_UNIT_CHANGE_PHOTO}
|
|
224
|
+
/>
|
|
172
225
|
<ButtonWrapper
|
|
173
226
|
onPress={setshowEdit}
|
|
174
227
|
testID={TESTID.MANAGE_UNIT_CHANGE_NAME}
|
|
@@ -187,10 +240,11 @@ const ManageUnit = ({ route }) => {
|
|
|
187
240
|
<ButtonWrapper
|
|
188
241
|
onPress={goToManageSubUnit}
|
|
189
242
|
title={t('manage_sub_units')}
|
|
190
|
-
value={`${
|
|
243
|
+
value={`${SensorNumbers} sub-units`}
|
|
244
|
+
testID={TESTID.MANAGE_UNIT_GO_TO_SUBUNIT}
|
|
191
245
|
/>
|
|
192
246
|
<ButtonWrapper
|
|
193
|
-
onPress={handleChoosePhoto}
|
|
247
|
+
onPress={() => handleChoosePhoto('background')}
|
|
194
248
|
title={t('unit_wallpaper')}
|
|
195
249
|
value={t('tap_to_change')}
|
|
196
250
|
valueColor={Colors.Orange}
|
|
@@ -213,7 +267,7 @@ const ManageUnit = ({ route }) => {
|
|
|
213
267
|
<ImagePicker
|
|
214
268
|
showImagePicker={showImagePicker}
|
|
215
269
|
setShowImagePicker={setShowImagePicker}
|
|
216
|
-
setImageUrl={
|
|
270
|
+
setImageUrl={onUpdateImage}
|
|
217
271
|
optionsCapture={options}
|
|
218
272
|
testID={TESTID.MANAGE_UNIT_IMAGE_PICKER}
|
|
219
273
|
/>
|
|
@@ -221,20 +275,22 @@ const ManageUnit = ({ route }) => {
|
|
|
221
275
|
)}
|
|
222
276
|
</View>
|
|
223
277
|
</WrapHeaderScrollable>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
<Text
|
|
230
|
-
type={'H4'}
|
|
231
|
-
semibold
|
|
232
|
-
color={Colors.Red}
|
|
233
|
-
style={styles.removeBorderBottom}
|
|
278
|
+
{!showEdit && (
|
|
279
|
+
<TouchableOpacity
|
|
280
|
+
style={styles.removeButton}
|
|
281
|
+
onPress={setshowRemove}
|
|
282
|
+
testID={TESTID.MANAGE_UNIT_SHOW_REMOVE}
|
|
234
283
|
>
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
284
|
+
<Text
|
|
285
|
+
type={'H4'}
|
|
286
|
+
semibold
|
|
287
|
+
color={Colors.Red}
|
|
288
|
+
style={styles.removeBorderBottom}
|
|
289
|
+
>
|
|
290
|
+
{t('remove_unit')}
|
|
291
|
+
</Text>
|
|
292
|
+
</TouchableOpacity>
|
|
293
|
+
)}
|
|
238
294
|
<ModalCustom
|
|
239
295
|
isVisible={showEdit}
|
|
240
296
|
onBackButtonPress={setHideEdit}
|
|
@@ -250,7 +306,7 @@ const ManageUnit = ({ route }) => {
|
|
|
250
306
|
</Text>
|
|
251
307
|
</View>
|
|
252
308
|
<_TextInput
|
|
253
|
-
defaultValue={
|
|
309
|
+
defaultValue={unitData?.name}
|
|
254
310
|
onChange={(value) => setUnitName(value)}
|
|
255
311
|
textInputStyle={styles.textInputStyle}
|
|
256
312
|
wrapStyle={styles.textInputWrapStyle}
|
|
@@ -16,6 +16,12 @@ export default StyleSheet.create({
|
|
|
16
16
|
borderBottomWidth: 0.5,
|
|
17
17
|
borderBottomColor: Colors.Gray6,
|
|
18
18
|
},
|
|
19
|
+
buttonWrapperAvatar: {
|
|
20
|
+
paddingTop: 14,
|
|
21
|
+
paddingBottom: 24,
|
|
22
|
+
borderBottomWidth: 0.5,
|
|
23
|
+
borderBottomColor: Colors.Gray7,
|
|
24
|
+
},
|
|
19
25
|
buttonInfo: {
|
|
20
26
|
flex: 1,
|
|
21
27
|
flexDirection: 'row',
|
|
@@ -29,6 +35,7 @@ export default StyleSheet.create({
|
|
|
29
35
|
},
|
|
30
36
|
value: {
|
|
31
37
|
marginRight: 20,
|
|
38
|
+
fontSize: 14,
|
|
32
39
|
},
|
|
33
40
|
location: {
|
|
34
41
|
marginTop: 16,
|
|
@@ -104,4 +111,17 @@ export default StyleSheet.create({
|
|
|
104
111
|
textInputWrapStyle: {
|
|
105
112
|
marginTop: 0,
|
|
106
113
|
},
|
|
114
|
+
avatar: {
|
|
115
|
+
height: 50,
|
|
116
|
+
width: 50,
|
|
117
|
+
borderRadius: 25,
|
|
118
|
+
borderWidth: 0.5,
|
|
119
|
+
borderColor: Colors.Gray5,
|
|
120
|
+
justifyContent: 'center',
|
|
121
|
+
alignItems: 'center',
|
|
122
|
+
},
|
|
123
|
+
wrapAvatar: {
|
|
124
|
+
flexDirection: 'row',
|
|
125
|
+
justifyContent: 'space-between',
|
|
126
|
+
},
|
|
107
127
|
});
|
|
@@ -18,6 +18,7 @@ import { usePopover, useBoolean } from '../../hooks/Common';
|
|
|
18
18
|
import { MenuActionMore, AlertAction } from '../../commons';
|
|
19
19
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
20
20
|
import { useStateAlertRemove } from '../Unit/hook/useStateAlertRemove';
|
|
21
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
21
22
|
|
|
22
23
|
const ListSmartAccount = ({ route }) => {
|
|
23
24
|
const { unitId } = route?.params || {};
|
|
@@ -76,8 +77,11 @@ const ListSmartAccount = ({ route }) => {
|
|
|
76
77
|
const { success } = await axiosDelete(
|
|
77
78
|
API.SMART_ACCOUNT.REMOVE_SMART_ACCOUNT(id)
|
|
78
79
|
);
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
if (success) {
|
|
81
|
+
ToastBottomHelper.success(t('removed_successfully'));
|
|
82
|
+
getAllSmartAccounts();
|
|
83
|
+
}
|
|
84
|
+
}, [getAllSmartAccounts, hideAlertAction, t]);
|
|
81
85
|
|
|
82
86
|
const listMenuItem = useMemo(() => {
|
|
83
87
|
return [{ action: 'remove', text: t('remove_account') }];
|
|
@@ -26,6 +26,16 @@ jest.mock('../../../iot/RemoteControl/GoogleHome', () => ({
|
|
|
26
26
|
|
|
27
27
|
jest.mock('axios');
|
|
28
28
|
|
|
29
|
+
jest.mock('@react-native-community/netinfo', () => {
|
|
30
|
+
return {
|
|
31
|
+
useNetInfo: () => {
|
|
32
|
+
return {
|
|
33
|
+
isConnected: true,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
|
|
29
39
|
const wrapComponent = (route, unitData, account) => (
|
|
30
40
|
<SCProvider initState={mockSCStore({})}>
|
|
31
41
|
<UnitDetail
|
|
@@ -62,6 +62,16 @@ jest.mock('home-assistant-js-websocket', () => {
|
|
|
62
62
|
};
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
+
jest.mock('@react-native-community/netinfo', () => {
|
|
66
|
+
return {
|
|
67
|
+
useNetInfo: () => {
|
|
68
|
+
return {
|
|
69
|
+
isConnected: true,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
65
75
|
jest.mock('axios');
|
|
66
76
|
|
|
67
77
|
describe('Test UnitDetail', () => {
|
|
@@ -452,7 +462,50 @@ describe('Test UnitDetail', () => {
|
|
|
452
462
|
expect(fullView).toHaveLength(1);
|
|
453
463
|
expect(fullView[0].props.isVisible).toEqual(false);
|
|
454
464
|
});
|
|
465
|
+
test('onPress subunit camera devices', async () => {
|
|
466
|
+
const unitData = {
|
|
467
|
+
stations: [
|
|
468
|
+
{
|
|
469
|
+
camera_devices: [
|
|
470
|
+
{
|
|
471
|
+
configuration: {
|
|
472
|
+
id: 4,
|
|
473
|
+
name: 'Camera cửa nhà xe',
|
|
474
|
+
uri: 'rtsp://admin:hd543211@/ISAPI/Streaming/Channels/101/',
|
|
475
|
+
preview_uri:
|
|
476
|
+
'rtsp://admin:hd543211@/ISAPI/Streaming/Channels/101/',
|
|
477
|
+
playback: 'rtsp://admin:hd543211@/Streaming/tracks/101/',
|
|
478
|
+
},
|
|
479
|
+
id: 41,
|
|
480
|
+
order: 1,
|
|
481
|
+
template: 'camera',
|
|
482
|
+
type: 'camera',
|
|
483
|
+
},
|
|
484
|
+
],
|
|
485
|
+
},
|
|
486
|
+
],
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
await act(async () => {
|
|
490
|
+
tree = await renderer.create(
|
|
491
|
+
wrapComponent({ params: { ...route.params, unitData } }, account)
|
|
492
|
+
);
|
|
493
|
+
});
|
|
494
|
+
const instance = tree.root;
|
|
495
|
+
const CameraDeviceViews = instance.findAllByType(CameraDevice);
|
|
496
|
+
expect(CameraDeviceViews).toHaveLength(1);
|
|
497
|
+
const goDetailButton = tree.root.findAll(
|
|
498
|
+
(el) =>
|
|
499
|
+
el.props.testID === TESTID.SUB_UNIT_GO_DETAIL &&
|
|
500
|
+
el.type === TouchableOpacity
|
|
501
|
+
);
|
|
455
502
|
|
|
503
|
+
expect(goDetailButton).toHaveLength(2);
|
|
504
|
+
await act(async () => {
|
|
505
|
+
await goDetailButton[0].props.onPress();
|
|
506
|
+
});
|
|
507
|
+
expect(mockedNavigate).toHaveBeenCalled();
|
|
508
|
+
});
|
|
456
509
|
test('render subunit favorites', async () => {
|
|
457
510
|
const unitData = {
|
|
458
511
|
stations: [
|