@eohjsc/react-native-smart-city 0.4.60 → 0.4.62

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 (38) hide show
  1. package/package.json +1 -1
  2. package/src/commons/Action/ItemQuickAction.js +1 -1
  3. package/src/commons/Action/__test__/ItemQuickAction.test.js +21 -3
  4. package/src/commons/Automate/ItemAutomate.js +4 -9
  5. package/src/commons/Button/index.js +4 -2
  6. package/src/commons/Grid/GridItem.js +20 -0
  7. package/src/commons/Grid/GridItemStyles.js +32 -0
  8. package/src/configs/API.js +0 -2
  9. package/src/configs/Constants.js +0 -1
  10. package/src/context/actionType.ts +1 -0
  11. package/src/context/reducer.ts +19 -1
  12. package/src/screens/Automate/AddNewAction/ChooseAction.js +0 -2
  13. package/src/screens/Automate/AddNewAction/ChooseConfig.js +46 -161
  14. package/src/screens/Automate/AddNewAction/Components/SelectDevices.js +2 -6
  15. package/src/screens/Automate/AddNewAction/NewActionWrapper.js +10 -6
  16. package/src/screens/Automate/AddNewAction/SelectMonitorDevices.js +1 -0
  17. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +143 -173
  18. package/src/screens/Automate/AddNewAction/Styles/SelectActionStyles.js +8 -0
  19. package/src/screens/Automate/AddNewAction/Styles/SetupSensorStyles.js +29 -62
  20. package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +77 -9
  21. package/src/screens/Automate/AddNewAction/__test__/ChooseConfig.test.js +23 -83
  22. package/src/screens/Automate/AddNewAction/__test__/SelectControlDevices.test.js +2 -19
  23. package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +125 -94
  24. package/src/screens/Automate/AddNewAutoSmart/AddAutomationTypeSmart.js +0 -4
  25. package/src/screens/Automate/AddNewAutoSmart/AddTypeSmart.js +24 -27
  26. package/src/screens/Automate/AddNewAutoSmart/AddUnknownTypeSmart.js +0 -4
  27. package/src/screens/Automate/AddNewAutoSmart/__test__/AddNewAutoSmart.test.js +1 -21
  28. package/src/screens/Automate/ScriptDetail/utils.js +42 -19
  29. package/src/screens/Automate/index.js +2 -4
  30. package/src/screens/Device/detail.js +4 -2
  31. package/src/screens/Device/hooks/__test__/useEvaluateValue.test.js +1 -1
  32. package/src/screens/Device/hooks/useEvaluateValue.js +10 -6
  33. package/src/screens/Notification/__test__/Notification.test.js +10 -0
  34. package/src/screens/Unit/__test__/AddMenu.test.js +76 -0
  35. package/src/screens/WaterQualityGuide/__test__/index.test.js +0 -5
  36. package/src/utils/I18n/translations/en.js +2 -0
  37. package/src/utils/I18n/translations/vi.js +2 -0
  38. package/src/utils/Route/index.js +5 -0
@@ -32,9 +32,43 @@ export const getAutomationData = (automate) => {
32
32
  return null;
33
33
  };
34
34
 
