@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
|
@@ -120,4 +120,22 @@ describe('Test useGateway', () => {
|
|
|
120
120
|
});
|
|
121
121
|
expect(hook.result.current.detailDeviceZigbee).toEqual({});
|
|
122
122
|
});
|
|
123
|
+
|
|
124
|
+
it('test fetchChipQrDetail', async () => {
|
|
125
|
+
const response = {
|
|
126
|
+
org_slug: 'eoh',
|
|
127
|
+
secret: '123456',
|
|
128
|
+
prefix: 'lite',
|
|
129
|
+
host: 'example.com',
|
|
130
|
+
port: 1883,
|
|
131
|
+
};
|
|
132
|
+
mock
|
|
133
|
+
.onGet(API.DEV_MODE.CHIP_QR_CODE.DETAIL_BY_SECRET())
|
|
134
|
+
.reply(200, response);
|
|
135
|
+
|
|
136
|
+
await act(async () => {
|
|
137
|
+
await hook.result.current.fetchChipQrDetail('123456');
|
|
138
|
+
});
|
|
139
|
+
expect(hook.result.current.detailChipQr).toEqual(response);
|
|
140
|
+
});
|
|
123
141
|
});
|
|
@@ -19,6 +19,7 @@ export const useGateway = () => {
|
|
|
19
19
|
const [detailDeviceZigbee, setDetailDeviceZigbee] = useState({});
|
|
20
20
|
const [detailDeviceModbus, setDetailDeviceModbus] = useState({});
|
|
21
21
|
const [detailDeviceInternal, setDetailDeviceInternal] = useState({});
|
|
22
|
+
const [detailChipQr, setDetailChipQr] = useState({});
|
|
22
23
|
const [dataModalPopupCT, setDataModalPopupCT] = useState({});
|
|
23
24
|
const [pages, setPages] = useState(1);
|
|
24
25
|
const [loadingMore, setLoadingMore] = useState(false);
|
|
@@ -251,6 +252,16 @@ export const useGateway = () => {
|
|
|
251
252
|
[canLoadMore]
|
|
252
253
|
);
|
|
253
254
|
|
|
255
|
+
const fetchChipQrDetail = useCallback(async (secret) => {
|
|
256
|
+
const { success, data } = await axiosGet(
|
|
257
|
+
API.DEV_MODE.CHIP_QR_CODE.DETAIL_BY_SECRET(),
|
|
258
|
+
{
|
|
259
|
+
params: { secret },
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
success && setDetailChipQr(data);
|
|
263
|
+
}, []);
|
|
264
|
+
|
|
254
265
|
return {
|
|
255
266
|
gateways,
|
|
256
267
|
fetchDataGateways,
|
|
@@ -267,11 +278,13 @@ export const useGateway = () => {
|
|
|
267
278
|
fetchActionConfigDevice,
|
|
268
279
|
fetchRegistersModbus,
|
|
269
280
|
fetchActionsModbus,
|
|
281
|
+
fetchChipQrDetail,
|
|
270
282
|
gatewayDevices,
|
|
271
283
|
setSelectedIndex,
|
|
272
284
|
selectedIndex,
|
|
273
285
|
detailDeviceZigbee,
|
|
274
286
|
detailDeviceModbus,
|
|
287
|
+
detailChipQr,
|
|
275
288
|
setIsShowModalPopupCT,
|
|
276
289
|
isShowModalPopupCT,
|
|
277
290
|
setDataModalPopupCT,
|
|
@@ -81,7 +81,7 @@ const SetupConfigCondition = () => {
|
|
|
81
81
|
|
|
82
82
|
const setupCustomCondition = () => {
|
|
83
83
|
setSelectedCondition('custom');
|
|
84
|
-
automate.value =
|
|
84
|
+
automate.value = NaN;
|
|
85
85
|
setIsShowModal(true);
|
|
86
86
|
};
|
|
87
87
|
|
|
@@ -98,7 +98,7 @@ const SetupConfigCondition = () => {
|
|
|
98
98
|
|
|
99
99
|
const resetCustomizeCondition = useCallback(() => {
|
|
100
100
|
automate.condition = null;
|
|
101
|
-
automate.value =
|
|
101
|
+
automate.value = NaN;
|
|
102
102
|
setCustomCondition(undefined);
|
|
103
103
|
}, [automate]);
|
|
104
104
|
|
|
@@ -182,7 +182,7 @@ const SetupConfigCondition = () => {
|
|
|
182
182
|
title={t('continue')}
|
|
183
183
|
testID={'continue_button'}
|
|
184
184
|
onPress={() => {
|
|
185
|
-
if (
|
|
185
|
+
if (isNaN(automate.value) || !automate.condition) {
|
|
186
186
|
ToastBottomHelper.error(t('please_enter_a_number'), '', 3000);
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import { Keyboard, TouchableWithoutFeedback, View } from 'react-native';
|
|
3
|
+
import { useNavigation } from '@react-navigation/native';
|
|
4
|
+
import styles from './Styles/SetupScriptEmailStyles';
|
|
5
|
+
import { HeaderCustom } from '../../../commons';
|
|
6
|
+
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
7
|
+
|
|
8
|
+
import _TextInput from '../../../commons/Form/TextInput';
|
|
9
|
+
import AccessibilityLabel from '../../../configs/AccessibilityLabel';
|
|
10
|
+
import BottomButtonView from '../../../commons/BottomButtonView';
|
|
11
|
+
import Routes from '../../../utils/Route';
|
|
12
|
+
|
|
13
|
+
const SetupScriptEmail = ({ route }) => {
|
|
14
|
+
const t = useTranslations();
|
|
15
|
+
const { goBack, navigate } = useNavigation();
|
|
16
|
+
const { automate, unitId, multiUnit } = route.params || {};
|
|
17
|
+
const [formData, setFormData] = useState({ unit: unitId || multiUnit.id });
|
|
18
|
+
|
|
19
|
+
const onChangeTitle = (value) => {
|
|
20
|
+
setFormData((state) => ({
|
|
21
|
+
...state,
|
|
22
|
+
title: value,
|
|
23
|
+
}));
|
|
24
|
+
};
|
|
25
|
+
const onChangeMessage = (value) => {
|
|
26
|
+
setFormData((state) => ({
|
|
27
|
+
...state,
|
|
28
|
+
message: value,
|
|
29
|
+
}));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const onNext = useCallback(async () => {
|
|
33
|
+
navigate(Routes.SetupScriptReceiverEmail, {
|
|
34
|
+
automate,
|
|
35
|
+
unitId: unitId,
|
|
36
|
+
formData,
|
|
37
|
+
});
|
|
38
|
+
}, [automate, navigate, unitId, formData]);
|
|
39
|
+
|
|
40
|
+
const canSave = useMemo(() => {
|
|
41
|
+
const { title, message } = formData || {};
|
|
42
|
+
return !!title && !!message;
|
|
43
|
+
}, [formData]);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<View style={styles.wrap}>
|
|
47
|
+
<HeaderCustom isShowClose onClose={goBack} title={t('email_content')} />
|
|
48
|
+
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
|
|
49
|
+
<View style={styles.container}>
|
|
50
|
+
<_TextInput
|
|
51
|
+
placeholder={t('subject')}
|
|
52
|
+
onChange={onChangeTitle}
|
|
53
|
+
textInputStyle={styles.textTitle}
|
|
54
|
+
value={formData?.title}
|
|
55
|
+
accessibilityLabel={AccessibilityLabel.AUTOMATE_TITLE_NOTIFY}
|
|
56
|
+
autoFocus
|
|
57
|
+
/>
|
|
58
|
+
<_TextInput
|
|
59
|
+
placeholder={t('message')}
|
|
60
|
+
onChange={onChangeMessage}
|
|
61
|
+
textInputStyle={styles.textMessage}
|
|
62
|
+
value={formData?.message}
|
|
63
|
+
accessibilityLabel={AccessibilityLabel.AUTOMATE_MESSAGE_NOTIFY}
|
|
64
|
+
multiline={true}
|
|
65
|
+
maxLength={255}
|
|
66
|
+
/>
|
|
67
|
+
<BottomButtonView
|
|
68
|
+
style={styles.bottomButtonView}
|
|
69
|
+
mainTitle={t('next')}
|
|
70
|
+
onPressMain={onNext}
|
|
71
|
+
typeMain={canSave ? 'primary' : 'disabled'}
|
|
72
|
+
/>
|
|
73
|
+
</View>
|
|
74
|
+
</TouchableWithoutFeedback>
|
|
75
|
+
</View>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default SetupScriptEmail;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import React, { useCallback, useMemo, useState, useEffect, memo } from 'react';
|
|
2
|
+
import { FlatList, View } from 'react-native';
|
|
3
|
+
import { useNavigation } from '@react-navigation/native';
|
|
4
|
+
import styles from './Styles/SetupScriptReceiverEmailStyles';
|
|
5
|
+
import { CircleView, HeaderCustom, Text } from '../../../commons';
|
|
6
|
+
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
7
|
+
|
|
8
|
+
import BottomButtonView from '../../../commons/BottomButtonView';
|
|
9
|
+
import { axiosPost, axiosGet } from '../../../utils/Apis/axios';
|
|
10
|
+
import { API, Colors } from '../../../configs';
|
|
11
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
12
|
+
import Routes from '../../../utils/Route';
|
|
13
|
+
import moment from 'moment';
|
|
14
|
+
import { Image } from 'react-native-svg';
|
|
15
|
+
import CheckBox from '@react-native-community/checkbox';
|
|
16
|
+
import { useSCContextSelector } from '../../../context';
|
|
17
|
+
|
|
18
|
+
const SetupScriptReceiverEmail = ({ route }) => {
|
|
19
|
+
const t = useTranslations();
|
|
20
|
+
const { goBack, navigate } = useNavigation();
|
|
21
|
+
const { automate = {}, unitId, formData } = route.params || {};
|
|
22
|
+
const { id: automateId } = automate;
|
|
23
|
+
const [members, setMembers] = useState([]);
|
|
24
|
+
const [listUser, setListUser] = useState([]);
|
|
25
|
+
const currentUserId = useSCContextSelector(
|
|
26
|
+
(state) => state.auth.account.user.id
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const loadMembers = useCallback(async () => {
|
|
30
|
+
const { success, data } = await axiosGet(API.SHARE.UNITS_MEMBERS(unitId));
|
|
31
|
+
if (success) {
|
|
32
|
+
setMembers(data);
|
|
33
|
+
}
|
|
34
|
+
}, [unitId]);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
loadMembers();
|
|
38
|
+
}, [loadMembers]);
|
|
39
|
+
|
|
40
|
+
const onNext = useCallback(async () => {
|
|
41
|
+
formData.receiver = listUser;
|
|
42
|
+
const { success } = await axiosPost(
|
|
43
|
+
API.AUTOMATE.ADD_SCRIPT_EMAIL(automateId),
|
|
44
|
+
formData
|
|
45
|
+
);
|
|
46
|
+
if (success) {
|
|
47
|
+
ToastBottomHelper.success(t('text_done'));
|
|
48
|
+
navigate({
|
|
49
|
+
name: Routes.ScriptDetail,
|
|
50
|
+
merge: true,
|
|
51
|
+
params: { saveAt: moment().valueOf() },
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
ToastBottomHelper.error(t('error_please_try_later'));
|
|
55
|
+
}
|
|
56
|
+
}, [automateId, formData, listUser, navigate, t]);
|
|
57
|
+
|
|
58
|
+
const canSave = useMemo(() => {
|
|
59
|
+
const { title, message } = formData;
|
|
60
|
+
return !!title && !!message && !!listUser.length;
|
|
61
|
+
}, [formData, listUser.length]);
|
|
62
|
+
|
|
63
|
+
const arrColor = useMemo(
|
|
64
|
+
() => [
|
|
65
|
+
Colors.GeekBlue3,
|
|
66
|
+
Colors.Purple3,
|
|
67
|
+
Colors.Orange3,
|
|
68
|
+
Colors.Volcano3,
|
|
69
|
+
Colors.Blue9,
|
|
70
|
+
Colors.Green3,
|
|
71
|
+
Colors.Cyan2,
|
|
72
|
+
],
|
|
73
|
+
[]
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const onChecked = useCallback(
|
|
77
|
+
(id) => (checked) => {
|
|
78
|
+
setListUser((prevListUser) =>
|
|
79
|
+
checked
|
|
80
|
+
? [...prevListUser, id]
|
|
81
|
+
: prevListUser.filter((userId) => userId !== id)
|
|
82
|
+
);
|
|
83
|
+
},
|
|
84
|
+
[]
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const RowMember = memo(({ member, index, onValueChange }) => {
|
|
88
|
+
const { id, name, avatar, share_id, email } = member;
|
|
89
|
+
const [role, roleColor] = useMemo(() => {
|
|
90
|
+
if (!share_id) {
|
|
91
|
+
return [t('owner'), Colors.Primary];
|
|
92
|
+
}
|
|
93
|
+
if (id === currentUserId) {
|
|
94
|
+
return [t('me'), Colors.Primary];
|
|
95
|
+
}
|
|
96
|
+
return [t('member'), Colors.Gray6];
|
|
97
|
+
}, [share_id, id]);
|
|
98
|
+
|
|
99
|
+
const firstWordsInName = useMemo(() => {
|
|
100
|
+
return name.charAt();
|
|
101
|
+
}, [name]);
|
|
102
|
+
|
|
103
|
+
const circleColor = arrColor[index % arrColor.length];
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<View style={styles.rowContainer}>
|
|
107
|
+
<View style={styles.Border}>
|
|
108
|
+
<CheckBox
|
|
109
|
+
disabled={!email}
|
|
110
|
+
lineWidth={4}
|
|
111
|
+
value={listUser.includes(id)}
|
|
112
|
+
onValueChange={onValueChange(id)}
|
|
113
|
+
/>
|
|
114
|
+
<View style={styles.paddingLeft16}>
|
|
115
|
+
{avatar ? (
|
|
116
|
+
<Image source={{ uri: avatar }} style={styles.avatar} />
|
|
117
|
+
) : (
|
|
118
|
+
<CircleView size={40} backgroundColor={circleColor} center>
|
|
119
|
+
<Text color={Colors.White}>{firstWordsInName}</Text>
|
|
120
|
+
</CircleView>
|
|
121
|
+
)}
|
|
122
|
+
</View>
|
|
123
|
+
<View style={styles.paddingLeft16}>
|
|
124
|
+
<Text style={styles.titleName}>{name}</Text>
|
|
125
|
+
{email ? (
|
|
126
|
+
<Text style={styles.status}>{email}</Text>
|
|
127
|
+
) : (
|
|
128
|
+
<Text style={styles.invalid}>{t('no_email')}</Text>
|
|
129
|
+
)}
|
|
130
|
+
</View>
|
|
131
|
+
<View style={styles.endFlex}>
|
|
132
|
+
<Text style={[styles.textRole, { color: roleColor }]}>{role}</Text>
|
|
133
|
+
</View>
|
|
134
|
+
</View>
|
|
135
|
+
</View>
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<View style={styles.wrap}>
|
|
141
|
+
<HeaderCustom isShowClose onClose={goBack} title={t('email_to')} />
|
|
142
|
+
<FlatList
|
|
143
|
+
data={members}
|
|
144
|
+
renderItem={({ item, index }) => (
|
|
145
|
+
<RowMember member={item} index={index} onValueChange={onChecked} />
|
|
146
|
+
)}
|
|
147
|
+
keyExtractor={(item) => item.id.toString()}
|
|
148
|
+
ListEmptyComponent={
|
|
149
|
+
<View style={styles.viewEmpty}>
|
|
150
|
+
<Text style={styles.textCenter}>{t('no_member')}</Text>
|
|
151
|
+
</View>
|
|
152
|
+
}
|
|
153
|
+
/>
|
|
154
|
+
<View style={styles.container}>
|
|
155
|
+
<BottomButtonView
|
|
156
|
+
style={styles.bottomButtonView}
|
|
157
|
+
mainTitle={t('done')}
|
|
158
|
+
onPressMain={onNext}
|
|
159
|
+
typeMain={canSave ? 'primary' : 'disabled'}
|
|
160
|
+
/>
|
|
161
|
+
</View>
|
|
162
|
+
</View>
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export default SetupScriptReceiverEmail;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors } from '../../../../configs';
|
|
3
|
+
import { getBottomSpace } from 'react-native-iphone-x-helper';
|
|
4
|
+
|
|
5
|
+
export default StyleSheet.create({
|
|
6
|
+
wrap: {
|
|
7
|
+
flex: 1,
|
|
8
|
+
backgroundColor: Colors.White,
|
|
9
|
+
},
|
|
10
|
+
container: {
|
|
11
|
+
flex: 1,
|
|
12
|
+
paddingHorizontal: 16,
|
|
13
|
+
paddingTop: 10,
|
|
14
|
+
paddingBottom: getBottomSpace() + 10,
|
|
15
|
+
},
|
|
16
|
+
textTitle: {
|
|
17
|
+
borderWidth: 1,
|
|
18
|
+
borderColor: Colors.Gray4,
|
|
19
|
+
borderStyle: 'solid',
|
|
20
|
+
borderRadius: 10,
|
|
21
|
+
},
|
|
22
|
+
textMessage: {
|
|
23
|
+
height: 500,
|
|
24
|
+
textAlignVertical: 'top',
|
|
25
|
+
borderWidth: 1,
|
|
26
|
+
borderColor: Colors.Gray4,
|
|
27
|
+
borderStyle: 'solid',
|
|
28
|
+
borderRadius: 10,
|
|
29
|
+
},
|
|
30
|
+
bottomButtonView: {
|
|
31
|
+
paddingTop: 24,
|
|
32
|
+
paddingBottom: 32,
|
|
33
|
+
backgroundColor: Colors.White,
|
|
34
|
+
borderColor: Colors.ShadownTransparent,
|
|
35
|
+
borderTopWidth: 1,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors, Constants } from '../../../../configs';
|
|
3
|
+
import { getBottomSpace } from 'react-native-iphone-x-helper';
|
|
4
|
+
|
|
5
|
+
export default StyleSheet.create({
|
|
6
|
+
wrap: {
|
|
7
|
+
flex: 1,
|
|
8
|
+
backgroundColor: Colors.White,
|
|
9
|
+
},
|
|
10
|
+
viewEmpty: {
|
|
11
|
+
justifyContent: 'center',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
height: Constants.height - 200,
|
|
14
|
+
backgroundColor: Colors.White,
|
|
15
|
+
},
|
|
16
|
+
textCenter: {
|
|
17
|
+
alignSelf: 'center',
|
|
18
|
+
},
|
|
19
|
+
container: {
|
|
20
|
+
flex: 1,
|
|
21
|
+
paddingHorizontal: 16,
|
|
22
|
+
paddingTop: 10,
|
|
23
|
+
paddingBottom: getBottomSpace() + 10,
|
|
24
|
+
},
|
|
25
|
+
bottomButtonView: {
|
|
26
|
+
paddingTop: 24,
|
|
27
|
+
paddingBottom: 32,
|
|
28
|
+
backgroundColor: Colors.White,
|
|
29
|
+
borderColor: Colors.ShadownTransparent,
|
|
30
|
+
borderTopWidth: 1,
|
|
31
|
+
},
|
|
32
|
+
rowContainer: {
|
|
33
|
+
marginTop: 16,
|
|
34
|
+
},
|
|
35
|
+
textRole: {
|
|
36
|
+
fontSize: 12,
|
|
37
|
+
lineHeight: 20,
|
|
38
|
+
},
|
|
39
|
+
endFlex: {
|
|
40
|
+
flex: 1,
|
|
41
|
+
justifyContent: 'flex-start',
|
|
42
|
+
alignItems: 'flex-end',
|
|
43
|
+
},
|
|
44
|
+
Border: {
|
|
45
|
+
flexDirection: 'row',
|
|
46
|
+
paddingBottom: 16,
|
|
47
|
+
paddingHorizontal: 16,
|
|
48
|
+
},
|
|
49
|
+
titleName: {
|
|
50
|
+
fontSize: 16,
|
|
51
|
+
lineHeight: 24,
|
|
52
|
+
fontStyle: 'normal',
|
|
53
|
+
fontWeight: '400',
|
|
54
|
+
},
|
|
55
|
+
status: {
|
|
56
|
+
fontSize: 12,
|
|
57
|
+
lineHeight: 20,
|
|
58
|
+
fontStyle: 'normal',
|
|
59
|
+
fontWeight: '400',
|
|
60
|
+
color: Colors.Gray7,
|
|
61
|
+
},
|
|
62
|
+
invalid: {
|
|
63
|
+
fontSize: 12,
|
|
64
|
+
lineHeight: 20,
|
|
65
|
+
fontStyle: 'normal',
|
|
66
|
+
fontWeight: '400',
|
|
67
|
+
color: Colors.Red,
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
paddingLeft16: {
|
|
71
|
+
paddingLeft: 16,
|
|
72
|
+
},
|
|
73
|
+
avatar: {
|
|
74
|
+
height: 40,
|
|
75
|
+
width: 40,
|
|
76
|
+
borderRadius: 40,
|
|
77
|
+
backgroundColor: Colors.Primary,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
@@ -182,7 +182,7 @@ describe('Test SetupConfigCondition', () => {
|
|
|
182
182
|
});
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
const testCustomCondition = async (value) => {
|
|
186
186
|
useRoute.mockReturnValue({
|
|
187
187
|
params: {
|
|
188
188
|
automate: {},
|
|
@@ -221,7 +221,7 @@ describe('Test SetupConfigCondition', () => {
|
|
|
221
221
|
const input = instance.findByType(TextInput);
|
|
222
222
|
|
|
223
223
|
await act(async () => {
|
|
224
|
-
input.props.onChange(
|
|
224
|
+
input.props.onChange(value.toString());
|
|
225
225
|
});
|
|
226
226
|
|
|
227
227
|
const bottomButtonView = instance.findByProps({
|
|
@@ -235,10 +235,18 @@ describe('Test SetupConfigCondition', () => {
|
|
|
235
235
|
expect(global.mockedNavigate).toBeCalledWith(Routes.ValueChangeName, {
|
|
236
236
|
automate: {
|
|
237
237
|
condition: '<',
|
|
238
|
-
value:
|
|
238
|
+
value: value,
|
|
239
239
|
},
|
|
240
240
|
closeScreen: undefined,
|
|
241
241
|
});
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
it('choose config custom condition', async () => {
|
|
245
|
+
await testCustomCondition(123);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('test custom condition with value = 0', async () => {
|
|
249
|
+
await testCustomCondition(0);
|
|
242
250
|
});
|
|
243
251
|
|
|
244
252
|
const testConditionValue = async (value, message) => {
|
|
@@ -273,9 +281,9 @@ describe('Test SetupConfigCondition', () => {
|
|
|
273
281
|
});
|
|
274
282
|
|
|
275
283
|
if (message === null) {
|
|
276
|
-
expect(global.mockedNavigate).
|
|
284
|
+
expect(global.mockedNavigate).toHaveBeenCalled();
|
|
277
285
|
} else {
|
|
278
|
-
expect(spyToastError).
|
|
286
|
+
expect(spyToastError).toHaveBeenCalledWith(message, '', 3000);
|
|
279
287
|
}
|
|
280
288
|
};
|
|
281
289
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useNavigation, useRoute } from '@react-navigation/native';
|
|
2
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { TouchableWithoutFeedback } from 'react-native';
|
|
5
|
+
import renderer, { act } from 'react-test-renderer';
|
|
6
|
+
import BottomButtonView from '../../../../commons/BottomButtonView';
|
|
7
|
+
import _TextInput from '../../../../commons/Form/TextInput';
|
|
8
|
+
import API from '../../../../configs/API';
|
|
9
|
+
import { SCProvider } from '../../../../context';
|
|
10
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
11
|
+
import api from '../../../../utils/Apis/axios';
|
|
12
|
+
import Routes from '../../../../utils/Route';
|
|
13
|
+
import SetupScriptEmail from '../SetupScriptEmail';
|
|
14
|
+
|
|
15
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
16
|
+
|
|
17
|
+
const wrapComponent = (route) => (
|
|
18
|
+
<SCProvider initState={mockSCStore({})}>
|
|
19
|
+
<SetupScriptEmail route={route} />
|
|
20
|
+
</SCProvider>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
describe('Test SetupScriptEmail', () => {
|
|
24
|
+
const mockedNavigate = useNavigation().navigate;
|
|
25
|
+
|
|
26
|
+
let tree;
|
|
27
|
+
const route = {
|
|
28
|
+
params: {
|
|
29
|
+
unitId: 1,
|
|
30
|
+
automateId: 1,
|
|
31
|
+
scriptName: 'scriptName test',
|
|
32
|
+
automate: {
|
|
33
|
+
id: 1,
|
|
34
|
+
sensor_id: 1,
|
|
35
|
+
},
|
|
36
|
+
closeScreen: Routes.ScriptDetail,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
mockedNavigate.mockClear();
|
|
41
|
+
useRoute.mockImplementation(() => route);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('SetupScriptNotify onPress create script notify success', async () => {
|
|
45
|
+
mock.onPost(API.AUTOMATE.ADD_SCRIPT_NOTIFY(1)).reply(200);
|
|
46
|
+
await act(async () => {
|
|
47
|
+
tree = await renderer.create(wrapComponent(route));
|
|
48
|
+
});
|
|
49
|
+
const instance = tree.root;
|
|
50
|
+
const inputs = instance.findAllByType(_TextInput);
|
|
51
|
+
expect(inputs).toHaveLength(2);
|
|
52
|
+
|
|
53
|
+
await act(async () => {
|
|
54
|
+
inputs[0].props.onChange('Title');
|
|
55
|
+
});
|
|
56
|
+
const touchable = instance.findAllByType(TouchableWithoutFeedback);
|
|
57
|
+
await act(async () => {
|
|
58
|
+
touchable[0].props.onPress();
|
|
59
|
+
});
|
|
60
|
+
await act(async () => {
|
|
61
|
+
inputs[1].props.onChange('Message');
|
|
62
|
+
});
|
|
63
|
+
const button = instance.findByType(BottomButtonView);
|
|
64
|
+
await act(async () => {
|
|
65
|
+
button.props.onPressMain();
|
|
66
|
+
});
|
|
67
|
+
expect(mockedNavigate).toHaveBeenCalledWith(
|
|
68
|
+
Routes.SetupScriptReceiverEmail,
|
|
69
|
+
{
|
|
70
|
+
automate: route.params.automate,
|
|
71
|
+
unitId: 1,
|
|
72
|
+
formData: { message: 'Message', title: 'Title', unit: 1 },
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { useNavigation, useRoute } from '@react-navigation/native';
|
|
2
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import renderer, { act } from 'react-test-renderer';
|
|
5
|
+
import BottomButtonView from '../../../../commons/BottomButtonView';
|
|
6
|
+
import API from '../../../../configs/API';
|
|
7
|
+
import { SCProvider } from '../../../../context';
|
|
8
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
9
|
+
import api from '../../../../utils/Apis/axios';
|
|
10
|
+
import Routes from '../../../../utils/Route';
|
|
11
|
+
import { ToastBottomHelper } from '../../../../utils/Utils';
|
|
12
|
+
import SetupScriptReceiverEmail from '../SetupScriptReceiverEmail';
|
|
13
|
+
import CheckBox from '@react-native-community/checkbox';
|
|
14
|
+
|
|
15
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
16
|
+
|
|
17
|
+
const wrapComponent = (route) => (
|
|
18
|
+
<SCProvider initState={mockSCStore({})}>
|
|
19
|
+
<SetupScriptReceiverEmail route={route} />
|
|
20
|
+
</SCProvider>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
describe('Test SetupScriptReceiverEmail', () => {
|
|
24
|
+
const mockedNavigate = useNavigation().navigate;
|
|
25
|
+
|
|
26
|
+
let tree;
|
|
27
|
+
const route = {
|
|
28
|
+
params: {
|
|
29
|
+
unitId: 1,
|
|
30
|
+
automateId: 1,
|
|
31
|
+
automate: {
|
|
32
|
+
id: 1,
|
|
33
|
+
sensor_id: 1,
|
|
34
|
+
},
|
|
35
|
+
closeScreen: Routes.ScriptDetail,
|
|
36
|
+
formData: { title: 'title', message: 'message' },
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const listUser = [
|
|
41
|
+
{
|
|
42
|
+
avatar: 'https://xxx',
|
|
43
|
+
email: 'user1.nh@eoh.io',
|
|
44
|
+
id: 140,
|
|
45
|
+
name: 'User 1',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
avatar: null,
|
|
49
|
+
email: null,
|
|
50
|
+
id: 56,
|
|
51
|
+
name: 'User 2',
|
|
52
|
+
share_id: 5386,
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
mockedNavigate.mockClear();
|
|
57
|
+
useRoute.mockImplementation(() => route);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('SetupScriptReceiverEmail onPress create script email success', async () => {
|
|
61
|
+
const spyToast = jest.spyOn(ToastBottomHelper, 'success');
|
|
62
|
+
mock.onGet(API.SHARE.UNITS_MEMBERS(1)).reply(200, listUser);
|
|
63
|
+
mock.onPost(API.AUTOMATE.ADD_SCRIPT_EMAIL(1)).reply(200);
|
|
64
|
+
await act(async () => {
|
|
65
|
+
tree = await renderer.create(wrapComponent(route));
|
|
66
|
+
});
|
|
67
|
+
const instance = tree.root;
|
|
68
|
+
const checkboxs = instance.findAllByType(CheckBox);
|
|
69
|
+
expect(checkboxs).toHaveLength(2);
|
|
70
|
+
expect(checkboxs[0].props.disabled).toBeFalsy();
|
|
71
|
+
expect(checkboxs[1].props.disabled).toBeTruthy();
|
|
72
|
+
await act(async () => {
|
|
73
|
+
checkboxs[0].props.onValueChange(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const button = instance.findByType(BottomButtonView);
|
|
77
|
+
await act(async () => {
|
|
78
|
+
button.props.onPressMain();
|
|
79
|
+
});
|
|
80
|
+
expect(spyToast).toHaveBeenCalled();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('SetupScriptReceiverEmail onPress create script email fail', async () => {
|
|
84
|
+
const spyToast = jest.spyOn(ToastBottomHelper, 'error');
|
|
85
|
+
mock.onGet(API.SHARE.UNITS_MEMBERS(1)).reply(200, listUser);
|
|
86
|
+
mock.onPost(API.AUTOMATE.ADD_SCRIPT_EMAIL(1)).reply(400);
|
|
87
|
+
await act(async () => {
|
|
88
|
+
tree = await renderer.create(wrapComponent(route));
|
|
89
|
+
});
|
|
90
|
+
const instance = tree.root;
|
|
91
|
+
const checkboxs = instance.findAllByType(CheckBox);
|
|
92
|
+
expect(checkboxs).toHaveLength(2);
|
|
93
|
+
expect(checkboxs[0].props.disabled).toBeFalsy();
|
|
94
|
+
expect(checkboxs[1].props.disabled).toBeTruthy();
|
|
95
|
+
await act(async () => {
|
|
96
|
+
checkboxs[0].props.onValueChange(true);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const button = instance.findByType(BottomButtonView);
|
|
100
|
+
await act(async () => {
|
|
101
|
+
button.props.onPressMain();
|
|
102
|
+
});
|
|
103
|
+
expect(spyToast).toHaveBeenCalled();
|
|
104
|
+
});
|
|
105
|
+
});
|