@eohjsc/react-native-smart-city 0.5.9 → 0.6.1
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/README.md +44 -6
- package/package.json +1 -1
- package/src/commons/Device/HorizontalBarChart.js +1 -1
- package/src/commons/Device/PowerConsumptionChart.js +159 -0
- package/src/commons/Device/ProgressBar/__test__/ProgressBar.test.js +2 -3
- package/src/commons/Device/ProgressBar/index.js +36 -38
- package/src/commons/Device/ProgressBar/styles.js +18 -24
- package/src/commons/Form/CurrencyInput.js +2 -0
- package/src/commons/UnitSummary/ConfigHistoryChart/index.js +6 -61
- package/src/commons/Widgets/IFrame/IFrame.js +54 -0
- package/src/commons/Widgets/IFrame/IFrameStyles.js +35 -0
- package/src/commons/Widgets/IFrame/__tests__/IFrame.test.js +74 -0
- package/src/commons/Widgets/IFrame/index.js +0 -0
- package/src/commons/Widgets/IFrameWithConfig/IFrameWithConfig.js +163 -0
- package/src/commons/Widgets/IFrameWithConfig/IFrameWithConfigStyles.js +9 -0
- package/src/commons/Widgets/IFrameWithConfig/__tests__/IFrameWithConfig.test.js +284 -0
- package/src/commons/Widgets/IFrameWithConfig/index.js +0 -0
- package/src/commons/Widgets/Widget.js +0 -0
- package/src/commons/Widgets/index.js +0 -0
- package/src/configs/AccessibilityLabel.js +3 -0
- package/src/configs/Constants.js +5 -0
- package/src/hooks/Common/useDevicesStatus.js +23 -23
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +3 -3
- package/src/screens/Device/components/SensorDisplayItem.js +23 -5
- package/src/screens/Device/components/__test__/VisualChart.test.js +2 -9
- package/src/screens/PlayBackCamera/Styles/index.js +2 -4
- package/src/screens/PlayBackCamera/Timer.js +65 -47
- package/src/screens/PlayBackCamera/__test__/index.test.js +27 -19
- package/src/screens/PlayBackCamera/index.js +114 -111
- package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +10 -23
- package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +57 -3
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +21 -30
- package/src/commons/Device/HistoryChart.js +0 -225
- package/src/commons/UnitSummary/ConfigHistoryChart/__test__/ConfigHistoryChart.test.js +0 -289
- package/src/screens/Device/__test__/DetailHistoryChart.test.js +0 -69
- package/src/screens/Device/components/DetailHistoryChart.js +0 -118
|
@@ -13,18 +13,19 @@ import ListQualityIndicator from '../../../commons/Device/WaterQualitySensor/Lis
|
|
|
13
13
|
import Compass from '../../../commons/Device/WindDirection/Compass';
|
|
14
14
|
import Anemometer from '../../../commons/Device/WindSpeed/Anemometer';
|
|
15
15
|
import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
|
|
16
|
-
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
16
|
+
import { AccessibilityLabel, WIDGET_TYPE } from '../../../configs/Constants';
|
|
17
17
|
import { useSCContextSelector } from '../../../context';
|
|
18
18
|
import { useRemoteControl } from '../../../hooks/IoT';
|
|
19
19
|
import { useConfigGlobalState } from '../../../iot/states';
|
|
20
20
|
import SmartIr from '../../../screens/SmartIr';
|
|
21
21
|
import { useEvaluateValue } from '../hooks/useEvaluateValue';
|
|
22
22
|
import styles from '../styles';
|
|
23
|
-
import { DetailHistoryChart } from './DetailHistoryChart';
|
|
24
23
|
import VisualChart from './VisualChart';
|
|
25
24
|
import { standardizeCameraScreenSize } from '../../../utils/Utils';
|
|
26
25
|
import { Device } from '../../../configs';
|
|
27
26
|
import DonutCharts from './DonutChart';
|
|
27
|
+
import IFrame from '../../../commons/Widgets/IFrame/IFrame';
|
|
28
|
+
import IFrameWithConfig from '../../../commons/Widgets/IFrameWithConfig/IFrameWithConfig';
|
|
28
29
|
|
|
29
30
|
const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
|
|
30
31
|
Device.screenWidth - 32
|
|
@@ -176,10 +177,27 @@ export const SensorDisplayItem = ({
|
|
|
176
177
|
isWidgetOrder={isWidgetOrder}
|
|
177
178
|
/>
|
|
178
179
|
);
|
|
180
|
+
case WIDGET_TYPE.iframe:
|
|
181
|
+
return (
|
|
182
|
+
<IFrame
|
|
183
|
+
doAction={doAction}
|
|
184
|
+
sensor={sensor}
|
|
185
|
+
id={idTemplate}
|
|
186
|
+
item={item}
|
|
187
|
+
isWidgetOrder={isWidgetOrder}
|
|
188
|
+
/>
|
|
189
|
+
);
|
|
190
|
+
case WIDGET_TYPE.iframeWithConfig:
|
|
191
|
+
return (
|
|
192
|
+
<IFrameWithConfig
|
|
193
|
+
doAction={doAction}
|
|
194
|
+
sensor={sensor}
|
|
195
|
+
id={idTemplate}
|
|
196
|
+
item={item}
|
|
197
|
+
isWidgetOrder={isWidgetOrder}
|
|
198
|
+
/>
|
|
199
|
+
);
|
|
179
200
|
case 'history':
|
|
180
|
-
if (configuration?.config === 'power_consumption') {
|
|
181
|
-
return <DetailHistoryChart item={item} sensor={sensor} />;
|
|
182
|
-
}
|
|
183
201
|
return (
|
|
184
202
|
<VisualChart
|
|
185
203
|
item={item}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import MockAdapter from 'axios-mock-adapter';
|
|
3
3
|
import moment from 'moment';
|
|
4
|
-
import { act
|
|
4
|
+
import { act } from 'react-test-renderer';
|
|
5
5
|
|
|
6
6
|
import VisualChart from '../VisualChart';
|
|
7
7
|
import { API } from '../../../../configs';
|
|
@@ -11,14 +11,7 @@ import api from '../../../../utils/Apis/axios';
|
|
|
11
11
|
import ChartAggregationOption from '../../../../commons/ChartAggregationOption';
|
|
12
12
|
import DateTimeRangeChange from '../../../../commons/DateTimeRangeChange';
|
|
13
13
|
import Highcharts from '../../../../commons/Highcharts';
|
|
14
|
-
|
|
15
|
-
const render = async (component) => {
|
|
16
|
-
let tree;
|
|
17
|
-
await act(async () => {
|
|
18
|
-
tree = await create(component);
|
|
19
|
-
});
|
|
20
|
-
return tree;
|
|
21
|
-
};
|
|
14
|
+
import { render } from '../../../../../jest/render';
|
|
22
15
|
|
|
23
16
|
const mockAxios = new MockAdapter(api.axiosInstance);
|
|
24
17
|
|
|
@@ -52,12 +52,14 @@ export default StyleSheet.create({
|
|
|
52
52
|
},
|
|
53
53
|
commonButton: {
|
|
54
54
|
height: 40,
|
|
55
|
+
width: 80,
|
|
55
56
|
justifyContent: 'center',
|
|
56
57
|
alignItems: 'center',
|
|
57
58
|
},
|
|
58
59
|
row: {
|
|
59
60
|
flexDirection: 'row',
|
|
60
61
|
alignItems: 'center',
|
|
62
|
+
marginHorizontal: 20,
|
|
61
63
|
},
|
|
62
64
|
container: {
|
|
63
65
|
position: 'absolute',
|
|
@@ -66,12 +68,8 @@ export default StyleSheet.create({
|
|
|
66
68
|
alignItems: 'center',
|
|
67
69
|
},
|
|
68
70
|
textDate: {
|
|
69
|
-
marginLeft: 32,
|
|
70
71
|
marginRight: 10,
|
|
71
72
|
},
|
|
72
|
-
iconDate: {
|
|
73
|
-
marginRight: 32,
|
|
74
|
-
},
|
|
75
73
|
timer: {
|
|
76
74
|
height: 80,
|
|
77
75
|
marginTop: 20,
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useEffect,
|
|
3
|
+
useMemo,
|
|
4
|
+
useRef,
|
|
5
|
+
useState,
|
|
6
|
+
useCallback,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import { View, Animated } from 'react-native';
|
|
3
9
|
import { Constants, Colors } from '../../configs';
|
|
4
10
|
import Text from '../../commons/Text';
|
|
5
11
|
import styles from './Styles/TimerStyles';
|
|
6
12
|
|
|
7
|
-
let time = -1;
|
|
8
|
-
let isFirstTime = true;
|
|
9
|
-
|
|
10
13
|
const Timer = ({
|
|
11
14
|
width = Constants.width,
|
|
12
15
|
onChangeValue,
|
|
@@ -29,70 +32,91 @@ const Timer = ({
|
|
|
29
32
|
}) => {
|
|
30
33
|
const scrollViewRef = useRef();
|
|
31
34
|
const [scrollX] = useState(new Animated.Value(0));
|
|
35
|
+
const isFirstTime = useRef(true); // Use useRef to track the first render
|
|
32
36
|
|
|
33
|
-
const snapSegment =
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
const snapSegment = useMemo(
|
|
38
|
+
() => segmentWidth + segmentSpacing,
|
|
39
|
+
[segmentWidth, segmentSpacing]
|
|
40
|
+
);
|
|
41
|
+
const spacerWidth = useMemo(
|
|
42
|
+
() => (width - segmentWidth) / 2,
|
|
43
|
+
[width, segmentWidth]
|
|
44
|
+
);
|
|
45
|
+
const timerWidth = useMemo(
|
|
46
|
+
() => width - segmentWidth + (maximum - minimum) * snapSegment,
|
|
47
|
+
[width, segmentWidth, maximum, minimum, snapSegment]
|
|
48
|
+
);
|
|
36
49
|
|
|
37
50
|
const renderTime = useMemo(() => {
|
|
51
|
+
let time = -1;
|
|
38
52
|
const data = [...Array(maximum - minimum + 1).keys()].map(
|
|
39
53
|
(i) => i + minimum
|
|
40
54
|
);
|
|
55
|
+
|
|
41
56
|
return (
|
|
42
57
|
<View style={[styles.wrap, { width: timerWidth + segmentWidth }]}>
|
|
43
|
-
<View
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
<View style={{ width: spacerWidth }} />
|
|
59
|
+
{data.map((i) => {
|
|
60
|
+
const isStep = i % step === 0;
|
|
61
|
+
if (isStep) {
|
|
62
|
+
time += 1;
|
|
63
|
+
}
|
|
49
64
|
return (
|
|
50
65
|
<View key={i}>
|
|
51
66
|
<View
|
|
52
67
|
style={{
|
|
53
|
-
backgroundColor:
|
|
54
|
-
height:
|
|
68
|
+
backgroundColor: isStep ? stepColor : normalColor,
|
|
69
|
+
height: isStep ? stepHeight : normalHeight,
|
|
55
70
|
width: segmentWidth,
|
|
56
71
|
marginRight: segmentSpacing,
|
|
57
72
|
}}
|
|
58
73
|
/>
|
|
59
|
-
{
|
|
60
|
-
<Text type="Label" color={Colors.Gray7} style={styles.time}>
|
|
61
|
-
time < 9 ? '0' +
|
|
62
|
-
|
|
74
|
+
{isStep && (
|
|
75
|
+
<Text type="Label" color={Colors.Gray7} style={styles.time}>
|
|
76
|
+
{`${time < 9 ? '0' + time : time}:00`}
|
|
77
|
+
</Text>
|
|
63
78
|
)}
|
|
64
79
|
</View>
|
|
65
80
|
);
|
|
66
81
|
})}
|
|
67
82
|
</View>
|
|
68
83
|
);
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
}, [
|
|
85
|
+
maximum,
|
|
86
|
+
minimum,
|
|
87
|
+
step,
|
|
88
|
+
stepColor,
|
|
89
|
+
normalColor,
|
|
90
|
+
stepHeight,
|
|
91
|
+
normalHeight,
|
|
92
|
+
segmentWidth,
|
|
93
|
+
segmentSpacing,
|
|
94
|
+
timerWidth,
|
|
95
|
+
spacerWidth,
|
|
96
|
+
]);
|
|
71
97
|
|
|
72
98
|
useEffect(() => {
|
|
73
99
|
const scrollListener = scrollX.addListener(({ value: timeValue }) => {
|
|
74
|
-
!isFirstTime
|
|
100
|
+
if (!isFirstTime.current) {
|
|
101
|
+
onChangeValue(timeValue, selected);
|
|
102
|
+
}
|
|
75
103
|
});
|
|
104
|
+
|
|
76
105
|
return () => scrollX.removeListener(scrollListener);
|
|
77
|
-
|
|
78
|
-
}, [isFirstTime, selected]);
|
|
106
|
+
}, [scrollX, onChangeValue, selected]);
|
|
79
107
|
|
|
80
108
|
useEffect(() => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
109
|
+
const timeoutId = setTimeout(() => {
|
|
110
|
+
if (scrollViewRef.current) {
|
|
111
|
+
scrollViewRef.current.scrollTo({ x: value, animated: false });
|
|
112
|
+
}
|
|
113
|
+
isFirstTime.current = false; // Set to false after initial scroll
|
|
114
|
+
}, 400);
|
|
86
115
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
clearTimeout(to);
|
|
92
|
-
isFirstTime = false;
|
|
93
|
-
}, 400);
|
|
94
|
-
}
|
|
95
|
-
}, [value, scrollViewRef]);
|
|
116
|
+
return () => clearTimeout(timeoutId);
|
|
117
|
+
}, [value]);
|
|
118
|
+
|
|
119
|
+
const handleScrollEndDrag = useCallback(onScrollEndDrag, [onScrollEndDrag]);
|
|
96
120
|
|
|
97
121
|
return (
|
|
98
122
|
<View>
|
|
@@ -104,17 +128,11 @@ const Timer = ({
|
|
|
104
128
|
showsHorizontalScrollIndicator={false}
|
|
105
129
|
scrollEventThrottle={16}
|
|
106
130
|
onScroll={Animated.event(
|
|
107
|
-
[
|
|
108
|
-
{
|
|
109
|
-
nativeEvent: {
|
|
110
|
-
contentOffset: { x: scrollX },
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
],
|
|
131
|
+
[{ nativeEvent: { contentOffset: { x: scrollX } } }],
|
|
114
132
|
{ useNativeDriver: true }
|
|
115
133
|
)}
|
|
116
|
-
onScrollEndDrag={
|
|
117
|
-
onMomentumScrollEnd={
|
|
134
|
+
onScrollEndDrag={handleScrollEndDrag}
|
|
135
|
+
onMomentumScrollEnd={handleScrollEndDrag}
|
|
118
136
|
>
|
|
119
137
|
{renderTime}
|
|
120
138
|
</Animated.ScrollView>
|
|
@@ -5,7 +5,6 @@ import { Calendar } from 'react-native-calendars';
|
|
|
5
5
|
|
|
6
6
|
import { act, create } from 'react-test-renderer';
|
|
7
7
|
import PlayBackCamera from '..';
|
|
8
|
-
import { ModalCustom } from '../../../commons/Modal';
|
|
9
8
|
import Text from '../../../commons/Text';
|
|
10
9
|
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
11
10
|
import { SCProvider } from '../../../context';
|
|
@@ -21,7 +20,14 @@ jest.mock('@react-navigation/native', () => {
|
|
|
21
20
|
}),
|
|
22
21
|
useRoute: jest.fn().mockReturnValue({
|
|
23
22
|
params: {
|
|
24
|
-
item: {
|
|
23
|
+
item: {
|
|
24
|
+
configuration: {
|
|
25
|
+
time_zone: 0,
|
|
26
|
+
playback: '',
|
|
27
|
+
name: 'name',
|
|
28
|
+
uri: '',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
25
31
|
thumbnail: {},
|
|
26
32
|
},
|
|
27
33
|
}),
|
|
@@ -43,23 +49,26 @@ describe('Test PlayBackCamera', () => {
|
|
|
43
49
|
tree = await create(wrapComponent());
|
|
44
50
|
});
|
|
45
51
|
const instance = tree.root;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const textOpenModal = instance.findAll(
|
|
52
|
+
|
|
53
|
+
const textOpenModal = instance.find(
|
|
49
54
|
(el) =>
|
|
50
55
|
el.props.accessibilityLabel === AccessibilityLabel.OPEN_DATE_MODAL &&
|
|
51
|
-
el.type ===
|
|
56
|
+
el.type === TouchableOpacity
|
|
52
57
|
);
|
|
53
58
|
|
|
54
59
|
await act(async () => {
|
|
55
|
-
textOpenModal
|
|
60
|
+
textOpenModal.props.onPress();
|
|
56
61
|
});
|
|
57
62
|
|
|
58
63
|
const texts = instance.findAllByType(Text);
|
|
59
64
|
await act(async () => {
|
|
60
65
|
texts[0].props.onPress();
|
|
61
66
|
});
|
|
62
|
-
|
|
67
|
+
|
|
68
|
+
let modalCustom = instance.find(
|
|
69
|
+
(el) => el.props.accessibilityLabel === AccessibilityLabel.MODAL_CUSTOM
|
|
70
|
+
);
|
|
71
|
+
expect(modalCustom.props.isVisible).toBeTruthy();
|
|
63
72
|
|
|
64
73
|
const Calendars = instance.findAllByType(Calendar);
|
|
65
74
|
expect(Calendars).toHaveLength(1);
|
|
@@ -69,27 +78,26 @@ describe('Test PlayBackCamera', () => {
|
|
|
69
78
|
|
|
70
79
|
expect(texts[0].props.children).toEqual('01/07/2022');
|
|
71
80
|
|
|
72
|
-
const buttonCancel = instance.
|
|
81
|
+
const buttonCancel = instance.find(
|
|
73
82
|
(el) =>
|
|
74
83
|
el.props.accessibilityLabel === AccessibilityLabel.ON_PRESS_CANCEL &&
|
|
75
84
|
el.type === TouchableOpacity
|
|
76
85
|
);
|
|
77
86
|
await act(async () => {
|
|
78
|
-
buttonCancel
|
|
87
|
+
buttonCancel.props.onPress();
|
|
79
88
|
});
|
|
80
|
-
|
|
89
|
+
|
|
81
90
|
const todayStr = moment().format('DD/MM/YYYY');
|
|
82
91
|
expect(texts[0].props.children).toEqual(todayStr);
|
|
83
92
|
|
|
84
|
-
const buttonOK = instance.
|
|
93
|
+
const buttonOK = instance.find(
|
|
85
94
|
(el) =>
|
|
86
95
|
el.props.accessibilityLabel === AccessibilityLabel.ON_PRESS_OK &&
|
|
87
96
|
el.type === TouchableOpacity
|
|
88
97
|
);
|
|
89
98
|
await act(async () => {
|
|
90
|
-
buttonOK
|
|
99
|
+
buttonOK.props.onPress();
|
|
91
100
|
});
|
|
92
|
-
expect(HeaderCustoms[0].props.isVisible).toBeFalsy();
|
|
93
101
|
|
|
94
102
|
const buttonAddDate = instance.findAll(
|
|
95
103
|
(el) =>
|
|
@@ -100,7 +108,9 @@ describe('Test PlayBackCamera', () => {
|
|
|
100
108
|
await act(async () => {
|
|
101
109
|
await buttonAddDate[0].props.onPress();
|
|
102
110
|
});
|
|
103
|
-
expect(texts[0].props.children).toEqual(
|
|
111
|
+
expect(texts[0].props.children).toEqual(
|
|
112
|
+
moment().add(1, 'days').format('DD/MM/YYYY')
|
|
113
|
+
);
|
|
104
114
|
|
|
105
115
|
const buttonSubDate = instance.findAll(
|
|
106
116
|
(el) =>
|
|
@@ -112,9 +122,7 @@ describe('Test PlayBackCamera', () => {
|
|
|
112
122
|
await buttonSubDate[0].props.onPress();
|
|
113
123
|
});
|
|
114
124
|
|
|
115
|
-
expect(texts[0].props.children).toEqual(
|
|
116
|
-
moment().subtract(1, 'days').format('DD/MM/YYYY')
|
|
117
|
-
);
|
|
125
|
+
expect(texts[0].props.children).toEqual(moment().format('DD/MM/YYYY'));
|
|
118
126
|
// todo Bang add timer test later
|
|
119
127
|
const timerScroll = instance.findAllByType(Animated.ScrollView);
|
|
120
128
|
const timer = instance.findAllByType(Timer);
|
|
@@ -148,7 +156,7 @@ describe('Test PlayBackCamera', () => {
|
|
|
148
156
|
});
|
|
149
157
|
const media = instance.findByType(MediaPlayerFull);
|
|
150
158
|
expect(media.props.uri).toEqual(
|
|
151
|
-
`=${moment().
|
|
159
|
+
`=${moment().format('YYYYMMDDT003730\\Z')}`
|
|
152
160
|
);
|
|
153
161
|
});
|
|
154
162
|
});
|