@eohjsc/react-native-smart-city 0.3.91 → 0.3.93

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 (237) hide show
  1. package/package.json +5 -1
  2. package/src/Images/Common/reorder.svg +3 -0
  3. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/AutoLockStyles.js +1 -1
  4. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/__test__/index.test.js +3 -1
  5. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/index.js +3 -3
  6. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/__test__/index.test.js +3 -10
  7. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/index.js +1 -0
  8. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/SetupGeneratePasscodeStyles.js +1 -1
  9. package/src/commons/ActionGroup/OnOffTemplate/SwitchButtonTemplate.js +13 -5
  10. package/src/commons/ActionGroup/SliderRangeTemplate.js +100 -69
  11. package/src/commons/ActionGroup/SliderRangeTemplateStyles.js +27 -27
  12. package/src/commons/ActionGroup/StatesGridActionTemplate.js +4 -1
  13. package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +4 -1
  14. package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +56 -0
  15. package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +2 -2
  16. package/src/commons/ActionGroup/__test__/SwitchButtonTemplate.test.js +45 -8
  17. package/src/commons/ActionGroup/__test__/index.test.js +0 -19
  18. package/src/commons/ActionGroup/index.js +0 -3
  19. package/src/commons/ActionTemplate/CurtainAction.js +3 -3
  20. package/src/commons/ActionTemplate/CurtainActionStyles.js +1 -1
  21. package/src/commons/ActionTemplate/OnOffButtonAction.js +2 -2
  22. package/src/commons/ActionTemplate/OnOffButtonActionStyles.js +1 -1
  23. package/src/commons/ActionTemplate/OnOffSimpleAction.js +2 -2
  24. package/src/commons/ActionTemplate/OnOffSimpleActionStyles.js +1 -1
  25. package/src/commons/ActionTemplate/OnOffSmartLockAction.js +2 -2
  26. package/src/commons/ActionTemplate/OnOffSmartLockActionStyles.js +1 -1
  27. package/src/commons/ActionTemplate/OneButtonAction.js +1 -1
  28. package/src/commons/ActionTemplate/OneButtonActionStyles.js +1 -1
  29. package/src/commons/ActionTemplate/ThreeButtonAction.js +3 -3
  30. package/src/commons/ActionTemplate/ThreeButtonActionStyles.js +1 -1
  31. package/src/commons/AlertAction/index.js +5 -0
  32. package/src/commons/Auth/AccountList.js +1 -1
  33. package/src/commons/Auth/__test__/OtpInputList.test.js +13 -17
  34. package/src/commons/Automate/ItemAutomate.js +10 -4
  35. package/src/commons/Automate/__test__/ItemAutomate.test.js +11 -11
  36. package/src/commons/BottomButtonView/index.js +22 -4
  37. package/src/commons/Button/index.js +5 -0
  38. package/src/commons/Device/ConnectedViewHeader.js +0 -1
  39. package/src/commons/Device/DeviceAlertStatus.js +2 -1
  40. package/src/commons/Device/Emergency/EmergencyDetail.js +4 -2
  41. package/src/commons/Device/Emergency/__test__/EmergencyDetail.test.js +4 -2
  42. package/src/commons/Device/ProgressBar/index.js +7 -11
  43. package/src/commons/Device/ProgressBar/styles.js +9 -4
  44. package/src/commons/Device/WindSpeed/Anemometer/index.js +3 -1
  45. package/src/commons/Device/WindSpeed/LinearChart/__test__/LinearChart.test.js +14 -1
  46. package/src/commons/Device/WindSpeed/LinearChart/index.js +4 -2
  47. package/src/commons/FlatListDnD/__test__/index.test.js +49 -0
  48. package/src/commons/FlatListDnD/index.js +37 -0
  49. package/src/commons/FlatListDnD/styles.js +12 -0
  50. package/src/commons/Form/__test__/TextInput.test.js +1 -1
  51. package/src/commons/Header/HeaderCustom.js +10 -19
  52. package/src/commons/HorizontalPicker/index.js +65 -38
  53. package/src/commons/IconComponent/index.js +3 -2
  54. package/src/commons/MediaPlayer/__test__/index.test.js +8 -3
  55. package/src/commons/MediaPlayer/index.js +11 -7
  56. package/src/commons/MenuActionMore/index.js +6 -4
  57. package/src/commons/Modal/ModalBottom.js +2 -3
  58. package/src/commons/Modal/ModalCustom.js +2 -3
  59. package/src/commons/NavBar/index.js +48 -50
  60. package/src/commons/OneTapTemplate/NumberUpDownActionTemplate.js +1 -1
  61. package/src/commons/OneTapTemplate/NumberUpDownActionTemplateStyles.js +1 -1
  62. package/src/commons/OneTapTemplate/OptionsDropdownActionTemplate.js +1 -1
  63. package/src/commons/OneTapTemplate/OptionsDropdownActionTemplateStyles.js +1 -1
  64. package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +1 -1
  65. package/src/commons/OneTapTemplate/StatesGridActionTemplateStyles.js +1 -1
  66. package/src/commons/PreventAccess/index.js +1 -1
  67. package/src/commons/Sharing/StationDevicePermissions.js +4 -4
  68. package/src/commons/Sharing/WrapHeaderScrollable.js +5 -5
  69. package/src/commons/Sharing/__test__/DevicePermissionsCheckbox.test.js +2 -2
  70. package/src/commons/SubUnit/OneTap/ItemOneTap.js +12 -59
  71. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +16 -20
  72. package/src/commons/SubUnit/OneTap/index.js +20 -7
  73. package/src/commons/UnitSummary/AirQuality/__test__/index.test.js +4 -0
  74. package/src/commons/UnitSummary/ConfigHistoryChart/__test__/ConfigHistoryChart.test.js +1 -1
  75. package/src/commons/ViewButtonBottom/index.js +32 -4
  76. package/src/configs/API.js +9 -0
  77. package/src/configs/AccessibilityLabel.js +2 -0
  78. package/src/configs/BLE.js +1 -0
  79. package/src/configs/Colors.js +1 -1
  80. package/src/configs/Constants.js +12 -18
  81. package/src/context/actionType.ts +2 -1
  82. package/src/context/mockStore.ts +1 -0
  83. package/src/context/reducer.ts +12 -1
  84. package/src/hooks/Common/__test__/useStatusbar.test.js +5 -5
  85. package/src/hooks/Common/index.js +0 -2
  86. package/src/hooks/Common/useKeyboardShow.js +4 -4
  87. package/src/hooks/Common/useStatusBar.js +2 -2
  88. package/src/hooks/Common/useTitleHeader.js +5 -7
  89. package/src/hooks/Explore/useKeyboardAnimated.js +10 -4
  90. package/src/hooks/IoT/__test__/useRemoteControl.test.js +11 -0
  91. package/src/hooks/IoT/useBluetoothConnection.js +20 -29
  92. package/src/hooks/index.js +1 -2
  93. package/src/hooks/useMqtt.js +95 -0
  94. package/src/iot/Monitor.js +2 -1
  95. package/src/iot/RemoteControl/Bluetooth.js +56 -19
  96. package/src/iot/RemoteControl/__test__/Bluetooth.test.js +140 -0
  97. package/src/iot/mqtt.js +233 -0
  98. package/src/navigations/UnitStack.js +44 -12
  99. package/src/screens/AddLocationMaps/index.js +18 -16
  100. package/src/screens/AddLocationMaps/indexStyle.js +3 -0
  101. package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +1 -2
  102. package/src/screens/AddNewGateway/__test__/AddNewGateway.test.js +5 -17
  103. package/src/screens/AddNewGateway/__test__/SelectDeviceSubUnit.test.js +5 -13
  104. package/src/screens/AddNewGateway/__test__/SelectDeviceUnit.test.js +9 -11
  105. package/src/screens/AddNewGateway/__test__/SelectModbusGateway.test.js +6 -14
  106. package/src/screens/AddNewGateway/__test__/SelectZigbeeGateway.test.js +6 -14
  107. package/src/screens/AddNewGateway/hooks/__Tests__/useWifiManage.test.js +3 -2
  108. package/src/screens/AddNewGateway/index.js +1 -1
  109. package/src/screens/AllCamera/index.js +2 -3
  110. package/src/screens/AllGateway/DetailConfigActionZigbee/__test__/index.test.js +0 -18
  111. package/src/screens/AllGateway/DetailConfigActionZigbee/index.js +1 -1
  112. package/src/screens/AllGateway/DeviceModbusDetail/__test__/index.test.js +5 -2
  113. package/src/screens/AllGateway/hooks/__test__/index.test.js +1 -1
  114. package/src/screens/{AddNewAction → Automate/AddNewAction}/ChooseAction.js +78 -119
  115. package/src/screens/{AddNewAction → Automate/AddNewAction}/ChooseConfig.js +45 -73
  116. package/src/screens/{AddNewAction → Automate/AddNewAction}/Components/LoadingSelectAction.js +1 -1
  117. package/src/screens/{AddNewAction → Automate/AddNewAction}/Components/SelectDevices.js +3 -3
  118. package/src/screens/{AddNewAction → Automate/AddNewAction}/Device/DeviceStyles.js +5 -1
  119. package/src/screens/{AddNewAction → Automate/AddNewAction}/Device/__test__/index.test.js +3 -3
  120. package/src/screens/{AddNewAction → Automate/AddNewAction}/Device/index.js +5 -4
  121. package/src/screens/{AddNewAction → Automate/AddNewAction}/NewActionWrapper.js +5 -7
  122. package/src/screens/{AddNewAction → Automate/AddNewAction}/SelectControlDevices.js +11 -49
  123. package/src/screens/{AddNewAction → Automate/AddNewAction}/SelectMonitorDevices.js +10 -42
  124. package/src/screens/{AddNewAction → Automate/AddNewAction}/SetupConfigCondition.js +52 -101
  125. package/src/screens/{AddNewAction → Automate/AddNewAction}/Styles/SelectActionStyles.js +1 -1
  126. package/src/screens/{AddNewAction → Automate/AddNewAction}/Styles/SelectSensorDevicesStyles.js +1 -1
  127. package/src/screens/{AddNewAction → Automate/AddNewAction}/Styles/SetupSensorStyles.js +4 -2
  128. package/src/screens/{AddNewAction → Automate/AddNewAction}/__test__/ChooseAction.test.js +10 -11
  129. package/src/screens/{AddNewAction → Automate/AddNewAction}/__test__/ChooseConfig.test.js +26 -27
  130. package/src/screens/{AddNewAction → Automate/AddNewAction}/__test__/SelectControlDevices.test.js +9 -9
  131. package/src/screens/{AddNewAction → Automate/AddNewAction}/__test__/SelectMonitorDevices.test.js +5 -5
  132. package/src/screens/{AddNewAction → Automate/AddNewAction}/__test__/SetupSensor.test.js +52 -16
  133. package/src/screens/Automate/AddNewAutoSmart/AddAutomationTypeSmart.js +25 -0
  134. package/src/screens/Automate/AddNewAutoSmart/AddTypeSmart.js +78 -0
  135. package/src/screens/Automate/AddNewAutoSmart/AddUnknownTypeSmart.js +29 -0
  136. package/src/screens/{AddNewAutoSmart → Automate/AddNewAutoSmart}/__test__/AddNewAutoSmart.test.js +18 -41
  137. package/src/screens/{AddNewAutoSmart → Automate/AddNewAutoSmart}/styles/AddNewAutoSmartStyles.js +1 -1
  138. package/src/screens/Automate/Components/InputName.js +64 -0
  139. package/src/screens/{AddNewOneTap/AddNewOneTapStyles.js → Automate/Components/InputNameStyles.js} +3 -3
  140. package/src/screens/{EditActionsList → Automate/EditActionsList}/Styles/indexStyles.js +5 -1
  141. package/src/screens/{EditActionsList → Automate/EditActionsList}/__tests__/index.test.js +17 -31
  142. package/src/screens/{EditActionsList → Automate/EditActionsList}/index.js +49 -51
  143. package/src/screens/Automate/MultiUnits.js +69 -67
  144. package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +134 -0
  145. package/src/screens/Automate/OneTap/index.js +16 -0
  146. package/src/screens/Automate/Scenario/ScenarioName.js +15 -0
  147. package/src/screens/{AddNewOneTap → Automate/Scenario}/__test__/AddNewOneTap.test.js +27 -45
  148. package/src/screens/Automate/ScriptDetail/Components/DeleteScript.js +45 -0
  149. package/src/screens/Automate/ScriptDetail/Components/RenameScript.js +58 -0
  150. package/src/screens/{ScriptDetail → Automate/ScriptDetail}/Styles/indexStyles.js +1 -1
  151. package/src/screens/{ScriptDetail → Automate/ScriptDetail}/__test__/index.test.js +110 -74
  152. package/src/screens/{ScriptDetail → Automate/ScriptDetail}/__test__/useStarredScript.test.js +7 -6
  153. package/src/screens/{ScriptDetail → Automate/ScriptDetail}/hooks/useStarredScript.js +4 -4
  154. package/src/screens/Automate/ScriptDetail/index.js +360 -0
  155. package/src/screens/{ScriptDetail → Automate/ScriptDetail}/utils.js +32 -31
  156. package/src/screens/{SetSchedule → Automate/SetSchedule}/__test__/SelectWeekday.test.js +2 -2
  157. package/src/screens/{SetSchedule → Automate/SetSchedule}/__test__/index.test.js +21 -46
  158. package/src/screens/{SetSchedule → Automate/SetSchedule}/components/RepeatOptionsPopup.js +4 -4
  159. package/src/screens/{SetSchedule → Automate/SetSchedule}/components/RowItem.js +2 -2
  160. package/src/screens/{SetSchedule → Automate/SetSchedule}/components/SelectWeekday.js +3 -3
  161. package/src/screens/Automate/SetSchedule/index.js +140 -0
  162. package/src/screens/{SetSchedule → Automate/SetSchedule}/styles/RepeatOptionsPopupStyles.js +1 -1
  163. package/src/screens/{SetSchedule → Automate/SetSchedule}/styles/RowItemStyles.js +1 -1
  164. package/src/screens/{SetSchedule → Automate/SetSchedule}/styles/SelectWeekdayStyles.js +1 -1
  165. package/src/screens/{SetSchedule → Automate/SetSchedule}/styles/indexStyles.js +1 -1
  166. package/src/screens/Automate/ValueChange/ValueChangeName.js +16 -0
  167. package/src/screens/Automate/__test__/MultiUnits.test.js +77 -121
  168. package/src/screens/Automate/__test__/index.test.js +3 -10
  169. package/src/screens/Automate/constants.js +0 -0
  170. package/src/screens/Automate/index.js +12 -23
  171. package/src/screens/ChangePosition/__test__/index.test.js +75 -0
  172. package/src/screens/ChangePosition/index.js +112 -0
  173. package/src/screens/ChangePosition/styles.js +87 -0
  174. package/src/screens/Device/__test__/detail.test.js +203 -258
  175. package/src/screens/Device/__test__/mqttDetail.test.js +599 -0
  176. package/src/screens/Device/__test__/sensorDisplayItem.test.js +4 -0
  177. package/src/screens/Device/components/SensorDisplayItem.js +3 -8
  178. package/src/screens/Device/components/VisualChart.js +55 -8
  179. package/src/screens/Device/detail.js +78 -30
  180. package/src/screens/Device/hooks/__test__/useEmergencyButton.test.js +35 -13
  181. package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +13 -3
  182. package/src/screens/Device/hooks/useEvaluateValue.js +20 -2
  183. package/src/screens/Device/styles.js +7 -0
  184. package/src/screens/GuestInfo/components/__test__/AccessScheduleSheet.test.js +52 -0
  185. package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +18 -13
  186. package/src/screens/Notification/__test__/Notification.test.js +1 -1
  187. package/src/screens/PlayBackCamera/index.js +2 -3
  188. package/src/screens/SelectUnit/__test__/index.test.js +8 -13
  189. package/src/screens/SharedUnit/index.js +5 -4
  190. package/src/screens/Sharing/SelectUser.js +2 -2
  191. package/src/screens/Sharing/__test__/MemberList.test.js +9 -15
  192. package/src/screens/Sharing/__test__/MemberList2.test.js +10 -16
  193. package/src/screens/Sharing/__test__/SelectUser.test.js +8 -4
  194. package/src/screens/SideMenuDetail/SideMenuDetailStyles.js +1 -1
  195. package/src/screens/SmartAccount/__test__/SmartAccount.test.js +8 -4
  196. package/src/screens/SmartAccount/index.js +9 -9
  197. package/src/screens/SmartAccount/style.js +8 -7
  198. package/src/screens/SubUnit/ManageSubUnit.js +4 -4
  199. package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +9 -28
  200. package/src/screens/TDSGuide/index.js +1 -1
  201. package/src/screens/Template/GatewayList.js +4 -1
  202. package/src/screens/Template/__test__/detail.test.js +14 -20
  203. package/src/screens/Template/detail.js +1 -0
  204. package/src/screens/UVIndexGuide/index.js +2 -2
  205. package/src/screens/Unit/Detail.js +10 -24
  206. package/src/screens/Unit/SelectAddToFavorites.js +1 -1
  207. package/src/screens/Unit/Summaries.js +6 -17
  208. package/src/screens/Unit/__test__/ChooseLocation.test.js +8 -13
  209. package/src/screens/Unit/__test__/Detail.test.js +3 -1
  210. package/src/screens/Unit/__test__/SelectAddToFavorites.test.js +1 -1
  211. package/src/screens/Unit/__test__/SmartAccount.test.js +8 -14
  212. package/src/screens/Unit/__test__/Summaries.test.js +2 -2
  213. package/src/screens/UnitSummary/components/UvIndex/__test__/index.test.js +4 -0
  214. package/src/screens/UnitSummary/components/WaterQuality/__test__/index.test.js +6 -11
  215. package/src/screens/WaterQualityGuide/index.js +10 -5
  216. package/src/utils/FactoryGateway.js +525 -0
  217. package/src/utils/I18n/translations/en.json +28 -19
  218. package/src/utils/I18n/translations/vi.json +26 -20
  219. package/src/utils/Route/index.js +5 -1
  220. package/src/utils/Utils.js +40 -0
  221. package/src/utils/__test__/Utils.test.js +6 -0
  222. package/src/commons/ActionGroup/CurtainButtonTemplate.js +0 -130
  223. package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +0 -109
  224. package/src/commons/Auth/SocialButton.js +0 -54
  225. package/src/commons/Auth/__test__/SocialButton.test.js +0 -46
  226. package/src/commons/Device/SensorConnectedStatus.js +0 -56
  227. package/src/commons/Device/__test__/SensorConnectedStatus.test.js +0 -29
  228. package/src/commons/Sharing/__test__/StationDevicePermission.test.js +0 -85
  229. package/src/hooks/__test__/useInitDeepLink.test.js +0 -28
  230. package/src/hooks/useInitDeepLink.js +0 -25
  231. package/src/screens/AddNewAutoSmart/index.js +0 -149
  232. package/src/screens/AddNewOneTap/index.js +0 -156
  233. package/src/screens/ScriptDetail/hooks/index.js +0 -136
  234. package/src/screens/ScriptDetail/index.js +0 -446
  235. package/src/screens/SetSchedule/index.js +0 -200
  236. /package/src/screens/{AddNewAction → Automate/AddNewAction}/Components/index.js +0 -0
  237. /package/src/screens/{AddNewAction → Automate/AddNewAction}/__test__/LoadingSelectAction.test.js +0 -0
