@eohjsc/react-native-smart-city 0.7.18 → 0.7.20
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/SelectGateway/index.js +3 -1
- package/src/screens/AddNewGateway/ScanDeviceLocal.js +15 -14
- package/src/screens/AddNewGateway/__test__/ScanDeviceLocal.test.js +51 -1
- package/src/screens/AddNewGateway/hooks/useConnectDevice.js +11 -9
- package/src/screens/AllGateway/DeviceInternalDetail/__test__/index.test.js +28 -0
- package/src/screens/AllGateway/DeviceModbusDetail/__test__/index.test.js +1 -1
- package/src/screens/AllGateway/__test__/index.test.js +19 -0
- package/src/screens/AllGateway/hooks/useGateway.js +16 -9
- package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +1 -0
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +8 -1
- package/src/screens/Automate/ScriptDetail/index.js +46 -35
- package/src/utils/I18n/translations/en.js +3 -0
- package/src/utils/I18n/translations/vi.js +3 -0
package/package.json
CHANGED
|
@@ -30,12 +30,18 @@ import styles from './ScanDeviceLocalStyles';
|
|
|
30
30
|
|
|
31
31
|
let zeroconf;
|
|
32
32
|
|
|
33
|
-
const DeviceItem = ({
|
|
33
|
+
const DeviceItem = ({
|
|
34
|
+
item,
|
|
35
|
+
selectedDevice,
|
|
36
|
+
setSelectedDevice,
|
|
37
|
+
fetchDeviceInfo,
|
|
38
|
+
}) => {
|
|
34
39
|
const handleSelectDevice = useCallback(
|
|
35
40
|
(device) => {
|
|
36
41
|
setSelectedDevice(device);
|
|
42
|
+
fetchDeviceInfo(device?.host);
|
|
37
43
|
},
|
|
38
|
-
[setSelectedDevice]
|
|
44
|
+
[setSelectedDevice, fetchDeviceInfo]
|
|
39
45
|
);
|
|
40
46
|
|
|
41
47
|
return (
|
|
@@ -69,9 +75,8 @@ const ScanDeviceLocal = ({ route }) => {
|
|
|
69
75
|
const [selectedDevice, setSelectedDevice] = useState();
|
|
70
76
|
const [isShowLoading, setIsShowLoading] = useState(false);
|
|
71
77
|
|
|
72
|
-
const { deviceInfo, fetchDeviceInfo, sendConfigToDevice } =
|
|
73
|
-
|
|
74
|
-
);
|
|
78
|
+
const { deviceInfo, fetchDeviceInfo, sendConfigToDevice } =
|
|
79
|
+
useConnectDevice();
|
|
75
80
|
|
|
76
81
|
const code = useMemo(() => {
|
|
77
82
|
return uuidv4();
|
|
@@ -107,7 +112,7 @@ const ScanDeviceLocal = ({ route }) => {
|
|
|
107
112
|
|
|
108
113
|
const onConnectingDevice = useCallback(async () => {
|
|
109
114
|
setIsShowLoading(true);
|
|
110
|
-
const success = await sendConfigToDevice({
|
|
115
|
+
const success = await sendConfigToDevice(selectedDevice?.host, {
|
|
111
116
|
token: code,
|
|
112
117
|
host: detailChipQr?.host,
|
|
113
118
|
port: detailChipQr?.port,
|
|
@@ -126,6 +131,7 @@ const ScanDeviceLocal = ({ route }) => {
|
|
|
126
131
|
code,
|
|
127
132
|
subUnit,
|
|
128
133
|
deviceInfo?.type,
|
|
134
|
+
selectedDevice?.host,
|
|
129
135
|
detailChipQr,
|
|
130
136
|
t,
|
|
131
137
|
sendConfigToDevice,
|
|
@@ -138,12 +144,13 @@ const ScanDeviceLocal = ({ route }) => {
|
|
|
138
144
|
return (
|
|
139
145
|
<DeviceItem
|
|
140
146
|
item={item}
|
|
141
|
-
setSelectedDevice={setSelectedDevice}
|
|
142
147
|
selectedDevice={selectedDevice}
|
|
148
|
+
setSelectedDevice={setSelectedDevice}
|
|
149
|
+
fetchDeviceInfo={fetchDeviceInfo}
|
|
143
150
|
/>
|
|
144
151
|
);
|
|
145
152
|
},
|
|
146
|
-
[selectedDevice, setSelectedDevice]
|
|
153
|
+
[selectedDevice, setSelectedDevice, fetchDeviceInfo]
|
|
147
154
|
);
|
|
148
155
|
|
|
149
156
|
const handleGoBack = useCallback(() => {
|
|
@@ -202,12 +209,6 @@ const ScanDeviceLocal = ({ route }) => {
|
|
|
202
209
|
};
|
|
203
210
|
}, []);
|
|
204
211
|
|
|
205
|
-
useEffect(() => {
|
|
206
|
-
if (selectedDevice) {
|
|
207
|
-
fetchDeviceInfo();
|
|
208
|
-
}
|
|
209
|
-
}, [selectedDevice, fetchDeviceInfo]);
|
|
210
|
-
|
|
211
212
|
useEffect(() => {
|
|
212
213
|
if (deviceInfo) {
|
|
213
214
|
fetchChipQrDetail(deviceInfo?.secret);
|
|
@@ -93,7 +93,7 @@ describe('test ScanDeviceLocal', () => {
|
|
|
93
93
|
await viewButtonBottom.props.onRightClick();
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
-
expect(deviceApi.
|
|
96
|
+
expect(deviceApi.getBaseURL()).toBe(`http://${resolvedDevice.host}/api`);
|
|
97
97
|
|
|
98
98
|
expect(zeroconfMock.on).toHaveBeenCalledWith(
|
|
99
99
|
'resolved',
|
|
@@ -259,6 +259,56 @@ describe('test ScanDeviceLocal', () => {
|
|
|
259
259
|
|
|
260
260
|
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
261
261
|
expect(viewButtonBottom.props.rightDisabled).toBeTruthy();
|
|
262
|
+
expect(spyToastError).toHaveBeenCalledWith(
|
|
263
|
+
getTranslate('en', 'cannot_fetch_data_from_device')
|
|
264
|
+
);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('test disable connect button when fetch chip qr info error', async () => {
|
|
268
|
+
const resolvedDevice = {
|
|
269
|
+
host: 'host-1.lan',
|
|
270
|
+
name: 'Device 1',
|
|
271
|
+
type: 'end_device',
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
mock.onGet(API.DEV_MODE.CHIP_QR_CODE.DETAIL_BY_SECRET()).reply(400);
|
|
275
|
+
mockDeviceApi.onGet(DEVICEAPI.BOARD.DETAIL()).reply(200, {
|
|
276
|
+
name: resolvedDevice.name,
|
|
277
|
+
type: resolvedDevice.type,
|
|
278
|
+
secret: '123456',
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const route = { params: { unit: 1 } };
|
|
282
|
+
await act(async () => {
|
|
283
|
+
tree = await renderer.create(wrapComponent(route));
|
|
284
|
+
});
|
|
285
|
+
const instance = tree.root;
|
|
286
|
+
|
|
287
|
+
const resolvedCallback = zeroconfMock.on.mock.calls.find(
|
|
288
|
+
(call) => call[0] === 'resolved'
|
|
289
|
+
)[1];
|
|
290
|
+
await act(async () => {
|
|
291
|
+
await resolvedCallback(resolvedDevice);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
const flatList = instance.findByType(FlatList);
|
|
295
|
+
expect(flatList.props.data).toEqual([resolvedDevice]);
|
|
296
|
+
await act(async () => {
|
|
297
|
+
await flatList.props.renderItem({ item: resolvedDevice });
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Select first device
|
|
301
|
+
const touchable = flatList.findAllByType(TouchableOpacity);
|
|
302
|
+
expect(touchable).toHaveLength(1);
|
|
303
|
+
await act(async () => {
|
|
304
|
+
await touchable[0].props.onPress();
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
308
|
+
expect(viewButtonBottom.props.rightDisabled).toBeTruthy();
|
|
309
|
+
expect(spyToastError).toHaveBeenCalledWith(
|
|
310
|
+
getTranslate('en', 'chip_qr_not_found')
|
|
311
|
+
);
|
|
262
312
|
});
|
|
263
313
|
|
|
264
314
|
it('test handle connecting device error', async () => {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { create } from 'apisauce';
|
|
2
|
-
import { useState, useCallback
|
|
2
|
+
import { useState, useCallback } from 'react';
|
|
3
3
|
|
|
4
4
|
import { API } from '../configs/API';
|
|
5
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
6
|
+
import t from '../../../hooks/Common/useTranslations';
|
|
5
7
|
|
|
6
8
|
export const api = create({
|
|
7
9
|
timeout: 10000,
|
|
@@ -10,15 +12,11 @@ export const api = create({
|
|
|
10
12
|
},
|
|
11
13
|
});
|
|
12
14
|
|
|
13
|
-
export const useConnectDevice = (
|
|
15
|
+
export const useConnectDevice = () => {
|
|
14
16
|
const [deviceInfo, setDeviceInfo] = useState();
|
|
15
17
|
const [listWiFiDevice, setListWiFiDevice] = useState([]);
|
|
16
18
|
const [lastError, setLastError] = useState();
|
|
17
19
|
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
api.baseURL = `http://${host}/api`;
|
|
20
|
-
}, [host]);
|
|
21
|
-
|
|
22
20
|
const parseResponse = (response, setInfo) => {
|
|
23
21
|
if (response.data?.status === 'error') {
|
|
24
22
|
setLastError(response.data?.message);
|
|
@@ -26,23 +24,27 @@ export const useConnectDevice = (host) => {
|
|
|
26
24
|
}
|
|
27
25
|
if (!response.ok) {
|
|
28
26
|
setLastError(response.problem);
|
|
27
|
+
setInfo && ToastBottomHelper.error(t('cannot_fetch_data_from_device'));
|
|
29
28
|
return false;
|
|
30
29
|
}
|
|
31
30
|
setInfo && setInfo(response.data);
|
|
32
31
|
return true;
|
|
33
32
|
};
|
|
34
33
|
|
|
35
|
-
const fetchDeviceInfo = useCallback(async () => {
|
|
34
|
+
const fetchDeviceInfo = useCallback(async (host) => {
|
|
35
|
+
api.setBaseURL(`http://${host}/api`);
|
|
36
36
|
const response = await api.get(API.BOARD.DETAIL());
|
|
37
37
|
return parseResponse(response, setDeviceInfo);
|
|
38
38
|
}, []);
|
|
39
39
|
|
|
40
|
-
const fetchListWiFiDevice = useCallback(async () => {
|
|
40
|
+
const fetchListWiFiDevice = useCallback(async (host) => {
|
|
41
|
+
api.setBaseURL(`http://${host}/api`);
|
|
41
42
|
const response = await api.get(API.BOARD.SCAN_WIFI());
|
|
42
43
|
return parseResponse(response, setListWiFiDevice);
|
|
43
44
|
}, []);
|
|
44
45
|
|
|
45
|
-
const sendConfigToDevice = useCallback(async (config) => {
|
|
46
|
+
const sendConfigToDevice = useCallback(async (host, config) => {
|
|
47
|
+
api.setBaseURL(`http://${host}/api`);
|
|
46
48
|
const response = await api.post(API.BOARD.CONFIG(), config);
|
|
47
49
|
return parseResponse(response);
|
|
48
50
|
}, []);
|
|
@@ -179,6 +179,34 @@ describe('Test DeviceInternalDetail', () => {
|
|
|
179
179
|
});
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
+
it('test render DeviceInternalDetail onPress more and onPress Delete internal failure', async () => {
|
|
183
|
+
await act(async () => {
|
|
184
|
+
tree = await create(wrapComponent());
|
|
185
|
+
});
|
|
186
|
+
const instance = tree.root;
|
|
187
|
+
const detail = instance?.findByType(Detail);
|
|
188
|
+
await headerCustomOnPressMore(detail);
|
|
189
|
+
const menuActionMore = detail?.findByType(MenuActionMore);
|
|
190
|
+
expect(menuActionMore.props.isVisible).toEqual(true);
|
|
191
|
+
await act(async () => {
|
|
192
|
+
menuActionMore.props.listMenuItem[1].doAction();
|
|
193
|
+
});
|
|
194
|
+
const modal = instance.findByType(ModalPopupCT);
|
|
195
|
+
|
|
196
|
+
mock.onDelete(API.DEV_MODE.ARDUINO.DEVICE_DETAIL(1, 1)).reply(400);
|
|
197
|
+
await act(async () => {
|
|
198
|
+
await modal.props.onPressConfirm();
|
|
199
|
+
});
|
|
200
|
+
expect(global.mockedPop).not.toHaveBeenCalled();
|
|
201
|
+
expect(Toast.show).toHaveBeenCalledWith({
|
|
202
|
+
position: 'bottom',
|
|
203
|
+
text1: 'CLIENT_ERROR',
|
|
204
|
+
text2: undefined,
|
|
205
|
+
type: 'error',
|
|
206
|
+
visibilityTime: 1000,
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
182
210
|
it('test render DeviceInternalDetail onPress TabPanel config write', async () => {
|
|
183
211
|
mock
|
|
184
212
|
.onGet(API.DEV_MODE.ARDUINO.CONFIG_PINS(1, 1))
|
|
@@ -137,7 +137,7 @@ describe('Test DeviceModbusDetail', () => {
|
|
|
137
137
|
await flushPromises();
|
|
138
138
|
|
|
139
139
|
const modal = instance.findByType(ModalPopupCT);
|
|
140
|
-
mock.onDelete(API.DEV_MODE.
|
|
140
|
+
mock.onDelete(API.DEV_MODE.MODBUS.DEVICE_DETAIL(1, 1)).reply(200);
|
|
141
141
|
await act(async () => {
|
|
142
142
|
await modal.props.onPressConfirm();
|
|
143
143
|
});
|
|
@@ -85,6 +85,25 @@ describe('Test Gateway screen', () => {
|
|
|
85
85
|
expect(flatList.props.data).toEqual([{ id: 1, name: 'device 1' }]);
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
it('render Gateway onLoadMore', async () => {
|
|
89
|
+
await act(async () => {
|
|
90
|
+
tree = await create(wrapComponent());
|
|
91
|
+
});
|
|
92
|
+
const instance = tree.root;
|
|
93
|
+
const flatList = instance.findByType(FlatList);
|
|
94
|
+
expect(flatList.props.data).toEqual([]);
|
|
95
|
+
mock
|
|
96
|
+
.onGet(API.DEV_MODE.GATEWAY.LIST())
|
|
97
|
+
.reply(200, { results: [{ id: 1, name: 'device 1' }] });
|
|
98
|
+
await act(async () => {
|
|
99
|
+
await flatList.props.onMomentumScrollBegin();
|
|
100
|
+
});
|
|
101
|
+
await act(async () => {
|
|
102
|
+
await flatList.props.onEndReached();
|
|
103
|
+
});
|
|
104
|
+
expect(flatList.props.data).toEqual([{ id: 1, name: 'device 1' }]);
|
|
105
|
+
});
|
|
106
|
+
|
|
88
107
|
it('Test render empty', async () => {
|
|
89
108
|
await act(async () => {
|
|
90
109
|
tree = await create(wrapComponent());
|
|
@@ -146,26 +146,29 @@ export const useGateway = () => {
|
|
|
146
146
|
isModbus,
|
|
147
147
|
numberGoBack = 1
|
|
148
148
|
) => {
|
|
149
|
-
let
|
|
149
|
+
let response;
|
|
150
150
|
if (isInternal) {
|
|
151
|
-
|
|
151
|
+
response = await axiosDelete(
|
|
152
152
|
API.DEV_MODE.ARDUINO.DEVICE_DETAIL(gatewayId, deviceId)
|
|
153
153
|
);
|
|
154
|
-
success &&
|
|
154
|
+
response.success &&
|
|
155
|
+
setGatewayDevices((prev) => ({ ...prev, internal: [] }));
|
|
155
156
|
}
|
|
156
157
|
if (isZigbee) {
|
|
157
|
-
|
|
158
|
+
response = await axiosDelete(
|
|
158
159
|
API.DEV_MODE.ZIGBEE.DEVICE_DETAIL(gatewayId, deviceId)
|
|
159
160
|
);
|
|
160
|
-
success &&
|
|
161
|
+
response.success &&
|
|
162
|
+
setGatewayDevices((prev) => ({ ...prev, zigbee: [] }));
|
|
161
163
|
}
|
|
162
164
|
if (isModbus) {
|
|
163
|
-
|
|
165
|
+
response = await axiosDelete(
|
|
164
166
|
API.DEV_MODE.MODBUS.DEVICE_DETAIL(gatewayId, deviceId)
|
|
165
167
|
);
|
|
166
|
-
success &&
|
|
168
|
+
response.success &&
|
|
169
|
+
setGatewayDevices((prev) => ({ ...prev, modbus: [] }));
|
|
167
170
|
}
|
|
168
|
-
if (success) {
|
|
171
|
+
if (response.success) {
|
|
169
172
|
ToastBottomHelper.success(t('delete_successfully'));
|
|
170
173
|
navigation.pop(numberGoBack);
|
|
171
174
|
}
|
|
@@ -259,7 +262,11 @@ export const useGateway = () => {
|
|
|
259
262
|
params: { secret },
|
|
260
263
|
}
|
|
261
264
|
);
|
|
262
|
-
|
|
265
|
+
if (success) {
|
|
266
|
+
setDetailChipQr(data);
|
|
267
|
+
} else {
|
|
268
|
+
ToastBottomHelper.error(t('chip_qr_not_found'));
|
|
269
|
+
}
|
|
263
270
|
}, []);
|
|
264
271
|
|
|
265
272
|
return {
|
|
@@ -158,17 +158,24 @@ describe('Test ScriptDetail', () => {
|
|
|
158
158
|
tree = await create(wrapComponent(route));
|
|
159
159
|
});
|
|
160
160
|
const instance = tree.root;
|
|
161
|
+
const icon = instance.find(
|
|
162
|
+
(el) => el.props.accessibilityLabel === AccessibilityLabel.ICON_MORE
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
await act(async () => {
|
|
166
|
+
await icon.props.onPress();
|
|
167
|
+
});
|
|
161
168
|
const menu = instance.find(
|
|
162
169
|
(el) =>
|
|
163
170
|
el.props.accessibilityLabel === AccessibilityLabel.MENU_POPPER_MORE
|
|
164
171
|
);
|
|
172
|
+
expect(menu.props.isVisible).toBeTruthy();
|
|
165
173
|
const alertAction = instance.findAllByType(AlertAction)[0];
|
|
166
174
|
const rename = menu.props.listMenuItem[0];
|
|
167
175
|
|
|
168
176
|
await act(async () => {
|
|
169
177
|
await menu.props.onItemClick(rename);
|
|
170
178
|
});
|
|
171
|
-
expect(menu.props.isVisible).toBeFalsy();
|
|
172
179
|
expect(alertAction.props.visible).toBeTruthy();
|
|
173
180
|
|
|
174
181
|
const textInput = instance.findByType(_TextInput);
|
|
@@ -5,7 +5,14 @@ import React, {
|
|
|
5
5
|
useRef,
|
|
6
6
|
useState,
|
|
7
7
|
} from 'react';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
Image,
|
|
10
|
+
Platform,
|
|
11
|
+
ScrollView,
|
|
12
|
+
Switch,
|
|
13
|
+
TouchableOpacity,
|
|
14
|
+
View,
|
|
15
|
+
} from 'react-native';
|
|
9
16
|
import { PopoverMode } from 'react-native-popover-view';
|
|
10
17
|
import { IconFill, IconOutline } from '@ant-design/icons-react-native';
|
|
11
18
|
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
|
@@ -343,7 +350,9 @@ const ScriptDetail = ({ route }) => {
|
|
|
343
350
|
const { success, data: listChip } = await axiosGet(
|
|
344
351
|
API.DEV_MODE.GATEWAY.SHARED(),
|
|
345
352
|
{
|
|
346
|
-
|
|
353
|
+
params: {
|
|
354
|
+
unit: unit_id,
|
|
355
|
+
},
|
|
347
356
|
},
|
|
348
357
|
true
|
|
349
358
|
);
|
|
@@ -548,46 +557,48 @@ const ScriptDetail = ({ route }) => {
|
|
|
548
557
|
onBackdropPress={onCloseLocalControl}
|
|
549
558
|
>
|
|
550
559
|
<View key={'localControl'} style={styles.popoverStyle}>
|
|
551
|
-
<
|
|
552
|
-
style={styles.textDisable}
|
|
553
|
-
key={'listChip'}
|
|
554
|
-
onPress={() => {
|
|
555
|
-
onPressSelectChip(false, {
|
|
556
|
-
id: local_control.chip_id_local_control,
|
|
557
|
-
name: local_control.chip_local_control,
|
|
558
|
-
});
|
|
559
|
-
}}
|
|
560
|
-
accessibilityLabel={
|
|
561
|
-
AccessibilityLabel.AUTOMATE_DISABLE_LOCAL_CONTROL
|
|
562
|
-
}
|
|
563
|
-
>
|
|
564
|
-
<Text>{t('disable')}</Text>
|
|
565
|
-
{!local_control.is_local_control && (
|
|
566
|
-
<IconOutline style={styles.checked} name={'check'} size={20} />
|
|
567
|
-
)}
|
|
568
|
-
</TouchableOpacity>
|
|
569
|
-
{listChipShared.map((item, index) => (
|
|
560
|
+
<ScrollView>
|
|
570
561
|
<TouchableOpacity
|
|
571
|
-
|
|
572
|
-
|
|
562
|
+
style={styles.textDisable}
|
|
563
|
+
key={'listChip'}
|
|
573
564
|
onPress={() => {
|
|
574
|
-
onPressSelectChip(
|
|
565
|
+
onPressSelectChip(false, {
|
|
566
|
+
id: local_control.chip_id_local_control,
|
|
567
|
+
name: local_control.chip_local_control,
|
|
568
|
+
});
|
|
575
569
|
}}
|
|
576
570
|
accessibilityLabel={
|
|
577
|
-
AccessibilityLabel.
|
|
571
|
+
AccessibilityLabel.AUTOMATE_DISABLE_LOCAL_CONTROL
|
|
578
572
|
}
|
|
579
573
|
>
|
|
580
|
-
<Text>{
|
|
581
|
-
{local_control.
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
style={styles.checked}
|
|
585
|
-
name={'check'}
|
|
586
|
-
size={20}
|
|
587
|
-
/>
|
|
588
|
-
)}
|
|
574
|
+
<Text>{t('disable')}</Text>
|
|
575
|
+
{!local_control.is_local_control && (
|
|
576
|
+
<IconOutline style={styles.checked} name={'check'} size={20} />
|
|
577
|
+
)}
|
|
589
578
|
</TouchableOpacity>
|
|
590
|
-
|
|
579
|
+
{listChipShared.map((item, index) => (
|
|
580
|
+
<TouchableOpacity
|
|
581
|
+
key={'listChip' + index} // Add key fix warning
|
|
582
|
+
style={styles.listChip}
|
|
583
|
+
onPress={() => {
|
|
584
|
+
onPressSelectChip(true, item);
|
|
585
|
+
}}
|
|
586
|
+
accessibilityLabel={
|
|
587
|
+
AccessibilityLabel.AUTOMATE_ENABLE_LOCAL_CONTROL
|
|
588
|
+
}
|
|
589
|
+
>
|
|
590
|
+
<Text>{item.name}</Text>
|
|
591
|
+
{local_control.chip_id_local_control === item.id &&
|
|
592
|
+
local_control.is_local_control && (
|
|
593
|
+
<IconOutline
|
|
594
|
+
style={styles.checked}
|
|
595
|
+
name={'check'}
|
|
596
|
+
size={20}
|
|
597
|
+
/>
|
|
598
|
+
)}
|
|
599
|
+
</TouchableOpacity>
|
|
600
|
+
))}
|
|
601
|
+
</ScrollView>
|
|
591
602
|
</View>
|
|
592
603
|
</ModalCustom>
|
|
593
604
|
</View>
|
|
@@ -1536,4 +1536,7 @@ export default {
|
|
|
1536
1536
|
'Press and hold the number and drag to rearrange the order of the Sub-Units',
|
|
1537
1537
|
rearrange_sub_unit: 'Rearrange Sub-Unit',
|
|
1538
1538
|
updated_sub_unit_order: 'Updated Sub-Units order successfully!',
|
|
1539
|
+
cannot_fetch_data_from_device:
|
|
1540
|
+
'Cannot fetch data from device, Please try again',
|
|
1541
|
+
chip_qr_not_found: 'Chip not found in the system',
|
|
1539
1542
|
};
|
|
@@ -1542,4 +1542,7 @@ export default {
|
|
|
1542
1542
|
'Nhấn giữ vào số thứ tự và di chuyển để sắp xếp lại thứ tự các khu vực',
|
|
1543
1543
|
rearrange_sub_unit: 'Sắp xếp lại các khu vực',
|
|
1544
1544
|
updated_sub_unit_order: 'Đã cập nhật thứ tự các khu vực thành công!',
|
|
1545
|
+
cannot_fetch_data_from_device:
|
|
1546
|
+
'Không thể lấy dữ liệu từ thiết bị, Vui lòng thử lại',
|
|
1547
|
+
chip_qr_not_found: 'Không tìm thấy chip trong hệ thống',
|
|
1545
1548
|
};
|