@eohjsc/react-native-smart-city 0.3.33 → 0.3.36
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-gateway-icon.svg +13 -0
- package/assets/images/AddNewDevice/add-modbus-device-icon.svg +8 -0
- package/assets/images/AddNewDevice/add-wifi-device-icon.svg +4 -0
- package/assets/images/AddNewDevice/add-zigbee-device-icon.svg +4 -0
- package/assets/images/AddNewDevice/interact-smartphone-icon.svg +14 -0
- package/assets/images/AddNewDevice/on-icon.svg +5 -0
- package/assets/images/AddNewDevice/router-connect-icon.svg +3 -0
- package/index.js +2 -0
- package/package.json +2 -1
- package/src/Images/SmartAccount/DienQuang.png +0 -0
- package/src/Images/SmartAccount/DienQuang@2x.png +0 -0
- package/src/Images/SmartAccount/DienQuang@3x.png +0 -0
- package/src/Images/SmartAccount/LG.png +0 -0
- package/src/Images/SmartAccount/LG@2x.png +0 -0
- package/src/Images/SmartAccount/LG@3x.png +0 -0
- package/src/Images/SmartAccount/Samsung.png +0 -0
- package/src/Images/SmartAccount/Samsung@2x.png +0 -0
- package/src/Images/SmartAccount/Samsung@3x.png +0 -0
- package/src/commons/Device/HorizontalBarChart.js +2 -6
- package/src/commons/SelectSubUnit/index.js +18 -18
- package/src/commons/SelectSubUnit/styles.js +0 -3
- package/src/commons/SelectUnit/index.js +2 -3
- package/src/commons/SelectUnit/styles.js +1 -2
- package/src/configs/API.js +10 -0
- package/src/configs/AccessibilityLabel.js +18 -0
- package/src/configs/Constants.js +2 -0
- package/src/configs/Images.js +2 -0
- package/src/context/actionType.ts +3 -0
- package/src/context/reducer.ts +22 -0
- package/src/navigations/AddGatewayStack.js +15 -0
- package/src/navigations/SmartAccountStack.js +52 -0
- package/src/screens/AddCommon/SelectSubUnit.js +17 -13
- package/src/screens/AddCommon/SelectUnit.js +14 -7
- package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +18 -11
- package/src/screens/AddCommon/__test__/SelectUnit.test.js +13 -6
- package/src/screens/AddNewAction/SetupSensor.js +6 -0
- package/src/screens/AddNewGateway/ConnectingModbusDevice.js +0 -1
- package/src/screens/AddNewGateway/ConnectingWifiGuide.js +167 -0
- package/src/screens/AddNewGateway/ConnectingWifiGuideStyles.js +58 -0
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectRouterGuide.js +49 -0
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectRouterGuideStyles.js +31 -0
- package/src/screens/AddNewGateway/PlugAndPlay/FirstWarning.js +0 -5
- package/src/screens/AddNewGateway/PlugAndPlay/ZigbeeDeviceConnectGuide.js +51 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/FirstWarning.test.js +1 -1
- package/src/screens/AddNewGateway/ScanGatewayQR.js +23 -12
- package/src/screens/AddNewGateway/ScanModbusQR.js +75 -11
- package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +19 -9
- package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +26 -7
- package/src/screens/AddNewGateway/SelectDeviceType.js +145 -43
- package/src/screens/AddNewGateway/SelectDeviceTypeStyles.js +51 -0
- package/src/screens/AddNewGateway/SelectDeviceUnit.js +1 -1
- package/src/screens/AddNewGateway/SelectZigbeeGateway.js +1 -1
- package/src/screens/AddNewGateway/ShareWifiPassword.js +7 -112
- package/src/screens/AddNewGateway/__test__/ConnectingWifiGuide.test.js +224 -0
- package/src/screens/AddNewGateway/__test__/ScanGatewayQR.test.js +6 -7
- package/src/screens/AddNewGateway/__test__/ScanModbusQR.test.js +4 -6
- package/src/screens/AddNewGateway/__test__/ScanWifiDeviceQR.test.js +5 -7
- package/src/screens/AddNewGateway/__test__/SelectDeviceSubUnit.test.js +2 -1
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +46 -11
- package/src/screens/AddNewGateway/__test__/SelectZigbeeGateway.test.js +1 -1
- package/src/screens/AddNewGateway/__test__/ShareWifiPassword.test.js +4 -143
- package/src/screens/EditActionsList/__tests__/index.test.js +120 -0
- package/src/screens/EditActionsList/index.js +15 -5
- package/src/screens/ScanChipQR/components/InvalidQRCode/index.js +33 -0
- package/src/screens/ScanChipQR/components/QRScan/index.js +7 -5
- package/src/screens/SharedUnit/__test__/ShareUnit.test.js +25 -0
- package/src/screens/SharedUnit/index.js +2 -0
- package/src/screens/Sharing/Components/DeviceItem.js +24 -8
- package/src/screens/Sharing/SelectPermission.js +78 -62
- package/src/screens/Sharing/__test__/SelectPermission.test.js +55 -2
- package/src/screens/SmartAccount/Connecting/index.js +171 -0
- package/src/screens/SmartAccount/Connecting/style.js +50 -0
- package/src/screens/SmartAccount/ListDevice/DeviceItem.js +45 -0
- package/src/screens/SmartAccount/ListDevice/__test__/DeviceItem.test.js +34 -0
- package/src/screens/SmartAccount/ListDevice/__test__/ListDevice.test.js +139 -0
- package/src/screens/SmartAccount/ListDevice/index.js +185 -0
- package/src/screens/SmartAccount/ListDevice/styles/DeviceItemStyles.js +70 -0
- package/src/screens/SmartAccount/ListDevice/styles/index.js +85 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/DeviceItem.js +37 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/DeviceItemStyles.js +49 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/__test__/DeviceItem.test.js +65 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/__test__/SuccessfullyConnected.test.js +88 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/index.js +101 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/styles.js +42 -0
- package/src/screens/SmartAccount/__test__/Connecting.test.js +86 -0
- package/src/screens/SmartAccount/__test__/SmartAccount.test.js +249 -0
- package/src/screens/SmartAccount/index.js +172 -0
- package/src/screens/SmartAccount/style.js +70 -0
- package/src/screens/SyncLGDevice/__test__/AddLGDevice.test.js +37 -10
- package/src/screens/Unit/AddMenu.js +4 -5
- package/src/screens/Unit/SmartAccount.js +8 -5
- package/src/screens/Unit/__test__/SmartAccount.test.js +8 -5
- package/src/utils/I18n/translations/en.json +35 -2
- package/src/utils/I18n/translations/vi.json +36 -2
- package/src/utils/Route/index.js +6 -0
- package/src/utils/Validation.js +4 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import DraggableFlatList from 'react-native-draggable-flatlist';
|
|
3
|
+
import { create, act } from 'react-test-renderer';
|
|
4
|
+
import { SCProvider } from '../../../context';
|
|
5
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
6
|
+
import EditActionsList from '../index';
|
|
7
|
+
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
8
|
+
import { TouchableOpacity } from 'react-native';
|
|
9
|
+
import api from '../../../utils/Apis/axios';
|
|
10
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
11
|
+
import API from '../../../configs/API';
|
|
12
|
+
|
|
13
|
+
import { ModalBottom } from '../../../commons/Modal';
|
|
14
|
+
|
|
15
|
+
const mockSetdata = jest.fn();
|
|
16
|
+
const mockedNavigate = jest.fn();
|
|
17
|
+
const mockGoBack = jest.fn();
|
|
18
|
+
|
|
19
|
+
const wrapComponent = () => (
|
|
20
|
+
<SCProvider initState={mockSCStore({})}>
|
|
21
|
+
<EditActionsList />
|
|
22
|
+
</SCProvider>
|
|
23
|
+
);
|
|
24
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
25
|
+
|
|
26
|
+
jest.mock('@react-navigation/native', () => {
|
|
27
|
+
return {
|
|
28
|
+
...jest.requireActual('@react-navigation/native'),
|
|
29
|
+
useRoute: jest.fn().mockReturnValue({
|
|
30
|
+
params: {
|
|
31
|
+
data: [{ id: 1, sensor_name: 'abc', station_name: 'abc' }],
|
|
32
|
+
id: 1,
|
|
33
|
+
setData: mockSetdata,
|
|
34
|
+
unit: { id: 1, name: 'unit' },
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
useNavigation: () => ({
|
|
38
|
+
navigate: mockedNavigate,
|
|
39
|
+
goBack: mockGoBack,
|
|
40
|
+
}),
|
|
41
|
+
useIsFocused: () => true,
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
jest.mock('react-native-parsed-text', () => () => []);
|
|
46
|
+
|
|
47
|
+
describe('EditActionsList', () => {
|
|
48
|
+
let tree;
|
|
49
|
+
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
mockGoBack.mockClear();
|
|
52
|
+
});
|
|
53
|
+
test('render EditActionsList', async () => {
|
|
54
|
+
await act(async () => {
|
|
55
|
+
tree = await create(wrapComponent());
|
|
56
|
+
});
|
|
57
|
+
const instance = tree.root;
|
|
58
|
+
const draggableFlatList = instance.findAllByType(DraggableFlatList);
|
|
59
|
+
const modalBottom = instance.findAllByType(ModalBottom);
|
|
60
|
+
expect(draggableFlatList).toHaveLength(1);
|
|
61
|
+
expect(modalBottom).toHaveLength(1);
|
|
62
|
+
});
|
|
63
|
+
test('EditActionsList onPress cancel', async () => {
|
|
64
|
+
await act(async () => {
|
|
65
|
+
tree = await create(wrapComponent());
|
|
66
|
+
});
|
|
67
|
+
const instance = tree.root;
|
|
68
|
+
const buttonCancel = instance.find(
|
|
69
|
+
(el) =>
|
|
70
|
+
el.props.accessibilityLabel ===
|
|
71
|
+
AccessibilityLabel.BUTTON_CANCEL_EDIT_ACTION_LIST &&
|
|
72
|
+
el.type === TouchableOpacity
|
|
73
|
+
);
|
|
74
|
+
expect(buttonCancel).toBeDefined();
|
|
75
|
+
buttonCancel.props.onPress();
|
|
76
|
+
expect(mockGoBack).toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
test('EditActionsList onPress save', async () => {
|
|
79
|
+
mock.onPut(API.AUTOMATE.ORDER_SCRIPT_ACTION(1)).reply(200);
|
|
80
|
+
await act(async () => {
|
|
81
|
+
tree = await create(wrapComponent());
|
|
82
|
+
});
|
|
83
|
+
const instance = tree.root;
|
|
84
|
+
const buttonSave = instance.find(
|
|
85
|
+
(el) =>
|
|
86
|
+
el.props.accessibilityLabel ===
|
|
87
|
+
AccessibilityLabel.BUTTON_SAVE_EDIT_ACTION_LIST &&
|
|
88
|
+
el.type === TouchableOpacity
|
|
89
|
+
);
|
|
90
|
+
expect(buttonSave).toBeDefined();
|
|
91
|
+
buttonSave.props.onPress();
|
|
92
|
+
expect(mock.history.put).toHaveLength(1);
|
|
93
|
+
});
|
|
94
|
+
test('EditActionsList onPress remove', async () => {
|
|
95
|
+
await act(async () => {
|
|
96
|
+
tree = await create(wrapComponent());
|
|
97
|
+
});
|
|
98
|
+
const instance = tree.root;
|
|
99
|
+
const buttonRemove = instance.find(
|
|
100
|
+
(el) =>
|
|
101
|
+
el.props.accessibilityLabel ===
|
|
102
|
+
AccessibilityLabel.BUTTON_REMOVE_EDIT_ACTION_LIST &&
|
|
103
|
+
el.type === TouchableOpacity
|
|
104
|
+
);
|
|
105
|
+
expect(buttonRemove).toBeDefined();
|
|
106
|
+
buttonRemove.props.onPress();
|
|
107
|
+
});
|
|
108
|
+
test('EditActionsList modal onPress remove', async () => {
|
|
109
|
+
await act(async () => {
|
|
110
|
+
tree = await create(wrapComponent());
|
|
111
|
+
});
|
|
112
|
+
const instance = tree.root;
|
|
113
|
+
const modalBottom = instance.findAllByType(ModalBottom);
|
|
114
|
+
modalBottom[0].props.onRemove();
|
|
115
|
+
|
|
116
|
+
mock.onDelete(API.AUTOMATE.DELETE_SCRIPT_ACTION(1, 1)).reply(200);
|
|
117
|
+
expect(mock.history.delete).toHaveLength(1);
|
|
118
|
+
modalBottom[0].props.onClose();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useCallback } from 'react';
|
|
1
|
+
import React, { memo, useState, useCallback } from 'react';
|
|
2
2
|
import { View, TouchableOpacity } from 'react-native';
|
|
3
3
|
import DraggableFlatList from 'react-native-draggable-flatlist';
|
|
4
4
|
import { useNavigation, useRoute } from '@react-navigation/native';
|
|
@@ -15,8 +15,9 @@ import Close from '../../../assets/images/Close.svg';
|
|
|
15
15
|
import { axiosDelete, axiosPut } from '../../utils/Apis/axios';
|
|
16
16
|
import { ModalBottom } from '../../commons/Modal';
|
|
17
17
|
import { ToastBottomHelper } from '../../utils/Utils';
|
|
18
|
+
import { AccessibilityLabel } from '../../configs/Constants';
|
|
18
19
|
|
|
19
|
-
const EditActionsList = () => {
|
|
20
|
+
const EditActionsList = memo(() => {
|
|
20
21
|
const t = useTranslations();
|
|
21
22
|
const { goBack } = useNavigation();
|
|
22
23
|
const { params = {} } = useRoute() || {};
|
|
@@ -115,6 +116,9 @@ const EditActionsList = () => {
|
|
|
115
116
|
</Text>
|
|
116
117
|
</View>
|
|
117
118
|
<TouchableOpacity
|
|
119
|
+
accessibilityLabel={
|
|
120
|
+
AccessibilityLabel.BUTTON_REMOVE_EDIT_ACTION_LIST
|
|
121
|
+
}
|
|
118
122
|
onPress={onPressRemove({
|
|
119
123
|
id: item?.id,
|
|
120
124
|
actionName: item?.sensor_name,
|
|
@@ -148,12 +152,18 @@ const EditActionsList = () => {
|
|
|
148
152
|
/>
|
|
149
153
|
</View>
|
|
150
154
|
<View style={styles.wrapBottom}>
|
|
151
|
-
<TouchableOpacity
|
|
155
|
+
<TouchableOpacity
|
|
156
|
+
onPress={onPressCancel}
|
|
157
|
+
accessibilityLabel={AccessibilityLabel.BUTTON_CANCEL_EDIT_ACTION_LIST}
|
|
158
|
+
>
|
|
152
159
|
<Text type="H4" hilight semibold>
|
|
153
160
|
{t('cancel')}
|
|
154
161
|
</Text>
|
|
155
162
|
</TouchableOpacity>
|
|
156
|
-
<TouchableOpacity
|
|
163
|
+
<TouchableOpacity
|
|
164
|
+
onPress={onPressSave}
|
|
165
|
+
accessibilityLabel={AccessibilityLabel.BUTTON_SAVE_EDIT_ACTION_LIST}
|
|
166
|
+
>
|
|
157
167
|
<Text type="H4" hilight semibold>
|
|
158
168
|
{t('save')}
|
|
159
169
|
</Text>
|
|
@@ -189,6 +199,6 @@ const EditActionsList = () => {
|
|
|
189
199
|
</ModalBottom>
|
|
190
200
|
</View>
|
|
191
201
|
);
|
|
192
|
-
};
|
|
202
|
+
});
|
|
193
203
|
|
|
194
204
|
export default EditActionsList;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { useTranslations } from '../../../../hooks/Common/useTranslations';
|
|
5
|
+
import Text from '../../../../commons/Text';
|
|
6
|
+
import { ViewButtonBottom } from '../../../../commons';
|
|
7
|
+
import BottomSheet from '../../../../commons/BottomSheet';
|
|
8
|
+
|
|
9
|
+
const InvalidQRCode = ({ isInvalidQrCode, goBack, onRetry }) => {
|
|
10
|
+
const t = useTranslations();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<BottomSheet isVisible={isInvalidQrCode} title={t('invalid_qr_code')}>
|
|
14
|
+
<Text style={styles.warningContainer}>
|
|
15
|
+
{t('invalid_qr_code_warning')}
|
|
16
|
+
</Text>
|
|
17
|
+
<ViewButtonBottom
|
|
18
|
+
leftTitle={t('cancel')}
|
|
19
|
+
onLeftClick={goBack}
|
|
20
|
+
rightTitle={t('retry')}
|
|
21
|
+
onRightClick={onRetry}
|
|
22
|
+
/>
|
|
23
|
+
</BottomSheet>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default InvalidQRCode;
|
|
28
|
+
|
|
29
|
+
const styles = StyleSheet.create({
|
|
30
|
+
warningContainer: {
|
|
31
|
+
paddingHorizontal: 16,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
@@ -46,7 +46,7 @@ const VerifingQRCode = memo(() => {
|
|
|
46
46
|
);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
const QRScan = ({ onScan }) => {
|
|
49
|
+
const QRScan = ({ isScanReady = true, onScan }) => {
|
|
50
50
|
const t = useTranslations();
|
|
51
51
|
const navigation = useNavigation();
|
|
52
52
|
const isFocused = useIsFocused();
|
|
@@ -55,12 +55,14 @@ const QRScan = ({ onScan }) => {
|
|
|
55
55
|
|
|
56
56
|
const onBarCodeRead = useCallback(
|
|
57
57
|
(e) => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
if (isScanReady) {
|
|
59
|
+
setLoading(true);
|
|
60
|
+
if (!loading) {
|
|
61
|
+
onScan(e.data, setLoading);
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
},
|
|
63
|
-
[loading, onScan]
|
|
65
|
+
[isScanReady, loading, onScan]
|
|
64
66
|
);
|
|
65
67
|
|
|
66
68
|
const onPressClose = useCallback(() => {
|
|
@@ -4,6 +4,12 @@ import SharedUnit from '../index';
|
|
|
4
4
|
import Modal from 'react-native-modal';
|
|
5
5
|
import { SCProvider } from '../../../context';
|
|
6
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
8
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
9
|
+
import api from '../../../utils/Apis/axios';
|
|
10
|
+
import { API } from '../../../configs';
|
|
11
|
+
|
|
12
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
7
13
|
|
|
8
14
|
const wrapComponent = () => (
|
|
9
15
|
<SCProvider initState={mockSCStore({})}>
|
|
@@ -16,9 +22,11 @@ jest.mock('react-redux', () => ({
|
|
|
16
22
|
useSelector: jest.fn(),
|
|
17
23
|
}));
|
|
18
24
|
|
|
25
|
+
const mockSetSharedUnits = jest.fn();
|
|
19
26
|
jest.mock('react', () => ({
|
|
20
27
|
...jest.requireActual('react'),
|
|
21
28
|
useLayoutEffect: jest.fn(),
|
|
29
|
+
useState: jest.fn((init) => [init, mockSetSharedUnits]),
|
|
22
30
|
}));
|
|
23
31
|
|
|
24
32
|
jest.mock('react-native-onesignal', () => {
|
|
@@ -37,4 +45,21 @@ describe('test SharedUnit', () => {
|
|
|
37
45
|
const modalShareds = instance.findAllByType(Modal);
|
|
38
46
|
expect(modalShareds[0]).not.toBeUndefined();
|
|
39
47
|
});
|
|
48
|
+
|
|
49
|
+
test('render touch item filter', async () => {
|
|
50
|
+
mock.onGet(API.UNIT.FILTER_SHARED_UNITS()).reply(200, [{}]);
|
|
51
|
+
|
|
52
|
+
await act(async () => {
|
|
53
|
+
tree = await create(wrapComponent());
|
|
54
|
+
});
|
|
55
|
+
const instance = tree.root;
|
|
56
|
+
const item = instance.findAll(
|
|
57
|
+
(el) =>
|
|
58
|
+
el.props.accessibilityLabel === AccessibilityLabel.FILTER_SHARING_ITEM
|
|
59
|
+
);
|
|
60
|
+
await act(async () => {
|
|
61
|
+
item[0].props.onPress();
|
|
62
|
+
});
|
|
63
|
+
expect(mockSetSharedUnits).toBeCalled();
|
|
64
|
+
});
|
|
40
65
|
});
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
useBoolean,
|
|
13
13
|
useBlockBackAndroid,
|
|
14
14
|
} from '../../hooks/Common';
|
|
15
|
+
import { AccessibilityLabel } from '../../configs/Constants';
|
|
15
16
|
|
|
16
17
|
import styles from './styles';
|
|
17
18
|
import TabHeader from './TabHeader';
|
|
@@ -185,6 +186,7 @@ const Shared = () => {
|
|
|
185
186
|
style={styles.row}
|
|
186
187
|
onPress={() => onFilter(item.filter, item.textFilter)}
|
|
187
188
|
key={`filter-${index}`}
|
|
189
|
+
accessibilityLabel={`${AccessibilityLabel.FILTER_SHARING_ITEM}`}
|
|
188
190
|
>
|
|
189
191
|
<Text
|
|
190
192
|
style={
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import React, { memo, useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
LayoutAnimation,
|
|
6
|
+
Platform,
|
|
7
|
+
UIManager,
|
|
8
|
+
TouchableOpacity,
|
|
9
|
+
} from 'react-native';
|
|
3
10
|
import { IconOutline } from '@ant-design/icons-react-native';
|
|
4
11
|
import { Colors } from '../../../configs';
|
|
5
12
|
import styles from './Styles/DeviceItemStyles';
|
|
@@ -13,6 +20,7 @@ const DeviceItem = ({
|
|
|
13
20
|
isRenderSeparated,
|
|
14
21
|
onTickedChild,
|
|
15
22
|
onTickedDevice,
|
|
23
|
+
onTickedDeviceIcon,
|
|
16
24
|
isItemExpanded,
|
|
17
25
|
toggleItem,
|
|
18
26
|
idGroup,
|
|
@@ -57,6 +65,14 @@ const DeviceItem = ({
|
|
|
57
65
|
);
|
|
58
66
|
};
|
|
59
67
|
|
|
68
|
+
const isCheckedIcon = useMemo(() => {
|
|
69
|
+
return dataConfig.some((i) => i.isChecked);
|
|
70
|
+
}, [dataConfig]);
|
|
71
|
+
|
|
72
|
+
const handleOnTickedIcon = () => {
|
|
73
|
+
onTickedDeviceIcon && onTickedDeviceIcon(idGroup, id, isCheckedIcon);
|
|
74
|
+
};
|
|
75
|
+
|
|
60
76
|
const handleOnTickedDevice = () => {
|
|
61
77
|
onTickedDevice && onTickedDevice(idGroup, id, !isChecked);
|
|
62
78
|
};
|
|
@@ -88,13 +104,13 @@ const DeviceItem = ({
|
|
|
88
104
|
|
|
89
105
|
return (
|
|
90
106
|
<View style={[styles.wrap, !isRenderSeparated && styles.isRenderSeparated]}>
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
<TouchableOpacity onPress={handleOnTickedIcon}>
|
|
108
|
+
<FImage
|
|
109
|
+
source={{ uri: icon_kit }}
|
|
110
|
+
style={styles.viewLeft}
|
|
111
|
+
tintColor={isCheckedIcon ? Colors.Primary : Colors.Gray}
|
|
112
|
+
/>
|
|
113
|
+
</TouchableOpacity>
|
|
98
114
|
<View style={styles.wrapRight}>
|
|
99
115
|
<View style={styles.viewRight}>
|
|
100
116
|
<Text
|
|
@@ -84,17 +84,6 @@ const SelectPermission = ({ route }) => {
|
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
const stationCheck = (data) => {
|
|
88
|
-
for (let station of data) {
|
|
89
|
-
if (station.devices.length) {
|
|
90
|
-
station.isChecked = !station.devices.some((i) => !i.isChecked);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
setIsTickAllDevices(!dataStationTemp.some((i) => !i.isChecked));
|
|
94
|
-
dataStationTemp = data;
|
|
95
|
-
setDataStations(data);
|
|
96
|
-
};
|
|
97
|
-
|
|
98
87
|
const onTickedChild = (
|
|
99
88
|
idGroup,
|
|
100
89
|
deviceId,
|
|
@@ -114,8 +103,18 @@ const SelectPermission = ({ route }) => {
|
|
|
114
103
|
device.read_configs.some((i) => !i.isChecked) ||
|
|
115
104
|
device.actions.some((i) => !i.isChecked)
|
|
116
105
|
);
|
|
117
|
-
|
|
118
|
-
|
|
106
|
+
for (let station of data) {
|
|
107
|
+
if (station.devices.length) {
|
|
108
|
+
station.isChecked = station.devices.some(
|
|
109
|
+
(i) =>
|
|
110
|
+
i.read_configs.some((r) => r.isChecked) ||
|
|
111
|
+
i.actions.some((a) => a.isChecked)
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
setIsTickAllDevices(!dataStationTemp.some((i) => !i.isChecked));
|
|
116
|
+
dataStationTemp = data;
|
|
117
|
+
setDataStations(data);
|
|
119
118
|
};
|
|
120
119
|
|
|
121
120
|
const onTickedDevice = (idGroup, deviceId, isChecked) => {
|
|
@@ -125,7 +124,48 @@ const SelectPermission = ({ route }) => {
|
|
|
125
124
|
|
|
126
125
|
device.isChecked = isChecked;
|
|
127
126
|
|
|
128
|
-
|
|
127
|
+
for (let station of data) {
|
|
128
|
+
if (station.devices.length) {
|
|
129
|
+
station.isChecked = !station.devices.some((i) => !i.isChecked);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
setIsTickAllDevices(!dataStationTemp.some((i) => !i.isChecked));
|
|
133
|
+
dataStationTemp = data;
|
|
134
|
+
setDataStations(data);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const onTickedDeviceIcon = (idGroup, deviceId, isChecked) => {
|
|
138
|
+
let data = [...dataStationTemp];
|
|
139
|
+
const group = data.find((i) => i.id === idGroup);
|
|
140
|
+
const device = group.devices.find((i) => i.id === deviceId);
|
|
141
|
+
const index = data.findIndex((item) => item.id === idGroup);
|
|
142
|
+
|
|
143
|
+
data[index] = {
|
|
144
|
+
...data[index],
|
|
145
|
+
devices: data[index]?.devices.map((i) => {
|
|
146
|
+
if (i.id === device?.id) {
|
|
147
|
+
return {
|
|
148
|
+
...i,
|
|
149
|
+
isChecked: !isChecked,
|
|
150
|
+
actions: i.actions.map((j) => ({ ...j, isChecked: !isChecked })),
|
|
151
|
+
read_configs: i.read_configs.map((j) => ({
|
|
152
|
+
...j,
|
|
153
|
+
isChecked: !isChecked,
|
|
154
|
+
})),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return { ...i };
|
|
158
|
+
}),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
data[index] = {
|
|
162
|
+
...data[index],
|
|
163
|
+
isChecked:
|
|
164
|
+
!data[index]?.devices.length ===
|
|
165
|
+
!data[index]?.devices.filter((i) => i.isChecked).length,
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
setDataStations(data);
|
|
129
169
|
};
|
|
130
170
|
|
|
131
171
|
const toggleDeviceItem = (deviceItem) => () => {
|
|
@@ -142,15 +182,8 @@ const SelectPermission = ({ route }) => {
|
|
|
142
182
|
const autoCheckedGroup = useCallback(async () => {
|
|
143
183
|
if (isUpdateSharedDevice) {
|
|
144
184
|
if (hasDataChecked) {
|
|
145
|
-
const stationIds =
|
|
146
|
-
|
|
147
|
-
const actionIds = object_Ids(dataDeviceShared)?.actionIds;
|
|
148
|
-
const configIds = object_Ids(dataDeviceShared)?.configIds;
|
|
149
|
-
const device_checked = [];
|
|
150
|
-
const action_checked = [];
|
|
151
|
-
const config_checked = [];
|
|
152
|
-
const action_temp = [];
|
|
153
|
-
const config_temp = [];
|
|
185
|
+
const { stationIds, deviceIds, actionIds, configIds } =
|
|
186
|
+
object_Ids(dataDeviceShared);
|
|
154
187
|
for (let station in dataStations) {
|
|
155
188
|
for (let item in dataStations[station].devices) {
|
|
156
189
|
const itemTemp = dataStations[station].devices[item];
|
|
@@ -158,54 +191,34 @@ const SelectPermission = ({ route }) => {
|
|
|
158
191
|
...itemTemp,
|
|
159
192
|
isChecked: deviceIds.includes(itemTemp?.id),
|
|
160
193
|
actions: itemTemp.actions.map((i) => {
|
|
161
|
-
if (actionIds?.includes(i.id)) {
|
|
162
|
-
action_checked.push(i);
|
|
163
|
-
}
|
|
164
|
-
action_temp.push(i);
|
|
165
194
|
return {
|
|
166
195
|
...i,
|
|
167
196
|
isChecked: actionIds?.includes(i.id),
|
|
168
197
|
};
|
|
169
198
|
}),
|
|
170
199
|
read_configs: itemTemp.read_configs.map((i) => {
|
|
171
|
-
if (configIds?.includes(i.id)) {
|
|
172
|
-
config_checked.push(i);
|
|
173
|
-
}
|
|
174
|
-
config_temp.push(i);
|
|
175
200
|
return {
|
|
176
201
|
...i,
|
|
177
202
|
isChecked: configIds?.includes(i.id),
|
|
178
203
|
};
|
|
179
204
|
}),
|
|
180
205
|
};
|
|
181
|
-
if (dataStations[station].devices[item]?.isChecked) {
|
|
182
|
-
device_checked.push(dataStations[station].devices[item]);
|
|
183
|
-
}
|
|
184
206
|
}
|
|
185
207
|
}
|
|
186
|
-
const check_action_config = () => {
|
|
187
|
-
return (
|
|
188
|
-
action_checked?.length === action_temp?.length &&
|
|
189
|
-
config_checked?.length === config_temp?.length
|
|
190
|
-
);
|
|
191
|
-
};
|
|
192
208
|
const data = dataStations?.map((i) => {
|
|
209
|
+
const devices = i?.devices;
|
|
210
|
+
const devices_checked = i?.devices?.filter(
|
|
211
|
+
(device) => device?.isChecked
|
|
212
|
+
);
|
|
193
213
|
return {
|
|
194
214
|
...i,
|
|
195
215
|
isChecked:
|
|
196
|
-
|
|
197
|
-
i?.devices?.length === device_checked?.length &&
|
|
216
|
+
!devices.length === !devices_checked.length &&
|
|
198
217
|
stationIds.includes(i.id),
|
|
199
218
|
};
|
|
200
219
|
});
|
|
201
|
-
const deviceIdsDefault = object_Ids(data)?.deviceIds;
|
|
202
|
-
const stationIdsDefault = object_Ids(data)?.stationIds;
|
|
203
220
|
setDataStations(data);
|
|
204
|
-
setIsTickAllDevices(
|
|
205
|
-
check_action_config() &&
|
|
206
|
-
deviceIdsDefault?.length === deviceIds?.length &&
|
|
207
|
-
stationIdsDefault?.length === stationIds?.length
|
|
208
|
-
);
|
|
221
|
+
setIsTickAllDevices(data?.length === stationIds?.length);
|
|
209
222
|
setHasDataChecked(false);
|
|
210
223
|
}
|
|
211
224
|
}
|
|
@@ -231,6 +244,7 @@ const SelectPermission = ({ route }) => {
|
|
|
231
244
|
isRenderSeparated={index !== devices?.length - 1}
|
|
232
245
|
onTickedChild={onTickedChild}
|
|
233
246
|
onTickedDevice={onTickedDevice}
|
|
247
|
+
onTickedDeviceIcon={onTickedDeviceIcon}
|
|
234
248
|
isItemExpanded={expandedItemIds.includes(i.id)}
|
|
235
249
|
toggleItem={toggleDeviceItem(i)}
|
|
236
250
|
idGroup={id}
|
|
@@ -331,33 +345,35 @@ const SelectPermission = ({ route }) => {
|
|
|
331
345
|
|
|
332
346
|
const getShareUnitPermission = useCallback(async () => {
|
|
333
347
|
if (isUpdateSharedDevice && dataStations?.length > 0) {
|
|
334
|
-
const
|
|
348
|
+
const { success, data } = await axiosGet(
|
|
335
349
|
API.SHARE.UNIT_MEMBER_SHARE_DEVICE(unit?.id, member?.id)
|
|
336
350
|
);
|
|
337
|
-
if (
|
|
338
|
-
setDataDeviceShared(
|
|
351
|
+
if (success) {
|
|
352
|
+
setDataDeviceShared(data);
|
|
339
353
|
setHasDataChecked(true);
|
|
340
354
|
}
|
|
341
355
|
}
|
|
342
356
|
}, [dataStations?.length, isUpdateSharedDevice, member?.id, unit?.id]);
|
|
343
357
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
358
|
+
const getUnitPermission = useCallback(async () => {
|
|
359
|
+
const { success, data } = await axiosGet(
|
|
360
|
+
API.SHARE.UNIT_PERMISSIONS(unit?.id)
|
|
361
|
+
);
|
|
362
|
+
if (success) {
|
|
363
|
+
setDataStations(data);
|
|
364
|
+
}
|
|
365
|
+
setLoading(false);
|
|
366
|
+
}, [unit?.id]);
|
|
347
367
|
|
|
348
368
|
useEffect(() => {
|
|
349
369
|
(async () => {
|
|
350
370
|
if (!unit) {
|
|
351
371
|
return;
|
|
352
372
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
API.SHARE.UNIT_PERMISSIONS(unit.id)
|
|
356
|
-
);
|
|
357
|
-
success && setDataStations(data);
|
|
358
|
-
setLoading(false);
|
|
373
|
+
await getUnitPermission();
|
|
374
|
+
await getShareUnitPermission();
|
|
359
375
|
})();
|
|
360
|
-
}, [
|
|
376
|
+
}, [getShareUnitPermission, getUnitPermission, unit]);
|
|
361
377
|
|
|
362
378
|
useEffect(() => {
|
|
363
379
|
dataStationTemp = dataStations;
|
|
@@ -43,7 +43,7 @@ const wrapComponent = (route) => (
|
|
|
43
43
|
|
|
44
44
|
describe('Test SelectPermission', () => {
|
|
45
45
|
let tree;
|
|
46
|
-
let route = { params: { unit:
|
|
46
|
+
let route = { params: { unit: { id: 1, name: 'unit 1' } } };
|
|
47
47
|
let listDevices = [
|
|
48
48
|
{
|
|
49
49
|
id: 204,
|
|
@@ -110,7 +110,31 @@ describe('Test SelectPermission', () => {
|
|
|
110
110
|
expect(TextElement[2].props.children).toBe('No data');
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
it('test get
|
|
113
|
+
it('test unit get permission default', () => {
|
|
114
|
+
mocSetdata();
|
|
115
|
+
const routes = { params: { unit: { id: 1, name: '123' } } };
|
|
116
|
+
mock.onGet(API.SHARE.UNIT_PERMISSIONS(1)).reply(200);
|
|
117
|
+
act(() => {
|
|
118
|
+
tree = create(wrapComponent(routes));
|
|
119
|
+
});
|
|
120
|
+
const instance = tree.root;
|
|
121
|
+
const FlatListElement = instance.findAllByType(FlatList);
|
|
122
|
+
expect(FlatListElement).toHaveLength(1);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('test unit fail default', () => {
|
|
126
|
+
mockLoading();
|
|
127
|
+
const routes = { params: { unit: null } };
|
|
128
|
+
mock.onGet(API.SHARE.UNIT_PERMISSIONS(1)).reply(400);
|
|
129
|
+
act(() => {
|
|
130
|
+
tree = create(wrapComponent(routes));
|
|
131
|
+
});
|
|
132
|
+
const instance = tree.root;
|
|
133
|
+
const TextElement = instance.findAllByType(Text);
|
|
134
|
+
expect(TextElement[2].props.children).toBe('No data');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('test get unit fail shared', () => {
|
|
114
138
|
mockLoading();
|
|
115
139
|
route.params.unit = 1;
|
|
116
140
|
mock.onGet(API.SHARE.UNIT_MEMBER_SHARE_DEVICE(1, 1)).reply(400);
|
|
@@ -172,6 +196,35 @@ describe('Test SelectPermission', () => {
|
|
|
172
196
|
expect(mockSetDataStations).toBeCalled();
|
|
173
197
|
});
|
|
174
198
|
|
|
199
|
+
it('test onTickedDevice function', () => {
|
|
200
|
+
mocSetdata();
|
|
201
|
+
act(() => {
|
|
202
|
+
tree = create(wrapComponent(route));
|
|
203
|
+
});
|
|
204
|
+
const instance = tree.root;
|
|
205
|
+
const DeviceItemElement = instance.findAllByType(DeviceItem);
|
|
206
|
+
expect(DeviceItemElement).toHaveLength(1);
|
|
207
|
+
act(() => {
|
|
208
|
+
DeviceItemElement[0].props.onTickedDevice(204, 123, true);
|
|
209
|
+
DeviceItemElement[0].props.toggleItem(123);
|
|
210
|
+
});
|
|
211
|
+
expect(mockSetDataStations).toBeCalled();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('test onTickedDeviceIcon function', () => {
|
|
215
|
+
mocSetdata();
|
|
216
|
+
act(() => {
|
|
217
|
+
tree = create(wrapComponent(route));
|
|
218
|
+
});
|
|
219
|
+
const instance = tree.root;
|
|
220
|
+
const DeviceItemElement = instance.findAllByType(DeviceItem);
|
|
221
|
+
expect(DeviceItemElement).toHaveLength(1);
|
|
222
|
+
act(() => {
|
|
223
|
+
DeviceItemElement[0].props.onTickedDeviceIcon(204, 123, true);
|
|
224
|
+
});
|
|
225
|
+
expect(mockSetDataStations).toBeCalled();
|
|
226
|
+
});
|
|
227
|
+
|
|
175
228
|
it('test ViewButtonBottom', () => {
|
|
176
229
|
mocSetdata();
|
|
177
230
|
act(() => {
|