@eohjsc/react-native-smart-city 0.3.29 → 0.3.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commons/Action/ItemQuickAction.js +1 -0
- package/src/commons/ActionGroup/SliderRangeTemplate.js +22 -14
- package/src/commons/BottomButtonView/index.js +1 -0
- package/src/commons/Button/index.js +2 -0
- package/src/commons/Device/ItemAddNew/index.js +5 -1
- package/src/commons/Device/ItemDevice.js +11 -9
- package/src/commons/MenuActionMore/index.js +1 -1
- package/src/commons/NavBar/index.js +2 -1
- package/src/commons/Popover/index.js +7 -6
- package/src/commons/SubUnit/OneTap/ItemOneTap.js +4 -1
- package/src/configs/Constants.js +11 -0
- package/src/hooks/Common/useDevicesStatus.js +1 -1
- package/src/hooks/IoT/useValueEvaluation.js +10 -19
- package/src/iot/RemoteControl/GoogleHome.js +6 -6
- package/src/navigations/UnitStack.js +5 -8
- package/src/screens/AddNewAction/Device/index.js +5 -1
- package/src/screens/AddNewAction/SelectAction.js +30 -14
- package/src/screens/AddNewAction/__test__/SelectAction.test.js +1 -0
- package/src/screens/AddNewAutoSmart/index.js +2 -0
- package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +13 -1
- package/src/screens/Device/components/SensorConnectStatusViewHeader.js +10 -11
- package/src/screens/Device/detail.js +35 -16
- package/src/screens/Device/hooks/useFavoriteDevice.js +4 -2
- package/src/screens/EmergencyContacts/EmergencyContactsAddNew.js +3 -3
- package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +4 -7
- package/src/screens/Notification/__test__/NotificationItem.test.js +6 -30
- package/src/screens/Notification/components/NotificationItem.js +3 -19
- package/src/screens/ScriptDetail/__test__/index.test.js +1 -1
- package/src/screens/ScriptDetail/index.js +2 -1
- package/src/screens/Sharing/Components/SensorItem.js +4 -1
- package/src/screens/Sharing/Components/Styles/SensorItemStyles.js +4 -0
- package/src/screens/Sharing/Components/Styles/TitleCheckBoxStyles.js +4 -0
- package/src/screens/Sharing/Components/TitleCheckBox.js +17 -8
- package/src/screens/Unit/Detail.js +6 -1
- package/src/screens/Unit/SelectAddToFavorites.js +11 -1
- package/src/screens/Unit/components/AutomateScript/index.js +5 -2
- package/src/utils/I18n/translations/en.json +5 -0
- package/src/utils/I18n/translations/vi.json +5 -0
package/package.json
CHANGED
|
@@ -88,6 +88,7 @@ const ItemQuickAction = memo(({ sensor, wrapperStyle, setStatus }) => {
|
|
|
88
88
|
return (
|
|
89
89
|
<TouchableOpacity
|
|
90
90
|
testID={TESTID.ITEM_QUICK_ACTION_PRESS}
|
|
91
|
+
accessibilityLabel={`${TESTID.ITEM_QUICK_ACTION_PRESS}-${sensor?.id}`}
|
|
91
92
|
onPress={onActionPress}
|
|
92
93
|
>
|
|
93
94
|
<View style={wrapperStyle}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { memo, useCallback, useState,
|
|
1
|
+
import React, { memo, useCallback, useState, useEffect } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
4
4
|
import styles from './SliderRangeTemplateStyles';
|
|
@@ -13,30 +13,38 @@ const SliderRangeTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
|
13
13
|
const { configuration } = actionGroup;
|
|
14
14
|
const [valueBrightness, setValueBrightness] = useState(0);
|
|
15
15
|
const [valueBrightnessTemp, setValueBrightnessTemp] = useState(0);
|
|
16
|
+
const [isFirstTime, setIsFirstTime] = useState(true);
|
|
17
|
+
|
|
16
18
|
const [configValues] = useConfigGlobalState('configValues');
|
|
17
19
|
|
|
18
20
|
const onChangeBrightness = useCallback(
|
|
19
|
-
(value) => {
|
|
20
|
-
doAction(
|
|
21
|
+
async (value) => {
|
|
22
|
+
await doAction(
|
|
21
23
|
configuration?.action_brightness_data,
|
|
22
24
|
JSON.stringify({ value_brness: value })
|
|
23
25
|
);
|
|
26
|
+
await setValueBrightness(value);
|
|
27
|
+
await setValueBrightnessTemp(value);
|
|
24
28
|
},
|
|
25
29
|
[configuration?.action_brightness_data, doAction]
|
|
26
30
|
);
|
|
27
31
|
|
|
28
|
-
const percentBrightness = useMemo(() => {
|
|
29
|
-
return valueBrightnessTemp || valueBrightness || 0;
|
|
30
|
-
}, [valueBrightness, valueBrightnessTemp]);
|
|
31
|
-
|
|
32
32
|
useEffect(() => {
|
|
33
33
|
const { config } = configuration;
|
|
34
34
|
const configValue = configValues[config];
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
if (configValue?.value >= 0 && isFirstTime) {
|
|
36
|
+
setValueBrightness(configValue?.value);
|
|
37
|
+
setIsFirstTime(false);
|
|
38
|
+
} else if (configValue?.value === valueBrightnessTemp) {
|
|
39
|
+
setValueBrightness(valueBrightnessTemp);
|
|
38
40
|
}
|
|
39
|
-
}, [
|
|
41
|
+
}, [
|
|
42
|
+
configuration.config,
|
|
43
|
+
configValues,
|
|
44
|
+
configuration,
|
|
45
|
+
isFirstTime,
|
|
46
|
+
valueBrightnessTemp,
|
|
47
|
+
]);
|
|
40
48
|
|
|
41
49
|
return (
|
|
42
50
|
<View style={styles.viewBrightness}>
|
|
@@ -49,9 +57,9 @@ const SliderRangeTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
|
49
57
|
<View style={styles.RightBrightness}>
|
|
50
58
|
<View style={styles.slider}>
|
|
51
59
|
<SliderRange
|
|
52
|
-
value={
|
|
60
|
+
value={valueBrightness}
|
|
53
61
|
onSlidingComplete={onChangeBrightness}
|
|
54
|
-
onValueChange={
|
|
62
|
+
onValueChange={setValueBrightness}
|
|
55
63
|
step={1}
|
|
56
64
|
minimumValue={0}
|
|
57
65
|
maximumValue={100}
|
|
@@ -64,7 +72,7 @@ const SliderRangeTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
|
64
72
|
</View>
|
|
65
73
|
<View style={styles.valuePercent}>
|
|
66
74
|
<Text type="Label" style={styles.textValuePercent}>
|
|
67
|
-
{`${
|
|
75
|
+
{`${valueBrightness}%`}
|
|
68
76
|
</Text>
|
|
69
77
|
</View>
|
|
70
78
|
</View>
|
|
@@ -133,6 +133,7 @@ export default ({
|
|
|
133
133
|
textSemiBold = true,
|
|
134
134
|
style,
|
|
135
135
|
testID,
|
|
136
|
+
accessibilityLabel,
|
|
136
137
|
}) => {
|
|
137
138
|
const styleButton = ButtonStyle[type];
|
|
138
139
|
const textColor = TextColor[type];
|
|
@@ -158,6 +159,7 @@ export default ({
|
|
|
158
159
|
onPress={onPress}
|
|
159
160
|
disabled={isDisabled}
|
|
160
161
|
activeOpacity={activeOpacity}
|
|
162
|
+
accessibilityLabel={accessibilityLabel}
|
|
161
163
|
>
|
|
162
164
|
<View style={styles.wrap}>
|
|
163
165
|
{icon}
|
|
@@ -9,7 +9,11 @@ import { TESTID } from '../../../configs/Constants';
|
|
|
9
9
|
|
|
10
10
|
const ItemAddNew = memo(({ title, onAddNew, wrapStyle }) => {
|
|
11
11
|
return (
|
|
12
|
-
<TouchableWithoutFeedback
|
|
12
|
+
<TouchableWithoutFeedback
|
|
13
|
+
onPress={onAddNew}
|
|
14
|
+
testID={TESTID.TOUCH_ADD_NEW_FAVORITES}
|
|
15
|
+
accessibilityLabel={TESTID.TOUCH_ADD_NEW_FAVORITES}
|
|
16
|
+
>
|
|
13
17
|
<View style={[styles.container, wrapStyle]}>
|
|
14
18
|
<View style={styles.boxIcon}>
|
|
15
19
|
<TouchableOpacity
|
|
@@ -61,17 +61,18 @@ const ItemDevice = memo(
|
|
|
61
61
|
|
|
62
62
|
const borderColor = (() => {
|
|
63
63
|
if (!!sensor && sensor?.is_managed_by_backend) {
|
|
64
|
+
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
65
|
+
return Colors.Gray4;
|
|
66
|
+
}
|
|
64
67
|
if (isConnectedViaBLE) {
|
|
65
68
|
return Colors.Gray4;
|
|
66
69
|
}
|
|
67
70
|
if (isFetchingStatus || isConnectedViaInternet) {
|
|
68
71
|
return Colors.Gray4;
|
|
69
72
|
}
|
|
73
|
+
return Colors.Red6;
|
|
70
74
|
}
|
|
71
75
|
// not managed by backend
|
|
72
|
-
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
73
|
-
return Colors.Gray4;
|
|
74
|
-
}
|
|
75
76
|
if (sensor?.device_type === DEVICE_TYPE.GOOGLE_HOME) {
|
|
76
77
|
if (isGGHomeConnecting || isGGHomeConnected) {
|
|
77
78
|
return Colors.Gray4;
|
|
@@ -82,6 +83,9 @@ const ItemDevice = memo(
|
|
|
82
83
|
|
|
83
84
|
const textConnected = (() => {
|
|
84
85
|
if (!!sensor && sensor?.is_managed_by_backend) {
|
|
86
|
+
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
87
|
+
return t('connected');
|
|
88
|
+
}
|
|
85
89
|
if (isConnectedViaBLE) {
|
|
86
90
|
return t('connected');
|
|
87
91
|
}
|
|
@@ -91,11 +95,9 @@ const ItemDevice = memo(
|
|
|
91
95
|
if (isConnectedViaInternet) {
|
|
92
96
|
return t('connected');
|
|
93
97
|
}
|
|
98
|
+
return t('disconnected');
|
|
94
99
|
}
|
|
95
100
|
// not managed by backend
|
|
96
|
-
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
97
|
-
return t('connected');
|
|
98
|
-
}
|
|
99
101
|
if (sensor?.device_type === DEVICE_TYPE.GOOGLE_HOME) {
|
|
100
102
|
if (isGGHomeConnecting) {
|
|
101
103
|
return t('connecting');
|
|
@@ -109,6 +111,9 @@ const ItemDevice = memo(
|
|
|
109
111
|
|
|
110
112
|
const canRenderQuickAction = (() => {
|
|
111
113
|
if (!!sensor && sensor?.is_managed_by_backend) {
|
|
114
|
+
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
112
117
|
if (isConnectedViaBLE) {
|
|
113
118
|
return true;
|
|
114
119
|
}
|
|
@@ -118,9 +123,6 @@ const ItemDevice = memo(
|
|
|
118
123
|
return true;
|
|
119
124
|
}
|
|
120
125
|
// not managed by backend
|
|
121
|
-
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
126
|
if (sensor?.device_type === DEVICE_TYPE.GOOGLE_HOME) {
|
|
125
127
|
return !isGGHomeConnecting;
|
|
126
128
|
}
|
|
@@ -67,7 +67,7 @@ const MenuActionMore = memo(
|
|
|
67
67
|
key={index}
|
|
68
68
|
testID={TESTID.TOUCHABLE_ACTION_ADD_MORE}
|
|
69
69
|
accessibilityLabel={`${idLabelItem}-${
|
|
70
|
-
item?.route ? item?.id : item?.station?.id
|
|
70
|
+
(item?.route ? item?.id : item?.station?.id) || index
|
|
71
71
|
}`}
|
|
72
72
|
disabled={isDisable}
|
|
73
73
|
>
|
|
@@ -18,6 +18,7 @@ const NavBar = memo(
|
|
|
18
18
|
style,
|
|
19
19
|
idLabelScrollView,
|
|
20
20
|
idLabelItem,
|
|
21
|
+
idLabelIconBars,
|
|
21
22
|
}) => {
|
|
22
23
|
const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
|
|
23
24
|
usePopover();
|
|
@@ -39,7 +40,7 @@ const NavBar = memo(
|
|
|
39
40
|
onPress={handleShowMenuAction}
|
|
40
41
|
ref={refMenuAction}
|
|
41
42
|
testID={TESTID.NAVBAR_ICON_BARS}
|
|
42
|
-
accessibilityLabel={
|
|
43
|
+
accessibilityLabel={idLabelIconBars}
|
|
43
44
|
>
|
|
44
45
|
<Icon name={'bars'} size={19} color={Colors.Black} />
|
|
45
46
|
</TouchableOpacity>
|
|
@@ -3,22 +3,23 @@ import Popover from 'react-native-popover-view';
|
|
|
3
3
|
import { SCContext } from '../../context';
|
|
4
4
|
import { Action } from '../../context/actionType';
|
|
5
5
|
|
|
6
|
-
const PopoverComponent = (
|
|
6
|
+
const PopoverComponent = ({ onRequestClose, ...restProps }) => {
|
|
7
7
|
const { setAction } = useContext(SCContext);
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const _onRequestClose = () => {
|
|
10
10
|
setAction(Action.SET_POPOVER_ANIMATING, true);
|
|
11
|
+
onRequestClose && onRequestClose();
|
|
11
12
|
};
|
|
12
13
|
|
|
13
|
-
const
|
|
14
|
+
const _onCloseComplete = () => {
|
|
14
15
|
setAction(Action.SET_POPOVER_ANIMATING, false);
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
return (
|
|
18
19
|
<Popover
|
|
19
|
-
|
|
20
|
-
onCloseComplete={
|
|
21
|
-
{...
|
|
20
|
+
onRequestClose={_onRequestClose}
|
|
21
|
+
onCloseComplete={_onCloseComplete}
|
|
22
|
+
{...restProps}
|
|
22
23
|
/>
|
|
23
24
|
);
|
|
24
25
|
};
|
|
@@ -103,7 +103,10 @@ const ItemOneTap = memo(
|
|
|
103
103
|
? timeDifference(new Date(), moment(activate_at), true)
|
|
104
104
|
: null;
|
|
105
105
|
return (
|
|
106
|
-
<TouchableWithoutFeedback
|
|
106
|
+
<TouchableWithoutFeedback
|
|
107
|
+
onPress={onPressItem || goToDetail}
|
|
108
|
+
accessibilityLabel={`${TESTID.AUTOMATE_SCRIPT_NAME}-${id}`}
|
|
109
|
+
>
|
|
107
110
|
<View style={[styles.container, wrapSyles]}>
|
|
108
111
|
<View style={styles.boxIcon}>
|
|
109
112
|
{displayIcon()}
|
package/src/configs/Constants.js
CHANGED
|
@@ -313,11 +313,13 @@ export const TESTID = {
|
|
|
313
313
|
SUB_UNIT_GO_DETAIL: 'SUB_UNIT_GO_DETAIL',
|
|
314
314
|
VIEW_SUB_UNIT_AUTOMATE: 'VIEW_SUB_UNIT_AUTOMATE',
|
|
315
315
|
SUB_UNIT_NAME: 'SUB_UNIT_NAME',
|
|
316
|
+
SUB_UNIT_FAVORITES: 'SUB_UNIT_FAVORITES',
|
|
316
317
|
ANIMATED_SCROLL: 'ANIMATED_SCROLL',
|
|
317
318
|
ADD_SUB_UNIT: 'ADD_SUB_UNIT',
|
|
318
319
|
|
|
319
320
|
// NavBar
|
|
320
321
|
NAVBAR_ICON_BARS: 'NAVBAR_ICON_BARS',
|
|
322
|
+
NAVBAR_ICON_BARS_ADD_FAVORITES: 'NAVBAR_ICON_BARS_ADD_FAVORITES',
|
|
321
323
|
NAVBAR_MENU_ACTION_MORE: 'NAVBAR_MENU_ACTION_MORE',
|
|
322
324
|
NAVBAR_ON_SNAP_ITEM: 'NAVBAR_ON_SNAP_ITEM',
|
|
323
325
|
|
|
@@ -427,6 +429,7 @@ export const TESTID = {
|
|
|
427
429
|
|
|
428
430
|
// Automate
|
|
429
431
|
AUTOMATE_SCRIPT_ACTION: 'AUTOMATE_SCRIPT_ACTION',
|
|
432
|
+
AUTOMATE_SCRIPT_NAME: 'AUTOMATE_SCRIPT_NAME',
|
|
430
433
|
NAME_YOUR_BUTTON: 'NAME_YOUR_BUTTON',
|
|
431
434
|
BUTTON_ACTIVATE_ONE_TAP: 'BUTTON_ACTIVATE_ONE_TAP',
|
|
432
435
|
BUTTON_EDIT_SCRIPT_ACTION: 'BUTTON_EDIT_SCRIPT_ACTION',
|
|
@@ -444,6 +447,7 @@ export const TESTID = {
|
|
|
444
447
|
|
|
445
448
|
// Header Device
|
|
446
449
|
HEADER_DEVICE_BUTTON_STAR: 'HEADER_DEVICE_BUTTON_STAR',
|
|
450
|
+
HEADER_SCRIPT_DETAIL_BUTTON_STAR: 'HEADER_SCRIPT_DETAIL_BUTTON_STAR',
|
|
447
451
|
HEADER_DEVICE_BUTTON_MORE: 'HEADER_DEVICE_BUTTON_MORE',
|
|
448
452
|
|
|
449
453
|
// EMERGENCY BUTTON
|
|
@@ -666,6 +670,13 @@ export const TESTID = {
|
|
|
666
670
|
ADD_NEW_DEVICE_ADD: 'ADD_NEW_DEVICE_ADD',
|
|
667
671
|
ADD_NEW_DEVICE_THEN_SELECT: 'ADD_NEW_DEVICE_THEN_SELECT',
|
|
668
672
|
|
|
673
|
+
// Add Favorites
|
|
674
|
+
TOUCH_ADD_NEW_FAVORITES: 'TOUCH_ADD_NEW_FAVORITES',
|
|
675
|
+
LIST_FAVORITES: 'LIST_FAVORITES',
|
|
676
|
+
TOUCHABLE_ACTION_ADD_ITEM_FAVORITE: 'TOUCHABLE_ACTION_ADD_ITEM_FAVORITE',
|
|
677
|
+
TOUCHABLE_ACTION_ADD_ITEM_AUTOMATE_FAVORITE:
|
|
678
|
+
'TOUCHABLE_ACTION_ADD_ITEM_AUTOMATE_FAVORITE',
|
|
679
|
+
|
|
669
680
|
// Setup gateway wifi
|
|
670
681
|
SETUP_GATEWAY_WIFI_TITLE: 'SETUP_GATEWAY_WIFI_TITLE',
|
|
671
682
|
SETUP_GATEWAY_WIFI_PLEASE_SELECT_A_WIFI: 'SETUP_GATEWAY_PLEASE_SELECT_A_WIFI',
|
|
@@ -27,7 +27,7 @@ const useDevicesStatus = (unit, devices) => {
|
|
|
27
27
|
if (success) {
|
|
28
28
|
setAction(Action.SET_DEVICES_STATUS, data);
|
|
29
29
|
}
|
|
30
|
-
timeoutId = setTimeout(() => getDevicesStatus(_unit, _devices),
|
|
30
|
+
timeoutId = setTimeout(() => getDevicesStatus(_unit, _devices), 10000);
|
|
31
31
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
32
32
|
}, []);
|
|
33
33
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useContext, useEffect
|
|
1
|
+
import { useCallback, useContext, useEffect } from 'react';
|
|
2
2
|
import { API } from '../../configs';
|
|
3
3
|
import { SCContext, useSCContextSelector } from '../../context';
|
|
4
4
|
import { Action } from '../../context/actionType';
|
|
@@ -6,14 +6,15 @@ import { axiosGet } from '../../utils/Apis/axios';
|
|
|
6
6
|
|
|
7
7
|
const useValueEvaluations = (unitId) => {
|
|
8
8
|
const { setAction } = useContext(SCContext);
|
|
9
|
-
const
|
|
9
|
+
const fetchedValueEvaluationUnits = useSCContextSelector((state) => {
|
|
10
|
+
return state.fetchedValueEvaluationUnits || [];
|
|
11
|
+
});
|
|
10
12
|
|
|
11
13
|
const fetchConfigValueEvaluations = useCallback(
|
|
12
14
|
async (page = 1) => {
|
|
13
|
-
if (!unitId) {
|
|
15
|
+
if (!unitId || fetchedValueEvaluationUnits.indexOf(unitId) !== -1) {
|
|
14
16
|
return;
|
|
15
17
|
}
|
|
16
|
-
setFetching(true);
|
|
17
18
|
const params = new URLSearchParams();
|
|
18
19
|
params.append('config__end_device__station__unit', unitId);
|
|
19
20
|
params.append('page', page);
|
|
@@ -34,25 +35,15 @@ const useValueEvaluations = (unitId) => {
|
|
|
34
35
|
data: [],
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
|
-
setFetching(false);
|
|
38
38
|
},
|
|
39
|
-
|
|
39
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
40
|
+
[unitId, fetchedValueEvaluationUnits]
|
|
40
41
|
);
|
|
41
42
|
|
|
42
|
-
const fetchedValueEvaluationUnits = useSCContextSelector((state) => {
|
|
43
|
-
return state.fetchedValueEvaluationUnits || [];
|
|
44
|
-
});
|
|
45
|
-
|
|
46
43
|
useEffect(() => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}, [
|
|
51
|
-
unitId,
|
|
52
|
-
fetching,
|
|
53
|
-
fetchConfigValueEvaluations,
|
|
54
|
-
fetchedValueEvaluationUnits,
|
|
55
|
-
]);
|
|
44
|
+
fetchConfigValueEvaluations();
|
|
45
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
46
|
+
}, [unitId]);
|
|
56
47
|
};
|
|
57
48
|
|
|
58
49
|
export default useValueEvaluations;
|
|
@@ -127,12 +127,6 @@ export const googleHomeConnect = async (
|
|
|
127
127
|
for (let i = 0; i < options.length; i++) {
|
|
128
128
|
const option = options[i];
|
|
129
129
|
|
|
130
|
-
if (option.chip_id in oldConnections && !!oldConnections[option.chip_id]) {
|
|
131
|
-
connections[option.chip_id] = oldConnections[option.chip_id];
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
connections[option.chip_id] = 0; // connecting
|
|
135
|
-
|
|
136
130
|
option.config_maps.forEach((configMap) => {
|
|
137
131
|
if (option.text_maps) {
|
|
138
132
|
textMaps[configMap.entity_id] = option.text_maps;
|
|
@@ -156,6 +150,12 @@ export const googleHomeConnect = async (
|
|
|
156
150
|
}
|
|
157
151
|
});
|
|
158
152
|
|
|
153
|
+
if (option.chip_id in oldConnections && !!oldConnections[option.chip_id]) {
|
|
154
|
+
connections[option.chip_id] = oldConnections[option.chip_id];
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
connections[option.chip_id] = 0; // connecting
|
|
158
|
+
|
|
159
159
|
try {
|
|
160
160
|
let auth = new Auth(option.auth);
|
|
161
161
|
const connection = await createConnection({ auth });
|
|
@@ -68,7 +68,7 @@ export const UnitStack = memo((props) => {
|
|
|
68
68
|
const t = useTranslations();
|
|
69
69
|
const { setAction } = useContext(SCContext);
|
|
70
70
|
const { route } = props;
|
|
71
|
-
const { unitId, unitData } = route.params.params;
|
|
71
|
+
const { unitId, unitData, isSuccessfullyConnected } = route.params.params;
|
|
72
72
|
|
|
73
73
|
useEffect(() => {
|
|
74
74
|
const unsubscribe = NetInfo.addEventListener((state) => {
|
|
@@ -129,15 +129,12 @@ export const UnitStack = memo((props) => {
|
|
|
129
129
|
}, []);
|
|
130
130
|
|
|
131
131
|
useEffect(() => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (!id) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
132
|
+
const id = unitId || unitData?.id;
|
|
133
|
+
if (id && isSuccessfullyConnected) {
|
|
137
134
|
setAction(Action.NEED_UPDATE_VALUE_EVALUATIONS, id);
|
|
138
|
-
}
|
|
135
|
+
}
|
|
139
136
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
140
|
-
}, []);
|
|
137
|
+
}, [isSuccessfullyConnected]);
|
|
141
138
|
|
|
142
139
|
return (
|
|
143
140
|
<Stack.Navigator
|
|
@@ -3,6 +3,7 @@ import { TouchableWithoutFeedback, View } from 'react-native';
|
|
|
3
3
|
import { Colors } from '../../../configs';
|
|
4
4
|
import Text from '../../../commons/Text';
|
|
5
5
|
import IconComponent from '../../../commons/IconComponent';
|
|
6
|
+
import { TESTID } from '../../../configs/Constants';
|
|
6
7
|
import styles from './DeviceStyles';
|
|
7
8
|
|
|
8
9
|
const Device = memo(({ svgMain, sensor, title, isSelectDevice, onPress }) => {
|
|
@@ -13,7 +14,10 @@ const Device = memo(({ svgMain, sensor, title, isSelectDevice, onPress }) => {
|
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
return (
|
|
16
|
-
<TouchableWithoutFeedback
|
|
17
|
+
<TouchableWithoutFeedback
|
|
18
|
+
onPress={onPressDevice}
|
|
19
|
+
accessibilityLabel={`${TESTID.TOUCHABLE_ACTION_ADD_ITEM_FAVORITE}-${sensor.id}`}
|
|
20
|
+
>
|
|
17
21
|
<View style={[styles.container, isActive]}>
|
|
18
22
|
<View style={styles.boxIcon}>
|
|
19
23
|
<IconComponent
|
|
@@ -10,7 +10,7 @@ import ActionTemplate from '../../commons/ActionTemplate';
|
|
|
10
10
|
import NumberUpDownActionTemplate from '../../commons/OneTapTemplate/NumberUpDownActionTemplate';
|
|
11
11
|
import OptionsDropdownActionTemplate from '../../commons/OneTapTemplate/OptionsDropdownActionTemplate';
|
|
12
12
|
import StatesGridActionTemplate from '../../commons/OneTapTemplate/StatesGridActionTemplate';
|
|
13
|
-
import { axiosGet, axiosPost } from '../../utils/Apis/axios';
|
|
13
|
+
import { axiosGet, axiosPost, axiosPut } from '../../utils/Apis/axios';
|
|
14
14
|
import { API, Images } from '../../configs';
|
|
15
15
|
import {
|
|
16
16
|
CONDITION_TYPES,
|
|
@@ -159,19 +159,35 @@ const SelectAction = memo(({ route }) => {
|
|
|
159
159
|
await checkConditionToContinue();
|
|
160
160
|
} else {
|
|
161
161
|
if (automateId) {
|
|
162
|
-
let
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
{
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
162
|
+
let result = false;
|
|
163
|
+
if (isCreateNewAction) {
|
|
164
|
+
let list_action = [...actions];
|
|
165
|
+
list_action = list_action.map((item) => ({
|
|
166
|
+
action: item.action,
|
|
167
|
+
data: item.data,
|
|
168
|
+
}));
|
|
169
|
+
const { success } = await axiosPost(
|
|
170
|
+
API.AUTOMATE.ADD_SCRIPT_ACTION(automateId),
|
|
171
|
+
{
|
|
172
|
+
list_action,
|
|
173
|
+
unit: unit.id,
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
result = success;
|
|
177
|
+
} else {
|
|
178
|
+
const params = {
|
|
179
|
+
unit: isMultiUnits ? null : unit.id,
|
|
180
|
+
type: type,
|
|
181
|
+
name: scriptName,
|
|
182
|
+
action: actions[0].action,
|
|
183
|
+
};
|
|
184
|
+
const { success } = await axiosPut(
|
|
185
|
+
API.AUTOMATE.UPDATE_AUTOMATE(automateId),
|
|
186
|
+
params
|
|
187
|
+
);
|
|
188
|
+
result = success;
|
|
189
|
+
}
|
|
190
|
+
result &&
|
|
175
191
|
navigate(Routes.ScriptDetail, {
|
|
176
192
|
id: automateId,
|
|
177
193
|
name: scriptName,
|
|
@@ -78,9 +78,11 @@ const AddNewAutoSmart = memo(({ route }) => {
|
|
|
78
78
|
},
|
|
79
79
|
],
|
|
80
80
|
};
|
|
81
|
+
|
|
81
82
|
const [data] = useState(
|
|
82
83
|
automate?.id ? typeAutoSmart[AUTOMATE_TYPE.AUTOMATE] : typeAutoSmart[type]
|
|
83
84
|
);
|
|
85
|
+
|
|
84
86
|
const [selectedIndex, setSelectedIndex] = useState(
|
|
85
87
|
automate?.id ? data.findIndex((obj) => obj.type === type) : -1
|
|
86
88
|
);
|
|
@@ -4,6 +4,7 @@ import React, {
|
|
|
4
4
|
useCallback,
|
|
5
5
|
useContext,
|
|
6
6
|
useEffect,
|
|
7
|
+
useRef,
|
|
7
8
|
} from 'react';
|
|
8
9
|
import {
|
|
9
10
|
View,
|
|
@@ -45,6 +46,7 @@ const GatewayWifiList = memo(({ route }) => {
|
|
|
45
46
|
const [password, setPassword] = useState('');
|
|
46
47
|
const [selectedWifi, setSelectedWifi] = useState('');
|
|
47
48
|
const [isSendWifi, setIsSendWifi] = useState(false);
|
|
49
|
+
const isCheckSocketOnOneTime = useRef(true);
|
|
48
50
|
const { setAction } = useContext(SCContext);
|
|
49
51
|
|
|
50
52
|
const isConnectWifiGateway = useSCContextSelector(
|
|
@@ -106,18 +108,26 @@ const GatewayWifiList = memo(({ route }) => {
|
|
|
106
108
|
}
|
|
107
109
|
},
|
|
108
110
|
() => {
|
|
109
|
-
ToastBottomHelper.error('
|
|
111
|
+
ToastBottomHelper.error(t('can_not_login_to_current_ssid'));
|
|
110
112
|
}
|
|
111
113
|
);
|
|
112
114
|
}, 3000);
|
|
113
115
|
}
|
|
116
|
+
if (isCheckSocketOnOneTime.current && data.status === 'error') {
|
|
117
|
+
isCheckSocketOnOneTime.current = false;
|
|
118
|
+
setAction(Action.IS_CONNECT_WIFI_GATEWAY, false);
|
|
119
|
+
setIsShowPopupPassword(false);
|
|
120
|
+
ToastBottomHelper.error(t('confirm_password_not_match'));
|
|
121
|
+
}
|
|
114
122
|
},
|
|
115
123
|
[
|
|
116
124
|
chip_id,
|
|
117
125
|
devicePrefixName,
|
|
126
|
+
isCheckSocketOnOneTime,
|
|
118
127
|
navigate,
|
|
119
128
|
scan_sensor_data,
|
|
120
129
|
setAction,
|
|
130
|
+
t,
|
|
121
131
|
unit_id,
|
|
122
132
|
unit_name,
|
|
123
133
|
wifi_pass,
|
|
@@ -160,6 +170,7 @@ const GatewayWifiList = memo(({ route }) => {
|
|
|
160
170
|
goBack();
|
|
161
171
|
});
|
|
162
172
|
|
|
173
|
+
isCheckSocketOnOneTime.current = true;
|
|
163
174
|
sendConnect(0);
|
|
164
175
|
setAction(Action.IS_CONNECT_WIFI_GATEWAY, true);
|
|
165
176
|
setIsSendWifi(true);
|
|
@@ -168,6 +179,7 @@ const GatewayWifiList = memo(({ route }) => {
|
|
|
168
179
|
goBack,
|
|
169
180
|
handleSocketOnMsg,
|
|
170
181
|
isConnectWifiGateway,
|
|
182
|
+
isCheckSocketOnOneTime,
|
|
171
183
|
sendConnect,
|
|
172
184
|
setAction,
|
|
173
185
|
socket,
|
|
@@ -18,9 +18,7 @@ export const SensorConnectStatusViewHeader = ({
|
|
|
18
18
|
if (!!sensor && sensor?.is_managed_by_backend) {
|
|
19
19
|
return false;
|
|
20
20
|
} else {
|
|
21
|
-
if (sensor?.device_type === DEVICE_TYPE.
|
|
22
|
-
return false;
|
|
23
|
-
} else if (sensor?.device_type === DEVICE_TYPE.GOOGLE_HOME) {
|
|
21
|
+
if (sensor?.device_type === DEVICE_TYPE.GOOGLE_HOME) {
|
|
24
22
|
return isGGHomeConnecting;
|
|
25
23
|
} else {
|
|
26
24
|
return false;
|
|
@@ -33,6 +31,14 @@ export const SensorConnectStatusViewHeader = ({
|
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
if (!!sensor && sensor?.is_managed_by_backend) {
|
|
34
|
+
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<ConnectedViewHeader lastUpdated={lastUpdated} />
|
|
38
|
+
{children}
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
36
42
|
if (connectedViaNetwork) {
|
|
37
43
|
return (
|
|
38
44
|
<>
|
|
@@ -63,14 +69,7 @@ export const SensorConnectStatusViewHeader = ({
|
|
|
63
69
|
}
|
|
64
70
|
} else {
|
|
65
71
|
// not managed by backend
|
|
66
|
-
if (sensor?.device_type === DEVICE_TYPE.
|
|
67
|
-
return (
|
|
68
|
-
<>
|
|
69
|
-
<ConnectedViewHeader lastUpdated={lastUpdated} />
|
|
70
|
-
{children}
|
|
71
|
-
</>
|
|
72
|
-
);
|
|
73
|
-
} else if (sensor?.device_type === DEVICE_TYPE.GOOGLE_HOME) {
|
|
72
|
+
if (sensor?.device_type === DEVICE_TYPE.GOOGLE_HOME) {
|
|
74
73
|
if (connectedViaGGHome) {
|
|
75
74
|
return (
|
|
76
75
|
<>
|
|
@@ -4,6 +4,7 @@ import React, {
|
|
|
4
4
|
useMemo,
|
|
5
5
|
useState,
|
|
6
6
|
useRef,
|
|
7
|
+
useContext,
|
|
7
8
|
} from 'react';
|
|
8
9
|
import { View, TouchableOpacity } from 'react-native';
|
|
9
10
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
@@ -34,6 +35,8 @@ import BottomButtonView from '../../commons/BottomButtonView';
|
|
|
34
35
|
import Text from '../../commons/Text';
|
|
35
36
|
import { AlertAction, ButtonPopup, MenuActionMore } from '../../commons';
|
|
36
37
|
import { DEVICE_TYPE, TESTID } from '../../configs/Constants';
|
|
38
|
+
import { SCContext } from '../../context';
|
|
39
|
+
import { Action } from '../../context/actionType';
|
|
37
40
|
|
|
38
41
|
import { usePopover } from '../../hooks/Common';
|
|
39
42
|
import { useConfigGlobalState } from '../../iot/states';
|
|
@@ -60,14 +63,17 @@ const DeviceDetail = ({ route }) => {
|
|
|
60
63
|
const t = useTranslations();
|
|
61
64
|
const navigation = useNavigation();
|
|
62
65
|
const token = useSCContextSelector((state) => state.auth.account.token);
|
|
66
|
+
const { setAction } = useContext(SCContext);
|
|
63
67
|
const [offsetTitle, setOffsetTitle] = useState(1);
|
|
64
68
|
const [display, setDisplay] = useState({ items: [] });
|
|
65
|
-
const [
|
|
69
|
+
const [displayValuesData, setDisplayValuesData] = useState({
|
|
70
|
+
configs: [],
|
|
71
|
+
isConnected: false,
|
|
72
|
+
lastUpdated: null,
|
|
73
|
+
});
|
|
66
74
|
const [controlOptions, setControlOptions] = useState({
|
|
67
75
|
internet: {},
|
|
68
76
|
});
|
|
69
|
-
const [isConnected, setConnected] = useState(false);
|
|
70
|
-
const [lastUpdated, setLastUpdated] = useState(null);
|
|
71
77
|
const [lastEvent, setLastEvent] = useState({ id: 0, reportedAt: 0 });
|
|
72
78
|
const [maxValue, setMaxValue] = useState(60);
|
|
73
79
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -447,7 +453,9 @@ const DeviceDetail = ({ route }) => {
|
|
|
447
453
|
|
|
448
454
|
const data = item.configuration.configs.map((config) => {
|
|
449
455
|
const configValue = configValues[config.id]?.value;
|
|
450
|
-
const displayValue =
|
|
456
|
+
const displayValue = (displayValuesData.configs || []).find(
|
|
457
|
+
(k) => k.id === config.id
|
|
458
|
+
);
|
|
451
459
|
if (
|
|
452
460
|
(configValue === null || configValue === undefined) &&
|
|
453
461
|
!displayValue
|
|
@@ -466,7 +474,7 @@ const DeviceDetail = ({ route }) => {
|
|
|
466
474
|
});
|
|
467
475
|
return data.filter((value) => value);
|
|
468
476
|
},
|
|
469
|
-
[configValues,
|
|
477
|
+
[configValues, displayValuesData, evaluateValue]
|
|
470
478
|
);
|
|
471
479
|
|
|
472
480
|
useEffect(() => {
|
|
@@ -501,17 +509,23 @@ const DeviceDetail = ({ route }) => {
|
|
|
501
509
|
}
|
|
502
510
|
);
|
|
503
511
|
if (success) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
data.last_updated = data.last_updated
|
|
512
|
+
data.isConnected = data.is_connected;
|
|
513
|
+
data.lastUpdated = data.last_updated
|
|
507
514
|
? moment(data.last_updated)
|
|
508
515
|
: data.last_updated;
|
|
509
|
-
|
|
510
|
-
|
|
516
|
+
setDisplayValuesData((prevState) => {
|
|
517
|
+
if (prevState.isConnected !== data.isConnected) {
|
|
518
|
+
setAction(Action.SET_DEVICES_STATUS, [
|
|
519
|
+
{ id: sensor?.id, is_connected: data.is_connected },
|
|
520
|
+
]);
|
|
521
|
+
}
|
|
522
|
+
return data;
|
|
523
|
+
});
|
|
511
524
|
} else if (resp_status >= 500) {
|
|
512
525
|
setServerDown(true);
|
|
513
526
|
}
|
|
514
|
-
|
|
527
|
+
loading.isConnected &&
|
|
528
|
+
setLoading((preState) => ({ ...preState, isConnected: false }));
|
|
515
529
|
};
|
|
516
530
|
if (
|
|
517
531
|
sensor?.is_managed_by_backend &&
|
|
@@ -524,7 +538,8 @@ const DeviceDetail = ({ route }) => {
|
|
|
524
538
|
Object.keys(sensor).length > 1 &&
|
|
525
539
|
setLoading((preState) => ({ ...preState, isConnected: false }));
|
|
526
540
|
}
|
|
527
|
-
|
|
541
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
542
|
+
}, [sensor, display, loading.isConnected]);
|
|
528
543
|
|
|
529
544
|
const isShowEmergencyResolve =
|
|
530
545
|
display.items.filter(
|
|
@@ -563,14 +578,17 @@ const DeviceDetail = ({ route }) => {
|
|
|
563
578
|
return (
|
|
564
579
|
<SensorConnectStatusViewHeader
|
|
565
580
|
sensor={sensor}
|
|
566
|
-
connectedViaNetwork={
|
|
581
|
+
connectedViaNetwork={
|
|
582
|
+
isNetworkConnected && displayValuesData.isConnected
|
|
583
|
+
}
|
|
567
584
|
connectedViaBle={
|
|
568
|
-
(!isNetworkConnected ||
|
|
585
|
+
(!isNetworkConnected ||
|
|
586
|
+
(isNetworkConnected && !displayValuesData.isConnected)) &&
|
|
569
587
|
isDeviceConnectedViaBle
|
|
570
588
|
}
|
|
571
589
|
connectedViaGGHome={isGGHomeConnected}
|
|
572
590
|
isGGHomeConnecting={isGGHomeConnecting}
|
|
573
|
-
lastUpdated={lastUpdated}
|
|
591
|
+
lastUpdated={displayValuesData.lastUpdated}
|
|
574
592
|
isDisplayTime={isShowSetupEmergencyContact ? false : isDisplayTime}
|
|
575
593
|
showWindDirection={showWindDirection}
|
|
576
594
|
isGGHomeConnected={isGGHomeConnected}
|
|
@@ -676,6 +694,7 @@ const DeviceDetail = ({ route }) => {
|
|
|
676
694
|
style={styles.buttonStar}
|
|
677
695
|
onPress={isFavorite ? removeFromFavorites : addToFavorites}
|
|
678
696
|
testID={TESTID.HEADER_DEVICE_BUTTON_STAR}
|
|
697
|
+
accessibilityLabel={TESTID.HEADER_DEVICE_BUTTON_STAR}
|
|
679
698
|
>
|
|
680
699
|
{isFavorite ? (
|
|
681
700
|
<IconFill name="star" size={25} color={Colors.Yellow6} />
|
|
@@ -725,7 +744,7 @@ const DeviceDetail = ({ route }) => {
|
|
|
725
744
|
renderSensorConnected()}
|
|
726
745
|
</View>
|
|
727
746
|
{isNetworkConnected &&
|
|
728
|
-
isConnected &&
|
|
747
|
+
displayValuesData?.isConnected &&
|
|
729
748
|
isShowSetupEmergencyContact &&
|
|
730
749
|
canManageSubUnit && (
|
|
731
750
|
<BottomButtonView
|
|
@@ -17,14 +17,16 @@ export const useFavoriteDevice = (device) => {
|
|
|
17
17
|
API.DEVICE.ADD_TO_FAVOURITES(device?.id)
|
|
18
18
|
);
|
|
19
19
|
success && setAction(Action.ADD_DEVICES_TO_FAVORITES, [device.id]);
|
|
20
|
-
|
|
20
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
21
|
+
}, [device]);
|
|
21
22
|
|
|
22
23
|
const removeFromFavorites = useCallback(async () => {
|
|
23
24
|
const { success } = await axiosPost(
|
|
24
25
|
API.DEVICE.REMOVE_FROM_FAVOURITES(device?.id)
|
|
25
26
|
);
|
|
26
27
|
success && setAction(Action.REMOVE_DEVICES_FROM_FAVORITES, [device.id]);
|
|
27
|
-
|
|
28
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
29
|
+
}, [device]);
|
|
28
30
|
|
|
29
31
|
return {
|
|
30
32
|
isFavorite,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { StyleSheet, TextInput, View } from 'react-native';
|
|
3
3
|
import { useNavigation } from '@react-navigation/native';
|
|
4
4
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
5
5
|
import { Section, ViewButtonBottom } from '../../commons';
|
|
@@ -53,7 +53,7 @@ export const EmergencyContactsAddNew = ({ route }) => {
|
|
|
53
53
|
}, [goBack, group.id, t, textName, textPhone]);
|
|
54
54
|
|
|
55
55
|
return (
|
|
56
|
-
<
|
|
56
|
+
<View style={styles.wrap}>
|
|
57
57
|
<WrapHeaderScrollable title={t('create_contact')}>
|
|
58
58
|
<Section type={'border'}>
|
|
59
59
|
<TextInput
|
|
@@ -87,7 +87,7 @@ export const EmergencyContactsAddNew = ({ route }) => {
|
|
|
87
87
|
onRightClick={onSave}
|
|
88
88
|
/>
|
|
89
89
|
</View>
|
|
90
|
-
</
|
|
90
|
+
</View>
|
|
91
91
|
);
|
|
92
92
|
};
|
|
93
93
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
3
|
import { IconOutline } from '@ant-design/icons-react-native';
|
|
4
4
|
import { useNavigation } from '@react-navigation/native';
|
|
5
5
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
@@ -70,9 +70,9 @@ export const EmergencyContactsSelectContacts = ({ route }) => {
|
|
|
70
70
|
loadMembers(unitId);
|
|
71
71
|
}, [loadMembers, unitId]);
|
|
72
72
|
return (
|
|
73
|
-
<
|
|
73
|
+
<View style={styles.container}>
|
|
74
74
|
<WrapHeaderScrollable title={t('select_contacts')} loading={loading}>
|
|
75
|
-
<Section type={'border'}
|
|
75
|
+
<Section type={'border'}>
|
|
76
76
|
{dataContact.map((contact, index) => (
|
|
77
77
|
<RowUser
|
|
78
78
|
key={contact.id.toString()}
|
|
@@ -108,7 +108,7 @@ export const EmergencyContactsSelectContacts = ({ route }) => {
|
|
|
108
108
|
onRightClick={goSave}
|
|
109
109
|
rightDisabled={false}
|
|
110
110
|
/>
|
|
111
|
-
</
|
|
111
|
+
</View>
|
|
112
112
|
);
|
|
113
113
|
};
|
|
114
114
|
|
|
@@ -117,9 +117,6 @@ const styles = StyleSheet.create({
|
|
|
117
117
|
flex: 1,
|
|
118
118
|
backgroundColor: Colors.Gray2,
|
|
119
119
|
},
|
|
120
|
-
section: {
|
|
121
|
-
marginTop: Platform.OS === 'ios' ? 40 : 0,
|
|
122
|
-
},
|
|
123
120
|
buttonRemove: {
|
|
124
121
|
height: 40,
|
|
125
122
|
width: 40,
|
|
@@ -57,7 +57,6 @@ describe('test NotificationItem', () => {
|
|
|
57
57
|
NOTIFICATION_TYPES.NOTIFY_MEMBER_LEAVE_UNIT,
|
|
58
58
|
NOTIFICATION_TYPES.NOTIFY_REMOVE_SUB_UNIT,
|
|
59
59
|
NOTIFICATION_TYPES.NOTIFY_REMOVE_DEVICE,
|
|
60
|
-
'default case',
|
|
61
60
|
];
|
|
62
61
|
|
|
63
62
|
for (const content_code of listCase2) {
|
|
@@ -176,11 +175,8 @@ describe('test NotificationItem', () => {
|
|
|
176
175
|
tree = create(wrapComponent(item));
|
|
177
176
|
});
|
|
178
177
|
const instance = tree.root;
|
|
179
|
-
const button = instance.
|
|
180
|
-
|
|
181
|
-
button.props.onPress();
|
|
182
|
-
});
|
|
183
|
-
expect(mockNavigate).not.toHaveBeenCalled();
|
|
178
|
+
const button = instance.findAllByType(TouchableOpacity);
|
|
179
|
+
expect(button).toHaveLength(0);
|
|
184
180
|
});
|
|
185
181
|
|
|
186
182
|
const listSensorType2 = [
|
|
@@ -249,25 +245,8 @@ describe('test NotificationItem', () => {
|
|
|
249
245
|
tree = create(wrapComponent(item));
|
|
250
246
|
});
|
|
251
247
|
const instance = tree.root;
|
|
252
|
-
const button = instance.
|
|
253
|
-
|
|
254
|
-
button.props.onPress();
|
|
255
|
-
});
|
|
256
|
-
expect(mockNavigate).not.toHaveBeenCalledWith();
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
test('test render Notify params is object', () => {
|
|
260
|
-
item.content_code = 'NEW CASE';
|
|
261
|
-
item.params = { unit_id: 1 };
|
|
262
|
-
act(() => {
|
|
263
|
-
tree = create(wrapComponent(item));
|
|
264
|
-
});
|
|
265
|
-
const instance = tree.root;
|
|
266
|
-
const button = instance.findByType(TouchableOpacity);
|
|
267
|
-
act(() => {
|
|
268
|
-
button.props.onPress();
|
|
269
|
-
});
|
|
270
|
-
expect(mockNavigate).not.toHaveBeenCalledWith();
|
|
248
|
+
const button = instance.findAllByType(TouchableOpacity);
|
|
249
|
+
expect(button).toHaveLength(0);
|
|
271
250
|
});
|
|
272
251
|
|
|
273
252
|
test('test notify emergency ', () => {
|
|
@@ -332,10 +311,7 @@ describe('test NotificationItem', () => {
|
|
|
332
311
|
tree = create(wrapComponent(item));
|
|
333
312
|
});
|
|
334
313
|
const instance = tree.root;
|
|
335
|
-
const button = instance.
|
|
336
|
-
|
|
337
|
-
button.props.onPress();
|
|
338
|
-
});
|
|
339
|
-
expect(mockNavigate).not.toHaveBeenCalled();
|
|
314
|
+
const button = instance.findAllByType(TouchableOpacity);
|
|
315
|
+
expect(button).toHaveLength(0);
|
|
340
316
|
});
|
|
341
317
|
});
|
|
@@ -195,13 +195,7 @@ const NotificationItem = memo(({ item }) => {
|
|
|
195
195
|
iconContent: <Image source={Images.logo} style={styles.logo} />,
|
|
196
196
|
};
|
|
197
197
|
default:
|
|
198
|
-
return
|
|
199
|
-
content: customColorText(
|
|
200
|
-
t('this_notification_will_be_updated_soon')
|
|
201
|
-
),
|
|
202
|
-
redirect: () => null,
|
|
203
|
-
iconContent: <Image source={Images.logo} style={styles.logo} />,
|
|
204
|
-
};
|
|
198
|
+
return null;
|
|
205
199
|
}
|
|
206
200
|
|
|
207
201
|
case NOTIFICATION_TYPES.NOTIFY_REMOVE_UNIT:
|
|
@@ -354,20 +348,10 @@ const NotificationItem = memo(({ item }) => {
|
|
|
354
348
|
iconContent: <Image source={Images.logo} style={styles.logo} />,
|
|
355
349
|
};
|
|
356
350
|
default:
|
|
357
|
-
return
|
|
358
|
-
content: customColorText(
|
|
359
|
-
t('this_notification_will_be_updated_soon')
|
|
360
|
-
),
|
|
361
|
-
redirect: () => null,
|
|
362
|
-
iconContent: <Image source={Images.logo} style={styles.logo} />,
|
|
363
|
-
};
|
|
351
|
+
return null;
|
|
364
352
|
}
|
|
365
353
|
default:
|
|
366
|
-
return
|
|
367
|
-
content: customColorText(t('this_notification_will_be_updated_soon')),
|
|
368
|
-
redirect: () => null,
|
|
369
|
-
iconContent: <Image source={Images.logo} style={styles.logo} />,
|
|
370
|
-
};
|
|
354
|
+
return null;
|
|
371
355
|
}
|
|
372
356
|
}, [content_code, customColorText, navigation, params, t]);
|
|
373
357
|
|
|
@@ -168,7 +168,7 @@ describe('Test ScriptDetail', () => {
|
|
|
168
168
|
});
|
|
169
169
|
const instance = tree.root;
|
|
170
170
|
const buttonStar = instance.find(
|
|
171
|
-
(el) => el.props.testID === TESTID.
|
|
171
|
+
(el) => el.props.testID === TESTID.HEADER_SCRIPT_DETAIL_BUTTON_STAR
|
|
172
172
|
);
|
|
173
173
|
mock.onPost(API.AUTOMATE.STAR_SCRIPT(1)).reply(200);
|
|
174
174
|
await act(async () => {
|
|
@@ -321,7 +321,8 @@ const ScriptDetail = ({ route }) => {
|
|
|
321
321
|
<PreventDoubleTouch
|
|
322
322
|
style={[styles.buttonStar, styles.headerButton]}
|
|
323
323
|
onPress={onPressStar}
|
|
324
|
-
testID={TESTID.
|
|
324
|
+
testID={TESTID.HEADER_SCRIPT_DETAIL_BUTTON_STAR}
|
|
325
|
+
accessibilityLabel={TESTID.HEADER_SCRIPT_DETAIL_BUTTON_STAR}
|
|
325
326
|
>
|
|
326
327
|
{isStarred ? (
|
|
327
328
|
<IconFill name="star" size={25} color={Colors.Yellow6} />
|
|
@@ -27,7 +27,7 @@ const SensorItem = ({
|
|
|
27
27
|
isChecked,
|
|
28
28
|
} = item;
|
|
29
29
|
const [dataConfig, setDataConfig] = useState([
|
|
30
|
-
...actions,
|
|
30
|
+
...actions.map((i) => ({ ...i, isControl: true })),
|
|
31
31
|
...read_configs.map((i) => ({ ...i, isConfig: true })),
|
|
32
32
|
]);
|
|
33
33
|
|
|
@@ -84,6 +84,9 @@ const SensorItem = ({
|
|
|
84
84
|
titleStyle={styles.titleStyle}
|
|
85
85
|
key={i.id}
|
|
86
86
|
idGroup={idGroup}
|
|
87
|
+
isConfig={i.isConfig}
|
|
88
|
+
isControl={i.isControl}
|
|
89
|
+
wrapStyle={styles.wrapStyleTitle}
|
|
87
90
|
/>
|
|
88
91
|
));
|
|
89
92
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -49,6 +49,7 @@ export default StyleSheet.create({
|
|
|
49
49
|
titleStyle: {
|
|
50
50
|
fontSize: 16,
|
|
51
51
|
fontWeight: 'normal',
|
|
52
|
+
width: 200,
|
|
52
53
|
},
|
|
53
54
|
wrapExpand: {
|
|
54
55
|
marginTop: 10,
|
|
@@ -57,4 +58,7 @@ export default StyleSheet.create({
|
|
|
57
58
|
width: normalize(20),
|
|
58
59
|
height: normalize(20),
|
|
59
60
|
},
|
|
61
|
+
wrapStyleTitle: {
|
|
62
|
+
justifyContent: 'space-between',
|
|
63
|
+
},
|
|
60
64
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { memo, useEffect, useState } from 'react';
|
|
2
2
|
import { View, Text } from 'react-native';
|
|
3
3
|
import { CheckBoxCustom } from '.';
|
|
4
|
+
import t from '../../../hooks/Common/useTranslations';
|
|
4
5
|
import styles from './Styles/TitleCheckBoxStyles';
|
|
5
6
|
|
|
6
7
|
const TitleCheckBox = ({
|
|
@@ -12,6 +13,8 @@ const TitleCheckBox = ({
|
|
|
12
13
|
wrapStyle,
|
|
13
14
|
titleStyle,
|
|
14
15
|
idGroup,
|
|
16
|
+
isConfig,
|
|
17
|
+
isControl,
|
|
15
18
|
}) => {
|
|
16
19
|
const [checked, setChecked] = useState(isChecked);
|
|
17
20
|
const handleOnPress = () => {
|
|
@@ -26,14 +29,20 @@ const TitleCheckBox = ({
|
|
|
26
29
|
|
|
27
30
|
return (
|
|
28
31
|
<View style={[styles.wrap, wrapStyle]}>
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
{title}
|
|
36
|
-
|
|
32
|
+
<View style={styles.wrapRow}>
|
|
33
|
+
<CheckBoxCustom
|
|
34
|
+
isChecked={checked}
|
|
35
|
+
onPress={handleOnPress}
|
|
36
|
+
wrapStyle={wrapCheckBoxStyle}
|
|
37
|
+
/>
|
|
38
|
+
<Text onPress={handleOnPress} style={[styles.title, titleStyle]}>
|
|
39
|
+
{title}
|
|
40
|
+
</Text>
|
|
41
|
+
</View>
|
|
42
|
+
<View>
|
|
43
|
+
{isControl && <Text>{t('can_control')}</Text>}
|
|
44
|
+
{isConfig && <Text>{t('view_only')}</Text>}
|
|
45
|
+
</View>
|
|
37
46
|
</View>
|
|
38
47
|
);
|
|
39
48
|
};
|
|
@@ -108,10 +108,12 @@ const UnitDetail = ({ route }) => {
|
|
|
108
108
|
rawUnitData.stations.unshift({
|
|
109
109
|
isOneTap: true,
|
|
110
110
|
name: t('smart'),
|
|
111
|
+
id: 'smart',
|
|
111
112
|
});
|
|
112
113
|
rawUnitData.stations.unshift({
|
|
113
114
|
isFavorites: true,
|
|
114
115
|
name: t('favorites'),
|
|
116
|
+
id: 'favorites',
|
|
115
117
|
});
|
|
116
118
|
},
|
|
117
119
|
[t]
|
|
@@ -302,7 +304,8 @@ const UnitDetail = ({ route }) => {
|
|
|
302
304
|
clearTimeout(to);
|
|
303
305
|
}, 3000);
|
|
304
306
|
}
|
|
305
|
-
|
|
307
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
308
|
+
}, [isFirstOpenCamera, isIOS]);
|
|
306
309
|
|
|
307
310
|
return (
|
|
308
311
|
<WrapParallaxScrollView
|
|
@@ -331,6 +334,8 @@ const UnitDetail = ({ route }) => {
|
|
|
331
334
|
onSnapToItem={onSnapToItem}
|
|
332
335
|
indexStation={indexStation}
|
|
333
336
|
idLabelScrollView={TESTID.NAV_LIST}
|
|
337
|
+
idLabelItem={TESTID.SUB_UNIT_NAME}
|
|
338
|
+
idLabelIconBars={TESTID.NAVBAR_ICON_BARS}
|
|
334
339
|
/>
|
|
335
340
|
{renderDetailSubUnit()}
|
|
336
341
|
{!!unit.can_add && unit.stations.length === 0 && (
|
|
@@ -21,6 +21,7 @@ import { SCContext } from '../../context';
|
|
|
21
21
|
import { Action } from '../../context/actionType';
|
|
22
22
|
import { axiosGet, axiosPost } from '../../utils/Apis/axios';
|
|
23
23
|
import { API, Colors } from '../../configs';
|
|
24
|
+
import { TESTID } from '../../configs/Constants';
|
|
24
25
|
import styles from './SelectAddToFavoritesStyles';
|
|
25
26
|
|
|
26
27
|
const SelectAddToFavorites = memo(({ route }) => {
|
|
@@ -136,7 +137,12 @@ const SelectAddToFavorites = memo(({ route }) => {
|
|
|
136
137
|
|
|
137
138
|
const rightComponent = useMemo(
|
|
138
139
|
() => (
|
|
139
|
-
<TouchableOpacity
|
|
140
|
+
<TouchableOpacity
|
|
141
|
+
testID={TESTID.ICON_BACK}
|
|
142
|
+
accessibilityLabel={TESTID.ICON_BACK}
|
|
143
|
+
style={styles.buttonClose}
|
|
144
|
+
onPress={goBack}
|
|
145
|
+
>
|
|
140
146
|
<Icon name={'close'} size={24} color={Colors.Black} />
|
|
141
147
|
</TouchableOpacity>
|
|
142
148
|
),
|
|
@@ -151,6 +157,8 @@ const SelectAddToFavorites = memo(({ route }) => {
|
|
|
151
157
|
style={styles.wrap}
|
|
152
158
|
contentContainerStyle={styles.contentContainerStyle}
|
|
153
159
|
scrollIndicatorInsets={{ right: 1 }}
|
|
160
|
+
testID={TESTID.LIST_FAVORITES}
|
|
161
|
+
idLabelScrollView={TESTID.LIST_FAVORITES}
|
|
154
162
|
>
|
|
155
163
|
<Text bold type="H2" style={styles.title}>
|
|
156
164
|
{t('select_device')}
|
|
@@ -162,6 +170,8 @@ const SelectAddToFavorites = memo(({ route }) => {
|
|
|
162
170
|
listMenuItem={listMenuItem}
|
|
163
171
|
onSnapToItem={onSnapToItem}
|
|
164
172
|
indexStation={indexStation}
|
|
173
|
+
idLabelItem={TESTID.SUB_UNIT_FAVORITES}
|
|
174
|
+
idLabelIconBars={TESTID.NAVBAR_ICON_BARS_ADD_FAVORITES}
|
|
165
175
|
style={styles.navbar}
|
|
166
176
|
/>
|
|
167
177
|
)}
|
|
@@ -9,7 +9,7 @@ import ValueChange from '../../../../../assets/images/ValueChange.svg';
|
|
|
9
9
|
import Schedule from '../../../../../assets/images/Schedule.svg';
|
|
10
10
|
import Event from '../../../../../assets/images/Event.svg';
|
|
11
11
|
import styles from './styles';
|
|
12
|
-
import { AUTOMATE_TYPE } from '../../../../configs/Constants';
|
|
12
|
+
import { AUTOMATE_TYPE, TESTID } from '../../../../configs/Constants';
|
|
13
13
|
import { Colors } from '../../../../configs';
|
|
14
14
|
|
|
15
15
|
const AutomateScript = ({ automate, onPress, isSelected }) => {
|
|
@@ -36,7 +36,10 @@ const AutomateScript = ({ automate, onPress, isSelected }) => {
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
return (
|
|
39
|
-
<TouchableWithoutFeedback
|
|
39
|
+
<TouchableWithoutFeedback
|
|
40
|
+
onPress={_onPress}
|
|
41
|
+
accessibilityLabel={`${TESTID.TOUCHABLE_ACTION_ADD_ITEM_AUTOMATE_FAVORITE}-${automate.id}`}
|
|
42
|
+
>
|
|
40
43
|
<View style={[styles.container, isSelected && styles.active]}>
|
|
41
44
|
<View style={styles.boxIcon}>{displayIcon()}</View>
|
|
42
45
|
<View>
|
|
@@ -687,6 +687,7 @@
|
|
|
687
687
|
"text_notification_content_update_address": "New address of **unit_name** has been updated by **unit_owner_name** to **unit_address**.",
|
|
688
688
|
"text_notification_content_emergency": "The Emergency button has been activated at **unit_name**: **sub_unit_name**. Please check now!",
|
|
689
689
|
"text_notification_content_emergency_resolve": "Emergency situation activated at **unit_name**: **sub_unit_name** has resolved.",
|
|
690
|
+
"text_notification_content_invite_member": "**unit_owner_name** invited you to join **unit_name**.",
|
|
690
691
|
"this_spot_does_not_exsit": "This spot does not exist",
|
|
691
692
|
"please_scan_again_or_contact_the_parking_manager": "Please scan again or contact the parking manager",
|
|
692
693
|
"this_spot_does_not_support_to_scan": "This spot does not support to scan",
|
|
@@ -979,10 +980,14 @@
|
|
|
979
980
|
"activated": "Activated",
|
|
980
981
|
"text_unit_add_to_favorites_no_devices": "You don't have any devices or all your devices was added to your favorites",
|
|
981
982
|
"not_found": "Not found",
|
|
983
|
+
"view_only": "View only",
|
|
984
|
+
"can_control": "Can control",
|
|
982
985
|
"not_activated": "Not activated",
|
|
983
986
|
"open": "Open",
|
|
984
987
|
"close": "Close",
|
|
985
988
|
"create_contact_success": "Create contact success!",
|
|
989
|
+
"can_not_login_to_current_ssid":"Can't login to current SSID",
|
|
990
|
+
"confirm_password_not_match": "Confirm password does not match",
|
|
986
991
|
"templates": "Templates",
|
|
987
992
|
"template": "Template",
|
|
988
993
|
"gateways": "Gateways",
|
|
@@ -702,6 +702,7 @@
|
|
|
702
702
|
"text_notification_content_update_address": "Địa chỉ mới của **unit_name** vừa được cập nhật bởi **unit_owner_name** thành **unit_address**.",
|
|
703
703
|
"text_notification_content_emergency": "Một tình huống khẩn cấp vừa được kích hoạt tại **unit_name**: **sub_unit_name**. Vui lòng kiểm tra ngay!",
|
|
704
704
|
"text_notification_content_emergency_resolve": "Tình huống khẩn cấp được kích hoạt tại **unit_name**: **sub_unit_name** đã được giải quyết.",
|
|
705
|
+
"text_notification_content_invite_member": "**unit_owner_name** mời bạn đến địa điểm **unit_name**.",
|
|
705
706
|
"this_spot_does_not_exsit": "Vị trí đỗ này không tồn tại",
|
|
706
707
|
"please_scan_again_or_contact_the_parking_manager": "Vui lòng quét lại hoặc liên hệ với người quản lý bãi đậu xe",
|
|
707
708
|
"this_spot_does_not_support_to_scan": "Vị trí đỗ này không hỗ trợ quét",
|
|
@@ -978,10 +979,14 @@
|
|
|
978
979
|
"activated": "Được kích hoạt",
|
|
979
980
|
"text_unit_add_to_favorites_no_devices": "Bạn không có thiết bị nào hoặc tất cả thiết bị của bạn đã được thêm vào yêu thích",
|
|
980
981
|
"not_found": "Không tìm thấy",
|
|
982
|
+
"view_only": "Chỉ xem",
|
|
983
|
+
"can_control": "Có thể điều khiển",
|
|
981
984
|
"not_activated": "Không kích hoạt",
|
|
982
985
|
"open": "Mở",
|
|
983
986
|
"close": "Đóng",
|
|
984
987
|
"create_contact_success": "Tạo liên hệ thành công!",
|
|
988
|
+
"can_not_login_to_current_ssid":"Không thể đăng nhập vào SSID hiện tại",
|
|
989
|
+
"confirm_password_not_match": "Mật khẩu xác nhận không trùng khớp",
|
|
985
990
|
"templates": "Mẫu",
|
|
986
991
|
"template": "Mẫu",
|
|
987
992
|
"gateways": "Cổng vào",
|