@eohjsc/react-native-smart-city 0.7.8 → 0.7.10
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 +2 -1
- 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/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 +83 -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/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
|
@@ -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
|
};
|
|
@@ -93,6 +93,7 @@ export default {
|
|
|
93
93
|
'báo cho người dùng thay lõi.',
|
|
94
94
|
verify: 'Xác nhận',
|
|
95
95
|
text_new_unit: 'Địa điểm',
|
|
96
|
+
text_unit: 'Địa điểm',
|
|
96
97
|
text_sub_units: 'Khu vực',
|
|
97
98
|
is_equal: 'bằng',
|
|
98
99
|
is_below: 'dưới',
|
|
@@ -178,6 +179,7 @@ export default {
|
|
|
178
179
|
'bạn kiểm soát dịch vụ và các thiết bị được kết nối của từng khu vực ' +
|
|
179
180
|
'sẽ được chia sẻ với các thành viên khác cùng địa điểm.',
|
|
180
181
|
add_user_invitation_sent: 'Lời mời đã được gửi',
|
|
182
|
+
check: 'Kiểm tra',
|
|
181
183
|
text_temperature: 'Nhiệt độ',
|
|
182
184
|
text_wind: 'Gió',
|
|
183
185
|
text_rain: 'Mưa',
|
|
@@ -745,9 +747,14 @@ export default {
|
|
|
745
747
|
notifications: 'Thông báo',
|
|
746
748
|
notification: 'Thông báo',
|
|
747
749
|
send_notification: 'Gửi thông báo',
|
|
748
|
-
title_notification: '
|
|
750
|
+
title_notification: 'Tiêu đề: “Cảnh báo”',
|
|
749
751
|
update_title_notification: 'Cập nhật tiêu đề',
|
|
750
752
|
update_message_notification: 'Cập nhật nội dung cảnh báo',
|
|
753
|
+
email_content: 'Nội dung E-mail',
|
|
754
|
+
email_to: 'Gửi E-mail tới',
|
|
755
|
+
subject: 'Tiêu đè',
|
|
756
|
+
message: 'Tin nhắn...',
|
|
757
|
+
no_email: 'Không có địa chỉ email',
|
|
751
758
|
update_action: 'Cập nhật hành động',
|
|
752
759
|
updated_action_order: 'Đã cập nhật thứ tự hành động',
|
|
753
760
|
message_notification:
|
|
@@ -1161,10 +1168,29 @@ export default {
|
|
|
1161
1168
|
connecting: 'Đang kết nối',
|
|
1162
1169
|
connect_device: 'Kết nối thiết bị',
|
|
1163
1170
|
connect: 'Kết nối',
|
|
1171
|
+
failed: 'Thất bại',
|
|
1172
|
+
other: 'Khác',
|
|
1164
1173
|
server_error: 'Lỗi hệ thống',
|
|
1174
|
+
change_wifi: 'Thay đổi Wi-Fi',
|
|
1175
|
+
change_wifi_success: 'Thay đổi Wi-Fi thành công',
|
|
1176
|
+
change_wifi_failed: 'Thay đổi Wi-Fi thất bại',
|
|
1177
|
+
gateway_need_to_be_connected:
|
|
1178
|
+
'Gateway cần được kết nối để thực hiện thay đổi Wi-Fi',
|
|
1165
1179
|
set_network: 'Chọn mạng',
|
|
1166
|
-
select_wifi: 'Chọn mạng
|
|
1167
|
-
enter_wifi_password: 'Nhập mật khẩu
|
|
1180
|
+
select_wifi: 'Chọn mạng Wi-Fi của bạn',
|
|
1181
|
+
enter_wifi_password: 'Nhập mật khẩu Wi-Fi',
|
|
1182
|
+
enter_wifi_name_password: 'Nhập tên và mật khẩu Wi-Fi',
|
|
1183
|
+
connect_wifi: 'Kết nối Wi-Fi',
|
|
1184
|
+
connect_to_wifi: 'Kết nối đến Wi-Fi',
|
|
1185
|
+
please_enter_wifi_name: 'Vui lòng nhập tên Wi-Fi',
|
|
1186
|
+
please_enter_wifi_password: 'Vui lòng nhập mật khẩu Wi-Fi',
|
|
1187
|
+
password_must_be_at_least_8_characters: 'Mật khẩu phải có ít nhất 8 ký tự',
|
|
1188
|
+
connection_timeout: 'Kết nối đã hết thời gian',
|
|
1189
|
+
you_have_successfully_connected_wifi:
|
|
1190
|
+
'Bạn đã kết nối thành công với Wi-Fi có tên (SSID)',
|
|
1191
|
+
device_scaned: 'Thiết bị đã được quét',
|
|
1192
|
+
select_device_and_connect: 'Chọn thiết bị và nhấn kết nối',
|
|
1193
|
+
error_sending_data_to_local_device: 'Lỗi gửi dữ liệu đến thiết bị cục bộ',
|
|
1168
1194
|
gateway_warning_content_1: 'Để mang đến cho bạn những trải nghiệm tốt, ',
|
|
1169
1195
|
gateway_warning_content_2: 'thiết bị cần kết nối wifi thường trực.',
|
|
1170
1196
|
gateway_warning_content_3:
|
|
@@ -1305,6 +1331,8 @@ export default {
|
|
|
1305
1331
|
zigbee: 'Zigbee',
|
|
1306
1332
|
device_connect_remotely_to_the_gateway:
|
|
1307
1333
|
'Thiết bị được kết nối từ xa với gateway',
|
|
1334
|
+
scan: 'Quét',
|
|
1335
|
+
device_connected_to_local_network: 'Thiết bị được kết nối với mạng cục bộ',
|
|
1308
1336
|
connect_wifi_asking:
|
|
1309
1337
|
'Bằng việc tiếp tục, {appName} cần kết nối với Wifi của thiết bị. Một thông báo sẽ hiện lên và yêu cầu ' +
|
|
1310
1338
|
'bạn kết nối.',
|
|
@@ -1356,6 +1384,7 @@ export default {
|
|
|
1356
1384
|
connection_methods: 'Các phương thức kết nối',
|
|
1357
1385
|
delete_gateway: 'Xoá cửa ngõ',
|
|
1358
1386
|
connection_time: 'Thời gian kết nối',
|
|
1387
|
+
board: 'Board',
|
|
1359
1388
|
device_id: 'ID thiết bị',
|
|
1360
1389
|
auth_token: 'Mã xác thực',
|
|
1361
1390
|
activate_date: 'Ngày kích hoạt',
|
|
@@ -1497,7 +1526,11 @@ export default {
|
|
|
1497
1526
|
uri_invalid: 'URI không hợp lệ',
|
|
1498
1527
|
when_value_is: 'Kích hoạt khi giá trị "{config_name}"',
|
|
1499
1528
|
template_not_supported: 'Tiện ích "{template}" chưa được hỗ trợ',
|
|
1500
|
-
invited_user: 'Đã mời người dùng
|
|
1529
|
+
invited_user: 'Đã mời người dùng',
|
|
1501
1530
|
enter_value: 'Nhập giá trị',
|
|
1502
1531
|
enter_parameters: 'Nhập thông số',
|
|
1532
|
+
rearrange_sub_unit_hint:
|
|
1533
|
+
'Nhấn giữ vào số thứ tự và di chuyển để sắp xếp lại thứ tự các khu vực',
|
|
1534
|
+
rearrange_sub_unit: 'Sắp xếp lại các khu vực',
|
|
1535
|
+
updated_sub_unit_order: 'Đã cập nhật thứ tự các khu vực thành công!',
|
|
1503
1536
|
};
|
package/src/utils/Route/index.js
CHANGED
|
@@ -72,6 +72,7 @@ const Routes = {
|
|
|
72
72
|
ShareWifiPassword: 'ShareWifiPassword',
|
|
73
73
|
RenameNewDevices: 'RenameNewDevices',
|
|
74
74
|
ConnectingWifiGuide: 'ConnectingWifiGuide',
|
|
75
|
+
ScanDeviceLocal: 'ScanDeviceLocal',
|
|
75
76
|
|
|
76
77
|
UnitMemberList: 'UnitMemberList',
|
|
77
78
|
UpdateShareDevice: 'UpdateShareDevice',
|
|
@@ -137,6 +138,9 @@ const Routes = {
|
|
|
137
138
|
AddUnknownTypeSmart: 'AddUnknownTypeSmart',
|
|
138
139
|
SetupScriptNotify: 'SetupScriptNotify',
|
|
139
140
|
SetupScriptDelay: 'SetupScriptDelay',
|
|
141
|
+
SetupScriptEmail: 'SetupScriptEmail',
|
|
142
|
+
SetupScriptReceiverEmail: 'SetupScriptReceiverEmail',
|
|
143
|
+
UpdateReceiverEmailScript: 'UpdateReceiverEmailScript',
|
|
140
144
|
ScenarioName: 'ScenarioName',
|
|
141
145
|
ValueChangeName: 'ValueChangeName',
|
|
142
146
|
AllCamera: 'AllCamera',
|
|
@@ -175,6 +179,8 @@ const Routes = {
|
|
|
175
179
|
Gateway: 'Gateway',
|
|
176
180
|
GatewayDetail: 'GatewayDetail',
|
|
177
181
|
GatewayInfo: 'GatewayInfo',
|
|
182
|
+
GatewayWifi: 'GatewayWifi',
|
|
183
|
+
Successfully: 'Successfully',
|
|
178
184
|
DeviceGatewayInfo: 'DeviceGatewayInfo',
|
|
179
185
|
GatewayConnectionMethods: 'GatewayConnectionMethods',
|
|
180
186
|
DeviceZigbeeDetail: 'DeviceZigbeeDetail',
|
|
@@ -198,6 +204,7 @@ const Routes = {
|
|
|
198
204
|
DetailConfigActionInternal: 'DetailConfigActionInternal',
|
|
199
205
|
DeviceInternalDetail: 'DeviceInternalDetail',
|
|
200
206
|
ChangePosition: 'ChangePosition',
|
|
207
|
+
RearrangeSubUnit: 'RearrangeSubUnit',
|
|
201
208
|
};
|
|
202
209
|
|
|
203
210
|
export default Routes;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import renderer, { act } from 'react-test-renderer';
|
|
3
|
-
import { Text } from 'react-native';
|
|
4
|
-
import AccountItem from '../AccountItem';
|
|
5
|
-
|
|
6
|
-
describe('Test AccountItem', () => {
|
|
7
|
-
let wrapper;
|
|
8
|
-
it('create AccountItem invalid', async () => {
|
|
9
|
-
await act(async () => {
|
|
10
|
-
wrapper = renderer.create(
|
|
11
|
-
<AccountItem key={'account'} account={'account'} />
|
|
12
|
-
);
|
|
13
|
-
});
|
|
14
|
-
const instance = wrapper.root;
|
|
15
|
-
const text = instance.findAllByType(Text);
|
|
16
|
-
expect(text.length).toBe(0);
|
|
17
|
-
});
|
|
18
|
-
it('create AccountItem account', async () => {
|
|
19
|
-
await act(async () => {
|
|
20
|
-
wrapper = renderer.create(
|
|
21
|
-
<AccountItem
|
|
22
|
-
key={'account'}
|
|
23
|
-
account={{ name: 'name', phone_number: '098xxxx' }}
|
|
24
|
-
/>
|
|
25
|
-
);
|
|
26
|
-
});
|
|
27
|
-
const instance = wrapper.root;
|
|
28
|
-
const text = instance.findAllByType(Text);
|
|
29
|
-
expect(text.length).toBe(2);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { useIsFocused } from '@react-navigation/native';
|
|
2
|
-
import { useCallback, useEffect } from 'react';
|
|
3
|
-
import { BackHandler } from 'react-native';
|
|
4
|
-
|
|
5
|
-
export const useBlockBackAndroid = (actionBack) => {
|
|
6
|
-
const focused = useIsFocused();
|
|
7
|
-
const blockBack = useCallback(() => {
|
|
8
|
-
actionBack && actionBack();
|
|
9
|
-
return true;
|
|
10
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11
|
-
}, []);
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
if (focused) {
|
|
14
|
-
BackHandler.addEventListener('hardwareBackPress', blockBack);
|
|
15
|
-
} else {
|
|
16
|
-
BackHandler.removeEventListener('hardwareBackPress', blockBack);
|
|
17
|
-
}
|
|
18
|
-
return () =>
|
|
19
|
-
BackHandler.removeEventListener('hardwareBackPress', blockBack);
|
|
20
|
-
}, [blockBack, focused]);
|
|
21
|
-
};
|