@eohjsc/react-native-smart-city 0.2.96 → 0.2.99

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 (109) hide show
  1. package/README.md +35 -14
  2. package/package.json +16 -4
  3. package/src/commons/Action/ItemQuickAction.js +5 -2
  4. package/src/commons/ActionGroup/ColorPickerTemplate.js +1 -1
  5. package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +12 -4
  6. package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLock.js +7 -4
  7. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/index.js +1 -0
  8. package/src/commons/ActionGroup/OnOffTemplate/OnOffSimpleTemplate.js +10 -10
  9. package/src/commons/ActionGroup/OnOffTemplate/index.js +18 -15
  10. package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +8 -2
  11. package/src/commons/ActionGroup/SliderRangeTemplate.js +1 -1
  12. package/src/commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate.js +4 -1
  13. package/src/commons/ActionGroup/StatesGridActionTemplate.js +14 -4
  14. package/src/commons/ActionGroup/TimerActionTemplate.js +9 -1
  15. package/src/commons/ActionGroup/TwoButtonTemplate/index.js +13 -9
  16. package/src/commons/ActionGroup/__test__/OnOffButtonTemplate.test.js +14 -14
  17. package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +53 -78
  18. package/src/commons/ActionGroup/__test__/OneBigButtonTemplate.test.js +36 -20
  19. package/src/commons/Auth/AccountList.js +1 -1
  20. package/src/commons/{Connecting → Connecting}/__test__/Connecting.test.js +0 -0
  21. package/src/commons/{Connecting → Connecting}/index.js +0 -0
  22. package/src/commons/{Connecting → Connecting}/styles.js +0 -0
  23. package/src/commons/ConnectingProcess/index.js +1 -1
  24. package/src/commons/Device/HistoryChart.js +6 -2
  25. package/src/commons/Device/PMSensor/PMSensorIndicatior.js +16 -12
  26. package/src/commons/Device/PMSensor/PMSensorIndicatorStyles.js +3 -0
  27. package/src/commons/Device/WaterQualitySensor/ListQualityIndicator.js +1 -0
  28. package/src/commons/FieldTemplate/ChooseUserField/ChooseFieldStyles.js +25 -0
  29. package/src/commons/FieldTemplate/ChooseUserField/ChoosePopup.js +96 -0
  30. package/src/commons/FieldTemplate/ChooseUserField/ChoosePopupStyles.js +39 -0
  31. package/src/commons/FieldTemplate/ChooseUserField/__test__/index.test.js +113 -0
  32. package/src/commons/FieldTemplate/ChooseUserField/index.js +62 -0
  33. package/src/commons/FieldTemplate/PasscodeField/PasscodeFieldStyles.js +30 -0
  34. package/src/commons/FieldTemplate/PasscodeField/__test__/index.test.js +93 -0
  35. package/src/commons/FieldTemplate/PasscodeField/index.js +43 -0
  36. package/src/commons/FieldTemplate/ScheduleField/ScheduleFieldStyles.js +13 -0
  37. package/src/commons/FieldTemplate/ScheduleField/__test__/index.test.js +182 -0
  38. package/src/commons/FieldTemplate/ScheduleField/index.js +176 -0
  39. package/src/commons/FullLoading/index.js +2 -1
  40. package/src/commons/MenuActionAddnew/index.js +1 -0
  41. package/src/commons/MenuActionList/index.js +1 -0
  42. package/src/commons/MenuActionMore/index.js +1 -1
  43. package/src/commons/PreventAccess/__test__/PreventAccess.test.js +62 -0
  44. package/src/commons/PreventAccess/index.js +67 -0
  45. package/src/commons/PreventAccess/styles.js +33 -0
  46. package/src/commons/WheelDateTimePicker/index.js +2 -1
  47. package/src/configs/API.js +3 -0
  48. package/src/configs/Constants.js +16 -1
  49. package/src/iot/RemoteControl/GoogleHome.js +24 -11
  50. package/src/iot/RemoteControl/__test__/GoogleHome.test.js +32 -0
  51. package/src/navigations/UnitStack.js +8 -0
  52. package/src/screens/AQIGuide/index.js +1 -1
  53. package/src/screens/ActivityLog/FilterPopup.js +2 -0
  54. package/src/screens/AddCommon/SelectSubUnit.js +1 -0
  55. package/src/screens/AddCommon/SelectUnit.js +1 -0
  56. package/src/screens/AddLocationMaps/index.js +4 -1
  57. package/src/screens/AddNewAction/SelectSensorDevices.js +14 -3
  58. package/src/screens/AddNewAction/__test__/SelectSensorDevices.test.js +34 -92
  59. package/src/screens/AddNewAutoSmart/__test__/AddNewAutoSmart.test.js +3 -1
  60. package/src/screens/AddNewAutoSmart/index.js +5 -2
  61. package/src/screens/AddNewDevice/index.js +1 -0
  62. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +1 -1
  63. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +4 -1
  64. package/src/screens/AddNewGateway/SelectGateway.js +1 -0
  65. package/src/screens/AddNewGateway/SetupGatewayWifi.js +1 -0
  66. package/src/screens/AddNewGateway/index.js +1 -0
  67. package/src/screens/AddNewOneTap/__test__/AddNewOneTap.test.js +1 -1
  68. package/src/screens/AddNewOneTap/index.js +3 -2
  69. package/src/screens/Automate/index.js +2 -0
  70. package/src/screens/Device/__test__/detail.test.js +4 -4
  71. package/src/screens/Device/detail.js +44 -6
  72. package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +5 -2
  73. package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +14 -0
  74. package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +19 -1
  75. package/src/screens/EmergencySetting/index.js +4 -1
  76. package/src/screens/Explore/index.js +2 -0
  77. package/src/screens/GuestInfo/__test__/index.test.js +1 -1
  78. package/src/screens/GuestInfo/components/RecurringDetail.js +1 -0
  79. package/src/screens/GuestInfo/components/TemporaryDetail.js +2 -2
  80. package/src/screens/ManageAccess/index.js +1 -0
  81. package/src/screens/MoveToAnotherSubUnit/index.js +1 -1
  82. package/src/screens/ScanChipQR/components/QRScan/index.js +1 -0
  83. package/src/screens/ScriptDetail/index.js +3 -3
  84. package/src/screens/SelectUnit/__test__/index.test.js +1 -1
  85. package/src/screens/SelectUnit/index.js +5 -2
  86. package/src/screens/SetSchedule/index.js +6 -2
  87. package/src/screens/SharedUnit/index.js +2 -0
  88. package/src/screens/Sharing/MemberList.js +12 -11
  89. package/src/screens/Sharing/SelectPermission.js +1 -1
  90. package/src/screens/Sharing/hooks/index.js +3 -0
  91. package/src/screens/SideMenuDetail/SideMenuDetailStyles.js +28 -0
  92. package/src/screens/SideMenuDetail/__test__/index.test.js +165 -0
  93. package/src/screens/SideMenuDetail/index.js +149 -0
  94. package/src/screens/SmartIr/components/SelectBrand.js +1 -1
  95. package/src/screens/SubUnit/ManageSubUnit.js +1 -0
  96. package/src/screens/SyncLGDevice/AddLGDevice.js +1 -0
  97. package/src/screens/TDSGuide/index.js +4 -1
  98. package/src/screens/UVIndexGuide/index.js +1 -1
  99. package/src/screens/Unit/Detail.js +18 -5
  100. package/src/screens/Unit/SelectAddress.js +4 -1
  101. package/src/screens/Unit/Station/index.js +1 -0
  102. package/src/screens/Unit/Summaries.js +1 -1
  103. package/src/screens/Unit/__test__/Detail.test.js +25 -5
  104. package/src/screens/UnitSummary/__test__/index.test.js +32 -0
  105. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +1 -1
  106. package/src/screens/WaterQualityGuide/index.js +1 -1
  107. package/src/utils/I18n/translations/en.json +5 -1
  108. package/src/utils/I18n/translations/vi.json +5 -1
  109. package/src/utils/Route/index.js +1 -0
