@eohjsc/react-native-smart-city 0.3.81 → 0.3.83

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 (37) hide show
  1. package/package.json +2 -2
  2. package/src/Images/Common/Sunny.png +0 -0
  3. package/src/Images/Common/Sunny@2x.png +0 -0
  4. package/src/Images/Common/Sunny@3x.png +0 -0
  5. package/src/commons/ActionGroup/SliderRangeTemplateStyles.js +1 -0
  6. package/src/commons/ActionGroup/__test__/OnOffButtonTemplate.test.js +54 -12
  7. package/src/commons/Device/ProgressBar/__test__/ProgressBar.test.js +49 -0
  8. package/src/commons/Device/ProgressBar/index.js +45 -0
  9. package/src/commons/Device/ProgressBar/styles.js +33 -0
  10. package/src/commons/Device/RainningSensor/CurrentRainSensor.js +14 -3
  11. package/src/commons/Device/RainningSensor/__test__/CurrentRainSensor.test.js +43 -3
  12. package/src/commons/Popover/__test__/index.test.js +31 -0
  13. package/src/configs/Colors.js +1 -0
  14. package/src/configs/Constants.js +1 -0
  15. package/src/configs/IOPinConstants.js +92 -165
  16. package/src/configs/Images.js +1 -0
  17. package/src/screens/AddNewDevice/__test__/AddNewDevice.test.js +17 -8
  18. package/src/screens/AddNewDevice/index.js +5 -4
  19. package/src/screens/AllGateway/DetailConfigActionInternal/__test__/index.test.js +1 -1
  20. package/src/screens/AllGateway/DetailConfigActionInternal/index.js +21 -23
  21. package/src/screens/AllGateway/DeviceInternalDetail/__test__/index.test.js +8 -6
  22. package/src/screens/AllGateway/DeviceInternalDetail/index.js +2 -0
  23. package/src/screens/AllGateway/hooks/useGateway.js +30 -2
  24. package/src/screens/Device/__test__/DetailHistoryChart.test.js +34 -21
  25. package/src/screens/Device/__test__/EmergencyCountdown.test.js +34 -0
  26. package/src/screens/Device/components/SensorDisplayItem.js +3 -0
  27. package/src/screens/EmergencySetting/__test__/index.test.js +22 -0
  28. package/src/screens/Notification/components/NotificationItem.js +8 -0
  29. package/src/screens/SyncLGDevice/AddLGDevice.js +5 -4
  30. package/src/screens/Unit/Detail.js +8 -7
  31. package/src/screens/Unit/components/MyUnitDevice/index.js +5 -2
  32. package/src/screens/Unit/hook/useFavorites.js +1 -1
  33. package/src/utils/Converter/__test__/timer.test.js +7 -0
  34. package/src/utils/Functions/preloadImages.js +1 -1
  35. package/src/utils/I18n/translations/en.json +3 -1
  36. package/src/utils/I18n/translations/vi.json +4 -1
  37. package/src/utils/Utils.js +18 -11
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.81",
4
+ "version": "0.3.83",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -162,7 +162,7 @@
162
162
  "react-native-credit-card-input": "^0.4.1",
163
163
  "react-native-dash": "^0.0.11",
164
164
  "react-native-deep-linking": "^2.2.0",
165
- "react-native-device-info": "^5.6.3",
165
+ "react-native-device-info": "^10.3.0",
166
166
  "react-native-draggable-flatlist": "^2.6.2",
167
167
  "react-native-fast-image": "^8.3.2",
168
168
  "react-native-geocoder": "^0.5.0",
