@eohjsc/react-native-smart-city 0.7.7 → 0.7.9
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/assets/images/AddNewDevice/add-scan-device-icon.svg +13 -0
- package/assets/images/Email.svg +9 -0
- package/assets/images/lan.svg +3 -0
- package/assets/images/wifi-open.svg +3 -0
- package/package.json +4 -3
- package/src/commons/ActionGroup/StatesGridActionTemplate.js +7 -3
- package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +7 -3
- package/src/commons/AlertAction/index.js +1 -0
- package/src/commons/Auth/AccountItem.js +17 -3
- package/src/commons/Auth/AccountList.js +3 -7
- package/src/commons/ConnectWifi/__test__/ConnectWifi.test.js +373 -0
- package/src/commons/ConnectWifi/index.js +201 -0
- package/src/commons/ConnectWifi/styles.js +69 -0
- package/src/commons/Device/LabelValue/__test__/LabelValue.test.js +74 -0
- package/src/commons/Device/LabelValue/index.js +49 -0
- package/src/commons/Device/LabelValue/styles.js +33 -0
- package/src/commons/Form/TextInputPassword.js +1 -1
- package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +6 -2
- package/src/configs/API.js +12 -0
- package/src/configs/AccessibilityLabel.js +7 -0
- package/src/configs/Constants.js +1 -0
- package/src/hooks/Common/index.js +2 -2
- package/src/hooks/Common/useBlockBack.js +36 -0
- package/src/hooks/useMqtt.js +10 -5
- package/src/navigations/AddGatewayStack.js +2 -0
- package/src/navigations/AllGatewayStack.js +4 -0
- package/src/navigations/Main.js +2 -2
- package/src/navigations/UnitStack.js +32 -0
- package/src/screens/AddNewGateway/ConnectingWifiDevice.js +7 -6
- package/src/screens/AddNewGateway/ScanDeviceLocal.js +267 -0
- package/src/screens/AddNewGateway/ScanDeviceLocalStyles.js +58 -0
- package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +10 -2
- package/src/screens/AddNewGateway/SelectDeviceType.js +19 -2
- package/src/screens/AddNewGateway/__test__/ScanDeviceLocal.test.js +475 -0
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +2 -2
- package/src/screens/AddNewGateway/configs/API.js +8 -0
- package/src/screens/AddNewGateway/hooks/useConnectDevice.js +59 -0
- package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +58 -1
- package/src/screens/AllGateway/GatewayInfo/index.js +8 -6
- package/src/screens/AllGateway/GatewayWifi/__test__/index.test.js +319 -0
- package/src/screens/AllGateway/GatewayWifi/index.js +107 -0
- package/src/screens/AllGateway/Successfully/__test__/index.test.js +77 -0
- package/src/screens/AllGateway/Successfully/index.js +66 -0
- package/src/screens/AllGateway/Successfully/styles.js +35 -0
- package/src/screens/AllGateway/components/Information/index.js +17 -1
- package/src/screens/AllGateway/components/RowItem/index.js +12 -1
- package/src/screens/AllGateway/hooks/__test__/index.test.js +18 -0
- package/src/screens/AllGateway/hooks/useGateway.js +13 -0
- package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +3 -3
- package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +79 -0
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +166 -0
- package/src/screens/Automate/AddNewAction/Styles/SetupScriptEmailStyles.js +37 -0
- package/src/screens/Automate/AddNewAction/Styles/SetupScriptReceiverEmailStyles.js +79 -0
- package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +1 -1
- package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -5
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptEmail.test.js +76 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +105 -0
- package/src/screens/Automate/EditActionsList/Styles/UpdateReceiverEmailScriptStyles.js +78 -0
- package/src/screens/Automate/EditActionsList/UpdateEmailScript.js +80 -0
- package/src/screens/Automate/EditActionsList/UpdateReceiverEmailScript.js +179 -0
- package/src/screens/Automate/EditActionsList/__tests__/UpdateEmailScript.test.js +81 -0
- package/src/screens/Automate/EditActionsList/__tests__/UpdateReceiverEmailScript.test.js +83 -0
- package/src/screens/Automate/EditActionsList/__tests__/index.test.js +38 -5
- package/src/screens/Automate/EditActionsList/index.js +59 -2
- package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +20 -0
- package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +5 -3
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +127 -21
- package/src/screens/Automate/ScriptDetail/index.js +57 -14
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +22 -0
- package/src/screens/Device/components/SensorDisplayItem.js +10 -0
- package/src/screens/SharedUnit/index.js +2 -2
- package/src/screens/Sharing/SelectUser.js +47 -47
- package/src/screens/Sharing/__test__/SelectUser.test.js +57 -103
- package/src/screens/SubUnit/ManageSubUnit.js +94 -90
- package/src/screens/SubUnit/ManageSubUnitStyles.js +4 -6
- package/src/screens/SubUnit/RearrageSubUnit.js +90 -0
- package/src/screens/SubUnit/RearrrageSubUnitStyle.js +65 -0
- package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +35 -19
- package/src/screens/SubUnit/__test__/RearrangeSubUnit.test.js +129 -0
- package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +6 -7
- package/src/screens/SubUnit/hooks/useManageSubUnit.js +8 -16
- package/src/screens/Unit/Detail.js +2 -6
- package/src/screens/Unit/ManageUnit.js +1 -1
- package/src/utils/Functions/__test__/ShortEmail.test.js +5 -0
- package/src/utils/I18n/translations/en.js +46 -8
- package/src/utils/I18n/translations/vi.js +37 -4
- package/src/utils/Route/index.js +7 -0
- package/src/commons/Auth/__test__/AccountItem.test.js +0 -31
- package/src/hooks/Common/useBlockBackAndroid.js +0 -21
- package/src/screens/SubUnit/DetailStyles.js +0 -46
|
@@ -8,6 +8,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
|
8
8
|
import Close from '../../../../assets/images/Close.svg';
|
|
9
9
|
import Delay from '../../../../assets/images/Delay.svg';
|
|
10
10
|
import Notify from '../../../../assets/images/Notify.svg';
|
|
11
|
+
import Email from '../../../../assets/images/Email.svg';
|
|
11
12
|
import Rearrange from '../../../../assets/images/Rearrange.svg';
|
|
12
13
|
import { FullLoading } from '../../../commons';
|
|
13
14
|
import FImage from '../../../commons/FImage';
|
|
@@ -23,6 +24,7 @@ import { ToastBottomHelper } from '../../../utils/Utils';
|
|
|
23
24
|
import styles from './Styles/indexStyles';
|
|
24
25
|
import UpdateDelayScript from './UpdateDelayScript';
|
|
25
26
|
import UpdateNotifyScript from './UpdateNotifyScript';
|
|
27
|
+
import UpdateEmailScript from './UpdateEmailScript';
|
|
26
28
|
|
|
27
29
|
const EditActionsList = () => {
|
|
28
30
|
const t = useTranslations();
|
|
@@ -138,7 +140,7 @@ const EditActionsList = () => {
|
|
|
138
140
|
({ item, getIndex, drag, isActive }) => {
|
|
139
141
|
const index = getIndex();
|
|
140
142
|
const paddedIndex = (index + 1).toString().padStart(2, '0');
|
|
141
|
-
const { action_script, notify_script, delay_script } = item;
|
|
143
|
+
const { action_script, notify_script, delay_script, email_script } = item;
|
|
142
144
|
if (action_script) {
|
|
143
145
|
const {
|
|
144
146
|
sensor_icon_kit,
|
|
@@ -236,6 +238,37 @@ const EditActionsList = () => {
|
|
|
236
238
|
/>
|
|
237
239
|
);
|
|
238
240
|
}
|
|
241
|
+
if (email_script) {
|
|
242
|
+
const { title, message, str_emails } = email_script;
|
|
243
|
+
|
|
244
|
+
return (
|
|
245
|
+
<CommonItem
|
|
246
|
+
paddedIndex={paddedIndex}
|
|
247
|
+
icon={
|
|
248
|
+
<View style={styles.iconItem}>
|
|
249
|
+
<Email />
|
|
250
|
+
</View>
|
|
251
|
+
}
|
|
252
|
+
content={
|
|
253
|
+
<>
|
|
254
|
+
<Text numberOfLines={1} type="H4" color={Colors.Gray9} semibold>
|
|
255
|
+
{title}
|
|
256
|
+
</Text>
|
|
257
|
+
<Text numberOfLines={1} type="H4" color={Colors.Gray9}>
|
|
258
|
+
{message}
|
|
259
|
+
</Text>
|
|
260
|
+
<Text numberOfLines={1} type="H4" color={Colors.Gray9}>
|
|
261
|
+
{str_emails}
|
|
262
|
+
</Text>
|
|
263
|
+
</>
|
|
264
|
+
}
|
|
265
|
+
onPress={() => onPressRemove(item)}
|
|
266
|
+
onPressUpdate={() => onShowPopupUpdate(item, index)}
|
|
267
|
+
isActive={isActive}
|
|
268
|
+
drag={drag}
|
|
269
|
+
/>
|
|
270
|
+
);
|
|
271
|
+
}
|
|
239
272
|
},
|
|
240
273
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
241
274
|
[needRefresh]
|
|
@@ -246,6 +279,7 @@ const EditActionsList = () => {
|
|
|
246
279
|
action_script,
|
|
247
280
|
notify_script,
|
|
248
281
|
delay_script,
|
|
282
|
+
email_script,
|
|
249
283
|
id: scriptItemId,
|
|
250
284
|
} = scriptItem;
|
|
251
285
|
|
|
@@ -294,6 +328,18 @@ const EditActionsList = () => {
|
|
|
294
328
|
/>
|
|
295
329
|
);
|
|
296
330
|
}
|
|
331
|
+
if (email_script) {
|
|
332
|
+
return (
|
|
333
|
+
<UpdateEmailScript
|
|
334
|
+
unitId={unitId}
|
|
335
|
+
automateId={id}
|
|
336
|
+
scriptItemId={scriptItemId}
|
|
337
|
+
email_script={email_script}
|
|
338
|
+
t={t}
|
|
339
|
+
onClosePopup={onClosePopup}
|
|
340
|
+
/>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
297
343
|
}, [actionsList, id, navigate, scriptItem, t, unitId, updateIndex]);
|
|
298
344
|
|
|
299
345
|
const onDragEnd = useCallback(
|
|
@@ -309,7 +355,8 @@ const EditActionsList = () => {
|
|
|
309
355
|
);
|
|
310
356
|
|
|
311
357
|
const renderMessageRemove = useMemo(() => {
|
|
312
|
-
const { action_script, notify_script, delay_script } =
|
|
358
|
+
const { action_script, notify_script, delay_script, email_script } =
|
|
359
|
+
itemRemove;
|
|
313
360
|
if (action_script) {
|
|
314
361
|
return (
|
|
315
362
|
<ParsedText
|
|
@@ -353,6 +400,16 @@ const EditActionsList = () => {
|
|
|
353
400
|
</ParsedText>
|
|
354
401
|
);
|
|
355
402
|
}
|
|
403
|
+
if (email_script) {
|
|
404
|
+
return (
|
|
405
|
+
<ParsedText
|
|
406
|
+
style={styles.messageDelete}
|
|
407
|
+
childrenProps={{ allowFontScaling: false }}
|
|
408
|
+
>
|
|
409
|
+
{t('message_delete_notify', { title: email_script.title })}
|
|
410
|
+
</ParsedText>
|
|
411
|
+
);
|
|
412
|
+
}
|
|
356
413
|
}, [itemRemove, t]);
|
|
357
414
|
|
|
358
415
|
return (
|
|
@@ -10,6 +10,7 @@ import { useBackendPermission } from '../../../../utils/Permission/backend';
|
|
|
10
10
|
import Event from '../../../../../assets/images/Event.svg';
|
|
11
11
|
import Notify from '../../../../../assets/images/Notify.svg';
|
|
12
12
|
import Delay from '../../../../../assets/images/Delay.svg';
|
|
13
|
+
import Email from '../../../../../assets/images/Email.svg';
|
|
13
14
|
import { TouchableOpacity } from 'react-native';
|
|
14
15
|
import { IconOutline } from '@ant-design/icons-react-native';
|
|
15
16
|
import { Text } from '../../../../commons';
|
|
@@ -79,6 +80,25 @@ const AddActionScript = memo(
|
|
|
79
80
|
});
|
|
80
81
|
},
|
|
81
82
|
},
|
|
83
|
+
{
|
|
84
|
+
id: 'send_email',
|
|
85
|
+
text: t('send_email'),
|
|
86
|
+
image: <Email />,
|
|
87
|
+
onClick: () => {
|
|
88
|
+
setIsVisible(false);
|
|
89
|
+
if (unit) {
|
|
90
|
+
navigate(Routes.SetupScriptEmail, {
|
|
91
|
+
automate,
|
|
92
|
+
unitId: unit,
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
navigate(Routes.SelectUnit, {
|
|
96
|
+
automate,
|
|
97
|
+
routeName: Routes.SetupScriptEmail,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
},
|
|
82
102
|
];
|
|
83
103
|
}, [
|
|
84
104
|
automate,
|
|
@@ -101,13 +101,15 @@ export default StyleSheet.create({
|
|
|
101
101
|
},
|
|
102
102
|
rightItem: {
|
|
103
103
|
flex: 1,
|
|
104
|
-
marginLeft: 4,
|
|
105
|
-
borderRadius: 4,
|
|
106
104
|
borderColor: Colors.Gray4,
|
|
107
105
|
borderWidth: 1,
|
|
108
|
-
|
|
106
|
+
borderRadius: 4,
|
|
109
107
|
paddingVertical: 15,
|
|
110
108
|
paddingHorizontal: 16,
|
|
109
|
+
marginLeft: 4,
|
|
110
|
+
},
|
|
111
|
+
insideItemRight: {
|
|
112
|
+
flexDirection: 'row',
|
|
111
113
|
},
|
|
112
114
|
rightItemAdd: {
|
|
113
115
|
flex: 1,
|
|
@@ -38,10 +38,13 @@ describe('Test ScriptDetail', () => {
|
|
|
38
38
|
let tree;
|
|
39
39
|
|
|
40
40
|
const mockGoBack = useNavigation().goBack;
|
|
41
|
+
const mockAddListener = useNavigation().addListener;
|
|
41
42
|
const mockedNavigate = useNavigation().navigate;
|
|
42
43
|
beforeEach(() => {
|
|
43
44
|
mockGoBack.mockClear();
|
|
45
|
+
mockAddListener.mockClear();
|
|
44
46
|
mockedNavigate.mockClear();
|
|
47
|
+
global.mockedNavigate.mockClear();
|
|
45
48
|
mock.reset();
|
|
46
49
|
route = {
|
|
47
50
|
params: {
|
|
@@ -91,6 +94,16 @@ describe('Test ScriptDetail', () => {
|
|
|
91
94
|
notify_script: null,
|
|
92
95
|
delay_script: { delay: 10 },
|
|
93
96
|
},
|
|
97
|
+
{
|
|
98
|
+
action_script: null,
|
|
99
|
+
notify_script: null,
|
|
100
|
+
email_script: {
|
|
101
|
+
title: 'title',
|
|
102
|
+
message: 'message',
|
|
103
|
+
unit_id: 60,
|
|
104
|
+
str_emails: 'email0@eoh.io',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
94
107
|
],
|
|
95
108
|
};
|
|
96
109
|
});
|
|
@@ -165,12 +178,12 @@ describe('Test ScriptDetail', () => {
|
|
|
165
178
|
await act(async () => {
|
|
166
179
|
await menu.props.onPress();
|
|
167
180
|
});
|
|
168
|
-
expect(spyToastError).
|
|
181
|
+
expect(spyToastError).toHaveBeenCalledWith(
|
|
169
182
|
getTranslate('en', 'only_owner_has_permission_to_edit_this_script')
|
|
170
183
|
);
|
|
171
184
|
});
|
|
172
185
|
|
|
173
|
-
it('test cannot
|
|
186
|
+
it('test cannot edit condition because not owner', async () => {
|
|
174
187
|
route.params.preAutomate.can_edit = false;
|
|
175
188
|
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
176
189
|
|
|
@@ -194,14 +207,46 @@ describe('Test ScriptDetail', () => {
|
|
|
194
207
|
|
|
195
208
|
await act(async () => {
|
|
196
209
|
menuActionMore.props.onItemClick({ doAction: jest.fn() });
|
|
197
|
-
menuActionMore.props.listMenuItem[
|
|
210
|
+
menuActionMore.props.listMenuItem[0].doAction();
|
|
198
211
|
});
|
|
199
212
|
|
|
200
|
-
expect(spyToastError).
|
|
213
|
+
expect(spyToastError).toHaveBeenCalledWith(
|
|
201
214
|
getTranslate('en', 'only_owner_has_permission_to_edit_this_script')
|
|
202
215
|
);
|
|
203
216
|
});
|
|
204
217
|
|
|
218
|
+
it('test cannot edit condition because script disabled', async () => {
|
|
219
|
+
route.params.preAutomate.script.enable = false;
|
|
220
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
221
|
+
|
|
222
|
+
await act(async () => {
|
|
223
|
+
tree = await create(wrapComponent(route));
|
|
224
|
+
});
|
|
225
|
+
const instance = tree.root;
|
|
226
|
+
const button = instance.find(
|
|
227
|
+
(el) =>
|
|
228
|
+
el.props.accessibilityLabel === AccessibilityLabel.ICON_MENU_POPUP &&
|
|
229
|
+
el.type === TouchableOpacity
|
|
230
|
+
);
|
|
231
|
+
await act(async () => {
|
|
232
|
+
await button.props.onPress();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const menuActionMore = instance.find(
|
|
236
|
+
(el) =>
|
|
237
|
+
el.props.accessibilityLabel === AccessibilityLabel.MENU_POPPER_MORE_2
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
await act(async () => {
|
|
241
|
+
menuActionMore.props.onItemClick({ doAction: jest.fn() });
|
|
242
|
+
menuActionMore.props.listMenuItem[0].doAction();
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
expect(spyToastError).toBeCalledWith(
|
|
246
|
+
getTranslate('en', 'this_script_has_been_disabled')
|
|
247
|
+
);
|
|
248
|
+
});
|
|
249
|
+
|
|
205
250
|
it('test delete script', async () => {
|
|
206
251
|
await act(async () => {
|
|
207
252
|
tree = await create(wrapComponent(route));
|
|
@@ -322,7 +367,7 @@ describe('Test ScriptDetail', () => {
|
|
|
322
367
|
AccessibilityLabel.AUTOMATE_LIST_SCRIPT_ACTION &&
|
|
323
368
|
el.type === TouchableOpacity
|
|
324
369
|
);
|
|
325
|
-
expect(listScriptActions).toHaveLength(
|
|
370
|
+
expect(listScriptActions).toHaveLength(4);
|
|
326
371
|
await act(async () => {
|
|
327
372
|
await listScriptActions[0].props.onPress();
|
|
328
373
|
});
|
|
@@ -360,6 +405,18 @@ describe('Test ScriptDetail', () => {
|
|
|
360
405
|
automate: route.params.preAutomate,
|
|
361
406
|
}
|
|
362
407
|
);
|
|
408
|
+
mockedNavigate.mockClear();
|
|
409
|
+
await act(async () => {
|
|
410
|
+
await listScriptActions[3].props.onPress();
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
expect(global.mockedNavigate).toHaveBeenCalledWith(
|
|
414
|
+
Routes.SetupScriptEmail,
|
|
415
|
+
{
|
|
416
|
+
automate: route.params.preAutomate,
|
|
417
|
+
unitId: route.params.preAutomate.unit,
|
|
418
|
+
}
|
|
419
|
+
);
|
|
363
420
|
});
|
|
364
421
|
|
|
365
422
|
it('test press disable script', async () => {
|
|
@@ -418,8 +475,8 @@ describe('Test ScriptDetail', () => {
|
|
|
418
475
|
await act(async () => {
|
|
419
476
|
await button.props.onPress();
|
|
420
477
|
});
|
|
421
|
-
expect(global.mockedNavigate).not.
|
|
422
|
-
expect(spyToastError).
|
|
478
|
+
expect(global.mockedNavigate).not.toHaveBeenCalled();
|
|
479
|
+
expect(spyToastError).toHaveBeenCalledWith(
|
|
423
480
|
getTranslate('en', 'reach_max_actions_per_automation', { length: 0 }),
|
|
424
481
|
'',
|
|
425
482
|
7000
|
|
@@ -500,21 +557,24 @@ describe('Test ScriptDetail', () => {
|
|
|
500
557
|
_testGoToActivityLog(3, AUTOMATE_TYPE.VALUE_CHANGE, 'automate', undefined);
|
|
501
558
|
|
|
502
559
|
it('Test render textCondition value change >', async () => {
|
|
560
|
+
const automate = {
|
|
561
|
+
can_edit: true,
|
|
562
|
+
type: AUTOMATE_TYPE.VALUE_CHANGE,
|
|
563
|
+
value_change: {
|
|
564
|
+
config_name: 'Light Value',
|
|
565
|
+
value: 3,
|
|
566
|
+
condition: '>',
|
|
567
|
+
end_device_id: 1,
|
|
568
|
+
unit_id: 1,
|
|
569
|
+
},
|
|
570
|
+
script: {
|
|
571
|
+
name: 'name',
|
|
572
|
+
enable: true,
|
|
573
|
+
},
|
|
574
|
+
};
|
|
503
575
|
route.params = {
|
|
504
576
|
...route.params,
|
|
505
|
-
preAutomate:
|
|
506
|
-
can_edit: true,
|
|
507
|
-
type: AUTOMATE_TYPE.VALUE_CHANGE,
|
|
508
|
-
value_change: {
|
|
509
|
-
config_name: 'Light Value',
|
|
510
|
-
value: 3,
|
|
511
|
-
condition: '>',
|
|
512
|
-
},
|
|
513
|
-
script: {
|
|
514
|
-
name: 'name',
|
|
515
|
-
enable: true,
|
|
516
|
-
},
|
|
517
|
-
},
|
|
577
|
+
preAutomate: automate,
|
|
518
578
|
};
|
|
519
579
|
await act(async () => {
|
|
520
580
|
tree = await create(wrapComponent(route));
|
|
@@ -534,9 +594,29 @@ describe('Test ScriptDetail', () => {
|
|
|
534
594
|
);
|
|
535
595
|
await act(async () => {
|
|
536
596
|
menuActionMore.props.onItemClick({ doAction: jest.fn() });
|
|
597
|
+
menuActionMore.props.listMenuItem[2].doAction();
|
|
598
|
+
});
|
|
599
|
+
expect(global.mockedNavigate).toBeCalledWith(Routes.AddUnknownTypeSmart, {
|
|
600
|
+
automate,
|
|
601
|
+
closeScreen: undefined,
|
|
602
|
+
});
|
|
603
|
+
global.mockedNavigate.mockClear();
|
|
604
|
+
expect(menuActionMore.props.listMenuItem[0].text).toEqual('Device display');
|
|
605
|
+
await act(async () => {
|
|
537
606
|
menuActionMore.props.listMenuItem[0].doAction();
|
|
538
607
|
});
|
|
539
|
-
expect(global.mockedNavigate).
|
|
608
|
+
expect(global.mockedNavigate).toBeCalledWith(Routes.DeviceDetail, {
|
|
609
|
+
sensorId: 1,
|
|
610
|
+
unitId: 1,
|
|
611
|
+
});
|
|
612
|
+
global.mockedNavigate.mockClear();
|
|
613
|
+
expect(menuActionMore.props.listMenuItem[1].text).toEqual('Unit');
|
|
614
|
+
await act(async () => {
|
|
615
|
+
menuActionMore.props.listMenuItem[1].doAction();
|
|
616
|
+
});
|
|
617
|
+
expect(global.mockedNavigate).toBeCalledWith(Routes.UnitDetail, {
|
|
618
|
+
unitId: 1,
|
|
619
|
+
});
|
|
540
620
|
});
|
|
541
621
|
|
|
542
622
|
it('Test render textCondition value change =', async () => {
|
|
@@ -623,4 +703,30 @@ describe('Test ScriptDetail', () => {
|
|
|
623
703
|
'Mon, Tue, Thu, Sat at 19:00'
|
|
624
704
|
);
|
|
625
705
|
});
|
|
706
|
+
|
|
707
|
+
it('test navigate to UnitDetail on event beforeRemove', async () => {
|
|
708
|
+
route.params.closeScreen = Routes.UnitDetail;
|
|
709
|
+
route.params.preAutomate.unit = 2;
|
|
710
|
+
|
|
711
|
+
await act(async () => {
|
|
712
|
+
await create(wrapComponent(route));
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
// beforeRemove test when swipe to back
|
|
716
|
+
const navigation = useNavigation();
|
|
717
|
+
const beforeRemoveEvent = { preventDefault: jest.fn() };
|
|
718
|
+
const beforeRemoveListener = navigation.addListener.mock.calls.find(
|
|
719
|
+
([event]) => event === 'beforeRemove'
|
|
720
|
+
)[1];
|
|
721
|
+
|
|
722
|
+
await act(async () => {
|
|
723
|
+
beforeRemoveListener(beforeRemoveEvent);
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
expect(mockAddListener).toHaveBeenCalled();
|
|
727
|
+
expect(beforeRemoveEvent.preventDefault).toHaveBeenCalled();
|
|
728
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.UnitDetail, {
|
|
729
|
+
unitId: 2,
|
|
730
|
+
});
|
|
731
|
+
});
|
|
626
732
|
});
|
|
@@ -14,6 +14,7 @@ import { useIsFocused, useNavigation } from '@react-navigation/native';
|
|
|
14
14
|
import Add from '../../../../assets/images/Add.svg';
|
|
15
15
|
import Delay from '../../../../assets/images/Delay.svg';
|
|
16
16
|
import Notify from '../../../../assets/images/Notify.svg';
|
|
17
|
+
import Email from '../../../../assets/images/Email.svg';
|
|
17
18
|
import IconComponent from '../../../commons/IconComponent';
|
|
18
19
|
import MenuActionMore from '../../../commons/MenuActionMore';
|
|
19
20
|
import WrapHeaderScrollable from '../../../commons/Sharing/WrapHeaderScrollable';
|
|
@@ -22,7 +23,7 @@ import withPreventDoubleClick from '../../../commons/WithPreventDoubleClick';
|
|
|
22
23
|
import { API, Colors } from '../../../configs';
|
|
23
24
|
import { AccessibilityLabel, AUTOMATE_TYPE } from '../../../configs/Constants';
|
|
24
25
|
import Images from '../../../configs/Images';
|
|
25
|
-
import { usePopover } from '../../../hooks/Common';
|
|
26
|
+
import { useBlockBack, usePopover } from '../../../hooks/Common';
|
|
26
27
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
27
28
|
import { axiosGet, axiosPost } from '../../../utils/Apis/axios';
|
|
28
29
|
import { useBackendPermission } from '../../../utils/Permission/backend';
|
|
@@ -127,7 +128,16 @@ const ScriptDetail = ({ route }) => {
|
|
|
127
128
|
const items = [
|
|
128
129
|
{ text: t('edit_condition'), doAction: () => handleUpdateAutomate() },
|
|
129
130
|
];
|
|
130
|
-
if (
|
|
131
|
+
if (unit_id) {
|
|
132
|
+
items.unshift({
|
|
133
|
+
text: t('text_unit'),
|
|
134
|
+
doAction: () =>
|
|
135
|
+
navigate(Routes.UnitDetail, {
|
|
136
|
+
unitId: unit_id,
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (end_device_id) {
|
|
131
141
|
items.unshift({
|
|
132
142
|
text: t('device_display'),
|
|
133
143
|
doAction: () =>
|
|
@@ -138,7 +148,7 @@ const ScriptDetail = ({ route }) => {
|
|
|
138
148
|
});
|
|
139
149
|
}
|
|
140
150
|
return items;
|
|
141
|
-
}, [t, handleUpdateAutomate,
|
|
151
|
+
}, [t, handleUpdateAutomate, navigate, unit_id, end_device_id]);
|
|
142
152
|
|
|
143
153
|
const handleShowMenuAction = useCallback(() => {
|
|
144
154
|
if (!can_edit) {
|
|
@@ -219,6 +229,8 @@ const ScriptDetail = ({ route }) => {
|
|
|
219
229
|
[automateId]
|
|
220
230
|
);
|
|
221
231
|
|
|
232
|
+
useBlockBack(handleGoBack);
|
|
233
|
+
|
|
222
234
|
useEffect(() => {
|
|
223
235
|
if (isFocused) {
|
|
224
236
|
fetchAutomate();
|
|
@@ -385,7 +397,7 @@ const ScriptDetail = ({ route }) => {
|
|
|
385
397
|
const Item = ({ item, index, enableScript, t }) => {
|
|
386
398
|
const color = enableScript ? Colors.Gray9 : Colors.Gray7;
|
|
387
399
|
const paddedIndex = (index + 1).toString().padStart(2, '0');
|
|
388
|
-
const { action_script, notify_script, delay_script } = item;
|
|
400
|
+
const { action_script, notify_script, delay_script, email_script } = item;
|
|
389
401
|
if (action_script) {
|
|
390
402
|
const {
|
|
391
403
|
sensor_icon_kit,
|
|
@@ -444,16 +456,18 @@ const Item = ({ item, index, enableScript, t }) => {
|
|
|
444
456
|
</Text>
|
|
445
457
|
</View>
|
|
446
458
|
<View style={styles.rightItem}>
|
|
447
|
-
<View style={styles.
|
|
448
|
-
<
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
<
|
|
452
|
-
{
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
{
|
|
456
|
-
|
|
459
|
+
<View style={styles.insideItemRight}>
|
|
460
|
+
<View style={styles.iconEndDevice}>
|
|
461
|
+
<Notify />
|
|
462
|
+
</View>
|
|
463
|
+
<View style={styles.contentItem}>
|
|
464
|
+
<Text numberOfLines={1} type="H4" color={color} semibold>
|
|
465
|
+
{title}
|
|
466
|
+
</Text>
|
|
467
|
+
<Text numberOfLines={1} type="H4" color={color}>
|
|
468
|
+
{message}
|
|
469
|
+
</Text>
|
|
470
|
+
</View>
|
|
457
471
|
</View>
|
|
458
472
|
</View>
|
|
459
473
|
</View>
|
|
@@ -482,6 +496,35 @@ const Item = ({ item, index, enableScript, t }) => {
|
|
|
482
496
|
</View>
|
|
483
497
|
</View>
|
|
484
498
|
);
|
|
499
|
+
} else if (email_script) {
|
|
500
|
+
const { title, message, str_emails } = email_script;
|
|
501
|
+
return (
|
|
502
|
+
<View style={styles.wrapItem}>
|
|
503
|
+
<View style={styles.leftItem}>
|
|
504
|
+
<Text color={color} type="H4" semibold>
|
|
505
|
+
{paddedIndex}
|
|
506
|
+
</Text>
|
|
507
|
+
</View>
|
|
508
|
+
<View style={styles.rightItem}>
|
|
509
|
+
<View style={styles.insideItemRight}>
|
|
510
|
+
<View style={styles.iconEndDevice}>
|
|
511
|
+
<Email />
|
|
512
|
+
</View>
|
|
513
|
+
<View style={styles.contentItem}>
|
|
514
|
+
<Text numberOfLines={1} type="H4" color={color} semibold>
|
|
515
|
+
{title}
|
|
516
|
+
</Text>
|
|
517
|
+
<Text numberOfLines={1} type="H4" color={color}>
|
|
518
|
+
{message}
|
|
519
|
+
</Text>
|
|
520
|
+
</View>
|
|
521
|
+
</View>
|
|
522
|
+
<Text numberOfLines={1} type="H4" color={color}>
|
|
523
|
+
{str_emails}
|
|
524
|
+
</Text>
|
|
525
|
+
</View>
|
|
526
|
+
</View>
|
|
527
|
+
);
|
|
485
528
|
}
|
|
486
529
|
};
|
|
487
530
|
|
|
@@ -17,6 +17,7 @@ import DeviceAlertStatus from '../../../commons/Device/DeviceAlertStatus';
|
|
|
17
17
|
import MockAdapter from 'axios-mock-adapter';
|
|
18
18
|
import api from '../../../utils/Apis/axios';
|
|
19
19
|
import CurrentRainSensor from '../../../commons/Device/RainningSensor/CurrentRainSensor';
|
|
20
|
+
import LabelValue from '../../../commons/Device/LabelValue';
|
|
20
21
|
|
|
21
22
|
jest.mock('../../../iot/states', () => ({
|
|
22
23
|
useConfigGlobalState: () => [{}, null],
|
|
@@ -410,4 +411,25 @@ describe('Test SensorDisplayItem', () => {
|
|
|
410
411
|
isWidgetOrder: undefined,
|
|
411
412
|
});
|
|
412
413
|
});
|
|
414
|
+
it('test render LabelValue', async () => {
|
|
415
|
+
const item = {
|
|
416
|
+
id: 10452,
|
|
417
|
+
order: 0,
|
|
418
|
+
template: 'LabelValue',
|
|
419
|
+
configuration: {},
|
|
420
|
+
is_configuration_ready: true,
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const sensor = {
|
|
424
|
+
name: 'Sensor name',
|
|
425
|
+
is_managed_by_backend: false,
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
await act(async () => {
|
|
429
|
+
tree = await renderer.create(wrapComponent({ item, sensor }));
|
|
430
|
+
});
|
|
431
|
+
const instance = tree.root;
|
|
432
|
+
const displayItems = instance.findAllByType(LabelValue);
|
|
433
|
+
expect(displayItems).toHaveLength(1);
|
|
434
|
+
});
|
|
413
435
|
});
|
|
@@ -8,6 +8,7 @@ import FlatListItems from '../../../commons/Device/FlatListItems';
|
|
|
8
8
|
import FooterInfo from '../../../commons/Device/FooterInfo';
|
|
9
9
|
import PMSensorIndicator from '../../../commons/Device/PMSensor/PMSensorIndicator';
|
|
10
10
|
import ProgressBar from '../../../commons/Device/ProgressBar';
|
|
11
|
+
import LabelValue from '../../../commons/Device/LabelValue';
|
|
11
12
|
import CurrentRainSensor from '../../../commons/Device/RainningSensor/CurrentRainSensor';
|
|
12
13
|
import ListQualityIndicator from '../../../commons/Device/WaterQualitySensor/ListQualityIndicator';
|
|
13
14
|
import Compass from '../../../commons/Device/WindDirection/Compass';
|
|
@@ -216,6 +217,15 @@ export const SensorDisplayItem = ({
|
|
|
216
217
|
isWidgetOrder={isWidgetOrder}
|
|
217
218
|
/>
|
|
218
219
|
);
|
|
220
|
+
// use the same method to get data for circle_mini
|
|
221
|
+
case 'LabelValue':
|
|
222
|
+
return (
|
|
223
|
+
<LabelValue
|
|
224
|
+
data={getDataCircleMini(item)}
|
|
225
|
+
item={item}
|
|
226
|
+
isWidgetOrder={isWidgetOrder}
|
|
227
|
+
/>
|
|
228
|
+
);
|
|
219
229
|
case 'value':
|
|
220
230
|
switch (type || template) {
|
|
221
231
|
case 'circle':
|
|
@@ -7,7 +7,7 @@ import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
|
7
7
|
import { API } from '../../configs';
|
|
8
8
|
import Text from '../../commons/Text';
|
|
9
9
|
import SharedUnit from '../../commons/Unit/SharedUnit';
|
|
10
|
-
import {
|
|
10
|
+
import { useBlockBack } from '../../hooks/Common';
|
|
11
11
|
import { AccessibilityLabel } from '../../configs/Constants';
|
|
12
12
|
|
|
13
13
|
import styles from './styles';
|
|
@@ -17,7 +17,7 @@ import { ModalCustom } from '../../commons/Modal';
|
|
|
17
17
|
import useTitleHeader from '../../hooks/Common/useTitleHeader';
|
|
18
18
|
|
|
19
19
|
const Shared = () => {
|
|
20
|
-
|
|
20
|
+
useBlockBack();
|
|
21
21
|
const t = useTranslations();
|
|
22
22
|
useTitleHeader(t('text_shared_with_me'));
|
|
23
23
|
const navigation = useNavigation();
|