@eohjsc/react-native-smart-city 0.7.21 → 0.7.23

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.
Files changed (101) hide show
  1. package/package.json +1 -1
  2. package/src/Images/Common/default_end_device.png +0 -0
  3. package/src/commons/ActionGroup/TerminalBoxTemplate.js +3 -0
  4. package/src/commons/ActionTemplate/OnOffButtonAction.js +38 -4
  5. package/src/commons/ActionTemplate/OnOffSimpleAction.js +55 -15
  6. package/src/commons/ActionTemplate/OnOffSmartLockAction.js +46 -8
  7. package/src/commons/ActionTemplate/SwitchButtonAction.js +35 -4
  8. package/src/commons/ActionTemplate/ThreeButtonAction.js +13 -3
  9. package/src/commons/ActionTemplate/__test__/OnOffButtonAction.test.js +46 -7
  10. package/src/commons/ActionTemplate/__test__/OnOffSimpleAction.test.js +66 -6
  11. package/src/commons/ActionTemplate/__test__/OnOffSmartLockAction.test.js +53 -13
  12. package/src/commons/ActionTemplate/__test__/SwitchButtonAction.test.js +46 -7
  13. package/src/commons/ActionTemplate/__test__/index.test.js +6 -2
  14. package/src/commons/ActionTemplate/index.js +65 -10
  15. package/src/commons/Dashboard/MyUnit/index.js +19 -20
  16. package/src/commons/DevMode/Search.js +1 -1
  17. package/src/commons/Device/RainningSensor/CurrentRainSensor.js +5 -5
  18. package/src/commons/MediaPlayerDetail/MediaPlayerFull.js +26 -32
  19. package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +8 -6
  20. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +6 -0
  21. package/src/commons/SubUnit/OneTap/index.js +5 -0
  22. package/src/commons/UnitSummary/ConfigHistoryChart/index.js +9 -11
  23. package/src/commons/Widgets/IFrameWithConfig/IFrameWithConfig.js +2 -2
  24. package/src/commons/Widgets/IFrameWithConfig/__tests__/IFrameWithConfig.test.js +1 -1
  25. package/src/configs/API.js +10 -0
  26. package/src/configs/AccessibilityLabel.js +5 -1
  27. package/src/configs/Images.js +1 -0
  28. package/src/navigations/AddMemberStack.js +3 -3
  29. package/src/screens/ActivityLog/__test__/index.test.js +10 -0
  30. package/src/screens/ActivityLog/hooks/index.js +1 -1
  31. package/src/screens/AddCommon/SelectUnit.js +3 -2
  32. package/src/screens/AddLocationMaps/__test__/index.test.js +13 -13
  33. package/src/screens/Automate/AddNewAction/ChooseAction.js +15 -51
  34. package/src/screens/Automate/AddNewAction/SelectControlDevices.js +13 -3
  35. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +74 -54
  36. package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +114 -4
  37. package/src/screens/Automate/AddNewAction/__test__/ChooseConfig.test.js +9 -11
  38. package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +37 -8
  39. package/src/screens/Automate/AddNewAutoSmart/AddTypeSmart.js +5 -0
  40. package/src/screens/Automate/AddNewAutoSmart/__test__/AddAutomationTypeSmart.test.js +31 -0
  41. package/src/screens/Automate/AddNewAutoSmart/__test__/AddNewAutoSmart.test.js +18 -2
  42. package/src/screens/Automate/Components/InputName.js +7 -6
  43. package/src/screens/Automate/Constants.js +12 -0
  44. package/src/screens/Automate/EditActionsList/UpdateActionScript.js +24 -55
  45. package/src/screens/Automate/EditActionsList/__tests__/UpdateActionScript.test.js +298 -41
  46. package/src/screens/Automate/EditActionsList/__tests__/index.test.js +2 -2
  47. package/src/screens/Automate/EditActionsList/index.js +26 -14
  48. package/src/screens/Automate/MultiUnits.js +9 -1
  49. package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +3 -3
  50. package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +4 -10
  51. package/src/screens/Automate/ScriptDetail/Components/DeleteScript.js +2 -4
  52. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +78 -0
  53. package/src/screens/Automate/ScriptDetail/index.js +16 -10
  54. package/src/screens/Automate/ScriptDetail/utils.js +39 -35
  55. package/src/screens/Automate/SetSchedule/AddEditConditionSchedule.js +27 -160
  56. package/src/screens/Automate/SetSchedule/EditSchedule.js +269 -0
  57. package/src/screens/Automate/SetSchedule/__test__/AddEditConditionSchedule.test.js +327 -22
  58. package/src/screens/Automate/SetSchedule/__test__/index.test.js +35 -22
  59. package/src/screens/Automate/SetSchedule/components/RepeatOptionsPopup.js +2 -8
  60. package/src/screens/Automate/SetSchedule/index.js +15 -129
  61. package/src/screens/Automate/SetSchedule/styles/indexStyles.js +9 -0
  62. package/src/screens/Automate/__test__/MultiUnits.test.js +6 -1
  63. package/src/screens/Automate/hooks/useAction.js +222 -0
  64. package/src/screens/ConfirmUnitDeletion/__test__/ConfirmUnitDeletion.test.js +69 -13
  65. package/src/screens/ConfirmUnitDeletion/index.js +14 -14
  66. package/src/screens/Device/__test__/detail.test.js +48 -1
  67. package/src/screens/Device/detail.js +46 -3
  68. package/src/screens/PlayBackCamera/__test__/index.test.js +48 -13
  69. package/src/screens/PlayBackCamera/index.js +1 -1
  70. package/src/screens/Sharing/Components/ConfigItem.js +34 -0
  71. package/src/screens/Sharing/Components/DeviceItem.js +77 -0
  72. package/src/screens/Sharing/Components/ItemChangeRole.js +3 -4
  73. package/src/screens/Sharing/Components/ShareDeviceSelector.js +255 -0
  74. package/src/screens/Sharing/Components/Styles/CheckBoxCustomStyles.js +1 -1
  75. package/src/screens/Sharing/Components/Styles/DeviceItemStyles.js +11 -27
  76. package/src/screens/Sharing/{Styles/SelectPermissionStyles.js → Components/Styles/ShareDeviceSelectorStyles.js} +3 -11
  77. package/src/screens/Sharing/Components/SubUnitItem.js +28 -0
  78. package/src/screens/Sharing/Components/SubUnitTreeView.js +68 -0
  79. package/src/screens/Sharing/Components/TitleCheckBox.js +23 -41
  80. package/src/screens/Sharing/Components/__test__/ItemChangeRole.test.js +7 -7
  81. package/src/screens/Sharing/Components/__test__/ShareDeviceSelector.test.js +298 -0
  82. package/src/screens/Sharing/Components/index.js +14 -1
  83. package/src/screens/Sharing/InfoMemberUnit.js +20 -20
  84. package/src/screens/Sharing/SelectShareDevice.js +11 -255
  85. package/src/screens/Sharing/SelectUser.js +12 -12
  86. package/src/screens/Sharing/UpdateShareDevice.js +45 -301
  87. package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +58 -11
  88. package/src/screens/Sharing/__test__/SelectShareDevice.test.js +51 -160
  89. package/src/screens/Sharing/__test__/SelectUser.test.js +72 -10
  90. package/src/screens/Sharing/__test__/UpdateShareDevice.test.js +49 -209
  91. package/src/utils/Apis/axios.js +6 -0
  92. package/src/utils/I18n/translations/en.js +9 -1
  93. package/src/utils/I18n/translations/vi.js +10 -2
  94. package/src/commons/Sharing/StationDevicePermissions.js +0 -204
  95. package/src/screens/Automate/constants.js +0 -0
  96. package/src/screens/Sharing/Components/CheckBoxConfig.js +0 -44
  97. package/src/screens/Sharing/Components/CheckBoxSubUnit.js +0 -35
  98. package/src/screens/Sharing/Components/EndDevice.js +0 -93
  99. package/src/screens/Sharing/Components/Styles/CheckBoxConfigStyles.js +0 -18
  100. package/src/screens/Sharing/Components/Styles/TitleCheckBoxStyles.js +0 -21
  101. package/src/screens/Sharing/Components/__test__/TitleCheckBox.test.js +0 -31
