@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.
- package/package.json +1 -1
- package/src/commons/ActionGroup/__test__/TwoButtonTemplate.test.js +30 -0
- package/src/commons/{FourButtonFilterHistory → ChartAggregationOption}/__test__/FourButtonFilterHistory.test.js +2 -2
- package/src/commons/ChartAggregationOption/index.js +72 -0
- package/src/commons/{FourButtonFilterHistory → ChartAggregationOption}/styles.js +0 -0
- package/src/commons/Dashboard/MyPinnedSharedUnit/__test__/MyPinnedSharedUnit.test.js +19 -0
- package/src/commons/Dashboard/MyPinnedSharedUnit/index.js +30 -9
- package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +13 -1
- package/src/commons/Dashboard/MyUnit/index.js +20 -10
- package/src/commons/DateTimeRangeChange/DateTimeButton.js +3 -12
- package/src/commons/DateTimeRangeChange/index.js +113 -19
- package/src/commons/Device/HistoryChart.js +2 -2
- package/src/commons/Device/LinearChart.js +2 -2
- package/src/commons/Device/WindSpeed/Anemometer/index.js +23 -18
- package/src/commons/Device/WindSpeed/__test__/Anemometer.test.js +1 -1
- package/src/commons/MenuActionAddnew/__test__/MenuActionAddNew.test.js +1 -1
- package/src/commons/MenuActionList/__test__/MenuActionList.test.js +1 -1
- package/src/commons/ModalPopupCT/index.js +31 -25
- package/src/commons/UnitSummary/ConfigHistoryChart/__test__/ConfigHistoryChart.test.js +7 -7
- package/src/commons/UnitSummary/ConfigHistoryChart/index.js +40 -13
- package/src/configs/API.js +2 -2
- package/src/configs/AccessibilityLabel.js +7 -0
- package/src/context/actionType.ts +2 -0
- package/src/context/reducer.ts +10 -0
- package/src/hooks/Common/useTranslations.ts +1 -1
- package/src/hooks/IoT/useRemoteControl.js +0 -1
- package/src/screens/ActivityLog/__test__/FilterPopup.test.js +1 -1
- package/src/screens/ActivityLog/__test__/index.test.js +1 -1
- package/src/screens/AddLocationMaps/index.js +5 -4
- package/src/screens/AddNewGateway/__test__/ScanModbusQR.test.js +15 -0
- package/src/screens/AllGateway/hooks/__test__/index.test.js +26 -2
- package/src/screens/AllGateway/hooks/useGateway.js +11 -9
- package/src/screens/Device/__test__/DetailHistoryChart.test.js +1 -0
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +150 -2
- package/src/screens/Device/components/ChartWrapper.js +39 -0
- package/src/screens/Device/components/ChartWrapperStyles.js +42 -0
- package/src/screens/Device/components/SensorDisplayItem.js +6 -2
- package/src/screens/Device/components/VisualChart.js +255 -0
- package/src/screens/Device/components/__test__/VisualChart.test.js +440 -0
- package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +7 -6
- package/src/screens/Sharing/InfoMemberUnit.js +41 -8
- package/src/screens/Sharing/Styles/inforMemberUnitStyles.js +11 -0
- package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +62 -2
- package/src/screens/SmartAccount/SuccessfullyConnected/__test__/SuccessfullyConnected.test.js +3 -0
- package/src/screens/SmartIr/__test__/GroupButtonByType.test.js +47 -0
- package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +15 -2
- package/src/screens/SubUnit/AddSubUnit.js +8 -5
- package/src/screens/SyncLGDevice/__test__/AddLGDevice.test.js +52 -0
- package/src/screens/Unit/ChooseLocationStyles.js +1 -0
- package/src/screens/Unit/components/__test__/Header.test.js +9 -0
- package/src/screens/Unit/hook/__test__/useUnitConnectRemoteDevices.test.js +57 -0
- package/src/utils/I18n/translations/en.json +4 -1
- package/src/utils/I18n/translations/vi.json +4 -1
- package/src/commons/FourButtonFilterHistory/index.js +0 -72
package/package.json
CHANGED
|
@@ -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
|
|
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
|
-
<
|
|
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;
|
|
File without changes
|
|
@@ -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, {
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
65
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
17
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
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
|
-
<
|
|
189
|
+
<ChartAggregationOption
|
|
190
190
|
groupBy={groupBy}
|
|
191
191
|
setGroupBy={setGroupBy}
|
|
192
192
|
/>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import 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
|
|
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
|
-
|
|
177
|
-
<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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={{
|
|
@@ -17,7 +17,7 @@ describe('Test MenuActionAddNew', () => {
|
|
|
17
17
|
let wrapper;
|
|
18
18
|
|
|
19
19
|
// flat list issue
|
|
20
|
-
it
|
|
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
|
|
12
|
+
it('onItemClick MenuActionList', async () => {
|
|
13
13
|
const mockOnItemClick = jest.fn();
|
|
14
14
|
const mockHideModal = jest.fn();
|
|
15
15
|
|