@eohjsc/react-native-smart-city 0.5.1 → 0.5.2-rc

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 (36) hide show
  1. package/package.json +1 -1
  2. package/src/commons/ActionGroup/OnOffTemplate/OnOffSimpleTemplateStyle.js +1 -0
  3. package/src/commons/ActionGroup/SliderRangeTemplate.js +10 -3
  4. package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +4 -0
  5. package/src/commons/ProcessingBar/index.js +32 -0
  6. package/src/commons/ProcessingBar/styles.js +57 -0
  7. package/src/configs/AccessibilityLabel.js +8 -0
  8. package/src/navigations/AddMemberStack.js +8 -3
  9. package/src/screens/AddCommon/SelectUnit.js +1 -1
  10. package/src/screens/AddCommon/__test__/SelectUnit.test.js +1 -1
  11. package/src/screens/EnterPassword/index.js +3 -2
  12. package/src/screens/Sharing/Components/CheckBoxConfig.js +44 -0
  13. package/src/screens/Sharing/Components/CheckBoxCustom.js +2 -13
  14. package/src/screens/Sharing/Components/CheckBoxSubUnit.js +35 -0
  15. package/src/screens/Sharing/Components/EndDevice.js +93 -0
  16. package/src/screens/Sharing/Components/Styles/CheckBoxConfigStyles.js +18 -0
  17. package/src/screens/Sharing/Components/Styles/DeviceItemStyles.js +28 -35
  18. package/src/screens/Sharing/Components/index.js +1 -2
  19. package/src/screens/Sharing/InfoMemberUnit.js +5 -3
  20. package/src/screens/Sharing/SelectShareDevice.js +273 -0
  21. package/src/screens/Sharing/SelectUser.js +6 -0
  22. package/src/screens/Sharing/Styles/SelectPermissionStyles.js +2 -11
  23. package/src/screens/Sharing/UnitMemberList.js +2 -1
  24. package/src/screens/Sharing/UpdateShareDevice.js +322 -0
  25. package/src/screens/Sharing/__test__/SelectShareDevice.test.js +215 -0
  26. package/src/screens/Sharing/__test__/UnitMemberList.test.js +1 -1
  27. package/src/screens/Sharing/__test__/UpdateShareDevice.test.js +307 -0
  28. package/src/screens/Sharing/hooks/index.js +5 -0
  29. package/src/screens/SubUnit/AddSubUnit.js +2 -6
  30. package/src/screens/SubUnit/EditSubUnitStyles.js +2 -1
  31. package/src/screens/Unit/AddMenu.js +1 -1
  32. package/src/utils/Route/index.js +2 -1
  33. package/src/screens/Sharing/Components/DeviceItem.js +0 -146
  34. package/src/screens/Sharing/Components/__test__/DeviceItem.test.js +0 -48
  35. package/src/screens/Sharing/SharingSelectPermission.js +0 -409
  36. package/src/screens/Sharing/__test__/SharingSelectPermission.test.js +0 -292
