@eohjsc/react-native-smart-city 0.3.86 → 0.3.88

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 (54) hide show
  1. package/package.json +1 -1
  2. package/src/commons/ActionGroup/__test__/TwoButtonTemplate.test.js +30 -0
  3. package/src/commons/{FourButtonFilterHistory → ChartAggregationOption}/__test__/FourButtonFilterHistory.test.js +2 -2
  4. package/src/commons/ChartAggregationOption/index.js +72 -0
  5. package/src/commons/{FourButtonFilterHistory → ChartAggregationOption}/styles.js +0 -0
  6. package/src/commons/Dashboard/MyPinnedSharedUnit/__test__/MyPinnedSharedUnit.test.js +19 -0
  7. package/src/commons/Dashboard/MyPinnedSharedUnit/index.js +30 -9
  8. package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +13 -1
  9. package/src/commons/Dashboard/MyUnit/index.js +20 -10
  10. package/src/commons/DateTimeRangeChange/DateTimeButton.js +3 -12
  11. package/src/commons/DateTimeRangeChange/index.js +113 -19
  12. package/src/commons/Device/HistoryChart.js +2 -2
  13. package/src/commons/Device/LinearChart.js +2 -2
  14. package/src/commons/Device/WindSpeed/Anemometer/index.js +23 -18
  15. package/src/commons/Device/WindSpeed/__test__/Anemometer.test.js +1 -1
  16. package/src/commons/MenuActionAddnew/__test__/MenuActionAddNew.test.js +1 -1
  17. package/src/commons/MenuActionList/__test__/MenuActionList.test.js +1 -1
  18. package/src/commons/ModalPopupCT/index.js +31 -25
  19. package/src/commons/UnitSummary/ConfigHistoryChart/__test__/ConfigHistoryChart.test.js +7 -7
  20. package/src/commons/UnitSummary/ConfigHistoryChart/index.js +40 -13
  21. package/src/configs/API.js +2 -2
  22. package/src/configs/AccessibilityLabel.js +7 -0
  23. package/src/context/actionType.ts +2 -0
  24. package/src/context/reducer.ts +10 -0
  25. package/src/hooks/Common/useTranslations.ts +1 -1
  26. package/src/hooks/IoT/useRemoteControl.js +0 -1
  27. package/src/screens/ActivityLog/__test__/FilterPopup.test.js +1 -1
  28. package/src/screens/ActivityLog/__test__/index.test.js +1 -1
  29. package/src/screens/AddLocationMaps/index.js +5 -4
  30. package/src/screens/AddNewGateway/__test__/ScanModbusQR.test.js +15 -0
  31. package/src/screens/AllGateway/hooks/__test__/index.test.js +26 -2
  32. package/src/screens/AllGateway/hooks/useGateway.js +11 -9
  33. package/src/screens/Device/__test__/DetailHistoryChart.test.js +1 -0
  34. package/src/screens/Device/__test__/sensorDisplayItem.test.js +150 -2
  35. package/src/screens/Device/components/ChartWrapper.js +39 -0
  36. package/src/screens/Device/components/ChartWrapperStyles.js +42 -0
  37. package/src/screens/Device/components/SensorDisplayItem.js +6 -2
  38. package/src/screens/Device/components/VisualChart.js +255 -0
  39. package/src/screens/Device/components/__test__/VisualChart.test.js +440 -0
  40. package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +7 -6
  41. package/src/screens/Sharing/InfoMemberUnit.js +41 -8
  42. package/src/screens/Sharing/Styles/inforMemberUnitStyles.js +11 -0
  43. package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +62 -2
  44. package/src/screens/SmartAccount/SuccessfullyConnected/__test__/SuccessfullyConnected.test.js +3 -0
  45. package/src/screens/SmartIr/__test__/GroupButtonByType.test.js +47 -0
  46. package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +15 -2
  47. package/src/screens/SubUnit/AddSubUnit.js +8 -5
  48. package/src/screens/SyncLGDevice/__test__/AddLGDevice.test.js +52 -0
  49. package/src/screens/Unit/ChooseLocationStyles.js +1 -0
  50. package/src/screens/Unit/components/__test__/Header.test.js +9 -0
  51. package/src/screens/Unit/hook/__test__/useUnitConnectRemoteDevices.test.js +57 -0
  52. package/src/utils/I18n/translations/en.json +4 -1
  53. package/src/utils/I18n/translations/vi.json +4 -1
  54. package/src/commons/FourButtonFilterHistory/index.js +0 -72
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.3.86",
4
+ "version": "0.3.88",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -172,4 +172,34 @@ describe('Test TwoButtonTemplate', () => {
172
172
  const touchableOpacities = instance.findAllByType(TouchableOpacity);
173
173
  expect(touchableOpacities.length).toEqual(2);
174
174
  });
