@eohjsc/react-native-smart-city 0.2.75 → 0.2.76
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/index.js +2 -1
- package/package.json +2 -2
- package/src/commons/ActionGroup/SmartTiviActionTemplate/component/ControlPlayStyles.js +1 -5
- package/src/commons/ActionGroup/__test__/TimerActionTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/TimerActionTemplateWithutConfigValue.test.js +1 -1
- package/src/commons/ActionGroup/__test__/index.test.js +3 -3
- package/src/commons/ActionTemplate/__test__/index.test.js +2 -2
- package/src/commons/Automate/__test__/ItemAutomate.test.js +1 -1
- package/src/commons/Dashboard/MyPinnedSharedUnit/__test__/MyPinnedSharedUnit.test.js +1 -1
- package/src/commons/Device/ItemDevice.js +17 -2
- package/src/commons/Device/WindDirection/Compass/Compass.test.js +2 -2
- package/src/commons/Device/__test__/ConnectedViewHeader.test.js +2 -2
- package/src/commons/Device/__test__/DisconnectedView.test.js +5 -5
- package/src/commons/Explore/__test__/HeaderExplore.test.js +1 -1
- package/src/commons/MediaPlayerDetail/__test__/MediaPlayerDetail.test.js +1 -1
- package/src/commons/Modal/__test__/ModalBottom.test.js +2 -2
- package/src/commons/Sharing/__test__/MemberList.test.js +3 -3
- package/src/commons/Sharing/__test__/RowMember.test.js +2 -2
- package/src/commons/SubUnit/Favorites/index.js +32 -1
- package/src/commons/SubUnit/ShortDetail.js +33 -3
- package/src/commons/SubUnit/__test__/Favorites.test.js +1 -0
- package/src/commons/SubUnit/__test__/ShortDetail.test.js +1 -0
- package/src/commons/Today/__test__/Today.test.js +1 -1
- package/src/configs/API.js +1 -0
- package/src/context/SCContext.tsx +35 -2
- package/src/context/index.ts +6 -1
- package/src/screens/ActivityLog/__test__/index.test.js +10 -11
- package/src/screens/AddNewAction/Device/__test__/index.test.js +2 -2
- package/src/screens/AddNewDevice/__test__/ConnectingDevices.test.js +1 -1
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/FirstWarning.test.js +1 -1
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/GatewayWifiList.test.js +1 -1
- package/src/screens/AddNewGateway/__test__/ConnectingGateway.test.js +1 -1
- package/src/screens/PlayBackCamera/__test__/index.test.js +1 -1
- package/src/screens/Unit/__test__/Detail.test.js +7 -1
- package/src/screens/Unit/components/__test__/Header.test.js +5 -5
- package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +4 -2
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SCContext, SCProvider } from './src/context';
|
|
1
|
+
import { SCContext, SCProvider, SCWrapper } from './src/context';
|
|
2
2
|
import { AddDeviceStack } from './src/navigations/AddDeviceStack';
|
|
3
3
|
import { AddGatewayStack } from './src/navigations/AddGatewayStack';
|
|
4
4
|
import { AddMemberStack } from './src/navigations/AddMemberStack';
|
|
@@ -35,4 +35,5 @@ export {
|
|
|
35
35
|
MyPinnedSharedUnit,
|
|
36
36
|
SharedUnit,
|
|
37
37
|
MyUnit,
|
|
38
|
+
SCWrapper,
|
|
38
39
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eohjsc/react-native-smart-city",
|
|
3
3
|
"title": "React Native Smart Home",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.76",
|
|
5
5
|
"description": "TODO",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"files": [
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
"react-native-snap-carousel": "4.0.0-beta.5",
|
|
183
183
|
"react-native-super-grid": "^4.0.3",
|
|
184
184
|
"react-native-svg": "^12.1.0",
|
|
185
|
-
"react-native-toast-message": "^1.
|
|
185
|
+
"react-native-toast-message": "^2.1.1",
|
|
186
186
|
"react-native-udp": "^4.1.3",
|
|
187
187
|
"react-native-unimodules": "^0.11.0",
|
|
188
188
|
"react-native-version-check": "^3.4.2",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
|
-
import {
|
|
2
|
+
import { Device } from '../../../../configs';
|
|
3
3
|
|
|
4
4
|
const widthMonitor = Device.screenWidth;
|
|
5
5
|
const centerRowItem = {
|
|
@@ -21,8 +21,4 @@ export default StyleSheet.create({
|
|
|
21
21
|
width: widthMonitor - 130,
|
|
22
22
|
...betweenRowItem,
|
|
23
23
|
},
|
|
24
|
-
iconStop: {
|
|
25
|
-
fontStyle: 'Bold',
|
|
26
|
-
color: Colors.Gray9,
|
|
27
|
-
},
|
|
28
24
|
});
|
|
@@ -60,7 +60,7 @@ describe('Test TimerActionTemplate success with config value', () => {
|
|
|
60
60
|
const instance = wrapper.root;
|
|
61
61
|
|
|
62
62
|
const texts = instance.findAllByType(Text);
|
|
63
|
-
expect(texts).toHaveLength(
|
|
63
|
+
expect(texts).toHaveLength(8);
|
|
64
64
|
expect(texts[0].props.children).toEqual('Timer');
|
|
65
65
|
expect(texts[1].props.children).toEqual('Setting at 18:30');
|
|
66
66
|
|
|
@@ -62,7 +62,7 @@ describe('Test TimerActionTemplate without config value', () => {
|
|
|
62
62
|
const instance = wrapper.root;
|
|
63
63
|
|
|
64
64
|
const texts = instance.findAllByType(Text);
|
|
65
|
-
expect(texts).toHaveLength(
|
|
65
|
+
expect(texts).toHaveLength(7);
|
|
66
66
|
expect(texts[0].props.children).toEqual('Timer');
|
|
67
67
|
|
|
68
68
|
const switchButton = instance.findByType(Switch);
|
|
@@ -332,8 +332,8 @@ describe('Test ActionGroup', () => {
|
|
|
332
332
|
wrapper = renderer.create(wrapComponent(actionGroup, mockDoAction, {}));
|
|
333
333
|
});
|
|
334
334
|
const instance = wrapper.root;
|
|
335
|
-
const text = instance.
|
|
336
|
-
expect(text.props.children).toEqual('28 *C');
|
|
335
|
+
const text = instance.findAllByType(Text);
|
|
336
|
+
expect(text[0].props.children).toEqual('28 *C');
|
|
337
337
|
|
|
338
338
|
const touchs = instance.findAllByType(TouchableOpacity);
|
|
339
339
|
expect(touchs).toHaveLength(2);
|
|
@@ -418,7 +418,7 @@ describe('Test ActionGroup', () => {
|
|
|
418
418
|
const instance = wrapper.root;
|
|
419
419
|
|
|
420
420
|
const texts = instance.findAllByType(Text);
|
|
421
|
-
expect(texts).toHaveLength(
|
|
421
|
+
expect(texts).toHaveLength(7);
|
|
422
422
|
expect(texts[0].props.children).toEqual('Timer');
|
|
423
423
|
|
|
424
424
|
const switchButton = instance.findByType(Switch);
|
|
@@ -77,11 +77,11 @@ describe('Test ActionTemplate', () => {
|
|
|
77
77
|
const instance = tree.root;
|
|
78
78
|
|
|
79
79
|
const selectActionCard = instance.findByType(SelectActionCard);
|
|
80
|
-
const modal = instance.
|
|
80
|
+
const modal = instance.findAllByType(Modal);
|
|
81
81
|
act(() => {
|
|
82
82
|
selectActionCard.props.onPress();
|
|
83
83
|
});
|
|
84
|
-
expect(modal.props.isVisible).toBe(true);
|
|
84
|
+
expect(modal[0].props.isVisible).toBe(true);
|
|
85
85
|
});
|
|
86
86
|
test('test onPressSelectAction', () => {
|
|
87
87
|
act(() => {
|
|
@@ -49,7 +49,7 @@ describe('Test MyPinnedSharedUnit', () => {
|
|
|
49
49
|
});
|
|
50
50
|
const instance = tree.root;
|
|
51
51
|
const texts = instance.findAllByType(Text);
|
|
52
|
-
expect(texts).toHaveLength(
|
|
52
|
+
expect(texts).toHaveLength(4);
|
|
53
53
|
expect(texts[0].props.children).toEqual(
|
|
54
54
|
getTranslate('en', 'text_shared_units')
|
|
55
55
|
);
|
|
@@ -8,8 +8,10 @@ import {
|
|
|
8
8
|
import Routes from '../../utils/Route';
|
|
9
9
|
import { IconFill, IconOutline } from '@ant-design/icons-react-native';
|
|
10
10
|
import { useNavigation } from '@react-navigation/native';
|
|
11
|
+
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
11
12
|
import ItemQuickAction from '../../commons/Action/ItemQuickAction';
|
|
12
13
|
import Text from '../../commons/Text';
|
|
14
|
+
import { isDeviceConnected } from '../../iot/RemoteControl/Bluetooth';
|
|
13
15
|
|
|
14
16
|
import { Colors, Constants } from '../../configs';
|
|
15
17
|
import { TESTID } from '../../configs/Constants';
|
|
@@ -29,8 +31,10 @@ const ItemDevice = memo(
|
|
|
29
31
|
unit,
|
|
30
32
|
station,
|
|
31
33
|
isGGHomeConnected,
|
|
34
|
+
status,
|
|
32
35
|
wrapStyle,
|
|
33
36
|
}) => {
|
|
37
|
+
const t = useTranslations();
|
|
34
38
|
const navigation = useNavigation();
|
|
35
39
|
|
|
36
40
|
const goToSensorDisplay = useCallback(() => {
|
|
@@ -52,10 +56,20 @@ const ItemDevice = memo(
|
|
|
52
56
|
);
|
|
53
57
|
};
|
|
54
58
|
|
|
59
|
+
const isNetworkConnected =
|
|
60
|
+
status === undefined ? sensor.is_connected : status.is_connected;
|
|
61
|
+
const isBLEConnected = isDeviceConnected(
|
|
62
|
+
sensor?.remote_control_options?.bluetooth?.address
|
|
63
|
+
);
|
|
64
|
+
const isConnected =
|
|
65
|
+
isNetworkConnected || isGGHomeConnected || isBLEConnected;
|
|
66
|
+
const borderColor = isConnected ? Colors.Gray4 : Colors.Red6;
|
|
67
|
+
const textConnected = isConnected ? t('connected') : t('disconnected');
|
|
68
|
+
|
|
55
69
|
return (
|
|
56
70
|
<TouchableWithoutFeedback onPress={goToSensorDisplay}>
|
|
57
71
|
<View
|
|
58
|
-
style={[styles.container, wrapStyle]}
|
|
72
|
+
style={[styles.container, wrapStyle, { borderColor }]}
|
|
59
73
|
testID={TESTID.SUB_UNIT_DEVICES}
|
|
60
74
|
>
|
|
61
75
|
<View style={styles.boxIcon}>
|
|
@@ -82,7 +96,7 @@ const ItemDevice = memo(
|
|
|
82
96
|
color={Colors.Gray8}
|
|
83
97
|
style={styles.lineHeight20}
|
|
84
98
|
>
|
|
85
|
-
{description}
|
|
99
|
+
{description || textConnected}
|
|
86
100
|
</Text>
|
|
87
101
|
<IconOutline name="right" size={12} />
|
|
88
102
|
</View>
|
|
@@ -112,6 +126,7 @@ const styles = StyleSheet.create({
|
|
|
112
126
|
backgroundColor: Colors.White,
|
|
113
127
|
justifyContent: 'space-between',
|
|
114
128
|
marginBottom: 8,
|
|
129
|
+
borderWidth: 1,
|
|
115
130
|
},
|
|
116
131
|
boxIcon: {
|
|
117
132
|
flexDirection: 'row',
|
|
@@ -37,7 +37,7 @@ describe('Test Compass', () => {
|
|
|
37
37
|
});
|
|
38
38
|
const instance = tree.root;
|
|
39
39
|
const textInputs = instance.findAllByType(Text);
|
|
40
|
-
expect(textInputs.length).toEqual(
|
|
40
|
+
expect(textInputs.length).toEqual(3);
|
|
41
41
|
expect(textInputs[0].props.children).toEqual(list_result[index]);
|
|
42
42
|
});
|
|
43
43
|
});
|
|
@@ -48,6 +48,6 @@ describe('Test Compass', () => {
|
|
|
48
48
|
});
|
|
49
49
|
const instance = tree.root;
|
|
50
50
|
const textInputs = instance.findAllByType(Text);
|
|
51
|
-
expect(textInputs.length).toEqual(
|
|
51
|
+
expect(textInputs.length).toEqual(3);
|
|
52
52
|
});
|
|
53
53
|
});
|
|
@@ -28,7 +28,7 @@ describe('Test ConnectedViewHeader', () => {
|
|
|
28
28
|
});
|
|
29
29
|
const isntance = tree.root;
|
|
30
30
|
const texts = isntance.findAllByType(Text);
|
|
31
|
-
expect(texts).toHaveLength(
|
|
31
|
+
expect(texts).toHaveLength(3);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
test('render ConnectedViewHeader no last updated', async () => {
|
|
@@ -37,6 +37,6 @@ describe('Test ConnectedViewHeader', () => {
|
|
|
37
37
|
});
|
|
38
38
|
const isntance = tree.root;
|
|
39
39
|
const texts = isntance.findAllByType(Text);
|
|
40
|
-
expect(texts).toHaveLength(
|
|
40
|
+
expect(texts).toHaveLength(3);
|
|
41
41
|
});
|
|
42
42
|
});
|
|
@@ -21,7 +21,7 @@ describe('Test DisconnectedView', () => {
|
|
|
21
21
|
});
|
|
22
22
|
const instance = tree.root;
|
|
23
23
|
const Views = instance.findAllByType(View);
|
|
24
|
-
expect(Views).toHaveLength(
|
|
24
|
+
expect(Views).toHaveLength(15);
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
test('render DisconnectedView icon sensor', () => {
|
|
@@ -31,7 +31,7 @@ describe('Test DisconnectedView', () => {
|
|
|
31
31
|
});
|
|
32
32
|
const instance = tree.root;
|
|
33
33
|
const Views = instance.findAllByType(View);
|
|
34
|
-
expect(Views).toHaveLength(
|
|
34
|
+
expect(Views).toHaveLength(15);
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
test('render DisconnectedView icon barrier', () => {
|
|
@@ -41,7 +41,7 @@ describe('Test DisconnectedView', () => {
|
|
|
41
41
|
});
|
|
42
42
|
const instance = tree.root;
|
|
43
43
|
const Views = instance.findAllByType(View);
|
|
44
|
-
expect(Views).toHaveLength(
|
|
44
|
+
expect(Views).toHaveLength(15);
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
test('render DisconnectedView icon wind', () => {
|
|
@@ -51,7 +51,7 @@ describe('Test DisconnectedView', () => {
|
|
|
51
51
|
});
|
|
52
52
|
const instance = tree.root;
|
|
53
53
|
const Views = instance.findAllByType(View);
|
|
54
|
-
expect(Views).toHaveLength(
|
|
54
|
+
expect(Views).toHaveLength(15);
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
test('render DisconnectedView icon test', () => {
|
|
@@ -61,6 +61,6 @@ describe('Test DisconnectedView', () => {
|
|
|
61
61
|
});
|
|
62
62
|
const instance = tree.root;
|
|
63
63
|
const Views = instance.findAllByType(View);
|
|
64
|
-
expect(Views).toHaveLength(
|
|
64
|
+
expect(Views).toHaveLength(15);
|
|
65
65
|
});
|
|
66
66
|
});
|
|
@@ -32,7 +32,7 @@ describe('Test MediaPlayerDetail', () => {
|
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
const texts = instance.findAllByType(Text);
|
|
35
|
-
expect(texts.length).toEqual(
|
|
35
|
+
expect(texts.length).toEqual(4);
|
|
36
36
|
expect(texts[1].props.children).toEqual('cameraName');
|
|
37
37
|
|
|
38
38
|
const pauseIcon = instance.findAllByType(PauseIcon);
|
|
@@ -25,7 +25,7 @@ describe('Test ModalBottom', () => {
|
|
|
25
25
|
});
|
|
26
26
|
const instance = tree.root;
|
|
27
27
|
const Views = instance.findAllByType(View);
|
|
28
|
-
expect(Views).toHaveLength(
|
|
28
|
+
expect(Views).toHaveLength(10);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it('Test render without isVisible', async () => {
|
|
@@ -34,6 +34,6 @@ describe('Test ModalBottom', () => {
|
|
|
34
34
|
});
|
|
35
35
|
const instance = tree.root;
|
|
36
36
|
const Views = instance.findAllByType(View);
|
|
37
|
-
expect(Views).toHaveLength(
|
|
37
|
+
expect(Views).toHaveLength(10);
|
|
38
38
|
});
|
|
39
39
|
});
|
|
@@ -27,7 +27,7 @@ describe('MemberList', () => {
|
|
|
27
27
|
});
|
|
28
28
|
const instance = tree.root;
|
|
29
29
|
const textInputs = instance.findAllByType(Text);
|
|
30
|
-
expect(textInputs.length).toBe(
|
|
30
|
+
expect(textInputs.length).toBe(4);
|
|
31
31
|
});
|
|
32
32
|
test('MemberList snapshot id dataMember !== ownerId', () => {
|
|
33
33
|
const dataMember = [{ id: 1, name: 'CEO' }];
|
|
@@ -36,7 +36,7 @@ describe('MemberList', () => {
|
|
|
36
36
|
});
|
|
37
37
|
const instance = tree.root;
|
|
38
38
|
const textInputs = instance.findAllByType(Text);
|
|
39
|
-
expect(textInputs.length).toBe(
|
|
39
|
+
expect(textInputs.length).toBe(3);
|
|
40
40
|
});
|
|
41
41
|
test('MemberList snapshot id dataMember === currentUserId', () => {
|
|
42
42
|
const dataMember = [{ id: 1, name: 'CEO' }];
|
|
@@ -45,7 +45,7 @@ describe('MemberList', () => {
|
|
|
45
45
|
});
|
|
46
46
|
const instance = tree.root;
|
|
47
47
|
const textInputs = instance.findAllByType(Text);
|
|
48
|
-
expect(textInputs.length).toBe(
|
|
48
|
+
expect(textInputs.length).toBe(4);
|
|
49
49
|
});
|
|
50
50
|
test('MemberList dataMember null', () => {
|
|
51
51
|
const dataMember = [];
|
|
@@ -26,7 +26,7 @@ describe('RowMember', () => {
|
|
|
26
26
|
});
|
|
27
27
|
const instance = tree.root;
|
|
28
28
|
const textInputs = instance.findAllByType(Text);
|
|
29
|
-
expect(textInputs.length).toBe(
|
|
29
|
+
expect(textInputs.length).toBe(4);
|
|
30
30
|
expect(textInputs[0].props.children).toEqual('CEO');
|
|
31
31
|
});
|
|
32
32
|
test('RowMember owner dont have name show start of email ', () => {
|
|
@@ -36,7 +36,7 @@ describe('RowMember', () => {
|
|
|
36
36
|
});
|
|
37
37
|
const instance = tree.root;
|
|
38
38
|
const textInputs = instance.findAllByType(Text);
|
|
39
|
-
expect(textInputs.length).toBe(
|
|
39
|
+
expect(textInputs.length).toBe(4);
|
|
40
40
|
expect(textInputs[0].props.children).toEqual('abc');
|
|
41
41
|
});
|
|
42
42
|
});
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
4
|
+
import { useIsFocused } from '@react-navigation/native';
|
|
4
5
|
|
|
5
6
|
import { Section } from '../../Section';
|
|
6
7
|
import ItemDevice from '../../Device/ItemDevice';
|
|
7
8
|
import ItemOneTap from '../OneTap/ItemOneTap';
|
|
8
9
|
import ItemAddNew from '../../Device/ItemAddNew';
|
|
9
10
|
import styles from './styles';
|
|
11
|
+
import { API } from '../../../configs';
|
|
12
|
+
import { axiosGet } from '../../../utils/Apis/axios';
|
|
10
13
|
|
|
11
14
|
const SubUnitFavorites = ({
|
|
12
15
|
unit,
|
|
@@ -16,6 +19,33 @@ const SubUnitFavorites = ({
|
|
|
16
19
|
wrapItemStyle,
|
|
17
20
|
}) => {
|
|
18
21
|
const t = useTranslations();
|
|
22
|
+
const isFocused = useIsFocused();
|
|
23
|
+
const intervalSensorStatus = useRef();
|
|
24
|
+
const [sensorsStatus, setSensorsStatus] = useState([]);
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (isFocused) {
|
|
28
|
+
const getSensorsStatus = async () => {
|
|
29
|
+
const params = new URLSearchParams();
|
|
30
|
+
if (favorites?.devices?.length > 0) {
|
|
31
|
+
favorites.devices.forEach((sensor) => {
|
|
32
|
+
params.append('sensors', sensor.id);
|
|
33
|
+
});
|
|
34
|
+
const { success, data } = await axiosGet(API.SENSOR.STATUS(), {
|
|
35
|
+
params: params,
|
|
36
|
+
});
|
|
37
|
+
if (success) {
|
|
38
|
+
setSensorsStatus(data);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const updateInterval = setInterval(getSensorsStatus, 5000);
|
|
43
|
+
intervalSensorStatus.current = updateInterval;
|
|
44
|
+
return () => clearInterval(updateInterval);
|
|
45
|
+
} else {
|
|
46
|
+
clearInterval(intervalSensorStatus.current);
|
|
47
|
+
}
|
|
48
|
+
}, [isFocused, favorites?.devices]);
|
|
19
49
|
|
|
20
50
|
const handleOnAddNew = () => {
|
|
21
51
|
alert(t('feature_under_development'));
|
|
@@ -39,6 +69,7 @@ const SubUnitFavorites = ({
|
|
|
39
69
|
unit={unit}
|
|
40
70
|
station={sensor.station}
|
|
41
71
|
isGGHomeConnected={isGGHomeConnected}
|
|
72
|
+
status={sensorsStatus.find((s) => s.id === sensor.id)}
|
|
42
73
|
wrapStyle={wrapItemStyle}
|
|
43
74
|
/>
|
|
44
75
|
))}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
|
-
import { useNavigation } from '@react-navigation/native';
|
|
3
|
+
import { useNavigation, useIsFocused } from '@react-navigation/native';
|
|
4
4
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
5
5
|
|
|
6
|
-
import { Images, Device } from '../../configs';
|
|
6
|
+
import { Images, Device, API } from '../../configs';
|
|
7
7
|
import { SubUnitName, TESTID } from '../../configs/Constants';
|
|
8
8
|
import { Section } from '../Section';
|
|
9
9
|
import Text from '../Text';
|
|
@@ -13,6 +13,7 @@ import { standardizeCameraScreenSize } from '../../utils/Utils';
|
|
|
13
13
|
import Routes from '../../utils/Route';
|
|
14
14
|
import FastImage from 'react-native-fast-image';
|
|
15
15
|
import MediaPlayerDetail from '../MediaPlayerDetail';
|
|
16
|
+
import { axiosGet } from '../../utils/Apis/axios';
|
|
16
17
|
|
|
17
18
|
const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
|
|
18
19
|
Device.screenWidth - 32
|
|
@@ -20,7 +21,35 @@ const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
|
|
|
20
21
|
|
|
21
22
|
const ShortDetailSubUnit = ({ unit, station, isGGHomeConnected }) => {
|
|
22
23
|
const t = useTranslations();
|
|
24
|
+
const isFocused = useIsFocused();
|
|
23
25
|
const { navigate } = useNavigation();
|
|
26
|
+
const intervalSensorStatus = useRef();
|
|
27
|
+
|
|
28
|
+
const [sensorsStatus, setSensorsStatus] = useState([]);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (isFocused) {
|
|
32
|
+
const getSensorsStatus = async () => {
|
|
33
|
+
const params = new URLSearchParams();
|
|
34
|
+
if (station?.sensors?.length > 0) {
|
|
35
|
+
station.sensors.forEach((sensor) => {
|
|
36
|
+
params.append('sensors', sensor.id);
|
|
37
|
+
});
|
|
38
|
+
const { success, data } = await axiosGet(API.SENSOR.STATUS(), {
|
|
39
|
+
params: params,
|
|
40
|
+
});
|
|
41
|
+
if (success) {
|
|
42
|
+
setSensorsStatus(data);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const updateInterval = setInterval(getSensorsStatus, 5000);
|
|
47
|
+
intervalSensorStatus.current = updateInterval;
|
|
48
|
+
return () => clearInterval(updateInterval);
|
|
49
|
+
} else {
|
|
50
|
+
clearInterval(intervalSensorStatus.current);
|
|
51
|
+
}
|
|
52
|
+
}, [isFocused, station?.sensors]);
|
|
24
53
|
|
|
25
54
|
const renderCamera = () => {
|
|
26
55
|
if (station?.camera) {
|
|
@@ -115,6 +144,7 @@ const ShortDetailSubUnit = ({ unit, station, isGGHomeConnected }) => {
|
|
|
115
144
|
unit={unit}
|
|
116
145
|
station={station}
|
|
117
146
|
isGGHomeConnected={isGGHomeConnected}
|
|
147
|
+
status={sensorsStatus.find((s) => s.id === sensor.id)}
|
|
118
148
|
/>
|
|
119
149
|
))}
|
|
120
150
|
<ItemAddNew title={itemAddNewTitle} onAddNew={handleOnAddNew} />
|
package/src/configs/API.js
CHANGED
|
@@ -87,6 +87,7 @@ const API = {
|
|
|
87
87
|
CHANGE_SUB_UNIT: (unit_id, station_id, id) =>
|
|
88
88
|
SCConfig.apiRoot +
|
|
89
89
|
`/property_manager/${unit_id}/sub_units/${station_id}/devices/${id}/change_sub_unit/`,
|
|
90
|
+
STATUS: () => SCConfig.apiRoot + '/property_manager/sensors/status/',
|
|
90
91
|
},
|
|
91
92
|
SHARED_SENSOR: {
|
|
92
93
|
ACCESS: (id) =>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import React, { useContext, useReducer } from 'react';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
import Toast from 'react-native-toast-message';
|
|
2
4
|
|
|
3
5
|
import {
|
|
4
6
|
ActionDataMap,
|
|
@@ -10,6 +12,18 @@ import {
|
|
|
10
12
|
import { initialState, Action, ContextData, reducer } from './reducer';
|
|
11
13
|
import { setConfigGlobalState } from '../iot/states.js';
|
|
12
14
|
import { setAxiosDefaultLanguage } from '../utils/Utils';
|
|
15
|
+
import { Alert } from '../commons';
|
|
16
|
+
import { Colors } from '../configs';
|
|
17
|
+
import Text from '../commons/Text';
|
|
18
|
+
|
|
19
|
+
const toastConfig = {
|
|
20
|
+
// only for error for now
|
|
21
|
+
error: (internalState) => (
|
|
22
|
+
<View style={styles.toastContainer}>
|
|
23
|
+
<Text style={styles.textWhite}>{internalState.text1}</Text>
|
|
24
|
+
</View>
|
|
25
|
+
),
|
|
26
|
+
};
|
|
13
27
|
|
|
14
28
|
type SCContextType = {
|
|
15
29
|
stateData: ContextData;
|
|
@@ -68,15 +82,34 @@ export const SCProvider = ({ children, initState = initialState }) => {
|
|
|
68
82
|
return (
|
|
69
83
|
<SCContext.Provider value={providerValue}>
|
|
70
84
|
{children}
|
|
71
|
-
|
|
72
|
-
<Toast config={toastConfig} ref={(ref) => Toast.setRef(ref)} /> */}
|
|
85
|
+
<Alert ref={(ref) => Alert.setRef(ref)} />
|
|
73
86
|
</SCContext.Provider>
|
|
74
87
|
);
|
|
75
88
|
};
|
|
76
89
|
|
|
90
|
+
export const SCWrapper = (props) => {
|
|
91
|
+
return (
|
|
92
|
+
<>
|
|
93
|
+
<SCProvider {...props} />
|
|
94
|
+
<Toast config={toastConfig} ref={(ref) => Toast.setRef(ref)} />
|
|
95
|
+
</>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
77
99
|
export const useSCContextSelector = (
|
|
78
100
|
selector: (contextData: ContextData) => unknown
|
|
79
101
|
) => {
|
|
80
102
|
const { stateData } = useContext(SCContext);
|
|
81
103
|
return selector(stateData);
|
|
82
104
|
};
|
|
105
|
+
|
|
106
|
+
const styles = StyleSheet.create({
|
|
107
|
+
toastContainer: {
|
|
108
|
+
borderRadius: 5,
|
|
109
|
+
padding: 10,
|
|
110
|
+
backgroundColor: Colors.Black,
|
|
111
|
+
},
|
|
112
|
+
textWhite: {
|
|
113
|
+
color: Colors.White,
|
|
114
|
+
},
|
|
115
|
+
});
|
package/src/context/index.ts
CHANGED
|
@@ -101,50 +101,49 @@ describe('Test Activity log', () => {
|
|
|
101
101
|
});
|
|
102
102
|
const instance = tree.root;
|
|
103
103
|
const dateTimeRangeChange = instance.findByType(DateTimeRangeChange);
|
|
104
|
-
const filterPopup = instance.
|
|
104
|
+
const filterPopup = instance.findAllByType(Modal);
|
|
105
105
|
const datePicker = instance.findByType(DateTimePickerModal);
|
|
106
106
|
const filterButton = instance.find(
|
|
107
107
|
(el) =>
|
|
108
108
|
el.props.testID === TESTID.FILTER_BUTTON && el.type === TouchableOpacity
|
|
109
109
|
);
|
|
110
110
|
// open popup
|
|
111
|
-
expect(filterPopup.props.isVisible).toBeFalsy();
|
|
111
|
+
expect(filterPopup[0].props.isVisible).toBeFalsy();
|
|
112
112
|
await act(async () => {
|
|
113
113
|
await filterButton.props.onPress();
|
|
114
114
|
});
|
|
115
|
-
expect(filterPopup.props.isVisible).toBeTruthy();
|
|
115
|
+
expect(filterPopup[0].props.isVisible).toBeTruthy();
|
|
116
116
|
// pick start date
|
|
117
117
|
await act(async () => {
|
|
118
118
|
await dateTimeRangeChange.props.onStart();
|
|
119
|
-
await filterPopup.props.onModalHide();
|
|
119
|
+
await filterPopup[0].props.onModalHide();
|
|
120
120
|
});
|
|
121
|
-
expect(filterPopup.props.isVisible).toBeFalsy();
|
|
122
|
-
expect(datePicker.props.isVisible).toBeTruthy();
|
|
121
|
+
expect(filterPopup[0].props.isVisible).toBeFalsy();
|
|
123
122
|
// cancel
|
|
124
123
|
await act(async () => {
|
|
125
124
|
await datePicker.props.onCancel();
|
|
126
125
|
await datePicker.props.onHide();
|
|
127
126
|
});
|
|
128
|
-
expect(filterPopup.props.isVisible).toBeTruthy();
|
|
127
|
+
expect(filterPopup[0].props.isVisible).toBeTruthy();
|
|
129
128
|
expect(datePicker.props.isVisible).toBeFalsy();
|
|
130
129
|
// open popup
|
|
131
130
|
await act(async () => {
|
|
132
131
|
await filterButton.props.onPress();
|
|
133
132
|
});
|
|
134
|
-
expect(filterPopup.props.isVisible).toBeTruthy();
|
|
133
|
+
expect(filterPopup[0].props.isVisible).toBeTruthy();
|
|
135
134
|
// pick end date
|
|
136
135
|
await act(async () => {
|
|
137
136
|
await dateTimeRangeChange.props.onEnd();
|
|
138
|
-
await filterPopup.props.onModalHide();
|
|
137
|
+
await filterPopup[0].props.onModalHide();
|
|
139
138
|
});
|
|
140
|
-
expect(filterPopup.props.isVisible).toBeFalsy();
|
|
139
|
+
expect(filterPopup[0].props.isVisible).toBeFalsy();
|
|
141
140
|
expect(datePicker.props.isVisible).toBeTruthy();
|
|
142
141
|
// confirm
|
|
143
142
|
await act(async () => {
|
|
144
143
|
await datePicker.props.onConfirm();
|
|
145
144
|
await datePicker.props.onHide();
|
|
146
145
|
});
|
|
147
|
-
expect(filterPopup.props.isVisible).toBeTruthy();
|
|
146
|
+
expect(filterPopup[0].props.isVisible).toBeTruthy();
|
|
148
147
|
expect(datePicker.props.isVisible).toBeFalsy();
|
|
149
148
|
});
|
|
150
149
|
});
|
|
@@ -31,11 +31,11 @@ describe('Test SelectDevice', () => {
|
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
const instance = tree.root;
|
|
34
|
-
const touchableWithoutFeedback = instance.
|
|
34
|
+
const touchableWithoutFeedback = instance.findAllByType(
|
|
35
35
|
TouchableWithoutFeedback
|
|
36
36
|
);
|
|
37
37
|
act(() => {
|
|
38
|
-
touchableWithoutFeedback.props.onPress();
|
|
38
|
+
touchableWithoutFeedback[0].props.onPress();
|
|
39
39
|
});
|
|
40
40
|
expect(mockFuntion).toHaveBeenCalledWith(sensor);
|
|
41
41
|
});
|
|
@@ -53,7 +53,7 @@ describe('Test ConnectingDevices', () => {
|
|
|
53
53
|
});
|
|
54
54
|
const instance = tree.root;
|
|
55
55
|
const texts = instance.findAllByType(Text);
|
|
56
|
-
expect(texts).toHaveLength(
|
|
56
|
+
expect(texts).toHaveLength(4);
|
|
57
57
|
expect(texts[0].props.children).toEqual(
|
|
58
58
|
getTranslate('en', 'connecting_your_device')
|
|
59
59
|
);
|
|
@@ -37,7 +37,7 @@ describe('Test FirstWarning', () => {
|
|
|
37
37
|
});
|
|
38
38
|
const instance = tree.root;
|
|
39
39
|
const texts = instance.findAllByType(Text);
|
|
40
|
-
expect(texts).toHaveLength(
|
|
40
|
+
expect(texts).toHaveLength(10);
|
|
41
41
|
expect(texts[1].props.children).toEqual(
|
|
42
42
|
getTranslate('en', 'warning_beta_test_feature')
|
|
43
43
|
);
|
|
@@ -28,7 +28,7 @@ describe('Test GatewayWifiList', () => {
|
|
|
28
28
|
});
|
|
29
29
|
const instance = tree.root;
|
|
30
30
|
const texts = instance.findAllByType(Text);
|
|
31
|
-
expect(texts).toHaveLength(
|
|
31
|
+
expect(texts).toHaveLength(10);
|
|
32
32
|
expect(texts[1].props.children).toEqual(getTranslate('en', 'set_network'));
|
|
33
33
|
expect(texts[3].props.children).toEqual('eoh@io');
|
|
34
34
|
});
|
|
@@ -53,7 +53,7 @@ describe('Test ConnectingGateway', () => {
|
|
|
53
53
|
});
|
|
54
54
|
const instance = tree.root;
|
|
55
55
|
const texts = instance.findAllByType(Text);
|
|
56
|
-
expect(texts).toHaveLength(
|
|
56
|
+
expect(texts).toHaveLength(8);
|
|
57
57
|
expect(texts[0].props.children).toEqual(
|
|
58
58
|
getTranslate('en', 'connecting_your_gateway')
|
|
59
59
|
);
|
|
@@ -74,6 +74,7 @@ describe('Test UnitDetail', () => {
|
|
|
74
74
|
|
|
75
75
|
const detailUnitApiUrl = API.UNIT.UNIT_DETAIL(1);
|
|
76
76
|
const summaryUnitApiUrl = API.UNIT.UNIT_SUMMARY(1);
|
|
77
|
+
const sensorStatusApiUrl = API.SENSOR.STATUS();
|
|
77
78
|
|
|
78
79
|
let tree;
|
|
79
80
|
|
|
@@ -318,6 +319,11 @@ describe('Test UnitDetail', () => {
|
|
|
318
319
|
status: 200,
|
|
319
320
|
data: [],
|
|
320
321
|
};
|
|
322
|
+
} else if (url === sensorStatusApiUrl) {
|
|
323
|
+
return {
|
|
324
|
+
status: 200,
|
|
325
|
+
data: [],
|
|
326
|
+
};
|
|
321
327
|
}
|
|
322
328
|
|
|
323
329
|
return {
|
|
@@ -396,7 +402,7 @@ describe('Test UnitDetail', () => {
|
|
|
396
402
|
);
|
|
397
403
|
});
|
|
398
404
|
await act(async () => {
|
|
399
|
-
await jest.
|
|
405
|
+
await jest.runOnlyPendingTimers();
|
|
400
406
|
});
|
|
401
407
|
// TODO Called but can not expect
|
|
402
408
|
// expect(axios.get).toHaveBeenCalledWith(API.IOT.LG.DEVICE_STATUS(2));
|
|
@@ -22,11 +22,11 @@ describe('Test Header', () => {
|
|
|
22
22
|
tree = renderer.create(wrapComponent());
|
|
23
23
|
});
|
|
24
24
|
const instance = tree.root;
|
|
25
|
-
const modal = instance.
|
|
25
|
+
const modal = instance.findAllByType(Modal);
|
|
26
26
|
act(() => {
|
|
27
|
-
modal.props.onBackButtonPress();
|
|
27
|
+
modal[0].props.onBackButtonPress();
|
|
28
28
|
});
|
|
29
|
-
expect(modal.props.isVisible).toBe(false);
|
|
29
|
+
expect(modal[0].props.isVisible).toBe(false);
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test('test onItemClick', () => {
|
|
@@ -34,12 +34,12 @@ describe('Test Header', () => {
|
|
|
34
34
|
tree = renderer.create(wrapComponent());
|
|
35
35
|
});
|
|
36
36
|
const instance = tree.root;
|
|
37
|
-
const modal = instance.
|
|
37
|
+
const modal = instance.findAllByType(Modal);
|
|
38
38
|
const imageButton = instance.findByType(ImageButton);
|
|
39
39
|
act(() => {
|
|
40
40
|
imageButton.props.onPress(Routes.Sharing);
|
|
41
41
|
});
|
|
42
|
-
expect(modal.props.isVisible).toBe(false);
|
|
42
|
+
expect(modal[0].props.isVisible).toBe(false);
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
test('test Popover Close Menu', () => {
|
|
@@ -22,7 +22,7 @@ describe('Test MyUnitDevice', () => {
|
|
|
22
22
|
});
|
|
23
23
|
const instance = tree.root;
|
|
24
24
|
const Views = instance.findAllByType(View);
|
|
25
|
-
expect(Views).toHaveLength(
|
|
25
|
+
expect(Views).toHaveLength(10);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
it('Test render without status', async () => {
|
|
@@ -31,6 +31,6 @@ describe('Test MyUnitDevice', () => {
|
|
|
31
31
|
});
|
|
32
32
|
const instance = tree.root;
|
|
33
33
|
const Views = instance.findAllByType(View);
|
|
34
|
-
expect(Views).toHaveLength(
|
|
34
|
+
expect(Views).toHaveLength(10);
|
|
35
35
|
});
|
|
36
36
|
});
|
|
@@ -91,8 +91,10 @@ const PowerConsumption = memo(({ summaryDetail }) => {
|
|
|
91
91
|
let params = new URLSearchParams();
|
|
92
92
|
params.append('config', listConfigs.total_power);
|
|
93
93
|
params.append('group_by', groupBy);
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
if (groupBy === 'date') {
|
|
95
|
+
params.append('date_from', moment(startDate).format('YYYY-MM-DD'));
|
|
96
|
+
params.append('date_to', moment(endDate).format('YYYY-MM-DD'));
|
|
97
|
+
}
|
|
96
98
|
const { success, data } = await axiosGet(
|
|
97
99
|
API.POWER_CONSUME.DISPLAY_HISTORY(),
|
|
98
100
|
{
|