@eohjsc/react-native-smart-city 0.2.96 → 0.2.97

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eohjsc/react-native-smart-city",
3
3
  "title": "React Native Smart Home",
4
- "version": "0.2.96",
4
+ "version": "0.2.97",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -81,10 +81,11 @@
81
81
  "eslint-plugin-react": "^7.21.5",
82
82
  "eslint-plugin-react-native": "^3.10.0",
83
83
  "factory-girl": "^5.0.4",
84
+ "husky": "^8.0.1",
84
85
  "jest": "^26.6.3",
85
86
  "jest-circus": "^26.6.3",
86
87
  "jetifier": "^1.6.6",
87
- "lint-staged": "^8.2.1",
88
+ "lint-staged": "^12.4.1",
88
89
  "metro-react-native-babel-preset": "^0.66.2",
89
90
  "node-html-parser": "^2.0.2",
90
91
  "react": "17.0.2",
@@ -97,6 +98,7 @@
97
98
  "dependencies": {
98
99
  "@ant-design/icons-react-native": "^2.2.1",
99
100
  "@ant-design/react-native": "^4.0.5",
101
+ "@babel/helper-environment-visitor": "^7.16.7",
100
102
  "@eohjsc/highcharts": "^1.0.8",
101
103
  "@eohjsc/react-native-keyboard-aware-scroll-view": "^0.9.5",
102
104
  "@formatjs/intl-getcanonicallocales": "^1.4.5",
@@ -209,5 +211,15 @@
209
211
  "bugs": {
210
212
  "url": "https://github.com/github_account/react-native-smart-city/issues"
211
213
  },
212
- "homepage": "https://github.com/github_account/react-native-smart-city#readme"
214
+ "homepage": "https://github.com/github_account/react-native-smart-city#readme",
215
+ "husky": {
216
+ "hooks": {
217
+ "pre-commit": "lint-staged"
218
+ }
219
+ },
220
+ "lint-staged": {
221
+ "*.{js, ts}": [
222
+ "yarn lint"
223
+ ]
224
+ }
213
225
  }
File without changes
File without changes
@@ -10,7 +10,7 @@ import { axiosPost } from '../../utils/Apis/axios';
10
10
  import { API, Colors } from '../../configs';
11
11
  import styles from './styles';
12
12
  import DeviceItem from './DeviceItem/DeviceItem';
13
- import Connecting from '../Connecting ';
13
+ import Connecting from '../Connecting';
14
14
  import { useSCContextSelector } from '../../context';
15
15
 
16
16
  const ConnectingProcess = ({ route }) => {
@@ -234,7 +234,7 @@ const HistoryChart = memo(
234
234
  )}
235
235
  <DateTimePickerModal
236
236
  isVisible={eventPicker.showModalStart}
237
- date={eventPicker.startTime.toDate()}
237
+ date={eventPicker.startTime.valueOf()}
238
238
  mode={formatType || 'datetime'}
239
239
  onConfirm={onConfirmStart}
240
240
  onCancel={onCancel}