Binary file
Binary file
Binary file
@@ -15,6 +15,7 @@ export default StyleSheet.create({
15
15
  },
16
16
  slider: {
17
17
  width: 131,
18
+ transform: [{ scaleY: 2 }],
18
19
  },
19
20
  trackSlider: {
20
21
  height: 8,
@@ -1,8 +1,16 @@
1
1
  import React from 'react';
2
+ import { TouchableOpacity } from 'react-native';
2
3
  import { act, create } from 'react-test-renderer';
4
+
3
5
  import OnOffTemplate from '../OnOffTemplate';
4
6
  import { mockSCStore } from '../../../context/mockStore';
5
7
  import { SCProvider } from '../../../context';
8
+ import Text from '../../Text';
9
+ import { useConfigGlobalState } from '../../../iot/states';
10
+
11
+ jest.mock('../../../iot/states', () => ({
12
+ useConfigGlobalState: jest.fn(),
13
+ }));
6
14
 
7
15
  const wrapComponent = (actionGroup, mockDoAction) => (
8
16
  <SCProvider initState={mockSCStore({})}>
@@ -49,45 +57,79 @@ describe('Test OneBigButtonTemplate', () => {
49
57
  action_off_data: action_off_data,
50
58
  icon_off: 'caret-up',
51
59
  text_off: 'OFF',
60
+ config: 1,
52
61
  },
62
+ template: 'on_off_button_action_template',
63
+ id: 1,
53
64
  };
54
65
  let wrapper;
55
66
 
56
- const assertRender = async () => {
67
+ beforeEach(() => {
68
+ useConfigGlobalState.mockClear();
69
+ });
70
+
71
+ const assertRender = async (textValue) => {
57
72
  const mockDoAction = jest.fn();
58
73
 
59
74
  await act(async () => {
60
75
  wrapper = create(wrapComponent(actionGroup, mockDoAction));
61
76
  });
62
77
 
63
- const renderJson = wrapper.toJSON();
64
-
65
- expect(renderJson[1].props?.visible).toEqual(false);
66
- expect(renderJson[1]?.type).toEqual('Modal');
78
+ const instance = wrapper.root;
79
+ const texts = instance.findAllByType(Text);
80
+ expect(texts[0].props.children).toEqual(textValue);
67
81
  };
68
82
 
69
83
  it('render state on', async () => {
70
- await assertRender(true, 'ON');
84
+ useConfigGlobalState.mockImplementation(() => [
85
+ {
86
+ 1: {
87
+ value: 1,
88
+ },
89
+ },
90
+ jest.fn(),
91
+ ]);
92
+ await assertRender('ON');
71
93
  });
72
94
 
73
95
  it('render state off', async () => {
74
- await assertRender(false, 'OFF');
96
+ useConfigGlobalState.mockImplementation(() => [
97
+ {
98
+ 1: {
99
+ value: 0,
100
+ },
101
+ },
102
+ jest.fn(),
103
+ ]);
104
+ await assertRender('OFF');
75
105
  });
76
106
 
77
- const assertActionCall = async (state, action_data) => {
107
+ const assertActionCall = async (state, action_data, data2) => {
108
+ useConfigGlobalState.mockImplementation(() => [
109
+ {
110
+ 1: {
111
+ value: state,
112
+ },
113
+ },
114
+ jest.fn(),
115
+ ]);
78
116
  const mockDoAction = jest.fn();
79
117
  await act(async () => {
80
118
  wrapper = create(wrapComponent(actionGroup, mockDoAction));
81
119
  });
82
-
83
- expect(mockDoAction).not.toHaveBeenCalled();
120
+ const instance = wrapper.root;
121
+ const button = instance.findByType(TouchableOpacity);
122
+ await act(async () => {
123
+ await button.props.onPress();
124
+ });
125
+ expect(mockDoAction).toHaveBeenCalledWith(action_data, data2);
84
126
  };
85
127
 
86
128
  it('action state on', async () => {
87
- await assertActionCall(true, action_off_data);
129
+ await assertActionCall(true, action_on_data, { state: 0, value: 0 });
88
130
  });
89
131
 
90
132
  it('action state off', async () => {
91
- await assertActionCall(false, action_on_data);
133
+ await assertActionCall(false, action_off_data, { state: 1, value: 1 });
92
134
  });
93
135
  });
@@ -0,0 +1,49 @@
1
+ /* eslint-disable promise/prefer-await-to-callbacks */
2
+ import React from 'react';
3
+ import { useSelector } from 'react-redux';
4
+ import renderer, { act } from 'react-test-renderer';
5
+
6
+ import ProgressBar from '..';
7
+ import Text from '../../../Text';
8
+ import { SCProvider } from '../../../../context';
9
+ import { mockSCStore } from '../../../../context/mockStore';
10
+
11
+ jest.mock('react-redux', () => ({
12
+ ...jest.requireActual('react-redux'),
13
+ useSelector: jest.fn(),
14
+ }));
15
+
16
+ const wrapComponent = (item, data) => (
17
+ <SCProvider initState={mockSCStore({})}>
18
+ <ProgressBar item={item} data={data} />
19
+ </SCProvider>
20
+ );
21
+
22
+ describe('Test ProgressBar', () => {
23
+ let tree;
24
+ beforeEach(() => {
25
+ const localState = {
26
+ language: 'en',
27
+ };
28
+ useSelector.mockImplementation((cb) => {
29
+ return cb(localState);
30
+ });
31
+ });
32
+
33
+ it('render ProgressBar', async () => {
34
+ const item = {
35
+ label: 'Value bar',
36
+ configuration: { max_value: 100 },
37
+ value: 8,
38
+ };
39
+ const data = [{ value: 10 }];
40
+ await act(async () => {
41
+ tree = renderer.create(wrapComponent(item, data));
42
+ });
43
+ const instance = tree.root;
44
+ const texts = instance.findAllByType(Text);
45
+ expect(texts[0].props.children).toBe('Value bar');
46
+ expect(texts[1].props.children).toEqual(['Max value', ': ', 100]);
47
+ expect(texts[2].props.children).toEqual([10, '%']);
48
+ });
49
+ });
@@ -0,0 +1,45 @@
1
+ import React, { memo, useMemo } from 'react';
2
+ import { View } from 'react-native';
3
+ import * as Progress from 'react-native-progress';
4
+
5
+ import { Colors } from '../../../configs';
6
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
7
+ import Text from '../../Text';
8
+ import styles from './styles';
9
+
10
+ const ProgressBar = memo(({ data = [], item }) => {
11
+ const t = useTranslations();
12
+
13
+ const maxValue = useMemo(() => {
14
+ return Number(item?.configuration?.max_value) || 60;
15
+ }, [item?.configuration?.max_value]);
16
+ const value = data.length ? data[0].value : 0;
17
+ const percent = value / maxValue; // a number between 0 and 1
18
+
19
+ return (
20
+ <View style={styles.container}>
21
+ <Text size={16} style={styles.textLabel}>
22
+ {item?.label || 'Label'}
23
+ </Text>
24
+
25
+ <Text size={16} style={styles.textMaxValue}>
26
+ {t('max_value')}: {maxValue}
27
+ </Text>
28
+
29
+ <View style={styles.wrapProgressBar}>
30
+ <Progress.Bar
31
+ progress={percent}
32
+ height={40}
33
+ width={200}
34
+ color={Colors.Blue16}
35
+ unfilledColor={Colors.Blue15}
36
+ borderWidth={0}
37
+ borderRadius={10}
38
+ />
39
+ <Text style={styles.textValue}>{value}%</Text>
40
+ </View>
41
+ </View>
42
+ );
43
+ });
44
+
45
+ export default ProgressBar;
@@ -0,0 +1,33 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ import { Colors } from '../../../configs';
4
+
5
+ export default StyleSheet.create({
6
+ container: {
7
+ flex: 1,
8
+ flexDirection: 'column', //column direction
9
+ marginRight: 60,
10
+ marginLeft: 60,
11
+ borderWidth: 1,
12
+ padding: 12,
13
+ borderRadius: 8,
14
+ borderColor: Colors.Gray4,
15
+ },
16
+ textLabel: {
17
+ paddingHorizontal: 16,
18
+ paddingTop: 8,
19
+ },
20
+ textMaxValue: {
21
+ textAlign: 'right',
22
+ },
23
+ wrapProgressBar: {
24
+ flex: 1,
25
+ flexDirection: 'row',
26
+ justifyContent: 'center',
27
+ alignItems: 'center',
28
+ padding: 8,
29
+ },
30
+ textValue: {
31
+ marginLeft: 8,
32
+ },
33
+ });
@@ -6,6 +6,8 @@ import { Colors } from '../../../configs';
6
6
  import { CircleView } from '../../../commons';
7
7
  import Text from '../../../commons/Text';
8
8
  import IconComponent from '../../IconComponent';
9
+ import images from '../../../configs/Images';
10
+ import FImage from '../../FImage';
9
11
 
10
12
  const CurrentRainSensor = memo(({ data = [] }) => {
11
13
  const item = data.length
@@ -31,9 +33,14 @@ const CurrentRainSensor = memo(({ data = [] }) => {
31
33
  start={{ x: 1, y: 0 }}
32
34
  end={{ x: 1, y: 1 }}
33
35
  />
34
- <IconComponent
35
- icon={icon_kit_data?.icon || icon || 'CheckCircleOutlined'}
36
- />
36
+ {icon_kit_data?.icon || icon ? (
37
+ <IconComponent icon={icon_kit_data?.icon || icon} />
38
+ ) : (
39
+ <FImage
40
+ source={images.activeCurrentSensor}
41
+ style={styles.iconDefault}
42
+ />
43
+ )}
37
44
  <Text style={styles.text}>{text}</Text>
38
45
  </CircleView>
39
46
  </View>
@@ -68,4 +75,8 @@ const styles = StyleSheet.create({
68
75
  lineHeight: 32,
69
76
  fontSize: 24,
70
77
  },
78
+ iconDefault: {
79
+ width: 37,
80
+ height: 37,
81
+ },
71
82
  });
@@ -2,6 +2,8 @@ import React from 'react';
2
2
  import { View } from 'react-native';
3
3
  import renderer, { act } from 'react-test-renderer';
4
4
  import CurrentRainSensor from '../CurrentRainSensor';
5
+ import FImage from '../../../FImage';
6
+ import IconComponent from '../../../IconComponent';
5
7
 
6
8
  describe('Test CurrentRainSensor', () => {
7
9
  let tree;
@@ -21,7 +23,7 @@ describe('Test CurrentRainSensor', () => {
21
23
  });
22
24
  const instance = tree.root;
23
25
  const Views = instance.findAllByType(View);
24
- expect(Views).toHaveLength(2);
26
+ expect(Views).toHaveLength(3);
25
27
  });
26
28
 
27
29
  it('render CurrentRainSensor raining: true', async () => {
@@ -40,7 +42,7 @@ describe('Test CurrentRainSensor', () => {
40
42
  });
41
43
  const instance = tree.root;
42
44
  const Views = instance.findAllByType(View);
43
- expect(Views).toHaveLength(2);
45
+ expect(Views).toHaveLength(3);
44
46
  });
45
47
 
46
48
  it('render CurrentRainSensor data empty', async () => {
@@ -49,6 +51,44 @@ describe('Test CurrentRainSensor', () => {
49
51
  });
50
52
  const instance = tree.root;
51
53
  const Views = instance.findAllByType(View);
52
- expect(Views).toHaveLength(2);
54
+ expect(Views).toHaveLength(3);
55
+ });
56
+ it('render CurrentRainSensor default icon', async () => {
57
+ const data = [
58
+ {
59
+ evaluate: {
60
+ text: 'default',
61
+ backgroundColor: '#FEFFE6',
62
+ borderColor: '#FADB14',
63
+ icon_kit_data: '',
64
+ icon: '',
65
+ },
66
+ },
67
+ ];
68
+ await act(async () => {
69
+ tree = renderer.create(<CurrentRainSensor data={data} />);
70
+ });
71
+ const instance = tree.root;
72
+ const fimage = instance.findAllByType(FImage);
73
+ expect(fimage).toHaveLength(1);
74
+ });
75
+ it('render CurrentRainSensor has icon kit and icon', async () => {
76
+ const data = [
77
+ {
78
+ evaluate: {
79
+ text: 'default',
80
+ backgroundColor: '#FEFFE6',
81
+ borderColor: '#FADB14',
82
+ icon_kit_data: 'http:s//',
83
+ icon: 'http:s//',
84
+ },
85
+ },
86
+ ];
87
+ await act(async () => {
88
+ tree = renderer.create(<CurrentRainSensor data={data} />);
89
+ });
90
+ const instance = tree.root;
91
+ const iconComponent = instance.findAllByType(IconComponent);
92
+ expect(iconComponent).toHaveLength(1);
53
93
  });
54
94
  });
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { create, act } from 'react-test-renderer';
3
+ import { SCProvider } from '../../../context';
4
+ import { mockSCStore } from '../../../context/mockStore';
5
+ import PopoverComponent from '../index';
6
+ import Popover from 'react-native-popover-view';
7
+
8
+ const wrapComponent = (data) => (
9
+ <SCProvider initState={mockSCStore({})}>
10
+ <PopoverComponent {...data} />
11
+ </SCProvider>
12
+ );
13
+ const mockOnCloseComplete = jest.fn();
14
+ describe('Test PopoverComponent', () => {
15
+ let tree;
16
+
17
+ it('Test Popover', async () => {
18
+ await act(async () => {
19
+ tree = await create(
20
+ wrapComponent({ isVisible: true, onCloseComplete: mockOnCloseComplete })
21
+ );
22
+ });
23
+ const instance = tree.root;
24
+ const popover = instance.findByType(Popover);
25
+ await act(async () => {
26
+ popover.props.onCloseComplete();
27
+ });
28
+ expect(popover.props.isVisible).toEqual(true);
29
+ expect(mockOnCloseComplete).toBeCalled();
30
+ });
31
+ });
@@ -120,6 +120,7 @@ export const Colors = {
120
120
  Blue13: '#E2F0F8',
121
121
  Blue14: '#D9ECFF',
122
122
  Blue15: '#99CCFF',
123
+ Blue16: '#0059B2',
123
124
 
124
125
  //Range Volcano:
125
126
  Volcano3: '#FFBB96',
@@ -260,6 +260,7 @@ export const NOTIFICATION_TYPES = {
260
260
  NOTIFY_REMOVE_SUB_UNIT: 'NOTIFY_REMOVE_SUB_UNIT',
261
261
  NOTIFY_REMOVE_DEVICE: 'NOTIFY_REMOVE_DEVICE',
262
262
  NOTIFY_EMERGENCY: 'NOTIFY_EMERGENCY',
263
+ NOTIFY_UPGRADE_SYSTEM: 'NOTIFY_UPGRADE_SYSTEM',
263
264
  NOTIFY_CHANGE_UNIT_OLD_OWNER: 'NOTIFY_CHANGE_UNIT_OLD_OWNER',
264
265
  NOTIFY_CHANGE_UNIT_NEW_OWNER: 'NOTIFY_CHANGE_UNIT_NEW_OWNER',
265
266
  AIR_QUALITY: 'AIR_QUALITY',