@eohjsc/react-native-smart-city 0.2.54 → 0.2.58
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/assets/images/SonosSpeaker/buttonpause-active.svg +3 -0
- package/assets/images/SonosSpeaker/buttonpause-notactive.svg +3 -0
- package/assets/images/SonosSpeaker/picture-main-notactive.svg +5 -0
- package/assets/images/SonosSpeaker/picture-main.svg +6 -0
- package/assets/images/SonosSpeaker/picture-volume.svg +3 -0
- package/package.json +4 -23
- package/src/commons/AlertAction/index.js +3 -3
- package/src/commons/Auth/__test__/AccountList.test.js +33 -0
- package/src/commons/CameraDevice/index.js +2 -0
- package/src/commons/CardShadow/index.js +1 -1
- package/src/commons/CardShadow/styles.js +1 -3
- package/src/commons/DateTimeRangeChange/index.js +2 -2
- package/src/commons/Device/HistoryChart.js +9 -39
- package/src/commons/Device/HorizontalBarChart.js +1 -1
- package/src/commons/Device/LinearChart.js +0 -34
- package/src/commons/Device/PMSensor/PMSensorIndicatior.js +1 -1
- package/src/commons/Device/PMSensor/PMSensorIndicatorStyles.js +2 -1
- package/src/commons/Device/SonosSpeaker/__test__/SonosSpeaker.test.js +57 -0
- package/src/commons/Device/SonosSpeaker/index.js +88 -0
- package/src/commons/Device/SonosSpeaker/styles.js +57 -0
- package/src/commons/Form/CurrencyInput.js +163 -0
- package/src/commons/Form/__test__/CurrencyInput.test.js +65 -0
- package/src/commons/MediaPlayerDetail/index.js +160 -160
- package/src/commons/Sharing/RowMember.js +7 -2
- package/src/commons/Sharing/__test__/RowMember.test.js +42 -0
- package/src/commons/SubUnit/ShortDetail.js +11 -5
- package/src/commons/ThreeButtonHistory/__test__/ThreeButtonHistory.test.js +17 -8
- package/src/commons/ThreeButtonHistory/index.js +52 -23
- package/src/commons/UnitSummary/AirQuality/SegmentedRoundDisplay/index.js +1 -1
- package/src/configs/API.js +5 -0
- package/src/configs/Constants.js +3 -3
- package/src/configs/SCConfig.js +8 -0
- package/src/iot/RemoteControl/Bluetooth.js +14 -0
- package/src/iot/RemoteControl/index.js +0 -1
- package/src/screens/ActivityLog/ItemLog.js +9 -0
- package/src/screens/ActivityLog/__test__/ItemLog.test.js +43 -0
- package/src/screens/AddCommon/SelectSubUnit.js +24 -2
- package/src/screens/AddCommon/SelectUnit.js +12 -0
- package/src/screens/Device/__test__/detail.test.js +0 -5
- package/src/screens/Device/components/SensorDisplayItem.js +10 -10
- package/src/screens/Device/detail.js +15 -1
- package/src/screens/Device/hooks/useDisconnectedDevice.js +31 -26
- package/src/screens/Sharing/MemberList.js +2 -9
- package/src/screens/SubUnit/AddSubUnit.js +78 -59
- package/src/screens/TDSGuide/index.js +6 -4
- package/src/screens/Unit/Detail.js +7 -1
- package/src/screens/Unit/ManageUnit/index.test.js +34 -0
- package/src/screens/Unit/ManageUnit.js +3 -4
- package/src/screens/Unit/SmartAccount.js +2 -3
- package/src/screens/Unit/SmartAccountItem.js +1 -1
- package/src/screens/Unit/Summaries.js +5 -1
- package/src/screens/Unit/hook/useStateAlertRemove.js +3 -1
- package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +1 -1
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +1 -1
- package/src/screens/UnitSummary/components/WaterQuality/Item/index.js +1 -3
- package/src/screens/UnitSummary/index.js +3 -2
- package/src/utils/Apis/axios.js +17 -5
- package/src/utils/I18n/translations/en.json +8 -3
- package/src/utils/I18n/translations/vi.json +9 -4
- package/src/utils/Utils.js +22 -2
|
@@ -214,18 +214,27 @@ describe('test ThreeButtonHistory', () => {
|
|
|
214
214
|
await calendar.props.onDayPress({ dateString: date });
|
|
215
215
|
});
|
|
216
216
|
};
|
|
217
|
-
|
|
218
|
-
await selectDate('2021-09-
|
|
219
|
-
await selectDate('2021-09-
|
|
220
|
-
await selectDate('2021-09-
|
|
221
|
-
await selectDate('2021-09-05');
|
|
222
|
-
await selectDate('2021-09-
|
|
223
|
-
await selectDate('2021-09-
|
|
217
|
+
// 2 -> 9
|
|
218
|
+
await selectDate('2021-09-20'); // 2 -> 20
|
|
219
|
+
await selectDate('2021-09-01'); // 1 -> 20
|
|
220
|
+
await selectDate('2021-09-15'); // 1 -> 15
|
|
221
|
+
await selectDate('2021-09-05'); // 5 -> 15
|
|
222
|
+
await selectDate('2021-09-15'); // 5 -> null
|
|
223
|
+
await selectDate('2021-09-05'); // null -> null
|
|
224
|
+
await selectDate('2021-09-10'); // 10 -> null
|
|
225
|
+
await selectDate('2021-09-05'); // 5 -> 10
|
|
226
|
+
await selectDate('2021-09-10'); // 5 -> null
|
|
227
|
+
await selectDate('2021-09-20'); // 5 -> 20
|
|
228
|
+
await selectDate('2021-09-05'); // null -> 20
|
|
229
|
+
await selectDate('2021-09-25'); // 20 -> 25
|
|
230
|
+
await selectDate('2021-09-20'); // null -> 25
|
|
231
|
+
await selectDate('2021-09-10'); // 10 -> 25
|
|
232
|
+
|
|
224
233
|
const viewButtonBottom = instance.findByType(ViewButtonBottom);
|
|
225
234
|
await act(async () => {
|
|
226
235
|
await viewButtonBottom.props.onRightClick();
|
|
227
236
|
});
|
|
228
237
|
expect(mockSetStartDate).toBeCalledWith(moment('2021-09-10').valueOf());
|
|
229
|
-
expect(mockSetEndDate).toBeCalledWith(moment('2021-09-
|
|
238
|
+
expect(mockSetEndDate).toBeCalledWith(moment('2021-09-25').valueOf());
|
|
230
239
|
});
|
|
231
240
|
});
|
|
@@ -20,7 +20,7 @@ const ThreeButtonHistory = memo(
|
|
|
20
20
|
const t = useTranslations();
|
|
21
21
|
const calendarRef = useRef();
|
|
22
22
|
const [selectedIndex, setSelectedIndex] = useState(2);
|
|
23
|
-
const [
|
|
23
|
+
const [showCalendar, setShowCalendar] = useState(false);
|
|
24
24
|
const [selectedStart, setSelectedStart] = useState(
|
|
25
25
|
moment(startDate).format('YYYY-MM-DD')
|
|
26
26
|
);
|
|
@@ -57,15 +57,15 @@ const ThreeButtonHistory = memo(
|
|
|
57
57
|
[selectedIndex]
|
|
58
58
|
);
|
|
59
59
|
|
|
60
|
-
const
|
|
60
|
+
const onCalendarCancel = useCallback(() => {
|
|
61
61
|
if (showSelectMonth) {
|
|
62
62
|
setShowSelectMonth(false);
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
setShowCalendar(false);
|
|
66
66
|
}, [showSelectMonth, setShowSelectMonth]);
|
|
67
67
|
|
|
68
|
-
const
|
|
68
|
+
const onCalendarDone = useCallback(() => {
|
|
69
69
|
if (showSelectMonth) {
|
|
70
70
|
setShowSelectMonth(false);
|
|
71
71
|
return;
|
|
@@ -73,7 +73,7 @@ const ThreeButtonHistory = memo(
|
|
|
73
73
|
if (selectedStart === null || selectedEnd === null) {
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
|
|
76
|
+
setShowCalendar(false);
|
|
77
77
|
setStartDate(moment(selectedStart).valueOf());
|
|
78
78
|
setEndDate(moment(selectedEnd).valueOf());
|
|
79
79
|
}, [
|
|
@@ -85,9 +85,12 @@ const ThreeButtonHistory = memo(
|
|
|
85
85
|
setShowSelectMonth,
|
|
86
86
|
]);
|
|
87
87
|
|
|
88
|
-
const
|
|
88
|
+
const onDateSelected = useCallback(
|
|
89
89
|
(date) => {
|
|
90
90
|
const selectedDate = date.dateString;
|
|
91
|
+
const mmSelectedDate = moment(selectedDate);
|
|
92
|
+
onMonthSelected(mmSelectedDate);
|
|
93
|
+
|
|
91
94
|
if (selectedDate === selectedStart) {
|
|
92
95
|
setSelectedStart(null);
|
|
93
96
|
return;
|
|
@@ -96,25 +99,54 @@ const ThreeButtonHistory = memo(
|
|
|
96
99
|
setSelectedEnd(null);
|
|
97
100
|
return;
|
|
98
101
|
}
|
|
99
|
-
|
|
102
|
+
|
|
103
|
+
if (!!selectedStart && !!selectedEnd) {
|
|
104
|
+
if (mmSelectedDate.isAfter(selectedEnd, 'date')) {
|
|
105
|
+
setSelectedEnd(selectedDate);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (mmSelectedDate.isBefore(selectedStart, 'date')) {
|
|
109
|
+
setSelectedStart(selectedDate);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (
|
|
113
|
+
Math.abs(mmSelectedDate.diff(selectedStart, 'days')) <=
|
|
114
|
+
Math.abs(mmSelectedDate.diff(selectedEnd, 'days'))
|
|
115
|
+
) {
|
|
116
|
+
setSelectedStart(selectedDate);
|
|
117
|
+
} else {
|
|
118
|
+
setSelectedEnd(selectedDate);
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (selectedStart) {
|
|
124
|
+
if (mmSelectedDate.isBefore(selectedStart, 'date')) {
|
|
125
|
+
setSelectedStart(selectedDate);
|
|
126
|
+
setSelectedEnd(selectedStart);
|
|
127
|
+
} else {
|
|
128
|
+
setSelectedEnd(selectedDate);
|
|
129
|
+
}
|
|
100
130
|
return;
|
|
101
131
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (moment(selectedDate).isAfter(selectedEnd, 'date')) {
|
|
132
|
+
|
|
133
|
+
if (selectedEnd) {
|
|
134
|
+
if (mmSelectedDate.isAfter(selectedEnd, 'date')) {
|
|
106
135
|
setSelectedStart(selectedEnd);
|
|
107
136
|
setSelectedEnd(selectedDate);
|
|
108
137
|
} else {
|
|
109
138
|
setSelectedStart(selectedDate);
|
|
110
139
|
}
|
|
140
|
+
return;
|
|
111
141
|
}
|
|
142
|
+
|
|
143
|
+
setSelectedStart(selectedDate);
|
|
112
144
|
},
|
|
113
|
-
[selectedStart, selectedEnd]
|
|
145
|
+
[selectedStart, selectedEnd, onMonthSelected]
|
|
114
146
|
);
|
|
115
147
|
|
|
116
148
|
const onPressItemButton = useCallback(
|
|
117
|
-
(index) => {
|
|
149
|
+
(index) => () => {
|
|
118
150
|
switch (index) {
|
|
119
151
|
case 0:
|
|
120
152
|
setGroupBy('week');
|
|
@@ -124,9 +156,7 @@ const ThreeButtonHistory = memo(
|
|
|
124
156
|
break;
|
|
125
157
|
case 2:
|
|
126
158
|
setGroupBy('date');
|
|
127
|
-
|
|
128
|
-
setIsShowDate(true);
|
|
129
|
-
}
|
|
159
|
+
selectedIndex === 2 && setShowCalendar(true);
|
|
130
160
|
}
|
|
131
161
|
setSelectedIndex(index);
|
|
132
162
|
},
|
|
@@ -212,7 +242,6 @@ const ThreeButtonHistory = memo(
|
|
|
212
242
|
},
|
|
213
243
|
},
|
|
214
244
|
selected: true,
|
|
215
|
-
disableTouchEvent: true,
|
|
216
245
|
color: Colors.Gray4,
|
|
217
246
|
};
|
|
218
247
|
}
|
|
@@ -228,15 +257,15 @@ const ThreeButtonHistory = memo(
|
|
|
228
257
|
<ItemButton
|
|
229
258
|
key={index}
|
|
230
259
|
dateTitle={item.dateTitle}
|
|
231
|
-
onPress={
|
|
260
|
+
onPress={onPressItemButton(index)}
|
|
232
261
|
isSelected={selectedIndex === index}
|
|
233
262
|
/>
|
|
234
263
|
);
|
|
235
264
|
})}
|
|
236
265
|
</View>
|
|
237
266
|
<BottomSheet
|
|
238
|
-
isVisible={
|
|
239
|
-
onBackdropPress={
|
|
267
|
+
isVisible={showCalendar}
|
|
268
|
+
onBackdropPress={onCalendarCancel}
|
|
240
269
|
style={styles.modal}
|
|
241
270
|
>
|
|
242
271
|
<View style={styles.calendar}>
|
|
@@ -257,7 +286,7 @@ const ThreeButtonHistory = memo(
|
|
|
257
286
|
current={currentMonth.format('YYYY-MM-DD')}
|
|
258
287
|
style={showSelectMonth && styles.displayNone}
|
|
259
288
|
markingType={'custom'}
|
|
260
|
-
onDayPress={
|
|
289
|
+
onDayPress={onDateSelected}
|
|
261
290
|
maxDate={moment().format('YYYY-MM-DD')}
|
|
262
291
|
markedDates={markedDates}
|
|
263
292
|
hideArrows={true}
|
|
@@ -267,9 +296,9 @@ const ThreeButtonHistory = memo(
|
|
|
267
296
|
<View style={styles.separator} />
|
|
268
297
|
<ViewButtonBottom
|
|
269
298
|
leftTitle={t('cancel')}
|
|
270
|
-
onLeftClick={
|
|
299
|
+
onLeftClick={onCalendarCancel}
|
|
271
300
|
rightTitle={t('done')}
|
|
272
|
-
onRightClick={
|
|
301
|
+
onRightClick={onCalendarDone}
|
|
273
302
|
/>
|
|
274
303
|
</View>
|
|
275
304
|
</BottomSheet>
|
|
@@ -163,7 +163,7 @@ const SegmentedRoundDisplay = ({
|
|
|
163
163
|
<Text
|
|
164
164
|
x={svgWidth / 2 + 50}
|
|
165
165
|
fontWeight="normal"
|
|
166
|
-
fontSize={valueText.toString().length >= 6 ?
|
|
166
|
+
fontSize={valueText.toString().length >= 6 ? 35 : 56}
|
|
167
167
|
y={svgHeight / 2 + 30}
|
|
168
168
|
fill={filledArcColor}
|
|
169
169
|
textAnchor="middle"
|
package/src/configs/API.js
CHANGED
|
@@ -172,6 +172,11 @@ const API = {
|
|
|
172
172
|
SCConfig.apiRoot +
|
|
173
173
|
`/connection_manager/lg_thinq/device_status/${sensorId}/`,
|
|
174
174
|
},
|
|
175
|
+
VCONNEX: {
|
|
176
|
+
AUTHORIZE: (client_id, redirect_uri, user_id, station_id) =>
|
|
177
|
+
// eslint-disable-next-line max-len
|
|
178
|
+
`https://partner-api-stg.vconnex.vn/oauth/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=code&scope=SYNCH&scope=CONTROL&scope=QUERY&state=${user_id}@${station_id}`,
|
|
179
|
+
},
|
|
175
180
|
},
|
|
176
181
|
NOTIFICATION: {
|
|
177
182
|
LIST_ALL_NOTIFICATIONS: (page, type) =>
|
package/src/configs/Constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Platform, Dimensions, StatusBar } from 'react-native';
|
|
2
2
|
import { RFValue } from 'react-native-responsive-fontsize';
|
|
3
|
-
import OneTap from '../../assets/images/OneTap
|
|
3
|
+
import OneTap from '../../assets/images/OneTap.svg';
|
|
4
4
|
import ValueChange from '../../assets/images/ValueChange.svg';
|
|
5
5
|
import Schedule from '../../assets/images/Schedule.svg';
|
|
6
6
|
|
|
@@ -116,13 +116,13 @@ export const AUTOMATES = {
|
|
|
116
116
|
value_change: {
|
|
117
117
|
value: AUTOMATE_TYPE.VALUE_CHANGE,
|
|
118
118
|
title: 'value_change',
|
|
119
|
-
explanation: '
|
|
119
|
+
explanation: 'setup_the_conditions',
|
|
120
120
|
icon: ValueChange,
|
|
121
121
|
},
|
|
122
122
|
schedule: {
|
|
123
123
|
value: AUTOMATE_TYPE.SCHEDULE,
|
|
124
124
|
title: 'schedule',
|
|
125
|
-
explanation: '
|
|
125
|
+
explanation: 'setup_the_schedule',
|
|
126
126
|
icon: Schedule,
|
|
127
127
|
},
|
|
128
128
|
};
|
package/src/configs/SCConfig.js
CHANGED
|
@@ -90,6 +90,8 @@ const SCDefaultConfig = {
|
|
|
90
90
|
LG_CLIENT_ID: '2b85aee334f046848341547894bb7c4e',
|
|
91
91
|
LG_REDIRECT_URI_APP: 'app://eoh/sync-lg-device',
|
|
92
92
|
LG_URL: 'https://qt-vn.m.lgaccount.com/emp/v2',
|
|
93
|
+
VCONNEX_CLIENT_ID: '',
|
|
94
|
+
VCONNEX_REDIRECT_URI_APP: '',
|
|
93
95
|
pusherAppKey: '9a591ae4a764acc08714',
|
|
94
96
|
pusherAppCluster: 'ap1',
|
|
95
97
|
};
|
|
@@ -100,6 +102,8 @@ export class SCConfig {
|
|
|
100
102
|
static LG_CLIENT_ID = SCDefaultConfig.LG_CLIENT_ID;
|
|
101
103
|
static LG_REDIRECT_URI_APP = SCDefaultConfig.LG_REDIRECT_URI_APP;
|
|
102
104
|
static LG_URL = SCDefaultConfig.LG_URL;
|
|
105
|
+
static VCONNEX_CLIENT_ID = SCDefaultConfig.VCONNEX_CLIENT_ID;
|
|
106
|
+
static VCONNEX_REDIRECT_URI_APP = SCDefaultConfig.VCONNEX_REDIRECT_URI_APP;
|
|
103
107
|
static pusherAppKey = SCDefaultConfig.pusherAppKey;
|
|
104
108
|
static pusherAppCluste = SCDefaultConfig.pusherAppCluster;
|
|
105
109
|
}
|
|
@@ -113,6 +117,10 @@ export const initSCConfig = (config) => {
|
|
|
113
117
|
SCConfig.LG_REDIRECT_URI_APP =
|
|
114
118
|
config.LG_REDIRECT_URI_APP ?? SCDefaultConfig.LG_REDIRECT_URI_APP;
|
|
115
119
|
SCConfig.LG_URL = config.LG_URL ?? SCDefaultConfig.LG_URL;
|
|
120
|
+
SCConfig.VCONNEX_CLIENT_ID =
|
|
121
|
+
config.VCONNEX_CLIENT_ID ?? SCDefaultConfig.VCONNEX_CLIENT_ID;
|
|
122
|
+
SCConfig.VCONNEX_REDIRECT_URI_APP =
|
|
123
|
+
config.VCONNEX_REDIRECT_URI_APP ?? SCDefaultConfig.VCONNEX_REDIRECT_URI_APP;
|
|
116
124
|
SCConfig.pusherAppKey = config.pusherAppKey ?? SCDefaultConfig.pusherAppKey;
|
|
117
125
|
SCConfig.pusherAppCluster =
|
|
118
126
|
config.pusherAppCluster ?? SCDefaultConfig.pusherAppCluster;
|
|
@@ -5,6 +5,7 @@ import t from '../../hooks/Common/useTranslations';
|
|
|
5
5
|
import base64 from 'react-native-base64';
|
|
6
6
|
import { BleManager } from 'react-native-ble-plx';
|
|
7
7
|
import { ToastBottomHelper } from '../../utils/Utils';
|
|
8
|
+
import { useEffect, useState } from 'react';
|
|
8
9
|
|
|
9
10
|
const bluetoothDevices = {};
|
|
10
11
|
const needToScanDevices = [];
|
|
@@ -165,6 +166,19 @@ export const isBluetoothEnabled = async () => {
|
|
|
165
166
|
return state === 'PoweredOn';
|
|
166
167
|
};
|
|
167
168
|
|
|
169
|
+
export const useIsBluetoothEnabled = () => {
|
|
170
|
+
const [isEnabled, setIsEnabled] = useState(null);
|
|
171
|
+
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
const subscription = bleManager.onStateChange((state) => {
|
|
174
|
+
setIsEnabled(state === 'PoweredOn');
|
|
175
|
+
}, true);
|
|
176
|
+
|
|
177
|
+
return () => subscription.remove();
|
|
178
|
+
}, []);
|
|
179
|
+
return isEnabled;
|
|
180
|
+
};
|
|
181
|
+
|
|
168
182
|
export const enableBluetoothForAndroid = async () => {
|
|
169
183
|
await bleManager.enable();
|
|
170
184
|
};
|
|
@@ -39,6 +39,15 @@ const DetailLog = ({ item }) => {
|
|
|
39
39
|
<Text style={styles.name}>{item.name || item.params?.username}</Text>
|
|
40
40
|
</Text>
|
|
41
41
|
);
|
|
42
|
+
default:
|
|
43
|
+
return (
|
|
44
|
+
<Text style={styles.text}>
|
|
45
|
+
{item.action_name
|
|
46
|
+
? `${item.action_name} ${t('by')} `
|
|
47
|
+
: `${t('activated_by')} `}
|
|
48
|
+
<Text style={styles.name}>{item.name || item.params?.username}</Text>
|
|
49
|
+
</Text>
|
|
50
|
+
);
|
|
42
51
|
}
|
|
43
52
|
};
|
|
44
53
|
|
|
@@ -60,6 +60,49 @@ test('test ItemLog one tap', () => {
|
|
|
60
60
|
expect(texts[2].props.children).toBe(props.item.params.username);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
test('test ItemLog script update', () => {
|
|
64
|
+
let tree;
|
|
65
|
+
let props = {
|
|
66
|
+
item: {
|
|
67
|
+
content_code: 'SCRIPT_UPDATED_BY',
|
|
68
|
+
params: {
|
|
69
|
+
username: 'username',
|
|
70
|
+
},
|
|
71
|
+
created_at: '2021-07-02T15:48:24.917932Z',
|
|
72
|
+
},
|
|
73
|
+
type: 'automate',
|
|
74
|
+
length: 2,
|
|
75
|
+
index: 1,
|
|
76
|
+
};
|
|
77
|
+
act(() => {
|
|
78
|
+
tree = create(wrapComponent(props));
|
|
79
|
+
});
|
|
80
|
+
const instance = tree.root;
|
|
81
|
+
const texts = instance.findAllByType(Text);
|
|
82
|
+
expect(texts[2].props.children).toBe(props.item.params.username);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('test ItemLog no content_code', () => {
|
|
86
|
+
let tree;
|
|
87
|
+
let props = {
|
|
88
|
+
item: {
|
|
89
|
+
params: {
|
|
90
|
+
username: 'username',
|
|
91
|
+
},
|
|
92
|
+
created_at: '2021-07-02T15:48:24.917932Z',
|
|
93
|
+
},
|
|
94
|
+
type: 'action',
|
|
95
|
+
length: 2,
|
|
96
|
+
index: 1,
|
|
97
|
+
};
|
|
98
|
+
act(() => {
|
|
99
|
+
tree = create(wrapComponent(props));
|
|
100
|
+
});
|
|
101
|
+
const instance = tree.root;
|
|
102
|
+
const texts = instance.findAllByType(Text);
|
|
103
|
+
expect(texts[2].props.children).toBe(props.item.params.username);
|
|
104
|
+
});
|
|
105
|
+
|
|
63
106
|
describe('test ItemLog emergency event', () => {
|
|
64
107
|
let tree;
|
|
65
108
|
let props;
|
|
@@ -11,6 +11,7 @@ import Routes from '../../utils/Route';
|
|
|
11
11
|
import { TESTID } from '../../configs/Constants';
|
|
12
12
|
import styles from './SelectSubUnitStyles';
|
|
13
13
|
import Button from '../../commons/Button';
|
|
14
|
+
import { SCConfig } from '../../configs/SCConfig';
|
|
14
15
|
|
|
15
16
|
const AddCommonSelectSubUnit = ({ route }) => {
|
|
16
17
|
const t = useTranslations();
|
|
@@ -31,6 +32,9 @@ const AddCommonSelectSubUnit = ({ route }) => {
|
|
|
31
32
|
case 'AddHassiDevice':
|
|
32
33
|
setTitle(t('select_a_sub_unit'));
|
|
33
34
|
break;
|
|
35
|
+
case 'AddVconnexDevice':
|
|
36
|
+
setTitle(t('select_a_sub_unit'));
|
|
37
|
+
break;
|
|
34
38
|
default:
|
|
35
39
|
setTitle(t('add_new_gateway'));
|
|
36
40
|
setSubTitle(t('select_a_sub_unit'));
|
|
@@ -70,10 +74,28 @@ const AddCommonSelectSubUnit = ({ route }) => {
|
|
|
70
74
|
station: subUnits[selectedIndex]?.id,
|
|
71
75
|
});
|
|
72
76
|
break;
|
|
77
|
+
case 'AddVconnexDevice':
|
|
78
|
+
navigation.navigate(Routes.Browser, {
|
|
79
|
+
link: API.IOT.VCONNEX.AUTHORIZE(
|
|
80
|
+
SCConfig.VCONNEX_CLIENT_ID,
|
|
81
|
+
SCConfig.VCONNEX_REDIRECT_URI_APP,
|
|
82
|
+
unit.user_id,
|
|
83
|
+
subUnits[selectedIndex]?.id
|
|
84
|
+
),
|
|
85
|
+
});
|
|
86
|
+
break;
|
|
73
87
|
default:
|
|
74
88
|
break;
|
|
75
89
|
}
|
|
76
|
-
}, [
|
|
90
|
+
}, [
|
|
91
|
+
addType,
|
|
92
|
+
navigation,
|
|
93
|
+
subUnits,
|
|
94
|
+
selectedIndex,
|
|
95
|
+
unit?.name,
|
|
96
|
+
unit.user_id,
|
|
97
|
+
route.params,
|
|
98
|
+
]);
|
|
77
99
|
|
|
78
100
|
const handleSelectIndex = (index) => {
|
|
79
101
|
if (index !== selectedIndex) {
|
|
@@ -86,7 +108,7 @@ const AddCommonSelectSubUnit = ({ route }) => {
|
|
|
86
108
|
const addSubUnit = useCallback(() => {
|
|
87
109
|
navigation.navigate(Routes.AddSubUnitStack, {
|
|
88
110
|
screen: Routes.AddSubUnit,
|
|
89
|
-
params: { unit, ...route.params },
|
|
111
|
+
params: { unit, ...route.params, addType: 'AddHassiDevice' },
|
|
90
112
|
});
|
|
91
113
|
}, [navigation, unit, route.params]);
|
|
92
114
|
|
|
@@ -48,6 +48,9 @@ const AddCommonSelectUnit = ({ route }) => {
|
|
|
48
48
|
case 'AddHassioDevice':
|
|
49
49
|
setTitle(t('text_select_a_unit'));
|
|
50
50
|
break;
|
|
51
|
+
case 'AddVconnexDevice':
|
|
52
|
+
setTitle(t('text_select_a_unit'));
|
|
53
|
+
break;
|
|
51
54
|
default:
|
|
52
55
|
setTitle(t('add_new_sub_unit'));
|
|
53
56
|
setSubTitle(t('add_new_subunit_select_unit'));
|
|
@@ -102,6 +105,15 @@ const AddCommonSelectUnit = ({ route }) => {
|
|
|
102
105
|
unit_id: units[selectedIndex].id,
|
|
103
106
|
});
|
|
104
107
|
break;
|
|
108
|
+
case 'AddVconnexDevice':
|
|
109
|
+
navigation.navigate(Routes.AddDeviceStack, {
|
|
110
|
+
screen: Routes.AddCommonSelectSubUnit,
|
|
111
|
+
params: {
|
|
112
|
+
unit_id: units[selectedIndex].id,
|
|
113
|
+
addType: 'AddVconnexDevice',
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
break;
|
|
105
117
|
default:
|
|
106
118
|
break;
|
|
107
119
|
}
|
|
@@ -239,11 +239,6 @@ describe('test DeviceDetail', () => {
|
|
|
239
239
|
);
|
|
240
240
|
expect(sensorDisplayItem.length).toEqual(2);
|
|
241
241
|
|
|
242
|
-
const itemMediaPlayer = instance.find(
|
|
243
|
-
(el) => el.props.testID === TESTID.DEVICE_DETAIL_MEDIA_PLAYER
|
|
244
|
-
);
|
|
245
|
-
expect(itemMediaPlayer).toBeDefined();
|
|
246
|
-
|
|
247
242
|
const itemActionGroup = instance.find(
|
|
248
243
|
(el) => el.props.testID === TESTID.DEVICE_DETAIL_ACTION_GROUP
|
|
249
244
|
);
|
|
@@ -2,11 +2,8 @@ import React, { useCallback } from 'react';
|
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import ActionGroup from '../../../commons/ActionGroup';
|
|
4
4
|
import { Card } from '../../../commons/CardShadow';
|
|
5
|
-
import MediaPlayer from '../../../commons/MediaPlayer';
|
|
6
|
-
import { Device } from '../../../configs';
|
|
7
5
|
import { TESTID } from '../../../configs/Constants';
|
|
8
6
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
9
|
-
import { standardizeCameraScreenSize } from '../../../utils/Utils';
|
|
10
7
|
import { DetailHistoryChart } from './DetailHistoryChart';
|
|
11
8
|
import { sendRemoteCommand } from '../../../iot/RemoteControl';
|
|
12
9
|
import CurrentRainSensor from '../../../commons/Device/RainningSensor/CurrentRainSensor';
|
|
@@ -20,8 +17,11 @@ import ListQualityIndicator from '../../../commons/Device/WaterQualitySensor/Lis
|
|
|
20
17
|
import EmergencyDetail from '../../../commons/Device/Emergency/EmergencyDetail';
|
|
21
18
|
import EmergencyButton from '../../../commons/Device/Emergency/EmergencyButton';
|
|
22
19
|
import FooterInfo from '../../../commons/Device/FooterInfo';
|
|
20
|
+
import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
|
|
21
|
+
import { standardizeCameraScreenSize } from '../../../utils/Utils';
|
|
22
|
+
import { Device } from '../../../configs';
|
|
23
23
|
|
|
24
|
-
const {
|
|
24
|
+
const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
|
|
25
25
|
Device.screenWidth - 32
|
|
26
26
|
);
|
|
27
27
|
|
|
@@ -51,15 +51,15 @@ export const SensorDisplayItem = ({
|
|
|
51
51
|
return (
|
|
52
52
|
<Card title={t('camera')}>
|
|
53
53
|
<View style={styles.mediaContainer}>
|
|
54
|
-
<
|
|
55
|
-
testID={TESTID.DEVICE_DETAIL_MEDIA_PLAYER}
|
|
54
|
+
<MediaPlayerDetail
|
|
56
55
|
uri={item.configuration.uri}
|
|
57
|
-
style={{ height: standardizeHeight }}
|
|
58
|
-
ratioWidth={standardizeWidth - 32}
|
|
59
56
|
thumbnail={{
|
|
60
|
-
uri:
|
|
57
|
+
uri: background,
|
|
61
58
|
}}
|
|
62
|
-
|
|
59
|
+
key={`camera-device-${item.configuration.id}`}
|
|
60
|
+
cameraName={item.configuration.name}
|
|
61
|
+
width={standardizeWidth - 32}
|
|
62
|
+
height={standardizeHeight - 16}
|
|
63
63
|
/>
|
|
64
64
|
</View>
|
|
65
65
|
</Card>
|
|
@@ -79,7 +79,21 @@ const DeviceDetail = ({ route }) => {
|
|
|
79
79
|
[sensor]
|
|
80
80
|
);
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
const isDeviceHasBle = useMemo(() => {
|
|
83
|
+
const action = display.items.filter((item) => item.type === 'action');
|
|
84
|
+
if (action.length === 0) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return action.some((item) => {
|
|
89
|
+
const { configuration } = item?.configuration;
|
|
90
|
+
return JSON.stringify(configuration).includes(
|
|
91
|
+
'"command_prefer_over_bluetooth":true'
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
}, [display]);
|
|
95
|
+
|
|
96
|
+
useDisconnectedDevice(sensorName, isDeviceHasBle);
|
|
83
97
|
|
|
84
98
|
const netInfo = useNetInfo();
|
|
85
99
|
|
|
@@ -4,10 +4,11 @@ import { Alert, Linking, Platform } from 'react-native';
|
|
|
4
4
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
5
5
|
import {
|
|
6
6
|
enableBluetoothForAndroid,
|
|
7
|
-
|
|
7
|
+
useIsBluetoothEnabled,
|
|
8
8
|
} from '../../../iot/RemoteControl/Bluetooth';
|
|
9
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
9
10
|
|
|
10
|
-
export const useDisconnectedDevice = (
|
|
11
|
+
export const useDisconnectedDevice = (sensorName, isDeviceHasBle) => {
|
|
11
12
|
const t = useTranslations();
|
|
12
13
|
const openBluetoothIOS = () => {
|
|
13
14
|
Linking.openURL('App-Prefs:Bluetooth');
|
|
@@ -32,32 +33,36 @@ export const useDisconnectedDevice = (isConnected, sensorName) => {
|
|
|
32
33
|
onPress: () => enableBluetoothForAndroid(),
|
|
33
34
|
},
|
|
34
35
|
];
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{ name: sensorName }
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
'
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
36
|
+
|
|
37
|
+
const netState = NetInfo.useNetInfo();
|
|
38
|
+
const isBluetoothEnabled = useIsBluetoothEnabled();
|
|
39
|
+
|
|
40
|
+
const checkNetWorkConnect = useCallback(
|
|
41
|
+
async (isHavingInternet, isBtEnabled) => {
|
|
42
|
+
if (!isHavingInternet && isDeviceHasBle) {
|
|
43
|
+
if (isBtEnabled === true) {
|
|
44
|
+
ToastBottomHelper.info(
|
|
45
|
+
t('your_internet_is_disconnected', { name: sensorName }),
|
|
46
|
+
t('change_to_control_via_bluetooth_connection', {
|
|
47
|
+
name: sensorName,
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
} else if (isBtEnabled === false) {
|
|
51
|
+
Alert.alert(
|
|
52
|
+
'',
|
|
53
|
+
t(
|
|
54
|
+
'your_connection_to_the_server_was_disconnected_please_open_the_bluetooth_to_continue'
|
|
55
|
+
),
|
|
56
|
+
actions
|
|
57
|
+
);
|
|
58
|
+
}
|
|
55
59
|
}
|
|
56
|
-
}
|
|
60
|
+
},
|
|
57
61
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
58
|
-
|
|
62
|
+
[isDeviceHasBle]
|
|
63
|
+
);
|
|
59
64
|
|
|
60
65
|
useEffect(() => {
|
|
61
|
-
checkNetWorkConnect();
|
|
62
|
-
}, [checkNetWorkConnect]);
|
|
66
|
+
checkNetWorkConnect(netState.isConnected, isBluetoothEnabled);
|
|
67
|
+
}, [netState.isConnected, isBluetoothEnabled, checkNetWorkConnect]);
|
|
63
68
|
};
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import React, { useCallback } from 'react';
|
|
2
2
|
import { IconOutline } from '@ant-design/icons-react-native';
|
|
3
3
|
import { useNavigation } from '@react-navigation/native';
|
|
4
|
-
import {
|
|
5
|
-
StyleSheet,
|
|
6
|
-
TouchableOpacity,
|
|
7
|
-
View,
|
|
8
|
-
ActivityIndicator,
|
|
9
|
-
} from 'react-native';
|
|
4
|
+
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
10
5
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
11
6
|
|
|
12
7
|
import { Colors } from '../../configs';
|
|
@@ -91,9 +86,7 @@ const MemberList = ({ route }) => {
|
|
|
91
86
|
loading={isRefresh}
|
|
92
87
|
onRefresh={onRefresh}
|
|
93
88
|
>
|
|
94
|
-
{loading
|
|
95
|
-
<ActivityIndicator />
|
|
96
|
-
) : (
|
|
89
|
+
{!loading && (
|
|
97
90
|
<SharingMembers
|
|
98
91
|
dataMember={dataMembers}
|
|
99
92
|
ownerId={unit.user_id}
|