@eohjsc/react-native-smart-city 0.2.67 → 0.2.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/images/Popover/Dashboard/SmartAccount.svg +5 -0
- package/assets/images/scan-qr-gateway.svg +14 -0
- package/assets/images/wifi-gateway.svg +18 -0
- package/assets/images/wifi.svg +3 -0
- package/package.json +3 -1
- package/src/Images/Common/buttonLeftCurtain@2x.png +0 -0
- package/src/Images/Common/buttonLeftCurtain@3x.png +0 -0
- package/src/Images/Common/{buttonPause-center-curtain.png → buttonPauseCurtain.png} +0 -0
- package/src/Images/Common/buttonPauseCurtain@2x.png +0 -0
- package/src/Images/Common/buttonPauseCurtain@3x.png +0 -0
- package/src/Images/Common/buttonRightCurtain@2x.png +0 -0
- package/src/Images/Common/buttonRightCurtain@3x.png +0 -0
- package/src/commons/Action/ItemQuickAction.js +4 -3
- package/src/commons/ActionGroup/CurtainButtonTemplate.js +0 -30
- package/src/commons/ActionGroup/CurtainButtonTemplateStyle.js +0 -12
- package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +1 -1
- package/src/commons/AlertAction/index.js +4 -3
- package/src/commons/CameraDevice/index.js +1 -1
- package/src/commons/Dashboard/MyPinnedSharedUnit/__test__/MyPinnedSharedUnit.test.js +70 -0
- package/src/commons/Device/HistoryChart.js +18 -18
- package/src/commons/Device/HorizontalBarChart.js +1 -2
- package/src/commons/Device/ItemDevice.js +1 -13
- package/src/commons/Device/LinearChart.js +13 -3
- package/src/commons/Device/WaterQualitySensor/QualityIndicatorsItem.js +1 -1
- package/src/commons/SubUnit/OneTap/OneTapStyles.js +14 -5
- package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +5 -68
- package/src/commons/SubUnit/OneTap/index.js +24 -33
- package/src/commons/UnitSummary/ConfigHistoryChart/__test__/ConfigHistoryChart.test.js +29 -0
- package/src/commons/UnitSummary/ConfigHistoryChart.js +4 -6
- package/src/commons/ViewButtonBottom/index.js +4 -0
- package/src/configs/API.js +2 -0
- package/src/configs/BLE.js +3 -0
- package/src/configs/Constants.js +2 -0
- package/src/configs/Images.js +1 -1
- package/src/context/SCContext.tsx +2 -0
- package/src/iot/RemoteControl/Bluetooth.js +34 -6
- package/src/iot/RemoteControl/__test__/Bluetooth.test.js +1 -0
- package/src/iot/RemoteControl/__test__/index.mock.js +1 -0
- package/src/iot/RemoteControl/index.js +7 -2
- package/src/navigations/AddDeviceStack.js +2 -0
- package/src/navigations/AddGatewayStack.js +11 -0
- package/src/navigations/AddLGDeviceStack.js +2 -0
- package/src/navigations/AddMemberStack.js +2 -0
- package/src/navigations/AddSubUnitStack.js +2 -0
- package/src/navigations/AddUnitStack.js +2 -0
- package/src/navigations/EmergencyContactsStack.js +2 -0
- package/src/navigations/SharedStack.js +2 -0
- package/src/navigations/UnitStack.js +2 -0
- package/src/navigations/utils.js +3 -0
- package/src/screens/AddCommon/SelectSubUnit.js +12 -2
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +190 -0
- package/src/screens/AddNewGateway/PlugAndPlay/FirstWarning.js +73 -0
- package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +154 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/FirstWarning.test.js +60 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/GatewayWifiList.test.js +35 -0
- package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +90 -0
- package/src/screens/AddNewOneTap/__test__/AddNewOneTap.test.js +0 -22
- package/src/screens/AddNewOneTap/index.js +15 -13
- package/src/screens/Device/components/SensorDisplayItem.js +4 -2
- package/src/screens/Notification/components/NotificationItem.js +24 -1
- package/src/screens/Notification/styles/NotificationItemStyles.js +1 -1
- package/src/screens/ScanChipQR/hooks/index.js +14 -5
- package/src/screens/SharedUnit/index.js +7 -5
- package/src/screens/Sharing/Components/SensorItem.js +27 -12
- package/src/screens/Sharing/Components/Styles/SensorItemStyles.js +4 -0
- package/src/screens/Sharing/SelectPermission.js +44 -32
- package/src/screens/Sharing/SelectUser.js +13 -1
- package/src/screens/Sharing/__test__/SelectPermission.test.js +2 -1
- package/src/screens/SubUnit/AddSubUnit.js +4 -1
- package/src/screens/Unit/AddMenu.js +15 -0
- package/src/screens/Unit/Detail.js +15 -4
- package/src/screens/Unit/SmartAccount.js +36 -15
- package/src/screens/Unit/SmartAccountStyles.js +20 -0
- package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +10 -6
- package/src/screens/Unit/hook/useStateAlertRemove.js +4 -6
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +2 -4
- package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +10 -6
- package/src/utils/I18n/translations/en.json +33 -4
- package/src/utils/I18n/translations/vi.json +34 -4
- package/src/utils/Route/index.js +4 -0
- package/src/utils/Utils.js +0 -4
- package/src/commons/ActionGroup/__test__/MenuActionAddSchedule.test.js +0 -71
- package/src/commons/ActionGroup/hooks/AccessScheduleDetailStyles.js +0 -41
- package/src/commons/ActionGroup/hooks/MenuActionAddSchedule.js +0 -110
- package/src/commons/ActionGroup/hooks/MenuActionAddScheduleStyle.js +0 -69
- package/src/commons/ActionGroup/hooks/RecurringDetail.js +0 -97
|
@@ -20,6 +20,7 @@ import FooterInfo from '../../../commons/Device/FooterInfo';
|
|
|
20
20
|
import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
|
|
21
21
|
import { standardizeCameraScreenSize } from '../../../utils/Utils';
|
|
22
22
|
import { Device } from '../../../configs';
|
|
23
|
+
import { useSCContextSelector } from '../../../context';
|
|
23
24
|
|
|
24
25
|
const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
|
|
25
26
|
Device.screenWidth - 32
|
|
@@ -37,11 +38,12 @@ export const SensorDisplayItem = ({
|
|
|
37
38
|
background,
|
|
38
39
|
}) => {
|
|
39
40
|
const t = useTranslations();
|
|
41
|
+
const userId = useSCContextSelector((state) => state.auth.account.user.id);
|
|
40
42
|
const doAction = useCallback(
|
|
41
43
|
(action, data) => {
|
|
42
|
-
sendRemoteCommand(sensor, action, data);
|
|
44
|
+
sendRemoteCommand(sensor, action, data, userId);
|
|
43
45
|
},
|
|
44
|
-
[sensor]
|
|
46
|
+
[sensor, userId]
|
|
45
47
|
);
|
|
46
48
|
if (item.configuration.type === 'compass') {
|
|
47
49
|
setShowWindDirection(true);
|
|
@@ -67,7 +67,7 @@ const NotificationItem = memo(({ item }) => {
|
|
|
67
67
|
iconContent: (
|
|
68
68
|
<IconComponent
|
|
69
69
|
icon_outlined={'usergroup-add'}
|
|
70
|
-
style={styles.
|
|
70
|
+
style={styles.backgroundSummer}
|
|
71
71
|
/>
|
|
72
72
|
),
|
|
73
73
|
};
|
|
@@ -220,6 +220,29 @@ const NotificationItem = memo(({ item }) => {
|
|
|
220
220
|
params: { id: booking_id },
|
|
221
221
|
}),
|
|
222
222
|
};
|
|
223
|
+
case NOTIFICATION_TYPES.NOTIFY_REMOVE_UNIT:
|
|
224
|
+
const unitOwerName = paramsJSON?.unit_owner_name;
|
|
225
|
+
const textNotify = unitOwerName
|
|
226
|
+
? t('text_notification_content_remove_unit_to_member')
|
|
227
|
+
: t('text_notification_content_remove_unit_to_owner');
|
|
228
|
+
return {
|
|
229
|
+
content: customColorText(textNotify, arrParams),
|
|
230
|
+
redirect: () => null,
|
|
231
|
+
iconContent: (
|
|
232
|
+
<IconComponent icon={'home'} style={styles.backgroundSummer} />
|
|
233
|
+
),
|
|
234
|
+
};
|
|
235
|
+
case NOTIFICATION_TYPES.NOTIFY_REMOVE_MEMBER:
|
|
236
|
+
return {
|
|
237
|
+
content: customColorText(
|
|
238
|
+
t('text_notification_content_remove_member'),
|
|
239
|
+
arrParams
|
|
240
|
+
),
|
|
241
|
+
redirect: () => null,
|
|
242
|
+
iconContent: (
|
|
243
|
+
<IconComponent icon={'home'} style={styles.backgroundSummer} />
|
|
244
|
+
),
|
|
245
|
+
};
|
|
223
246
|
default:
|
|
224
247
|
return {
|
|
225
248
|
content: customColorText(t('this_notification_will_be_updated_soon')),
|
|
@@ -17,7 +17,7 @@ const useChipScan = (route) => {
|
|
|
17
17
|
const { success, data: new_chip } = await axiosPost(
|
|
18
18
|
API.UNIT.CHIP_SCAN(unit_id),
|
|
19
19
|
{
|
|
20
|
-
imei: imei,
|
|
20
|
+
imei: imei || body.imei,
|
|
21
21
|
qr_code: body.imei,
|
|
22
22
|
phone: phoneNumber,
|
|
23
23
|
name: chipName,
|
|
@@ -27,10 +27,19 @@ const useChipScan = (route) => {
|
|
|
27
27
|
}
|
|
28
28
|
);
|
|
29
29
|
if (success) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
if (new_chip.is_wifi) {
|
|
31
|
+
navigation.navigate(Routes.ConnectWifiWarning, {
|
|
32
|
+
wifi_ssid: new_chip.wifi_ssid,
|
|
33
|
+
wifi_pass: new_chip.wifi_pass,
|
|
34
|
+
chip_id: new_chip.id,
|
|
35
|
+
unit_id: unit_id,
|
|
36
|
+
});
|
|
37
|
+
} else {
|
|
38
|
+
navigation.navigate(Routes.ConnectingGateway, {
|
|
39
|
+
new_chip,
|
|
40
|
+
...route.params,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
34
43
|
} else {
|
|
35
44
|
navigation.goBack();
|
|
36
45
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { useEffect, useCallback, useState, useMemo } from 'react';
|
|
2
2
|
import { View, TouchableOpacity, FlatList, RefreshControl } from 'react-native';
|
|
3
|
-
import { useNavigation } from '@react-navigation/native';
|
|
3
|
+
import { useNavigation, useIsFocused } from '@react-navigation/native';
|
|
4
|
+
|
|
4
5
|
import { axiosGet } from '../../utils/Apis/axios';
|
|
5
6
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
6
|
-
|
|
7
7
|
import { API } from '../../configs';
|
|
8
8
|
import Text from '../../commons/Text';
|
|
9
9
|
import SharedUnit from '../../commons/Unit/SharedUnit';
|
|
@@ -24,7 +24,7 @@ const Shared = () => {
|
|
|
24
24
|
useTitleHeader(t('text_shared_with_me'));
|
|
25
25
|
const navigation = useNavigation();
|
|
26
26
|
const [tab, setTabActiveState] = useState(0);
|
|
27
|
-
|
|
27
|
+
const isFocused = useIsFocused();
|
|
28
28
|
const [sharedUnits, setSharedUnits] = useState([]);
|
|
29
29
|
|
|
30
30
|
const dataStarred = useMemo(
|
|
@@ -73,8 +73,10 @@ const Shared = () => {
|
|
|
73
73
|
}, [language, forceUpdate]);
|
|
74
74
|
|
|
75
75
|
useEffect(() => {
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
if (isFocused) {
|
|
77
|
+
filterSharedUnits(filter);
|
|
78
|
+
}
|
|
79
|
+
}, [filterSharedUnits, filter, isFocused]);
|
|
78
80
|
|
|
79
81
|
const onRefresh = useCallback(() => {
|
|
80
82
|
filterSharedUnits(filter);
|
|
@@ -5,11 +5,13 @@ import { Colors } from '../../../configs';
|
|
|
5
5
|
import styles from './Styles/SensorItemStyles';
|
|
6
6
|
import FImage from '../../../commons/FImage';
|
|
7
7
|
import { TitleCheckBox } from '.';
|
|
8
|
+
import { CheckBoxCustom } from '.';
|
|
8
9
|
|
|
9
10
|
const SensorItem = ({
|
|
10
11
|
item = {},
|
|
11
12
|
isRenderSeparated,
|
|
12
13
|
onTickedChild,
|
|
14
|
+
onTickedSensor,
|
|
13
15
|
titleGroup,
|
|
14
16
|
activeItemId,
|
|
15
17
|
setActiveItemId,
|
|
@@ -21,21 +23,22 @@ const SensorItem = ({
|
|
|
21
23
|
actions = [],
|
|
22
24
|
read_configs = [],
|
|
23
25
|
icon_kit = '',
|
|
26
|
+
isChecked,
|
|
24
27
|
} = item;
|
|
25
|
-
const [expanded, setExpanded] = useState(activeItemId === id);
|
|
26
28
|
const [dataConfig, setDataConfig] = useState([
|
|
27
29
|
...actions,
|
|
28
30
|
...read_configs.map((i) => ({ ...i, isConfig: true })),
|
|
29
31
|
]);
|
|
30
32
|
|
|
33
|
+
const expanded = activeItemId === id;
|
|
34
|
+
|
|
31
35
|
const onPressItem = () => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
if (dataConfig.length > 0) {
|
|
37
|
+
expanded ? setActiveItemId(-1) : setActiveItemId(id);
|
|
38
|
+
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
|
35
39
|
} else {
|
|
36
|
-
|
|
40
|
+
handleOnTickedSensor();
|
|
37
41
|
}
|
|
38
|
-
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
const handleOnTickedChild = (idGroup, isChecked, childId) => {
|
|
@@ -56,6 +59,10 @@ const SensorItem = ({
|
|
|
56
59
|
);
|
|
57
60
|
};
|
|
58
61
|
|
|
62
|
+
const handleOnTickedSensor = () => {
|
|
63
|
+
onTickedSensor && onTickedSensor(idGroup, id, !isChecked);
|
|
64
|
+
};
|
|
65
|
+
|
|
59
66
|
useEffect(() => {
|
|
60
67
|
if (
|
|
61
68
|
Platform.OS === 'android' &&
|
|
@@ -97,12 +104,20 @@ const SensorItem = ({
|
|
|
97
104
|
<Text numberOfLines={1} style={styles.text} onPress={onPressItem}>
|
|
98
105
|
{name}
|
|
99
106
|
</Text>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
{dataConfig.length > 0 ? (
|
|
108
|
+
<IconOutline
|
|
109
|
+
onPress={onPressItem}
|
|
110
|
+
name={expanded ? 'up' : 'down'}
|
|
111
|
+
size={20}
|
|
112
|
+
color={Colors.Gray6}
|
|
113
|
+
/>
|
|
114
|
+
) : (
|
|
115
|
+
<CheckBoxCustom
|
|
116
|
+
isChecked={isChecked}
|
|
117
|
+
onPress={onPressItem}
|
|
118
|
+
wrapStyle={styles.checkBox}
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
106
121
|
</View>
|
|
107
122
|
{expanded && <View style={styles.wrapExpand}>{renderData}</View>}
|
|
108
123
|
{isRenderSeparated && <View style={styles.viewSeparated} />}
|
|
@@ -38,11 +38,12 @@ const SelectPermission = ({ route }) => {
|
|
|
38
38
|
...i,
|
|
39
39
|
isChecked,
|
|
40
40
|
}));
|
|
41
|
-
for (let
|
|
42
|
-
for (let item in data[
|
|
43
|
-
const itemTemp = data[
|
|
44
|
-
data[
|
|
41
|
+
for (let station in data) {
|
|
42
|
+
for (let item in data[station].sensors) {
|
|
43
|
+
const itemTemp = data[station].sensors[item];
|
|
44
|
+
data[station].sensors[item] = {
|
|
45
45
|
...itemTemp,
|
|
46
|
+
isChecked,
|
|
46
47
|
actions: itemTemp.actions.map((i) => ({
|
|
47
48
|
...i,
|
|
48
49
|
isChecked,
|
|
@@ -63,6 +64,7 @@ const SelectPermission = ({ route }) => {
|
|
|
63
64
|
isChecked,
|
|
64
65
|
sensors: data[index]?.sensors.map((i) => ({
|
|
65
66
|
...i,
|
|
67
|
+
isChecked,
|
|
66
68
|
actions: i.actions.map((j) => ({ ...j, isChecked })),
|
|
67
69
|
read_configs: i.read_configs.map((j) => ({ ...j, isChecked })),
|
|
68
70
|
})),
|
|
@@ -80,33 +82,38 @@ const SelectPermission = ({ route }) => {
|
|
|
80
82
|
isReadConfig
|
|
81
83
|
) => {
|
|
82
84
|
let data = [...dataStationTemp];
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
85
|
+
const group = data.find((i) => i.id === idGroup);
|
|
86
|
+
const sensor = group.sensors.find((i) => i.id === sensorId);
|
|
87
|
+
const child = sensor[`${isReadConfig ? 'read_configs' : 'actions'}`].find(
|
|
88
|
+
(i) => i.id === childId
|
|
86
89
|
);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
90
|
+
|
|
91
|
+
child.isChecked = isChecked;
|
|
92
|
+
sensor.isChecked = !(
|
|
93
|
+
sensor.read_configs.some((i) => !i.isChecked) ||
|
|
94
|
+
sensor.actions.some((i) => !i.isChecked)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
for (let station of data) {
|
|
98
|
+
if (station.sensors.length) {
|
|
99
|
+
station.isChecked = !station.sensors.some((i) => !i.isChecked);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
setIsTickAllDevices(!dataStationTemp.some((i) => !i.isChecked));
|
|
103
|
+
dataStationTemp = data;
|
|
104
|
+
setDataStations(data);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const onTickedSensor = (idGroup, sensorId, isChecked) => {
|
|
108
|
+
let data = [...dataStationTemp];
|
|
109
|
+
const group = data.find((i) => i.id === idGroup);
|
|
110
|
+
const sensor = group.sensors.find((i) => i.id === sensorId);
|
|
111
|
+
|
|
112
|
+
sensor.isChecked = isChecked;
|
|
113
|
+
|
|
114
|
+
for (let station of data) {
|
|
115
|
+
if (station.sensors.length) {
|
|
116
|
+
station.isChecked = !station.sensors.some((i) => !i.isChecked);
|
|
110
117
|
}
|
|
111
118
|
}
|
|
112
119
|
setIsTickAllDevices(!dataStationTemp.some((i) => !i.isChecked));
|
|
@@ -133,6 +140,7 @@ const SelectPermission = ({ route }) => {
|
|
|
133
140
|
key={i.id}
|
|
134
141
|
isRenderSeparated={index !== sensors.length - 1}
|
|
135
142
|
onTickedChild={onTickedChild}
|
|
143
|
+
onTickedSensor={onTickedSensor}
|
|
136
144
|
titleGroup={name}
|
|
137
145
|
activeItemId={activeItemId}
|
|
138
146
|
setActiveItemId={setActiveItemId}
|
|
@@ -147,8 +155,8 @@ const SelectPermission = ({ route }) => {
|
|
|
147
155
|
const onPressNext = () => {
|
|
148
156
|
let read_permissions = [],
|
|
149
157
|
control_permissions = [];
|
|
150
|
-
for (let
|
|
151
|
-
for (let item of
|
|
158
|
+
for (let station of dataStationTemp) {
|
|
159
|
+
for (let item of station.sensors) {
|
|
152
160
|
let arrIdControlTemp = [],
|
|
153
161
|
arrIdReadTemp = [];
|
|
154
162
|
for (let i of item.actions) {
|
|
@@ -161,6 +169,10 @@ const SelectPermission = ({ route }) => {
|
|
|
161
169
|
control_permissions.push({ id: item.id, values: arrIdControlTemp });
|
|
162
170
|
arrIdReadTemp.length &&
|
|
163
171
|
read_permissions.push({ id: item.id, values: arrIdReadTemp });
|
|
172
|
+
!arrIdControlTemp.length &&
|
|
173
|
+
!arrIdReadTemp.length &&
|
|
174
|
+
item.isChecked &&
|
|
175
|
+
read_permissions.push({ id: item.id, values: [] });
|
|
164
176
|
}
|
|
165
177
|
}
|
|
166
178
|
if (!read_permissions.length && !control_permissions.length) {
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
import { axiosPost } from '../../utils/Apis/axios';
|
|
22
22
|
import { TESTID } from '../../configs/Constants';
|
|
23
23
|
import Text from '../../commons/Text';
|
|
24
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
24
25
|
|
|
25
26
|
const SelectUser = ({ route }) => {
|
|
26
27
|
const t = useTranslations();
|
|
@@ -46,9 +47,20 @@ const SelectUser = ({ route }) => {
|
|
|
46
47
|
});
|
|
47
48
|
if (success) {
|
|
48
49
|
setUsers([...users, data.user]);
|
|
50
|
+
} else {
|
|
51
|
+
const textTemp = t(
|
|
52
|
+
data?.phone
|
|
53
|
+
? 'text_phone_share_permission'
|
|
54
|
+
: data?.email
|
|
55
|
+
? 'text_email_share_permission'
|
|
56
|
+
: ''
|
|
57
|
+
);
|
|
58
|
+
ToastBottomHelper.error(
|
|
59
|
+
t('error_share_permission', { data: phone || email, text: textTemp })
|
|
60
|
+
);
|
|
49
61
|
}
|
|
50
62
|
},
|
|
51
|
-
[unit, permissions,
|
|
63
|
+
[users, unit.id, permissions, t]
|
|
52
64
|
);
|
|
53
65
|
|
|
54
66
|
const validate = useCallback(() => {
|
|
@@ -144,6 +144,7 @@ describe('Test SelectPermission', () => {
|
|
|
144
144
|
{
|
|
145
145
|
actions: [{ id: 136, isChecked: true, name: 'action 1' }],
|
|
146
146
|
id: 123,
|
|
147
|
+
isChecked: true,
|
|
147
148
|
name: 'child1',
|
|
148
149
|
read_configs: [{ id: 137, isChecked: true, name: 'config 1' }],
|
|
149
150
|
},
|
|
@@ -165,7 +166,7 @@ describe('Test SelectPermission', () => {
|
|
|
165
166
|
const SensorItemElement = instance.findAllByType(SensorItem);
|
|
166
167
|
expect(SensorItemElement).toHaveLength(1);
|
|
167
168
|
act(() => {
|
|
168
|
-
SensorItemElement[0].props.onTickedChild(204, 123,
|
|
169
|
+
SensorItemElement[0].props.onTickedChild(204, 123, 137, true, true);
|
|
169
170
|
});
|
|
170
171
|
expect(mockSetDataStations).toBeCalled();
|
|
171
172
|
});
|
|
@@ -24,9 +24,11 @@ import { axiosPost, createFormData } from '../../utils/Apis/axios';
|
|
|
24
24
|
import { ToastBottomHelper } from '../../utils/Utils';
|
|
25
25
|
import { TESTID } from '../../configs/Constants';
|
|
26
26
|
import styles from './AddSubUnitStyles';
|
|
27
|
+
import useKeyboardShow from '../../hooks/Common/useKeyboardShow';
|
|
27
28
|
|
|
28
29
|
const AddSubUnit = ({ route }) => {
|
|
29
30
|
const t = useTranslations();
|
|
31
|
+
const { dismissKeyboard } = useKeyboardShow();
|
|
30
32
|
const { navigate, goBack } = useNavigation();
|
|
31
33
|
const { unit, addType, isAddUnit, location = '' } = route?.params;
|
|
32
34
|
const [roomName, setRoomName] = useState('');
|
|
@@ -126,8 +128,9 @@ const AddSubUnit = ({ route }) => {
|
|
|
126
128
|
]);
|
|
127
129
|
|
|
128
130
|
const onChoosePhoto = useCallback(() => {
|
|
131
|
+
dismissKeyboard();
|
|
129
132
|
setShowImagePicker(true);
|
|
130
|
-
}, []);
|
|
133
|
+
}, [dismissKeyboard]);
|
|
131
134
|
|
|
132
135
|
useEffect(() => {
|
|
133
136
|
if (imageUrl) {
|
|
@@ -4,6 +4,7 @@ import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
|
4
4
|
import Routes from '../../utils/Route';
|
|
5
5
|
import AddSubUnitIcon from '../../../assets/images/Popover/Dashboard/AddSubUnit.svg';
|
|
6
6
|
import AddDeviceIcon from '../../../assets/images/Popover/Dashboard/AddDevice.svg';
|
|
7
|
+
import SmartAccount from '../../../assets/images/Popover/Dashboard/SmartAccount.svg';
|
|
7
8
|
import AddMemberIcon from '../../../assets/images/Popover/Dashboard/AddMember.svg';
|
|
8
9
|
import { useNavigation } from '@react-navigation/native';
|
|
9
10
|
|
|
@@ -50,6 +51,20 @@ const AddMenu = memo(({ unit, afterItemClick, showAdd, setHideAdd }) => {
|
|
|
50
51
|
image: <AddDeviceIcon width={43} height={43} />, // TODO change icon
|
|
51
52
|
data: { screen: Routes.SetupGatewayWifi, params: { unit_id: unit.id } },
|
|
52
53
|
},
|
|
54
|
+
{
|
|
55
|
+
id: 5,
|
|
56
|
+
route: Routes.AddGatewayStack,
|
|
57
|
+
text: t('gateway') + ' Wifi',
|
|
58
|
+
image: <AddDeviceIcon width={43} height={43} />,
|
|
59
|
+
data: { screen: Routes.FirstWarning, params: { unit_id: unit.id } },
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 6,
|
|
63
|
+
route: Routes.SmartAccount,
|
|
64
|
+
text: t('name_smart_account'),
|
|
65
|
+
image: <SmartAccount width={43} height={43} />, // TODO change icon
|
|
66
|
+
type: Routes.SmartAccount,
|
|
67
|
+
},
|
|
53
68
|
];
|
|
54
69
|
}, [t, unit]);
|
|
55
70
|
|
|
@@ -31,7 +31,14 @@ import { AUTOMATE_TYPE } from '../../configs/Constants';
|
|
|
31
31
|
const UnitDetail = ({ route }) => {
|
|
32
32
|
const t = useTranslations();
|
|
33
33
|
|
|
34
|
-
const {
|
|
34
|
+
const {
|
|
35
|
+
unitId,
|
|
36
|
+
unitData,
|
|
37
|
+
isOneTap,
|
|
38
|
+
routeName,
|
|
39
|
+
isAddSubUnit,
|
|
40
|
+
isSuccessfullyConnected,
|
|
41
|
+
} = route.params;
|
|
35
42
|
|
|
36
43
|
const isFocused = useIsFocused();
|
|
37
44
|
const { stateData, setAction } = useContext(SCContext);
|
|
@@ -266,7 +273,7 @@ const UnitDetail = ({ route }) => {
|
|
|
266
273
|
/>
|
|
267
274
|
);
|
|
268
275
|
}
|
|
269
|
-
if (station
|
|
276
|
+
if (station?.camera_devices) {
|
|
270
277
|
return (
|
|
271
278
|
<CameraDevice
|
|
272
279
|
station={station}
|
|
@@ -274,7 +281,7 @@ const UnitDetail = ({ route }) => {
|
|
|
274
281
|
goToPlayBack={goToPlayBack}
|
|
275
282
|
/>
|
|
276
283
|
);
|
|
277
|
-
} else if (station
|
|
284
|
+
} else if (station?.isOneTap) {
|
|
278
285
|
return (
|
|
279
286
|
<SubUnitAutomate
|
|
280
287
|
isOwner={isOwner}
|
|
@@ -298,6 +305,10 @@ const UnitDetail = ({ route }) => {
|
|
|
298
305
|
navigate(routeName);
|
|
299
306
|
}, [navigate, routeName]);
|
|
300
307
|
|
|
308
|
+
const Dashboard = useCallback(() => {
|
|
309
|
+
navigate(Routes.Dashboard);
|
|
310
|
+
}, [navigate]);
|
|
311
|
+
|
|
301
312
|
return (
|
|
302
313
|
<WrapParallaxScrollView
|
|
303
314
|
uriImg={unit.background}
|
|
@@ -310,7 +321,7 @@ const UnitDetail = ({ route }) => {
|
|
|
310
321
|
onAdd={setShowAdd}
|
|
311
322
|
onMore={showPopoverWithRef}
|
|
312
323
|
hideRightPlus={!isOwner}
|
|
313
|
-
onBack={routeName && onBack}
|
|
324
|
+
onBack={(isSuccessfullyConnected && Dashboard) || (routeName && onBack)}
|
|
314
325
|
>
|
|
315
326
|
<View style={styles.container}>
|
|
316
327
|
<Summaries unit={unit} />
|
|
@@ -14,9 +14,10 @@ import Routes from '../../utils/Route';
|
|
|
14
14
|
import { useNavigation } from '@react-navigation/native';
|
|
15
15
|
import { axiosDelete, axiosGet } from '../../utils/Apis/axios';
|
|
16
16
|
import { SmartAccountItem } from './SmartAccountItem';
|
|
17
|
-
import { usePopover } from '../../hooks/Common';
|
|
18
|
-
import { MenuActionMore } from '../../commons';
|
|
17
|
+
import { usePopover, useBoolean } from '../../hooks/Common';
|
|
18
|
+
import { MenuActionMore, AlertAction } from '../../commons';
|
|
19
19
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
20
|
+
import { useStateAlertRemove } from '../Unit/hook/useStateAlertRemove';
|
|
20
21
|
|
|
21
22
|
const ListSmartAccount = ({ route }) => {
|
|
22
23
|
const { unitId } = route?.params || {};
|
|
@@ -36,6 +37,9 @@ const ListSmartAccount = ({ route }) => {
|
|
|
36
37
|
|
|
37
38
|
const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
|
|
38
39
|
usePopover();
|
|
40
|
+
const [lockShowing, acquireLockShowing, releaseLockShowing] = useBoolean();
|
|
41
|
+
const { stateAlertRemove, onShowRemoveAlert, hideAlertAction } =
|
|
42
|
+
useStateAlertRemove();
|
|
39
43
|
|
|
40
44
|
useEffect(() => {
|
|
41
45
|
getAllSmartAccounts();
|
|
@@ -50,29 +54,31 @@ const ListSmartAccount = ({ route }) => {
|
|
|
50
54
|
[showPopoverWithRef]
|
|
51
55
|
);
|
|
52
56
|
|
|
53
|
-
const deleteSmartAccount = useCallback(async () => {
|
|
54
|
-
if (!smartAccountRef?.current) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const id = smartAccountRef.current.id;
|
|
58
|
-
const { success } = await axiosDelete(
|
|
59
|
-
API.SMART_ACCOUNT.REMOVE_SMART_ACCOUNT(id)
|
|
60
|
-
);
|
|
61
|
-
success && getAllSmartAccounts();
|
|
62
|
-
}, [getAllSmartAccounts]);
|
|
63
|
-
|
|
64
57
|
const onItemClick = useCallback(
|
|
65
58
|
(item) => {
|
|
66
59
|
if (!smartAccountRef?.current) {
|
|
67
60
|
return;
|
|
68
61
|
}
|
|
69
62
|
if (item.action === 'remove') {
|
|
70
|
-
|
|
63
|
+
acquireLockShowing();
|
|
64
|
+
onShowRemoveAlert(smartAccountRef.current.brand)();
|
|
71
65
|
}
|
|
72
66
|
},
|
|
73
|
-
[
|
|
67
|
+
[acquireLockShowing, onShowRemoveAlert]
|
|
74
68
|
);
|
|
75
69
|
|
|
70
|
+
const deleteSmartAccount = useCallback(async () => {
|
|
71
|
+
hideAlertAction();
|
|
72
|
+
if (!smartAccountRef?.current) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const id = smartAccountRef.current.id;
|
|
76
|
+
const { success } = await axiosDelete(
|
|
77
|
+
API.SMART_ACCOUNT.REMOVE_SMART_ACCOUNT(id)
|
|
78
|
+
);
|
|
79
|
+
success && getAllSmartAccounts();
|
|
80
|
+
}, [getAllSmartAccounts, hideAlertAction]);
|
|
81
|
+
|
|
76
82
|
const listMenuItem = useMemo(() => {
|
|
77
83
|
return [{ action: 'remove', text: t('remove_account') }];
|
|
78
84
|
}, [t]);
|
|
@@ -88,6 +94,7 @@ const ListSmartAccount = ({ route }) => {
|
|
|
88
94
|
},
|
|
89
95
|
[navigate, unitId]
|
|
90
96
|
);
|
|
97
|
+
|
|
91
98
|
return (
|
|
92
99
|
<View style={styles.wrap}>
|
|
93
100
|
<WrapHeaderScrollable
|
|
@@ -109,12 +116,26 @@ const ListSmartAccount = ({ route }) => {
|
|
|
109
116
|
);
|
|
110
117
|
})}
|
|
111
118
|
</View>
|
|
119
|
+
<AlertAction
|
|
120
|
+
visible={stateAlertRemove.visible && !lockShowing}
|
|
121
|
+
hideModal={hideAlertAction}
|
|
122
|
+
title={stateAlertRemove.title}
|
|
123
|
+
message={stateAlertRemove.message}
|
|
124
|
+
leftButtonTitle={stateAlertRemove.leftButton}
|
|
125
|
+
leftButtonClick={deleteSmartAccount}
|
|
126
|
+
rightButtonTitle={stateAlertRemove.rightButton}
|
|
127
|
+
rightButtonClick={hideAlertAction}
|
|
128
|
+
boxLeftButtonStyle={styles.boxButtonNotSelect}
|
|
129
|
+
boxRightButtonStyle={styles.boxButtonSelect}
|
|
130
|
+
rightButtonStyle={styles.textRightButton}
|
|
131
|
+
/>
|
|
112
132
|
<MenuActionMore
|
|
113
133
|
isVisible={showingPopover}
|
|
114
134
|
hideMore={hidePopover}
|
|
115
135
|
listMenuItem={listMenuItem}
|
|
116
136
|
childRef={childRef}
|
|
117
137
|
onItemClick={onItemClick}
|
|
138
|
+
hideComplete={releaseLockShowing}
|
|
118
139
|
/>
|
|
119
140
|
</WrapHeaderScrollable>
|
|
120
141
|
</View>
|
|
@@ -42,4 +42,24 @@ export default StyleSheet.create({
|
|
|
42
42
|
borderColor: Colors.ShadownTransparent,
|
|
43
43
|
borderTopWidth: 1,
|
|
44
44
|
},
|
|
45
|
+
boxButtonNotSelect: {
|
|
46
|
+
marginVertical: 16,
|
|
47
|
+
height: 45,
|
|
48
|
+
borderRadius: 30,
|
|
49
|
+
borderColor: Colors.Primary,
|
|
50
|
+
borderWidth: 1,
|
|
51
|
+
paddingVertical: 0,
|
|
52
|
+
},
|
|
53
|
+
boxButtonSelect: {
|
|
54
|
+
marginVertical: 16,
|
|
55
|
+
height: 45,
|
|
56
|
+
borderRadius: 30,
|
|
57
|
+
borderColor: Colors.Primary,
|
|
58
|
+
backgroundColor: Colors.Primary,
|
|
59
|
+
borderWidth: 1,
|
|
60
|
+
paddingVertical: 0,
|
|
61
|
+
},
|
|
62
|
+
textRightButton: {
|
|
63
|
+
color: Colors.White,
|
|
64
|
+
},
|
|
45
65
|
});
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { act, create } from 'react-test-renderer';
|
|
4
|
+
import { SCProvider } from '../../../../context';
|
|
5
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
4
6
|
import MyUnitDevice from '../MyUnitDevice';
|
|
5
7
|
|
|
8
|
+
const wrapComponent = (sensor) => (
|
|
9
|
+
<SCProvider initState={mockSCStore({})}>
|
|
10
|
+
<MyUnitDevice sensor={sensor} />
|
|
11
|
+
</SCProvider>
|
|
12
|
+
);
|
|
13
|
+
|
|
6
14
|
describe('Test MyUnitDevice', () => {
|
|
7
15
|
let tree;
|
|
8
16
|
|
|
9
17
|
it('Test render with status', async () => {
|
|
10
18
|
await act(() => {
|
|
11
19
|
tree = create(
|
|
12
|
-
|
|
13
|
-
sensor={{ status: 'Ok', name: 'Test', station_name: '' }}
|
|
14
|
-
/>
|
|
20
|
+
wrapComponent({ status: 'Ok', name: 'Test', station_name: '' })
|
|
15
21
|
);
|
|
16
22
|
});
|
|
17
23
|
const instance = tree.root;
|
|
@@ -21,9 +27,7 @@ describe('Test MyUnitDevice', () => {
|
|
|
21
27
|
|
|
22
28
|
it('Test render without status', async () => {
|
|
23
29
|
await act(() => {
|
|
24
|
-
tree = create(
|
|
25
|
-
<MyUnitDevice sensor={{ name: 'Test', station_name: '' }} />
|
|
26
|
-
);
|
|
30
|
+
tree = create(wrapComponent({ name: 'Test', station_name: '' }));
|
|
27
31
|
});
|
|
28
32
|
const instance = tree.root;
|
|
29
33
|
const Views = instance.findAllByType(View);
|