@eohjsc/react-native-smart-city 0.2.85 → 0.2.86
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/Device/button-lock.svg +3 -0
- package/assets/images/Device/button-unlock.svg +3 -0
- package/package.json +1 -1
- package/src/commons/ActionGroup/OnOffSmartLock.js +48 -0
- package/src/commons/ActionGroup/OnOffSmartLockStyle.js +51 -0
- package/src/commons/ActionGroup/index.js +3 -0
- package/src/commons/ConnectingProcess/index.js +5 -2
- package/src/commons/Device/ItemDevice.js +8 -3
- package/src/commons/MediaPlayer/__test__/index.test.js +45 -0
- package/src/commons/SubUnit/ShortDetail.js +10 -22
- package/src/commons/SubUnit/__test__/ShortDetail.test.js +57 -48
- package/src/configs/API.js +2 -2
- package/src/configs/Constants.js +13 -0
- package/src/screens/ActivityLog/hooks/index.js +18 -4
- package/src/screens/ActivityLog/index.js +3 -0
- package/src/screens/AddCommon/SelectSubUnit.js +1 -0
- package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +1 -1
- package/src/screens/AddNewAction/SelectSensorDevices.js +4 -2
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +10 -2
- package/src/screens/AddNewGateway/PlugAndPlay/FirstWarning.js +4 -2
- package/src/screens/AddNewOneTap/index.js +32 -17
- package/src/screens/Automate/index.js +2 -2
- package/src/screens/Device/EditDevice/index.js +5 -3
- package/src/screens/Device/components/SensorDisplayItem.js +3 -0
- package/src/screens/Device/detail.js +1 -0
- package/src/screens/Notification/__test__/NotificationItem.test.js +15 -3
- package/src/screens/Notification/components/NotificationItem.js +52 -8
- package/src/screens/ScanChipQR/__test__/ScanChipQR.test.js +1 -0
- package/src/screens/ScanChipQR/hooks/index.js +90 -44
- package/src/screens/ScriptDetail/index.js +1 -6
- package/src/screens/SelectUnit/index.js +1 -0
- package/src/screens/SharedUnit/index.js +1 -1
- package/src/screens/SmartIr/__test__/SmartIr.test.js +61 -0
- package/src/screens/SmartIr/index.js +23 -0
- package/src/screens/SmartIr/styles.js +14 -0
- package/src/screens/Unit/AddMenu.js +4 -1
- package/src/screens/Unit/Detail.js +1 -1
- package/src/screens/UnitSummary/components/PowerConsumeHistoryChart/__test__/index.test.js +32 -1
- package/src/screens/UnitSummary/components/PowerConsumeHistoryChart/index.js +1 -1
- package/src/utils/I18n/translations/en.json +9 -2
- package/src/utils/I18n/translations/vi.json +9 -2
- package/src/utils/Route/index.js +1 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M22.0495 3.90313C22.0112 3.88385 21.9687 3.87473 21.9259 3.87662C21.8831 3.87852 21.8415 3.89138 21.8051 3.91397C21.7687 3.93656 21.7388 3.96811 21.7181 4.00561C21.6974 4.04311 21.6867 4.0853 21.687 4.12813V6.13438C21.687 6.30625 21.7776 6.46562 21.9213 6.55937C22.626 7.00293 23.2781 7.52502 23.8651 8.11563C24.887 9.14063 25.6901 10.3313 26.2495 11.6563C26.828 13.0279 27.1245 14.502 27.1213 15.9906C27.1213 17.4938 26.8276 18.9531 26.2495 20.325C25.6907 21.6481 24.881 22.8504 23.8651 23.8656C22.8525 24.8841 21.6509 25.6951 20.3276 26.2531C18.9588 26.8344 17.4995 27.1281 15.9995 27.1281C14.4995 27.1281 13.0401 26.8344 11.6713 26.2531C10.348 25.6951 9.14638 24.8841 8.13384 23.8656C7.11791 22.8504 6.3082 21.6481 5.74946 20.325C5.17097 18.9533 4.87446 17.4793 4.87759 15.9906C4.87759 14.4875 5.17134 13.0281 5.74946 11.6562C6.30884 10.3313 7.11196 9.14063 8.13384 8.11563C8.72759 7.52188 9.37759 7.00312 10.0776 6.55937C10.2245 6.46875 10.312 6.30625 10.312 6.13438V4.125C10.312 3.9375 10.1151 3.81875 9.94946 3.9C5.57759 6.1 2.56196 10.6031 2.49946 15.8219C2.41196 23.2844 8.51509 29.4844 15.9745 29.5C23.4432 29.5156 29.4995 23.4594 29.4995 15.9875C29.4995 10.7 26.4682 6.12188 22.0495 3.90313ZM14.9995 17.5H16.9995C17.137 17.5 17.2495 17.3875 17.2495 17.25V2.75C17.2495 2.6125 17.137 2.5 16.9995 2.5H14.9995C14.862 2.5 14.7495 2.6125 14.7495 2.75L14.7495 17.25C14.7495 17.3875 14.862 17.5 14.9995 17.5Z" fill="#00979D"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M22.0495 3.90313C22.0112 3.88385 21.9687 3.87473 21.9259 3.87662C21.8831 3.87852 21.8415 3.89138 21.8051 3.91397C21.7687 3.93656 21.7388 3.96811 21.7181 4.00561C21.6974 4.04311 21.6867 4.0853 21.687 4.12813V6.13438C21.687 6.30625 21.7776 6.46562 21.9213 6.55937C22.626 7.00293 23.2781 7.52502 23.8651 8.11563C24.887 9.14063 25.6901 10.3313 26.2495 11.6563C26.828 13.0279 27.1245 14.502 27.1213 15.9906C27.1213 17.4938 26.8276 18.9531 26.2495 20.325C25.6907 21.6481 24.881 22.8504 23.8651 23.8656C22.8525 24.8841 21.6509 25.6951 20.3276 26.2531C18.9588 26.8344 17.4995 27.1281 15.9995 27.1281C14.4995 27.1281 13.0401 26.8344 11.6713 26.2531C10.348 25.6951 9.14638 24.8841 8.13384 23.8656C7.11791 22.8504 6.3082 21.6481 5.74946 20.325C5.17097 18.9533 4.87446 17.4793 4.87759 15.9906C4.87759 14.4875 5.17134 13.0281 5.74946 11.6562C6.30884 10.3313 7.11196 9.14063 8.13384 8.11563C8.72759 7.52188 9.37759 7.00312 10.0776 6.55937C10.2245 6.46875 10.312 6.30625 10.312 6.13438V4.125C10.312 3.9375 10.1151 3.81875 9.94946 3.9C5.57759 6.1 2.56196 10.6031 2.49946 15.8219C2.41196 23.2844 8.51509 29.4844 15.9745 29.5C23.4432 29.5156 29.4995 23.4594 29.4995 15.9875C29.4995 10.7 26.4682 6.12188 22.0495 3.90313ZM14.9995 17.5H16.9995C17.137 17.5 17.2495 17.3875 17.2495 17.25V2.75C17.2495 2.6125 17.137 2.5 16.9995 2.5H14.9995C14.862 2.5 14.7495 2.6125 14.7495 2.75L14.7495 17.25C14.7495 17.3875 14.862 17.5 14.9995 17.5Z" fill="#F5222D"/>
|
|
3
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React, { memo, useCallback, useState } from 'react';
|
|
2
|
+
import { SafeAreaView, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
4
|
+
import { Section } from '../Section';
|
|
5
|
+
import Text from '../Text';
|
|
6
|
+
import styles from './OnOffSmartLockStyle';
|
|
7
|
+
import ButtonLock from '../../../assets/images/Device/button-lock.svg';
|
|
8
|
+
import ButtonUnLock from '../../../assets/images/Device/button-unlock.svg';
|
|
9
|
+
|
|
10
|
+
const OnOffSmartLock = memo(({ actionGroup, doAction, sensor }) => {
|
|
11
|
+
const t = useTranslations();
|
|
12
|
+
const [active, setActive] = useState(true);
|
|
13
|
+
|
|
14
|
+
const handleClickButton = useCallback(() => {
|
|
15
|
+
setActive(!active);
|
|
16
|
+
}, [active]);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<SafeAreaView style={styles.container}>
|
|
20
|
+
<View style={styles.wrap}>
|
|
21
|
+
<Section style={styles.section}>
|
|
22
|
+
<View style={styles.wrapController}>
|
|
23
|
+
<Text style={styles.textController}>{t('controller')}</Text>
|
|
24
|
+
</View>
|
|
25
|
+
<View style={styles.wrapButtonSmartLock}>
|
|
26
|
+
<TouchableOpacity onPress={handleClickButton}>
|
|
27
|
+
{active ? (
|
|
28
|
+
<ButtonLock style={styles.buttonSmartLock} />
|
|
29
|
+
) : (
|
|
30
|
+
<ButtonUnLock style={styles.buttonSmartLock} />
|
|
31
|
+
)}
|
|
32
|
+
</TouchableOpacity>
|
|
33
|
+
<Text style={styles.textSmartLock}>
|
|
34
|
+
{active ? t('lock') : t('unlock')}
|
|
35
|
+
</Text>
|
|
36
|
+
</View>
|
|
37
|
+
<View style={styles.wrapStatus}>
|
|
38
|
+
<Text style={styles.textStatus}>
|
|
39
|
+
{active ? t('door_is_open') : t('door_is_close')}
|
|
40
|
+
</Text>
|
|
41
|
+
</View>
|
|
42
|
+
</Section>
|
|
43
|
+
</View>
|
|
44
|
+
</SafeAreaView>
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export default OnOffSmartLock;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors } from '../../configs';
|
|
3
|
+
|
|
4
|
+
export default StyleSheet.create({
|
|
5
|
+
container: {
|
|
6
|
+
flex: 1,
|
|
7
|
+
},
|
|
8
|
+
wrap: {
|
|
9
|
+
paddingHorizontal: 16,
|
|
10
|
+
},
|
|
11
|
+
section: {
|
|
12
|
+
borderRadius: 10,
|
|
13
|
+
},
|
|
14
|
+
wrapController: {
|
|
15
|
+
flexDirection: 'row',
|
|
16
|
+
justifyContent: 'flex-start',
|
|
17
|
+
},
|
|
18
|
+
textController: {
|
|
19
|
+
color: Colors.Gray8,
|
|
20
|
+
fontSize: 16,
|
|
21
|
+
marginBottom: 16,
|
|
22
|
+
},
|
|
23
|
+
wrapButtonSmartLock: {
|
|
24
|
+
flexDirection: 'column',
|
|
25
|
+
justifyContent: 'center',
|
|
26
|
+
alignItems: 'center',
|
|
27
|
+
backgroundColor: Colors.Gray2,
|
|
28
|
+
borderRadius: 10,
|
|
29
|
+
borderColor: Colors.Gray4,
|
|
30
|
+
borderWidth: 1,
|
|
31
|
+
},
|
|
32
|
+
buttonSmartLock: {
|
|
33
|
+
marginTop: 14,
|
|
34
|
+
},
|
|
35
|
+
textSmartLock: {
|
|
36
|
+
color: Colors.Gray9,
|
|
37
|
+
fontSize: 14,
|
|
38
|
+
marginTop: 8,
|
|
39
|
+
marginBottom: 18,
|
|
40
|
+
},
|
|
41
|
+
wrapStatus: {
|
|
42
|
+
flexDirection: 'row',
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
alignItems: 'center',
|
|
45
|
+
},
|
|
46
|
+
textStatus: {
|
|
47
|
+
color: Colors.Gray8,
|
|
48
|
+
fontSize: 14,
|
|
49
|
+
marginTop: 16,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -11,6 +11,7 @@ import TimerActionTemplate from './TimerActionTemplate';
|
|
|
11
11
|
import CurtainButtonTemplate from './CurtainButtonTemplate';
|
|
12
12
|
import SmartTiviActionTemplate from './SmartTiviActionTemplate/SmartTiviActionTemplate';
|
|
13
13
|
import LightActionTemplate from './LightActionTemplate';
|
|
14
|
+
import OnOffSmartLock from './OnOffSmartLock';
|
|
14
15
|
|
|
15
16
|
export const getActionComponent = (template) => {
|
|
16
17
|
switch (template) {
|
|
@@ -21,6 +22,8 @@ export const getActionComponent = (template) => {
|
|
|
21
22
|
case 'OnOffButtonActionTemplate':
|
|
22
23
|
case 'OnOffSimpleActionTemplate':
|
|
23
24
|
return OnOffTemplate;
|
|
25
|
+
case 'OnOffButtonActionSmartLock':
|
|
26
|
+
return OnOffSmartLock;
|
|
24
27
|
case 'one_button_action_template': // todo refactor later with backend
|
|
25
28
|
case 'OneBigButtonActionTemplate':
|
|
26
29
|
return OneBigButtonTemplate;
|
|
@@ -23,6 +23,7 @@ const ConnectingProcess = ({ route }) => {
|
|
|
23
23
|
station,
|
|
24
24
|
unit,
|
|
25
25
|
unit_id,
|
|
26
|
+
unit_name,
|
|
26
27
|
devicePrefixName,
|
|
27
28
|
wifi_ssid,
|
|
28
29
|
wifi_pass,
|
|
@@ -156,12 +157,14 @@ const ConnectingProcess = ({ route }) => {
|
|
|
156
157
|
{t('successfully_connected')}
|
|
157
158
|
</Text>
|
|
158
159
|
<Text size={14} style={styles.textHome}>
|
|
159
|
-
|
|
160
|
+
{`${unit?.name || unit_name} ${
|
|
161
|
+
station?.name !== undefined ? '- ' + station?.name : ''
|
|
162
|
+
}`}
|
|
160
163
|
</Text>
|
|
161
164
|
<DeviceItem icon={sensor?.icon_kit} name={sensor?.name} />
|
|
162
165
|
</View>
|
|
163
166
|
);
|
|
164
|
-
}, [sensor?.icon_kit, sensor?.name, station?.name, t]);
|
|
167
|
+
}, [sensor?.icon_kit, sensor?.name, station?.name, t, unit?.name, unit_name]);
|
|
165
168
|
|
|
166
169
|
const handleDone = useCallback(() => {
|
|
167
170
|
navigate(Routes.UnitStack, {
|
|
@@ -14,7 +14,7 @@ import Text from '../../commons/Text';
|
|
|
14
14
|
import { isDeviceConnected } from '../../iot/RemoteControl/Bluetooth';
|
|
15
15
|
|
|
16
16
|
import { Colors, Constants } from '../../configs';
|
|
17
|
-
import { TESTID } from '../../configs/Constants';
|
|
17
|
+
import { TESTID, DEVICE_TYPE } from '../../configs/Constants';
|
|
18
18
|
import FImage from '../../commons/FImage';
|
|
19
19
|
|
|
20
20
|
const marginItem = 12;
|
|
@@ -61,11 +61,16 @@ const ItemDevice = memo(
|
|
|
61
61
|
status === undefined
|
|
62
62
|
? isNetworkConnected && sensor.is_connected
|
|
63
63
|
: isNetworkConnected && status.is_connected;
|
|
64
|
-
const
|
|
64
|
+
const isConnectedViaBLE = isDeviceConnected(
|
|
65
65
|
sensor?.remote_control_options?.bluetooth?.address
|
|
66
66
|
);
|
|
67
|
+
const isConnectedViaGGHome =
|
|
68
|
+
!!sensor &&
|
|
69
|
+
sensor?.is_other_device &&
|
|
70
|
+
!sensor?.device_type !== DEVICE_TYPE.LG_THINQ &&
|
|
71
|
+
isGGHomeConnected;
|
|
67
72
|
const isConnected =
|
|
68
|
-
isConnectedViaInternet ||
|
|
73
|
+
isConnectedViaInternet || isConnectedViaGGHome || isConnectedViaBLE;
|
|
69
74
|
const borderColor = isConnected ? Colors.Gray4 : Colors.Red6;
|
|
70
75
|
const textConnected = isConnected ? t('connected') : t('disconnected');
|
|
71
76
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { act, create } from 'react-test-renderer';
|
|
3
|
+
import { SCProvider } from '../../../context';
|
|
4
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
5
|
+
import { TouchableOpacity } from 'react-native';
|
|
6
|
+
import MediaPlay from '../index';
|
|
7
|
+
|
|
8
|
+
jest.mock('react', () => {
|
|
9
|
+
return {
|
|
10
|
+
...jest.requireActual('react'),
|
|
11
|
+
memo: (x) => x,
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const wrapComponent = (props) => (
|
|
16
|
+
<SCProvider initState={mockSCStore({})}>
|
|
17
|
+
<MediaPlay {...props} />
|
|
18
|
+
</SCProvider>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
describe('Test MediaPlayer', () => {
|
|
22
|
+
let tree, props;
|
|
23
|
+
|
|
24
|
+
beforeAll(() => {
|
|
25
|
+
jest.useFakeTimers();
|
|
26
|
+
props = {
|
|
27
|
+
uri: 'uri',
|
|
28
|
+
previewUri: 'previewUri',
|
|
29
|
+
thumbnail: 'thumbnail',
|
|
30
|
+
background: 'background',
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('Test render', async () => {
|
|
35
|
+
await act(async () => {
|
|
36
|
+
tree = await create(wrapComponent(props));
|
|
37
|
+
});
|
|
38
|
+
const instance = tree.root;
|
|
39
|
+
const pauseButton = instance.findByType(TouchableOpacity);
|
|
40
|
+
await act(async () => {
|
|
41
|
+
await pauseButton.props.onPress();
|
|
42
|
+
});
|
|
43
|
+
jest.runAllTimers();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -4,7 +4,7 @@ import { useNavigation, useIsFocused } from '@react-navigation/native';
|
|
|
4
4
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
5
5
|
|
|
6
6
|
import { Images, Device, API } from '../../configs';
|
|
7
|
-
import {
|
|
7
|
+
import { TESTID } from '../../configs/Constants';
|
|
8
8
|
import { Section } from '../Section';
|
|
9
9
|
import Text from '../Text';
|
|
10
10
|
import ItemDevice from '../Device/ItemDevice';
|
|
@@ -104,28 +104,16 @@ const ShortDetailSubUnit = ({
|
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
const handleOnAddNew = () => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
});
|
|
116
|
-
} else {
|
|
117
|
-
alert(t('feature_under_development'));
|
|
118
|
-
}
|
|
107
|
+
navigate(Routes.AddDeviceStack, {
|
|
108
|
+
screen: Routes.ScanSensorQR,
|
|
109
|
+
params: {
|
|
110
|
+
station_id: station?.id,
|
|
111
|
+
unit_id: unit.id,
|
|
112
|
+
unit_name: unit.name,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
119
115
|
};
|
|
120
116
|
|
|
121
|
-
const itemAddNewTitle = t(
|
|
122
|
-
station?.isFavorites
|
|
123
|
-
? 'add_to_favorites'
|
|
124
|
-
: station?.name === SubUnitName.smart
|
|
125
|
-
? 'add_script'
|
|
126
|
-
: 'add_new'
|
|
127
|
-
);
|
|
128
|
-
|
|
129
117
|
return (
|
|
130
118
|
<Section style={styles.noShadow}>
|
|
131
119
|
{renderCamera()}
|
|
@@ -156,7 +144,7 @@ const ShortDetailSubUnit = ({
|
|
|
156
144
|
status={sensorsStatus.find((s) => s.id === sensor.id)}
|
|
157
145
|
/>
|
|
158
146
|
))}
|
|
159
|
-
<ItemAddNew title={
|
|
147
|
+
<ItemAddNew title={t('add_new_device')} onAddNew={handleOnAddNew} />
|
|
160
148
|
</View>
|
|
161
149
|
</Section>
|
|
162
150
|
);
|
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Image, View
|
|
2
|
+
import { Image, View } from 'react-native';
|
|
3
3
|
import { act, create } from 'react-test-renderer';
|
|
4
4
|
import { TESTID } from '../../../configs/Constants';
|
|
5
5
|
import { SCProvider } from '../../../context';
|
|
6
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
import ShortDetailSubUnit from '../ShortDetail';
|
|
8
|
+
import ItemAddNew from '../../Device/ItemAddNew';
|
|
7
9
|
import Routes from '../../../utils/Route';
|
|
8
10
|
|
|
9
|
-
const wrapComponent = (
|
|
11
|
+
const wrapComponent = (props) => (
|
|
10
12
|
<SCProvider initState={mockSCStore({})}>
|
|
11
|
-
<ShortDetailSubUnit
|
|
13
|
+
<ShortDetailSubUnit {...props} />
|
|
12
14
|
</SCProvider>
|
|
13
15
|
);
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
jest.mock('react', () => {
|
|
18
|
+
return {
|
|
19
|
+
...jest.requireActual('react'),
|
|
20
|
+
memo: (x) => x,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
16
23
|
|
|
17
24
|
const mockedNavigate = jest.fn();
|
|
18
|
-
|
|
19
25
|
jest.mock('@react-navigation/native', () => {
|
|
20
26
|
return {
|
|
21
27
|
...jest.requireActual('@react-navigation/native'),
|
|
@@ -27,43 +33,46 @@ jest.mock('@react-navigation/native', () => {
|
|
|
27
33
|
});
|
|
28
34
|
|
|
29
35
|
describe('test ShortDetail Subunit', () => {
|
|
30
|
-
let tree,
|
|
36
|
+
let tree, props;
|
|
31
37
|
beforeEach(() => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
38
|
+
props = {
|
|
39
|
+
unit: {
|
|
40
|
+
address: null,
|
|
41
|
+
background:
|
|
42
|
+
'https://cdn-staging.eoh.io/image-90a42c0a-96ad-42e5-b736-b2b8a2e7fb20.jpg',
|
|
43
|
+
can_add: true,
|
|
44
|
+
icon: 'https://cdn-staging.eoh.io/baelen.jpg',
|
|
45
|
+
id: 21,
|
|
46
|
+
main_config_count: 0,
|
|
47
|
+
name: 'Gia Cat Unit',
|
|
48
|
+
remote_control_options: { bluetooth: [], googlehome: [] },
|
|
49
|
+
stations: [
|
|
50
|
+
{
|
|
51
|
+
background:
|
|
52
|
+
'https://cdn-staging.eoh.io/image-cc9ea441-e113-46b5-bff3-23d924723733.jpg',
|
|
53
|
+
camera: null,
|
|
54
|
+
id: 71,
|
|
55
|
+
name: 'Station 1',
|
|
56
|
+
sensors: [],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
user_id: 64,
|
|
60
|
+
},
|
|
61
|
+
station: {
|
|
62
|
+
background:
|
|
63
|
+
'https://cdn-staging.eoh.io/image-cc9ea441-e113-46b5-bff3-23d924723733.jpg',
|
|
64
|
+
camera: null,
|
|
65
|
+
id: 71,
|
|
66
|
+
name: 'Station 1',
|
|
67
|
+
},
|
|
68
|
+
isNetworkConnected: true,
|
|
69
|
+
isGGHomeConnected: true,
|
|
61
70
|
};
|
|
62
71
|
});
|
|
63
72
|
|
|
64
73
|
test('render ShortDetail', () => {
|
|
65
74
|
act(() => {
|
|
66
|
-
tree = create(wrapComponent(
|
|
75
|
+
tree = create(wrapComponent(props));
|
|
67
76
|
});
|
|
68
77
|
const instance = tree.root;
|
|
69
78
|
const image = instance.findAllByType(Image);
|
|
@@ -74,9 +83,9 @@ describe('test ShortDetail Subunit', () => {
|
|
|
74
83
|
});
|
|
75
84
|
|
|
76
85
|
test('render ShortDetail without background', () => {
|
|
77
|
-
station.background = '';
|
|
86
|
+
props.station.background = '';
|
|
78
87
|
act(() => {
|
|
79
|
-
tree = create(wrapComponent(
|
|
88
|
+
tree = create(wrapComponent(props));
|
|
80
89
|
});
|
|
81
90
|
const instance = tree.root;
|
|
82
91
|
const image = instance.findAllByType(Image);
|
|
@@ -87,7 +96,7 @@ describe('test ShortDetail Subunit', () => {
|
|
|
87
96
|
});
|
|
88
97
|
|
|
89
98
|
test('render ShortDetail with camera', () => {
|
|
90
|
-
station.camera = {
|
|
99
|
+
props.station.camera = {
|
|
91
100
|
id: 2,
|
|
92
101
|
name: 'EoH Gate',
|
|
93
102
|
preview_uri: '',
|
|
@@ -95,7 +104,7 @@ describe('test ShortDetail Subunit', () => {
|
|
|
95
104
|
};
|
|
96
105
|
|
|
97
106
|
act(() => {
|
|
98
|
-
tree = create(wrapComponent(
|
|
107
|
+
tree = create(wrapComponent(props));
|
|
99
108
|
});
|
|
100
109
|
const instance = tree.root;
|
|
101
110
|
const view = instance.findAllByType(View);
|
|
@@ -106,7 +115,7 @@ describe('test ShortDetail Subunit', () => {
|
|
|
106
115
|
});
|
|
107
116
|
|
|
108
117
|
test('render ShortDetail with device', () => {
|
|
109
|
-
station.sensors = [
|
|
118
|
+
props.station.sensors = [
|
|
110
119
|
{
|
|
111
120
|
action: {
|
|
112
121
|
color: '#00979D',
|
|
@@ -129,7 +138,7 @@ describe('test ShortDetail Subunit', () => {
|
|
|
129
138
|
];
|
|
130
139
|
|
|
131
140
|
act(() => {
|
|
132
|
-
tree = create(wrapComponent(
|
|
141
|
+
tree = create(wrapComponent(props));
|
|
133
142
|
});
|
|
134
143
|
const instance = tree.root;
|
|
135
144
|
const itemDevice = instance.findAll(
|
|
@@ -141,19 +150,19 @@ describe('test ShortDetail Subunit', () => {
|
|
|
141
150
|
|
|
142
151
|
test('render ShortDetail add new device', () => {
|
|
143
152
|
act(() => {
|
|
144
|
-
tree = create(wrapComponent(
|
|
153
|
+
tree = create(wrapComponent(props));
|
|
145
154
|
});
|
|
146
155
|
const instance = tree.root;
|
|
147
|
-
const buttonAddNew = instance.
|
|
156
|
+
const buttonAddNew = instance.findByType(ItemAddNew);
|
|
148
157
|
act(() => {
|
|
149
|
-
buttonAddNew
|
|
158
|
+
buttonAddNew.props.onAddNew();
|
|
150
159
|
});
|
|
151
160
|
expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddDeviceStack, {
|
|
152
161
|
screen: Routes.ScanSensorQR,
|
|
153
162
|
params: {
|
|
154
|
-
station_id: station.id,
|
|
155
|
-
unit_id: unit.id,
|
|
156
|
-
unit_name: unit.name,
|
|
163
|
+
station_id: props.station.id,
|
|
164
|
+
unit_id: props.unit.id,
|
|
165
|
+
unit_name: props.unit.name,
|
|
157
166
|
},
|
|
158
167
|
});
|
|
159
168
|
});
|
package/src/configs/API.js
CHANGED
|
@@ -182,9 +182,9 @@ const API = {
|
|
|
182
182
|
`/connection_manager/lg_thinq/device_status/${sensorId}/`,
|
|
183
183
|
},
|
|
184
184
|
VCONNEX: {
|
|
185
|
-
AUTHORIZE: (client_id, redirect_uri, user_id, station_id) =>
|
|
185
|
+
AUTHORIZE: (client_id, redirect_uri, user_id, unit_id, station_id) =>
|
|
186
186
|
// eslint-disable-next-line max-len
|
|
187
|
-
`https://partner-api-stg.vconnex.vn/oauth/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=code&scope=SYNCH&scope=CONTROL&scope=QUERY&state=${user_id}@${station_id}`,
|
|
187
|
+
`https://partner-api-stg.vconnex.vn/oauth/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=code&scope=SYNCH&scope=CONTROL&scope=QUERY&state=${user_id}@${unit_id}@${station_id}`,
|
|
188
188
|
},
|
|
189
189
|
},
|
|
190
190
|
NOTIFICATION: {
|
package/src/configs/Constants.js
CHANGED
|
@@ -663,6 +663,8 @@ export const NOTIFICATION_TYPES = {
|
|
|
663
663
|
NOTIFY_DEVICE_DISCONNECT: 'NOTIFY_DEVICE_DISCONNECT',
|
|
664
664
|
NOTIFY_RENAME_SUB_UNIT: 'NOTIFY_RENAME_SUB_UNIT',
|
|
665
665
|
NOTIFY_UPDATE_ADDRESS: 'NOTIFY_UPDATE_ADDRESS',
|
|
666
|
+
NOTIFY_REMOVE_SUB_UNIT: 'NOTIFY_REMOVE_SUB_UNIT',
|
|
667
|
+
NOTIFY_REMOVE_DEVICE: 'NOTIFY_REMOVE_DEVICE',
|
|
666
668
|
};
|
|
667
669
|
|
|
668
670
|
export const ACTIVITY_LOG_TYPES = {
|
|
@@ -670,3 +672,14 @@ export const ACTIVITY_LOG_TYPES = {
|
|
|
670
672
|
ACTIVATED_BY: 'ACTIVATED_BY',
|
|
671
673
|
SCRIPT_UPDATED_BY: 'SCRIPT_UPDATED_BY',
|
|
672
674
|
};
|
|
675
|
+
|
|
676
|
+
export const SENSOR_TYPE = {
|
|
677
|
+
AIR_QUALITY: 'air_quality',
|
|
678
|
+
TURBIDITY: 'turbidity',
|
|
679
|
+
PH: 'ph',
|
|
680
|
+
CLO: 'clo',
|
|
681
|
+
UV: 'uv',
|
|
682
|
+
SMOKE: 'smoke',
|
|
683
|
+
FIRE: 'fire',
|
|
684
|
+
SOS: 'sos',
|
|
685
|
+
};
|
|
@@ -37,6 +37,7 @@ String.prototype.capitalize = function () {
|
|
|
37
37
|
return this.charAt(0).toUpperCase() + this.slice(1);
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
let onEndReachedCalledDuringMomentum = false;
|
|
40
41
|
let dataTemp = [];
|
|
41
42
|
|
|
42
43
|
export default ({ id, type, share, filterEnabled }) => {
|
|
@@ -59,7 +60,7 @@ export default ({ id, type, share, filterEnabled }) => {
|
|
|
59
60
|
if (page === 1) {
|
|
60
61
|
setIsRefreshing(true);
|
|
61
62
|
} else {
|
|
62
|
-
if (!isCanLoadMore
|
|
63
|
+
if (!isCanLoadMore) {
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
66
|
setIsLoading(true);
|
|
@@ -81,6 +82,7 @@ export default ({ id, type, share, filterEnabled }) => {
|
|
|
81
82
|
params.append(key, value);
|
|
82
83
|
}
|
|
83
84
|
params.append('page', page);
|
|
85
|
+
|
|
84
86
|
const { success, data } = await axiosGet(api.url(id), {
|
|
85
87
|
params: params,
|
|
86
88
|
});
|
|
@@ -91,9 +93,9 @@ export default ({ id, type, share, filterEnabled }) => {
|
|
|
91
93
|
setData(api.standardizeData(results));
|
|
92
94
|
} else {
|
|
93
95
|
dataTemp = dataTemp.concat(results);
|
|
96
|
+
setIsCanLoadMore(page < Math.ceil(data.count / 20));
|
|
94
97
|
setData(api.standardizeData(dataTemp));
|
|
95
98
|
}
|
|
96
|
-
setIsCanLoadMore(page < Math.ceil(data.count / 20));
|
|
97
99
|
}
|
|
98
100
|
page === 1 ? setIsRefreshing(false) : setIsLoading(false);
|
|
99
101
|
};
|
|
@@ -110,9 +112,20 @@ export default ({ id, type, share, filterEnabled }) => {
|
|
|
110
112
|
}
|
|
111
113
|
};
|
|
112
114
|
|
|
113
|
-
const onRefresh = () =>
|
|
115
|
+
const onRefresh = () => {
|
|
116
|
+
setIsCanLoadMore(true);
|
|
117
|
+
fetchData({ ...filters, page: 1 });
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const onLoadMore = () => {
|
|
121
|
+
if (!onEndReachedCalledDuringMomentum) {
|
|
122
|
+
onEndReachedCalledDuringMomentum = true;
|
|
123
|
+
fetchData({ ...filters, page: page + 1 });
|
|
124
|
+
}
|
|
125
|
+
};
|
|
114
126
|
|
|
115
|
-
const
|
|
127
|
+
const onMomentumScrollBegin = () =>
|
|
128
|
+
(onEndReachedCalledDuringMomentum = false);
|
|
116
129
|
|
|
117
130
|
return {
|
|
118
131
|
data,
|
|
@@ -124,5 +137,6 @@ export default ({ id, type, share, filterEnabled }) => {
|
|
|
124
137
|
fetchMembers,
|
|
125
138
|
filters,
|
|
126
139
|
setFilters,
|
|
140
|
+
onMomentumScrollBegin,
|
|
127
141
|
};
|
|
128
142
|
};
|
|
@@ -34,7 +34,9 @@ const ActivityLogScreen = ({ route }) => {
|
|
|
34
34
|
fetchMembers,
|
|
35
35
|
filters,
|
|
36
36
|
setFilters,
|
|
37
|
+
onMomentumScrollBegin,
|
|
37
38
|
} = useActivityLog({ id, type, share, filterEnabled });
|
|
39
|
+
|
|
38
40
|
const [showFilterPopup, setShowFilterPopup, setHideFilterPopup] =
|
|
39
41
|
useBoolean();
|
|
40
42
|
|
|
@@ -113,6 +115,7 @@ const ActivityLogScreen = ({ route }) => {
|
|
|
113
115
|
removeClippedSubviews={true}
|
|
114
116
|
maxToRenderPerBatch={20}
|
|
115
117
|
contentContainerStyle={styles.contentContainerStyle}
|
|
118
|
+
onMomentumScrollBegin={onMomentumScrollBegin}
|
|
116
119
|
/>
|
|
117
120
|
</View>
|
|
118
121
|
{(filterEnabled.user || filterEnabled.date) && (
|
|
@@ -152,7 +152,7 @@ describe('Test SelectSubUnit container', () => {
|
|
|
152
152
|
case 'AddVconnexDevice':
|
|
153
153
|
expect(mockedNavigate).toBeCalledWith('Browser', {
|
|
154
154
|
// eslint-disable-next-line max-len
|
|
155
|
-
link: 'https://partner-api-stg.vconnex.vn/oauth/authorize?client_id=&redirect_uri=&response_type=code&scope=SYNCH&scope=CONTROL&scope=QUERY&state=undefined@undefined',
|
|
155
|
+
link: 'https://partner-api-stg.vconnex.vn/oauth/authorize?client_id=&redirect_uri=&response_type=code&scope=SYNCH&scope=CONTROL&scope=QUERY&state=undefined@undefined@undefined',
|
|
156
156
|
});
|
|
157
157
|
break;
|
|
158
158
|
case 'AddDeviceNewFlow':
|
|
@@ -175,7 +175,7 @@ const SelectSensorDevices = memo(({ route }) => {
|
|
|
175
175
|
{t(title)}
|
|
176
176
|
</Text>
|
|
177
177
|
|
|
178
|
-
{
|
|
178
|
+
{listStation ? (
|
|
179
179
|
<NavBar
|
|
180
180
|
listStation={listStation}
|
|
181
181
|
listMenuItem={listMenuItem}
|
|
@@ -185,7 +185,9 @@ const SelectSensorDevices = memo(({ route }) => {
|
|
|
185
185
|
/>
|
|
186
186
|
) : (
|
|
187
187
|
<View style={styles.noneData}>
|
|
188
|
-
<Text center>
|
|
188
|
+
<Text center>
|
|
189
|
+
{t('you_do_not_have_the_device_or_have_share_control_device')}
|
|
190
|
+
</Text>
|
|
189
191
|
</View>
|
|
190
192
|
)}
|
|
191
193
|
|
|
@@ -28,8 +28,15 @@ import { SCContext } from '../../../context';
|
|
|
28
28
|
import { Action } from '../../../context/actionType';
|
|
29
29
|
|
|
30
30
|
const ConnectWifiWarning = memo(({ route }) => {
|
|
31
|
-
const {
|
|
32
|
-
|
|
31
|
+
const {
|
|
32
|
+
wifi_ssid,
|
|
33
|
+
wifi_pass,
|
|
34
|
+
unit_id,
|
|
35
|
+
chip_id,
|
|
36
|
+
devicePrefixName,
|
|
37
|
+
body,
|
|
38
|
+
unit_name,
|
|
39
|
+
} = route.params;
|
|
33
40
|
const t = useTranslations();
|
|
34
41
|
const { navigate, goBack } = useNavigation();
|
|
35
42
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -109,6 +116,7 @@ const ConnectWifiWarning = memo(({ route }) => {
|
|
|
109
116
|
screen: Routes.ConnectingProcess,
|
|
110
117
|
params: {
|
|
111
118
|
unit_id: unit_id,
|
|
119
|
+
unit_name: unit_name,
|
|
112
120
|
scan_sensor_data: { ...body },
|
|
113
121
|
gateway: data?.gateway,
|
|
114
122
|
devicePrefixName: devicePrefixName,
|