@eohjsc/react-native-smart-city 0.7.8 → 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.
Files changed (85) hide show
  1. package/assets/images/AddNewDevice/add-scan-device-icon.svg +13 -0
  2. package/assets/images/Email.svg +9 -0
  3. package/assets/images/lan.svg +3 -0
  4. package/assets/images/wifi-open.svg +3 -0
  5. package/package.json +2 -1
  6. package/src/commons/ActionGroup/StatesGridActionTemplate.js +7 -3
  7. package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +7 -3
  8. package/src/commons/AlertAction/index.js +1 -0
  9. package/src/commons/Auth/AccountItem.js +17 -3
  10. package/src/commons/Auth/AccountList.js +3 -7
  11. package/src/commons/ConnectWifi/__test__/ConnectWifi.test.js +373 -0
  12. package/src/commons/ConnectWifi/index.js +201 -0
  13. package/src/commons/ConnectWifi/styles.js +69 -0
  14. package/src/commons/Form/TextInputPassword.js +1 -1
  15. package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +6 -2
  16. package/src/configs/API.js +12 -0
  17. package/src/configs/AccessibilityLabel.js +7 -0
  18. package/src/configs/Constants.js +1 -0
  19. package/src/hooks/Common/index.js +2 -2
  20. package/src/hooks/Common/useBlockBack.js +36 -0
  21. package/src/hooks/useMqtt.js +10 -5
  22. package/src/navigations/AddGatewayStack.js +2 -0
  23. package/src/navigations/AllGatewayStack.js +4 -0
  24. package/src/navigations/Main.js +2 -2
  25. package/src/navigations/UnitStack.js +32 -0
  26. package/src/screens/AddNewGateway/ConnectingWifiDevice.js +7 -6
  27. package/src/screens/AddNewGateway/ScanDeviceLocal.js +267 -0
  28. package/src/screens/AddNewGateway/ScanDeviceLocalStyles.js +58 -0
  29. package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +10 -2
  30. package/src/screens/AddNewGateway/SelectDeviceType.js +19 -2
  31. package/src/screens/AddNewGateway/__test__/ScanDeviceLocal.test.js +475 -0
  32. package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +2 -2
  33. package/src/screens/AddNewGateway/configs/API.js +8 -0
  34. package/src/screens/AddNewGateway/hooks/useConnectDevice.js +59 -0
  35. package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +58 -1
  36. package/src/screens/AllGateway/GatewayInfo/index.js +8 -6
  37. package/src/screens/AllGateway/GatewayWifi/__test__/index.test.js +319 -0
  38. package/src/screens/AllGateway/GatewayWifi/index.js +107 -0
  39. package/src/screens/AllGateway/Successfully/__test__/index.test.js +77 -0
  40. package/src/screens/AllGateway/Successfully/index.js +66 -0
  41. package/src/screens/AllGateway/Successfully/styles.js +35 -0
  42. package/src/screens/AllGateway/components/Information/index.js +17 -1
  43. package/src/screens/AllGateway/components/RowItem/index.js +12 -1
  44. package/src/screens/AllGateway/hooks/__test__/index.test.js +18 -0
  45. package/src/screens/AllGateway/hooks/useGateway.js +13 -0
  46. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +3 -3
  47. package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +79 -0
  48. package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +166 -0
  49. package/src/screens/Automate/AddNewAction/Styles/SetupScriptEmailStyles.js +37 -0
  50. package/src/screens/Automate/AddNewAction/Styles/SetupScriptReceiverEmailStyles.js +79 -0
  51. package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +1 -1
  52. package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -5
  53. package/src/screens/Automate/AddNewAction/__test__/SetupScriptEmail.test.js +76 -0
  54. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +105 -0
  55. package/src/screens/Automate/EditActionsList/Styles/UpdateReceiverEmailScriptStyles.js +78 -0
  56. package/src/screens/Automate/EditActionsList/UpdateEmailScript.js +80 -0
  57. package/src/screens/Automate/EditActionsList/UpdateReceiverEmailScript.js +179 -0
  58. package/src/screens/Automate/EditActionsList/__tests__/UpdateEmailScript.test.js +81 -0
  59. package/src/screens/Automate/EditActionsList/__tests__/UpdateReceiverEmailScript.test.js +83 -0
  60. package/src/screens/Automate/EditActionsList/__tests__/index.test.js +38 -5
  61. package/src/screens/Automate/EditActionsList/index.js +59 -2
  62. package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +20 -0
  63. package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +5 -3
  64. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +127 -21
  65. package/src/screens/Automate/ScriptDetail/index.js +57 -14
  66. package/src/screens/SharedUnit/index.js +2 -2
  67. package/src/screens/Sharing/SelectUser.js +47 -47
  68. package/src/screens/Sharing/__test__/SelectUser.test.js +57 -103
  69. package/src/screens/SubUnit/ManageSubUnit.js +94 -90
  70. package/src/screens/SubUnit/ManageSubUnitStyles.js +4 -6
  71. package/src/screens/SubUnit/RearrageSubUnit.js +90 -0
  72. package/src/screens/SubUnit/RearrrageSubUnitStyle.js +65 -0
  73. package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +35 -19
  74. package/src/screens/SubUnit/__test__/RearrangeSubUnit.test.js +129 -0
  75. package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +6 -7
  76. package/src/screens/SubUnit/hooks/useManageSubUnit.js +8 -16
  77. package/src/screens/Unit/Detail.js +2 -6
  78. package/src/screens/Unit/ManageUnit.js +1 -1
  79. package/src/utils/Functions/__test__/ShortEmail.test.js +5 -0
  80. package/src/utils/I18n/translations/en.js +46 -8
  81. package/src/utils/I18n/translations/vi.js +37 -4
  82. package/src/utils/Route/index.js +7 -0
  83. package/src/commons/Auth/__test__/AccountItem.test.js +0 -31
  84. package/src/hooks/Common/useBlockBackAndroid.js +0 -21
  85. 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(2);
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: { id: 1, name: 'sensor' },
53
- unit: {
54
- id: 1,
55
- name: 'unit 1',
56
- },
55
+ station: data[0],
56
+ unit: route.params.unit,
57
57
  },