175
+
176
+ it('render data configuration case button1 on value is null', async () => {
177
+ const mockDoAction = jest.fn();
178
+ let new_actionGroup = {
179
+ ...actionGroup,
180
+ configuration: {
181
+ ...actionGroup.configuration,
182
+ button1: {
183
+ ...actionGroup.configuration.button1,
184
+ is_on_value: null,
185
+ },
186
+ button2: {
187
+ ...actionGroup.configuration.button2,
188
+ is_on_value: [true],
189
+ },
190
+ },
191
+ };
192
+ await act(async () => {
193
+ wrapper = create(
194
+ <TwoButtonTemplate
195
+ actionGroup={new_actionGroup}
196
+ doAction={mockDoAction}
197
+ sensor={sensor}
198
+ />
199
+ );
200
+ });
201
+ const instance = wrapper.root;
202
+ const touchableOpacities = instance.findAllByType(TouchableOpacity);
203
+ expect(touchableOpacities.length).toEqual(2);
204
+ });
175
205
  });
@@ -2,12 +2,12 @@ import React from 'react';
2
2
  import { act, create } from 'react-test-renderer';
3
3
  import { SCProvider } from '../../../context';
4
4
  import { mockSCStore } from '../../../context/mockStore';
5
- import FourButtonFilterHistory from '../index';
5
+ import ChartAggregationOption from '../index';
6
6
  import { TouchableOpacity } from 'react-native';
7
7
 
8
8
  const wrapComponent = (props) => (
9
9
  <SCProvider initState={mockSCStore({})}>
10
- <FourButtonFilterHistory {...props} />
10
+ <ChartAggregationOption {...props} />
11
11
  </SCProvider>
12
12
  );
13
13
 
@@ -0,0 +1,72 @@
1
+ import React, { useCallback } from 'react';
2
+ import { View, TouchableOpacity } from 'react-native';
3
+ import Text from '../Text';
4
+ import { Colors } from '../../configs';
5
+ import styles from './styles';
6
+
7
+ const defaultOptions = [
8
+ {
9
+ title: 'D',
10
+ data: 'date',
11
+ },
12
+
13
+ {
14
+ title: 'W',
15
+ data: 'week',
16
+ },
17
+
18
+ {
19
+ title: 'M',
20
+ data: 'month',
21
+ },
22
+
23
+ {
24
+ title: 'Y',
25
+ data: 'year',
26
+ },
27
+ ];
28
+
29
+ const ItemButton = ({ title, onPress, isSelected }) => {
30
+ return (
31
+ <TouchableOpacity
32
+ onPress={onPress}
33
+ style={[styles.button, isSelected && styles.selectedButton]}
34
+ >
35
+ <View>
36
+ <Text bold color={isSelected && Colors.Primary}>
37
+ {title}
38
+ </Text>
39
+ </View>
40
+ </TouchableOpacity>
41
+ );
42
+ };
43
+
44
+ const ChartAggregationOption = ({
45
+ groupBy,
46
+ setGroupBy,
47
+ options = defaultOptions,
48
+ }) => {
49
+ const onPressButton = useCallback(
50
+ (data) => () => {
51
+ setGroupBy && setGroupBy(data);
52
+ },
53
+ [setGroupBy]
54
+ );
55
+
56
+ return (
57
+ <View style={styles.row}>
58
+ {options.map((item, index) => {
59
+ return (
60
+ <ItemButton
61
+ key={index}
62
+ title={item.title}
63
+ onPress={onPressButton(item.data)}
64
+ isSelected={item.data === groupBy}
65
+ />
66
+ );
67
+ })}
68
+ </View>
69
+ );
70
+ };
71
+
72
+ export default ChartAggregationOption;
@@ -12,10 +12,13 @@ import { API } from '../../../../configs';
12
12
  import { TouchableOpacity } from 'react-native';
