@eohjsc/react-native-smart-city 0.7.21 → 0.7.22
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/Images/Common/default_end_device.png +0 -0
- package/src/commons/Dashboard/MyUnit/index.js +19 -20
- package/src/commons/DevMode/Search.js +1 -1
- package/src/commons/Device/RainningSensor/CurrentRainSensor.js +5 -5
- package/src/commons/Widgets/IFrameWithConfig/IFrameWithConfig.js +1 -3
- package/src/commons/Widgets/IFrameWithConfig/__tests__/IFrameWithConfig.test.js +1 -1
- package/src/configs/API.js +4 -0
- package/src/configs/AccessibilityLabel.js +3 -1
- package/src/configs/Images.js +1 -0
- package/src/navigations/AddMemberStack.js +3 -3
- package/src/screens/AddCommon/SelectUnit.js +3 -2
- package/src/screens/AddLocationMaps/__test__/index.test.js +13 -13
- package/src/screens/Automate/AddNewAction/__test__/ChooseConfig.test.js +9 -11
- package/src/screens/Automate/AddNewAutoSmart/__test__/AddAutomationTypeSmart.test.js +31 -0
- package/src/screens/Automate/ScriptDetail/utils.js +0 -20
- package/src/screens/ConfirmUnitDeletion/__test__/ConfirmUnitDeletion.test.js +69 -13
- package/src/screens/ConfirmUnitDeletion/index.js +14 -14
- package/src/screens/Sharing/Components/ConfigItem.js +34 -0
- package/src/screens/Sharing/Components/DeviceItem.js +77 -0
- package/src/screens/Sharing/Components/ItemChangeRole.js +3 -4
- package/src/screens/Sharing/Components/ShareDeviceSelector.js +255 -0
- package/src/screens/Sharing/Components/Styles/CheckBoxCustomStyles.js +1 -1
- package/src/screens/Sharing/Components/Styles/DeviceItemStyles.js +11 -27
- package/src/screens/Sharing/{Styles/SelectPermissionStyles.js → Components/Styles/ShareDeviceSelectorStyles.js} +3 -11
- package/src/screens/Sharing/Components/SubUnitItem.js +28 -0
- package/src/screens/Sharing/Components/SubUnitTreeView.js +68 -0
- package/src/screens/Sharing/Components/TitleCheckBox.js +23 -41
- package/src/screens/Sharing/Components/__test__/ItemChangeRole.test.js +7 -7
- package/src/screens/Sharing/Components/__test__/ShareDeviceSelector.test.js +298 -0
- package/src/screens/Sharing/Components/index.js +14 -1
- package/src/screens/Sharing/InfoMemberUnit.js +20 -20
- package/src/screens/Sharing/SelectShareDevice.js +11 -255
- package/src/screens/Sharing/SelectUser.js +12 -12
- package/src/screens/Sharing/UpdateShareDevice.js +45 -301
- package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +58 -11
- package/src/screens/Sharing/__test__/SelectShareDevice.test.js +51 -160
- package/src/screens/Sharing/__test__/SelectUser.test.js +72 -10
- package/src/screens/Sharing/__test__/UpdateShareDevice.test.js +49 -209
- package/src/utils/I18n/translations/en.js +1 -1
- package/src/utils/I18n/translations/vi.js +2 -2
- package/src/commons/Sharing/StationDevicePermissions.js +0 -204
- package/src/screens/Sharing/Components/CheckBoxConfig.js +0 -44
- package/src/screens/Sharing/Components/CheckBoxSubUnit.js +0 -35
- package/src/screens/Sharing/Components/EndDevice.js +0 -93
- package/src/screens/Sharing/Components/Styles/CheckBoxConfigStyles.js +0 -18
- package/src/screens/Sharing/Components/Styles/TitleCheckBoxStyles.js +0 -21
- package/src/screens/Sharing/Components/__test__/TitleCheckBox.test.js +0 -31
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import API from '../../../../configs/API';
|
|
2
|
+
import AccessibilityLabel from '../../../../configs/AccessibilityLabel';
|
|
3
|
+
import { Alert } from 'react-native';
|
|
4
|
+
import ConfigItem from '../ConfigItem';
|
|
5
|
+
import DeviceItem from '../DeviceItem';
|
|
6
|
+
import { IconOutline } from '@ant-design/icons-react-native';
|
|
7
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { SCProvider } from '../../../../context';
|
|
10
|
+
import ShareDeviceSelector from '../ShareDeviceSelector';
|
|
11
|
+
import SubUnitItem from '../SubUnitItem';
|
|
12
|
+
import SubUnitTreeView from '../SubUnitTreeView';
|
|
13
|
+
import { ViewButtonBottom } from '../../../../commons';
|
|
14
|
+
import { act } from '@testing-library/react-hooks';
|
|
15
|
+
import api from '../../../../utils/Apis/axios';
|
|
16
|
+
import { create } from 'react-test-renderer';
|
|
17
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
18
|
+
import { useNavigation } from '@react-navigation/native';
|
|
19
|
+
|
|
20
|
+
jest.spyOn(Alert, 'alert').mockImplementation(() => {});
|
|
21
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
22
|
+
const mockOnRightClick = jest.fn();
|
|
23
|
+
|
|
24
|
+
const wrapComponent = (unitId, initKeys = undefined) => (
|
|
25
|
+
<SCProvider initState={mockSCStore({})}>
|
|
26
|
+
<ShareDeviceSelector
|
|
27
|
+
unitId={unitId}
|
|
28
|
+
onRightClick={mockOnRightClick}
|
|
29
|
+
rightTitle={'done'}
|
|
30
|
+
initialSelectedKeys={initKeys}
|
|
31
|
+
/>
|
|
32
|
+
</SCProvider>
|
|
33
|
+
);
|
|
34
|
+
describe('test ShareDeviceSelector', () => {
|
|
35
|
+
const unitId = 1;
|
|
36
|
+
let listDevices = [];
|
|
37
|
+
let tree;
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
mockOnRightClick.mockClear();
|
|
40
|
+
Alert.alert.mockClear();
|
|
41
|
+
listDevices = [
|
|
42
|
+
{
|
|
43
|
+
id: 1,
|
|
44
|
+
name: 'Sub unit 1',
|
|
45
|
+
devices: [
|
|
46
|
+
{
|
|
47
|
+
id: 1,
|
|
48
|
+
icon_kit: 'https://xxx.png',
|
|
49
|
+
actions: [{ id: 1, name: 'action 1' }],
|
|
50
|
+
read_configs: [{ id: 1, name: 'config 1' }],
|
|
51
|
+
name: 'child1',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: 2,
|
|
55
|
+
actions: [{ id: 2, name: 'action 2' }],
|
|
56
|
+
read_configs: [{ id: 2, name: 'config 2' }],
|
|
57
|
+
name: 'child2',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 3,
|
|
61
|
+
actions: [],
|
|
62
|
+
read_configs: [],
|
|
63
|
+
name: 'child3',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 2,
|
|
69
|
+
name: 'Sub unit 2',
|
|
70
|
+
devices: [
|
|
71
|
+
{
|
|
72
|
+
id: 4,
|
|
73
|
+
icon: 'acb.png',
|
|
74
|
+
actions: [{ id: 3, name: 'action 3' }],
|
|
75
|
+
read_configs: [{ id: 3, name: 'config 3' }],
|
|
76
|
+
name: 'child1',
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const clickChooseAllDevices = async (instance, status) => {
|
|
84
|
+
const chooseAllDevices = instance.find(
|
|
85
|
+
(el) =>
|
|
86
|
+
el.props.accessibilityLabel ===
|
|
87
|
+
`${AccessibilityLabel.CHECK_BOX_CUSTOM}-all`
|
|
88
|
+
);
|
|
89
|
+
await act(async () => {
|
|
90
|
+
chooseAllDevices.props.onPress();
|
|
91
|
+
});
|
|
92
|
+
expect(chooseAllDevices.props.isChecked).toEqual(status);
|
|
93
|
+
};
|
|
94
|
+
const clickChooseDevice = async (instance, deviceId, status) => {
|
|
95
|
+
const chooseDevice = instance.find(
|
|
96
|
+
(el) =>
|
|
97
|
+
el.props.accessibilityLabel ===
|
|
98
|
+
`${AccessibilityLabel.SHARE_DEVICE.NAME_END_DEVICE}-device-${deviceId}`
|
|
99
|
+
);
|
|
100
|
+
await act(async () => {
|
|
101
|
+
chooseDevice.props.onPress();
|
|
102
|
+
});
|
|
103
|
+
const iconCheck = instance.findAll(
|
|
104
|
+
(el) =>
|
|
105
|
+
el.props.accessibilityLabel ===
|
|
106
|
+
`${AccessibilityLabel.SHARE_DEVICE.ICON_CHECK}-device-${deviceId}` &&
|
|
107
|
+
el.type === IconOutline
|
|
108
|
+
);
|
|
109
|
+
expect(iconCheck).toHaveLength(status ? 1 : 0);
|
|
110
|
+
};
|
|
111
|
+
const clickChooseConfig = async (instance, configId, status) => {
|
|
112
|
+
const chooseConfig = instance.find(
|
|
113
|
+
(el) =>
|
|
114
|
+
el.props.accessibilityLabel ===
|
|
115
|
+
`${AccessibilityLabel.CHECK_BOX_CUSTOM}-config-${configId}`
|
|
116
|
+
);
|
|
117
|
+
await act(async () => {
|
|
118
|
+
chooseConfig.props.onPress();
|
|
119
|
+
});
|
|
120
|
+
expect(chooseConfig.props.isChecked).toEqual(status);
|
|
121
|
+
};
|
|
122
|
+
const clickChooseAction = async (instance, actionId, status) => {
|
|
123
|
+
const chooseAction = instance.find(
|
|
124
|
+
(el) =>
|
|
125
|
+
el.props.accessibilityLabel ===
|
|
126
|
+
`${AccessibilityLabel.CHECK_BOX_CUSTOM}-action-${actionId}`
|
|
127
|
+
);
|
|
128
|
+
await act(async () => {
|
|
129
|
+
chooseAction.props.onPress();
|
|
130
|
+
});
|
|
131
|
+
expect(chooseAction.props.isChecked).toEqual(status);
|
|
132
|
+
};
|
|
133
|
+
const clickExpandDevice = async (instance, deviceId, status) => {
|
|
134
|
+
const expandDevice = instance.find(
|
|
135
|
+
(el) =>
|
|
136
|
+
el.props.accessibilityLabel ===
|
|
137
|
+
`${AccessibilityLabel.SHARE_DEVICE.EXPAND_END_DEVICE}-device-${deviceId}`
|
|
138
|
+
);
|
|
139
|
+
await act(async () => {
|
|
140
|
+
expandDevice.props.onPress();
|
|
141
|
+
});
|
|
142
|
+
expect(expandDevice.props.name).toEqual(status);
|
|
143
|
+
};
|
|
144
|
+
const clickSubmitSharePermission = async (instance, dataSubmit = null) => {
|
|
145
|
+
const submitSharePermission = instance.findByType(ViewButtonBottom);
|
|
146
|
+
await act(async () => {
|
|
147
|
+
submitSharePermission.props.onRightClick();
|
|
148
|
+
});
|
|
149
|
+
if (!dataSubmit) {
|
|
150
|
+
expect(mockOnRightClick).not.toHaveBeenCalled();
|
|
151
|
+
expect(Alert.alert.mock.calls[0][1]).toEqual(
|
|
152
|
+
'Please choose at least one device.'
|
|
153
|
+
);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
expect(mockOnRightClick).toHaveBeenCalledTimes(1);
|
|
157
|
+
expect(mockOnRightClick).toHaveBeenCalledWith(dataSubmit);
|
|
158
|
+
};
|
|
159
|
+
test('render all devices', async () => {
|
|
160
|
+
mock.onGet(API.SHARE.UNIT_PERMISSIONS_v2(unitId)).reply(200, listDevices);
|
|
161
|
+
await act(async () => {
|
|
162
|
+
tree = await create(wrapComponent(unitId));
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const instance = tree.root;
|
|
166
|
+
expect(instance.findAllByType(ShareDeviceSelector)).toHaveLength(1);
|
|
167
|
+
expect(instance.findAllByType(ViewButtonBottom)).toHaveLength(1);
|
|
168
|
+
expect(instance.findAllByType(SubUnitTreeView)).toHaveLength(1);
|
|
169
|
+
await clickChooseAllDevices(instance, true);
|
|
170
|
+
await clickExpandDevice(instance, 1, 'up');
|
|
171
|
+
await clickExpandDevice(instance, 2, 'up');
|
|
172
|
+
await clickExpandDevice(instance, 4, 'up');
|
|
173
|
+
expect(instance.findAllByType(SubUnitItem)).toHaveLength(3); //All + 2 subunits
|
|
174
|
+
expect(instance.findAllByType(DeviceItem)).toHaveLength(4);
|
|
175
|
+
expect(instance.findAllByType(ConfigItem)).toHaveLength(6);
|
|
176
|
+
const dataSubmit = {
|
|
177
|
+
read_permissions: [
|
|
178
|
+
{ id: 1, values: [1] },
|
|
179
|
+
{ id: 2, values: [2] },
|
|
180
|
+
{ id: 3, values: [] },
|
|
181
|
+
{ id: 4, values: [3] },
|
|
182
|
+
],
|
|
183
|
+
control_permissions: [
|
|
184
|
+
{ id: 1, values: [1] },
|
|
185
|
+
{ id: 2, values: [2] },
|
|
186
|
+
{ id: 4, values: [3] },
|
|
187
|
+
],
|
|
188
|
+
};
|
|
189
|
+
await clickSubmitSharePermission(instance, dataSubmit);
|
|
190
|
+
});
|
|
191
|
+
test('render empty subunit', async () => {
|
|
192
|
+
mock.onGet(API.SHARE.UNIT_PERMISSIONS_v2(unitId)).reply(200, []);
|
|
193
|
+
await act(async () => {
|
|
194
|
+
tree = await create(wrapComponent(unitId));
|
|
195
|
+
});
|
|
196
|
+
const instance = tree.root;
|
|
197
|
+
const noDataText = instance.find(
|
|
198
|
+
(el) =>
|
|
199
|
+
el.props.accessibilityLabel === AccessibilityLabel.TEXT_NO_DATA_STATIONS
|
|
200
|
+
);
|
|
201
|
+
expect(noDataText).toBeDefined();
|
|
202
|
+
expect(instance.findAllByType(SubUnitItem)).toHaveLength(0);
|
|
203
|
+
expect(instance.findAllByType(DeviceItem)).toHaveLength(0);
|
|
204
|
+
expect(instance.findAllByType(ConfigItem)).toHaveLength(0);
|
|
205
|
+
await clickSubmitSharePermission(instance);
|
|
206
|
+
});
|
|
207
|
+
test('click choose end device and config', async () => {
|
|
208
|
+
mock.onGet(API.SHARE.UNIT_PERMISSIONS_v2(unitId)).reply(200, listDevices);
|
|
209
|
+
await act(async () => {
|
|
210
|
+
tree = await create(wrapComponent(unitId));
|
|
211
|
+
});
|
|
212
|
+
const instance = tree.root;
|
|
213
|
+
expect(instance.findAllByType(SubUnitItem)).toHaveLength(3); //All + 2 subunits
|
|
214
|
+
expect(instance.findAllByType(DeviceItem)).toHaveLength(4);
|
|
215
|
+
await clickChooseDevice(instance, 1, true);
|
|
216
|
+
await clickExpandDevice(instance, 1, 'up');
|
|
217
|
+
expect(instance.findAllByType(ConfigItem)).toHaveLength(2);
|
|
218
|
+
const dataSubmit = {
|
|
219
|
+
read_permissions: [{ id: 1, values: [1] }],
|
|
220
|
+
control_permissions: [{ id: 1, values: [1] }],
|
|
221
|
+
};
|
|
222
|
+
await clickSubmitSharePermission(instance, dataSubmit);
|
|
223
|
+
});
|
|
224
|
+
test('render with init keys and go back', async () => {
|
|
225
|
+
mock.onGet(API.SHARE.UNIT_PERMISSIONS_v2(unitId)).reply(200, listDevices);
|
|
226
|
+
await act(async () => {
|
|
227
|
+
tree = await create(wrapComponent(unitId, ['config-3', 'action-3']));
|
|
228
|
+
});
|
|
229
|
+
const instance = tree.root;
|
|
230
|
+
expect(instance.findAllByType(SubUnitItem)).toHaveLength(3); //All + 2 subunits
|
|
231
|
+
expect(instance.findAllByType(DeviceItem)).toHaveLength(4);
|
|
232
|
+
const iconCheck = instance.findAll(
|
|
233
|
+
(el) =>
|
|
234
|
+
el.props.accessibilityLabel ===
|
|
235
|
+
`${AccessibilityLabel.SHARE_DEVICE.ICON_CHECK}-device-4` &&
|
|
236
|
+
el.type === IconOutline
|
|
237
|
+
);
|
|
238
|
+
expect(iconCheck).toHaveLength(1);
|
|
239
|
+
await clickExpandDevice(instance, 4, 'up');
|
|
240
|
+
const config = instance.find(
|
|
241
|
+
(el) =>
|
|
242
|
+
el.props.accessibilityLabel ===
|
|
243
|
+
`${AccessibilityLabel.CHECK_BOX_CUSTOM}-config-3`
|
|
244
|
+
);
|
|
245
|
+
const action = instance.find(
|
|
246
|
+
(el) =>
|
|
247
|
+
el.props.accessibilityLabel ===
|
|
248
|
+
`${AccessibilityLabel.CHECK_BOX_CUSTOM}-action-3`
|
|
249
|
+
);
|
|
250
|
+
expect(config.props.isChecked).toEqual(true);
|
|
251
|
+
expect(action.props.isChecked).toEqual(true);
|
|
252
|
+
await clickChooseDevice(instance, 4, false);
|
|
253
|
+
|
|
254
|
+
const mockGoBack = useNavigation().goBack;
|
|
255
|
+
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
256
|
+
await act(() => {
|
|
257
|
+
viewButtonBottom.props.onLeftClick();
|
|
258
|
+
});
|
|
259
|
+
expect(mockGoBack).toHaveBeenCalledTimes(1);
|
|
260
|
+
});
|
|
261
|
+
test('test 1 config id in 2 device', async () => {
|
|
262
|
+
listDevices[0].devices[1].actions.push({ id: 3, name: 'action-3' });
|
|
263
|
+
mock.onGet(API.SHARE.UNIT_PERMISSIONS_v2(unitId)).reply(200, listDevices);
|
|
264
|
+
await act(async () => {
|
|
265
|
+
tree = await create(wrapComponent(unitId));
|
|
266
|
+
});
|
|
267
|
+
const instance = tree.root;
|
|
268
|
+
expect(instance.findAllByType(SubUnitItem)).toHaveLength(3); //All + 2 subunits
|
|
269
|
+
expect(instance.findAllByType(DeviceItem)).toHaveLength(4);
|
|
270
|
+
|
|
271
|
+
await clickExpandDevice(instance, 1, 'up');
|
|
272
|
+
await clickChooseConfig(instance, 1, true);
|
|
273
|
+
await clickChooseAction(instance, 1, true);
|
|
274
|
+
|
|
275
|
+
await clickExpandDevice(instance, 2, 'up');
|
|
276
|
+
await clickExpandDevice(instance, 4, 'up');
|
|
277
|
+
|
|
278
|
+
const actions = instance.findAll(
|
|
279
|
+
(el) =>
|
|
280
|
+
el.props.accessibilityLabel ===
|
|
281
|
+
`${AccessibilityLabel.CHECK_BOX_CUSTOM}-action-3`
|
|
282
|
+
);
|
|
283
|
+
expect(actions).toHaveLength(2);
|
|
284
|
+
await act(async () => {
|
|
285
|
+
actions[0].props.onPress();
|
|
286
|
+
});
|
|
287
|
+
expect(actions[0].props.isChecked).toEqual(true);
|
|
288
|
+
|
|
289
|
+
const dataSubmit = {
|
|
290
|
+
read_permissions: [{ id: 1, values: [1] }],
|
|
291
|
+
control_permissions: [
|
|
292
|
+
{ id: 1, values: [1] },
|
|
293
|
+
{ id: 4, values: [3] },
|
|
294
|
+
],
|
|
295
|
+
};
|
|
296
|
+
await clickSubmitSharePermission(instance, dataSubmit);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import CheckBoxCustom from './CheckBoxCustom';
|
|
2
|
+
import ConfigItem from './ConfigItem';
|
|
3
|
+
import DeviceItem from './DeviceItem';
|
|
4
|
+
import ShareDeviceSelector from './ShareDeviceSelector';
|
|
5
|
+
import SubUnitItem from './SubUnitItem';
|
|
6
|
+
import SubUnitTreeView from './SubUnitTreeView';
|
|
2
7
|
import TitleCheckBox from './TitleCheckBox';
|
|
3
8
|
|
|
4
|
-
export {
|
|
9
|
+
export {
|
|
10
|
+
CheckBoxCustom,
|
|
11
|
+
TitleCheckBox,
|
|
12
|
+
ConfigItem,
|
|
13
|
+
DeviceItem,
|
|
14
|
+
SubUnitItem,
|
|
15
|
+
SubUnitTreeView,
|
|
16
|
+
ShareDeviceSelector,
|
|
17
|
+
};
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { API, Colors, Images, SCConfig } from '../../configs';
|
|
2
|
+
import { ActivityIndicator, Image, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { AlertAction, ViewButtonBottom } from '../../commons';
|
|
4
|
+
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
|
5
|
+
import { useDataMember, useStateAlertAction } from './hooks';
|
|
6
|
+
import { useIsFocused, useNavigation } from '@react-navigation/native';
|
|
7
|
+
|
|
8
|
+
import { AccessibilityLabel } from '../../configs/Constants';
|
|
4
9
|
import { CircleView } from '../../commons/CircleView';
|
|
5
|
-
import Text from '../../commons/Text';
|
|
6
|
-
import { shortEmailName } from '../../utils/Utils';
|
|
7
|
-
import { Colors, Images, API, SCConfig } from '../../configs';
|
|
8
10
|
import { HeaderCustom } from '../../commons/Header';
|
|
9
|
-
import RowMemberInfo from '../GuestInfo/components/RowGuestInfo';
|
|
10
|
-
import { useIsOwnerOfUnit } from '../../hooks/Common';
|
|
11
|
-
import { axiosGet } from '../../utils/Apis/axios';
|
|
12
|
-
import { AlertAction, ViewButtonBottom } from '../../commons';
|
|
13
|
-
import { useStateAlertAction, useDataMember } from './hooks';
|
|
14
11
|
import ItemChangeRole from './Components/ItemChangeRole';
|
|
15
12
|
import MemberSvg from '../../Images/Common/member.svg';
|
|
13
|
+
import ModalPopupCT from '../../commons/ModalPopupCT';
|
|
16
14
|
import OwnerSvg from '../../Images/Common/owner.svg';
|
|
17
|
-
import styles from './Styles/inforMemberUnitStyles';
|
|
18
|
-
import { useNavigation, useIsFocused } from '@react-navigation/native';
|
|
19
15
|
import Routes from '../../utils/Route';
|
|
20
|
-
import
|
|
21
|
-
import
|
|
16
|
+
import RowMemberInfo from '../GuestInfo/components/RowGuestInfo';
|
|
17
|
+
import Text from '../../commons/Text';
|
|
18
|
+
import { axiosGet } from '../../utils/Apis/axios';
|
|
19
|
+
import { shortEmailName } from '../../utils/Utils';
|
|
20
|
+
import styles from './Styles/inforMemberUnitStyles';
|
|
21
|
+
import { useIsOwnerOfUnit } from '../../hooks/Common';
|
|
22
|
+
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
22
23
|
|
|
23
24
|
const InfoMemberUnit = memo(({ route }) => {
|
|
24
25
|
const t = useTranslations();
|
|
25
|
-
const { member, unit } = route?.params ||
|
|
26
|
-
{}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
};
|
|
26
|
+
const { member, unit } = route?.params || {
|
|
27
|
+
member: {},
|
|
28
|
+
unit: {},
|
|
29
|
+
};
|
|
30
30
|
const { navigate } = useNavigation();
|
|
31
31
|
const [isLoading, setIsLoading] = useState(true);
|
|
32
32
|
const [isShowWarning, setIsShowWarning] = useState(false);
|
|
@@ -1,232 +1,15 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Routes from '../../utils/Route';
|
|
3
|
+
import { ShareDeviceSelector } from './Components';
|
|
3
4
|
import { useNavigation } from '@react-navigation/native';
|
|
4
|
-
|
|
5
5
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
6
|
-
import ViewButtonBottom from '../../commons/ViewButtonBottom';
|
|
7
|
-
import Text from '../../commons/Text';
|
|
8
|
-
import styles from './Styles/SelectPermissionStyles';
|
|
9
|
-
import { axiosGet } from '../../utils/Apis/axios';
|
|
10
|
-
import Routes from '../../utils/Route';
|
|
11
|
-
import { API, Colors } from '../../configs';
|
|
12
|
-
import { AccessibilityLabel } from '../../configs/Constants';
|
|
13
|
-
import CheckBoxSubUnit from './Components/CheckBoxSubUnit';
|
|
14
|
-
import EndDevice from './Components/EndDevice';
|
|
15
6
|
|
|
16
7
|
const SelectShareDevice = ({ route }) => {
|
|
17
8
|
const { unit } = route.params;
|
|
18
|
-
const t = useTranslations();
|
|
19
9
|
const navigation = useNavigation();
|
|
20
|
-
const
|
|
21
|
-
const [isTickAllDevices, setIsTickAllDevices] = useState(false);
|
|
22
|
-
const [expandedItemIds, setExpandedItemIds] = useState([]);
|
|
23
|
-
const [needRefresh, setNeedRefresh] = useState(false);
|
|
24
|
-
const [loading, setLoading] = useState(true);
|
|
25
|
-
|
|
26
|
-
const onTickAllDevices = (indexSubUnit, isChecked) => {
|
|
27
|
-
setIsTickAllDevices(isChecked);
|
|
28
|
-
const updatedDataStations = dataStations.map((station) => ({
|
|
29
|
-
...station,
|
|
30
|
-
isChecked,
|
|
31
|
-
devices: station.devices.map((device) => ({
|
|
32
|
-
...device,
|
|
33
|
-
isChecked,
|
|
34
|
-
actions: device.actions.map((action) => ({
|
|
35
|
-
...action,
|
|
36
|
-
isChecked,
|
|
37
|
-
})),
|
|
38
|
-
read_configs: device.read_configs.map((config) => ({
|
|
39
|
-
...config,
|
|
40
|
-
isChecked,
|
|
41
|
-
})),
|
|
42
|
-
})),
|
|
43
|
-
}));
|
|
44
|
-
setDataStations(updatedDataStations);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const onTickSubUnit = (indexSubUnit, isChecked) => {
|
|
48
|
-
dataStations[indexSubUnit] = {
|
|
49
|
-
...dataStations[indexSubUnit],
|
|
50
|
-
isChecked,
|
|
51
|
-
devices: dataStations[indexSubUnit].devices.map((i) => ({
|
|
52
|
-
...i,
|
|
53
|
-
isChecked,
|
|
54
|
-
actions: i.actions.map((j) => ({ ...j, isChecked })),
|
|
55
|
-
read_configs: i.read_configs.map((j) => ({ ...j, isChecked })),
|
|
56
|
-
})),
|
|
57
|
-
};
|
|
58
|
-
setDataStations(dataStations);
|
|
59
|
-
setIsTickAllDevices(!dataStations.some((object) => !object.isChecked));
|
|
60
|
-
setNeedRefresh(true);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const onTickEndDevice = (indexSubUnit, indexEndDevice, item, isChecked) => {
|
|
64
|
-
item.isChecked = isChecked;
|
|
65
|
-
item.actions = item.actions.map((j) => ({ ...j, isChecked }));
|
|
66
|
-
item.read_configs = item.read_configs.map((j) => ({ ...j, isChecked }));
|
|
67
|
-
|
|
68
|
-
dataStations[indexSubUnit].devices[indexEndDevice] = item;
|
|
69
|
-
|
|
70
|
-
dataStations[indexSubUnit] = {
|
|
71
|
-
...dataStations[indexSubUnit],
|
|
72
|
-
isChecked:
|
|
73
|
-
dataStations[indexSubUnit].devices.length ===
|
|
74
|
-
dataStations[indexSubUnit].devices.filter((i) => i.isChecked).length,
|
|
75
|
-
};
|
|
76
|
-
setIsTickAllDevices(!dataStations.some((i) => !i.isChecked));
|
|
77
|
-
setDataStations(dataStations);
|
|
78
|
-
setNeedRefresh(true);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const onTickedChild = (
|
|
82
|
-
indexSubUnit,
|
|
83
|
-
indexEndDevice,
|
|
84
|
-
configId,
|
|
85
|
-
item,
|
|
86
|
-
isConfig,
|
|
87
|
-
isChecked
|
|
88
|
-
) => {
|
|
89
|
-
const subUnit = dataStations[indexSubUnit];
|
|
90
|
-
const device = subUnit.devices[indexEndDevice];
|
|
91
|
-
const configs = item[`${isConfig ? 'read_configs' : 'actions'}`];
|
|
92
|
-
const child = configs.find((i) => i.id === configId);
|
|
93
|
-
|
|
94
|
-
child.isChecked = isChecked;
|
|
95
|
-
device.isChecked =
|
|
96
|
-
configs.length === configs.filter((i) => i.isChecked).length;
|
|
97
|
-
|
|
98
|
-
subUnit.isChecked =
|
|
99
|
-
subUnit.devices.length ===
|
|
100
|
-
subUnit.devices.filter((i) => i.isChecked).length;
|
|
101
|
-
|
|
102
|
-
setIsTickAllDevices(!dataStations.some((i) => !i.isChecked));
|
|
103
|
-
setDataStations(dataStations);
|
|
104
|
-
setNeedRefresh(true);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const toggleExpandEndDevice = (deviceItem) => () => {
|
|
108
|
-
setExpandedItemIds((ids) => {
|
|
109
|
-
const index = ids.indexOf(deviceItem.id);
|
|
110
|
-
if (index !== -1) {
|
|
111
|
-
return [...ids.slice(0, index), ...ids.slice(index + 1)];
|
|
112
|
-
} else {
|
|
113
|
-
return [...ids, deviceItem.id];
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const expandEndDevice = (deviceItem) => () => {
|
|
119
|
-
if (!expandedItemIds.includes(deviceItem.id)) {
|
|
120
|
-
setExpandedItemIds((prev) => [...prev, deviceItem.id]);
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const GroupEndDevice = ({ item, indexSubUnit }) => {
|
|
125
|
-
const { name, devices, isChecked } = item;
|
|
126
|
-
return (
|
|
127
|
-
<View style={styles.viewGroup}>
|
|
128
|
-
<CheckBoxSubUnit
|
|
129
|
-
title={name}
|
|
130
|
-
item={item}
|
|
131
|
-
onPress={onTickSubUnit}
|
|
132
|
-
isChecked={isChecked}
|
|
133
|
-
indexSubUnit={indexSubUnit}
|
|
134
|
-
/>
|
|
135
|
-
<View style={styles.wrapDevice}>
|
|
136
|
-
{devices.map((i, index) => (
|
|
137
|
-
<EndDevice
|
|
138
|
-
item={i}
|
|
139
|
-
key={i.id}
|
|
140
|
-
onTickedChild={onTickedChild}
|
|
141
|
-
onTickEndDevice={onTickEndDevice}
|
|
142
|
-
isItemExpanded={expandedItemIds.includes(i.id)}
|
|
143
|
-
toggleExpandEndDevice={toggleExpandEndDevice(i)}
|
|
144
|
-
expandEndDevice={expandEndDevice(i)}
|
|
145
|
-
indexSubUnit={indexSubUnit}
|
|
146
|
-
indexEndDevice={index}
|
|
147
|
-
/>
|
|
148
|
-
))}
|
|
149
|
-
</View>
|
|
150
|
-
</View>
|
|
151
|
-
);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const renderSubUnit = ({ item, index }) => (
|
|
155
|
-
<GroupEndDevice key={item.id} item={item} indexSubUnit={index} />
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
const renderFlatList = useMemo(() => {
|
|
159
|
-
setNeedRefresh(false);
|
|
160
|
-
return (
|
|
161
|
-
<FlatList
|
|
162
|
-
keyExtractor={(item) => item.id}
|
|
163
|
-
extraData={dataStations}
|
|
164
|
-
data={dataStations}
|
|
165
|
-
renderItem={renderSubUnit}
|
|
166
|
-
scrollIndicatorInsets={{ right: 1 }}
|
|
167
|
-
ListHeaderComponent={
|
|
168
|
-
<CheckBoxSubUnit
|
|
169
|
-
title={t('text_all_devices')}
|
|
170
|
-
onPress={onTickAllDevices}
|
|
171
|
-
isChecked={isTickAllDevices}
|
|
172
|
-
/>
|
|
173
|
-
}
|
|
174
|
-
/>
|
|
175
|
-
);
|
|
176
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
177
|
-
}, [dataStations, isTickAllDevices, expandedItemIds, needRefresh]);
|
|
178
|
-
|
|
179
|
-
const getUnitPermission = useCallback(async () => {
|
|
180
|
-
const { success, data } = await axiosGet(
|
|
181
|
-
API.SHARE.UNIT_PERMISSIONS(unit.id)
|
|
182
|
-
);
|
|
183
|
-
if (success) {
|
|
184
|
-
setDataStations(data);
|
|
185
|
-
}
|
|
186
|
-
setLoading(false);
|
|
187
|
-
}, [unit.id]);
|
|
188
|
-
|
|
189
|
-
useEffect(() => {
|
|
190
|
-
getUnitPermission();
|
|
191
|
-
}, [getUnitPermission, unit]);
|
|
192
|
-
|
|
193
|
-
const onPressBottom = async () => {
|
|
194
|
-
setLoading(true);
|
|
195
|
-
let read_permissions = [];
|
|
196
|
-
let control_permissions = [];
|
|
197
|
-
|
|
198
|
-
for (const station of dataStations) {
|
|
199
|
-
for (const end_device of station.devices) {
|
|
200
|
-
const action_ids = end_device.actions
|
|
201
|
-
.filter((action) => action.isChecked)
|
|
202
|
-
.map((action) => action.id);
|
|
203
|
-
|
|
204
|
-
const config_ids = end_device.read_configs
|
|
205
|
-
.filter((config) => config.isChecked)
|
|
206
|
-
.map((config) => config.id);
|
|
207
|
-
|
|
208
|
-
if (action_ids.length > 0) {
|
|
209
|
-
control_permissions.push({ id: end_device.id, values: action_ids });
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (config_ids.length > 0) {
|
|
213
|
-
read_permissions.push({ id: end_device.id, values: config_ids });
|
|
214
|
-
}
|
|
10
|
+
const t = useTranslations();
|
|
215
11
|
|
|
216
|
-
|
|
217
|
-
action_ids.length === 0 &&
|
|
218
|
-
config_ids.length === 0 &&
|
|
219
|
-
end_device.isChecked
|
|
220
|
-
) {
|
|
221
|
-
read_permissions.push({ id: end_device.id, values: [] });
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
setLoading(false);
|
|
226
|
-
if (read_permissions.length === 0 && control_permissions.length === 0) {
|
|
227
|
-
Alert.alert('', t('choose_at_least_one'));
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
12
|
+
const handleOnRightClick = ({ read_permissions, control_permissions }) => {
|
|
230
13
|
navigation.navigate(Routes.SharingInviteMembers, {
|
|
231
14
|
unit,
|
|
232
15
|
permissions: { read_permissions, control_permissions },
|
|
@@ -234,39 +17,12 @@ const SelectShareDevice = ({ route }) => {
|
|
|
234
17
|
};
|
|
235
18
|
|
|
236
19
|
return (
|
|
237
|
-
<
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
<View style={styles.contentContainer}>
|
|
243
|
-
{loading ? (
|
|
244
|
-
<ActivityIndicator color={Colors.Primary} />
|
|
245
|
-
) : dataStations.length > 0 ? (
|
|
246
|
-
renderFlatList
|
|
247
|
-
) : (
|
|
248
|
-
<Text
|
|
249
|
-
style={styles.textNodata}
|
|
250
|
-
accessibilityLabel={AccessibilityLabel.TEXT_NO_DATA_STATIONS}
|
|
251
|
-
>
|
|
252
|
-
{t('no_data')}
|
|
253
|
-
</Text>
|
|
254
|
-
)}
|
|
255
|
-
</View>
|
|
256
|
-
<View style={styles.wrapViewButtonStyle}>
|
|
257
|
-
<ViewButtonBottom
|
|
258
|
-
accessibilityLabelPrefix={
|
|
259
|
-
AccessibilityLabel.PREFIX.SHARING_SELECT_PERMISSION
|
|
260
|
-
}
|
|
261
|
-
leftTitle={t('cancel')}
|
|
262
|
-
onLeftClick={() => navigation.goBack()}
|
|
263
|
-
rightTitle={t('next')}
|
|
264
|
-
rightDisabled={false}
|
|
265
|
-
onRightClick={onPressBottom}
|
|
266
|
-
/>
|
|
267
|
-
</View>
|
|
268
|
-
</View>
|
|
20
|
+
<ShareDeviceSelector
|
|
21
|
+
unitId={unit.id}
|
|
22
|
+
onRightClick={handleOnRightClick}
|
|
23
|
+
rightTitle={t('next')}
|
|
24
|
+
/>
|
|
269
25
|
);
|
|
270
26
|
};
|
|
271
27
|
|
|
272
|
-
export default
|
|
28
|
+
export default SelectShareDevice;
|