@eohjsc/react-native-smart-city 0.7.15 → 0.7.17
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/Sms.svg +9 -0
- package/package.json +1 -1
- package/src/commons/Automate/ItemConditionScriptDetailStyles.js +1 -0
- package/src/commons/Unit/__test__/SharedUnit.test.js +57 -0
- package/src/configs/API.js +6 -1
- package/src/configs/AccessibilityLabel.js +4 -0
- package/src/hooks/Common/useBlockBack.js +10 -2
- package/src/navigations/UnitStack.js +24 -0
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverSms.js +167 -0
- package/src/screens/Automate/AddNewAction/SetupScriptSms.js +73 -0
- package/src/screens/Automate/AddNewAction/Styles/SetupScriptEmailStyles.js +5 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverSms.test.js +105 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptSms.test.js +70 -0
- package/src/screens/Automate/EditActionsList/UpdateReceiverSmsScript.js +178 -0
- package/src/screens/Automate/EditActionsList/UpdateSmsScript.js +66 -0
- package/src/screens/Automate/EditActionsList/__tests__/UpdateReceiverSmsScript.test.js +82 -0
- package/src/screens/Automate/EditActionsList/__tests__/UpdateSmsScript.test.js +71 -0
- package/src/screens/Automate/EditActionsList/index.js +50 -1
- package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +52 -19
- package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +39 -2
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +295 -57
- package/src/screens/Automate/ScriptDetail/index.js +234 -32
- package/src/utils/I18n/translations/en.js +10 -0
- package/src/utils/I18n/translations/vi.js +10 -0
- package/src/utils/Route/index.js +3 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M30.3334 0.333313H3.66671C1.83337 0.333313 0.350041 1.83331 0.350041 3.66665L0.333374 33.6666L7.00004 27H30.3334C32.1667 27 33.6667 25.5 33.6667 23.6666V3.66665C33.6667 1.83331 32.1667 0.333313 30.3334 0.333313ZM12 15.3333H8.66671V12H12V15.3333ZM18.6667 15.3333H15.3334V12H18.6667V15.3333ZM25.3334 15.3333H22V12H25.3334V15.3333Z" fill="url(#paint0_linear_3441_1581)"/>
|
|
3
|
+
<defs>
|
|
4
|
+
<linearGradient id="paint0_linear_3441_1581" x1="0.333374" y1="0.333313" x2="33.6298" y2="33.6667" gradientUnits="userSpaceOnUse">
|
|
5
|
+
<stop stop-color="#2B6B9F"/>
|
|
6
|
+
<stop offset="1" stop-color="#D5FFCB"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
</defs>
|
|
9
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -109,6 +109,63 @@ describe('Test SharedUnit', () => {
|
|
|
109
109
|
});
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
+
it('Test remove pin and start shared unit', async () => {
|
|
113
|
+
const navigation = useNavigation();
|
|
114
|
+
item.is_pin = true;
|
|
115
|
+
item.is_star = true;
|
|
116
|
+
const mockedRenewItem = jest.fn();
|
|
117
|
+
await act(async () => {
|
|
118
|
+
tree = await create(
|
|
119
|
+
wrapComponent(item, navigation, undefined, mockedRenewItem)
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
const instance = tree.root;
|
|
123
|
+
|
|
124
|
+
const iconAddPinSharedUnit = instance.findAll(
|
|
125
|
+
(el) =>
|
|
126
|
+
el.props.accessibilityLabel ===
|
|
127
|
+
AccessibilityLabel.ICON_ADD_PIN_SHARED_UNIT + '-69'
|
|
128
|
+
);
|
|
129
|
+
const iconAddStarSharedUnit = instance.findAll(
|
|
130
|
+
(el) =>
|
|
131
|
+
el.props.accessibilityLabel ===
|
|
132
|
+
AccessibilityLabel.ICON_ADD_STAR_SHARED_UNIT + '-69'
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const iconRemovePinSharedUnit = instance.find(
|
|
136
|
+
(el) =>
|
|
137
|
+
el.props.accessibilityLabel ===
|
|
138
|
+
AccessibilityLabel.ICON_REMOVE_PIN_SHARED_UNIT + '-69'
|
|
139
|
+
);
|
|
140
|
+
mock.onPost(API.UNIT.UNPIN_UNIT(3)).reply(200);
|
|
141
|
+
await act(async () => {
|
|
142
|
+
iconRemovePinSharedUnit.props.onPress();
|
|
143
|
+
});
|
|
144
|
+
mock.onPost(API.UNIT.UNPIN_UNIT(3)).reply(400);
|
|
145
|
+
await act(async () => {
|
|
146
|
+
iconRemovePinSharedUnit.props.onPress();
|
|
147
|
+
});
|
|
148
|
+
expect(mockedRenewItem).toHaveBeenCalledTimes(1);
|
|
149
|
+
|
|
150
|
+
const iconRemoveStarSharedUnit = instance.find(
|
|
151
|
+
(el) =>
|
|
152
|
+
el.props.accessibilityLabel ===
|
|
153
|
+
AccessibilityLabel.ICON_REMOVE_STAR_SHARED_UNIT + '-69'
|
|
154
|
+
);
|
|
155
|
+
mock.onPost(API.UNIT.UNSTAR_UNIT(3)).reply(200);
|
|
156
|
+
await act(async () => {
|
|
157
|
+
iconRemoveStarSharedUnit.props.onPress();
|
|
158
|
+
});
|
|
159
|
+
mock.onPost(API.UNIT.UNSTAR_UNIT(3)).reply(400);
|
|
160
|
+
await act(async () => {
|
|
161
|
+
iconRemoveStarSharedUnit.props.onPress();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
expect(mockedRenewItem).toHaveBeenCalledTimes(2);
|
|
165
|
+
expect(iconAddPinSharedUnit).toHaveLength(0);
|
|
166
|
+
expect(iconAddStarSharedUnit).toHaveLength(0);
|
|
167
|
+
});
|
|
168
|
+
|
|
112
169
|
// it('test create SharedUnit unit without unit owner', async () => {
|
|
113
170
|
// const navigation = useNavigation();
|
|
114
171
|
// delete unit.owner_name;
|
package/src/configs/API.js
CHANGED
|
@@ -108,6 +108,8 @@ const API = {
|
|
|
108
108
|
`/property_manager/automate/${automateId}/update_script_action/`,
|
|
109
109
|
UPDATE_SCRIPT_EMAIL: (automateId) =>
|
|
110
110
|
`/property_manager/automate/${automateId}/update_script_email/`,
|
|
111
|
+
UPDATE_SCRIPT_SMS: (automateId) =>
|
|
112
|
+
`/property_manager/automate/${automateId}/update_script_sms/`,
|
|
111
113
|
ADD_SCRIPT_ACTION: (id) =>
|
|
112
114
|
`/property_manager/automate/${id}/add_script_action/`,
|
|
113
115
|
ADD_SCRIPT_NOTIFY: (id) =>
|
|
@@ -116,7 +118,7 @@ const API = {
|
|
|
116
118
|
`/property_manager/automate/${id}/add_script_delay/`,
|
|
117
119
|
ADD_SCRIPT_EMAIL: (id) =>
|
|
118
120
|
`/property_manager/automate/${id}/add_script_email/`,
|
|
119
|
-
|
|
121
|
+
ADD_SCRIPT_SMS: (id) => `/property_manager/automate/${id}/add_script_sms/`,
|
|
120
122
|
FETCH_AUTOMATE: (automateId) => `/property_manager/automate/${automateId}/`,
|
|
121
123
|
CREATE_AUTOMATE: () => '/property_manager/automate/',
|
|
122
124
|
UPDATE_AUTOMATE: (automateId) =>
|
|
@@ -131,6 +133,8 @@ const API = {
|
|
|
131
133
|
GET_MULTI_UNITS: () => '/property_manager/automate/multi_unit/',
|
|
132
134
|
ACTIVITY_LOG: (id) => `/property_manager/automate/${id}/logs/`,
|
|
133
135
|
STARRED_SCRIPTS: () => '/property_manager/automate/starred_scripts/',
|
|
136
|
+
ENABLE_LOCAL_CONTROL: (id) =>
|
|
137
|
+
`/property_manager/automate/${id}/enable_local_control/`,
|
|
134
138
|
},
|
|
135
139
|
HOME_ASSISTANT: {
|
|
136
140
|
CHECK_SEND_EMAIL: () =>
|
|
@@ -245,6 +249,7 @@ const API = {
|
|
|
245
249
|
COUNT: () => '/chip_manager/developer_mode_chips/count/',
|
|
246
250
|
DETAIL: (id) => `/chip_manager/developer_mode_chips/${id}/`,
|
|
247
251
|
REBOOT: (id) => `/chip_manager/developer_mode_chips/${id}/reboot_chip/`,
|
|
252
|
+
SHARED: () => '/property_manager/iot_dashboard/filters/chip_shared/',
|
|
248
253
|
},
|
|
249
254
|
ARDUINO: {
|
|
250
255
|
DETAIL: (id) => `/iot/modules/arduino/gateways/${id}/`,
|
|
@@ -251,6 +251,10 @@ export default {
|
|
|
251
251
|
AUTOMATE_TITLE_NOTIFY: 'AUTOMATE_TITLE_NOTIFY',
|
|
252
252
|
AUTOMATE_MESSAGE_NOTIFY: 'AUTOMATE_MESSAGE_NOTIFY',
|
|
253
253
|
AUTOMATE_INPUT_DELAY: 'AUTOMATE_INPUT_DELAY',
|
|
254
|
+
AUTOMATE_SHOW_LOCAL_CONTROL: 'AUTOMATE_SHOW_LOCAL_CONTROL',
|
|
255
|
+
AUTOMATE_DISABLE_LOCAL_CONTROL: 'AUTOMATE_DISABLE_LOCAL_CONTROL',
|
|
256
|
+
AUTOMATE_ENABLE_LOCAL_CONTROL: 'AUTOMATE_ENABLE_LOCAL_CONTROL',
|
|
257
|
+
|
|
254
258
|
// Parking input maunaly spot
|
|
255
259
|
PARKING_SPOT_INFO_BUTTON: 'PARKING_SPOT_INFO_BUTTON',
|
|
256
260
|
PARKING_SPOT_CONFIRM_SPOT: 'PARKING_SPOT_CONFIRM_SPOT',
|
|
@@ -5,6 +5,7 @@ import { BackHandler, Platform } from 'react-native';
|
|
|
5
5
|
export const useBlockBack = (actionBack) => {
|
|
6
6
|
const navigation = useNavigation();
|
|
7
7
|
const isListening = useRef(false);
|
|
8
|
+
const isBeforeRemoveHandled = useRef(false);
|
|
8
9
|
|
|
9
10
|
const blockBack = useCallback(() => {
|
|
10
11
|
actionBack && actionBack();
|
|
@@ -13,8 +14,15 @@ export const useBlockBack = (actionBack) => {
|
|
|
13
14
|
|
|
14
15
|
const blockBeforeRemove = useCallback(
|
|
15
16
|
(e) => {
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
if (isBeforeRemoveHandled.current) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const { type } = e.data.action;
|
|
21
|
+
if (type === 'GO_BACK' || type === 'POP') {
|
|
22
|
+
isBeforeRemoveHandled.current = true;
|
|
23
|
+
e.preventDefault();
|
|
24
|
+
blockBack();
|
|
25
|
+
}
|
|
18
26
|
},
|
|
19
27
|
[blockBack]
|
|
20
28
|
);
|
|
@@ -72,6 +72,9 @@ import { HanetCameraStack } from './HanetCameraStack';
|
|
|
72
72
|
import { styles } from './UnitStackStyles';
|
|
73
73
|
import { bleManager } from '../utils/bluetooth';
|
|
74
74
|
import UpdateReceiverEmailScript from '../screens/Automate/EditActionsList/UpdateReceiverEmailScript';
|
|
75
|
+
import SetupScriptSms from '../screens/Automate/AddNewAction/SetupScriptSms';
|
|
76
|
+
import SetupScriptReceiverSms from '../screens/Automate/AddNewAction/SetupScriptReceiverSms';
|
|
77
|
+
import UpdateReceiverSmsScript from '../screens/Automate/EditActionsList/UpdateReceiverSmsScript';
|
|
75
78
|
|
|
76
79
|
const Stack = createNativeStackNavigator();
|
|
77
80
|
|
|
@@ -446,6 +449,27 @@ export const UnitStack = memo((props) => {
|
|
|
446
449
|
headerShown: false,
|
|
447
450
|
}}
|
|
448
451
|
/>
|
|
452
|
+
<Stack.Screen
|
|
453
|
+
name={Route.SetupScriptSms}
|
|
454
|
+
component={SetupScriptSms}
|
|
455
|
+
options={{
|
|
456
|
+
headerShown: false,
|
|
457
|
+
}}
|
|
458
|
+
/>
|
|
459
|
+
<Stack.Screen
|
|
460
|
+
name={Route.SetupScriptReceiverSms}
|
|
461
|
+
component={SetupScriptReceiverSms}
|
|
462
|
+
options={{
|
|
463
|
+
headerShown: false,
|
|
464
|
+
}}
|
|
465
|
+
/>
|
|
466
|
+
<Stack.Screen
|
|
467
|
+
name={Route.UpdateReceiverSmsScript}
|
|
468
|
+
component={UpdateReceiverSmsScript}
|
|
469
|
+
options={{
|
|
470
|
+
headerShown: false,
|
|
471
|
+
}}
|
|
472
|
+
/>
|
|
449
473
|
<Stack.Screen
|
|
450
474
|
name={Route.AddAutomationTypeSmart}
|
|
451
475
|
component={AddAutomationTypeSmart}
|
|
@@ -0,0 +1,167 @@
|
|
|
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 CheckBox from '@react-native-community/checkbox';
|
|
15
|
+
import { useSCContextSelector } from '../../../context';
|
|
16
|
+
import { Image } from 'react-native';
|
|
17
|
+
|
|
18
|
+
const SetupScriptReceiverSms = ({ 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_SMS(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 { message } = formData;
|
|
60
|
+
return !!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, phone_number } = 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={!phone_number}
|
|
110
|
+
lineWidth={4}
|
|
111
|
+
value={listUser.includes(id)}
|
|
112
|
+
onValueChange={onValueChange(id)}
|
|
113
|
+
style={styles.checkbox}
|
|
114
|
+
/>
|
|
115
|
+
<View style={styles.paddingLeft16}>
|
|
116
|
+
{avatar ? (
|
|
117
|
+
<Image source={{ uri: avatar }} style={styles.avatar} />
|
|
118
|
+
) : (
|
|
119
|
+
<CircleView size={40} backgroundColor={circleColor} center>
|
|
120
|
+
<Text color={Colors.White}>{firstWordsInName}</Text>
|
|
121
|
+
</CircleView>
|
|
122
|
+
)}
|
|
123
|
+
</View>
|
|
124
|
+
<View style={styles.paddingLeft16}>
|
|
125
|
+
<Text style={styles.titleName}>{name}</Text>
|
|
126
|
+
{phone_number ? (
|
|
127
|
+
<Text style={styles.status}>{phone_number}</Text>
|
|
128
|
+
) : (
|
|
129
|
+
<Text style={styles.invalid}>{t('no_phone_number')}</Text>
|
|
130
|
+
)}
|
|
131
|
+
</View>
|
|
132
|
+
<View style={styles.endFlex}>
|
|
133
|
+
<Text style={[styles.textRole, { color: roleColor }]}>{role}</Text>
|
|
134
|
+
</View>
|
|
135
|
+
</View>
|
|
136
|
+
</View>
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<View style={styles.wrap}>
|
|
142
|
+
<HeaderCustom isShowClose onClose={goBack} title={t('sms_to')} />
|
|
143
|
+
<FlatList
|
|
144
|
+
data={members}
|
|
145
|
+
renderItem={({ item, index }) => (
|
|
146
|
+
<RowMember member={item} index={index} onValueChange={onChecked} />
|
|
147
|
+
)}
|
|
148
|
+
keyExtractor={(item) => item.id.toString()}
|
|
149
|
+
ListEmptyComponent={
|
|
150
|
+
<View style={styles.viewEmpty}>
|
|
151
|
+
<Text style={styles.textCenter}>{t('no_member')}</Text>
|
|
152
|
+
</View>
|
|
153
|
+
}
|
|
154
|
+
/>
|
|
155
|
+
<View style={styles.container}>
|
|
156
|
+
<BottomButtonView
|
|
157
|
+
style={styles.bottomButtonView}
|
|
158
|
+
mainTitle={t('done')}
|
|
159
|
+
onPressMain={onNext}
|
|
160
|
+
typeMain={canSave ? 'primary' : 'disabled'}
|
|
161
|
+
/>
|
|
162
|
+
</View>
|
|
163
|
+
</View>
|
|
164
|
+
);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export default SetupScriptReceiverSms;
|
|
@@ -0,0 +1,73 @@
|
|
|
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, Text } 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
|
+
import { Colors } from '../../../configs';
|
|
13
|
+
|
|
14
|
+
const SetupScriptSms = ({ route }) => {
|
|
15
|
+
const t = useTranslations();
|
|
16
|
+
const { goBack, navigate } = useNavigation();
|
|
17
|
+
const { automate, unitId, multiUnit } = route.params || {};
|
|
18
|
+
const initialUnitId = useMemo(
|
|
19
|
+
() => unitId || multiUnit.id,
|
|
20
|
+
[unitId, multiUnit?.id]
|
|
21
|
+
);
|
|
22
|
+
const [formData, setFormData] = useState({ unit: initialUnitId });
|
|
23
|
+
|
|
24
|
+
const onChangeMessage = (value) => {
|
|
25
|
+
setFormData((state) => ({
|
|
26
|
+
...state,
|
|
27
|
+
message: value,
|
|
28
|
+
}));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const onNext = useCallback(async () => {
|
|
32
|
+
navigate(Routes.SetupScriptReceiverSms, {
|
|
33
|
+
automate,
|
|
34
|
+
unitId: initialUnitId,
|
|
35
|
+
formData,
|
|
36
|
+
});
|
|
37
|
+
}, [navigate, automate, initialUnitId, formData]);
|
|
38
|
+
|
|
39
|
+
const canSave = useMemo(() => {
|
|
40
|
+
const { message } = formData || {};
|
|
41
|
+
return !!message;
|
|
42
|
+
}, [formData]);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<View style={styles.wrap}>
|
|
46
|
+
<HeaderCustom isShowClose onClose={goBack} title={t('sms_content')} />
|
|
47
|
+
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
|
|
48
|
+
<View style={styles.container}>
|
|
49
|
+
<_TextInput
|
|
50
|
+
placeholder={t('message_sms')}
|
|
51
|
+
onChange={onChangeMessage}
|
|
52
|
+
textInputStyle={styles.textMessage}
|
|
53
|
+
value={formData?.message}
|
|
54
|
+
accessibilityLabel={AccessibilityLabel.AUTOMATE_MESSAGE_NOTIFY}
|
|
55
|
+
multiline={true}
|
|
56
|
+
maxLength={255}
|
|
57
|
+
/>
|
|
58
|
+
<View style={styles.textWarning}>
|
|
59
|
+
<Text color={Colors.Gray}>{t('only_in_local_control')}</Text>
|
|
60
|
+
</View>
|
|
61
|
+
<BottomButtonView
|
|
62
|
+
style={styles.bottomButtonView}
|
|
63
|
+
mainTitle={t('next')}
|
|
64
|
+
onPressMain={onNext}
|
|
65
|
+
typeMain={canSave ? 'primary' : 'disabled'}
|
|
66
|
+
/>
|
|
67
|
+
</View>
|
|
68
|
+
</TouchableWithoutFeedback>
|
|
69
|
+
</View>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default SetupScriptSms;
|
|
@@ -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 SetupScriptReceiverSms from '../SetupScriptReceiverSms';
|
|
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
|
+
<SetupScriptReceiverSms route={route} />
|
|
20
|
+
</SCProvider>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
describe('Test SetupScriptReceiverSms', () => {
|
|
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: { message: 'message' },
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const listUser = [
|
|
41
|
+
{
|
|
42
|
+
avatar: 'https://xxx',
|
|
43
|
+
phone_number: '0902xx',
|
|
44
|
+
id: 140,
|
|
45
|
+
name: 'User 1',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
avatar: null,
|
|
49
|
+
phone_number: 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('SetupScriptReceiverSms onPress create script sms 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_SMS(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('SetupScriptReceiverSms 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_SMS(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
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
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 SetupScriptSms from '../SetupScriptSms';
|
|
14
|
+
|
|
15
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
16
|
+
|
|
17
|
+
const wrapComponent = (route) => (
|
|
18
|
+
<SCProvider initState={mockSCStore({})}>
|
|
19
|
+
<SetupScriptSms route={route} />
|
|
20
|
+
</SCProvider>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
describe('Test SetupScriptSms', () => {
|
|
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 SMS success', async () => {
|
|
45
|
+
mock.onPost(API.AUTOMATE.ADD_SCRIPT_SMS(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(1);
|
|
52
|
+
|
|
53
|
+
const touchable = instance.findAllByType(TouchableWithoutFeedback);
|
|
54
|
+
await act(async () => {
|
|
55
|
+
touchable[0].props.onPress();
|
|
56
|
+
});
|
|
57
|
+
await act(async () => {
|
|
58
|
+
inputs[0].props.onChange('Message');
|
|
59
|
+
});
|
|
60
|
+
const button = instance.findByType(BottomButtonView);
|
|
61
|
+
await act(async () => {
|
|
62
|
+
button.props.onPressMain();
|
|
63
|
+
});
|
|
64
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.SetupScriptReceiverSms, {
|
|
65
|
+
automate: route.params.automate,
|
|
66
|
+
unitId: 1,
|
|
67
|
+
formData: { message: 'Message', unit: 1 },
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|