35
+ const generateAutomationConditionValueEvaluation = (
36
+ automateData,
37
+ valueEvaluations,
38
+ t
39
+ ) => {
40
+ const { action, end_device_name, config_name, value } = automateData;
41
+
42
+ const index = value[1];
43
+ const valueEvaluation = valueEvaluations?.find((v) => v.id === value[0]);
44
+
45
+ if (valueEvaluation) {
46
+ if (valueEvaluation.template === 'range') {
47
+ return `${config_name} ${t('is')} ${
48
+ valueEvaluation.configuration.ranges[index]?.evaluate.text
49
+ }`;
50
+ }
51
+ if (valueEvaluation.template === 'boolean') {
52
+ return `${config_name} ${t('is')} ${
53
+ index
54
+ ? valueEvaluation.configuration.on.text
55
+ : valueEvaluation.configuration.off.text
56
+ }`;
57
+ }
58
+ }
59
+ let textEvent = '';
60
+ if (config_name) {
61
+ const stateConditionData = null;
62
+ textEvent = `${config_name} - ${t(stateConditionData?.stateValue[value])}`;
63
+ } else {
64
+ textEvent = `${end_device_name} - ${action}`;
65
+ }
66
+ return textEvent;
67
+ };
68
+
35
69
  export const generateAutomationConditionText = (
36
70
  automate,
37
- valueEvaluation,
71
+ valueEvaluations,
38
72
  t
39
73
  ) => {
40
74
  const automateData = getAutomationData(automate);
@@ -44,6 +78,13 @@ export const generateAutomationConditionText = (
44
78
 
45
79
  if ([AUTOMATE_TYPE.VALUE_CHANGE].includes(automate?.type)) {
46
80
  const { condition, config_name, value } = automateData;
81
+ if (condition === 'value_evaluation') {
82
+ return generateAutomationConditionValueEvaluation(
83
+ automateData,
84
+ valueEvaluations,
85
+ t
86
+ );
87
+ }
47
88
 
48
89
  let text;
49
90
  if (condition === '>') {
@@ -90,24 +131,6 @@ export const generateAutomationConditionText = (
90
131
  const textWeekday = sortWeekday.map((item) => weekday[item]).join(', ');
91
132
  return `${textWeekday} ${t('at')} ${time}`;
92
133
  }
93
- } else if ([AUTOMATE_TYPE.EVENT].includes(automate?.type)) {
94
- const { action, end_device_name, config_name, value } = automateData;
95
-
96
- if (valueEvaluation) {
97
- return `${config_name} ${t('is')} ${
98
- valueEvaluation.configuration.ranges[value]?.evaluate.text
99
- }`;
100
- }
101
- let textEvent = '';
102
- if (config_name) {
103
- const stateConditionData = null;
104
- textEvent = `${config_name} - ${t(
105
- stateConditionData?.stateValue[value]
106
- )}`;
107
- } else {
108
- textEvent = `${end_device_name} - ${action}`;
109
- }
110
- return textEvent;
111
134
  }
112
135
  return null;
113
136
  };
@@ -60,10 +60,7 @@ const Automate = () => {
60
60
  if (success && data && data.length) {
61
61
  setAutomatesData(data);
62
62
  }
63
- const timeout = setTimeout(() => {
64
- setIsLoading(false);
65
- clearTimeout(timeout);
66
- }, 1000);
63
+ setIsLoading(false);
67
64
  }, []);
68
65
 
69
66
  const onPressItem = useCallback(
@@ -197,6 +194,7 @@ const Automate = () => {
197
194
 
198
195
  useLayoutEffect(() => {
199
196
  setOptions({
197
+ /* istanbul ignore next */
200
198
  headerRight: () => (
201
199
  <TouchableOpacity style={styles.buttonAdd}>
202
200
  <IconFill name={'plus-circle'} size={28} color={Colors.Orange} />
@@ -513,8 +513,10 @@ const DeviceDetail = ({ route }) => {
513
513
  }
514
514
  });
515
515
  if (item.configuration.config) {
516
- !configIds.includes(item.configuration.config) &&
517
- configIds.push(item.configuration.config);
516
+ const config = item.configuration.config;
517
+ config?.id &&
518
+ !configIds.includes(config.id) &&
519
+ configIds.push(config.id);
518
520
  }
519
521
  });
520
522
  configIdsTemp.current = configIds.filter(Boolean);
@@ -177,7 +177,7 @@ describe('useEvaluateValue', () => {
177
177
 
178
178
  it('test evaluate fetch from server if not exists', async () => {
179
179
  const mock = new MockAdapter(api.axiosInstance);
180
- mock.onGet(API.FETCH_VALUE_EVALUATION(111)).reply(200, {
180
+ mock.onGet(API.VALUE_EVALUATIONS()).reply(200, {
181
181
  unit_id: 1,
182
182
  configs: [111],
183
183
  });
@@ -87,7 +87,7 @@ export const useEvaluateValue = () => {
87
87
  return evaluateValue;
88
88
  };
89
89
 
90
- export const useGetEvaluateValue = (configId) => {
90
+ export const useGetEvaluateValue = (configId, unitId) => {
91
91
  const valueEvaluations = useSCContextSelector((state) => {
92
92
  return state.valueEvaluations;
93
93
  });
@@ -95,13 +95,17 @@ export const useGetEvaluateValue = (configId) => {
95
95
 
96
96
  if (configId && valueEvaluations[configId] === undefined) {
97
97
  (async () => {
98
- const { success, data } = await axiosGet(
99
- API.FETCH_VALUE_EVALUATION(configId)
100
- );
98
+ const { success, data } = await axiosGet(API.VALUE_EVALUATIONS(), {
99
+ configs__id: configId,
100
+ });
101
101
  if (success) {
102
+ setAction(Action.INIT_VALUE_EVALUATIONS, {
103
+ configId: configId,
104
+ });
105
+
102
106
  setAction(Action.UPDATE_VALUE_EVALUATIONS, {
103
- unitId: data.unit_id,
104
- data: [data],
107
+ unitId: unitId,
108
+ data: data.results,
105
109
  });
106
110
  }
107
111
  })();
@@ -12,6 +12,8 @@ import { API } from '../../../configs';
12
12
  import api from '../../../utils/Apis/axios';
13
13
  import { WrapHeaderScrollable } from '../../../commons';
14
14
 
15
+ import { getPusher } from '../../../utils/Pusher';
16
+
15
17
  const wrapComponent = () => (
16
18
  <SCProvider initState={mockSCStore({})}>
17
19
  <NavigationContext.Provider
@@ -154,4 +156,12 @@ describe('test Notification', () => {
154
156
  });
155
157
  expect(refreshControl).toBeDefined();
156
158
  });
159
+
160
+ it('should call unwatchNotificationData when unmounting', async () => {
161
+ await act(async () => {
162
+ tree = await create(wrapComponent());
163
+ await tree.unmount();
164
+ });
165
+ expect(getPusher().unsubscribe).toBeCalledWith('private-user-1');
166
+ });
157
167
  });
@@ -8,6 +8,7 @@ import AddMenu from '../AddMenu';
8
8
  import { useNavigation } from '@react-navigation/native';
9
9
  import { ToastBottomHelper } from '../../../utils/Utils';
10
10
  import { getTranslate } from '../../../utils/I18n';
11
+ import Routes from '../../../utils/Route';
11
12
 
12
13
  const mockedAfterItemClick = jest.fn();
13
14
  const mockedHideAddModal = jest.fn();
@@ -130,4 +131,79 @@ describe('Test AddMenu Unit', () => {
130
131
  });
131
132
  expect(spyToastError).not.toBeCalled();
132
133
  });
134
+
135
+ it('add sub_unit but has not permission', async () => {
136
+ let unit = {
137
+ id: 1,
138
+ name: 'Unit 1',
139
+ stations: [
140
+ { name: 'station name 1' },
141
+ { name: 'station name 2' },
142
+ { name: 'station name 3' },
143
+ ],
144
+ };
145
+ await act(async () => {
146
+ tree = await create(
147
+ wrapComponent(unit, {
148
+ auth: {
149
+ account: {
150
+ user: {
151
+ permissions: {
152
+ max_stations_per_unit: 1,
153
+ },
154
+ },
155
+ },
156
+ },
157
+ })
158
+ );
159
+ });
160
+
161
+ const instance = tree.root;
162
+ const menuActionAddnew = instance.findByType(MenuActionAddnew);
163
+ await act(async () => {
164
+ menuActionAddnew.props.onItemClick(menuActionAddnew.props.dataActions[0]);
165
+ });
166
+ expect(spyToastError).toBeCalledWith(
167
+ getTranslate('en', 'reach_max_stations_per_unit'),
168
+ '',
169
+ 7000
170
+ );
171
+ });
172
+
173
+ it('add smart account', async () => {
174
+ let unit = {
175
+ id: 1,
176
+ name: 'Unit 1',
177
+ stations: [
178
+ { name: 'station name 1' },
179
+ { name: 'station name 2' },
180
+ { name: 'station name 3' },
181
+ ],
182
+ };
183
+ await act(async () => {
184
+ tree = await create(
185
+ wrapComponent(unit, {
186
+ auth: {
187
+ account: {
188
+ user: {
189
+ permissions: {
190
+ max_stations_per_unit: 1,
191
+ },
192
+ },
193
+ },
194
+ },
195
+ })
196
+ );
197
+ });
198
+
199
+ const instance = tree.root;
200
+ const menuActionAddnew = instance.findByType(MenuActionAddnew);
201
+ await act(async () => {
202
+ menuActionAddnew.props.onItemClick(menuActionAddnew.props.dataActions[3]);
203
+ });
204
+ expect(mockedNavigate).toBeCalledWith(Routes.SmartAccountStack, {
205
+ params: { unitId: 1, unitName: 'Unit 1' },
206
+ screen: 'SmartAccount',
207
+ });
208
+ });
133
209
  });
@@ -6,11 +6,6 @@ import Text from '../../../commons/Text';
6
6
  import { SCProvider } from '../../../context';
7
7
  import { mockSCStore } from '../../../context/mockStore';
8
8
 
9
- jest.mock('react', () => ({
10
- ...jest.requireActual('react'),
11
- useLayoutEffect: jest.fn(),
12
- }));
13
-
14
9
  const wrapComponent = (route) => (
15
10
  <SCProvider initState={mockSCStore({})}>
16
11
  <WaterQualityGuide route={route} />
@@ -1444,4 +1444,6 @@ export default {
1444
1444
  end_devices_added: 'end devices added',
1445
1445
  bellow_widget_is_not_configured: 'Bellow widget is not configured',
1446
1446
  bellow_widget_is_wrongly_configured: 'Bellow widget is wrongly configured',
1447
+ 'customize...': 'Customize...',
1448
+ when_value_is: 'When value is',
1447
1449
  };
@@ -1455,4 +1455,6 @@ export default {
1455
1455
  end_devices_added: 'thiết bị được thêm vào',
1456
1456
  bellow_widget_is_not_configured: 'Tiện ích bên dưới chưa được cấu hình',
1457
1457
  bellow_widget_is_wrongly_configured: 'Tiện ích bên dưới được cấu hình sai',
1458
+ 'customize...': 'Tùy chỉnh...',
1459
+ when_value_is: 'Khi giá trị là',
1458
1460
  };
@@ -114,11 +114,16 @@ const Routes = {
114
114
  Browser: 'Browser',
115
115
  ManageAccess: 'ManageAccess',
116
116
  MoveToAnotherSubUnit: 'MoveToAnotherSubUnit',
117
+
118
+ // start automate
117
119
  SelectMonitorDevices: 'SelectMonitorDevices',
118
120
  SelectControlDevices: 'SelectControlDevices',
119
121
  ChooseEvent: 'ChooseEvent',
120
122
  ChooseAction: 'ChooseAction',
121
123
  ChooseConfig: 'ChooseConfig',
124
+ PreviewAutomate: 'PreviewAutomate',
125
+ // end automate
126
+
122
127
  GuestInfo: 'GuestInfo',
123
128
  AddLGDevice: 'AddLGDevice',
124
129
  AddLGDeviceStack: 'AddLGDeviceStack',