@eohjsc/react-native-smart-city 0.2.59 → 0.2.63
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.
- package/README.md +115 -68
- package/assets/images/Map/MarkerGeolocation.svg +4 -0
- package/package.json +3 -3
- package/src/commons/ActionGroup/CurtainButtonTemplate.js +10 -2
- package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/MenuActionAddSchedule.test.js +71 -0
- package/src/commons/ActionGroup/hooks/AccessScheduleDetailStyles.js +41 -0
- package/src/commons/ActionGroup/hooks/MenuActionAddSchedule.js +110 -0
- package/src/commons/ActionGroup/hooks/MenuActionAddScheduleStyle.js +69 -0
- package/src/commons/ActionGroup/hooks/RecurringDetail.js +97 -0
- package/src/commons/DateTimeRangeChange/DateTimeButton.js +7 -2
- package/src/commons/Device/HistoryChart.js +80 -81
- package/src/commons/Device/HorizontalBarChart.js +48 -31
- package/src/commons/Device/LinearChart.js +28 -1
- package/src/commons/Form/CurrencyInput.js +1 -0
- package/src/commons/FourButtonFilterHistory/__test__/FourButtonFilterHistory.test.js +48 -0
- package/src/commons/FourButtonFilterHistory/index.js +72 -0
- package/src/commons/FourButtonFilterHistory/styles.js +22 -0
- package/src/commons/ImagePicker/index.js +27 -33
- package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +11 -1
- package/src/commons/MediaPlayerDetail/index.js +14 -5
- package/src/commons/SubUnit/OneTap/OneTapStyles.js +20 -1
- package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +151 -40
- package/src/commons/SubUnit/OneTap/index.js +64 -12
- package/src/commons/UnitSummary/AirQuality/index.js +9 -7
- package/src/commons/UnitSummary/ConfigHistoryChart.js +2 -1
- package/src/configs/API.js +3 -0
- package/src/configs/Constants.js +15 -0
- package/src/iot/RemoteControl/Bluetooth.js +6 -3
- package/src/iot/RemoteControl/GoogleHome.js +6 -3
- package/src/iot/RemoteControl/Internet.js +1 -0
- package/src/iot/RemoteControl/LG.js +2 -1
- package/src/iot/RemoteControl/index.js +13 -6
- package/src/navigations/SharedStack.js +11 -9
- package/src/navigations/UnitStack.js +26 -2
- package/src/screens/ActivityLog/ItemLog.js +3 -3
- package/src/screens/ActivityLog/__test__/ItemLog.test.js +5 -2
- package/src/screens/ActivityLog/hooks/index.js +2 -1
- package/src/screens/ActivityLog/index.js +0 -1
- package/src/screens/AddLocationMaps/index.js +4 -2
- package/src/screens/AddNewAction/SelectSensorDevices.js +18 -11
- package/src/screens/AddNewAction/Styles/SelectSensorDevicesStyles.js +5 -1
- package/src/screens/AddNewAction/__test__/SelectSensorDevices.test.js +6 -1
- package/src/screens/Automate/MultiUnits.js +7 -4
- package/src/screens/Automate/__test__/MultiUnits.test.js +1 -1
- package/src/screens/Automate/__test__/index.test.js +12 -0
- package/src/screens/ConfirmUnitDeletion/__test__/ConfirmUnitDeletion.test.js +61 -0
- package/src/screens/ConfirmUnitDeletion/index.js +64 -0
- package/src/screens/ConfirmUnitDeletion/styles.js +37 -0
- package/src/screens/Device/__test__/detail.test.js +3 -2
- package/src/screens/Device/detail.js +48 -15
- package/src/screens/Device/hooks/useDisconnectedDevice.js +2 -1
- package/src/screens/Device/styles.js +3 -3
- package/src/screens/EmergencySetting/__test__/DropDownItem.test.js +59 -0
- package/src/screens/EmergencySetting/__test__/index.test.js +27 -0
- package/src/screens/EmergencySetting/components/DropDownItem.js +54 -0
- package/src/screens/EmergencySetting/index.js +92 -0
- package/src/screens/EmergencySetting/styles/DropDownItem.js +38 -0
- package/src/screens/EmergencySetting/styles.js +25 -0
- package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +126 -0
- package/src/screens/MoveToAnotherSubUnit/index.js +88 -0
- package/src/screens/MoveToAnotherSubUnit/styles/MoveToAnotherSubUnitStyles.js +50 -0
- package/src/screens/ScriptDetail/Styles/indexStyles.js +0 -1
- package/src/screens/ScriptDetail/index.js +1 -0
- package/src/screens/SubUnit/AddSubUnit.js +3 -3
- package/src/screens/SubUnit/AddSubUnitStyles.js +0 -2
- package/src/screens/SubUnit/EditSubUnit.js +16 -7
- package/src/screens/SubUnit/EditSubUnitStyles.js +2 -3
- package/src/screens/SubUnit/__test__/EditSubUnit.test.js +2 -2
- package/src/screens/TDSGuide/index.js +1 -1
- package/src/screens/Unit/ChooseLocation.js +3 -7
- package/src/screens/Unit/ChooseLocationStyles.js +5 -8
- package/src/screens/Unit/Detail.js +16 -6
- package/src/screens/Unit/ManageUnit.js +20 -26
- package/src/screens/Unit/SmartAccount.js +25 -41
- package/src/screens/Unit/SmartAccountItem.js +2 -1
- package/src/screens/Unit/SmartAccountStyles.js +0 -1
- package/src/screens/Unit/__test__/ManageUnit.test.js +0 -6
- package/src/screens/Unit/__test__/SmartAccount.test.js +24 -0
- package/src/screens/Unit/__test__/SmartAccountItem.test.js +72 -0
- package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +58 -59
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +26 -22
- package/src/screens/UnitSummary/components/Temperature/ItemTemperature/index.js +2 -2
- package/src/screens/UnitSummary/components/Temperature/index.js +15 -14
- package/src/screens/UnitSummary/components/UvIndex/index.js +6 -5
- package/src/screens/UnitSummary/components/WaterQuality/index.js +9 -7
- package/src/screens/UnitSummary/index.js +11 -7
- package/src/screens/WaterQualityGuide/index.js +1 -0
- package/src/utils/Apis/axios.js +4 -4
- package/src/utils/I18n/translations/en.json +20 -2
- package/src/utils/I18n/translations/vi.json +21 -2
- package/src/utils/Route/index.js +3 -0
- package/src/utils/Utils.js +4 -0
- package/src/commons/ThreeButtonHistory/CalendarHeader.js +0 -35
- package/src/commons/ThreeButtonHistory/CalendarHeaderStyles.js +0 -17
- package/src/commons/ThreeButtonHistory/SelectMonth.js +0 -53
- package/src/commons/ThreeButtonHistory/SelectMonthStyles.js +0 -29
- package/src/commons/ThreeButtonHistory/__test__/SelectMonth.test.js +0 -37
- package/src/commons/ThreeButtonHistory/__test__/ThreeButtonHistory.test.js +0 -240
- package/src/commons/ThreeButtonHistory/index.js +0 -310
- package/src/commons/ThreeButtonHistory/styles.js +0 -65
|
@@ -69,7 +69,17 @@ export default StyleSheet.create({
|
|
|
69
69
|
bottom: 0,
|
|
70
70
|
},
|
|
71
71
|
firstOpenCamera: {
|
|
72
|
-
zIndex: -
|
|
72
|
+
zIndex: -9999,
|
|
73
73
|
position: 'absolute',
|
|
74
|
+
width: 1,
|
|
75
|
+
height: 1,
|
|
76
|
+
},
|
|
77
|
+
loading: {
|
|
78
|
+
position: 'absolute',
|
|
79
|
+
zIndex: 10,
|
|
80
|
+
width: '100%',
|
|
81
|
+
height: '100%',
|
|
82
|
+
justifyContent: 'center',
|
|
83
|
+
alignItems: 'center',
|
|
74
84
|
},
|
|
75
85
|
});
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
Text,
|
|
14
14
|
TouchableOpacity,
|
|
15
15
|
Platform,
|
|
16
|
+
ActivityIndicator,
|
|
16
17
|
} from 'react-native';
|
|
17
18
|
import { VLCPlayer } from 'react-native-vlc-media-player';
|
|
18
19
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
@@ -46,9 +47,10 @@ const MediaPlayerDetail = ({
|
|
|
46
47
|
);
|
|
47
48
|
const t = useTranslations();
|
|
48
49
|
const [paused, setPaused] = useState(isPaused);
|
|
50
|
+
|
|
49
51
|
const onTapPause = useCallback(() => {
|
|
50
|
-
setPaused(false);
|
|
51
|
-
}, []);
|
|
52
|
+
!isFirstOpenCamera && setPaused(false);
|
|
53
|
+
}, [isFirstOpenCamera]);
|
|
52
54
|
|
|
53
55
|
const onTapGoDetail = useCallback(() => {
|
|
54
56
|
if (!paused) {
|
|
@@ -139,7 +141,7 @@ const MediaPlayerDetail = ({
|
|
|
139
141
|
const to = setTimeout(() => {
|
|
140
142
|
setAction(Action.IS_FIRST_OPEN_CAMERA, false);
|
|
141
143
|
clearTimeout(to);
|
|
142
|
-
},
|
|
144
|
+
}, 1000);
|
|
143
145
|
}
|
|
144
146
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
145
147
|
}, [isFirstOpenCamera]);
|
|
@@ -147,7 +149,14 @@ const MediaPlayerDetail = ({
|
|
|
147
149
|
const source = !thumbnail || !thumbnail.uri ? Images.BgDevice : thumbnail;
|
|
148
150
|
return (
|
|
149
151
|
<View style={[styles.wrap, wrapStyles]}>
|
|
150
|
-
{isFirstOpenCamera && Platform.OS === 'ios' &&
|
|
152
|
+
{isFirstOpenCamera && Platform.OS === 'ios' && (
|
|
153
|
+
<>
|
|
154
|
+
{renderCamera}
|
|
155
|
+
<View style={styles.loading}>
|
|
156
|
+
<ActivityIndicator size={'small'} color={Colors.Primary} />
|
|
157
|
+
</View>
|
|
158
|
+
</>
|
|
159
|
+
)}
|
|
151
160
|
<View style={[styles.loadingWrap]}>
|
|
152
161
|
<Text style={styles.loadingText}>{t('loading')}</Text>
|
|
153
162
|
</View>
|
|
@@ -172,7 +181,7 @@ const MediaPlayerDetail = ({
|
|
|
172
181
|
/>
|
|
173
182
|
</View>
|
|
174
183
|
) : (
|
|
175
|
-
renderCamera
|
|
184
|
+
!isFirstOpenCamera && renderCamera
|
|
176
185
|
)}
|
|
177
186
|
|
|
178
187
|
<View style={styles.buttonView}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native';
|
|
1
|
+
import { Platform, StyleSheet } from 'react-native';
|
|
2
2
|
import { Colors, Device } from '../../../configs';
|
|
3
3
|
|
|
4
4
|
export default StyleSheet.create({
|
|
@@ -33,4 +33,23 @@ export default StyleSheet.create({
|
|
|
33
33
|
alignItems: 'center',
|
|
34
34
|
paddingBottom: 3,
|
|
35
35
|
},
|
|
36
|
+
dropDown: {
|
|
37
|
+
width: 114,
|
|
38
|
+
height: 40,
|
|
39
|
+
borderRadius: 30,
|
|
40
|
+
backgroundColor: Colors.Gray3,
|
|
41
|
+
},
|
|
42
|
+
boxDropDown: {
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
flexDirection: 'row',
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
padding: Platform.select({
|
|
47
|
+
ios: 10,
|
|
48
|
+
android: 6,
|
|
49
|
+
}),
|
|
50
|
+
},
|
|
51
|
+
textDropDown: {
|
|
52
|
+
color: Colors.Primary,
|
|
53
|
+
marginRight: 10,
|
|
54
|
+
},
|
|
36
55
|
});
|
|
@@ -4,7 +4,7 @@ import { TouchableOpacity } from 'react-native';
|
|
|
4
4
|
import Toast from 'react-native-toast-message';
|
|
5
5
|
import { act, create } from 'react-test-renderer';
|
|
6
6
|
import SubUnitAutomate from '..';
|
|
7
|
-
import { TESTID } from '../../../../configs/Constants';
|
|
7
|
+
import { AUTOMATE_TYPE, TESTID } from '../../../../configs/Constants';
|
|
8
8
|
import { SCProvider } from '../../../../context';
|
|
9
9
|
import { mockSCStore } from '../../../../context/mockStore';
|
|
10
10
|
import Routes from '../../../../utils/Route';
|
|
@@ -37,18 +37,23 @@ jest.mock('axios');
|
|
|
37
37
|
let tree;
|
|
38
38
|
let data = {
|
|
39
39
|
isOwner: true,
|
|
40
|
-
|
|
41
|
-
automates: [
|
|
40
|
+
listAutomate: [
|
|
42
41
|
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
text: 'Scenario',
|
|
43
|
+
data: [
|
|
44
|
+
{
|
|
45
|
+
id: 1,
|
|
46
|
+
user: 6,
|
|
47
|
+
type: 'one_tap',
|
|
48
|
+
activate_at: '2021-09-17T05:30:00Z',
|
|
49
|
+
script: {
|
|
50
|
+
name: 'Joshua Ray',
|
|
51
|
+
icon: '',
|
|
52
|
+
icon_kit: '',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
type: AUTOMATE_TYPE.ONE_TAP,
|
|
52
57
|
},
|
|
53
58
|
],
|
|
54
59
|
};
|
|
@@ -58,7 +63,7 @@ describe('test Item', () => {
|
|
|
58
63
|
axios.post.mockClear();
|
|
59
64
|
mockedNavigate.mockClear();
|
|
60
65
|
});
|
|
61
|
-
test('render SubUnitAutomate isOwner', async () => {
|
|
66
|
+
test('render SubUnitAutomate isOwner and handleOnAddNew', async () => {
|
|
62
67
|
const response = {
|
|
63
68
|
status: 200,
|
|
64
69
|
};
|
|
@@ -100,7 +105,7 @@ describe('test Item', () => {
|
|
|
100
105
|
type: 'one_tap',
|
|
101
106
|
unit: undefined,
|
|
102
107
|
textCondition: null,
|
|
103
|
-
automate: data.
|
|
108
|
+
automate: data.listAutomate[0].data[0],
|
|
104
109
|
});
|
|
105
110
|
|
|
106
111
|
const handleScriptAction = instance.findAll(
|
|
@@ -154,20 +159,26 @@ describe('test Item', () => {
|
|
|
154
159
|
test('render SubUnitAutomate script value_change', async () => {
|
|
155
160
|
data.isOwner = false;
|
|
156
161
|
data.type = 'value_change';
|
|
157
|
-
data.
|
|
162
|
+
data.listAutomate = [
|
|
158
163
|
{
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
text: AUTOMATE_TYPE.AUTOMATION,
|
|
165
|
+
type: AUTOMATE_TYPE.AUTOMATION,
|
|
166
|
+
data: [
|
|
167
|
+
{
|
|
168
|
+
id: 1,
|
|
169
|
+
user: 6,
|
|
170
|
+
type: 'value_change',
|
|
171
|
+
activate_at: null,
|
|
172
|
+
condition: '>',
|
|
173
|
+
config: 'Temperature',
|
|
174
|
+
value: 29,
|
|
175
|
+
script: {
|
|
176
|
+
name: 'Rain',
|
|
177
|
+
icon: '',
|
|
178
|
+
icon_kit: 'https://www.figma.com/',
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
],
|
|
171
182
|
},
|
|
172
183
|
];
|
|
173
184
|
const response = {
|
|
@@ -197,30 +208,36 @@ describe('test Item', () => {
|
|
|
197
208
|
type: 'value_change',
|
|
198
209
|
unit: undefined,
|
|
199
210
|
textCondition: 'Temperature higher than 29',
|
|
200
|
-
automate: data.
|
|
211
|
+
automate: data.listAutomate[0].data[0],
|
|
201
212
|
});
|
|
202
213
|
});
|
|
203
|
-
test('render SubUnitAutomate script schedule', async () => {
|
|
214
|
+
test('render SubUnitAutomate script schedule and handleOnAddNew item automate', async () => {
|
|
204
215
|
data.isOwner = false;
|
|
205
216
|
data.type = 'schedule';
|
|
206
|
-
data.
|
|
217
|
+
data.listAutomate = [
|
|
207
218
|
{
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
219
|
+
text: AUTOMATE_TYPE.AUTOMATION,
|
|
220
|
+
type: AUTOMATE_TYPE.AUTOMATION,
|
|
221
|
+
data: [
|
|
222
|
+
{
|
|
223
|
+
id: 1,
|
|
224
|
+
user: 6,
|
|
225
|
+
type: 'schedule',
|
|
226
|
+
activate_at: null,
|
|
227
|
+
script: {
|
|
228
|
+
name: 'Rain',
|
|
229
|
+
icon: '',
|
|
230
|
+
icon_kit: '',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
],
|
|
217
234
|
},
|
|
218
235
|
];
|
|
219
236
|
const response = {
|
|
220
237
|
status: 200,
|
|
221
238
|
};
|
|
222
239
|
|
|
223
|
-
axios.post.mockImplementation(async () => {
|
|
240
|
+
await axios.post.mockImplementation(async () => {
|
|
224
241
|
return response;
|
|
225
242
|
});
|
|
226
243
|
|
|
@@ -228,10 +245,104 @@ describe('test Item', () => {
|
|
|
228
245
|
tree = await create(wrapComponent(data));
|
|
229
246
|
});
|
|
230
247
|
|
|
248
|
+
const instance = tree.root;
|
|
249
|
+
const item = instance.findAll(
|
|
250
|
+
(el) => el.props.testID === TESTID.PLUS && el.type === TouchableOpacity
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
expect(item).toHaveLength(1);
|
|
254
|
+
await act(async () => {
|
|
255
|
+
await item[0].props.onPress();
|
|
256
|
+
});
|
|
257
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddNewAutoSmart, {
|
|
258
|
+
type: AUTOMATE_TYPE.VALUE_CHANGE,
|
|
259
|
+
unit: undefined,
|
|
260
|
+
});
|
|
261
|
+
mockedNavigate.mockClear();
|
|
262
|
+
|
|
231
263
|
const goDetail = tree.root.findAll(
|
|
232
264
|
(el) =>
|
|
233
265
|
el.props.testID === TESTID.GO_DETAIL && el.type === TouchableOpacity
|
|
234
266
|
);
|
|
235
267
|
expect(goDetail).toHaveLength(1);
|
|
236
268
|
});
|
|
269
|
+
|
|
270
|
+
test('render click select option filter by automation', async () => {
|
|
271
|
+
data.isOwner = false;
|
|
272
|
+
data.type = 'schedule';
|
|
273
|
+
data.listAutomate = [
|
|
274
|
+
{
|
|
275
|
+
text: AUTOMATE_TYPE.SCENARIO,
|
|
276
|
+
type: AUTOMATE_TYPE.ONE_TAP,
|
|
277
|
+
data: [
|
|
278
|
+
{
|
|
279
|
+
id: 1,
|
|
280
|
+
user: 6,
|
|
281
|
+
type: 'one_tap',
|
|
282
|
+
activate_at: null,
|
|
283
|
+
script: {
|
|
284
|
+
name: 'One-tap',
|
|
285
|
+
icon: '',
|
|
286
|
+
icon_kit: '',
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
text: AUTOMATE_TYPE.AUTOMATION,
|
|
293
|
+
type: AUTOMATE_TYPE.AUTOMATION,
|
|
294
|
+
data: [
|
|
295
|
+
{
|
|
296
|
+
id: 2,
|
|
297
|
+
user: 6,
|
|
298
|
+
type: 'schedule',
|
|
299
|
+
activate_at: null,
|
|
300
|
+
script: {
|
|
301
|
+
name: 'Rain',
|
|
302
|
+
icon: '',
|
|
303
|
+
icon_kit: '',
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
},
|
|
308
|
+
];
|
|
309
|
+
const response = {
|
|
310
|
+
status: 200,
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
await axios.post.mockImplementation(async () => {
|
|
314
|
+
return response;
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
await act(async () => {
|
|
318
|
+
tree = await create(wrapComponent(data));
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const instance = tree.root;
|
|
322
|
+
const menuDropDown = instance.find(
|
|
323
|
+
(el) =>
|
|
324
|
+
el.props.testID === TESTID.SUB_UNIT_SELECT_AUTOMATE_TYPE &&
|
|
325
|
+
el.type === TouchableOpacity
|
|
326
|
+
);
|
|
327
|
+
await act(async () => {
|
|
328
|
+
await menuDropDown.props.onPress();
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
const menu = instance.find(
|
|
332
|
+
(el) => el.props.testID === TESTID.NAVBAR_MENU_ACTION_MORE
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
expect(menu.props.isVisible).toBeTruthy();
|
|
336
|
+
|
|
337
|
+
const automation = menu.props.listMenuItem[1];
|
|
338
|
+
|
|
339
|
+
await act(async () => {
|
|
340
|
+
await menu.props.onItemClick(automation, 1);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
const text = instance.find(
|
|
344
|
+
(el) => el.props.testID === TESTID.SUB_UNIT_TEXT_DROPDOWN
|
|
345
|
+
);
|
|
346
|
+
expect(text.props.children).toEqual(AUTOMATE_TYPE.AUTOMATION);
|
|
347
|
+
});
|
|
237
348
|
});
|
|
@@ -1,33 +1,75 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
3
|
-
import
|
|
4
|
-
import { Section } from '../..';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { Icon } from '@ant-design/react-native';
|
|
5
4
|
|
|
5
|
+
import { MenuActionMore, Section } from '../..';
|
|
6
6
|
import ItemAddNew from '../../Device/ItemAddNew';
|
|
7
7
|
import ItemOneTap from './ItemOneTap';
|
|
8
8
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
9
9
|
import { useNavigation } from '@react-navigation/native';
|
|
10
10
|
import Routes from '../../../utils/Route/index.js';
|
|
11
|
-
import { AUTOMATE_TYPE } from '../../../configs/Constants';
|
|
11
|
+
import { AUTOMATE_TYPE, TESTID } from '../../../configs/Constants';
|
|
12
|
+
import { Colors } from '../../../configs/Colors.js';
|
|
13
|
+
import usePopover from '../../../hooks/Common/usePopover.js';
|
|
14
|
+
import Text from '../../Text/index.js';
|
|
15
|
+
|
|
16
|
+
import styles from './OneTapStyles.js';
|
|
12
17
|
|
|
13
|
-
const SubUnitAutomate = ({ isOwner,
|
|
18
|
+
const SubUnitAutomate = ({ isOwner, listAutomate, unit, wrapItemStyle }) => {
|
|
14
19
|
const t = useTranslations();
|
|
15
20
|
const { navigate } = useNavigation();
|
|
21
|
+
const [automates, setAutomates] = useState(listAutomate[0]);
|
|
22
|
+
const [indexAutomate, setIndexAutomate] = useState(0);
|
|
16
23
|
const handleOnAddNew = () => {
|
|
17
|
-
switch (type) {
|
|
24
|
+
switch (automates.type) {
|
|
18
25
|
case AUTOMATE_TYPE.ONE_TAP:
|
|
19
|
-
navigate(Routes.AddNewOneTap, { type:
|
|
26
|
+
navigate(Routes.AddNewOneTap, { type: AUTOMATE_TYPE.ONE_TAP, unit });
|
|
20
27
|
break;
|
|
21
|
-
case AUTOMATE_TYPE.
|
|
22
|
-
navigate(Routes.AddNewAutoSmart, {
|
|
28
|
+
case AUTOMATE_TYPE.AUTOMATION:
|
|
29
|
+
navigate(Routes.AddNewAutoSmart, {
|
|
30
|
+
type: AUTOMATE_TYPE.VALUE_CHANGE,
|
|
31
|
+
unit,
|
|
32
|
+
});
|
|
23
33
|
break;
|
|
24
34
|
}
|
|
25
35
|
};
|
|
36
|
+
const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
|
|
37
|
+
usePopover();
|
|
38
|
+
|
|
39
|
+
const refMenuAction = useRef();
|
|
40
|
+
const handleShowMenuAction = () => showPopoverWithRef(refMenuAction);
|
|
41
|
+
|
|
42
|
+
const onItemClick = useCallback((item, index) => {
|
|
43
|
+
setAutomates(item);
|
|
44
|
+
setIndexAutomate(index);
|
|
45
|
+
}, []);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
setAutomates(listAutomate[indexAutomate]);
|
|
48
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
+
}, [listAutomate]);
|
|
50
|
+
|
|
26
51
|
return (
|
|
27
52
|
<Section style={styles.noShadow}>
|
|
53
|
+
<TouchableOpacity
|
|
54
|
+
style={styles.dropDown}
|
|
55
|
+
onPress={handleShowMenuAction}
|
|
56
|
+
ref={refMenuAction}
|
|
57
|
+
testID={TESTID.SUB_UNIT_SELECT_AUTOMATE_TYPE}
|
|
58
|
+
>
|
|
59
|
+
<View style={styles.boxDropDown}>
|
|
60
|
+
<Text
|
|
61
|
+
testID={TESTID.SUB_UNIT_TEXT_DROPDOWN}
|
|
62
|
+
style={styles.textDropDown}
|
|
63
|
+
semibold
|
|
64
|
+
>
|
|
65
|
+
{automates?.text}
|
|
66
|
+
</Text>
|
|
67
|
+
<Icon name={'caret-down'} size={14} style={{ color: Colors.Gray8 }} />
|
|
68
|
+
</View>
|
|
69
|
+
</TouchableOpacity>
|
|
28
70
|
<View style={styles.boxDevices}>
|
|
29
|
-
{
|
|
30
|
-
automates.map((item) => (
|
|
71
|
+
{automates?.data &&
|
|
72
|
+
automates.data.map((item) => (
|
|
31
73
|
<ItemOneTap isOwner={isOwner} automate={item} unit={unit} />
|
|
32
74
|
))}
|
|
33
75
|
<ItemAddNew
|
|
@@ -36,6 +78,16 @@ const SubUnitAutomate = ({ isOwner, type, automates, unit, wrapItemStyle }) => {
|
|
|
36
78
|
wrapStyle={wrapItemStyle}
|
|
37
79
|
/>
|
|
38
80
|
</View>
|
|
81
|
+
<MenuActionMore
|
|
82
|
+
isVisible={showingPopover}
|
|
83
|
+
hideMore={hidePopover}
|
|
84
|
+
listMenuItem={listAutomate}
|
|
85
|
+
childRef={childRef}
|
|
86
|
+
onItemClick={onItemClick}
|
|
87
|
+
isTextCenter={false}
|
|
88
|
+
testID={TESTID.NAVBAR_MENU_ACTION_MORE}
|
|
89
|
+
wrapStyle={styles.wrapStyle}
|
|
90
|
+
/>
|
|
39
91
|
</Section>
|
|
40
92
|
);
|
|
41
93
|
};
|
|
@@ -63,6 +63,14 @@ const AirQuality = memo(({ summaryDetail }) => {
|
|
|
63
63
|
return outdoor_pm10_id || outdoor_pm2_5_id || outdoor_co_id ? true : false;
|
|
64
64
|
}, [outdoor_pm10_id, outdoor_pm2_5_id, outdoor_co_id]);
|
|
65
65
|
|
|
66
|
+
const configs = useMemo(() => {
|
|
67
|
+
return [
|
|
68
|
+
{ id: outdoor_pm2_5_id, title: 'PM2.5', color: 'red' },
|
|
69
|
+
{ id: outdoor_pm10_id, title: 'PM10', color: 'blue' },
|
|
70
|
+
{ id: outdoor_co_id, title: 'CO', color: 'orange' },
|
|
71
|
+
];
|
|
72
|
+
}, [outdoor_pm10_id, outdoor_pm2_5_id, outdoor_co_id]);
|
|
73
|
+
|
|
66
74
|
const [indexOutdoor, setIndexOutdoor] = useState(0);
|
|
67
75
|
const onSelectOutdoor = useCallback((i) => {
|
|
68
76
|
setIndexOutdoor(i);
|
|
@@ -154,13 +162,7 @@ const AirQuality = memo(({ summaryDetail }) => {
|
|
|
154
162
|
)}
|
|
155
163
|
{showBoxHistory && (
|
|
156
164
|
<Section type={'border'}>
|
|
157
|
-
<ConfigHistoryChart
|
|
158
|
-
configs={[
|
|
159
|
-
{ id: outdoor_pm2_5_id, title: 'PM2.5', color: 'red' },
|
|
160
|
-
{ id: outdoor_pm10_id, title: 'PM10', color: 'blue' },
|
|
161
|
-
{ id: outdoor_co_id, title: 'CO', color: 'orange' },
|
|
162
|
-
]}
|
|
163
|
-
/>
|
|
165
|
+
<ConfigHistoryChart configs={configs} />
|
|
164
166
|
</Section>
|
|
165
167
|
)}
|
|
166
168
|
</View>
|
package/src/configs/API.js
CHANGED
|
@@ -82,6 +82,9 @@ const API = {
|
|
|
82
82
|
SCConfig.apiRoot + `/property_manager/sensors/${id}/`,
|
|
83
83
|
REMOVE_SENSOR: (id) =>
|
|
84
84
|
SCConfig.apiRoot + `/property_manager/sensors/${id}/`,
|
|
85
|
+
CHANGE_SUB_UNIT: (unit_id, station_id, id) =>
|
|
86
|
+
SCConfig.apiRoot +
|
|
87
|
+
`/property_manager/${unit_id}/sub_units/${station_id}/devices/${id}/change_sub_unit/`,
|
|
85
88
|
},
|
|
86
89
|
SHARED_SENSOR: {
|
|
87
90
|
ACCESS: (id) =>
|
package/src/configs/Constants.js
CHANGED
|
@@ -93,6 +93,9 @@ export const AUTOMATE_TYPE = {
|
|
|
93
93
|
SCHEDULE: 'schedule',
|
|
94
94
|
ONE_TAP_ONLY: 'one_tap_only',
|
|
95
95
|
AUTOMATE: 'automate',
|
|
96
|
+
AUTOMATION: 'automation',
|
|
97
|
+
ALL: 'all',
|
|
98
|
+
SCENARIO: 'scenario',
|
|
96
99
|
};
|
|
97
100
|
|
|
98
101
|
export const AUTOMATE_SELECT = {
|
|
@@ -138,6 +141,10 @@ export const TESTID = {
|
|
|
138
141
|
DASHBOARD_VIEW_ALL_SHARED_UNITS: 'DASHBOARD_VIEW_ALL_SHARED_UNITS',
|
|
139
142
|
DASHBOARD_HOME_SCROLL_VIEW: 'DASHBOARD_HOME_SCROLL_VIEW',
|
|
140
143
|
|
|
144
|
+
//SmartAccountItem
|
|
145
|
+
SMART_ACCOUNT_ITEM: 'SMART_ACCOUNT_ITEM',
|
|
146
|
+
SMART_ACCOUNT_ITEM_PRESSMORE: 'SMART_ACCOUNT_ITEM_PRESSMORE',
|
|
147
|
+
|
|
141
148
|
// Login
|
|
142
149
|
LOGIN_TITLE: 'LOGIN_TITLE',
|
|
143
150
|
LOGIN_INPUT_PHONE_NUMBER: 'LOGIN_INPUT_PHONE_NUMBER',
|
|
@@ -179,6 +186,8 @@ export const TESTID = {
|
|
|
179
186
|
SUB_UNIT_DEVICES: 'SUB_UNIT_DEVICES',
|
|
180
187
|
SUB_UNIT_ICON_BARS: 'SUB_UNIT_ICON_BARS',
|
|
181
188
|
SUB_UNIT_STATION: 'SUB_UNIT_STATION',
|
|
189
|
+
SUB_UNIT_SELECT_AUTOMATE_TYPE: 'SUB_UNIT_SELECT_AUTOMATE_TYPE',
|
|
190
|
+
SUB_UNIT_TEXT_DROPDOWN: 'SUB_UNIT_TEXT_DROPDOWN',
|
|
182
191
|
|
|
183
192
|
// NavBar
|
|
184
193
|
NAVBAR_ICON_BARS: 'NAVBAR_ICON_BARS',
|
|
@@ -573,9 +582,15 @@ export const TESTID = {
|
|
|
573
582
|
HISTORY_BUTTON: 'HISTORY_BUTTON',
|
|
574
583
|
HISTORY_CALENDAR: 'HISTORY_CALENDAR',
|
|
575
584
|
|
|
585
|
+
// DropDownPicker
|
|
586
|
+
DROP_DOWN_PICKER_ITEM: 'DROP_DOWN_PICKER_ITEM',
|
|
587
|
+
|
|
576
588
|
// SelectAddress
|
|
577
589
|
BUTTON_YOUR_LOCATION: 'BUTTON_YOUR_LOCATION',
|
|
578
590
|
BUTTON_CHOOSE_ON_MAP: 'BUTTON_CHOOSE_ON_MAP',
|
|
591
|
+
|
|
592
|
+
// MoveToAnotherSubUnit
|
|
593
|
+
ROW_SUB_UNIT: 'ROW_SUB_UNIT',
|
|
579
594
|
};
|
|
580
595
|
|
|
581
596
|
export const NOTIFICATION_TYPES = {
|
|
@@ -94,12 +94,13 @@ export const sendCommandOverBluetooth = async (sensor, action, data) => {
|
|
|
94
94
|
device = getDeviceByName(bluetooth.address);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
await sendDataOverBluetooth(device, {
|
|
97
|
+
const result = await sendDataOverBluetooth(device, {
|
|
98
98
|
type: 'command',
|
|
99
99
|
command: action.key,
|
|
100
100
|
password: bluetooth ? bluetooth.password : '',
|
|
101
101
|
data,
|
|
102
102
|
});
|
|
103
|
+
return result;
|
|
103
104
|
};
|
|
104
105
|
|
|
105
106
|
export const getDeviceByName = (name) => {
|
|
@@ -138,7 +139,7 @@ export const sendDataOverBluetooth = async (
|
|
|
138
139
|
|
|
139
140
|
let connectedDevice = null;
|
|
140
141
|
let fullDataDevice = null;
|
|
141
|
-
|
|
142
|
+
let result = false;
|
|
142
143
|
try {
|
|
143
144
|
connectedDevice = await device.connect();
|
|
144
145
|
fullDataDevice =
|
|
@@ -149,16 +150,18 @@ export const sendDataOverBluetooth = async (
|
|
|
149
150
|
base64.encode(JSON.stringify(data))
|
|
150
151
|
);
|
|
151
152
|
ToastBottomHelper.success(t('Command is sent to device via bluetooth'));
|
|
153
|
+
result = true;
|
|
152
154
|
} catch (e) {
|
|
153
155
|
ToastBottomHelper.error(t('Command is fail to send via bluetooth'));
|
|
154
156
|
throw SEND_COMMAND_OVER_BLUETOOTH_FAIL;
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
if (keepConnect) {
|
|
158
|
-
return;
|
|
160
|
+
return result;
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
await device.cancelConnection();
|
|
164
|
+
return result;
|
|
162
165
|
};
|
|
163
166
|
|
|
164
167
|
export const isBluetoothEnabled = async () => {
|
|
@@ -27,7 +27,7 @@ function numberType(value) {
|
|
|
27
27
|
|
|
28
28
|
function textType(value, entityId) {
|
|
29
29
|
const textMap = textMaps[entityId];
|
|
30
|
-
return textMap[value];
|
|
30
|
+
return textMap ? textMap[value] : '';
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function keepValue(value) {
|
|
@@ -224,9 +224,12 @@ export async function sendCommandOverGoogleHome(sensor, action, data) {
|
|
|
224
224
|
await connection.sendMessagePromise(message);
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
await axiosPost(API.SENSOR.ACTIVITY_LOG(), {
|
|
227
|
+
const { success } = await axiosPost(API.SENSOR.ACTIVITY_LOG(), {
|
|
228
228
|
action_id: action.id,
|
|
229
229
|
message: 'Trigger by user action with google home',
|
|
230
230
|
});
|
|
231
|
-
|
|
231
|
+
if (success) {
|
|
232
|
+
ToastBottomHelper.success(t('command_send_success_googlehome'));
|
|
233
|
+
}
|
|
234
|
+
return success;
|
|
232
235
|
}
|
|
@@ -167,11 +167,12 @@ export const sendCommandOverLGThinq = async (sensor, action, data) => {
|
|
|
167
167
|
new_message[key] = new_property;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
await sendCommandOverInternet(
|
|
170
|
+
const result = await sendCommandOverInternet(
|
|
171
171
|
sensor,
|
|
172
172
|
action,
|
|
173
173
|
JSON.stringify(new_message),
|
|
174
174
|
'lg_thinq'
|
|
175
175
|
);
|
|
176
|
+
return result;
|
|
176
177
|
}
|
|
177
178
|
};
|