@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.
Files changed (36) hide show
  1. package/README.md +44 -6
  2. package/package.json +1 -1
  3. package/src/commons/Device/HorizontalBarChart.js +1 -1
  4. package/src/commons/Device/PowerConsumptionChart.js +159 -0
  5. package/src/commons/Device/ProgressBar/__test__/ProgressBar.test.js +2 -3
  6. package/src/commons/Device/ProgressBar/index.js +36 -38
  7. package/src/commons/Device/ProgressBar/styles.js +18 -24
  8. package/src/commons/Form/CurrencyInput.js +2 -0
  9. package/src/commons/UnitSummary/ConfigHistoryChart/index.js +6 -61
  10. package/src/commons/Widgets/IFrame/IFrame.js +54 -0
  11. package/src/commons/Widgets/IFrame/IFrameStyles.js +35 -0
  12. package/src/commons/Widgets/IFrame/__tests__/IFrame.test.js +74 -0
  13. package/src/commons/Widgets/IFrame/index.js +0 -0
  14. package/src/commons/Widgets/IFrameWithConfig/IFrameWithConfig.js +163 -0
  15. package/src/commons/Widgets/IFrameWithConfig/IFrameWithConfigStyles.js +9 -0
  16. package/src/commons/Widgets/IFrameWithConfig/__tests__/IFrameWithConfig.test.js +284 -0
  17. package/src/commons/Widgets/IFrameWithConfig/index.js +0 -0
  18. package/src/commons/Widgets/Widget.js +0 -0
  19. package/src/commons/Widgets/index.js +0 -0
  20. package/src/configs/AccessibilityLabel.js +3 -0
  21. package/src/configs/Constants.js +5 -0
  22. package/src/hooks/Common/useDevicesStatus.js +23 -23
  23. package/src/screens/Device/__test__/sensorDisplayItem.test.js +3 -3
  24. package/src/screens/Device/components/SensorDisplayItem.js +23 -5
  25. package/src/screens/Device/components/__test__/VisualChart.test.js +2 -9
  26. package/src/screens/PlayBackCamera/Styles/index.js +2 -4
  27. package/src/screens/PlayBackCamera/Timer.js +65 -47
  28. package/src/screens/PlayBackCamera/__test__/index.test.js +27 -19
  29. package/src/screens/PlayBackCamera/index.js +114 -111
  30. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +10 -23
  31. package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +57 -3
  32. package/src/screens/UnitSummary/components/PowerConsumption/index.js +21 -30
  33. package/src/commons/Device/HistoryChart.js +0 -225
  34. package/src/commons/UnitSummary/ConfigHistoryChart/__test__/ConfigHistoryChart.test.js +0 -289
  35. package/src/screens/Device/__test__/DetailHistoryChart.test.js +0 -69
  36. 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, create } from 'react-test-renderer';
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, { useEffect, useMemo, useRef, useState } from '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 = segmentWidth + segmentSpacing;
34
- const spacerWidth = (width - segmentWidth) / 2;
35
- const timerWidth = width - segmentWidth + (maximum - minimum) * snapSegment;
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
- style={{
45
- width: spacerWidth,
46
- }}
47
- />
48
- {data.map((i, index) => {
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: i % step === 0 ? stepColor : normalColor,
54
- height: i % step === 0 ? stepHeight : normalHeight,
68
+ backgroundColor: isStep ? stepColor : normalColor,
69
+ height: isStep ? stepHeight : normalHeight,
55
70
  width: segmentWidth,
56
71
  marginRight: segmentSpacing,
57
72
  }}
58
73
  />
59
- {i % step === 0 && (
60
- <Text type="Label" color={Colors.Gray7} style={styles.time}>{`${
61
- time < 9 ? '0' + ++time : ++time
62
- }:00`}</Text>
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
- // eslint-disable-next-line react-hooks/exhaustive-deps
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 && onChangeValue && onChangeValue(timeValue, selected);
100
+ if (!isFirstTime.current) {
101
+ onChangeValue(timeValue, selected);
102
+ }
75
103
  });
104
+
76
105
  return () => scrollX.removeListener(scrollListener);
77
- // eslint-disable-next-line react-hooks/exhaustive-deps
78
- }, [isFirstTime, selected]);
106
+ }, [scrollX, onChangeValue, selected]);
79
107
 
80
108
  useEffect(() => {
81
- return () => {
82
- time = -1;
83
- isFirstTime = true;
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
- useEffect(() => {
88
- if (isFirstTime) {
89
- const to = setTimeout(() => {
90
- scrollViewRef?.current.scrollTo({ x: value });
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={onScrollEndDrag}
117
- onMomentumScrollEnd={onScrollEndDrag}
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
- const HeaderCustoms = instance.findAllByType(ModalCustom);
47
- expect(HeaderCustoms).toHaveLength(2);
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 === Text
56
+ el.type === TouchableOpacity
52
57
  );
53
58
 
54
59
  await act(async () => {
55
- textOpenModal[0].props.onPress();
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
- expect(HeaderCustoms[0].props.isVisible).toBeTruthy();
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.findAll(
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[0].props.onPress();
87
+ buttonCancel.props.onPress();
79
88
  });
80
- expect(HeaderCustoms[0].props.isVisible).toBeFalsy();
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.findAll(
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[0].props.onPress();
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(todayStr);
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().subtract(1, 'days').format('YYYYMMDDT003730\\Z')}`
159
+ `=${moment().format('YYYYMMDDT003730\\Z')}`
152
160
  );
153
161
  });
154
162
  });