@@ -1,146 +0,0 @@
1
- import React, { memo, useEffect, useMemo, useState } from 'react';
2
- import {
3
- View,
4
- Text,
5
- LayoutAnimation,
6
- Platform,
7
- UIManager,
8
- TouchableOpacity,
9
- } from 'react-native';
10
- import { IconOutline } from '@ant-design/icons-react-native';
11
- import { Colors } from '../../../configs';
12
- import styles from './Styles/DeviceItemStyles';
13
- import FImage from '../../../commons/FImage';
14
- import { TitleCheckBox } from '.';
15
- import { CheckBoxCustom } from '.';
16
- import { AccessibilityLabel } from '../../../configs/Constants';
17
-
18
- const DeviceItem = ({
19
- item = {},
20
- isRenderSeparated,
21
- onTickedChild,
22
- onTickedDevice,
23
- onTickedDeviceIcon,
24
- isItemExpanded,
25
- toggleItem,
26
- idGroup,
27
- }) => {
28
- const {
29
- id = '',
30
- name = '',
31
- actions = [],
32
- read_configs = [],
33
- icon_kit = '',
34
- isChecked,
35
- } = item;
36
- const [dataConfig, setDataConfig] = useState([
37
- ...actions.map((i) => ({ ...i, isControl: true })),
38
- ...read_configs.map((i) => ({ ...i, isConfig: true })),
39
- ]);
40
-
41
- const onPressItem = () => {
42
- if (dataConfig.length > 0) {
43
- toggleItem();
44
- LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
45
- } else {
46
- handleOnTickedDevice();
47
- }
48
- };
49
-
50
- const handleOnTickedChild = (group, checked, childId) => {
51
- const dataTemp = [...dataConfig];
52
- const indexTemp = dataTemp.findIndex((i) => i.id === childId);
53
- dataTemp.splice(indexTemp, 1, {
54
- ...dataTemp[indexTemp],
55
- isChecked: checked,
56
- });
57
- setDataConfig(dataTemp);
58
- onTickedChild &&
59
- onTickedChild(
60
- group,
61
- id,
62
- childId,
63
- checked,
64
- Boolean(dataTemp[indexTemp]?.isConfig)
65
- );
66
- };
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
-
76
- const handleOnTickedDevice = () => {
77
- onTickedDevice && onTickedDevice(idGroup, id, !isChecked);
78
- };
79
-
80
- useEffect(() => {
81
- Platform.OS === 'android' &&
82
- UIManager.setLayoutAnimationEnabledExperimental &&
83
- UIManager.setLayoutAnimationEnabledExperimental(true);
84
- }, []);
85
-
86
- const renderData = useMemo(() => {
87
- return dataConfig.map((i) => (
88
- <TitleCheckBox
89
- title={i.name}
90
- wrapCheckBoxStyle={styles.wrapCheckBoxStyle}
91
- onPress={handleOnTickedChild}
92
- isChecked={i.isChecked}
93
- id={i.id}
94
- titleStyle={styles.titleStyle}
95
- key={i.id}
96
- idGroup={idGroup}
97
- isConfig={i.isConfig}
98
- isControl={i.isControl}
99
- wrapStyle={styles.wrapStyleTitle}
100
- />
101
- ));
102
- // eslint-disable-next-line react-hooks/exhaustive-deps
103
- }, [dataConfig]);
104
-
105
- return (
106
- <View style={[styles.wrap, !isRenderSeparated && styles.isRenderSeparated]}>
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>
114
- <View style={styles.wrapRight}>
115
- <View style={styles.viewRight}>
116
- <Text
117
- numberOfLines={1}
118
- style={styles.text}
119
- onPress={onPressItem}
120
- accessibilityLabel={AccessibilityLabel.TEXT_SENSOR_ITEM}
121
- >
122
- {name}
123
- </Text>
124
- {dataConfig.length > 0 ? (
125
- <IconOutline
126
- onPress={onPressItem}
127
- name={isItemExpanded ? 'up' : 'down'}
128
- size={20}
129
- color={Colors.Gray6}
130
- />
131
- ) : (
132
- <CheckBoxCustom
133
- isChecked={isChecked}
134
- onPress={onPressItem}
135
- wrapStyle={styles.checkBox}
136
- />
137
- )}
138
- </View>
139
- {isItemExpanded && <View style={styles.wrapExpand}>{renderData}</View>}
140
- {isRenderSeparated && <View style={styles.viewSeparated} />}
141
- </View>
142
- </View>
143
- );
144
- };
145
-
146
- export default memo(DeviceItem);
@@ -1,48 +0,0 @@
1
- import React from 'react';
2
- import { create, act } from 'react-test-renderer';
3
-
4
- import { SCProvider } from '../../../../context';
5
- import { mockSCStore } from '../../../../context/mockStore';
6
- import DeviceItem from '../DeviceItem';
7
- import { Text } from 'react-native';
8
- import { AccessibilityLabel } from '../../../../configs/Constants';
9
-
10
- const mockOnTickedDevice = jest.fn();
11
- const mockOnTickedChild = jest.fn();
12
- const wrapComponent = (item) => (
13
- <SCProvider initState={mockSCStore({})}>
14
- <DeviceItem
15
- item={item}
16
- onTickedChild={mockOnTickedChild}
17
- onTickedSensor={mockOnTickedDevice}
18
- activeItemId={item.id}
19
- />
20
- </SCProvider>
21
- );
22
-
23
- describe('test DeviceTemplate', () => {
24
- it('test DeviceTemplate', async () => {
25
- const item = {
26
- id: 1,
27
- name: 'abc',
28
- actions: [],
29
- read_configs: [],
30
- icon_kit: '',
31
- isChecked: true,
32
- };
33
- let tree;
34
- await act(async () => {
35
- tree = await create(wrapComponent(item));
36
- });
37
- const instance = tree.root;
38
- const onPressText = instance.find(
39
- (el) =>
40
- el.type === Text &&
41
- el.props.accessibilityLabel === AccessibilityLabel.TEXT_SENSOR_ITEM
42
- );
43
- expect(onPressText).toBeDefined();
44
- await act(async () => {
45
- onPressText.props.onPress();
46
- });
47
- });
48
- });
@@ -1,409 +0,0 @@
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';
4
-
5
- import { useTranslations } from '../../hooks/Common/useTranslations';
6
- import ViewButtonBottom from '../../commons/ViewButtonBottom';
7
- import Text from '../../commons/Text';
8
- import { DeviceItem, TitleCheckBox } from './Components';
9
- import styles from './Styles/SelectPermissionStyles';
10
- import { axiosGet, axiosPost } from '../../utils/Apis/axios';
11
- import { objectIds } from '../../utils/Utils';
12
- import Routes from '../../utils/Route';
13
- import { API, Colors } from '../../configs';
14
- import { AccessibilityLabel } from '../../configs/Constants';
15
-
16
- let dataStationTemp = [];
17
-
18
- const SharingSelectPermission = ({ route }) => {
19
- const t = useTranslations();
20
- const { unit, type = '', member } = route?.params || {};
21
- const navigation = useNavigation();
22
- const [dataStations, setDataStations] = useState([]);
23
- const [isTickAllDevices, setIsTickAllDevices] = useState(false);
24
- const [expandedItemIds, setExpandedItemIds] = useState([]);
25
- const [loading, setLoading] = useState(true);
26
- const [hasDataChecked, setHasDataChecked] = useState(false);
27
- const [dataDeviceShared, setDataDeviceShared] = useState([]);
28
-
29
- const isUpdateSharedDevice = useMemo(() => {
30
- return type === 'update_shared';
31
- }, [type]);
32
-
33
- const onTickTitle = (idGroup, isChecked, id) => {
34
- if (!idGroup) {
35
- setIsTickAllDevices(isChecked);
36
- const data = dataStations.map((i) => ({
37
- ...i,
38
- isChecked,
39
- }));
40
- for (let station in data) {
41
- for (let item in data[station].devices) {
42
- const itemTemp = data[station].devices[item];
43
- data[station].devices[item] = {
44
- ...itemTemp,
45
- isChecked,
46
- actions: itemTemp.actions.map((i) => ({
47
- ...i,
48
- isChecked,
49
- })),
50
- read_configs: itemTemp.read_configs.map((i) => ({
51
- ...i,
52
- isChecked,
53
- })),
54
- };
55
- }
56
- }
57
- setDataStations(data);
58
- } else {
59
- const data = [...dataStationTemp];
60
-
61
- const index = data.findIndex((item) => item.id === idGroup);
62
-
63
- data[index] = {
64
- ...data[index],
65
- isChecked,
66
- devices: data[index]?.devices.map((i) => ({
67
- ...i,
68
- isChecked,
69
- actions: i.actions.map((j) => ({ ...j, isChecked })),
70
- read_configs: i.read_configs.map((j) => ({ ...j, isChecked })),
71
- })),
72
- };
73
- setDataStations(data);
74
- setIsTickAllDevices(!data.some((item) => !item.isChecked));
75
- }
76
- };
77
-
78
- const onTickedChild = (
79
- idGroup,
80
- deviceId,
81
- childId,
82
- isChecked,
83
- isReadConfig
84
- ) => {
85
- let data = [...dataStationTemp];
86
- const group = data.find((i) => i.id === idGroup);
87
- const device = group.devices.find((i) => i.id === deviceId);
88
- const child = device[`${isReadConfig ? 'read_configs' : 'actions'}`].find(
89
- (i) => i.id === childId
90
- );
91
-
92
- child.isChecked = isChecked;
93
- device.isChecked = !(
94
- device.read_configs.some((i) => !i.isChecked) ||
95
- device.actions.some((i) => !i.isChecked)
96
- );
97
- for (let station of data) {
98
- if (station.devices.length) {
99
- station.isChecked = station.devices.some(
100
- (i) =>
101
- i.read_configs.some((r) => r.isChecked) ||
102
- i.actions.some((a) => a.isChecked)
103
- );
104
- }
105
- }
106
- setIsTickAllDevices(!dataStationTemp.some((i) => !i.isChecked));
107
- dataStationTemp = data;
108
- setDataStations(data);
109
- };
110
-
111
- const onTickedDevice = (idGroup, deviceId, isChecked) => {
112
- let data = [...dataStationTemp];
113
- const group = data.find((i) => i.id === idGroup);
114
- const device = group.devices.find((i) => i.id === deviceId);
115
-
116
- device.isChecked = isChecked;
117
-
118
- for (let station of data) {
119
- if (station.devices.length) {
120
- station.isChecked = !station.devices.some((i) => !i.isChecked);
121
- }
122
- }
123
- setIsTickAllDevices(!dataStationTemp.some((i) => !i.isChecked));
124
- dataStationTemp = data;
125
- setDataStations(data);
126
- };
127
-
128
- const onTickedDeviceIcon = (idGroup, deviceId, isChecked) => {
129
- let data = [...dataStationTemp];
130
- const group = data.find((i) => i.id === idGroup);
131
- const device = group.devices.find((i) => i.id === deviceId);
132
- const index = data.findIndex((item) => item.id === idGroup);
133
-
134
- data[index] = {
135
- ...data[index],
136
- devices: data[index]?.devices.map((i) => {
137
- if (i.id === device?.id) {
138
- return {
139
- ...i,
140
- isChecked: !isChecked,
141
- actions: i.actions.map((j) => ({ ...j, isChecked: !isChecked })),
142
- read_configs: i.read_configs.map((j) => ({
143
- ...j,
144
- isChecked: !isChecked,
145
- })),
146
- };
147
- }
148
- return { ...i };
149
- }),
150
- };
151
-
152
- data[index] = {
153
- ...data[index],
154
- isChecked:
155
- !data[index]?.devices.length ===
156
- !data[index]?.devices.filter((i) => i.isChecked).length,
157
- };
158
-
159
- setDataStations(data);
160
- };
161
-
162
- const toggleDeviceItem = (deviceItem) => () => {
163
- setExpandedItemIds((ids) => {
164
- const index = ids.indexOf(deviceItem.id);
165
- if (index !== -1) {
166
- return [...ids.slice(0, index), ...ids.slice(index + 1)];
167
- } else {
168
- return [...ids, deviceItem.id];
169
- }
170
- });
171
- };
172
-
173
- const autoCheckedGroup = useCallback(async () => {
174
- if (isUpdateSharedDevice) {
175
- if (hasDataChecked) {
176
- const { stationIds, deviceIds, actionIds, configIds } =
177
- objectIds(dataDeviceShared);
178
- for (let station in dataStations) {
179
- for (let item in dataStations[station].devices) {
180
- const itemTemp = dataStations[station].devices[item];
181
- dataStations[station].devices[item] = {
182
- ...itemTemp,
183
- isChecked: deviceIds.includes(itemTemp?.id),
184
- actions: itemTemp.actions.map((i) => {
185
- return {
186
- ...i,
187
- isChecked: actionIds?.includes(i.id),
188
- };
189
- }),
190
- read_configs: itemTemp.read_configs.map((i) => {
191
- return {
192
- ...i,
193
- isChecked: configIds?.includes(i.id),
194
- };
195
- }),
196
- };
197
- }
198
- }
199
- const data = dataStations?.map((i) => {
200
- const devices = i?.devices;
201
- const devices_checked = i?.devices?.filter(
202
- (device) => device?.isChecked
203
- );
204
- return {
205
- ...i,
206
- isChecked:
207
- !devices.length === !devices_checked.length &&
208
- stationIds.includes(i.id),
209
- };
210
- });
211
- setDataStations(data);
212
- setIsTickAllDevices(data?.length === stationIds?.length);
213
- setHasDataChecked(false);
214
- }
215
- }
216
- }, [dataDeviceShared, dataStations, hasDataChecked, isUpdateSharedDevice]);
217
-
218
- const GroupDeviceItem = ({ item = {} }) => {
219
- const { name = '', devices = [], isChecked, id = '' } = item;
220
- return (
221
- <View style={styles.viewGroup}>
222
- <TitleCheckBox
223
- title={name}
224
- wrapCheckBoxStyle={styles.checkBoxTile}
225
- onPress={onTickTitle}
226
- titleStyle={styles.GroupDeviceItem}
227
- isChecked={isChecked}
228
- idGroup={id}
229
- />
230
- <View style={styles.wrapDevice}>
231
- {devices?.map((i, index) => (
232
- <DeviceItem
233
- item={i}
234
- key={i.id}
235
- isRenderSeparated={index !== devices?.length - 1}
236
- onTickedChild={onTickedChild}
237
- onTickedDevice={onTickedDevice}
238
- onTickedDeviceIcon={onTickedDeviceIcon}
239
- isItemExpanded={expandedItemIds.includes(i.id)}
240
- toggleItem={toggleDeviceItem(i)}
241
- idGroup={id}
242
- />
243
- ))}
244
- </View>
245
- </View>
246
- );
247
- };
248
-
249
- const onPressBottom = async () => {
250
- let read_permissions = [],
251
- control_permissions = [];
252
- for (let station of dataStationTemp) {
253
- for (let item of station.devices) {
254
- let arrIdControlTemp = [],
255
- arrIdReadTemp = [];
256
-
257
- for (let i of item.actions) {
258
- i.isChecked && arrIdControlTemp.push(i.id);
259
- }
260
- for (let i of item.read_configs) {
261
- i.isChecked && arrIdReadTemp.push(i.id);
262
- }
263
-
264
- arrIdControlTemp.length &&
265
- control_permissions.push({ id: item.id, values: arrIdControlTemp });
266
-
267
- arrIdReadTemp.length &&
268
- read_permissions.push({ id: item.id, values: arrIdReadTemp });
269
-
270
- !arrIdControlTemp.length &&
271
- !arrIdReadTemp.length &&
272
- item.isChecked &&
273
- read_permissions.push({ id: item.id, values: [] });
274
- }
275
- }
276
- if (!read_permissions.length && !control_permissions.length) {
277
- Alert.alert('', t('choose_at_least_one'));
278
- return;
279
- }
280
- if (isUpdateSharedDevice) {
281
- const phone =
282
- member?.phone_number && member?.email
283
- ? member?.phone_number
284
- : member?.phone_number || '';
285
- const email = member?.phone_number ? '' : member?.email || '';
286
- const { success } = await axiosPost(API.SHARE.SHARE(), {
287
- phone,
288
- email,
289
- unit: unit?.id,
290
- permissions: { read_permissions, control_permissions },
291
- is_remove_old_permission: true,
292
- });
293
- success && navigation.goBack();
294
- } else {
295
- navigation.navigate(Routes.SharingInviteMembers, {
296
- unit,
297
- permissions: { read_permissions, control_permissions },
298
- });
299
- }
300
- };
301
-
302
- const renderGroupItem = ({ item }) => (
303
- <GroupDeviceItem key={item.id} item={item} />
304
- );
305
-
306
- const renderFlatList = useMemo(() => {
307
- return (
308
- <FlatList
309
- keyExtractor={(item) => item.id}
310
- extraData={dataStations}
311
- data={dataStations}
312
- renderItem={renderGroupItem}
313
- ListHeaderComponent={
314
- dataStations?.length > 0 ? (
315
- <TitleCheckBox
316
- title={t('text_all_devices')}
317
- wrapStyle={styles.wrapAllDevices}
318
- onPress={onTickTitle}
319
- titleStyle={styles.textAllDevice}
320
- isChecked={isTickAllDevices}
321
- />
322
- ) : (
323
- <></>
324
- )
325
- }
326
- scrollIndicatorInsets={{ right: 1 }}
327
- />
328
- );
329
-
330
- // eslint-disable-next-line react-hooks/exhaustive-deps
331
- }, [dataStations, isTickAllDevices, expandedItemIds]);
332
-
333
- useEffect(() => {
334
- autoCheckedGroup();
335
- }, [autoCheckedGroup]);
336
-
337
- const getShareUnitPermission = useCallback(async () => {
338
- if (isUpdateSharedDevice && dataStations?.length > 0) {
339
- const { success, data } = await axiosGet(
340
- API.SHARE.UNIT_MEMBER_SHARE_DEVICE(unit?.id, member?.id)
341
- );
342
- if (success) {
343
- setDataDeviceShared(data);
344
- setHasDataChecked(true);
345
- }
346
- }
347
- }, [dataStations?.length, isUpdateSharedDevice, member?.id, unit?.id]);
348
-
349
- const getUnitPermission = useCallback(async () => {
350
- const { success, data } = await axiosGet(
351
- API.SHARE.UNIT_PERMISSIONS(unit?.id)
352
- );
353
- if (success) {
354
- setDataStations(data);
355
- }
356
- setLoading(false);
357
- }, [unit?.id]);
358
-
359
- useEffect(() => {
360
- (async () => {
361
- if (!unit) {
362
- return;
363
- }
364
- await getUnitPermission();
365
- await getShareUnitPermission();
366
- })();
367
- }, [getShareUnitPermission, getUnitPermission, unit]);
368
-
369
- useEffect(() => {
370
- dataStationTemp = dataStations;
371
- }, [dataStations]);
372
-
373
- return (
374
- <View style={styles.wrap}>
375
- <Text semibold style={styles.title}>
376
- {t('select_device')}
377
- </Text>
378
- <Text style={styles.subtitle}>{t('sharing_select_devices_hint')}</Text>
379
- <View style={styles.contentContainer}>
380
- {loading ? (
381
- <ActivityIndicator color={Colors.Primary} />
382
- ) : dataStations?.length > 0 ? (
383
- renderFlatList
384
- ) : (
385
- <Text
386
- style={styles.textNodata}
387
- accessibilityLabel={AccessibilityLabel.TEXT_NO_DATA_STATIONS}
388
- >
389
- {t('no_data')}
390
- </Text>
391
- )}
392
- </View>
393
- <View style={styles.wrapViewButtonStyle}>
394
- <ViewButtonBottom
395
- accessibilityLabelPrefix={
396
- AccessibilityLabel.PREFIX.SHARING_SELECT_PERMISSION
397
- }
398
- leftTitle={t('cancel')}
399
- onLeftClick={() => navigation.goBack()}
400
- rightTitle={isUpdateSharedDevice ? t('done') : t('next')}
401
- rightDisabled={false}
402
- onRightClick={onPressBottom}
403
- />
404
- </View>
405
- </View>
406
- );
407
- };
408
-
409
- export default memo(SharingSelectPermission);