@eohjsc/react-native-smart-city 0.7.7 → 0.7.9
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/AddNewDevice/add-scan-device-icon.svg +13 -0
- package/assets/images/Email.svg +9 -0
- package/assets/images/lan.svg +3 -0
- package/assets/images/wifi-open.svg +3 -0
- package/package.json +4 -3
- package/src/commons/ActionGroup/StatesGridActionTemplate.js +7 -3
- package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +7 -3
- package/src/commons/AlertAction/index.js +1 -0
- package/src/commons/Auth/AccountItem.js +17 -3
- package/src/commons/Auth/AccountList.js +3 -7
- package/src/commons/ConnectWifi/__test__/ConnectWifi.test.js +373 -0
- package/src/commons/ConnectWifi/index.js +201 -0
- package/src/commons/ConnectWifi/styles.js +69 -0
- package/src/commons/Device/LabelValue/__test__/LabelValue.test.js +74 -0
- package/src/commons/Device/LabelValue/index.js +49 -0
- package/src/commons/Device/LabelValue/styles.js +33 -0
- package/src/commons/Form/TextInputPassword.js +1 -1
- package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +6 -2
- package/src/configs/API.js +12 -0
- package/src/configs/AccessibilityLabel.js +7 -0
- package/src/configs/Constants.js +1 -0
- package/src/hooks/Common/index.js +2 -2
- package/src/hooks/Common/useBlockBack.js +36 -0
- package/src/hooks/useMqtt.js +10 -5
- package/src/navigations/AddGatewayStack.js +2 -0
- package/src/navigations/AllGatewayStack.js +4 -0
- package/src/navigations/Main.js +2 -2
- package/src/navigations/UnitStack.js +32 -0
- package/src/screens/AddNewGateway/ConnectingWifiDevice.js +7 -6
- package/src/screens/AddNewGateway/ScanDeviceLocal.js +267 -0
- package/src/screens/AddNewGateway/ScanDeviceLocalStyles.js +58 -0
- package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +10 -2
- package/src/screens/AddNewGateway/SelectDeviceType.js +19 -2
- package/src/screens/AddNewGateway/__test__/ScanDeviceLocal.test.js +475 -0
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +2 -2
- package/src/screens/AddNewGateway/configs/API.js +8 -0
- package/src/screens/AddNewGateway/hooks/useConnectDevice.js +59 -0
- package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +58 -1
- package/src/screens/AllGateway/GatewayInfo/index.js +8 -6
- package/src/screens/AllGateway/GatewayWifi/__test__/index.test.js +319 -0
- package/src/screens/AllGateway/GatewayWifi/index.js +107 -0
- package/src/screens/AllGateway/Successfully/__test__/index.test.js +77 -0
- package/src/screens/AllGateway/Successfully/index.js +66 -0
- package/src/screens/AllGateway/Successfully/styles.js +35 -0
- package/src/screens/AllGateway/components/Information/index.js +17 -1
- package/src/screens/AllGateway/components/RowItem/index.js +12 -1
- package/src/screens/AllGateway/hooks/__test__/index.test.js +18 -0
- package/src/screens/AllGateway/hooks/useGateway.js +13 -0
- package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +3 -3
- package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +79 -0
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +166 -0
- package/src/screens/Automate/AddNewAction/Styles/SetupScriptEmailStyles.js +37 -0
- package/src/screens/Automate/AddNewAction/Styles/SetupScriptReceiverEmailStyles.js +79 -0
- package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +1 -1
- package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -5
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptEmail.test.js +76 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +105 -0
- package/src/screens/Automate/EditActionsList/Styles/UpdateReceiverEmailScriptStyles.js +78 -0
- package/src/screens/Automate/EditActionsList/UpdateEmailScript.js +80 -0
- package/src/screens/Automate/EditActionsList/UpdateReceiverEmailScript.js +179 -0
- package/src/screens/Automate/EditActionsList/__tests__/UpdateEmailScript.test.js +81 -0
- package/src/screens/Automate/EditActionsList/__tests__/UpdateReceiverEmailScript.test.js +83 -0
- package/src/screens/Automate/EditActionsList/__tests__/index.test.js +38 -5
- package/src/screens/Automate/EditActionsList/index.js +59 -2
- package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +20 -0
- package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +5 -3
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +127 -21
- package/src/screens/Automate/ScriptDetail/index.js +57 -14
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +22 -0
- package/src/screens/Device/components/SensorDisplayItem.js +10 -0
- package/src/screens/SharedUnit/index.js +2 -2
- package/src/screens/Sharing/SelectUser.js +47 -47
- package/src/screens/Sharing/__test__/SelectUser.test.js +57 -103
- package/src/screens/SubUnit/ManageSubUnit.js +94 -90
- package/src/screens/SubUnit/ManageSubUnitStyles.js +4 -6
- package/src/screens/SubUnit/RearrageSubUnit.js +90 -0
- package/src/screens/SubUnit/RearrrageSubUnitStyle.js +65 -0
- package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +35 -19
- package/src/screens/SubUnit/__test__/RearrangeSubUnit.test.js +129 -0
- package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +6 -7
- package/src/screens/SubUnit/hooks/useManageSubUnit.js +8 -16
- package/src/screens/Unit/Detail.js +2 -6
- package/src/screens/Unit/ManageUnit.js +1 -1
- package/src/utils/Functions/__test__/ShortEmail.test.js +5 -0
- package/src/utils/I18n/translations/en.js +46 -8
- package/src/utils/I18n/translations/vi.js +37 -4
- package/src/utils/Route/index.js +7 -0
- package/src/commons/Auth/__test__/AccountItem.test.js +0 -31
- package/src/hooks/Common/useBlockBackAndroid.js +0 -21
- package/src/screens/SubUnit/DetailStyles.js +0 -46
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { isEqual } from 'lodash';
|
|
4
|
+
import { API } from '../../configs';
|
|
5
|
+
import { axiosPost } from '../../utils/Apis/axios';
|
|
6
|
+
import styles from './RearrrageSubUnitStyle';
|
|
7
|
+
import Text from '../../commons/Text';
|
|
8
|
+
import FlatListDnD from '../../commons/FlatListDnD';
|
|
9
|
+
import ViewButtonBottom from '../../commons/ViewButtonBottom';
|
|
10
|
+
import { HeaderCustom } from '../../commons/Header';
|
|
11
|
+
import Rearrange from '../../../assets/images/Rearrange.svg';
|
|
12
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
13
|
+
import { useNavigation } from '@react-navigation/native';
|
|
14
|
+
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
15
|
+
|
|
16
|
+
const RearrangeSubUnit = ({ route }) => {
|
|
17
|
+
const { stations, unit } = route.params;
|
|
18
|
+
const t = useTranslations();
|
|
19
|
+
const { goBack } = useNavigation();
|
|
20
|
+
const [reorderItems, setReorderItems] = useState(stations);
|
|
21
|
+
const handleOnSave = async () => {
|
|
22
|
+
const idOrderSubUnits = reorderItems.map((i) => i.id);
|
|
23
|
+
const { success } = await axiosPost(API.SUB_UNIT.ORDER_SUB_UNITS(unit.id), {
|
|
24
|
+
id_order_sub_units: idOrderSubUnits,
|
|
25
|
+
});
|
|
26
|
+
if (success) {
|
|
27
|
+
ToastBottomHelper.success(t('updated_sub_unit_order'));
|
|
28
|
+
goBack();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const renderItem = ({ item, getIndex, drag, isActive }) => {
|
|
33
|
+
const index = getIndex() + 1;
|
|
34
|
+
return (
|
|
35
|
+
<View style={styles.itemWrapper}>
|
|
36
|
+
<TouchableOpacity
|
|
37
|
+
style={[
|
|
38
|
+
styles.border,
|
|
39
|
+
styles.indexWrapper,
|
|
40
|
+
/* istanbul ignore next */
|
|
41
|
+
isActive && styles.isDragging,
|
|
42
|
+
]}
|
|
43
|
+
onPressIn={drag}
|
|
44
|
+
>
|
|
45
|
+
<Text style={styles.indexText}>{`${index}`.padStart(2, '0')}</Text>
|
|
46
|
+
<Rearrange />
|
|
47
|
+
</TouchableOpacity>
|
|
48
|
+
<View
|
|
49
|
+
style={[
|
|
50
|
+
styles.border,
|
|
51
|
+
styles.subUnitWrapper,
|
|
52
|
+
/* istanbul ignore next */
|
|
53
|
+
isActive && styles.isDragging,
|
|
54
|
+
]}
|
|
55
|
+
>
|
|
56
|
+
<Text style={styles.indexText}>{item.name}</Text>
|
|
57
|
+
<Text style={styles.deviceText}>
|
|
58
|
+
{`${item.devices.length} ${t('devices').toLowerCase()}`}
|
|
59
|
+
</Text>
|
|
60
|
+
</View>
|
|
61
|
+
</View>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<View style={styles.container}>
|
|
67
|
+
<HeaderCustom title={t('rearrange_sub_unit')} isShowSeparator />
|
|
68
|
+
<Text style={styles.hintText}>{t('rearrange_sub_unit_hint')}</Text>
|
|
69
|
+
<View style={styles.flatList}>
|
|
70
|
+
<FlatListDnD
|
|
71
|
+
data={reorderItems}
|
|
72
|
+
extraData={reorderItems}
|
|
73
|
+
setData={setReorderItems}
|
|
74
|
+
renderItem={renderItem}
|
|
75
|
+
/>
|
|
76
|
+
</View>
|
|
77
|
+
<ViewButtonBottom
|
|
78
|
+
leftTitle={t('cancel')}
|
|
79
|
+
onLeftClick={() => goBack()}
|
|
80
|
+
rightTitle={t('save')}
|
|
81
|
+
rightDisabled={isEqual(stations, reorderItems)}
|
|
82
|
+
onRightClick={handleOnSave}
|
|
83
|
+
isPreventDoubleTouch
|
|
84
|
+
wrapStyle={styles.bottomButtonWrapper}
|
|
85
|
+
/>
|
|
86
|
+
</View>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export default RearrangeSubUnit;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Colors } from '../../configs';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export default StyleSheet.create({
|
|
5
|
+
container: {
|
|
6
|
+
flex: 1,
|
|
7
|
+
backgroundColor: Colors.White,
|
|
8
|
+
},
|
|
9
|
+
border: {
|
|
10
|
+
borderRadius: 5,
|
|
11
|
+
borderColor: Colors.Gray6,
|
|
12
|
+
borderWidth: 1,
|
|
13
|
+
padding: 20,
|
|
14
|
+
backgroundColor: Colors.White,
|
|
15
|
+
shadowColor: Colors.Black,
|
|
16
|
+
shadowOffset: {
|
|
17
|
+
width: 0,
|
|
18
|
+
height: 10,
|
|
19
|
+
},
|
|
20
|
+
shadowOpacity: 0.23,
|
|
21
|
+
shadowRadius: 11.27,
|
|
22
|
+
elevation: 4,
|
|
23
|
+
},
|
|
24
|
+
flatList: {
|
|
25
|
+
flex: 0.95,
|
|
26
|
+
marginBottom: 10,
|
|
27
|
+
},
|
|
28
|
+
isDragging: {
|
|
29
|
+
borderBottomWidth: 1,
|
|
30
|
+
borderColor: Colors.Red,
|
|
31
|
+
},
|
|
32
|
+
itemWrapper: {
|
|
33
|
+
flexDirection: 'row',
|
|
34
|
+
marginBottom: 20,
|
|
35
|
+
marginHorizontal: 16,
|
|
36
|
+
backgroundColor: Colors.White,
|
|
37
|
+
},
|
|
38
|
+
indexWrapper: {
|
|
39
|
+
flexDirection: 'column',
|
|
40
|
+
justifyContent: 'center',
|
|
41
|
+
alignItems: 'center',
|
|
42
|
+
},
|
|
43
|
+
subUnitWrapper: {
|
|
44
|
+
flex: 1,
|
|
45
|
+
marginLeft: 10,
|
|
46
|
+
justifyContent: 'center',
|
|
47
|
+
},
|
|
48
|
+
hintText: {
|
|
49
|
+
marginHorizontal: 16,
|
|
50
|
+
marginTop: 10,
|
|
51
|
+
},
|
|
52
|
+
indexText: {
|
|
53
|
+
fontSize: 16,
|
|
54
|
+
lineHeight: 24,
|
|
55
|
+
fontWeight: 'bold',
|
|
56
|
+
},
|
|
57
|
+
deviceText: {
|
|
58
|
+
fontSize: 14,
|
|
59
|
+
lineHeight: 20,
|
|
60
|
+
color: Colors.Gray7,
|
|
61
|
+
},
|
|
62
|
+
bottomButtonWrapper: {
|
|
63
|
+
backgroundColor: Colors.White,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
@@ -22,26 +22,29 @@ const wrapComponent = (route) => (
|
|
|
22
22
|
);
|
|
23
23
|
|
|
24
24
|
describe('Test ManageSubUnit', () => {
|
|
25
|
-
let tree;
|
|
25
|
+
let tree, route, data;
|
|
26
26
|
const mockedNavigate = useNavigation().navigate;
|
|
27
27
|
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
route = {
|
|
30
|
+
params: { unit: { id: 1, name: 'unit 1' } },
|
|
31
|
+
};
|
|
32
|
+
data = [{ id: 1, name: 'station', devices: [{ id: 1, name: 'device' }] }];
|
|
33
|
+
});
|
|
34
|
+
|
|
28
35
|
afterEach(() => {
|
|
29
36
|
mockedNavigate.mockClear();
|
|
30
37
|
mock.reset();
|
|
31
38
|
});
|
|
32
39
|
|
|
33
40
|
it('render ManageSubUnit', async () => {
|
|
34
|
-
let route = {
|
|
35
|
-
params: { unit: { id: 1, name: 'unit 1' } },
|
|
36
|
-
};
|
|
37
|
-
const data = [{ id: 1, name: 'sensor' }];
|
|
38
41
|
mock.onGet(API.UNIT.UNIT_DETAIL(1)).reply(200, { stations: data });
|
|
39
42
|
await act(async () => {
|
|
40
43
|
tree = await create(wrapComponent(route));
|
|
41
44
|
});
|
|
42
45
|
const instance = tree.root;
|
|
43
46
|
const subUnitScrollViews = instance.findAllByType(ScrollView);
|
|
44
|
-
expect(subUnitScrollViews).toHaveLength(
|
|
47
|
+
expect(subUnitScrollViews).toHaveLength(1);
|
|
45
48
|
const rowItem = instance.findAllByType(RowItem);
|
|
46
49
|
expect(rowItem).toHaveLength(1);
|
|
47
50
|
await act(async () => {
|
|
@@ -49,19 +52,13 @@ describe('Test ManageSubUnit', () => {
|
|
|
49
52
|
});
|
|
50
53
|
expect(global.mockedNavigate).toHaveBeenCalledWith(Routes.UnitStack, {
|
|
51
54
|
params: {
|
|
52
|
-
station:
|
|
53
|
-
unit:
|
|
54
|
-
id: 1,
|
|
55
|
-
name: 'unit 1',
|
|
56
|
-
},
|
|
55
|
+
station: data[0],
|
|
56
|
+
unit: route.params.unit,
|
|
57
57
|
},
|
|
58
|
-
screen:
|
|
58
|
+
screen: Routes.EditSubUnit,
|
|
59
59
|
});
|
|
60
60
|
});
|
|
61
61
|
it('ManageSubUnit add sub unit', async () => {
|
|
62
|
-
let route = {
|
|
63
|
-
params: { unit: { id: 1, name: 'unit 1' } },
|
|
64
|
-
};
|
|
65
62
|
await act(async () => {
|
|
66
63
|
tree = await create(wrapComponent(route));
|
|
67
64
|
});
|
|
@@ -76,12 +73,31 @@ describe('Test ManageSubUnit', () => {
|
|
|
76
73
|
});
|
|
77
74
|
expect(global.mockedNavigate).toHaveBeenCalledWith(Routes.AddSubUnitStack, {
|
|
78
75
|
params: {
|
|
79
|
-
unit:
|
|
80
|
-
id: 1,
|
|
81
|
-
name: 'unit 1',
|
|
82
|
-
},
|
|
76
|
+
unit: route.params.unit,
|
|
83
77
|
},
|
|
84
78
|
screen: Routes.AddSubUnit,
|
|
85
79
|
});
|
|
86
80
|
});
|
|
81
|
+
it('ManageSubUnit rearrange sub unit', async () => {
|
|
82
|
+
mock.onGet(API.UNIT.UNIT_DETAIL(1)).reply(200, { stations: data });
|
|
83
|
+
await act(async () => {
|
|
84
|
+
tree = await create(wrapComponent(route));
|
|
85
|
+
});
|
|
86
|
+
const instance = tree.root;
|
|
87
|
+
const buttonRearrangeSubUnit = instance.find(
|
|
88
|
+
(el) =>
|
|
89
|
+
el.props.accessibilityLabel === AccessibilityLabel.REARRANGE_SUB_UNIT &&
|
|
90
|
+
el.type === TouchableOpacity
|
|
91
|
+
);
|
|
92
|
+
await act(async () => {
|
|
93
|
+
buttonRearrangeSubUnit.props.onPress();
|
|
94
|
+
});
|
|
95
|
+
expect(global.mockedNavigate).toHaveBeenCalledWith(Routes.UnitStack, {
|
|
96
|
+
params: {
|
|
97
|
+
unit: route.params.unit,
|
|
98
|
+
stations: data,
|
|
99
|
+
},
|
|
100
|
+
screen: Routes.RearrangeSubUnit,
|
|
101
|
+
});
|
|
102
|
+
});
|
|
87
103
|
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { create } from 'react-test-renderer';
|
|
3
|
+
import { act } from '@testing-library/react-hooks';
|
|
4
|
+
import { API } from '../../../configs';
|
|
5
|
+
import { ViewButtonBottom } from '../../../commons';
|
|
6
|
+
import { SCProvider } from '../../../context';
|
|
7
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
8
|
+
import api from '../../../utils/Apis/axios';
|
|
9
|
+
import RearrageSubUnit from '../RearrageSubUnit';
|
|
10
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
11
|
+
import { useNavigation } from '@react-navigation/native';
|
|
12
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
13
|
+
import DraggableFlatList from 'react-native-draggable-flatlist';
|
|
14
|
+
|
|
15
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
16
|
+
|
|
17
|
+
const wrapComponent = (route) => (
|
|
18
|
+
<SCProvider initState={mockSCStore({})}>
|
|
19
|
+
<RearrageSubUnit route={route} />
|
|
20
|
+
</SCProvider>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
describe('Test RearrangeSubUnit', () => {
|
|
24
|
+
let tree, route;
|
|
25
|
+
const mockGoBack = useNavigation().goBack;
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
route = {
|
|
29
|
+
params: {
|
|
30
|
+
unit: { id: 1, name: 'unit 1' },
|
|
31
|
+
stations: [
|
|
32
|
+
{ id: 1, name: 'station 1', devices: [{ id: 1, name: 'device 1' }] },
|
|
33
|
+
{ id: 2, name: 'station 2', devices: [{ id: 1, name: 'device 2' }] },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
mockGoBack.mockClear();
|
|
40
|
+
mock.reset();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('test render RearrageSubUnit', async () => {
|
|
44
|
+
await act(async () => {
|
|
45
|
+
tree = await create(wrapComponent(route));
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const spyToastSuccess = jest.spyOn(ToastBottomHelper, 'success');
|
|
49
|
+
mock.onPost(API.SUB_UNIT.ORDER_SUB_UNITS(1)).reply(200);
|
|
50
|
+
|
|
51
|
+
const instance = tree.root;
|
|
52
|
+
const flatListDnD = instance.findByType(DraggableFlatList);
|
|
53
|
+
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
54
|
+
|
|
55
|
+
expect(flatListDnD.props.data).toEqual(route.params.stations);
|
|
56
|
+
|
|
57
|
+
const swappedStations = [
|
|
58
|
+
{ id: 2, name: 'station 2', devices: [{ id: 1, name: 'device 2' }] },
|
|
59
|
+
{ id: 1, name: 'station 1', devices: [{ id: 1, name: 'device 1' }] },
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
await act(async () => {
|
|
63
|
+
flatListDnD.props.onDragEnd({ data: swappedStations });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await act(async () => {
|
|
67
|
+
viewButtonBottom.props.onRightClick();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(mock.history.post).toHaveLength(1);
|
|
71
|
+
expect(mock.history.post[0].data).toEqual(
|
|
72
|
+
JSON.stringify({ id_order_sub_units: [2, 1] })
|
|
73
|
+
);
|
|
74
|
+
expect(spyToastSuccess).toHaveBeenCalledTimes(1);
|
|
75
|
+
expect(mockGoBack).toHaveBeenCalled();
|
|
76
|
+
expect(flatListDnD.props.data).toEqual(swappedStations);
|
|
77
|
+
});
|
|
78
|
+
it('test click cancel and save button is disabled', async () => {
|
|
79
|
+
await act(async () => {
|
|
80
|
+
tree = await create(wrapComponent(route));
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const instance = tree.root;
|
|
84
|
+
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
85
|
+
|
|
86
|
+
expect(viewButtonBottom.props.rightDisabled).toEqual(true);
|
|
87
|
+
await act(async () => {
|
|
88
|
+
viewButtonBottom.props.onLeftClick();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(mockGoBack).toHaveBeenCalled();
|
|
92
|
+
expect(mock.history.post).toHaveLength(0);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('test call api error', async () => {
|
|
96
|
+
await act(async () => {
|
|
97
|
+
tree = await create(wrapComponent(route));
|
|
98
|
+
});
|
|
99
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
100
|
+
mock.onPost(API.SUB_UNIT.ORDER_SUB_UNITS(1)).reply(400);
|
|
101
|
+
|
|
102
|
+
const instance = tree.root;
|
|
103
|
+
const flatListDnD = instance.findByType(DraggableFlatList);
|
|
104
|
+
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
105
|
+
|
|
106
|
+
expect(flatListDnD.props.data).toEqual(route.params.stations);
|
|
107
|
+
|
|
108
|
+
const swappedStations = [
|
|
109
|
+
{ id: 2, name: 'station 2', devices: [{ id: 1, name: 'device 2' }] },
|
|
110
|
+
{ id: 1, name: 'station 1', devices: [{ id: 1, name: 'device 1' }] },
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
await act(async () => {
|
|
114
|
+
flatListDnD.props.onDragEnd({ data: swappedStations });
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
await act(async () => {
|
|
118
|
+
viewButtonBottom.props.onRightClick();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(mock.history.post).toHaveLength(1);
|
|
122
|
+
expect(mock.history.post[0].data).toEqual(
|
|
123
|
+
JSON.stringify({ id_order_sub_units: [2, 1] })
|
|
124
|
+
);
|
|
125
|
+
expect(spyToastError).toHaveBeenCalledTimes(1);
|
|
126
|
+
expect(mockGoBack).toHaveBeenCalledTimes(0);
|
|
127
|
+
expect(flatListDnD.props.data).toEqual(swappedStations);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -10,14 +10,13 @@ describe('Test Manage Access', () => {
|
|
|
10
10
|
const unit = { id: 1, name: 'unit name' };
|
|
11
11
|
|
|
12
12
|
it('Test init', async () => {
|
|
13
|
-
const { result } = renderHook(() => useManageSubUnit(unit));
|
|
13
|
+
const { result } = renderHook(() => useManageSubUnit(unit.id));
|
|
14
14
|
expect(result.current.stations).toEqual([]);
|
|
15
|
-
expect(result.current.
|
|
16
|
-
expect(result.current.isRefreshing).toBeFalsy();
|
|
15
|
+
expect(result.current.refreshing).toBeFalsy();
|
|
17
16
|
});
|
|
18
17
|
|
|
19
18
|
it('Test onRefresh', async () => {
|
|
20
|
-
const { result } = renderHook(() => useManageSubUnit(unit));
|
|
19
|
+
const { result } = renderHook(() => useManageSubUnit(unit.id));
|
|
21
20
|
mock.onGet(API.UNIT.UNIT_DETAIL(unit?.id)).reply(200, [
|
|
22
21
|
{
|
|
23
22
|
id: 1,
|
|
@@ -55,15 +54,15 @@ describe('Test Manage Access', () => {
|
|
|
55
54
|
await act(async () => {
|
|
56
55
|
result.current.onRefresh();
|
|
57
56
|
});
|
|
58
|
-
expect(result.current.
|
|
57
|
+
expect(result.current.refreshing).toBeFalsy();
|
|
59
58
|
});
|
|
60
59
|
|
|
61
60
|
it('Test get unit failure', async () => {
|
|
62
|
-
const { result } = renderHook(() => useManageSubUnit(unit));
|
|
61
|
+
const { result } = renderHook(() => useManageSubUnit(unit.id));
|
|
63
62
|
mock.onGet(API.UNIT.UNIT_DETAIL(unit?.id)).reply(400);
|
|
64
63
|
await act(async () => {
|
|
65
64
|
result.current.onRefresh();
|
|
66
65
|
});
|
|
67
|
-
expect(result.current.
|
|
66
|
+
expect(result.current.refreshing).toBeFalsy();
|
|
68
67
|
});
|
|
69
68
|
});
|
|
@@ -2,34 +2,26 @@ import { useCallback, useState } from 'react';
|
|
|
2
2
|
import { axiosGet } from '../../../utils/Apis/axios';
|
|
3
3
|
import API from '../../../configs/API';
|
|
4
4
|
|
|
5
|
-
export default (
|
|
5
|
+
export default (unit_id) => {
|
|
6
6
|
const [stations, setStations] = useState([]);
|
|
7
|
-
const [
|
|
8
|
-
const [isRefresh, setRefresh] = useState(false);
|
|
7
|
+
const [refreshing, setRefreshing] = useState(false);
|
|
9
8
|
|
|
10
9
|
const fetchData = useCallback(async () => {
|
|
11
|
-
|
|
10
|
+
setRefreshing(true);
|
|
12
11
|
const { success, data } = await axiosGet(
|
|
13
|
-
API.UNIT.UNIT_DETAIL(
|
|
12
|
+
API.UNIT.UNIT_DETAIL(unit_id),
|
|
14
13
|
{},
|
|
15
14
|
true
|
|
16
15
|
);
|
|
17
16
|
if (success) {
|
|
18
17
|
setStations(data?.stations);
|
|
19
18
|
}
|
|
20
|
-
|
|
21
|
-
}, [
|
|
22
|
-
|
|
23
|
-
const onRefresh = useCallback(async () => {
|
|
24
|
-
setRefresh(true);
|
|
25
|
-
await fetchData();
|
|
26
|
-
setRefresh(false);
|
|
27
|
-
}, [fetchData]);
|
|
19
|
+
setRefreshing(false);
|
|
20
|
+
}, [unit_id]);
|
|
28
21
|
|
|
29
22
|
return {
|
|
30
23
|
stations,
|
|
31
|
-
|
|
32
|
-
onRefresh,
|
|
33
|
-
isLoading,
|
|
24
|
+
refreshing,
|
|
25
|
+
onRefresh: fetchData,
|
|
34
26
|
};
|
|
35
27
|
};
|
|
@@ -14,11 +14,7 @@ import Summaries from './Summaries';
|
|
|
14
14
|
|
|
15
15
|
import Text from '../../commons/Text';
|
|
16
16
|
import { API } from '../../configs';
|
|
17
|
-
import {
|
|
18
|
-
useBlockBackAndroid,
|
|
19
|
-
useBoolean,
|
|
20
|
-
useIsOwnerOfUnit,
|
|
21
|
-
} from '../../hooks/Common';
|
|
17
|
+
import { useBlockBack, useBoolean, useIsOwnerOfUnit } from '../../hooks/Common';
|
|
22
18
|
import { useFavorites } from './hook/useFavorites';
|
|
23
19
|
import { useUnitConnectRemoteDevices } from './hook/useUnitConnectRemoteDevices';
|
|
24
20
|
import { useValueEvaluations } from '../../hooks/IoT';
|
|
@@ -209,7 +205,7 @@ const UnitDetail = ({ route }) => {
|
|
|
209
205
|
[navigate]
|
|
210
206
|
);
|
|
211
207
|
|
|
212
|
-
|
|
208
|
+
useBlockBack(
|
|
213
209
|
isSuccessfullyConnected ? RouterHardware(Routes.Dashboard) : goBack
|
|
214
210
|
);
|
|
215
211
|
const user = useSCContextSelector((state) => state?.auth?.account?.user);
|
|
@@ -193,7 +193,7 @@ const ManageUnit = ({ route }) => {
|
|
|
193
193
|
<ButtonWrapper
|
|
194
194
|
onPress={goToManageSubUnit}
|
|
195
195
|
title={t('manage_sub_units')}
|
|
196
|
-
value={`${SensorNumbers}
|
|
196
|
+
value={`${SensorNumbers} ${t('sub_units').toLowerCase()}`}
|
|
197
197
|
accessibilityLabel={
|
|
198
198
|
AccessibilityLabel.MANAGE_UNIT_GO_TO_SUBUNIT
|
|
199
199
|
}
|
|
@@ -13,6 +13,7 @@ export default {
|
|
|
13
13
|
'Please note that your personal data including records of your control of the connected devices and services ' +
|
|
14
14
|
'will be shared with other members in the same unit.',
|
|
15
15
|
add_user_invitation_sent: 'Invitation sent',
|
|
16
|
+
check: 'Check',
|
|
16
17
|
cancel: 'Cancel',
|
|
17
18
|
max_value: 'Max value',
|
|
18
19
|
text_password: 'Password',
|
|
@@ -51,6 +52,7 @@ export default {
|
|
|
51
52
|
text_all_locations: 'All locations',
|
|
52
53
|
text_starred: 'Starred',
|
|
53
54
|
text_new_unit: 'New Unit',
|
|
55
|
+
text_unit: 'Unit',
|
|
54
56
|
text_good_morning: 'Good morning, {0}',
|
|
55
57
|
text_good_afternoon: 'Good afternoon, {0}',
|
|
56
58
|
text_good_evening: 'Good evening, {0}',
|
|
@@ -79,7 +81,7 @@ export default {
|
|
|
79
81
|
text_visibility: 'Visibility',
|
|
80
82
|
text_air_quality: 'Air Quality',
|
|
81
83
|
sub_units: 'Sub-units',
|
|
82
|
-
text_no_sub_unit_yet: "No
|
|
84
|
+
text_no_sub_unit_yet: "No Sub-Units yet. Tap '+’ to add new sub-units.",
|
|
83
85
|
text_no_units: 'No units',
|
|
84
86
|
text_last_7_days: 'Last 7 days',
|
|
85
87
|
text_average: 'Average',
|
|
@@ -411,8 +413,8 @@ export default {
|
|
|
411
413
|
choose_on_map: 'Choose on map',
|
|
412
414
|
plan_and_zoom_to_adjust: 'Plan and zoom to adjust',
|
|
413
415
|
add_remote_control: 'Add remote control',
|
|
414
|
-
manage_sub_unit: 'Manage
|
|
415
|
-
remove_sub_unit: 'Remove
|
|
416
|
+
manage_sub_unit: 'Manage Sub-Unit',
|
|
417
|
+
remove_sub_unit: 'Remove Sub-Unit',
|
|
416
418
|
text_ble_is_powered_on: 'Bluetooth is powered on',
|
|
417
419
|
current_wind_speed: 'Current Wind Speed',
|
|
418
420
|
history: 'History',
|
|
@@ -725,6 +727,13 @@ export default {
|
|
|
725
727
|
title_notification: 'Subject: “Warning”',
|
|
726
728
|
update_title_notification: 'Update title',
|
|
727
729
|
update_message_notification: 'Update warning content',
|
|
730
|
+
email_content: 'E-mail content',
|
|
731
|
+
email_to: 'E-mail to',
|
|
732
|
+
subject: 'Subject',
|
|
733
|
+
message: 'Message...',
|
|
734
|
+
no_email: 'No email address',
|
|
735
|
+
update_title_email: 'Update title',
|
|
736
|
+
update_message_email: 'Update warning content',
|
|
728
737
|
update_action: 'Update action',
|
|
729
738
|
updated_action_order: 'Updated action order',
|
|
730
739
|
message_notification:
|
|
@@ -978,7 +987,7 @@ export default {
|
|
|
978
987
|
alert_send_error: 'Send alert fail!',
|
|
979
988
|
unit_name: 'Unit name',
|
|
980
989
|
location: 'Location',
|
|
981
|
-
manage_sub_units: 'Manage Sub-
|
|
990
|
+
manage_sub_units: 'Manage Sub-Unit',
|
|
982
991
|
unit_wallpaper: 'Unit Wallpaper',
|
|
983
992
|
tap_to_change: 'Tap to change',
|
|
984
993
|
choose_location: 'Choose location',
|
|
@@ -1041,7 +1050,7 @@ export default {
|
|
|
1041
1050
|
rename_automate: 'Rename automate',
|
|
1042
1051
|
edit_sub_unit: 'Edit Sub-unit',
|
|
1043
1052
|
no_sub_unit_yet: 'No sub-unit yet.',
|
|
1044
|
-
'tap_+_to_add_new_sub_unit': 'Tap + to add new
|
|
1053
|
+
'tap_+_to_add_new_sub_unit': 'Tap + to add new Sub-Unit.',
|
|
1045
1054
|
go_to_automate_scripts: 'Go to automate scripts',
|
|
1046
1055
|
Script: 'Script',
|
|
1047
1056
|
'One-Tap': 'One-Tap',
|
|
@@ -1065,6 +1074,7 @@ export default {
|
|
|
1065
1074
|
send_email: 'Send e-mail',
|
|
1066
1075
|
send_app_notification: 'Send app notification',
|
|
1067
1076
|
delay_the_action: 'Delay the action',
|
|
1077
|
+
email_the_action: 'Send e-mail',
|
|
1068
1078
|
wait: 'Wait',
|
|
1069
1079
|
set_timeout_seconds: 'Set timeout (seconds)',
|
|
1070
1080
|
update_waiting_time: 'Update waiting time (seconds)',
|
|
@@ -1160,11 +1170,32 @@ export default {
|
|
|
1160
1170
|
connecting: 'Connecting',
|
|
1161
1171
|
connect_device: 'Connect Device',
|
|
1162
1172
|
connect: 'Connect',
|
|
1173
|
+
failed: 'Failed',
|
|
1174
|
+
other: 'Other',
|
|
1163
1175
|
server_error: 'Server Error',
|
|
1164
1176
|
add_gateway_success: 'Add gateway success',
|
|
1177
|
+
change_wifi: 'Change Wi-Fi',
|
|
1178
|
+
change_wifi_success: 'Change Wi-Fi success',
|
|
1179
|
+
change_wifi_failed: 'Change Wi-Fi failed',
|
|
1180
|
+
gateway_need_to_be_connected:
|
|
1181
|
+
'Gateway needs to be connected to make Wi-Fi changes',
|
|
1165
1182
|
set_network: 'Set network',
|
|
1166
|
-
select_wifi: 'Select your
|
|
1167
|
-
enter_wifi_password: 'Enter
|
|
1183
|
+
select_wifi: 'Select your Wi-Fi network',
|
|
1184
|
+
enter_wifi_password: 'Enter Wi-Fi password',
|
|
1185
|
+
enter_wifi_name_password: 'Enter Wi-Fi name and password',
|
|
1186
|
+
connect_wifi: 'Connect Wi-Fi',
|
|
1187
|
+
connect_to_wifi: 'Connect to Wi-Fi',
|
|
1188
|
+
please_enter_wifi_name: 'Please enter Wi-Fi name',
|
|
1189
|
+
please_enter_wifi_password: 'Please enter Wi-Fi password',
|
|
1190
|
+
password_must_be_at_least_8_characters:
|
|
1191
|
+
'Password must be at least 8 characters',
|
|
1192
|
+
connection_timeout: 'Connection timeout',
|
|
1193
|
+
you_have_successfully_connected_wifi:
|
|
1194
|
+
'You have successfully connected to the Wi-Fi name (SSID)',
|
|
1195
|
+
device_scaned: 'Device scaned',
|
|
1196
|
+
select_device_and_connect: 'Select a device and press connect',
|
|
1197
|
+
error_sending_data_to_local_device:
|
|
1198
|
+
'Error sending data to local device. Please try again.',
|
|
1168
1199
|
gateway_warning_content_1: 'To bring you good experiences, ',
|
|
1169
1200
|
gateway_warning_content_2: 'your device needs a permanent wifi connection.',
|
|
1170
1201
|
gateway_warning_content_3:
|
|
@@ -1302,6 +1333,8 @@ export default {
|
|
|
1302
1333
|
zigbee: 'Zigbee',
|
|
1303
1334
|
device_connect_remotely_to_the_gateway:
|
|
1304
1335
|
'Device connected remotely to the gateway',
|
|
1336
|
+
scan: 'Scan',
|
|
1337
|
+
device_connected_to_local_network: 'Device connected to the local network',
|
|
1305
1338
|
connect_wifi_asking:
|
|
1306
1339
|
"By continuing, {appName} needs to connect to the device's Wifi. A message will appear asking you to connect.",
|
|
1307
1340
|
previous: 'Previous',
|
|
@@ -1348,6 +1381,7 @@ export default {
|
|
|
1348
1381
|
connection_methods: 'Connection methods',
|
|
1349
1382
|
delete_gateway: 'Delete gateway',
|
|
1350
1383
|
connection_time: 'Connection time',
|
|
1384
|
+
board: 'Board',
|
|
1351
1385
|
device_id: 'Device id',
|
|
1352
1386
|
auth_token: 'Auth token',
|
|
1353
1387
|
activate_date: 'Activate date',
|
|
@@ -1486,7 +1520,11 @@ export default {
|
|
|
1486
1520
|
uri_invalid: 'URI invalid',
|
|
1487
1521
|
when_value_is: 'Activates when "{config_name}" value is',
|
|
1488
1522
|
template_not_supported: 'Widget "{template}" not yet supported',
|
|
1489
|
-
invited_user: 'Invited user
|
|
1523
|
+
invited_user: 'Invited user',
|
|
1490
1524
|
enter_value: 'Enter value',
|
|
1491
1525
|
enter_parameters: 'Enter parameters',
|
|
1526
|
+
rearrange_sub_unit_hint:
|
|
1527
|
+
'Press and hold the number and drag to rearrange the order of the Sub-Units',
|
|
1528
|
+
rearrange_sub_unit: 'Rearrange Sub-Unit',
|
|
1529
|
+
updated_sub_unit_order: 'Updated Sub-Units order successfully!',
|
|
1492
1530
|
};
|