58
- screen: 'EditSubUnit',
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.isLoading).toBeFalsy();
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.isRefreshing).toBeFalsy();
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.isRefreshing).toBeFalsy();
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 (unit) => {
5
+ export default (unit_id) => {
6
6
  const [stations, setStations] = useState([]);
7
- const [isLoading, setIsLoading] = useState(false);
8
- const [isRefresh, setRefresh] = useState(false);
7
+ const [refreshing, setRefreshing] = useState(false);
9
8
 
10
9
  const fetchData = useCallback(async () => {
11
- setIsLoading(true);
10
+ setRefreshing(true);
12
11
  const { success, data } = await axiosGet(
13
- API.UNIT.UNIT_DETAIL(unit?.id),
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
- setIsLoading(false);
21
- }, [unit]);
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
- isRefresh,
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
- useBlockBackAndroid(
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} sub-units`}
196
+ value={`${SensorNumbers} ${t('sub_units').toLowerCase()}`}
197
197
  accessibilityLabel={
198
198
  AccessibilityLabel.MANAGE_UNIT_GO_TO_SUBUNIT
199
199
  }
@@ -4,3 +4,8 @@ it('Test shortEmailName function', async () => {
4
4
  const data = shortEmailName('emailExample@gmail.com');
5
5
  expect(data).toEqual('emailExample');
6
6
  });
7
+
8
+ it('Test email null', async () => {
9
+ const data = shortEmailName(null);
10
+ expect(data).toEqual('');
11
+ });
@@ -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 sub-units yet. Tap '+’ to add new sub-units.",
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 sub-unit',
415
- remove_sub_unit: 'Remove sub-unit',
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-units',
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 sub-unit.',
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 wifi network',
1167
- enter_wifi_password: 'Enter wifi password',
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 {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: 'Chủ đề: “Cảnh báo”',
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 wifi của bạn',
1167
- enter_wifi_password: 'Nhập mật khẩu wifi',
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 {user}',
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
  };
@@ -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
- };