@@ -242,7 +242,7 @@ const HistoryChart = memo(
242
242
  />
243
243
  <DateTimePickerModal
244
244
  isVisible={eventPicker.showModalEnd}
245
- date={eventPicker.endTime.toDate()}
245
+ date={eventPicker.endTime.valueOf()}
246
246
  mode={formatType || 'datetime'}
247
247
  onConfirm={onConfirmEnd}
248
248
  onCancel={onCancel}
@@ -0,0 +1,59 @@
1
+ import React, { memo, useCallback, useMemo } from 'react';
2
+ import { View } from 'react-native';
3
+ import Modal from 'react-native-modal';
4
+ import { useNavigation } from '@react-navigation/native';
5
+
6
+ import t from '../../hooks/Common/useTranslations';
7
+ import Text from '../Text';
8
+ import { Colors } from '../../configs';
9
+ import { styles } from './styles';
10
+
11
+ const PreventAccess = memo(({ headerBodyText, visible, hidePreventAccess }) => {
12
+ const { goBack } = useNavigation();
13
+
14
+ const dataText = useMemo(() => {
15
+ return {
16
+ headerText: t('note'),
17
+ bodyText: t('This {name} was removed!', {
18
+ name: headerBodyText ? headerBodyText : '',
19
+ }),
20
+ endOfText: t('back'),
21
+ };
22
+ }, [headerBodyText]);
23
+
24
+ const handleBackPress = useCallback(() => {
25
+ hidePreventAccess();
26
+ goBack();
27
+ }, [goBack, hidePreventAccess]);
28
+
29
+ const handleDonePopup = useCallback(() => {
30
+ goBack();
31
+ hidePreventAccess();
32
+ }, [goBack, hidePreventAccess]);
33
+
34
+ return (
35
+ <Modal
36
+ isVisible={visible}
37
+ transparent={true}
38
+ onBackButtonPress={handleBackPress}
39
+ style={styles.container}
40
+ >
41
+ <View style={styles.popoverStyle}>
42
+ <View style={styles.actionTextWrap}>
43
+ <Text size={17} bold color={Colors.Gray9} style={styles.textHeader}>
44
+ {dataText?.headerText}
45
+ </Text>
46
+ <Text type="H4" color={Colors.Gray8} style={styles.textNotification}>
47
+ {dataText?.bodyText}
48
+ </Text>
49
+ </View>
50
+ <View style={styles.endOfText}>
51
+ <Text size={16} bold color={Colors.Primary} onPress={handleDonePopup}>
52
+ {dataText?.endOfText}
53
+ </Text>
54
+ </View>
55
+ </View>
56
+ </Modal>
57
+ );
58
+ });
59
+ export default PreventAccess;
@@ -0,0 +1,33 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ import { Colors } from '../../configs';
4
+
5
+ export const styles = StyleSheet.create({
6
+ container: {
7
+ flex: 1,
8
+ },
9
+ popoverStyle: {
10
+ flex: 1,
11
+ width: '100%',
12
+ backgroundColor: Colors.White,
13
+ position: 'absolute',
14
+ borderRadius: 10,
15
+ },
16
+ actionTextWrap: {
17
+ marginTop: 14,
18
+ marginHorizontal: 20,
19
+ },
20
+ textHeader: {
21
+ marginVertical: 10,
22
+ },
23
+ textNotification: {
24
+ lineHeight: 20,
25
+ },
26
+ endOfText: {
27
+ flexDirection: 'row',
28
+ justifyContent: 'flex-end',
29
+ marginTop: 5,
30
+ marginBottom: 20,
31
+ marginRight: 20,
32
+ },
33
+ });
@@ -201,8 +201,22 @@ function getServiceName(message) {
201
201
  return serviceSplit.join('_');
202
202
  }
203
203
 
204
+ async function sendCommandSingleAction(connection, ghAction, data) {
205
+ const { message } = ghAction || {};
206
+ const name = getServiceName(message);
207
+
208
+ if (name && data) {
209
+ message.service_data[name] = data;
210
+ }
211
+
212
+ await connection.sendMessagePromise(message);
213
+ }
214
+
204
215
  export async function sendCommandOverGoogleHome(sensor, action, data) {
205
- if (!action.googlehome_actions || !action.googlehome_actions.length) {
216
+ if (
217
+ !(action.googlehome_actions && action.googlehome_actions.length) &&
218
+ !action.googlehome_action
219
+ ) {
206
220
  return;
207
221
  }
208
222
 
@@ -212,20 +226,19 @@ export async function sendCommandOverGoogleHome(sensor, action, data) {
212
226
  return;
213
227
  }
214
228
 
215
- for (let i = 0; i < action.googlehome_actions.length; i++) {
216
- const ghAction = action.googlehome_actions[i];
217
- const { message } = ghAction;
218
- const name = getServiceName(ghAction.message);
219
-
220
- if (name && data) {
221
- message.service_data[name] = data;
229
+ if (action.googlehome_actions) {
230
+ for (let i = 0; i < action.googlehome_actions.length; i++) {
231
+ await sendCommandSingleAction(
232
+ connection,
233
+ action.googlehome_actions[i],
234
+ data
235
+ );
222
236
  }
223
-
224
- await connection.sendMessagePromise(message);
237
+ } else if (action.googlehome_action) {
238
+ await sendCommandSingleAction(connection, action.googlehome_action, data);
225
239
  }
226
240
 
227
241
  const { success } = await axiosPost(API.SENSOR.ACTIVITY_LOG(), {
228
- sensor_id: sensor.id,
229
242
  action_id: action.id,
230
243
  message: 'Trigger by user action with google home',
231
244
  });
@@ -75,6 +75,9 @@ describe('Remote Control Google Home', () => {
75
75
  message: 'message',
76
76
  },
77
77
  ],
78
+ googlehome_action: {
79
+ message: 'message',
80
+ },
78
81
  };
79
82
 
80
83
  const response = {
@@ -223,6 +226,35 @@ describe('Remote Control Google Home', () => {
223
226
  });
224
227
  });
225
228
 
229
+ it('Send command over google home action googlehome_action one to one', async () => {
230
+ action.googlehome_actions = null;
231
+ action.googlehome_action.message = {
232
+ type: 'call_service',
233
+ domain: 'climate',
234
+ service: 'set_temperature',
235
+ service_data: {
236
+ temperature: 0,
237
+ entity_id: 'climate.dqsmart_0108f6cdde',
238
+ },
239
+ id: 20,
240
+ };
241
+
242
+ axios.post.mockImplementation(async () => {
243
+ return response;
244
+ });
245
+ await googleHomeConnect(options);
246
+ await sendCommandOverGoogleHome(sensor, action, 19);
247
+
248
+ action.googlehome_action.message.service_data.temperature = 19;
249
+ expect(connection.sendMessagePromise).toBeCalledWith(
250
+ action.googlehome_action.message
251
+ );
252
+ expect(axios.post).toHaveBeenCalledWith(API.SENSOR.ACTIVITY_LOG(), {
253
+ action_id: 1,
254
+ message: 'Trigger by user action with google home',
255
+ });
256
+ });
257
+
226
258
  it('Send command over google home that not connected', async () => {
227
259
  await googleHomeConnect(options);
228
260
  await sendCommandOverGoogleHome({ chip_id: 2 }, action);
@@ -37,6 +37,7 @@ const SelectSensorDevices = memo(({ route }) => {
37
37
  const [selectedDevice, setSelectedDevice] = useState();
38
38
  const { navigate, dispatch, goBack } = useNavigation();
39
39
  const isSelectSensor = title === AUTOMATE_SELECT.SELECT_SENSOR;
40
+ const [loading, setLoading] = useState(true);
40
41
 
41
42
  const onSnapToItem = useCallback(
42
43
  (item, index) => {
@@ -83,6 +84,7 @@ const SelectSensorDevices = memo(({ route }) => {
83
84
  }
84
85
  }
85
86
  );
87
+ setLoading(false);
86
88
  }, [automate.sensor_id, isSelectSensor, unit]);
87
89
 
88
90
  useEffect(() => {
@@ -162,6 +164,9 @@ const SelectSensorDevices = memo(({ route }) => {
162
164
  // eslint-disable-next-line react-hooks/exhaustive-deps
163
165
  [route.params]
164
166
  );
167
+ if (loading) {
168
+ return null;
169
+ }
165
170
 
166
171
  return (
167
172
  <View style={styles.wrap}>
@@ -175,7 +180,7 @@ const SelectSensorDevices = memo(({ route }) => {
175
180
  {t(title)}
176
181
  </Text>
177
182
 
178
- {listStation ? (
183
+ {listStation.length ? (
179
184
  <NavBar
180
185
  listStation={listStation}
181
186
  listMenuItem={listMenuItem}
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React from 'react';
2
2
  import renderer, { act } from 'react-test-renderer';
3
3
  import axios from 'axios';
4
4
 
@@ -25,12 +25,10 @@ jest.mock('@react-navigation/native', () => {
25
25
  };
26
26
  });
27
27
 
28
- const mockSetState = jest.fn();
29
28
  jest.mock('react', () => {
30
29
  return {
31
30
  ...jest.requireActual('react'),
32
31
  memo: (x) => x,
33
- useState: jest.fn((init) => [init, mockSetState]),
34
32
  };
35
33
  });
36
34
 
@@ -49,28 +47,27 @@ describe('Test SelectSensorDevices', () => {
49
47
  scriptName: 'scriptName test',
50
48
  },
51
49
  };
50
+ const response = {
51
+ status: 200,
52
+ success: true,
53
+ data: [
54
+ {
55
+ id: 1,
56
+ name: 'Device 1',
57
+ sensors: [
58
+ { id: 1, name: 'sensor' },
59
+ { id: 2, name: 'sensor' },
60
+ ],
61
+ },
62
+ ],
63
+ };
52
64
 
53
65
  beforeEach(() => {
54
66
  axios.get.mockClear();
55
67
  mockedNavigate.mockClear();
56
- mockSetState.mockClear();
57
68
  });
58
69
 
59
70
  test('fetch Device success', async () => {
60
- const response = {
61
- status: 200,
62
- success: true,
63
- data: [
64
- {
65
- id: 1,
66
- name: 'Device 1',
67
- sensors: [
68
- { id: 1, name: 'sensor' },
69
- { id: 2, name: 'sensor' },
70
- ],
71
- },
72
- ],
73
- };
74
71
  axios.get.mockImplementation(async () => {
75
72
  return response;
76
73
  });
@@ -78,12 +75,17 @@ describe('Test SelectSensorDevices', () => {
78
75
  await act(async () => {
79
76
  tree = renderer.create(wrapComponent(route));
80
77
  });
78
+ const instance = tree.root;
79
+ const navBar = instance.findByType(NavBar);
81
80
 
82
81
  expect(axios.get).toHaveBeenCalledWith(API.UNIT.DEVICE_CONTROL(1), {});
83
- expect(mockSetState).toHaveBeenCalledTimes(3);
82
+ expect(navBar.props.listStation).toHaveLength(1);
84
83
  });
85
84
 
86
85
  test('onPress continue', async () => {
86
+ axios.get.mockImplementation(async () => {
87
+ return response;
88
+ });
87
89
  await act(async () => {
88
90
  tree = renderer.create(wrapComponent(route));
89
91
  });
@@ -97,23 +99,9 @@ describe('Test SelectSensorDevices', () => {
97
99
  });
98
100
 
99
101
  test('test onPressDevice', async () => {
100
- const data = [
101
- {
102
- id: 1,
103
- name: 'Device 1',
104
- sensors: [
105
- { id: 1, name: 'sensor' },
106
- { id: 2, name: 'sensor' },
107
- ],
108
- },
109
- ];
110
- const mockSetSelectedDevice = jest.fn();
111
- useState.mockImplementationOnce((init) => [init, mockSetState]);
112
- useState.mockImplementationOnce((init) => [init, mockSetState]);
113
- useState.mockImplementationOnce((init) => [init, mockSetState]);
114
- useState.mockImplementationOnce((init) => [data, mockSetState]);
115
- useState.mockImplementationOnce((init) => [false, mockSetSelectedDevice]);
116
-
102
+ axios.get.mockImplementation(async () => {
103
+ return response;
104
+ });
117
105
  await act(async () => {
118
106
  tree = renderer.create(wrapComponent(route));
119
107
  });
@@ -124,67 +112,18 @@ describe('Test SelectSensorDevices', () => {
124
112
  act(() => {
125
113
  device[0].props.onPress({ id: 1, name: 'sensor' });
126
114
  });
127
- expect(mockSetSelectedDevice).toHaveBeenCalledWith({
128
- id: 1,
129
- name: 'sensor',
130
- });
131
- });
132
-
133
- test('test onPressDevice false', async () => {
134
- const data = [
135
- {
136
- id: 1,
137
- name: 'Device 1',
138
- sensors: [
139
- { id: 1, name: 'sensor' },
140
- { id: 2, name: 'sensor' },
141
- ],
142
- },
143
- ];
144
- const mockSetSelectedDevice = jest.fn();
145
- useState.mockImplementationOnce((init) => [init, mockSetState]);
146
- useState.mockImplementationOnce((init) => [init, mockSetState]);
147
- useState.mockImplementationOnce((init) => [init, mockSetState]);
148
- useState.mockImplementationOnce((init) => [data, mockSetState]);
149
- useState.mockImplementationOnce((init) => [
150
- { id: 1, name: 'sensor' },
151
- mockSetSelectedDevice,
152
- ]);
153
-
154
- await act(async () => {
155
- tree = renderer.create(wrapComponent(route));
156
- });
157
- const instance = tree.root;
158
- const device = instance.findAllByType(Device);
159
- expect(device).toHaveLength(2);
115
+ expect(device[0].props.isSelectDevice).toEqual(true);
160
116
 
161
117
  act(() => {
162
118
  device[0].props.onPress({ id: 1, name: 'sensor' });
163
119
  });
164
- expect(mockSetSelectedDevice).toHaveBeenCalledWith(false);
120
+ expect(device[0].props.isSelectDevice).toEqual(false);
165
121
  });
166
122
 
167
123
  test('test onSnapItem', async () => {
168
- const data = [
169
- {
170
- id: 1,
171
- name: 'Device 1',
172
- sensors: [
173
- { id: 1, name: 'sensor' },
174
- { id: 2, name: 'sensor' },
175
- ],
176
- },
177
- ];
178
- const listMenu = data.map((item, index) => ({
179
- text: item.name,
180
- station: item,
181
- index: index,
182
- }));
183
- const mockSetIndexStation = jest.fn();
184
- useState.mockImplementationOnce((init) => [listMenu, mockSetState]);
185
- useState.mockImplementationOnce((init) => [init, mockSetState]);
186
- useState.mockImplementationOnce((init) => [init, mockSetIndexStation]);
187
- useState.mockImplementationOnce((init) => [data, mockSetState]);
124
+ axios.get.mockImplementation(async () => {
125
+ return response;
126
+ });
188
127
 
189
128
  await act(async () => {
190
129
  tree = renderer.create(wrapComponent(route));
@@ -195,10 +134,13 @@ describe('Test SelectSensorDevices', () => {
195
134
  act(() => {
196
135
  navBar.props.onSnapToItem({ id: 1, name: 'sensor' }, 0);
197
136
  });
198
-
199
- expect(mockSetIndexStation).toBeCalledWith(0);
137
+ expect(navBar.props.indexStation).toEqual(0);
200
138
  });
139
+
201
140
  test('test onPressClose user already has an automateId', async () => {
141
+ axios.get.mockImplementation(async () => {
142
+ return response;
143
+ });
202
144
  await act(async () => {
203
145
  tree = renderer.create(wrapComponent(route));
204
146
  });
@@ -26,7 +26,7 @@ import Routes from '../../../utils/Route';
26
26
  import { SCContext } from '../../../context';
27
27
  import { Action } from '../../../context/actionType';
28
28
  import { TESTID } from '../../../configs/Constants';
29
- import Connecting from '../../../commons/Connecting ';
29
+ import Connecting from '../../../commons/Connecting';
30
30
 
31
31
  const isIos = Platform.OS === 'ios';
32
32
  const isAndroid = Platform.OS === 'android';
@@ -47,6 +47,7 @@ import { EmergencyCountdown } from './components/EmergencyCountdown';
47
47
  import { SensorConnectStatusViewHeader } from './components/SensorConnectStatusViewHeader';
48
48
  import { useDisconnectedDevice } from './hooks/useDisconnectedDevice';
49
49
  import { Card } from '../../commons/CardShadow';
50
+ import PreventAccess from '../../commons/PreventAccess';
50
51
 
51
52
  const DeviceDetail = ({ route }) => {
52
53
  const t = useTranslations();
@@ -73,6 +74,8 @@ const DeviceDetail = ({ route }) => {
73
74
  const { isOwner } = useIsOwnerOfUnit(unit?.user_id);
74
75
  const [sensorName, setSensorName] = useState(sensor?.name);
75
76
  const [lockShowing, acquireLockShowing, releaseLockShowing] = useBoolean();
77
+ const [showPreventAccess, setShowPreventAccess, setHidePreventAccess] =
78
+ useBoolean(false);
76
79
  const [showWindDirection, setShowWindDirection] = useState(false);
77
80
  const [loading, setLoading] = useState({
78
81
  isConnected: true,
@@ -142,7 +145,9 @@ const DeviceDetail = ({ route }) => {
142
145
  }, [currentUserId, unit]);
143
146
 
144
147
  const fetchUnitDetail = useCallback(async () => {
145
- const { success, data } = await axiosGet(API.UNIT.UNIT_DETAIL(unitId));
148
+ const { success, data } = await axiosGet(API.UNIT.UNIT_DETAIL(unitId), {
149
+ headers: { 'Cache-Control': 'no-cache' },
150
+ });
146
151
  if (success) {
147
152
  setUnit(data);
148
153
  }
@@ -155,15 +160,17 @@ const DeviceDetail = ({ route }) => {
155
160
  }, [fetchUnitDetail, unitId, unitData]);
156
161
 
157
162
  const fetchSensorDetail = useCallback(async () => {
158
- const { success, data } = await axiosGet(
163
+ const { success, data, resp_status } = await axiosGet(
159
164
  API.SENSOR.SENSOR_DETAIL(sensorId)
160
165
  );
161
166
  if (success) {
162
167
  setSensor(data);
163
168
  setSensorName(data.name);
164
169
  setStation(data.station);
170
+ } else if (resp_status === 404) {
171
+ setShowPreventAccess();
165
172
  }
166
- }, [sensorId]);
173
+ }, [sensorId, setShowPreventAccess]);
167
174
 
168
175
  useEffect(() => {
169
176
  if (sensorId && !sensorData) {
@@ -500,6 +507,7 @@ const DeviceDetail = ({ route }) => {
500
507
  return isFlag;
501
508
  }, [display]);
502
509
  // replace isConnected=True to see template
510
+
503
511
  const renderSensorConnected = () => {
504
512
  return (
505
513
  <SensorConnectStatusViewHeader
@@ -691,6 +699,11 @@ const DeviceDetail = ({ route }) => {
691
699
  unit={unit}
692
700
  station={sensor?.station}
693
701
  />
702
+ <PreventAccess
703
+ visible={showPreventAccess}
704
+ hidePreventAccess={setHidePreventAccess}
705
+ headerBodyText={'device'}
706
+ />
694
707
  </WrapHeaderScrollable>
695
708
  {isShowEmergencyResolve && (
696
709
  <BottomButtonView
@@ -47,6 +47,7 @@ import {
47
47
  watchNotificationData,
48
48
  unwatchNotificationData,
49
49
  } from '../../utils/Monitor';
50
+ import PreventAccess from '../../commons/PreventAccess';
50
51
 
51
52
  const UnitDetail = ({ route }) => {
52
53
  const t = useTranslations();
@@ -63,14 +64,17 @@ const UnitDetail = ({ route }) => {
63
64
 
64
65
  const isFocused = useIsFocused();
65
66
  const { stateData, setAction } = useContext(SCContext);
66
- const { navigate } = useNavigation();
67
+ const { navigate, goBack } = useNavigation();
67
68
  const RouterHardware = useCallback(
68
69
  (routeHardware) => () => {
69
70
  navigate(routeHardware);
70
71
  },
71
72
  [navigate]
72
73
  );
73
- useBlockBackAndroid(RouterHardware(Routes.Dashboard));
74
+
75
+ useBlockBackAndroid(
76
+ isSuccessfullyConnected ? RouterHardware(Routes.Dashboard) : goBack
77
+ );
74
78
  const user = useSCContextSelector((state) => state?.auth?.account?.user);
75
79
  const isLavidaSource = useSCContextSelector(
76
80
  (state) => state.app.isLavidaSource
@@ -84,6 +88,8 @@ const UnitDetail = ({ route }) => {
84
88
  const [station, setStation] = useState({});
85
89
  const [indexStation, setIndexStation] = useState(0);
86
90
  const [showAdd, setShowAdd, setHideAdd] = useBoolean();
91
+ const [showPreventAccess, setShowPreventAccess, setHidePreventAccess] =
92
+ useBoolean(false);
87
93
  const [isFullScreen, setIsFullScreen] = useState(false);
88
94
  const [dataFullScreen, setDataFullScreen] = useState();
89
95
  const appState = useRef(AppState.currentState);
@@ -122,16 +128,18 @@ const UnitDetail = ({ route }) => {
122
128
 
123
129
  const fetchDetails = useCallback(async () => {
124
130
  getAutomates();
125
- const { success, data } = await axiosGet(
131
+ const { success, data, resp_status } = await axiosGet(
126
132
  API.UNIT.UNIT_DETAIL(unitId),
127
- {},
133
+ { headers: { 'Cache-Control': 'no-cache' } },
128
134
  true
129
135
  );
130
136
  if (success) {
131
137
  prepareData(data);
132
138
  setUnit(data);
139
+ } else if (resp_status === 404) {
140
+ setShowPreventAccess();
133
141
  }
134
- }, [setUnit, unitId, prepareData, getAutomates]);
142
+ }, [getAutomates, unitId, prepareData, setShowPreventAccess]);
135
143
 
136
144
  const getAutomates = useCallback(async () => {
137
145
  await fetchWithCache(
@@ -395,6 +403,11 @@ const UnitDetail = ({ route }) => {
395
403
  modalStyles={styles.modal}
396
404
  onClose={onClose}
397
405
  />
406
+ <PreventAccess
407
+ visible={showPreventAccess}
408
+ hidePreventAccess={setHidePreventAccess}
409
+ headerBodyText={'unit'}
410
+ />
398
411
  </WrapParallaxScrollView>
399
412
  );
400
413
  };
@@ -96,7 +96,11 @@ describe('Test UnitDetail', () => {
96
96
  await renderer.create(wrapComponent(route));
97
97
  });
98
98
 
99
- expect(axios.get).toHaveBeenCalledWith(detailUnitApiUrl, {});
99
+ expect(axios.get).toHaveBeenCalledWith(detailUnitApiUrl, {
100
+ headers: {
101
+ 'Cache-Control': 'no-cache',
102
+ },
103
+ });
100
104
  });
101
105
 
102
106
  test('fetch unit detail no network then load from cache', async () => {
@@ -118,7 +122,11 @@ describe('Test UnitDetail', () => {
118
122
  await renderer.create(wrapComponent(route, account));
119
123
  });
120
124
 
121
- expect(axios.get).toHaveBeenCalledWith(detailUnitApiUrl, {});
125
+ expect(axios.get).toHaveBeenCalledWith(detailUnitApiUrl, {
126
+ headers: {
127
+ 'Cache-Control': 'no-cache',
128
+ },
129
+ });
122
130
  });
123
131
 
124
132
  test('fetch unit detail no network and fail load from cache', async () => {
@@ -129,7 +137,11 @@ describe('Test UnitDetail', () => {
129
137
  await renderer.create(wrapComponent(route, account));
130
138
  });
131
139
 
132
- expect(axios.get).toHaveBeenCalledWith(detailUnitApiUrl, {});
140
+ expect(axios.get).toHaveBeenCalledWith(detailUnitApiUrl, {
141
+ headers: {
142
+ 'Cache-Control': 'no-cache',
143
+ },
144
+ });
133
145
  });
134
146
 
135
147
  test('fetch unit summary empty', async () => {
@@ -193,7 +205,11 @@ describe('Test UnitDetail', () => {
193
205
  await renderer.create(wrapComponent(route, account));
194
206
  });
195
207
 
196
- expect(axios.get).not.toHaveBeenCalledWith(summaryUnitApiUrl, {});
208
+ expect(axios.get).not.toHaveBeenCalledWith(summaryUnitApiUrl, {
209
+ headers: {
210
+ 'Cache-Control': 'no-cache',
211
+ },
212
+ });
197
213
  });
198
214
 
199
215
  test('fetch unit detail when refresh', async () => {
@@ -206,7 +222,11 @@ describe('Test UnitDetail', () => {
206
222
  await act(async () => {
207
223
  refreshControl.props.onRefresh();
208
224
  });
209
- expect(axios.get).toHaveBeenCalledWith(detailUnitApiUrl, {});
225
+ expect(axios.get).toHaveBeenCalledWith(detailUnitApiUrl, {
226
+ headers: {
227
+ 'Cache-Control': 'no-cache',
228
+ },
229
+ });
210
230
  });
211
231
 
212
232
  test('when unit has google home action then connect to google home', async () => {
@@ -207,7 +207,7 @@ const ThreePhasePowerConsumption = memo(({ summaryDetail }) => {
207
207
  params.append('date_from', moment(startDate).format('YYYY-MM-DD'));
208
208
  params.append('date_to', moment(endDate).format('YYYY-MM-DD'));
209
209
  const { success, data } = await axiosGet(
210
- API.VALUE_CONSUME.DISPLAY_HISTORY,
210
+ API.VALUE_CONSUME.DISPLAY_HISTORY(),
211
211
  {
212
212
  params,
213
213
  }
@@ -982,5 +982,8 @@
982
982
  "saving_contact_successful" : "Saving contact successful",
983
983
  "maxmium_contacts": "Maxmium contacts",
984
984
  "enter_password": "Enter Your Password",
985
- "you_need_to_enter_password": "You need to enter password to perform this action"
985
+ "you_need_to_enter_password": "You need to enter password to perform this action",
986
+ "note": "Note",
987
+ "back": "Back",
988
+ "This {name} was removed!" : "This {name} was removed!"
986
989
  }
@@ -982,5 +982,8 @@
982
982
  "search": "Tìm kiếm",
983
983
  "connect_home_wifi" : "Kết nối Wifi của gia đình",
984
984
  "saving_contact_successful" : "Lưu liên hệ thành công",
985
- "maxmium_contacts": "Địa chỉ liên hệ tối đa"
985
+ "maxmium_contacts": "Địa chỉ liên hệ tối đa",
986
+ "note": "Lưu ý ",
987
+ "back": "Quay lại",
988
+ "This {name} was removed!" : "{Name} này đã bị xóa!"
986
989
  }