@@ -0,0 +1,176 @@
1
+ import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
2
+ import { View } from 'react-native';
3
+ import styles from './ScheduleFieldStyles';
4
+ import moment from 'moment';
5
+
6
+ import Text from '../../Text';
7
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
8
+ import AccessScheduleItem from '../../../screens/GuestInfo/components/AccessScheduleItem';
9
+ import RecurringDetail from '../../../screens/GuestInfo/components/RecurringDetail';
10
+ import TemporaryDetail from '../../../screens/GuestInfo/components/TemporaryDetail';
11
+ import { useBoolean } from '../../../hooks/Common';
12
+ import WheelDateTimePicker from '../../WheelDateTimePicker';
13
+ import { ACCESS_SCHEDULE } from '../../../screens/GuestInfo/constant';
14
+
15
+ const ScheduleField = ({ dataItem, index, setDataForm, dataForm }) => {
16
+ const t = useTranslations();
17
+ const [accessSchedule, setAccessSchedule] = useState('always');
18
+ const [lockShowing, releaseLockShowing, acquireLockShowing] =
19
+ useBoolean(true);
20
+
21
+ const [stateDateTimePicker, setStateDateTimePicker] = useState({
22
+ isVisible: false,
23
+ mode: 'time',
24
+ defaultValue: moment(),
25
+ setter: null,
26
+ });
27
+ const [recurringTimeStart, setRecurringTimeStart] = useState(moment());
28
+ const [recurringTimeEnd, setRecurringTimeEnd] = useState(
29
+ moment().add(1, 'hours')
30
+ );
31
+ const [recurringTimeRepeat, setRecurringTimeRepeat] = useState([]);
32
+ const [temporaryTimeStart, setTemporaryTimeStart] = useState(moment());
33
+ const [temporaryTimeEnd, setTemporaryTimeEnd] = useState(
34
+ moment().add(1, 'days')
35
+ );
36
+ useEffect(() => {
37
+ if (accessSchedule === ACCESS_SCHEDULE.ALWAYS) {
38
+ dataItem.valid = true;
39
+ dataItem.data = {
40
+ access_schedule: accessSchedule,
41
+ };
42
+ } else if (accessSchedule === ACCESS_SCHEDULE.RECURRING) {
43
+ dataItem.valid = true;
44
+ dataItem.data = {
45
+ access_schedule: accessSchedule,
46
+ recurring_time_start: recurringTimeStart.format(),
47
+ recurring_time_end: recurringTimeEnd.format(),
48
+ recurring_time_repeat: recurringTimeRepeat,
49
+ };
50
+ } else if (accessSchedule === ACCESS_SCHEDULE.TEMPORARY) {
51
+ if (temporaryTimeStart > temporaryTimeEnd) {
52
+ dataItem.valid = false;
53
+ } else {
54
+ dataItem.valid = true;
55
+ dataItem.data = {
56
+ access_schedule: accessSchedule,
57
+ temporary_time_start: temporaryTimeStart.format(),
58
+ temporary_time_end: temporaryTimeEnd.format(),
59
+ };
60
+ }
61
+ }
62
+ dataItem[dataItem.action.type] = dataItem.action.id[accessSchedule];
63
+ dataForm[index] = dataItem;
64
+ setDataForm([...dataForm]);
65
+ // eslint-disable-next-line react-hooks/exhaustive-deps
66
+ }, [
67
+ accessSchedule,
68
+ recurringTimeEnd,
69
+ recurringTimeRepeat,
70
+ recurringTimeStart,
71
+ temporaryTimeEnd,
72
+ temporaryTimeStart,
73
+ ]);
74
+ const onShowSetDateTime = useCallback(
75
+ (currentValue, setter, mode) => {
76
+ releaseLockShowing();
77
+ setStateDateTimePicker((state) => ({
78
+ ...state,
79
+ isVisible: true,
80
+ mode: mode,
81
+ defaultValue: currentValue,
82
+ setter: setter,
83
+ }));
84
+ },
85
+ [releaseLockShowing]
86
+ );
87
+
88
+ const onHideSetDateTime = useCallback(() => {
89
+ acquireLockShowing();
90
+ setStateDateTimePicker((state) => ({
91
+ ...state,
92
+ isVisible: false,
93
+ }));
94
+ }, [setStateDateTimePicker, acquireLockShowing]);
95
+
96
+ const onDateTimePicked = useCallback(
97
+ (timeData) => {
98
+ const setter = stateDateTimePicker.setter;
99
+ setter && setter(moment(timeData));
100
+ },
101
+ [stateDateTimePicker]
102
+ );
103
+
104
+ const listAccessSchedule = useMemo(
105
+ () => [
106
+ {
107
+ text: t(`${ACCESS_SCHEDULE.ALWAYS}`),
108
+ value: ACCESS_SCHEDULE.ALWAYS,
109
+ detail: () => <></>,
110
+ },
111
+ {
112
+ text: t(`${ACCESS_SCHEDULE.RECURRING}`),
113
+ value: ACCESS_SCHEDULE.RECURRING,
114
+ detail: () => (
115
+ <RecurringDetail
116
+ onShowSetDateTime={onShowSetDateTime}
117
+ recurringTimeStart={recurringTimeStart}
118
+ recurringTimeEnd={recurringTimeEnd}
119
+ recurringTimeRepeat={recurringTimeRepeat}
120
+ setRecurringTimeStart={setRecurringTimeStart}
121
+ setRecurringTimeEnd={setRecurringTimeEnd}
122
+ setRecurringTimeRepeat={setRecurringTimeRepeat}
123
+ />
124
+ ),
125
+ },
126
+ {
127
+ text: t(`${ACCESS_SCHEDULE.TEMPORARY}`),
128
+ value: ACCESS_SCHEDULE.TEMPORARY,
129
+ detail: () => (
130
+ <TemporaryDetail
131
+ onShowSetDateTime={onShowSetDateTime}
132
+ temporaryTimeStart={temporaryTimeStart}
133
+ temporaryTimeEnd={temporaryTimeEnd}
134
+ setTemporaryTimeStart={setTemporaryTimeStart}
135
+ setTemporaryTimeEnd={setTemporaryTimeEnd}
136
+ />
137
+ ),
138
+ },
139
+ ],
140
+ // eslint-disable-next-line react-hooks/exhaustive-deps
141
+ [
142
+ onShowSetDateTime,
143
+ recurringTimeEnd,
144
+ recurringTimeRepeat,
145
+ recurringTimeStart,
146
+ temporaryTimeEnd,
147
+ temporaryTimeStart,
148
+ ]
149
+ );
150
+
151
+ return (
152
+ <View style={styles.wrapper}>
153
+ <Text style={styles.textHeadLine}>{t('access_schedule')}</Text>
154
+
155
+ {listAccessSchedule.map((item, index) => (
156
+ <AccessScheduleItem
157
+ key={index}
158
+ item={item}
159
+ isSelected={item.value === accessSchedule}
160
+ onSelect={setAccessSchedule}
161
+ isSetupGeneratePasscode
162
+ />
163
+ ))}
164
+ <WheelDateTimePicker
165
+ mode={stateDateTimePicker.mode}
166
+ isVisible={stateDateTimePicker.isVisible && lockShowing}
167
+ defaultValue={stateDateTimePicker.defaultValue}
168
+ onPicked={onDateTimePicked}
169
+ onCancel={onHideSetDateTime}
170
+ onHide={releaseLockShowing}
171
+ />
172
+ </View>
173
+ );
174
+ };
175
+
176
+ export default memo(ScheduleField);
@@ -22,7 +22,8 @@ const styles = StyleSheet.create({
22
22
  left: 0,
23
23
  bottom: 0,
24
24
  right: 0,
25
- zIndex: 10,
25
+ zIndex: 1000, // works on ios
26
+ elevation: 1000, // works on android
26
27
  },
27
28
  background: {
28
29
  backgroundColor: colorOpacity(Colors.White, 0.8),
@@ -59,6 +59,7 @@ const MenuActionAddnew = memo(
59
59
  data={dataActions}
60
60
  keyExtractor={keyExtractor}
61
61
  renderItem={renderItem}
62
+ scrollIndicatorInsets={{ right: 1 }}
62
63
  />
63
64
  </View>
64
65
  </View>
@@ -57,6 +57,7 @@ const MenuActionList = memo(
57
57
  data={listItem}
58
58
  keyExtractor={keyExtractor}
59
59
  renderItem={renderItem}
60
+ scrollIndicatorInsets={{ right: 1 }}
60
61
  />
61
62
  </View>
62
63
  </View>
@@ -50,7 +50,7 @@ const MenuActionMore = memo(
50
50
  isVisible={isVisible}
51
51
  arrowStyle={styles.wrap}
52
52
  >
53
- <ScrollView>
53
+ <ScrollView scrollIndicatorInsets={{ right: 1 }}>
54
54
  {listMenuItem.map((item, index) => {
55
55
  return (
56
56
  <TouchableOpacity
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import { create } from 'react-test-renderer';
3
+ import { act } from 'react-test-renderer';
4
+ import PreventAccess from '..';
5
+ import { TESTID } from '../../../configs/Constants';
6
+ import { SCProvider } from '../../../context';
7
+ import { mockSCStore } from '../../../context/mockStore';
8
+ import Text from '../../Text';
9
+
10
+ const mockGoBack = jest.fn();
11
+
12
+ const wrapComponent = (headerBodyText, visible, hidePreventAccess) => (
13
+ <SCProvider initState={mockSCStore({})}>
14
+ <PreventAccess
15
+ headerBodyText={headerBodyText}
16
+ visible={visible}
17
+ hidePreventAccess={hidePreventAccess}
18
+ />
19
+ </SCProvider>
20
+ );
21
+
22
+ jest.mock('@react-navigation/native', () => {
23
+ return {
24
+ ...jest.requireActual('@react-navigation/native'),
25
+ useRoute: jest.fn(),
26
+ useNavigation: () => ({
27
+ goBack: mockGoBack,
28
+ }),
29
+ };
30
+ });
31
+
32
+ describe('Test PreventAccess.test', () => {
33
+ let tree;
34
+ let headerBodyText;
35
+ let visible;
36
+ let hidePreventAccess = () => {};
37
+
38
+ test('onItemClick MenuActionList', () => {
39
+ act(() => {
40
+ tree = create(wrapComponent(headerBodyText, visible, hidePreventAccess));
41
+ });
42
+ const instance = tree.root;
43
+ const text = instance.findAllByType(Text);
44
+ expect(text).toHaveLength(5);
45
+ const button1 = instance.find(
46
+ (el) => el.props.testID === TESTID.BUTTON_PREVENT_ACCESS
47
+ );
48
+ const button2 = instance.find(
49
+ (el) => el.props.testID === TESTID.TEXT_PREVENT_ACCESS
50
+ );
51
+ act(() => {
52
+ button1.props.onBackButtonPress();
53
+ });
54
+
55
+ act(() => {
56
+ button2.props.onPress();
57
+ });
58
+ expect(button1).toBeDefined();
59
+ expect(button2).toBeDefined();
60
+ expect(mockGoBack).toHaveBeenCalled();
61
+ });
62
+ });
@@ -0,0 +1,67 @@
1
+ import React, { memo, useCallback, useMemo } from 'react';
2
+ import { View } from 'react-native';
3
+ import Modal from 'react-native-modal';
4
+ import { useNavigation } from '@react-navigation/native';
5
+
6
+ import t from '../../hooks/Common/useTranslations';
7
+ import Text from '../Text';
8
+ import { Colors } from '../../configs';
9
+ import { styles } from './styles';
10
+ import { TESTID } from '../../configs/Constants';
11
+
12
+ const PreventAccess = memo(({ headerBodyText, visible, hidePreventAccess }) => {
13
+ const { goBack } = useNavigation();
14
+
15
+ const dataText = useMemo(() => {
16
+ return {
17
+ headerText: t('note'),
18
+ bodyText: t('This {name} was removed!', {
19
+ name: headerBodyText ? headerBodyText : '',
20
+ }),
21
+ endOfText: t('back'),
22
+ };
23
+ }, [headerBodyText]);
24
+
25
+ const handleBackPress = useCallback(() => {
26
+ hidePreventAccess();
27
+ goBack();
28
+ }, [goBack, hidePreventAccess]);
29
+
30
+ const handleDonePopup = useCallback(() => {
31
+ goBack();
32
+ hidePreventAccess();
33
+ }, [goBack, hidePreventAccess]);
34
+
35
+ return (
36
+ <Modal
37
+ isVisible={visible}
38
+ transparent={true}
39
+ onBackButtonPress={handleBackPress}
40
+ style={styles.container}
41
+ testID={TESTID.BUTTON_PREVENT_ACCESS}
42
+ >
43
+ <View style={styles.popoverStyle}>
44
+ <View style={styles.actionTextWrap}>
45
+ <Text size={17} bold color={Colors.Gray9} style={styles.textHeader}>
46
+ {dataText?.headerText}
47
+ </Text>
48
+ <Text type="H4" color={Colors.Gray8} style={styles.textNotification}>
49
+ {dataText?.bodyText}
50
+ </Text>
51
+ </View>
52
+ <View style={styles.endOfText}>
53
+ <Text
54
+ testID={TESTID.TEXT_PREVENT_ACCESS}
55
+ size={16}
56
+ bold
57
+ color={Colors.Primary}
58
+ onPress={handleDonePopup}
59
+ >
60
+ {dataText?.endOfText}
61
+ </Text>
62
+ </View>
63
+ </View>
64
+ </Modal>
65
+ );
66
+ });
67
+ export default PreventAccess;
@@ -0,0 +1,33 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ import { Colors } from '../../configs';
4
+
5
+ export const styles = StyleSheet.create({
6
+ container: {
7
+ flex: 1,
8
+ },
9
+ popoverStyle: {
10
+ flex: 1,
11
+ width: '100%',
12
+ backgroundColor: Colors.White,
13
+ position: 'absolute',
14
+ borderRadius: 10,
15
+ },
16
+ actionTextWrap: {
17
+ marginTop: 14,
18
+ marginHorizontal: 20,
19
+ },
20
+ textHeader: {
21
+ marginVertical: 10,
22
+ },
23
+ textNotification: {
24
+ lineHeight: 20,
25
+ },
26
+ endOfText: {
27
+ flexDirection: 'row',
28
+ justifyContent: 'flex-end',
29
+ marginTop: 5,
30
+ marginBottom: 20,
31
+ marginRight: 20,
32
+ },
33
+ });
@@ -104,6 +104,7 @@ const WheelDateTimePicker = ({
104
104
 
105
105
  return (
106
106
  <BottomSheet
107
+ testID={TESTID.WHEEL_DATE_TIME_PICKER}
107
108
  isVisible={isVisible}
108
109
  onBackdropPress={onPickerCancel}
109
110
  onHide={onHide}
@@ -173,7 +174,7 @@ const WheelDateTimePicker = ({
173
174
  onLeftClick={onPickerCancel}
174
175
  rightTitle={t('done')}
175
176
  onRightClick={onDone}
176
- testIDPrefix={TESTID.WHEEL_DATE_TIME_PICKER}
177
+ testIDPrefix={TESTID.WHEEL_DATE_TIME_PICKER_BUTTON}
177
178
  />
178
179
  </BottomSheet>
179
180
  );
@@ -65,6 +65,9 @@ const API = {
65
65
  SCConfig.apiRoot + `/property_manager/sensors/${id}/`,
66
66
  DISPLAY: (id) =>
67
67
  SCConfig.apiRoot + `/property_manager/sensors/${id}/display/`,
68
+ SIDE_MENU_DETAIL: (id, side_menu_id) =>
69
+ SCConfig.apiRoot +
70
+ `/property_manager/sensors/${id}/display/side_menu/${side_menu_id}/`,
68
71
  DISPLAY_VALUES: (id) =>
69
72
  SCConfig.apiRoot + `/property_manager/sensors/${id}/display_values/`,
70
73
  DISPLAY_VALUES_V2: (id) =>
@@ -674,13 +674,16 @@ export const TESTID = {
674
674
 
675
675
  // WheelDateTimePicker
676
676
  WHEEL_DATE_TIME_PICKER: 'WHEEL_DATE_TIME_PICKER',
677
+ WHEEL_DATE_TIME_PICKER_BUTTON: 'WHEEL_DATE_TIME_PICKER_BUTTON',
677
678
 
678
679
  // GuestInfo
679
680
  SAVE_ACCESS_SCHEDULE: 'SAVE_ACCESS_SCHEDULE',
680
681
  ACCESS_SCHEDULE_RADIO_BUTTON: 'ACCESS_SCHEDULE_RADIO_BUTTON',
681
682
  ACCESS_SCHEDULE_SHEET: 'ACCESS_SCHEDULE_SHEET',
682
683
  RECURRING_TEXT_BUTTON: 'RECURRING_TEXT_BUTTON',
683
- TEMPORARY_TEXT_BUTTON: 'TEMPORARY_TEXT_BUTTON',
684
+ RECURRING_REPEAT_ITEM: 'RECURRING_REPEAT_ITEM',
685
+ TEMPORARY_START_TEXT_BUTTON: 'TEMPORARY_START_TEXT_BUTTON',
686
+ TEMPORARY_END_TEXT_BUTTON: 'TEMPORARY_END_TEXT_BUTTON',
684
687
 
685
688
  // ActivityLog
686
689
  FILTER_BUTTON: 'FILTER_BUTTON',
@@ -722,6 +725,18 @@ export const TESTID = {
722
725
  AUTO_LOCK_BUTTON_ENABLE: 'AUTO_LOCK_BUTTON_ENABLE',
723
726
  AUTO_LOCK_BUTTON_INSTANT: 'AUTO_LOCK_BUTTON_INSTANT',
724
727
  AUTO_LOCK_BUTTON_RELOCK_TIMING: 'AUTO_LOCK_BUTTON_RELOCK_TIMING',
728
+
729
+ //PreventAccess
730
+ BUTTON_PREVENT_ACCESS: 'BUTTON_PREVENT_ACCESS',
731
+ TEXT_PREVENT_ACCESS: 'TEXT_PREVENT_ACCESS',
732
+
733
+ //Template field
734
+ CHOOSE_FIELD: 'CHOOSE_FIELD',
735
+ CHOOSE_POPUP: 'CHOOSE_POPUP',
736
+ CHOOSE_ITEM: 'CHOOSE_ITEM',
737
+
738
+ PASSCODE_FIELD: 'PASSCODE_FIELD',
739
+ SUBMIT: 'SUBMIT',
725
740
  };
726
741
 
727
742
  export const NOTIFICATION_TYPES = {
@@ -201,8 +201,22 @@ function getServiceName(message) {
201
201
  return serviceSplit.join('_');
202
202
  }
203
203
 
204
+ async function sendCommandSingleAction(connection, ghAction, data) {
205
+ const { message } = ghAction || {};
206
+ const name = getServiceName(message);
207
+
208
+ if (name && data) {
209
+ message.service_data[name] = data;
210
+ }
211
+
212
+ await connection.sendMessagePromise(message);
213
+ }
214
+
204
215
  export async function sendCommandOverGoogleHome(sensor, action, data) {
205
- if (!action.googlehome_actions || !action.googlehome_actions.length) {
216
+ if (
217
+ !(action.googlehome_actions && action.googlehome_actions.length) &&
218
+ !action.googlehome_action
219
+ ) {
206
220
  return;
207
221
  }
208
222
 
@@ -212,20 +226,19 @@ export async function sendCommandOverGoogleHome(sensor, action, data) {
212
226
  return;
213
227
  }
214
228
 
215
- for (let i = 0; i < action.googlehome_actions.length; i++) {
216
- const ghAction = action.googlehome_actions[i];
217
- const { message } = ghAction;
218
- const name = getServiceName(ghAction.message);
219
-
220
- if (name && data) {
221
- message.service_data[name] = data;
229
+ if (action.googlehome_actions) {
230
+ for (let i = 0; i < action.googlehome_actions.length; i++) {
231
+ await sendCommandSingleAction(
232
+ connection,
233
+ action.googlehome_actions[i],
234
+ data
235
+ );
222
236
  }
223
-
224
- await connection.sendMessagePromise(message);
237
+ } else if (action.googlehome_action) {
238
+ await sendCommandSingleAction(connection, action.googlehome_action, data);
225
239
  }
226
240
 
227
241
  const { success } = await axiosPost(API.SENSOR.ACTIVITY_LOG(), {
228
- sensor_id: sensor.id,
229
242
  action_id: action.id,
230
243
  message: 'Trigger by user action with google home',
231
244
  });
@@ -75,6 +75,9 @@ describe('Remote Control Google Home', () => {
75
75
  message: 'message',
76
76
  },
77
77
  ],
78
+ googlehome_action: {
79
+ message: 'message',
80
+ },
78
81
  };
79
82
 
80
83
  const response = {
@@ -223,6 +226,35 @@ describe('Remote Control Google Home', () => {
223
226
  });
224
227
  });
225
228
 
229
+ it('Send command over google home action googlehome_action one to one', async () => {
230
+ action.googlehome_actions = null;
231
+ action.googlehome_action.message = {
232
+ type: 'call_service',
233
+ domain: 'climate',
234
+ service: 'set_temperature',
235
+ service_data: {
236
+ temperature: 0,
237
+ entity_id: 'climate.dqsmart_0108f6cdde',
238
+ },
239
+ id: 20,
240
+ };
241
+
242
+ axios.post.mockImplementation(async () => {
243
+ return response;
244
+ });
245
+ await googleHomeConnect(options);
246
+ await sendCommandOverGoogleHome(sensor, action, 19);
247
+
248
+ action.googlehome_action.message.service_data.temperature = 19;
249
+ expect(connection.sendMessagePromise).toBeCalledWith(
250
+ action.googlehome_action.message
251
+ );
252
+ expect(axios.post).toHaveBeenCalledWith(API.SENSOR.ACTIVITY_LOG(), {
253
+ action_id: 1,
254
+ message: 'Trigger by user action with google home',
255
+ });
256
+ });
257
+
226
258
  it('Send command over google home that not connected', async () => {
227
259
  await googleHomeConnect(options);
228
260
  await sendCommandOverGoogleHome({ chip_id: 2 }, action);
@@ -55,6 +55,7 @@ import { HanetCameraStack } from './HanetCameraStack';
55
55
 
56
56
  import { axiosGet } from '../utils/Apis/axios';
57
57
  import { API } from '../configs';
58
+ import SideMenuDetail from '../screens/SideMenuDetail';
58
59
 
59
60
  const Stack = createStackNavigator();
60
61
 
@@ -263,6 +264,13 @@ export const UnitStack = memo((props) => {
263
264
  headerShown: false,
264
265
  }}
265
266
  />
267
+ <Stack.Screen
268
+ name={Route.SideMenuDetail}
269
+ component={SideMenuDetail}
270
+ options={{
271
+ headerShown: false,
272
+ }}
273
+ />
266
274
  <Stack.Screen
267
275
  name={Route.UnitMemberList}
268
276
  component={SharingMemberList}
@@ -83,7 +83,7 @@ const AQIGuide = memo(() => {
83
83
 
84
84
  return (
85
85
  <SafeAreaView style={styles.container}>
86
- <ScrollView style={styles.container}>
86
+ <ScrollView style={styles.container} scrollIndicatorInsets={{ right: 1 }}>
87
87
  {titles.map((item, index) => {
88
88
  const { title, des } = item;
89
89
  return (
@@ -257,6 +257,8 @@ const FilterPopup = ({
257
257
  onCancel={onPickerCancel}
258
258
  onHide={releaseLockShowing}
259
259
  display="spinner"
260
+ cancelTextIOS={t('cancel')}
261
+ confirmTextIOS={t('confirm')}
260
262
  />
261
263
  </>
262
264
  );
@@ -174,6 +174,7 @@ const AddCommonSelectSubUnit = ({ route }) => {
174
174
  <ScrollView
175
175
  style={styles.scrollContainer}
176
176
  showsVerticalScrollIndicator={false}
177
+ scrollIndicatorInsets={{ right: 1 }}
177
178
  >
178
179
  <Section type={'border'}>
179
180
  {subUnits.map((item, index) => (
@@ -159,6 +159,7 @@ const AddCommonSelectUnit = ({ route }) => {
159
159
  <ScrollView
160
160
  style={styles.scrollContainer}
161
161
  showsVerticalScrollIndicator={false}
162
+ scrollIndicatorInsets={{ right: 1 }}
162
163
  >
163
164
  <Section type={'border'}>
164
165
  {units.map((item, index) => (
@@ -169,7 +169,10 @@ const AddLocationMaps = memo(() => {
169
169
  </Text>
170
170
  <View style={styles.searchLocation}>
171
171
  <SearchBarLocation input={input} onTextInput={onTextInput} />
172
- <ScrollView style={styles.searchData}>
172
+ <ScrollView
173
+ style={styles.searchData}
174
+ scrollIndicatorInsets={{ right: 1 }}
175
+ >
173
176
  {searchData.map((item) => (
174
177
  <RowLocation item={item} onPress={onPressRowLocation} />
175
178
  ))}