13
13
  import api from '../../../../utils/Apis/axios';
14
14
  import SharedUnit from '../../../Unit/SharedUnit';
15
+ import { Action } from '../../../../context/actionType';
15
16
 
16
17
  const mock = new MockAdapter(api.axiosInstance);
17
18
 
18
19
  const mockedNavigate = jest.fn();
20
+ const mockSetAction = jest.fn();
21
+
19
22
  jest.mock('@react-navigation/native', () => {
20
23
  return {
21
24
  ...jest.requireActual('@react-navigation/native'),
@@ -26,6 +29,18 @@ jest.mock('@react-navigation/native', () => {
26
29
  };
27
30
  });
28
31
 
32
+ jest.mock('react', () => {
33
+ return {
34
+ ...jest.requireActual('react'),
35
+ useContext: () => ({
36
+ stateData: mockSCStore({
37
+ app: { isNeedUpdateCache: true },
38
+ }),
39
+ setAction: mockSetAction,
40
+ }),
41
+ };
42
+ });
43
+
29
44
  const wrapComponent = (route) => (
30
45
  <SCProvider initState={mockSCStore({})}>
31
46
  <MyPinnedSharedUnit />
@@ -60,6 +75,10 @@ describe('Test MyPinnedSharedUnit', () => {
60
75
  goToAllSharedUnits.props.onPress();
61
76
  });
62
77
  expect(mockedNavigate).toHaveBeenCalled();
78
+ expect(mockSetAction).toBeCalledWith(
79
+ Action.IS_CHECK_CLEAR_CACHE_UNITS,
80
+ false
81
+ );
63
82
  });
64
83
 
65
84
  it('render without item', async () => {
@@ -1,4 +1,10 @@
1
- import React, { useCallback, useEffect, useState, memo } from 'react';
1
+ import React, {
2
+ useCallback,
3
+ useEffect,
4
+ useState,
5
+ memo,
6
+ useContext,
7
+ } from 'react';
2
8
  import { TouchableOpacity, View } from 'react-native';
3
9
 
4
10
  import styles from './styles';
@@ -10,15 +16,22 @@ import Routes from '../../../utils/Route';
10
16
  import { AccessibilityLabel } from '../../../configs/Constants';
11
17
  import { useTranslations } from '../../../hooks/Common/useTranslations';
12
18
  import SharedUnit from '../../Unit/SharedUnit';
13
- import { fetchWithCache } from '../../../utils/Apis/axios';
19
+ import { axiosGet, fetchWithCache } from '../../../utils/Apis/axios';
14
20
  import { preloadImagesFromUnits } from '../../../utils/Functions/preloadImages';
15
21
  import { STORAGE_KEY } from '../../../utils/Storage';
22
+ import { SCContext, useSCContextSelector } from '../../../context';
23
+ import { Action } from '../../../context/actionType';
16
24
 
17
25
  const MyPinnedSharedUnit = ({ refreshing }) => {
18
26
  const t = useTranslations();
19
27
  const isFocused = useIsFocused();
20
28
  const navigation = useNavigation();
21
29
  const [sharedUnits, setSharedUnits] = useState([]);
30
+ const { setAction } = useContext(SCContext);
31
+
32
+ const isNeedUpdateCache = useSCContextSelector(
33
+ (state) => state.app.isNeedUpdateCache
34
+ );
22
35
 
23
36
  const goToAllSharedUnits = () => {
24
37
  navigation.navigate(Routes.SharedStack, {
@@ -27,13 +40,21 @@ const MyPinnedSharedUnit = ({ refreshing }) => {
27
40
  };
28
41
 
29
42
  const fetchSharedUnitDashboard = useCallback(async () => {
30
- await fetchWithCache(API.UNIT.SHARED_UNITS(), {}, (response) => {
31
- const { success, data } = response;
32
-
33
- if (success) {
34
- setSharedUnits(data);
35
- }
36
- });
43
+ if (isNeedUpdateCache) {
44
+ setAction(Action.IS_CHECK_CLEAR_CACHE_UNITS, false);
45
+ const { success, data } = await axiosGet(
46
+ API.UNIT.SHARED_UNITS(),
47
+ {},
48
+ true
49
+ );
50
+ success && setSharedUnits(data);
51
+ } else {
52
+ await fetchWithCache(API.UNIT.SHARED_UNITS(), {}, (response) => {
53
+ const { success, data } = response;
54
+ success && setSharedUnits(data);
55
+ });
56
+ }
57
+ // eslint-disable-next-line react-hooks/exhaustive-deps
37
58
  }, [setSharedUnits]);
38
59
 
39
60
  useEffect(() => {
@@ -16,6 +16,14 @@ const mock = new MockAdapter(api.axiosInstance);
16
16
 
17
17
  const mockedNavigate = jest.fn();
18
18
  const mockedDispatch = jest.fn();
19
+ const mockedSetAction = jest.fn();
20
+
21
+ const mockUseContext = jest.fn().mockImplementation(() => ({
22
+ stateData: mockSCStore({}),
23
+ setAction: mockedSetAction,
24
+ }));
25
+
26
+ React.useContext = mockUseContext;
19
27
 
20
28
  const mockSetAction = jest.fn();
21
29
  jest.mock('react', () => {
@@ -23,7 +31,7 @@ jest.mock('react', () => {
23
31
  ...jest.requireActual('react'),
24
32
  useContext: () => ({
25
33
  stateData: mockSCStore({
26
- app: { isDeleteUnitSuccessFully: true },
34
+ app: { isDeleteUnitSuccessFully: true, isNeedUpdateCache: true },
27
35
  }),
28
36
  setAction: mockSetAction,
29
37
  }),
@@ -131,6 +139,10 @@ describe('Test MyUnit', () => {
131
139
  params: { unitId: 1 },
132
140
  screen: Routes.UnitDetail,
133
141
  });
142
+ expect(mockSetAction).toBeCalledWith(
143
+ Action.IS_CHECK_CLEAR_CACHE_UNITS,
144
+ false
145
+ );
134
146
  });
135
147
 
136
148
  it('Test isDeleteUnitSuccessFully', async () => {
@@ -17,7 +17,7 @@ import NetInfo from '@react-native-community/netinfo';
17
17
  import { BleManager } from 'react-native-ble-plx';
18
18
  import { API, Colors, Images } from '../../../configs';
19
19
  import Text from '../../Text';
20
- import { fetchWithCache } from '../../../utils/Apis/axios';
20
+ import { axiosGet, fetchWithCache } from '../../../utils/Apis/axios';
21
21
 
22
22
  import styles from './styles';
23
23
  import { Section } from '../../Section';
@@ -50,6 +50,9 @@ const MyUnit = ({ refreshing }) => {
50
50
  const isDeleteUnitSuccessFully = useSCContextSelector(
51
51
  (state) => state.app.isDeleteUnitSuccessFully
52
52
  );
53
+ const isNeedUpdateCache = useSCContextSelector(
54
+ (state) => state.app.isNeedUpdateCache
55
+ );
53
56
 
54
57
  const {
55
58
  permissionsRequested: bluetoothPermRequested,
@@ -61,17 +64,18 @@ const MyUnit = ({ refreshing }) => {
61
64
  }, [bluetoothPermRequested, requestBluetoothPerm]);
62
65
 
63
66
  const fetchMyUnitDashboard = useCallback(async () => {
64
- await fetchWithCache(API.UNIT.MY_UNITS(), {}, (response) => {
65
- const { success, data } = response;
67
+ if (isNeedUpdateCache) {
68
+ setAction(Action.IS_CHECK_CLEAR_CACHE_UNITS, false);
69
+ const { success, data } = await axiosGet(API.UNIT.MY_UNITS(), {}, true);
66
70
  success && setMyUnits(data);
67
- });
68
- }, [setMyUnits]);
69
-
70
- useEffect(() => {
71
- if (isFocused || refreshing) {
72
- fetchMyUnitDashboard();
71
+ } else {
72
+ await fetchWithCache(API.UNIT.MY_UNITS(), {}, (response) => {
73
+ const { success, data } = response;
74
+ success && setMyUnits(data);
75
+ });
73
76
  }
74
- }, [fetchMyUnitDashboard, isFocused, refreshing]);
77
+ // eslint-disable-next-line react-hooks/exhaustive-deps
78
+ }, [setMyUnits]);
75
79
 
76
80
  useFocusEffect(
77
81
  useCallback(() => {
@@ -169,6 +173,12 @@ const MyUnit = ({ refreshing }) => {
169
173
  preloadImagesFromUnits(myUnits, STORAGE_KEY.IS_FIRST_TIME_LOAD_MY_UNITS);
170
174
  }, [myUnits]);
171
175
 
176
+ useEffect(() => {
177
+ if (isFocused || refreshing) {
178
+ fetchMyUnitDashboard();
179
+ }
180
+ }, [fetchMyUnitDashboard, isFocused, refreshing]);
181
+
172
182
  useEffect(() => {
173
183
  if (isDeleteUnitSuccessFully) {
174
184
  const to = setTimeout(() => {
@@ -1,21 +1,12 @@
1
1
  import React, { memo } from 'react';
2
2
  import { StyleSheet, TouchableOpacity } from 'react-native';
3
3
  import { IconOutline } from '@ant-design/icons-react-native';
4
- import moment from 'moment';
5
-
6
- import Text from '../Text';
7
4
  import { Colors } from '../../configs';
8
5
 
9
- const DateTimeButton = memo(({ onPress, time, date, formatType, style }) => {
10
- let format = 'DD.MM.YY HH:mm';
11
- if (formatType === 'date') {
12
- format = 'DD.MM.YY';
13
- }
6
+ const DateTimeButton = memo(({ onPress, style, children }) => {
14
7
  return (
15
8
  <TouchableOpacity style={[styles.dateSelect, style]} onPress={onPress}>
16
- <Text type={'Label'} color={Colors.Gray8} style={styles.txtTime}>
17
- {moment(time).format(format)}
18
- </Text>
9
+ {children}
19
10
  <IconOutline style={styles.iconDateTime} name={'calendar'} />
20
11
  </TouchableOpacity>
21
12
  );
@@ -34,7 +25,7 @@ const styles = StyleSheet.create({
34
25
  marginHorizontal: 8,
35
26
  flexDirection: 'row',
36
27
  justifyContent: 'space-between',
37
- width: 124,
28
+ width: 130,
38
29
  alignItems: 'center',
39
30
  },
40
31
  txtTime: {
@@ -1,23 +1,94 @@
1
- import React, { memo } from 'react';
1
+ import React, { memo, useCallback, useState } from 'react';
2
2
  import { useTranslations } from '../../hooks/Common/useTranslations';
3
3
  import { StyleSheet, View } from 'react-native';
4
4
 
5
5
  import { Colors } from '../../configs';
6
6
  import Text from '../Text';
7
7
  import DateTimeButton from './DateTimeButton';
8
+ import DateTimePickerModal from 'react-native-modal-datetime-picker';
9
+ import moment from 'moment/moment';
8
10
 
9
11
  const DateTimeRangeChange = memo(
10
12
  ({
11
13
  startTime,
12
- onStart,
13
- onEnd,
14
14
  endTime,
15
15
  style,
16
- date,
17
- formatType,
16
+ showTime,
17
+ selectStart,
18
+ selectEnd,
18
19
  inline = true,
19
20
  }) => {
21
+ const format = showTime ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD';
22
+ const mode = showTime ? 'datetime' : 'date';
20
23
  const t = useTranslations();
24
+ const ensureDateStart = moment(startTime);
25
+ const ensureDateEnd = moment(endTime);
26
+
27
+ const [eventPicker, setEventPicker] = useState({
28
+ showModalEnd: false,
29
+ showModalStart: false,
30
+ });
31
+
32
+ const onStart = useCallback(() => {
33
+ setEventPicker((state) => ({
34
+ ...state,
35
+ showModalStart: true,
36
+ showModalEnd: false,
37
+ }));
38
+ }, []);
39
+ const onEnd = useCallback(() => {
40
+ setEventPicker((state) => ({
41
+ ...state,
42
+ showModalStart: false,
43
+ showModalEnd: true,
44
+ }));
45
+ }, []);
46
+ const onConfirmStart = useCallback(
47
+ (date) => {
48
+ const selectedDate = date ? moment(date) : moment().valueOf();
49
+ setEventPicker((state) => {
50
+ if (typeof date === 'number') {
51
+ onCancel();
52
+ return state;
53
+ }
54
+ return {
55
+ ...state,
56
+ showModalStart: false,
57
+ showModalEnd: true,
58
+ };
59
+ });
60
+ selectStart(selectedDate);
61
+ },
62
+ [onCancel, selectStart]
63
+ );
64
+
65
+ const onConfirmEnd = useCallback(
66
+ (date) => {
67
+ const selectedDate = date ? moment(date) : moment().valueOf();
68
+ setEventPicker((state) => {
69
+ if (typeof date === 'number') {
70
+ onCancel();
71
+ return state;
72
+ }
73
+
74
+ return {
75
+ ...state,
76
+ showModalEnd: false,
77
+ };
78
+ });
79
+ selectEnd(selectedDate);
80
+ },
81
+ [onCancel, selectEnd]
82
+ );
83
+
84
+ const onCancel = useCallback(() => {
85
+ setEventPicker((state) => ({
86
+ ...state,
87
+ showModalEnd: false,
88
+ showModalStart: false,
89
+ }));
90
+ }, []);
91
+
21
92
  return (
22
93
  <View
23
94
  style={[styles.dateTimeView, !inline && styles.spaceBetween, style]}
@@ -26,26 +97,49 @@ const DateTimeRangeChange = memo(
26
97
  <Text type="Label" color={Colors.Gray7}>
27
98
  {t('from')}
28
99
  </Text>
29
- <DateTimeButton
30
- onPress={onStart}
31
- time={startTime}
32
- date={date}
33
- formatType={formatType}
34
- style={!inline && styles.button}
35
- />
100
+ <DateTimeButton onPress={onStart} style={!inline && styles.button}>
101
+ <Text type={'Label'} color={Colors.Gray8} style={styles.txtTime}>
102
+ {ensureDateStart.format(format)}
103
+ </Text>
104
+ </DateTimeButton>
36
105
  </View>
37
106
  <View style={[styles.wrap, !inline && styles.buttonWrap]}>
38
107
  <Text type="Label" color={Colors.Gray7}>
39
108
  {t('to')}
40
109
  </Text>
41
- <DateTimeButton
42
- onPress={onEnd}
43
- time={endTime}
44
- date={date}
45
- formatType={formatType}
46
- style={!inline && styles.button}
47
- />
110
+ <DateTimeButton onPress={onEnd} style={!inline && styles.button}>
111
+ <Text type={'Label'} color={Colors.Gray8} style={styles.txtTime}>
112
+ {ensureDateEnd.format(format)}
113
+ </Text>
114
+ </DateTimeButton>
48
115
  </View>
116
+ <DateTimePickerModal
117
+ isVisible={eventPicker.showModalStart}
118
+ date={ensureDateStart._d}
119
+ mode={mode}
120
+ onConfirm={onConfirmStart}
121
+ onCancel={onCancel}
122
+ display="spinner"
123
+ title={t('select_start_time')}
124
+ headerTextIOS={t('pick_a_date')}
125
+ cancelTextIOS={t('cancel')}
126
+ confirmTextIOS={t('confirm')}
127
+ maximumDate={new Date()}
128
+ />
129
+ <DateTimePickerModal
130
+ isVisible={eventPicker.showModalEnd}
131
+ date={ensureDateEnd._d}
132
+ mode={mode}
133
+ onConfirm={onConfirmEnd}
134
+ onCancel={onCancel}
135
+ display="spinner"
136
+ title={t('select_end_time')}
137
+ headerTextIOS={t('pick_a_date')}
138
+ cancelTextIOS={t('cancel')}
139
+ confirmTextIOS={t('confirm')}
140
+ maximumDate={new Date()}
141
+ minimumDate={ensureDateStart._d}
142
+ />
49
143
  </View>
50
144
  );
51
145
  }
@@ -11,7 +11,7 @@ import DateTimeRangeChange from '../DateTimeRangeChange';
11
11
  import HorizontalBarChart from './HorizontalBarChart';
12
12
  import DateTimePickerModal from 'react-native-modal-datetime-picker';
13
13
  import LinearChart from './LinearChart';
14
- import FourButtonFilterHistory from '../FourButtonFilterHistory';
14
+ import ChartAggregationOption from '../ChartAggregationOption';
15
15
  import { formatMoney } from '../../utils/Utils';
16
16
 
17
17
  export const dateTimeType = {
@@ -186,7 +186,7 @@ const HistoryChart = memo(
186
186
  {t('history')}
187
187
  </Text>
188
188
  {configuration.type === 'horizontal_bar_chart' && (
189
- <FourButtonFilterHistory
189
+ <ChartAggregationOption
190
190
  groupBy={groupBy}
191
191
  setGroupBy={setGroupBy}
192
192
  />
@@ -1,4 +1,4 @@
1
- import React, { memo, useState, useEffect, useCallback } from 'react';
1
+ import React, { useState, useEffect, useCallback } from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
3
  import HighchartsReactNative from '@eohjsc/highcharts';
4
4
  import moment from 'moment';
@@ -117,7 +117,7 @@ function LinearChart({ datas }) {
117
117
  );
118
118
  }
119
119
 
120
- export default memo(LinearChart);
120
+ export default LinearChart;
121
121
 
122
122
  const styles = StyleSheet.create({
123
123
  container: {
@@ -128,7 +128,7 @@ const Anemometer = memo(
128
128
 
129
129
  const valueSize = useMemo(() => {
130
130
  if ([null, undefined, NaN].includes(value)) {
131
- return;
131
+ return [];
132
132
  }
133
133
  if (value.toString().length < 4) {
134
134
  return [56, 16];
@@ -143,6 +143,9 @@ const Anemometer = memo(
143
143
  }, [value]);
144
144
 
145
145
  const toolTipTranslateX = useMemo(() => {
146
+ if (!value) {
147
+ return;
148
+ }
146
149
  if (value.toString().length < 4) {
147
150
  return -20;
148
151
  }
@@ -173,23 +176,25 @@ const Anemometer = memo(
173
176
  </View>
174
177
 
175
178
  <View style={styles.textValue}>
176
- <Svg width={width} height={width} {...viewBox}>
177
- <Text
178
- fill={Colors.Lime6}
179
- fontSize={valueSize[0]}
180
- fontWeight="bold"
181
- x={width / 2}
182
- y={width / 2 + valueSize[1]}
183
- textAnchor="middle"
184
- fontFamily={Fonts.Regular}
185
- onPressIn={handleShowToolTip(true)}
186
- onPressOut={handleShowToolTip(false)}
187
- >
188
- {value.toString().length > 10
189
- ? value.toString().substring(0, 10) + '...'
190
- : value}
191
- </Text>
192
- </Svg>
179
+ {value && (
180
+ <Svg width={width} height={width} {...viewBox}>
181
+ <Text
182
+ fill={Colors.Lime6}
183
+ fontSize={valueSize[0]}
184
+ fontWeight="bold"
185
+ x={width / 2}
186
+ y={width / 2 + valueSize[1]}
187
+ textAnchor="middle"
188
+ fontFamily={Fonts.Regular}
189
+ onPressIn={handleShowToolTip(true)}
190
+ onPressOut={handleShowToolTip(false)}
191
+ >
192
+ {value.toString().length > 10
193
+ ? value.toString().substring(0, 10) + '...'
194
+ : value}
195
+ </Text>
196
+ </Svg>
197
+ )}
193
198
  {isShowToolTip && (
194
199
  <View
195
200
  style={{
@@ -26,7 +26,7 @@ describe('Test Anemometer', () => {
26
26
  });
27
27
  const instance = wrapper.root;
28
28
  const text = instance.findAllByType(Text);
29
- expect(text.length).toBe(5);
29
+ expect(text.length).toBe(4);
30
30
  });
31
31
 
32
32
  it('test render value font size length < 4', async () => {
@@ -17,7 +17,7 @@ describe('Test MenuActionAddNew', () => {
17
17
  let wrapper;
18
18
 
19
19
  // flat list issue
20
- it.skip('onItemClick MenuActionAddNew', async () => {
20
+ it('onItemClick MenuActionAddNew', async () => {
21
21
  const mockFunc = jest.fn();
22
22
  await act(async () => {
23
23
  wrapper = create(wrapComponent(dataActions));
@@ -9,7 +9,7 @@ describe('Test MenuActionList', () => {
9
9
  const listItem = [item(1)];
10
10
  let wrapper;
11
11
 
12
- it.skip('onItemClick MenuActionList', async () => {
12
+ it('onItemClick MenuActionList', async () => {
13
13
  const mockOnItemClick = jest.fn();
14
14
  const mockHideModal = jest.fn();
15
15