@eohjsc/react-native-smart-city 0.3.94 → 0.3.95
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 +1 -1
- package/src/commons/ActionGroup/OnOffTemplate/index.js +20 -17
- package/src/commons/ActionGroup/__test__/OnOffButtonTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +5 -24
- package/src/screens/ActivityLog/__test__/index.test.js +60 -2
- package/src/screens/ActivityLog/hooks/__test__/index.test.js +5 -0
- package/src/screens/ActivityLog/hooks/index.js +11 -0
- package/src/screens/AddLocationMaps/index.js +1 -1
- package/src/screens/AddNewGateway/ConnectingWifiDevice.js +6 -4
- package/src/screens/AddNewGateway/ConnectingWifiGuide.js +0 -1
- package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +1 -6
- package/src/screens/AddNewGateway/ShareWifiPassword.js +20 -3
- package/src/screens/AddNewGateway/__test__/ScanWifiDeviceQR.test.js +0 -10
- package/src/screens/AllGateway/GatewayInfo/index.js +3 -3
- package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +0 -1
- package/src/screens/Automate/MultiUnits.js +4 -0
- package/src/screens/Automate/__test__/MultiUnits.test.js +62 -2
- package/src/screens/Automate/__test__/index.test.js +51 -1
- package/src/screens/Automate/index.js +10 -1
- package/src/screens/SubUnit/AddSubUnit.js +1 -1
- package/src/screens/SubUnit/__test__/AddSubUnit.test.js +16 -3
- package/src/utils/I18n/translations/en.js +3 -3
- package/src/utils/I18n/translations/vi.js +3 -0
package/package.json
CHANGED
|
@@ -22,7 +22,7 @@ const getComponent = (template) => {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
const OnOffTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
25
|
+
const OnOffTemplate = memo(({ actionGroup = {}, doAction, sensor = {} }) => {
|
|
26
26
|
const { configuration = {} } = actionGroup;
|
|
27
27
|
const {
|
|
28
28
|
action_on_data,
|
|
@@ -41,6 +41,7 @@ const OnOffTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
41
41
|
|
|
42
42
|
// eslint-disable-next-line no-unused-vars
|
|
43
43
|
const [configValues, _] = useConfigGlobalState('configValues');
|
|
44
|
+
const { device_type, is_managed_by_backend } = sensor;
|
|
44
45
|
|
|
45
46
|
const getIsOnValue = useCallback(() => {
|
|
46
47
|
const configValue = configValues[config];
|
|
@@ -65,34 +66,36 @@ const OnOffTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
65
66
|
return;
|
|
66
67
|
}
|
|
67
68
|
let data;
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
if (
|
|
70
|
+
allow_config_store_value &&
|
|
71
|
+
config &&
|
|
72
|
+
device_type !== DEVICE_TYPE.GOOGLE_HOME
|
|
73
|
+
) {
|
|
71
74
|
data = {
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
config_id: config,
|
|
76
|
+
config_value: isOn ? 0 : 1,
|
|
74
77
|
};
|
|
75
|
-
if (allow_config_store_value && config) {
|
|
76
|
-
data.config_id = config;
|
|
77
|
-
data.config_value = data.value;
|
|
78
|
-
}
|
|
79
78
|
}
|
|
80
|
-
|
|
79
|
+
|
|
80
|
+
if (device_type === DEVICE_TYPE.LG_THINQ) {
|
|
81
81
|
setTempIsOn((prev) => !prev);
|
|
82
82
|
}
|
|
83
83
|
await doAction(action_data, data);
|
|
84
84
|
updateStatusFromPusher(); // todo Bang read about this magic
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
if (
|
|
87
|
+
is_managed_by_backend &&
|
|
87
88
|
config &&
|
|
88
|
-
|
|
89
|
+
device_type === DEVICE_TYPE.LG_THINQ
|
|
90
|
+
) {
|
|
89
91
|
watchMultiConfigs([config]);
|
|
92
|
+
}
|
|
90
93
|
}, [
|
|
91
94
|
isOn,
|
|
92
95
|
action_off_data,
|
|
93
96
|
action_on_data,
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
device_type,
|
|
98
|
+
is_managed_by_backend,
|
|
96
99
|
allow_config_store_value,
|
|
97
100
|
config,
|
|
98
101
|
doAction,
|
|
@@ -110,10 +113,10 @@ const OnOffTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
110
113
|
}, [isOn]);
|
|
111
114
|
|
|
112
115
|
useEffect(() => {
|
|
113
|
-
if (
|
|
116
|
+
if (device_type !== DEVICE_TYPE.LG_THINQ) {
|
|
114
117
|
setTempIsOn(getIsOnValue());
|
|
115
118
|
}
|
|
116
|
-
}, [getIsOnValue,
|
|
119
|
+
}, [getIsOnValue, device_type]);
|
|
117
120
|
|
|
118
121
|
const Component = useMemo(() => {
|
|
119
122
|
return getComponent(actionGroup.template);
|
|
@@ -122,7 +122,7 @@ describe('Test OneBigButtonTemplate', () => {
|
|
|
122
122
|
await act(async () => {
|
|
123
123
|
await button.props.onPress();
|
|
124
124
|
});
|
|
125
|
-
expect(mockDoAction).toHaveBeenCalledWith(action_data,
|
|
125
|
+
expect(mockDoAction).toHaveBeenCalledWith(action_data, undefined);
|
|
126
126
|
};
|
|
127
127
|
|
|
128
128
|
it('action state on', async () => {
|
|
@@ -163,10 +163,7 @@ describe('Test OnOffTemplate', () => {
|
|
|
163
163
|
await act(async () => {
|
|
164
164
|
await template.props.triggerAction();
|
|
165
165
|
});
|
|
166
|
-
expect(mockDoAction).toHaveBeenCalledWith(action_off_data,
|
|
167
|
-
value: 0,
|
|
168
|
-
state: 0,
|
|
169
|
-
});
|
|
166
|
+
expect(mockDoAction).toHaveBeenCalledWith(action_off_data, undefined);
|
|
170
167
|
expect(watchMultiConfigs).toBeCalledTimes(0);
|
|
171
168
|
});
|
|
172
169
|
|
|
@@ -183,10 +180,7 @@ describe('Test OnOffTemplate', () => {
|
|
|
183
180
|
await act(async () => {
|
|
184
181
|
await template.props.triggerAction();
|
|
185
182
|
});
|
|
186
|
-
expect(mockDoAction).toHaveBeenCalledWith(action_on_data,
|
|
187
|
-
value: 1,
|
|
188
|
-
state: 1,
|
|
189
|
-
});
|
|
183
|
+
expect(mockDoAction).toHaveBeenCalledWith(action_on_data, undefined);
|
|
190
184
|
});
|
|
191
185
|
|
|
192
186
|
it('template OnOffSimpleActionTemplate doAction with is_on_value and is_managed_by_backend', async () => {
|
|
@@ -201,10 +195,7 @@ describe('Test OnOffTemplate', () => {
|
|
|
201
195
|
await act(async () => {
|
|
202
196
|
await template.props.triggerAction();
|
|
203
197
|
});
|
|
204
|
-
expect(mockDoAction).toHaveBeenCalledWith(action_off_data,
|
|
205
|
-
value: 0,
|
|
206
|
-
state: 0,
|
|
207
|
-
});
|
|
198
|
+
expect(mockDoAction).toHaveBeenCalledWith(action_off_data, undefined);
|
|
208
199
|
expect(watchMultiConfigs).toBeCalledTimes(0);
|
|
209
200
|
});
|
|
210
201
|
|
|
@@ -231,10 +222,7 @@ describe('Test OnOffTemplate', () => {
|
|
|
231
222
|
await act(async () => {
|
|
232
223
|
await template[0].props.triggerAction();
|
|
233
224
|
});
|
|
234
|
-
expect(mockDoAction).toHaveBeenCalledWith(action_data,
|
|
235
|
-
state: 0,
|
|
236
|
-
value: 0,
|
|
237
|
-
});
|
|
225
|
+
expect(mockDoAction).toHaveBeenCalledWith(action_data, undefined);
|
|
238
226
|
});
|
|
239
227
|
|
|
240
228
|
it('render with template OnOffSimpleActionTemplate with just action_data lg_thinq', async () => {
|
|
@@ -269,10 +257,7 @@ describe('Test OnOffTemplate', () => {
|
|
|
269
257
|
await act(async () => {
|
|
270
258
|
jest.runAllTimers();
|
|
271
259
|
});
|
|
272
|
-
expect(mockDoAction).toHaveBeenCalledWith(action_data,
|
|
273
|
-
value: 0,
|
|
274
|
-
state: 0,
|
|
275
|
-
});
|
|
260
|
+
expect(mockDoAction).toHaveBeenCalledWith(action_data, undefined);
|
|
276
261
|
});
|
|
277
262
|
|
|
278
263
|
it('render with template OnOffSimpleActionTemplate with action_data zigbee trigger off', async () => {
|
|
@@ -303,10 +288,8 @@ describe('Test OnOffTemplate', () => {
|
|
|
303
288
|
await template[0].props.triggerAction();
|
|
304
289
|
});
|
|
305
290
|
expect(mockDoAction).toHaveBeenCalledWith(action_off_data, {
|
|
306
|
-
state: 0,
|
|
307
291
|
config_id: 5,
|
|
308
292
|
config_value: 0,
|
|
309
|
-
value: 0,
|
|
310
293
|
});
|
|
311
294
|
});
|
|
312
295
|
|
|
@@ -338,10 +321,8 @@ describe('Test OnOffTemplate', () => {
|
|
|
338
321
|
await template[0].props.triggerAction();
|
|
339
322
|
});
|
|
340
323
|
expect(mockDoAction).toHaveBeenCalledWith(action_on_data, {
|
|
341
|
-
state: 1, // todo Bang remove this after production
|
|
342
324
|
config_id: 5,
|
|
343
325
|
config_value: 1,
|
|
344
|
-
value: 1, // this is correct
|
|
345
326
|
});
|
|
346
327
|
});
|
|
347
328
|
|
|
@@ -33,8 +33,8 @@ jest.mock('react', () => {
|
|
|
33
33
|
|
|
34
34
|
const mock = new MockAdapter(api.axiosInstance);
|
|
35
35
|
|
|
36
|
-
const wrapComponent = (route) => (
|
|
37
|
-
<SCProvider initState={mockSCStore(
|
|
36
|
+
const wrapComponent = (route, storeData = {}) => (
|
|
37
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
38
38
|
<ActivityLog route={route} />
|
|
39
39
|
</SCProvider>
|
|
40
40
|
);
|
|
@@ -149,4 +149,62 @@ describe('Test Activity log', () => {
|
|
|
149
149
|
expect(filterPopup[0].props.isVisible).toBeTruthy();
|
|
150
150
|
expect(datePicker.props.isVisible).toBeFalsy();
|
|
151
151
|
});
|
|
152
|
+
|
|
153
|
+
const setUpActionLogScreen = () => {
|
|
154
|
+
route = {
|
|
155
|
+
params: {
|
|
156
|
+
id: 1,
|
|
157
|
+
type: 'action',
|
|
158
|
+
filterEnabled: {},
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
mock.onGet(API.DEVICE.ACTIVITY_LOG(1)).reply(200, {
|
|
163
|
+
results: [
|
|
164
|
+
{
|
|
165
|
+
id: 1,
|
|
166
|
+
content_code: 'ACTIVATED_BY',
|
|
167
|
+
params: { username: 'name' },
|
|
168
|
+
created_at: '2021-07-01T15:48:24.917932Z',
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
count: 1,
|
|
172
|
+
});
|
|
173
|
+
global.URLSearchParams = jest.fn(() => ({
|
|
174
|
+
append: jest.fn(),
|
|
175
|
+
}));
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
it('render action log has permission', async () => {
|
|
179
|
+
const storeData = {
|
|
180
|
+
auth: {
|
|
181
|
+
account: {
|
|
182
|
+
user: {
|
|
183
|
+
permissions: {
|
|
184
|
+
view_action_log: true,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
setUpActionLogScreen();
|
|
191
|
+
|
|
192
|
+
await act(async () => {
|
|
193
|
+
tree = await create(wrapComponent(route, storeData));
|
|
194
|
+
});
|
|
195
|
+
const instance = tree.root;
|
|
196
|
+
const items = instance.findAllByType(ItemLog);
|
|
197
|
+
expect(items).toHaveLength(1);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('render action log no permission', async () => {
|
|
201
|
+
setUpActionLogScreen();
|
|
202
|
+
|
|
203
|
+
await act(async () => {
|
|
204
|
+
tree = await create(wrapComponent(route));
|
|
205
|
+
});
|
|
206
|
+
const instance = tree.root;
|
|
207
|
+
const items = instance.findAllByType(ItemLog);
|
|
208
|
+
expect(items).toHaveLength(0);
|
|
209
|
+
});
|
|
152
210
|
});
|
|
@@ -7,6 +7,11 @@ import api from '../../../../utils/Apis/axios';
|
|
|
7
7
|
import { getDataForList, getEmergencyEventDataForList } from '../../utils';
|
|
8
8
|
|
|
9
9
|
const mock = new MockAdapter(api.axiosInstance);
|
|
10
|
+
jest.mock('../../../../utils/Permission/backend', () => ({
|
|
11
|
+
useBackendPermission: jest.fn(() => ({
|
|
12
|
+
view_action_log: true,
|
|
13
|
+
})),
|
|
14
|
+
}));
|
|
10
15
|
|
|
11
16
|
describe('Test useActivityLog', () => {
|
|
12
17
|
let props;
|
|
@@ -6,6 +6,8 @@ import API from '../../../configs/API';
|
|
|
6
6
|
import t from '../../../hooks/Common/useTranslations';
|
|
7
7
|
import { AUTOMATE_TYPE } from '../../../configs/Constants';
|
|
8
8
|
import { getDataForList, getEmergencyEventDataForList } from '../utils';
|
|
9
|
+
import { useBackendPermission } from '../../../utils/Permission/backend';
|
|
10
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
9
11
|
|
|
10
12
|
const apiMaps = {
|
|
11
13
|
['action']: {
|
|
@@ -13,6 +15,7 @@ const apiMaps = {
|
|
|
13
15
|
params: (id) => ({ id: id }),
|
|
14
16
|
standardizeData: getDataForList,
|
|
15
17
|
memberUrl: (id) => API.SHARE.UNITS_MEMBERS(id),
|
|
18
|
+
needPermission: 'view_action_log',
|
|
16
19
|
},
|
|
17
20
|
['emergency_event']: {
|
|
18
21
|
url: () => API.EMERGENCY_BUTTON.ACTIVITY_LOG(),
|
|
@@ -54,7 +57,15 @@ export default ({ id, type, share, filterEnabled }) => {
|
|
|
54
57
|
});
|
|
55
58
|
const api = apiMaps[type];
|
|
56
59
|
|
|
60
|
+
const permissions = useBackendPermission();
|
|
57
61
|
const fetchData = async (filters) => {
|
|
62
|
+
if (api?.needPermission && !permissions?.[api?.needPermission]) {
|
|
63
|
+
setIsLoading(false);
|
|
64
|
+
setIsRefreshing(false);
|
|
65
|
+
ToastBottomHelper.error(t(`no_permission_${api?.needPermission}`));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
58
69
|
const { page } = filters;
|
|
59
70
|
setPage(page);
|
|
60
71
|
if (page === 1) {
|
|
@@ -287,7 +287,7 @@ const AddLocationMaps = memo(() => {
|
|
|
287
287
|
onPressMain={onDone}
|
|
288
288
|
secondaryTitle={t('cancel')}
|
|
289
289
|
onPressSecondary={goBack}
|
|
290
|
-
typeMain={
|
|
290
|
+
typeMain={searchedLocation?.description ? 'primaryText' : 'disabled'}
|
|
291
291
|
typeSecondary="primaryText"
|
|
292
292
|
accessibilityLabelPrefix="LOCATION_"
|
|
293
293
|
disableBackgroundMainButton
|
|
@@ -12,7 +12,7 @@ let isCallingAPI = false;
|
|
|
12
12
|
|
|
13
13
|
const ConnectingWifiDevice = ({ route }) => {
|
|
14
14
|
const t = useTranslations();
|
|
15
|
-
const { unit, subUnit, gateway, selectedWifi, qrData, addDeviceType } =
|
|
15
|
+
const { unit, subUnit, gateway, selectedWifi, qrData, addDeviceType, code } =
|
|
16
16
|
route?.params || {};
|
|
17
17
|
const { goBack } = useNavigation();
|
|
18
18
|
|
|
@@ -40,7 +40,8 @@ const ConnectingWifiDevice = ({ route }) => {
|
|
|
40
40
|
const { success, problem, data } = await axiosPost(
|
|
41
41
|
API.UNIT.CHIP_SCAN(unit?.id),
|
|
42
42
|
{
|
|
43
|
-
|
|
43
|
+
code,
|
|
44
|
+
host: qrData?.host,
|
|
44
45
|
secret: qrData?.secret,
|
|
45
46
|
name: gateway?.model,
|
|
46
47
|
station: subUnit?.id,
|
|
@@ -61,9 +62,10 @@ const ConnectingWifiDevice = ({ route }) => {
|
|
|
61
62
|
},
|
|
62
63
|
[
|
|
63
64
|
unit?.id,
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
code,
|
|
66
|
+
qrData?.host,
|
|
66
67
|
qrData?.secret,
|
|
68
|
+
gateway?.model,
|
|
67
69
|
subUnit?.id,
|
|
68
70
|
selectedWifi.ssid,
|
|
69
71
|
selectedWifi.password,
|
|
@@ -124,7 +124,6 @@ const ConnectingWifiGuide = ({ route }) => {
|
|
|
124
124
|
socket = dgram.createSocket({ type: 'udp4' });
|
|
125
125
|
socket.bind(54321);
|
|
126
126
|
}
|
|
127
|
-
|
|
128
127
|
socket.on('message', (msg, rinfo) => {
|
|
129
128
|
const data = JSON.parse(msg.toString());
|
|
130
129
|
if (Object.prototype.hasOwnProperty.call(data, 'wifi')) {
|
|
@@ -9,7 +9,6 @@ const ScanWifiDeviceQR = memo(({ route }) => {
|
|
|
9
9
|
const { unit, subUnit } = route?.params || {};
|
|
10
10
|
const [isInvalidQrCode, setIsInvalidQrCode] = useState(false);
|
|
11
11
|
const { navigate, goBack } = useNavigation();
|
|
12
|
-
|
|
13
12
|
const onScan = useCallback(
|
|
14
13
|
(body, setLoading) => {
|
|
15
14
|
let data;
|
|
@@ -20,11 +19,7 @@ const ScanWifiDeviceQR = memo(({ route }) => {
|
|
|
20
19
|
setLoading(false);
|
|
21
20
|
return;
|
|
22
21
|
}
|
|
23
|
-
|
|
24
|
-
setIsInvalidQrCode(true);
|
|
25
|
-
setLoading(false);
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
22
|
+
|
|
28
23
|
navigate(Routes.ConnectingWifiGuide, {
|
|
29
24
|
unit,
|
|
30
25
|
subUnit,
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useRef,
|
|
4
|
+
useState,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import {
|
|
3
9
|
Alert,
|
|
4
10
|
TouchableOpacity,
|
|
@@ -9,6 +15,7 @@ import {
|
|
|
9
15
|
import dgram from 'react-native-udp';
|
|
10
16
|
import { useNavigation, useIsFocused } from '@react-navigation/native';
|
|
11
17
|
import LottieView from 'lottie-react-native';
|
|
18
|
+
import uuid from 'uuid';
|
|
12
19
|
|
|
13
20
|
import { ToastBottomHelper } from '../../utils/Utils';
|
|
14
21
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
@@ -68,6 +75,10 @@ const ShareWifiPassword = ({ route }) => {
|
|
|
68
75
|
const [isDisabled, setIsDisabled] = useState(false);
|
|
69
76
|
const [dataGateway, setDataGateway] = useState({ gateway: [], error: '' });
|
|
70
77
|
|
|
78
|
+
const code = useMemo(() => {
|
|
79
|
+
return uuid.v4();
|
|
80
|
+
}, []);
|
|
81
|
+
|
|
71
82
|
const hidePopupPassword = useCallback(() => {
|
|
72
83
|
setIsShowPopupPassword(false);
|
|
73
84
|
}, []);
|
|
@@ -80,7 +91,11 @@ const ShareWifiPassword = ({ route }) => {
|
|
|
80
91
|
socket.send(
|
|
81
92
|
JSON.stringify({
|
|
82
93
|
type: 'connect',
|
|
83
|
-
data: {
|
|
94
|
+
data: {
|
|
95
|
+
token: code,
|
|
96
|
+
host: qrData?.host,
|
|
97
|
+
wifi: { ssid: selectedWifi, pass: selectedWifiPassword },
|
|
98
|
+
},
|
|
84
99
|
}),
|
|
85
100
|
undefined,
|
|
86
101
|
undefined,
|
|
@@ -94,7 +109,7 @@ const ShareWifiPassword = ({ route }) => {
|
|
|
94
109
|
}
|
|
95
110
|
}, 1000);
|
|
96
111
|
},
|
|
97
|
-
[
|
|
112
|
+
[code, qrData?.host, selectedWifi, selectedWifiPassword]
|
|
98
113
|
);
|
|
99
114
|
|
|
100
115
|
const isWrongPassword = useRef(true);
|
|
@@ -197,6 +212,7 @@ const ShareWifiPassword = ({ route }) => {
|
|
|
197
212
|
password: selectedWifiPassword,
|
|
198
213
|
},
|
|
199
214
|
addDeviceType,
|
|
215
|
+
code,
|
|
200
216
|
});
|
|
201
217
|
}
|
|
202
218
|
}, 800);
|
|
@@ -223,6 +239,7 @@ const ShareWifiPassword = ({ route }) => {
|
|
|
223
239
|
t,
|
|
224
240
|
wifiList,
|
|
225
241
|
unit,
|
|
242
|
+
code,
|
|
226
243
|
]);
|
|
227
244
|
|
|
228
245
|
return (
|
|
@@ -5,7 +5,6 @@ import ScanWifiDeviceQR from '../ScanWifiDeviceQR';
|
|
|
5
5
|
import { SCProvider } from '../../../context';
|
|
6
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
7
7
|
import QRScan from '../../ScanChipQR/components/QRScan';
|
|
8
|
-
import { getTranslate } from '../../../utils/I18n';
|
|
9
8
|
import Routes from '../../../utils/Route';
|
|
10
9
|
|
|
11
10
|
const mockedGoBack = jest.fn();
|
|
@@ -54,15 +53,6 @@ describe('test scan wifi device QR', () => {
|
|
|
54
53
|
});
|
|
55
54
|
};
|
|
56
55
|
|
|
57
|
-
it('on scan wrong QR code', async () => {
|
|
58
|
-
await scanQRCode({ imei: 'SAMSUNG-xxx' });
|
|
59
|
-
const instance = tree.root;
|
|
60
|
-
const bottomSheet = instance.findByProps({
|
|
61
|
-
title: getTranslate('en', 'invalid_qr_code'),
|
|
62
|
-
});
|
|
63
|
-
expect(bottomSheet.props.isVisible).toBe(true);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
56
|
it('on scan correct QR code', async () => {
|
|
67
57
|
await scanQRCode({ prefix: 'robot', org_slug: 'eoh' }, jest.fn());
|
|
68
58
|
expect(mockedNavigate).toHaveBeenCalled();
|
|
@@ -36,7 +36,7 @@ const GatewayInfo = () => {
|
|
|
36
36
|
date_install = '',
|
|
37
37
|
expired_at = '',
|
|
38
38
|
firmware = {},
|
|
39
|
-
|
|
39
|
+
code = '',
|
|
40
40
|
arduino_gateway = undefined,
|
|
41
41
|
modbus_gateway = undefined,
|
|
42
42
|
zigbee_gateway = undefined,
|
|
@@ -81,7 +81,7 @@ const GatewayInfo = () => {
|
|
|
81
81
|
{
|
|
82
82
|
id: 5,
|
|
83
83
|
title: 'auth_token',
|
|
84
|
-
data:
|
|
84
|
+
data: code || '--',
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
87
|
id: 7,
|
|
@@ -105,7 +105,7 @@ const GatewayInfo = () => {
|
|
|
105
105
|
expired_at,
|
|
106
106
|
firmware?.board,
|
|
107
107
|
id,
|
|
108
|
-
|
|
108
|
+
code,
|
|
109
109
|
wifi_ssid,
|
|
110
110
|
]
|
|
111
111
|
);
|
|
@@ -172,7 +172,6 @@ const SetupConfigCondition = () => {
|
|
|
172
172
|
style={styles.modal}
|
|
173
173
|
>
|
|
174
174
|
<View style={styles.modalContent}>
|
|
175
|
-
<Text type="H3">{t('select_condition')}</Text>
|
|
176
175
|
{conditionOptions.map((option, index) => (
|
|
177
176
|
<React.Fragment key={index}>
|
|
178
177
|
<TouchableOpacity
|
|
@@ -81,6 +81,9 @@ const MultiUnits = () => {
|
|
|
81
81
|
ToastBottomHelper.error(t('reach_max_automations_per_unit'));
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
|
+
} else if (!permissions?.smart_script_for_multi_unit) {
|
|
85
|
+
ToastBottomHelper.error(t('no_permission_smart_script_for_multi_unit'));
|
|
86
|
+
return;
|
|
84
87
|
}
|
|
85
88
|
if (tabActive === AUTOMATE_TABS.SCENARIO) {
|
|
86
89
|
navigate(Routes.UnitStack, {
|
|
@@ -105,6 +108,7 @@ const MultiUnits = () => {
|
|
|
105
108
|
data.length,
|
|
106
109
|
navigate,
|
|
107
110
|
permissions?.max_automations_per_unit,
|
|
111
|
+
permissions?.smart_script_for_multi_unit,
|
|
108
112
|
t,
|
|
109
113
|
tabActive,
|
|
110
114
|
unit?.id,
|
|
@@ -80,7 +80,19 @@ describe('Test MultiUnits', () => {
|
|
|
80
80
|
},
|
|
81
81
|
});
|
|
82
82
|
await act(async () => {
|
|
83
|
-
tree = await create(
|
|
83
|
+
tree = await create(
|
|
84
|
+
wrapComponent({
|
|
85
|
+
auth: {
|
|
86
|
+
account: {
|
|
87
|
+
user: {
|
|
88
|
+
permissions: {
|
|
89
|
+
smart_script_for_multi_unit: true,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
);
|
|
84
96
|
});
|
|
85
97
|
const instance = tree.root;
|
|
86
98
|
const WrapHeaderScrollables = instance.findAllByType(WrapHeaderScrollable);
|
|
@@ -157,7 +169,19 @@ describe('Test MultiUnits', () => {
|
|
|
157
169
|
},
|
|
158
170
|
});
|
|
159
171
|
await act(async () => {
|
|
160
|
-
tree = await create(
|
|
172
|
+
tree = await create(
|
|
173
|
+
wrapComponent({
|
|
174
|
+
auth: {
|
|
175
|
+
account: {
|
|
176
|
+
user: {
|
|
177
|
+
permissions: {
|
|
178
|
+
smart_script_for_multi_unit: true,
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
})
|
|
184
|
+
);
|
|
161
185
|
});
|
|
162
186
|
const instance = tree.root;
|
|
163
187
|
const WrapHeaderScrollables = instance.findAllByType(WrapHeaderScrollable);
|
|
@@ -232,6 +256,42 @@ describe('Test MultiUnits', () => {
|
|
|
232
256
|
);
|
|
233
257
|
});
|
|
234
258
|
|
|
259
|
+
it('create new smart multi unit but missing permission', async () => {
|
|
260
|
+
mock.onGet(API.UNIT.AUTOMATE(1)).reply(200, []);
|
|
261
|
+
useRoute.mockReturnValue({
|
|
262
|
+
params: {
|
|
263
|
+
isMultiUnits: true,
|
|
264
|
+
unitName: null,
|
|
265
|
+
unit: null,
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
await act(async () => {
|
|
269
|
+
tree = await create(
|
|
270
|
+
wrapComponent({
|
|
271
|
+
auth: {
|
|
272
|
+
account: {
|
|
273
|
+
user: {
|
|
274
|
+
permissions: {
|
|
275
|
+
smart_script_for_multi_unit: false,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
})
|
|
281
|
+
);
|
|
282
|
+
});
|
|
283
|
+
const instance = tree.root;
|
|
284
|
+
const itemAddNews = instance.findAllByType(ItemAddNew);
|
|
285
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
286
|
+
await act(async () => {
|
|
287
|
+
itemAddNews[0].props.onAddNew();
|
|
288
|
+
});
|
|
289
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
290
|
+
expect(spyToastError).toBeCalledWith(
|
|
291
|
+
getTranslate('en', 'no_permission_smart_script_for_multi_unit')
|
|
292
|
+
);
|
|
293
|
+
});
|
|
294
|
+
|
|
235
295
|
it('Test is not multi unit', async () => {
|
|
236
296
|
useRoute.mockReturnValue({
|
|
237
297
|
params: {
|
|
@@ -81,7 +81,19 @@ describe('Test Automate', () => {
|
|
|
81
81
|
mock.onGet(API.AUTOMATE.GET_SMART()).reply(200, response.data);
|
|
82
82
|
|
|
83
83
|
await act(async () => {
|
|
84
|
-
tree = await create(
|
|
84
|
+
tree = await create(
|
|
85
|
+
wrapComponent({
|
|
86
|
+
auth: {
|
|
87
|
+
account: {
|
|
88
|
+
user: {
|
|
89
|
+
permissions: {
|
|
90
|
+
smart_script_for_multi_unit: true,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
);
|
|
85
97
|
});
|
|
86
98
|
|
|
87
99
|
const instance = tree.root;
|
|
@@ -245,4 +257,42 @@ describe('Test Automate', () => {
|
|
|
245
257
|
unit: { id: 3, name: 'La Vida' },
|
|
246
258
|
});
|
|
247
259
|
});
|
|
260
|
+
|
|
261
|
+
it('onPress onAddNew multi unit script but missing permission', async () => {
|
|
262
|
+
mock.onGet(API.AUTOMATE.GET_SMART()).reply(200, [
|
|
263
|
+
{
|
|
264
|
+
type: 'MultiUnit',
|
|
265
|
+
unit_id: null,
|
|
266
|
+
automates: [],
|
|
267
|
+
},
|
|
268
|
+
]);
|
|
269
|
+
|
|
270
|
+
await act(async () => {
|
|
271
|
+
tree = await create(
|
|
272
|
+
wrapComponent({
|
|
273
|
+
auth: {
|
|
274
|
+
account: {
|
|
275
|
+
user: {
|
|
276
|
+
permissions: {
|
|
277
|
+
smart_script_for_multi_unit: false,
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
})
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const instance = tree.root;
|
|
287
|
+
|
|
288
|
+
const itemAddNew = instance.findByType(ItemAddNew);
|
|
289
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
290
|
+
await act(async () => {
|
|
291
|
+
itemAddNew.props.onAddNew(1, []);
|
|
292
|
+
});
|
|
293
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
294
|
+
expect(spyToastError).toBeCalledWith(
|
|
295
|
+
getTranslate('en', 'no_permission_smart_script_for_multi_unit')
|
|
296
|
+
);
|
|
297
|
+
});
|
|
248
298
|
});
|
|
@@ -88,6 +88,9 @@ const Automate = () => {
|
|
|
88
88
|
ToastBottomHelper.error(t('reach_max_automations_per_unit'));
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
|
+
} else if (!permissions?.smart_script_for_multi_unit) {
|
|
92
|
+
ToastBottomHelper.error(t('no_permission_smart_script_for_multi_unit'));
|
|
93
|
+
return;
|
|
91
94
|
}
|
|
92
95
|
navigate(Routes.UnitStack, {
|
|
93
96
|
screen: Routes.AddUnknownTypeSmart,
|
|
@@ -97,7 +100,13 @@ const Automate = () => {
|
|
|
97
100
|
},
|
|
98
101
|
});
|
|
99
102
|
},
|
|
100
|
-
[
|
|
103
|
+
[
|
|
104
|
+
currentRouteName,
|
|
105
|
+
navigate,
|
|
106
|
+
permissions?.max_automations_per_unit,
|
|
107
|
+
permissions?.smart_script_for_multi_unit,
|
|
108
|
+
t,
|
|
109
|
+
]
|
|
101
110
|
);
|
|
102
111
|
|
|
103
112
|
const onPressArrowRight = useCallback(
|
|
@@ -163,7 +163,7 @@ const AddSubUnit = ({ route }) => {
|
|
|
163
163
|
|
|
164
164
|
const validateData = useMemo(() => {
|
|
165
165
|
if (isAddUnit) {
|
|
166
|
-
return roomName === '' || wallpaper === '' || location.description
|
|
166
|
+
return roomName === '' || wallpaper === '' || !location.description;
|
|
167
167
|
} else {
|
|
168
168
|
return roomName === '' || wallpaper === '';
|
|
169
169
|
}
|
|
@@ -62,6 +62,9 @@ describe('Test AddSubUnit', () => {
|
|
|
62
62
|
unit: {
|
|
63
63
|
id: 1,
|
|
64
64
|
name: 'Unit name',
|
|
65
|
+
location: {
|
|
66
|
+
description: 'location',
|
|
67
|
+
},
|
|
65
68
|
},
|
|
66
69
|
},
|
|
67
70
|
};
|
|
@@ -187,7 +190,9 @@ describe('Test AddSubUnit', () => {
|
|
|
187
190
|
it('test create Unit', async () => {
|
|
188
191
|
route.params = {
|
|
189
192
|
...route.params,
|
|
190
|
-
location:
|
|
193
|
+
location: {
|
|
194
|
+
description: 'Unit address',
|
|
195
|
+
},
|
|
191
196
|
isAddUnit: true,
|
|
192
197
|
};
|
|
193
198
|
mock.onPost(API.UNIT.CREATE_UNIT()).reply(200, {
|
|
@@ -231,7 +236,9 @@ describe('Test AddSubUnit', () => {
|
|
|
231
236
|
it('test create Unit Fail', async () => {
|
|
232
237
|
route.params = {
|
|
233
238
|
...route.params,
|
|
234
|
-
location:
|
|
239
|
+
location: {
|
|
240
|
+
description: 'Unit address',
|
|
241
|
+
},
|
|
235
242
|
isAddUnit: true,
|
|
236
243
|
};
|
|
237
244
|
mock.onPost(API.UNIT.CREATE_UNIT()).reply(400);
|
|
@@ -270,7 +277,13 @@ describe('Test AddSubUnit', () => {
|
|
|
270
277
|
isAddSubUnit: true,
|
|
271
278
|
routeName: 'DashboardStack',
|
|
272
279
|
stationId: undefined,
|
|
273
|
-
unitData: {
|
|
280
|
+
unitData: {
|
|
281
|
+
id: 1,
|
|
282
|
+
name: 'Unit name',
|
|
283
|
+
location: {
|
|
284
|
+
description: 'location',
|
|
285
|
+
},
|
|
286
|
+
},
|
|
274
287
|
unitId: 1,
|
|
275
288
|
},
|
|
276
289
|
});
|
|
@@ -1126,9 +1126,6 @@ export default {
|
|
|
1126
1126
|
'To give you a good experience, you need to know the name and password of the wifi network and make sure the ' +
|
|
1127
1127
|
'device is placed in a good location.',
|
|
1128
1128
|
warning_beta_test_feature: 'This feature is in beta test, not official yet',
|
|
1129
|
-
connecting_gateway_warning_1:
|
|
1130
|
-
"By continuing, {appName} needs to connect to the device's wifi.",
|
|
1131
|
-
connecting_gateway_warning_2: 'A message will appear asking you to connect.',
|
|
1132
1129
|
remove_account: 'Remove Account',
|
|
1133
1130
|
brightness: 'Brightness',
|
|
1134
1131
|
tap_to_add_new_schedule: 'Tap + to add new schedule',
|
|
@@ -1406,4 +1403,7 @@ export default {
|
|
|
1406
1403
|
no_permission_plug_and_play_wifi: "You don't have permission to add wifi",
|
|
1407
1404
|
no_permission_plug_and_play_gateway:
|
|
1408
1405
|
"You don't have permission to add gateway",
|
|
1406
|
+
no_permission_smart_script_for_multi_unit:
|
|
1407
|
+
"You don't have permission to access feature Smart script for Multi Unit",
|
|
1408
|
+
no_permission_view_action_log: "You don't have permission to view action log",
|
|
1409
1409
|
};
|
|
@@ -1408,4 +1408,7 @@ export default {
|
|
|
1408
1408
|
no_permission_plug_and_play_zigbee: 'Không có quyền kết nối tự động zigbee',
|
|
1409
1409
|
no_permission_plug_and_play_wifi: 'Không có quyền kết nối tự động wifi',
|
|
1410
1410
|
no_permission_plug_and_play_gateway: 'Không có quyền kết nối tự động gateway',
|
|
1411
|
+
no_permission_smart_script_for_multi_unit:
|
|
1412
|
+
'Không có quyền truy cập tính năng Kịch bản thông minh liên quan đến nhiều địa điểm',
|
|
1413
|
+
no_permission_view_action_log: 'Không có quyền xem lịch sử hoạt dộng',
|
|
1411
1414
|
};
|