@@ -9,6 +9,8 @@ import { StyleSheet, View } from 'react-native';
9
9
  import { Colors } from '../../../configs';
10
10
  import ChartAggregationOption from '../../../commons/ChartAggregationOption';
11
11
  import Text from '../../../commons/Text';
12
+ import { CHART_GROUP_TYPE } from '../../../configs/Constants';
13
+ import { getDateRangeOfWeek } from '../../../utils/Utils';
12
14
 
13
15
  const groupByTime = (format) => (x) => x[0].format(format);
14
16
 
@@ -26,6 +28,9 @@ const groupByFunc = {
26
28
  hour: groupByHour,
27
29
  };
28
30
 
31
+ const roundNumber = (number, round = 1) =>
32
+ Math.round(number * 10 ** round) / 10 ** round;
33
+
29
34
  export const convertLineChartData = (data = [], valueType = 'raw', groupBy) => {
30
35
  let arr = [];
31
36
  for (let i = 0; i < data.length; i++) {
@@ -38,12 +43,44 @@ export const convertLineChartData = (data = [], valueType = 'raw', groupBy) => {
38
43
  arr = _.groupBy(arr, groupByFunc[groupBy]);
39
44
  arr = Object.entries(arr).map((x) => {
40
45
  if (valueType === 'sum') {
41
- return [moment(x[0]).valueOf(), _.sum(x[1].map((i) => i[1]))];
46
+ if (groupBy === CHART_GROUP_TYPE.WEEK) {
47
+ const dataX = x[0].split('-');
48
+ return [
49
+ getDateRangeOfWeek(dataX[1], dataX[0]),
50
+ roundNumber(_.sum(x[1].map((i) => i[1]))),
51
+ ];
52
+ }
53
+ if (
54
+ groupBy === CHART_GROUP_TYPE.MONTH ||
55
+ groupBy === CHART_GROUP_TYPE.YEAR
56
+ ) {
57
+ return [x[0], roundNumber(_.sum(x[1].map((i) => i[1])))];
58
+ }
59
+ return [
60
+ moment(x[0]).valueOf(),
61
+ roundNumber(_.sum(x[1].map((i) => i[1]))),
62
+ ];
42
63
  }
43
64
  if (valueType === 'avg') {
65
+ if (groupBy === CHART_GROUP_TYPE.WEEK) {
66
+ const dataX = x[0].split('-');
67
+ return [
68
+ getDateRangeOfWeek(dataX[1], dataX[0]),
69
+ roundNumber(_.sum(x[1].map((i) => i[1])) / x[1].length),
70
+ ];
71
+ }
72
+ if (
73
+ groupBy === CHART_GROUP_TYPE.MONTH ||
74
+ groupBy === CHART_GROUP_TYPE.YEAR
75
+ ) {
76
+ return [
77
+ x[0],
78
+ roundNumber(_.sum(x[1].map((i) => i[1])) / x[1].length),
79
+ ];
80
+ }
44
81
  return [
45
82
  moment(x[0]).valueOf(),
46
- _.sum(x[1].map((i) => i[1])) / x[1].length,
83
+ roundNumber(_.sum(x[1].map((i) => i[1])) / x[1].length),
47
84
  ];
48
85
  }
49
86
  /* istanbul ignore next */
@@ -105,11 +142,11 @@ const chartOptions = {
105
142
  };
106
143
 
107
144
  const groupByOptions = [
108
- { title: 'H', data: 'hour' },
109
- { title: 'D', data: 'day' },
110
- { title: 'W', data: 'week' },
111
- { title: 'M', data: 'month' },
112
- { title: 'Y', data: 'year' },
145
+ { title: 'H', data: CHART_GROUP_TYPE.HOUR },
146
+ { title: 'D', data: CHART_GROUP_TYPE.DAY },
147
+ { title: 'W', data: CHART_GROUP_TYPE.WEEK },
148
+ { title: 'M', data: CHART_GROUP_TYPE.MONTH },
149
+ { title: 'Y', data: CHART_GROUP_TYPE.YEAR },
113
150
  ];
114
151
 
115
152
  const VisualChart = ({ item, isDemo = false, isTemplate }) => {
@@ -129,6 +166,12 @@ const VisualChart = ({ item, isDemo = false, isTemplate }) => {
129
166
  );
130
167
  const chartRef = useRef();
131
168
 
169
+ const shouldDisplayCategory =
170
+ value_type !== 'raw' &&
171
+ (groupBy === CHART_GROUP_TYPE.WEEK ||
172
+ groupBy === CHART_GROUP_TYPE.MONTH ||
173
+ groupBy === CHART_GROUP_TYPE.YEAR);
174
+
132
175
  const fetchDataDisplayHistory = useFetchConfigHistory(configs, setChartData);
133
176
 
134
177
  const getSeries = useCallback(() => {
@@ -154,8 +197,12 @@ const VisualChart = ({ item, isDemo = false, isTemplate }) => {
154
197
  setOption((prev) => ({
155
198
  ...prev,
156
199
  series: getSeries(),
200
+ xAxis: {
201
+ ...prev.xAxis,
202
+ type: shouldDisplayCategory ? 'category' : 'datetime',
203
+ },
157
204
  }));
158
- }, [getSeries]);
205
+ }, [getSeries, shouldDisplayCategory]);
159
206
 
160
207
  useEffect(() => {
161
208
  setOption((prev) => {
@@ -25,7 +25,7 @@ import {
25
25
  } from './hooks/useEmergencyButton';
26
26
  import { useFavoriteDevice } from './hooks/useFavoriteDevice';
27
27
  import { usePopover } from '../../hooks/Common';
28
- import { useConfigGlobalState } from '../../iot/states';
28
+ import { setConfigGlobalState, getConfigGlobalState } from '../../iot/states';
29
29
  import { useIsOwnerOfUnit, useBoolean } from '../../hooks/Common';
30
30
  import {
31
31
  useBluetoothConnection,
@@ -58,17 +58,24 @@ import { DEVICE_TYPE, AccessibilityLabel } from '../../configs/Constants';
58
58
  import { axiosGet } from '../../utils/Apis/axios';
59
59
  import { notImplemented } from '../../utils/Utils';
60
60
  import { useReceiveNotifications } from '../../hooks';
61
+ import useChipJsonConfiguration, {
62
+ useConnectChipMqtt,
63
+ } from '../../hooks/useMqtt';
64
+ import { realWatchMultiConfigs } from '../../iot/Monitor';
61
65
 
62
66
  const DeviceDetail = ({ route }) => {
67
+ const configIdsTemp = useRef([]);
68
+
63
69
  const t = useTranslations();
64
70
  const navigation = useNavigation();
65
71
  const token = useSCContextSelector((state) => state.auth.account.token);
66
- const { isLockWhenPickColor } = useSCContextSelector((state) => state.app);
72
+ const { isLockWhenPickColor, appState } = useSCContextSelector(
73
+ (state) => state.app
74
+ );
75
+
67
76
  const { setAction } = useContext(SCContext);
68
77
  const [offsetTitle, setOffsetTitle] = useState(1);
69
78
  const [display, setDisplay] = useState({ items: [] });
70
- // eslint-disable-next-line no-unused-vars
71
- const [configValues, setConfigValues] = useConfigGlobalState('configValues');
72
79
  const [displayValuesData, setDisplayValuesData] = useState({
73
80
  isConnected: false,
74
81
  lastUpdated: null,
@@ -140,7 +147,14 @@ const DeviceDetail = ({ route }) => {
140
147
 
141
148
  useDisconnectedDevice(sensorName, isDeviceHasBle, serverDown);
142
149
 
143
- useDeviceWatchConfigControl(sensor, display);
150
+ const { chips } = useChipJsonConfiguration(unit?.id);
151
+
152
+ const chipFiltered = useMemo(() => {
153
+ return chips?.filter((item) => item?.id === sensor?.chip_id);
154
+ }, [chips, sensor?.chip_id]);
155
+
156
+ const { mqttConfigs } = useConnectChipMqtt(chipFiltered);
157
+ useDeviceWatchConfigControl(sensor, display, mqttConfigs);
144
158
 
145
159
  const isShowSetupEmergencyContact = useMemo(
146
160
  () =>
@@ -150,7 +164,6 @@ const DeviceDetail = ({ route }) => {
150
164
  ).length > 0,
151
165
  [display.items]
152
166
  );
153
-
154
167
  const isShowSetUpSmartLock = useMemo(
155
168
  () =>
156
169
  display.items.filter(
@@ -349,6 +362,18 @@ const DeviceDetail = ({ route }) => {
349
362
  data: { unit, sensor },
350
363
  text: t('manage_access'),
351
364
  });
365
+ menuItems.push({
366
+ route: Routes.ChangePosition,
367
+ data: {
368
+ unit,
369
+ sensor,
370
+ displayItems: display.items,
371
+ evaluate,
372
+ station,
373
+ fetchDataDeviceDetail,
374
+ },
375
+ text: t('change_position'),
376
+ });
352
377
  menuItems.push({
353
378
  text: t('move_to_another_sub_unit'),
354
379
  route: Routes.MoveToAnotherSubUnit,
@@ -439,7 +464,9 @@ const DeviceDetail = ({ route }) => {
439
464
  sensor,
440
465
  unit,
441
466
  sensorName,
467
+ evaluate,
442
468
  station,
469
+ fetchDataDeviceDetail,
443
470
  isMyUnitDeviceScreen,
444
471
  emergencyDeviceId,
445
472
  addToFavorites,
@@ -474,20 +501,32 @@ const DeviceDetail = ({ route }) => {
474
501
  const configIds = [];
475
502
 
476
503
  display.items.map((item) => {
477
- if (item.type !== 'value') {
504
+ if (!item.configuration) {
478
505
  return;
479
506
  }
480
-
481
- if (!item.configuration) {
507
+ if (!['action', 'value'].includes(item.type)) {
482
508
  return;
483
509
  }
484
-
485
- item.configuration.configs.map((config) => {
486
- if (!configIds.includes(config.id)) {
487
- configIds.push(config.id);
510
+ if (item.type === 'action') {
511
+ if (
512
+ [
513
+ 'on_off_button_action_template',
514
+ 'one_button_action_template',
515
+ ].includes(item.configuration.template)
516
+ ) {
517
+ !configIds.includes(item.configuration.configuration.config) &&
518
+ configIds.push(item.configuration.configuration.config);
488
519
  }
489
- });
520
+ }
521
+ if (item.type === 'value') {
522
+ item.configuration.configs.map((config) => {
523
+ if (!configIds.includes(config.id)) {
524
+ configIds.push(config.id);
525
+ }
526
+ });
527
+ }
490
528
  });
529
+ configIdsTemp.current = configIds;
491
530
 
492
531
  configIds.map((id) => {
493
532
  params.append('config', id);
@@ -532,23 +571,28 @@ const DeviceDetail = ({ route }) => {
532
571
  lastUpdated: lastUpdated,
533
572
  };
534
573
  });
535
- setConfigValues((prev) => {
536
- let hasValueChange = false;
537
- data.configs.map((config) => {
538
- if (prev[config.id]?.value !== config.value) {
539
- hasValueChange = true;
540
- prev[config.id] = { ...prev[config.id], value: config.value };
541
- }
542
- setEvaluate((prevE) => ({
543
- ...prevE,
544
- [config?.id]: config?.evaluate,
545
- }));
546
- });
547
- if (hasValueChange) {
548
- return { ...prev };
574
+ const configsData = data.configs.filter(
575
+ (id) => !mqttConfigs.includes(id)
576
+ );
577
+ let configValues = getConfigGlobalState('configValues');
578
+ let hasValueChange = false;
579
+ configsData.map((config) => {
580
+ if (configValues[config.id]?.value !== config.value) {
581
+ hasValueChange = true;
582
+ configValues[config.id] = {
583
+ ...configValues[config.id],
584
+ value: config.value,
585
+ };
549
586
  }
550
- return prev;
587
+ setEvaluate((prev) => ({
588
+ ...prev,
589
+ [config?.id]: config?.evaluate,
590
+ }));
551
591
  });
592
+ if (hasValueChange) {
593
+ configValues = { ...configValues };
594
+ }
595
+ setConfigGlobalState('configValues', { ...configValues });
552
596
  } else if (resp_status >= 500) {
553
597
  setServerDown(true);
554
598
  }
@@ -566,7 +610,7 @@ const DeviceDetail = ({ route }) => {
566
610
  setLoading((preState) => ({ ...preState, isConnected: false }));
567
611
  }
568
612
  // eslint-disable-next-line react-hooks/exhaustive-deps
569
- }, [sensor, display, isNetworkConnected])
613
+ }, [display.items, isNetworkConnected, sensor, mqttConfigs])
570
614
  );
571
615
 
572
616
  const isShowEmergencyResolve =
@@ -673,6 +717,10 @@ const DeviceDetail = ({ route }) => {
673
717
  SCConfig.setCurrentSensorDisplay(sensor);
674
718
  }, [sensor]);
675
719
 
720
+ useEffect(() => {
721
+ appState === 'active' && realWatchMultiConfigs(configIdsTemp.current);
722
+ }, [appState]);
723
+
676
724
  const shouldRender =
677
725
  loading.displayTemplate === false &&
678
726
  loading.isConnected === false &&
@@ -1,5 +1,7 @@
1
1
  import { renderHook } from '@testing-library/react-hooks';
2
2
  import MockAdapter from 'axios-mock-adapter';
3
+ import { act } from 'react-test-renderer';
4
+
3
5
  import { API } from '../../../../configs';
4
6
  import api from '../../../../utils/Apis/axios';
5
7
  import { useEmergencyButton } from '../useEmergencyButton';
@@ -10,28 +12,48 @@ const mockAcquireLockShowing = jest.fn();
10
12
  const mock = new MockAdapter(api.axiosInstance);
11
13
 
12
14
  describe('Test useEmergencyButton', () => {
15
+ let result;
13
16
  it('Test render', async () => {
14
- const { result } = renderHook(() =>
15
- useEmergencyButton(mockFetchDataDeviceDetail, mockAcquireLockShowing)
16
- );
17
+ await act(async () => {
18
+ result = renderHook(() =>
19
+ useEmergencyButton(mockFetchDataDeviceDetail, mockAcquireLockShowing)
20
+ ).result;
21
+ });
17
22
  jest.useFakeTimers();
18
- await result.current.onCancelConfirmAlert();
23
+ await act(async () => {
24
+ await result.current.onCancelConfirmAlert();
25
+ });
26
+
19
27
  expect(result.current.showAlertConfirm).toBe(false);
20
28
  jest.runAllTimers();
21
- await result.current.onEmergencyButtonPress();
29
+ await act(async () => {
30
+ await result.current.onEmergencyButtonPress();
31
+ });
32
+
22
33
  mock.onPost(API.EMERGENCY_BUTTON.SEND_ALERT()).reply(200);
23
- await result.current.onSendNowAlert();
24
- expect(result.current.showAlertConfirm).toBe(true);
34
+
35
+ await act(async () => {
36
+ await result.current.onSendNowAlert();
37
+ });
38
+ expect(result.current.showAlertSent).toBe(true);
25
39
  });
26
40
 
27
41
  it('Test send alert fail', async () => {
28
42
  mock.onPost(API.EMERGENCY_BUTTON.SEND_ALERT()).reply(400);
29
- const { result } = renderHook(() =>
30
- useEmergencyButton(mockFetchDataDeviceDetail, mockAcquireLockShowing)
31
- );
32
- await result.current.onSendNowAlert();
33
- await result.current.onCloseAlertSent();
34
- await result.current.onViewDetails();
43
+ await act(async () => {
44
+ result = renderHook(() =>
45
+ useEmergencyButton(mockFetchDataDeviceDetail, mockAcquireLockShowing)
46
+ ).result;
47
+ });
48
+ await act(async () => {
49
+ await result.current.onSendNowAlert();
50
+ });
51
+ await act(async () => {
52
+ await result.current.onCloseAlertSent();
53
+ });
54
+ await act(async () => {
55
+ await result.current.onViewDetails();
56
+ });
35
57
  expect(result.current.showAlertConfirm).toBe(false);
36
58
  });
37
59
  });
@@ -3,7 +3,7 @@ import { DEVICE_TYPE } from '../../../configs/Constants';
3
3
  import { getConfigControlFromDeviceDisplay } from '../utils';
4
4
  import { useWatchConfigs } from '../../../hooks/IoT';
5
5
 
6
- export const useDeviceWatchConfigControl = (device, display) => {
6
+ export const useDeviceWatchConfigControl = (device, display, mqttConfigs) => {
7
7
  const configsNeedWatching = useMemo(() => {
8
8
  if (
9
9
  !device?.is_managed_by_backend ||
@@ -13,8 +13,18 @@ export const useDeviceWatchConfigControl = (device, display) => {
13
13
  ) {
14
14
  return [];
15
15
  }
16
- return getConfigControlFromDeviceDisplay(display);
17
- }, [device, display]);
16
+
17
+ const configsControl = getConfigControlFromDeviceDisplay(display);
18
+ if (mqttConfigs?.length) {
19
+ return configsControl.filter((id) => !mqttConfigs.includes(id));
20
+ }
21
+ return configsControl;
22
+ }, [
23
+ mqttConfigs,
24
+ device?.device_type,
25
+ device?.is_managed_by_backend,
26
+ display,
27
+ ]);
18
28
 
19
29
  useWatchConfigs(configsNeedWatching);
20
30
  };
@@ -1,5 +1,8 @@
1
- import { useCallback } from 'react';
2
- import { useSCContextSelector } from '../../../context';
1
+ import { useCallback, useContext } from 'react';
2
+ import { SCContext, useSCContextSelector } from '../../../context';
3
+ import { axiosGet } from '../../../utils/Apis/axios';
4
+ import { API } from '../../../configs';
5
+ import { Action } from '../../../context/actionType';
3
6
 
4
7
  const evaluateRange = (value, configuration) => {
5
8
  /*
@@ -98,6 +101,21 @@ export const useGetEvaluateValue = (configId) => {
98
101
  const valueEvaluations = useSCContextSelector((state) => {
99
102
  return state.valueEvaluations;
100
103
  });
104
+ const { setAction } = useContext(SCContext);
105
+
106
+ if (configId && valueEvaluations[configId] === undefined) {
107
+ (async () => {
108
+ const { success, data } = await axiosGet(
109
+ API.FETCH_VALUE_EVALUATION(configId)
110
+ );
111
+ if (success) {
112
+ setAction(Action.UPDATE_VALUE_EVALUATIONS, {
113
+ unitId: data.unit_id,
114
+ data: [data],
115
+ });
116
+ }
117
+ })();
118
+ }
101
119
 
102
120
  return valueEvaluations[configId];
103
121
  };
@@ -24,6 +24,13 @@ export default StyleSheet.create({
24
24
  paddingHorizontal: 4,
25
25
  marginBottom: 16,
26
26
  },
27
+ cameraOrder: {
28
+ alignSelf: 'center',
29
+ width: '100%',
30
+ height: 150,
31
+ paddingHorizontal: 16,
32
+ marginBottom: 16,
33
+ },
27
34
  bottomButtonEmergencyResolve: {
28
35
  borderTopWidth: 1,
29
36
  borderColor: Colors.Gray4,
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import { create, act } from 'react-test-renderer';
3
+
4
+ import { SCProvider } from '../../../../context';
5
+ import { mockSCStore } from '../../../../context/mockStore';
6
+ import AccessScheduleSheet from '../AccessScheduleSheet';
7
+ import BottomSheet from '../../../../commons/BottomSheet';
8
+
9
+ const wrapComponent = (props) => (
10
+ <SCProvider initState={mockSCStore({})}>
11
+ <AccessScheduleSheet {...props} />
12
+ </SCProvider>
13
+ );
14
+
15
+ describe('AccessScheduleSheet', () => {
16
+ let tree;
17
+ const mockOnHide = jest.fn();
18
+ let props = {
19
+ isVisible: true,
20
+ data: {
21
+ access_schedule: {},
22
+ recurring_time_start: {},
23
+ recurring_time_end: {},
24
+ recurring_time_repeat: {},
25
+ temporary_time_start: {},
26
+ temporary_time_end: {},
27
+ },
28
+ onHide: mockOnHide,
29
+ };
30
+ it('render AccessScheduleSheet', async () => {
31
+ await act(async () => {
32
+ tree = await create(wrapComponent(props));
33
+ });
34
+ const instance = tree.root;
35
+ const bottomSheet = instance.findAllByType(BottomSheet);
36
+ expect(bottomSheet[0].props.accessibilityLabel).toEqual(
37
+ 'ACCESS_SCHEDULE_SHEET'
38
+ );
39
+ });
40
+
41
+ it('AccessScheduleSheet onCancel', async () => {
42
+ await act(async () => {
43
+ tree = await create(wrapComponent(props));
44
+ });
45
+ const instance = tree.root;
46
+ const bottomSheet = instance.findAllByType(BottomSheet);
47
+ await act(async () => {
48
+ bottomSheet[0].props.onBackdropPress();
49
+ });
50
+ expect(mockOnHide).toBeCalled();
51
+ });
52
+ });
@@ -11,19 +11,10 @@ import { SCProvider } from '../../../context';
11
11
  import { mockSCStore } from '../../../context/mockStore';
12
12
  import BottomButtonView from '../../../commons/BottomButtonView';
13
13
  import api from '../../../utils/Apis/axios';
14
+ import { useNavigation } from '@react-navigation/native';
14
15
 
15
16
  const mock = new MockAdapter(api.axiosInstance);
16
17
 
17
- const mockNavigate = jest.fn();
18
- jest.mock('@react-navigation/native', () => {
19
- return {
20
- ...jest.requireActual('@react-navigation/native'),
21
- useNavigation: () => ({
22
- navigate: mockNavigate,
23
- }),
24
- };
25
- });
26
-
27
18
  const wrapComponent = (route) => (
28
19
  <SCProvider initState={mockSCStore({})}>
29
20
  <MoveToAnotherSubUnit route={route} />
@@ -88,6 +79,11 @@ describe('Test Render ListSubUnit', () => {
88
79
  },
89
80
  },
90
81
  };
82
+ const mockNavigate = useNavigation().navigate;
83
+
84
+ beforeEach(() => {
85
+ mockNavigate.mockReset();
86
+ });
91
87
 
92
88
  it('render ListSubUnit with out params', async () => {
93
89
  await act(async () => {
@@ -128,13 +124,22 @@ describe('Test Render ListSubUnit', () => {
128
124
  });
129
125
  });
130
126
  mock.onPatch(API.DEVICE.CHANGE_SUB_UNIT(200, 3, 73)).reply(200);
131
- await bottomButtonView.props.onPressMain();
127
+ await act(async () => {
128
+ await bottomButtonView.props.onPressMain();
129
+ });
130
+
132
131
  expect(mockNavigate).toBeCalled();
133
132
  const TouchableOpacities = instance.findAllByType(TouchableOpacity);
134
- await TouchableOpacities[2].props.onPress();
133
+ await act(async () => {
134
+ await TouchableOpacities[2].props.onPress();
135
+ });
136
+
135
137
  mockNavigate.mockClear();
136
138
  mock.onPatch(API.DEVICE.CHANGE_SUB_UNIT(200, 3, 73)).reply(400);
137
- await bottomButtonView.props.onPressMain();
139
+
140
+ await act(async () => {
141
+ await bottomButtonView.props.onPressMain();
142
+ });
138
143
  expect(mockNavigate).not.toBeCalled();
139
144
  });
140
145
  });
@@ -82,7 +82,7 @@ describe('test Notification', () => {
82
82
  expect(notificationItem).toHaveLength(2);
83
83
  });
84
84
 
85
- it.only('test handleOnLoadMore', async () => {
85
+ it('test handleOnLoadMore', async () => {
86
86
  const response = {
87
87
  count: 13,
88
88
  results: [],
@@ -11,7 +11,7 @@ import { Colors, Images } from '../../configs';
11
11
  import { useTranslations } from '../../hooks/Common/useTranslations';
12
12
  import Text from '../../commons/Text';
13
13
  import Timer from './Timer';
14
- import { useStatusBarPreview } from '../../hooks/Common/useStatusBar';
14
+ import { setStatusBarPreview } from '../../hooks/Common/useStatusBar';
15
15
  import MediaPlayerFull from '../../commons/MediaPlayerDetail/MediaPlayerFull';
16
16
  import { DATE_TIME_FORMAT, AccessibilityLabel } from '../../configs/Constants';
17
17
 
@@ -173,8 +173,7 @@ const PlayBackCamera = () => {
173
173
  }, [selected, getHourWithTimeZone]);
174
174
 
175
175
  useEffect(() => {
176
- // eslint-disable-next-line react-hooks/rules-of-hooks
177
- useStatusBarPreview(
176
+ setStatusBarPreview(
178
177
  isShowDate ? Colors.BlackTransparent4 : Colors.TextTransparent
179
178
  );
180
179
  }, [isShowDate]);
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React from 'react';
2
2
  import { TouchableOpacity } from 'react-native';
3
3
  import { useRoute } from '@react-navigation/native';
4
4
  import { act, create } from 'react-test-renderer';
@@ -11,21 +11,14 @@ import { AccessibilityLabel } from '../../../configs/Constants';
11
11
  import Routes from '../../../utils/Route';
12
12
  import api from '../../../utils/Apis/axios';
13
13
  import { API } from '../../../configs';
14
+ import BottomButtonView from '../../../commons/BottomButtonView';
14
15
 
15
16
  const mock = new MockAdapter(api.axiosInstance);
16
17
 
17
- const mockSetState = jest.fn();
18
18
  const mockDispatch = jest.fn();
19
19
  const mockGoBack = jest.fn();
20
20
  const mockNavigate = jest.fn();
21
21
 
22
- jest.mock('react', () => {
23
- return {
24
- ...jest.requireActual('react'),
25
- useState: jest.fn((init) => [init, mockSetState]),
26
- };
27
- });
28
-
29
22
  jest.mock('@react-navigation/native', () => {
30
23
  return {
31
24
  ...jest.requireActual('@react-navigation/native'),
@@ -48,7 +41,6 @@ describe('Test Select unit screen', () => {
48
41
  let tree;
49
42
 
50
43
  beforeEach(() => {
51
- mockSetState.mockClear();
52
44
  mockNavigate.mockClear();
53
45
  });
54
46
 
@@ -74,18 +66,21 @@ describe('Test Select unit screen', () => {
74
66
  ],
75
67
  };
76
68
  mock.onGet(API.AUTOMATE.GET_ALL_UNITS()).reply(200, response.data);
77
- useState.mockImplementation((init) => [response.data, mockSetState]);
69
+
78
70
  await act(async () => {
79
71
  tree = await create(wrapComponent());
80
72
  });
81
73
  const instance = tree.root;
82
74
  const TouchableOpacities = instance.findAllByType(TouchableOpacity);
75
+ const bottomButtonView = instance.findByType(BottomButtonView);
76
+
77
+ expect(bottomButtonView.props.typeMain).toEqual('disabled');
83
78
  expect(TouchableOpacities).toHaveLength(4);
84
79
  await act(async () => {
85
80
  await TouchableOpacities[1].props.onPress();
86
81
  await TouchableOpacities[2].props.onPress(response.data[0]);
87
82
  });
88
- expect(mockSetState).toBeCalledWith(response.data[0]);
83
+ expect(bottomButtonView.props.typeMain).toEqual('primary');
89
84
  });
90
85
 
91
86
  it('Test SelectUnit getAllUnits fail', async () => {
@@ -106,7 +101,7 @@ describe('Test Select unit screen', () => {
106
101
 
107
102
  const instance = tree.root;
108
103
  const TouchableOpacities = instance.findAllByType(TouchableOpacity);
109
- expect(TouchableOpacities).toHaveLength(4);
104
+ expect(TouchableOpacities).toHaveLength(3);
110
105
  await act(async () => {
111
106
  await TouchableOpacities[1].props.onPress();
112
107
  await TouchableOpacities[2].props.onPress();