@@ -0,0 +1,68 @@
1
+ import {
2
+ AccessibilityLabel,
3
+ Constants,
4
+ normalize,
5
+ } from '../../../configs/Constants';
6
+ import { FlatList, Text, View } from 'react-native';
7
+
8
+ import React from 'react';
9
+ import { StyleSheet } from 'react-native';
10
+ import SubUnitItem from './SubUnitItem';
11
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
12
+
13
+ const SubUnitTreeNode = ({ dataNode, render }) => {
14
+ return (
15
+ <View>
16
+ {render &&
17
+ render({
18
+ item: dataNode,
19
+ childrenRender: (dataNode?.children || []).map((child) => (
20
+ <SubUnitTreeNode key={child.key} dataNode={child} render={render} />
21
+ )),
22
+ })}
23
+ </View>
24
+ );
25
+ };
26
+
27
+ const SubUnitTreeView = ({ data, render, selectedKeys, onSelect }) => {
28
+ const t = useTranslations();
29
+ const { key, children: subUnitsData } = data[0];
30
+ return (
31
+ <View>
32
+ <FlatList
33
+ data={subUnitsData}
34
+ renderItem={({ item }) => (
35
+ <SubUnitTreeNode dataNode={item} render={render} />
36
+ )}
37
+ extraData={subUnitsData}
38
+ keyExtractor={(item) => item.key}
39
+ ListHeaderComponent={
40
+ subUnitsData.length && (
41
+ <SubUnitItem
42
+ isChecked={selectedKeys.includes(key)}
43
+ item={data[0]}
44
+ onSelect={onSelect}
45
+ />
46
+ )
47
+ }
48
+ ListEmptyComponent={() => (
49
+ <Text
50
+ style={styles.textNodata}
51
+ accessibilityLabel={AccessibilityLabel.TEXT_NO_DATA_STATIONS}
52
+ >
53
+ {t('no_data')}
54
+ </Text>
55
+ )}
56
+ />
57
+ </View>
58
+ );
59
+ };
60
+
61
+ const styles = StyleSheet.create({
62
+ textNodata: {
63
+ alignSelf: 'center',
64
+ marginTop: normalize(Constants.height * 0.3),
65
+ },
66
+ });
67
+
68
+ export default SubUnitTreeView;
@@ -1,51 +1,33 @@
1
- import React, { useEffect, useState } from 'react';
2
- import { View, Text } from 'react-native';
1
+ import AccessibilityLabel from '../../../configs/AccessibilityLabel';
3
2
  import { CheckBoxCustom } from '.';
