@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
@@ -1,232 +1,15 @@
1
- import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
2
- import { View, FlatList, Alert, ActivityIndicator } from 'react-native';
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 [dataStations, setDataStations] = useState([]);
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
- if (
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
- <View style={styles.wrap}>
238
- <Text semibold style={styles.title}>
239
- {t('select_device')}
240
- </Text>
241
- <Text style={styles.subtitle}>{t('sharing_select_devices_hint')}</Text>
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 memo(SelectShareDevice);
28
+ export default SelectShareDevice;
@@ -1,32 +1,32 @@
1
- import React, { useCallback, useMemo, useState } from 'react';
1
+ import { API, Colors, Theme } from '../../configs';
2
+ import { Button, ViewButtonBottom } from '../../commons';
2
3
  import {
3
4
  Keyboard,
4
5
  StyleSheet,
5
6
  TouchableWithoutFeedback,
6
7
  View,
7
8
  } from 'react-native';
8
- import { useNavigation } from '@react-navigation/native';
9
- import { getStatusBarHeight } from 'react-native-iphone-x-helper';
10
-
11
- import { useTranslations } from '../../hooks/Common/useTranslations';
12
- import { API, Colors, Theme } from '../../configs';
13
- import AccountList from '../../commons/Auth/AccountList';
14
- import _TextInput from '../../commons/Form/TextInput';
15
- import { ViewButtonBottom, Button } from '../../commons';
9
+ import React, { useCallback, useMemo, useState } from 'react';
10
+ import { axiosGet, axiosPost } from '../../utils/Apis/axios';
16
11
  import {
17
12
  isValidEmailAddress,
18
13
  isValidPhoneNumber,
19
14
  } from '../../utils/Validation';
20
- import { axiosGet, axiosPost } from '../../utils/Apis/axios';
15
+
21
16
  import { AccessibilityLabel } from '../../configs/Constants';
17
+ import AccountList from '../../commons/Auth/AccountList';
18
+ import Routes from '../../utils/Route';
22
19
  import Text from '../../commons/Text';
23
20
  import { ToastBottomHelper } from '../../utils/Utils';
24
- import Routes from '../../utils/Route';
21
+ import _TextInput from '../../commons/Form/TextInput';
22
+ import { getStatusBarHeight } from 'react-native-iphone-x-helper';
23
+ import { useNavigation } from '@react-navigation/native';
24
+ import { useTranslations } from '../../hooks/Common/useTranslations';
25
25
 
26
26
  const SharingInviteMembers = ({ route }) => {
27
27
  const t = useTranslations();
28
28
  const { goBack, navigate } = useNavigation();
29
- const { unit, permissions } = route?.params || {};
29
+ const { unit, permissions } = route?.params;
30
30
  const [errorText, setErrorText] = useState('');
31
31
  const [content, setContent] = useState('');
32
32
  const [users, setUsers] = useState([]);
@@ -1,322 +1,66 @@
1
- import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
2
- import { View, FlatList, Alert, ActivityIndicator } from 'react-native';
3
- import { useNavigation } from '@react-navigation/native';
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import { axiosGet, axiosPost } from '../../utils/Apis/axios';
4
3
 
4
+ import { API } from '../../configs';
5
+ import { ShareDeviceSelector } from './Components';
6
+ import { useNavigation } from '@react-navigation/native';
5
7
  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, axiosPost } from '../../utils/Apis/axios';
10
- import { objectIds } from '../../utils/Utils';
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
8
 
16
9
  const UpdateShareDevice = ({ route }) => {
17
- const t = useTranslations();
18
10
  const { unit, member } = route.params;
19
11
  const navigation = useNavigation();
20
- const [dataStations, setDataStations] = useState([]);
21
- const [isTickAllDevices, setIsTickAllDevices] = useState(false);
22
- const [expandedItemIds, setExpandedItemIds] = useState([]);
23
- const [loading, setLoading] = useState(true);
24
- const [needRefresh, setNeedRefresh] = useState(false);
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;
12
+ const t = useTranslations();
13
+ const [initialSelectedKeys, setInitialSelectedKeys] = useState([]);
14
+
15
+ const getInitialSelectedKeys = useCallback(
16
+ (sharedDevices) =>
17
+ sharedDevices.flatMap((subUnit) => [
18
+ `subUnit-${subUnit.id}`,
19
+ ...subUnit.devices.flatMap((device) => [
20
+ `device-${device.id}`,
21
+ ...device.actions.map((action) => `action-${action.id}`),
22
+ ...device.read_configs.map((config) => `config-${config.id}`),
23
+ ]),
24
+ ]),
25
+ []
26
+ );
101
27
 
102
- setIsTickAllDevices(!dataStations.some((i) => !i.isChecked));
103
- setDataStations(dataStations);
104
- setNeedRefresh(true);
105
- };
106
- const toggleExpandEndDevice = (deviceItem) => () => {
107
- setExpandedItemIds((ids) => {
108
- const index = ids.indexOf(deviceItem.id);
109
- if (index !== -1) {
110
- return [...ids.slice(0, index), ...ids.slice(index + 1)];
111
- } else {
112
- return [...ids, deviceItem.id];
28
+ useEffect(() => {
29
+ const getShareUnitPermission = async () => {
30
+ const { success, data } = await axiosGet(
31
+ API.SHARE.UNIT_MEMBER_SHARE_DEVICE_V2(unit.id, member.id)
32
+ );
33
+ if (success) {
34
+ const selectedKeys = getInitialSelectedKeys(data);
35
+ setInitialSelectedKeys(selectedKeys);
113
36
  }
114
- });
115
- };
116
-
117
- const expandEndDevice = (deviceItem) => () => {
118
- if (!expandedItemIds.includes(deviceItem.id)) {
119
- setExpandedItemIds((prev) => [...prev, deviceItem.id]);
120
- }
121
- };
122
-
123
- const autoCheckedGroup = (stations, dataDeviceShared) => {
124
- const { deviceIds, actionIds, configIds } = objectIds(dataDeviceShared);
125
- const updatedStations = stations.map((station) => ({
126
- ...station,
127
- isChecked: station.devices.every((device) =>
128
- deviceIds.includes(device.id)
129
- ),
130
- devices: station.devices.map((device) => ({
131
- ...device,
132
- isChecked: deviceIds.includes(device.id),
133
- actions: device.actions.map((action) => ({
134
- ...action,
135
- isChecked: actionIds.includes(action.id),
136
- })),
137
- read_configs: device.read_configs.map((config) => ({
138
- ...config,
139
- isChecked: configIds.includes(config.id),
140
- })),
141
- })),
142
- }));
143
- setDataStations(updatedStations);
144
- setIsTickAllDevices(
145
- updatedStations.length ===
146
- updatedStations.filter((i) => i.isChecked).length
147
- );
148
- };
149
-
150
- const GroupEndDevice = ({ item, indexSubUnit }) => {
151
- const { name, devices, isChecked } = item;
152
- return (
153
- <View style={styles.viewGroup}>
154
- <CheckBoxSubUnit
155
- title={name}
156
- onPress={onTickSubUnit}
157
- isChecked={isChecked}
158
- indexSubUnit={indexSubUnit}
159
- />
160
- <View style={styles.wrapDevice}>
161
- {devices.map((i, index) => (
162
- <EndDevice
163
- item={i}
164
- key={i.id}
165
- onTickedChild={onTickedChild}
166
- onTickEndDevice={onTickEndDevice}
167
- isItemExpanded={expandedItemIds.includes(i.id)}
168
- toggleExpandEndDevice={toggleExpandEndDevice(i)}
169
- expandEndDevice={expandEndDevice(i)}
170
- indexSubUnit={indexSubUnit}
171
- indexEndDevice={index}
172
- />
173
- ))}
174
- </View>
175
- </View>
176
- );
177
- };
178
-
179
- const onPressBottom = async () => {
180
- setLoading(true);
181
- let read_permissions = [];
182
- let control_permissions = [];
183
-
184
- for (const station of dataStations) {
185
- for (const end_device of station.devices) {
186
- const action_ids = end_device.actions
187
- .filter((action) => action.isChecked)
188
- .map((action) => action.id);
189
-
190
- const config_ids = end_device.read_configs
191
- .filter((config) => config.isChecked)
192
- .map((config) => config.id);
193
-
194
- if (action_ids.length > 0) {
195
- control_permissions.push({ id: end_device.id, values: action_ids });
196
- }
197
-
198
- if (config_ids.length > 0) {
199
- read_permissions.push({ id: end_device.id, values: config_ids });
200
- }
37
+ };
201
38
 
202
- if (
203
- action_ids.length === 0 &&
204
- config_ids.length === 0 &&
205
- end_device.isChecked
206
- ) {
207
- read_permissions.push({ id: end_device.id, values: [] });
208
- }
209
- }
210
- }
39
+ getShareUnitPermission();
40
+ }, [unit.id, member.id, getInitialSelectedKeys]);
211
41
 
212
- if (!read_permissions.length && !control_permissions.length) {
213
- setLoading(false);
214
- Alert.alert('', t('choose_at_least_one'));
215
- return;
216
- }
217
- let phone = '';
218
- let email = '';
219
- if (member.phone_number) {
220
- phone = member.phone_number;
221
- email = '';
222
- } else if (member.email) {
223
- phone = '';
224
- email = member.email;
225
- }
226
- const { success } = await axiosPost(API.SHARE.SHARE(), {
227
- phone,
228
- email,
42
+ const handleOnRightClick = async ({
43
+ read_permissions,
44
+ control_permissions,
45
+ }) => {
46
+ const { success } = await axiosPost(API.SHARE.SHARE_V2(), {
47
+ user_ids: [member.id],
229
48
  unit: unit.id,
230
49
  permissions: { read_permissions, control_permissions },
231
50
  is_remove_old_permission: true,
232
51
  });
233
- setLoading(false);
52
+
234
53
  success && navigation.goBack();
235
54
  };
236
55
 
237
- const renderSubUnit = ({ item, index }) => (
238
- <GroupEndDevice key={item.id} item={item} indexSubUnit={index} />
239
- );
240
-
241
- const renderFlatList = useMemo(() => {
242
- setNeedRefresh(false);
243
- return (
244
- <FlatList
245
- keyExtractor={(item) => item.id}
246
- extraData={dataStations}
247
- data={dataStations}
248
- renderItem={renderSubUnit}
249
- scrollIndicatorInsets={{ right: 1 }}
250
- ListHeaderComponent={
251
- <CheckBoxSubUnit
252
- title={t('text_all_devices')}
253
- onPress={onTickAllDevices}
254
- isChecked={isTickAllDevices}
255
- />
256
- }
257
- />
258
- );
259
- // eslint-disable-next-line react-hooks/exhaustive-deps
260
- }, [dataStations, isTickAllDevices, expandedItemIds, needRefresh]);
261
-
262
- const getShareUnitPermission = useCallback(
263
- async (stations) => {
264
- const { success, data } = await axiosGet(
265
- API.SHARE.UNIT_MEMBER_SHARE_DEVICE(unit.id, member.id)
266
- );
267
- if (success) {
268
- autoCheckedGroup(stations, data);
269
- }
270
- },
271
- [member.id, unit.id]
272
- );
273
-
274
- const getUnitPermission = useCallback(async () => {
275
- const { success, data } = await axiosGet(
276
- API.SHARE.UNIT_PERMISSIONS(unit.id)
277
- );
278
- if (success) {
279
- setDataStations(data);
280
- await getShareUnitPermission(data);
281
- }
282
- setLoading(false);
283
- }, [getShareUnitPermission, unit.id]);
284
-
285
- useEffect(() => {
286
- getUnitPermission();
287
- }, [getUnitPermission]);
288
-
289
56
  return (
290
- <View style={styles.wrap}>
291
- <Text semibold style={styles.title}>
292
- {t('select_device')}
293
- </Text>
294
- <Text style={styles.subtitle}>{t('sharing_select_devices_hint')}</Text>
295
- <View style={styles.contentContainer}>
296
- {loading ? (
297
- <ActivityIndicator color={Colors.Primary} />
298
- ) : dataStations.length > 0 ? (
299
- renderFlatList
300
- ) : (
301
- <Text
302
- style={styles.textNodata}
303
- accessibilityLabel={AccessibilityLabel.TEXT_NO_DATA_STATIONS}
304
- >
305
- {t('no_data')}
306
- </Text>
307
- )}
308
- </View>
309
- <View style={styles.wrapViewButtonStyle}>
310
- <ViewButtonBottom
311
- leftTitle={t('cancel')}
312
- onLeftClick={() => navigation.goBack()}
313
- rightTitle={t('done')}
314
- rightDisabled={false}
315
- onRightClick={onPressBottom}
316
- />
317
- </View>
318
- </View>
57
+ <ShareDeviceSelector
58
+ unitId={unit.id}
59
+ onRightClick={handleOnRightClick}
60
+ rightTitle={t('done')}
61
+ initialSelectedKeys={initialSelectedKeys}
62
+ />
319
63
  );
320
64
  };
321
65
 
322
- export default memo(UpdateShareDevice);
66
+ export default UpdateShareDevice;