4
- import t from '../../../hooks/Common/useTranslations';
5
- import styles from './Styles/TitleCheckBoxStyles';
3
+ import React from 'react';
4
+ import { StyleSheet } from 'react-native';
5
+ import { Text } from '../../../commons';
6
+ import { View } from 'react-native';
6
7
 
7
- const TitleCheckBox = ({
8
- isChecked = false,
9
- onPress,
10
- title = '',
11
- id,
12
- wrapCheckBoxStyle,
13
- wrapStyle,
14
- titleStyle,
15
- idGroup,
16
- isConfig,
17
- isControl,
18
- }) => {
19
- const [checked, setChecked] = useState(isChecked);
8
+ const TitleCheckBox = ({ isChecked, item, onSelect, checkBoxStyle }) => {
9
+ const { label, key } = item;
20
10
  const handleOnPress = () => {
21
- setChecked(!checked);
22
- onPress && onPress(idGroup, !checked, id);
11
+ onSelect(item, !isChecked);
23
12
  };
24
-
25
- useEffect(() => {
26
- isChecked !== checked && setChecked(isChecked);
27
- // eslint-disable-next-line react-hooks/exhaustive-deps
28
- }, [isChecked]);
29
-
30
13
  return (
31
- <View style={[styles.wrap, wrapStyle]}>
32
- <View style={styles.wrapRow}>
33
- <CheckBoxCustom
34
- isChecked={checked}
35
- onPress={handleOnPress}
36
- wrapStyle={wrapCheckBoxStyle}
37
- id={idGroup}
38
- />
39
- <Text onPress={handleOnPress} style={[styles.title, titleStyle]}>
40
- {title}
41
- </Text>
42
- </View>
43
- <View>
44
- {isControl && <Text>{t('can_control')}</Text>}
45
- {isConfig && <Text>{t('view_only')}</Text>}
46
- </View>
14
+ <View style={styles.wrapRow}>
15
+ <CheckBoxCustom
16
+ isChecked={isChecked}
17
+ onPress={handleOnPress}
18
+ wrapStyle={checkBoxStyle}
19
+ accessibilityLabel={`${AccessibilityLabel.SHARE_DEVICE.CHECK_BOX_CUSTOM}-${key}`}
20
+ />
21
+ <Text onPress={handleOnPress}>{label}</Text>
47
22
  </View>
48
23
  );
49
24
  };
50
25
 
26
+ const styles = StyleSheet.create({
27
+ wrapRow: {
28
+ flexDirection: 'row',
29
+ alignItems: 'center',
30
+ },
31
+ });
32
+
51
33
  export default TitleCheckBox;
@@ -1,15 +1,15 @@
1
- import React from 'react';
2
- import { create, act } from 'react-test-renderer';
1
+ import { act, create } from 'react-test-renderer';
3
2
 
4
- import { SCProvider } from '../../../../context';
5
- import { mockSCStore } from '../../../../context/mockStore';
6
3
  import ItemChangeRole from '../ItemChangeRole';
4
+ import React from 'react';
5
+ import { SCProvider } from '../../../../context';
7
6
  import { TouchableOpacity } from 'react-native';
7
+ import { mockSCStore } from '../../../../context/mockStore';
8
8
 
9
9
  const mockOnPress = jest.fn();
10
- const wrapComponent = () => (
10
+ const wrapComponent = (disabled) => (
11
11
  <SCProvider initState={mockSCStore({})}>
12
- <ItemChangeRole onPress={mockOnPress} />
12
+ <ItemChangeRole onPress={mockOnPress} disabled={disabled} />
13
13
  </SCProvider>
14
14
  );
15
15
 
@@ -17,7 +17,7 @@ describe('test ItemChangeRole', () => {
17
17
  it('test ItemChangeRole', async () => {
18
18
  let tree;
19
19
  await act(async () => {
20
- tree = await create(wrapComponent());
20
+ tree = await create(wrapComponent(true));
21
21
  });
22
22
  const instance = tree.root;
23
23
  const touchableOpacity = instance.findAllByType(TouchableOpacity);
@@ -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 { CheckBoxCustom, TitleCheckBox };
9
+ export {
10
+ CheckBoxCustom,
11
+ TitleCheckBox,
12
+ ConfigItem,
13
+ DeviceItem,
14
+ SubUnitItem,
15
+ SubUnitTreeView,
16
+ ShareDeviceSelector,
17
+ };
@@ -1,32 +1,32 @@
1
- import React, { useState, useCallback, useEffect, memo, useMemo } from 'react';
2
- import { View, ActivityIndicator, Image, TouchableOpacity } from 'react-native';
3
- import { useTranslations } from '../../hooks/Common/useTranslations';
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 { AccessibilityLabel } from '../../configs/Constants';
21
- import ModalPopupCT from '../../commons/ModalPopupCT';
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
- member: {},
28
- unit: {},
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);