@eohjsc/react-native-smart-city 0.7.23 → 0.7.25
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/index.js +2 -0
- package/package.json +1 -1
- package/src/commons/Dashboard/MyDashboardDevice/__test__/index.test.js +171 -0
- package/src/commons/Dashboard/MyDashboardDevice/index.js +218 -0
- package/src/commons/Dashboard/MyDashboardDevice/styles.js +60 -0
- package/src/commons/Device/ItemDevice.js +12 -3
- package/src/commons/Device/ItemDeviceWrapper.js +10 -2
- package/src/commons/SubUnit/DeviceTemplate/DeviceTemplate.js +8 -3
- package/src/commons/UnitSummary/ConfigHistoryChart/index.js +7 -1
- package/src/configs/API.js +7 -0
- package/src/configs/AccessibilityLabel.js +2 -0
- package/src/context/actionType.ts +4 -0
- package/src/context/mockStore.ts +5 -0
- package/src/context/reducer.ts +30 -0
- package/src/iot/mqtt.js +163 -47
- package/src/navigations/UnitStack.js +14 -0
- package/src/screens/Device/__test__/detail.test.js +42 -1
- package/src/screens/Device/__test__/mqttDetail.test.js +411 -190
- package/src/screens/Device/detail.js +50 -14
- package/src/screens/Device/hooks/useDashboardDevice.js +34 -0
- package/src/utils/FactoryGateway.js +105 -0
- package/src/utils/I18n/translations/en.js +3 -0
- package/src/utils/I18n/translations/vi.js +7 -4
- package/src/utils/Storage.js +18 -2
package/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { initSCConfig } from './src/configs';
|
|
|
14
14
|
import AutomateStack from './src/navigations/AutomateStack';
|
|
15
15
|
import NotificationStack from './src/navigations/NotificationStack';
|
|
16
16
|
import MyPinnedSharedUnit from './src/commons/Dashboard/MyPinnedSharedUnit';
|
|
17
|
+
import MyDashboardDevice from './src/commons/Dashboard/MyDashboardDevice';
|
|
17
18
|
import MyUnit from './src/commons/Dashboard/MyUnit';
|
|
18
19
|
import SharedUnit from './src/commons/Unit/SharedUnit';
|
|
19
20
|
import { Action } from './src/context/actionType';
|
|
@@ -41,6 +42,7 @@ export {
|
|
|
41
42
|
NotificationStack,
|
|
42
43
|
MyPinnedSharedUnit,
|
|
43
44
|
SharedUnit,
|
|
45
|
+
MyDashboardDevice,
|
|
44
46
|
MyUnit,
|
|
45
47
|
SCWrapper,
|
|
46
48
|
Action,
|
package/package.json
CHANGED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
2
|
+
import React, { useContext } from 'react';
|
|
3
|
+
import renderer, { act } from 'react-test-renderer';
|
|
4
|
+
|
|
5
|
+
import { Action } from '../../../../context/actionType';
|
|
6
|
+
import { API } from '../../../../configs';
|
|
7
|
+
import { AccessibilityLabel } from '../../../../configs/Constants';
|
|
8
|
+
import { SCProvider } from '../../../../context';
|
|
9
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
10
|
+
import { Section } from '../../../Section';
|
|
11
|
+
import ItemDevice from '../../../Device/ItemDevice';
|
|
12
|
+
import { DeviceTemplate } from '../../../SubUnit/DeviceTemplate/DeviceTemplate';
|
|
13
|
+
import api from '../../../../utils/Apis/axios';
|
|
14
|
+
import Routes from '../../../../utils/Route';
|
|
15
|
+
import MyDashboardDevice from '..';
|
|
16
|
+
|
|
17
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
18
|
+
|
|
19
|
+
const wrapComponent = () => (
|
|
20
|
+
<SCProvider initState={mockSCStore({})}>
|
|
21
|
+
<MyDashboardDevice refreshing={true} />
|
|
22
|
+
</SCProvider>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
describe('Test MyDashboardDevice', () => {
|
|
26
|
+
let tree;
|
|
27
|
+
const data = [
|
|
28
|
+
{
|
|
29
|
+
id: 1,
|
|
30
|
+
name: 'EoH',
|
|
31
|
+
devices: [
|
|
32
|
+
{
|
|
33
|
+
id: 1,
|
|
34
|
+
name: 'LED',
|
|
35
|
+
is_managed_by_backend: true,
|
|
36
|
+
device_type: '',
|
|
37
|
+
station: {
|
|
38
|
+
id: 1,
|
|
39
|
+
name: 'Phòng họp',
|
|
40
|
+
},
|
|
41
|
+
quick_action: {
|
|
42
|
+
config_id: 1,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 2,
|
|
47
|
+
name: 'Presence',
|
|
48
|
+
is_managed_by_backend: true,
|
|
49
|
+
device_type: '',
|
|
50
|
+
station: {
|
|
51
|
+
id: 1,
|
|
52
|
+
name: 'Phòng họp',
|
|
53
|
+
},
|
|
54
|
+
station_items: [
|
|
55
|
+
{
|
|
56
|
+
configuration: {
|
|
57
|
+
config: 2,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 3,
|
|
64
|
+
name: 'Switch',
|
|
65
|
+
is_managed_by_backend: false,
|
|
66
|
+
device_type: 'GOOGLE_HOME',
|
|
67
|
+
station: {
|
|
68
|
+
id: 1,
|
|
69
|
+
name: 'Phòng họp',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
const mockSetAction = jest.fn();
|
|
76
|
+
|
|
77
|
+
beforeEach(async () => {
|
|
78
|
+
mock.reset();
|
|
79
|
+
useContext.mockReturnValue({
|
|
80
|
+
stateData: mockSCStore({
|
|
81
|
+
app: { isNeedUpdateCache: false },
|
|
82
|
+
}),
|
|
83
|
+
setAction: mockSetAction,
|
|
84
|
+
});
|
|
85
|
+
mockSetAction.mockClear();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('Test dashboard no device', async () => {
|
|
89
|
+
await act(async () => {
|
|
90
|
+
tree = await renderer.create(wrapComponent());
|
|
91
|
+
});
|
|
92
|
+
const instance = tree.root;
|
|
93
|
+
const sectors = instance.findAllByType(Section);
|
|
94
|
+
expect(sectors).toHaveLength(0);
|
|
95
|
+
expect(mockSetAction).not.toHaveBeenCalled();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('Test dashboard with devices and go to unit', async () => {
|
|
99
|
+
mock.onGet(API.UNIT.MY_DASHBOARD_DEVICES()).reply(200, data);
|
|
100
|
+
await act(async () => {
|
|
101
|
+
tree = await renderer.create(wrapComponent());
|
|
102
|
+
});
|
|
103
|
+
const instance = tree.root;
|
|
104
|
+
const devices = instance.findAllByType(ItemDevice);
|
|
105
|
+
expect(devices).toHaveLength(2);
|
|
106
|
+
const deviceTemplates = instance.findAllByType(DeviceTemplate);
|
|
107
|
+
expect(deviceTemplates).toHaveLength(1);
|
|
108
|
+
|
|
109
|
+
const goToUnit = instance.findByProps({
|
|
110
|
+
accessibilityLabel: `${AccessibilityLabel.UNIT_GO_TO_DETAIL}-0`,
|
|
111
|
+
});
|
|
112
|
+
await act(async () => {
|
|
113
|
+
await goToUnit.props.onPress();
|
|
114
|
+
});
|
|
115
|
+
expect(global.mockedNavigate).toHaveBeenCalledWith(Routes.UnitStack, {
|
|
116
|
+
params: {
|
|
117
|
+
unitId: 1,
|
|
118
|
+
},
|
|
119
|
+
screen: Routes.UnitDetail,
|
|
120
|
+
});
|
|
121
|
+
expect(mockSetAction).toHaveBeenCalledWith(
|
|
122
|
+
Action.SET_DEVICES_STATUS,
|
|
123
|
+
data[0].devices
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('Test dashboard with devices and go to device', async () => {
|
|
128
|
+
useContext.mockReturnValue({
|
|
129
|
+
stateData: mockSCStore({
|
|
130
|
+
app: { isNeedUpdateCache: true },
|
|
131
|
+
}),
|
|
132
|
+
setAction: mockSetAction,
|
|
133
|
+
});
|
|
134
|
+
mock.onGet(API.UNIT.MY_DASHBOARD_DEVICES()).reply(200, data);
|
|
135
|
+
await act(async () => {
|
|
136
|
+
tree = await renderer.create(wrapComponent());
|
|
137
|
+
});
|
|
138
|
+
const instance = tree.root;
|
|
139
|
+
const devices = instance.findAllByType(ItemDevice);
|
|
140
|
+
expect(devices).toHaveLength(2);
|
|
141
|
+
const deviceTemplates = instance.findAllByType(DeviceTemplate);
|
|
142
|
+
expect(deviceTemplates).toHaveLength(1);
|
|
143
|
+
|
|
144
|
+
await act(async () => {
|
|
145
|
+
await devices[0].props.goToDetail();
|
|
146
|
+
});
|
|
147
|
+
expect(global.mockedNavigate).toHaveBeenCalledWith(Routes.UnitStack, {
|
|
148
|
+
params: {
|
|
149
|
+
sensorId: 1,
|
|
150
|
+
station: {
|
|
151
|
+
id: 1,
|
|
152
|
+
name: 'Phòng họp',
|
|
153
|
+
},
|
|
154
|
+
title: 'LED',
|
|
155
|
+
unitId: 1,
|
|
156
|
+
},
|
|
157
|
+
screen: Routes.DeviceDetail,
|
|
158
|
+
});
|
|
159
|
+
expect(mockSetAction).toHaveBeenCalledTimes(2);
|
|
160
|
+
expect(mockSetAction).toHaveBeenNthCalledWith(
|
|
161
|
+
1,
|
|
162
|
+
Action.IS_CHECK_CLEAR_CACHE_UNITS,
|
|
163
|
+
false
|
|
164
|
+
);
|
|
165
|
+
expect(mockSetAction).toHaveBeenNthCalledWith(
|
|
166
|
+
2,
|
|
167
|
+
Action.SET_DEVICES_STATUS,
|
|
168
|
+
data[0].devices
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { API, Colors, Images } from '../../../configs';
|
|
2
|
+
import { AccessibilityLabel, DEVICE_TYPE } from '../../../configs/Constants';
|
|
3
|
+
import { Image, FlatList, TouchableOpacity, View } from 'react-native';
|
|
4
|
+
import React, {
|
|
5
|
+
memo,
|
|
6
|
+
useCallback,
|
|
7
|
+
useContext,
|
|
8
|
+
useMemo,
|
|
9
|
+
useEffect,
|
|
10
|
+
useState,
|
|
11
|
+
} from 'react';
|
|
12
|
+
import { SCContext, useSCContextSelector } from '../../../context';
|
|
13
|
+
import { axiosGet, fetchWithCache } from '../../../utils/Apis/axios';
|
|
14
|
+
import { useWatchConfigs } from '../../../hooks/IoT';
|
|
15
|
+
import { useIsFocused, useNavigation } from '@react-navigation/native';
|
|
16
|
+
|
|
17
|
+
import { Action } from '../../../context/actionType';
|
|
18
|
+
import Routes from '../../../utils/Route';
|
|
19
|
+
import { Section } from '../../Section';
|
|
20
|
+
import Text from '../../Text';
|
|
21
|
+
import { keyExtractor } from '../../../utils/Utils';
|
|
22
|
+
import ItemDevice from '../../Device/ItemDevice';
|
|
23
|
+
import { DeviceTemplate } from '../../SubUnit/DeviceTemplate/DeviceTemplate';
|
|
24
|
+
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
25
|
+
import styles from './styles';
|
|
26
|
+
|
|
27
|
+
const MyDashboardDevice = ({ refreshing }) => {
|
|
28
|
+
const t = useTranslations();
|
|
29
|
+
const isFocused = useIsFocused();
|
|
30
|
+
const navigation = useNavigation();
|
|
31
|
+
const { setAction } = useContext(SCContext);
|
|
32
|
+
const isNeedUpdateCache = useSCContextSelector(
|
|
33
|
+
(state) => state.app.isNeedUpdateCache
|
|
34
|
+
);
|
|
35
|
+
const [myDashboardDevices, setMyDashboardDevices] = useState([]);
|
|
36
|
+
|
|
37
|
+
const configsNeedWatching = useMemo(() => {
|
|
38
|
+
const configIds = [];
|
|
39
|
+
|
|
40
|
+
myDashboardDevices.forEach(({ devices }) => {
|
|
41
|
+
devices
|
|
42
|
+
.filter((device) => device.device_type !== DEVICE_TYPE.GOOGLE_HOME)
|
|
43
|
+
.forEach((device) => {
|
|
44
|
+
const quickActionId = device.quick_action?.config_id;
|
|
45
|
+
quickActionId && configIds.push(quickActionId);
|
|
46
|
+
|
|
47
|
+
device.station_items?.forEach((item) => {
|
|
48
|
+
const stationConfigId = item.configuration?.config;
|
|
49
|
+
stationConfigId && configIds.push(stationConfigId);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return configIds;
|
|
55
|
+
}, [myDashboardDevices]);
|
|
56
|
+
|
|
57
|
+
useWatchConfigs(configsNeedWatching);
|
|
58
|
+
|
|
59
|
+
const fetchMyDashboardDevices = useCallback(async () => {
|
|
60
|
+
if (isNeedUpdateCache) {
|
|
61
|
+
setAction(Action.IS_CHECK_CLEAR_CACHE_UNITS, false);
|
|
62
|
+
const { success, data } = await axiosGet(
|
|
63
|
+
API.UNIT.MY_DASHBOARD_DEVICES(),
|
|
64
|
+
{},
|
|
65
|
+
true
|
|
66
|
+
);
|
|
67
|
+
if (success) {
|
|
68
|
+
setMyDashboardDevices(data);
|
|
69
|
+
data.forEach((dashboard) => {
|
|
70
|
+
setAction(Action.SET_DEVICES_STATUS, dashboard.devices);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
await fetchWithCache(API.UNIT.MY_DASHBOARD_DEVICES(), {}, (response) => {
|
|
75
|
+
const { success, data } = response;
|
|
76
|
+
if (success) {
|
|
77
|
+
setMyDashboardDevices(data);
|
|
78
|
+
data.forEach((dashboard) => {
|
|
79
|
+
setAction(Action.SET_DEVICES_STATUS, dashboard.devices);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
85
|
+
}, []);
|
|
86
|
+
|
|
87
|
+
const goToUnitDetail = useCallback(
|
|
88
|
+
(unit) => () => {
|
|
89
|
+
navigation.navigate(Routes.UnitStack, {
|
|
90
|
+
screen: Routes.UnitDetail,
|
|
91
|
+
params: {
|
|
92
|
+
unitId: unit.id,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
[navigation]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const goToDeviceDetail = useCallback(
|
|
100
|
+
(unitId, device) => () => {
|
|
101
|
+
navigation.navigate(Routes.UnitStack, {
|
|
102
|
+
screen: Routes.DeviceDetail,
|
|
103
|
+
params: {
|
|
104
|
+
unitId: unitId,
|
|
105
|
+
station: device.station,
|
|
106
|
+
sensorId: device.id,
|
|
107
|
+
title: device.name,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
[navigation]
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const renderStationItem = useCallback(
|
|
115
|
+
(device, unitId, stationItem) => {
|
|
116
|
+
return (
|
|
117
|
+
<DeviceTemplate
|
|
118
|
+
device={device}
|
|
119
|
+
stationItem={stationItem}
|
|
120
|
+
unit={{ id: unitId }}
|
|
121
|
+
station={device.station}
|
|
122
|
+
goToDetail={goToDeviceDetail(unitId, device)}
|
|
123
|
+
key={`device-template-${stationItem.id}`}
|
|
124
|
+
/>
|
|
125
|
+
);
|
|
126
|
+
},
|
|
127
|
+
[goToDeviceDetail]
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const renderDisplayItem = useCallback(
|
|
131
|
+
(device, unitId) => {
|
|
132
|
+
let displays = [];
|
|
133
|
+
if (!device.station_items?.length || device.quick_action) {
|
|
134
|
+
displays.push(
|
|
135
|
+
<ItemDevice
|
|
136
|
+
description={device.value}
|
|
137
|
+
title={device.name}
|
|
138
|
+
sensor={device}
|
|
139
|
+
unit={{ id: unitId }}
|
|
140
|
+
station={device.station}
|
|
141
|
+
goToDetail={goToDeviceDetail(unitId, device)}
|
|
142
|
+
key={`device-${device.id}`}
|
|
143
|
+
/>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
if (device.station_items?.length) {
|
|
147
|
+
displays.push(
|
|
148
|
+
...device.station_items.map((item) =>
|
|
149
|
+
renderStationItem(device, unitId, item)
|
|
150
|
+
)
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return displays;
|
|
154
|
+
},
|
|
155
|
+
[goToDeviceDetail, renderStationItem]
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const renderItem = useCallback(
|
|
159
|
+
({ item, index }) => {
|
|
160
|
+
return (
|
|
161
|
+
<View style={styles.wrapItem}>
|
|
162
|
+
<View style={styles.titleItem}>
|
|
163
|
+
<Text type="H3" semibold>
|
|
164
|
+
{item.name}
|
|
165
|
+
</Text>
|
|
166
|
+
<TouchableOpacity
|
|
167
|
+
onPress={goToUnitDetail(item)}
|
|
168
|
+
style={styles.arrowRightButton}
|
|
169
|
+
accessibilityLabel={`${AccessibilityLabel.UNIT_GO_TO_DETAIL}-${index}`}
|
|
170
|
+
>
|
|
171
|
+
<Image source={Images.arrowBack} style={styles.arrowRight} />
|
|
172
|
+
</TouchableOpacity>
|
|
173
|
+
</View>
|
|
174
|
+
<View style={styles.wrapperDevices}>
|
|
175
|
+
{item.devices.map((device) => {
|
|
176
|
+
return renderDisplayItem(device, item.id);
|
|
177
|
+
})}
|
|
178
|
+
</View>
|
|
179
|
+
</View>
|
|
180
|
+
);
|
|
181
|
+
},
|
|
182
|
+
[goToUnitDetail, renderDisplayItem]
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
if (isFocused || refreshing) {
|
|
187
|
+
fetchMyDashboardDevices();
|
|
188
|
+
}
|
|
189
|
+
}, [fetchMyDashboardDevices, isFocused, refreshing]);
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<>
|
|
193
|
+
{!!myDashboardDevices.length && (
|
|
194
|
+
<Section style={styles.wrapperDashboardDevice}>
|
|
195
|
+
<Text
|
|
196
|
+
style={styles.dashboardDevicesTitle}
|
|
197
|
+
type="H5"
|
|
198
|
+
color={Colors.Gray8}
|
|
199
|
+
>
|
|
200
|
+
{t('dashboard_devices')}
|
|
201
|
+
</Text>
|
|
202
|
+
<View style={styles.container}>
|
|
203
|
+
<FlatList
|
|
204
|
+
keyExtractor={keyExtractor}
|
|
205
|
+
data={myDashboardDevices}
|
|
206
|
+
extraData={myDashboardDevices}
|
|
207
|
+
renderItem={renderItem}
|
|
208
|
+
contentContainerStyle={styles.contentContainerStyle}
|
|
209
|
+
refreshing={false}
|
|
210
|
+
/>
|
|
211
|
+
</View>
|
|
212
|
+
</Section>
|
|
213
|
+
)}
|
|
214
|
+
</>
|
|
215
|
+
);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
export default memo(MyDashboardDevice);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors } from '../../../configs';
|
|
3
|
+
|
|
4
|
+
const styles = StyleSheet.create({
|
|
5
|
+
contentContainerStyle: {
|
|
6
|
+
paddingLeft: 16,
|
|
7
|
+
paddingRight: 16,
|
|
8
|
+
},
|
|
9
|
+
wrapperDashboardDevice: {
|
|
10
|
+
padding: 0,
|
|
11
|
+
paddingBottom: 10,
|
|
12
|
+
backgroundColor: Colors.White,
|
|
13
|
+
},
|
|
14
|
+
dashboardDevicesTitle: {
|
|
15
|
+
flexDirection: 'row',
|
|
16
|
+
justifyContent: 'space-between',
|
|
17
|
+
alignItems: 'center',
|
|
18
|
+
paddingHorizontal: 16,
|
|
19
|
+
paddingBottom: 8,
|
|
20
|
+
paddingTop: 16,
|
|
21
|
+
},
|
|
22
|
+
container: {
|
|
23
|
+
flex: 1,
|
|
24
|
+
backgroundColor: Colors.White,
|
|
25
|
+
},
|
|
26
|
+
wrapperDevices: {
|
|
27
|
+
flexWrap: 'wrap',
|
|
28
|
+
flexDirection: 'row',
|
|
29
|
+
justifyContent: 'space-between',
|
|
30
|
+
marginTop: 10,
|
|
31
|
+
borderBottomColor: Colors.Gray4,
|
|
32
|
+
borderBottomWidth: 1,
|
|
33
|
+
},
|
|
34
|
+
arrowRightButton: {
|
|
35
|
+
width: 20,
|
|
36
|
+
height: 20,
|
|
37
|
+
justifyContent: 'center',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
},
|
|
40
|
+
arrowRight: {
|
|
41
|
+
transform: [
|
|
42
|
+
{
|
|
43
|
+
rotate: '180deg',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
tintColor: Colors.Gray7,
|
|
47
|
+
width: 8,
|
|
48
|
+
height: 12,
|
|
49
|
+
},
|
|
50
|
+
wrapItem: {
|
|
51
|
+
marginBottom: 16,
|
|
52
|
+
},
|
|
53
|
+
titleItem: {
|
|
54
|
+
flexDirection: 'row',
|
|
55
|
+
justifyContent: 'space-between',
|
|
56
|
+
alignItems: 'center',
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export default styles;
|
|
@@ -18,7 +18,7 @@ import IconComponent from '../IconComponent';
|
|
|
18
18
|
import ItemDeviceWrapper from './ItemDeviceWrapper';
|
|
19
19
|
|
|
20
20
|
const ItemDevice = memo(
|
|
21
|
-
({ description, title, sensor, unit, station, wrapStyle }) => {
|
|
21
|
+
({ description, title, sensor, unit, station, goToDetail, wrapStyle }) => {
|
|
22
22
|
const t = useTranslations();
|
|
23
23
|
const navigation = useNavigation();
|
|
24
24
|
const { is_managed_by_backend, device_type, icon_kit, icon, quick_action } =
|
|
@@ -44,6 +44,14 @@ const ItemDevice = memo(
|
|
|
44
44
|
});
|
|
45
45
|
}, [navigation, sensor, station, title, unit]);
|
|
46
46
|
|
|
47
|
+
const onPress = useCallback(() => {
|
|
48
|
+
if (goToDetail) {
|
|
49
|
+
goToDetail();
|
|
50
|
+
} else {
|
|
51
|
+
goToSensorDisplay();
|
|
52
|
+
}
|
|
53
|
+
}, [goToDetail, goToSensorDisplay]);
|
|
54
|
+
|
|
47
55
|
const textConnected = useMemo(() => {
|
|
48
56
|
if (is_managed_by_backend) {
|
|
49
57
|
if (
|
|
@@ -80,10 +88,11 @@ const ItemDevice = memo(
|
|
|
80
88
|
device={sensor}
|
|
81
89
|
unit={unit}
|
|
82
90
|
station={station}
|
|
91
|
+
goToDetail={goToDetail}
|
|
83
92
|
wrapStyle={wrapStyle}
|
|
84
93
|
>
|
|
85
94
|
<View style={styles.boxIcon}>
|
|
86
|
-
<TouchableOpacity onPress={
|
|
95
|
+
<TouchableOpacity onPress={onPress}>
|
|
87
96
|
<IconComponent icon={icon_kit || icon} />
|
|
88
97
|
</TouchableOpacity>
|
|
89
98
|
{canRenderQuickAction && (
|
|
@@ -94,7 +103,7 @@ const ItemDevice = memo(
|
|
|
94
103
|
/>
|
|
95
104
|
)}
|
|
96
105
|
</View>
|
|
97
|
-
<TouchableOpacity onPress={
|
|
106
|
+
<TouchableOpacity onPress={onPress}>
|
|
98
107
|
<Text
|
|
99
108
|
numberOfLines={1}
|
|
100
109
|
semibold
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from '../../configs/Constants';
|
|
18
18
|
|
|
19
19
|
const ItemDeviceWrapper = memo(
|
|
20
|
-
({ device, unit, station, wrapStyle, children }) => {
|
|
20
|
+
({ device, unit, station, goToDetail, wrapStyle, children }) => {
|
|
21
21
|
const navigation = useNavigation();
|
|
22
22
|
|
|
23
23
|
const {
|
|
@@ -42,6 +42,14 @@ const ItemDeviceWrapper = memo(
|
|
|
42
42
|
});
|
|
43
43
|
}, [navigation, device, station, unit]);
|
|
44
44
|
|
|
45
|
+
const onPress = useCallback(() => {
|
|
46
|
+
if (goToDetail) {
|
|
47
|
+
goToDetail();
|
|
48
|
+
} else {
|
|
49
|
+
goToSensorDisplay();
|
|
50
|
+
}
|
|
51
|
+
}, [goToDetail, goToSensorDisplay]);
|
|
52
|
+
|
|
45
53
|
const borderColor = useMemo(() => {
|
|
46
54
|
if (!!device && device?.is_managed_by_backend) {
|
|
47
55
|
if (device?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
@@ -73,7 +81,7 @@ const ItemDeviceWrapper = memo(
|
|
|
73
81
|
|
|
74
82
|
return (
|
|
75
83
|
<TouchableWithoutFeedback
|
|
76
|
-
onPress={
|
|
84
|
+
onPress={onPress}
|
|
77
85
|
accessibilityLabel={`${AccessibilityLabel.SENSOR_NAME}-${device?.id}`}
|
|
78
86
|
>
|
|
79
87
|
<View
|
|
@@ -3,14 +3,19 @@ import { getTemplate } from './';
|
|
|
3
3
|
import ItemDeviceWrapper from '../../Device/ItemDeviceWrapper';
|
|
4
4
|
|
|
5
5
|
export const DeviceTemplate = memo(
|
|
6
|
-
({ device, stationItem, unit, station,
|
|
6
|
+
({ device, stationItem, unit, station, goToDetail }) => {
|
|
7
7
|
const Template = getTemplate(stationItem);
|
|
8
8
|
if (!Template) {
|
|
9
9
|
return null;
|
|
10
10
|
}
|
|
11
11
|
return (
|
|
12
|
-
<ItemDeviceWrapper
|
|
13
|
-
|
|
12
|
+
<ItemDeviceWrapper
|
|
13
|
+
device={device}
|
|
14
|
+
unit={unit}
|
|
15
|
+
station={station}
|
|
16
|
+
goToDetail={goToDetail}
|
|
17
|
+
>
|
|
18
|
+
<Template.Display device={device} stationItem={stationItem} />
|
|
14
19
|
</ItemDeviceWrapper>
|
|
15
20
|
);
|
|
16
21
|
}
|
|
@@ -23,7 +23,13 @@ export const useFetchConfigHistory = (
|
|
|
23
23
|
) => {
|
|
24
24
|
const fetchDataDisplayHistory = useCallback(
|
|
25
25
|
async (startDate, endDate, setProcessing = () => {}) => {
|
|
26
|
-
if (
|
|
26
|
+
if (
|
|
27
|
+
!configs ||
|
|
28
|
+
!Array.isArray(configs) ||
|
|
29
|
+
!configs.length ||
|
|
30
|
+
!startDate ||
|
|
31
|
+
!endDate
|
|
32
|
+
) {
|
|
27
33
|
return;
|
|
28
34
|
}
|
|
29
35
|
|
package/src/configs/API.js
CHANGED
|
@@ -27,6 +27,9 @@ const API = {
|
|
|
27
27
|
END_DEVICES_STATUS: (id) =>
|
|
28
28
|
`/property_manager/units/${id}/end_devices_status/`,
|
|
29
29
|
CHANGE_OWNER: (id) => `/property_manager/units/${id}/change_owner/`,
|
|
30
|
+
MY_DASHBOARD_DEVICES: () => '/property_manager/units/my_dashboard_devices/',
|
|
31
|
+
DASHBOARD_DEVICES: (id) =>
|
|
32
|
+
`/property_manager/units/${id}/dashboard_devices/`,
|
|
30
33
|
FAVOURITE_DEVICES: (id) =>
|
|
31
34
|
`/property_manager/units/${id}/favourite_devices/`,
|
|
32
35
|
DEVICES_NOT_FAVORITES: (id) =>
|
|
@@ -75,6 +78,10 @@ const API = {
|
|
|
75
78
|
DISPLAY_ACTIONS: (id) => `/property_manager/devices/${id}/display_actions/`,
|
|
76
79
|
CHANGE_SUB_UNIT: (unit_id, station_id, id) =>
|
|
77
80
|
`/property_manager/${unit_id}/sub_units/${station_id}/devices/${id}/change_sub_unit/`,
|
|
81
|
+
ADD_TO_DASHBOARD: (id) =>
|
|
82
|
+
`/property_manager/devices/${id}/add_to_dashboard/`,
|
|
83
|
+
REMOVE_FROM_DASHBOARD: (id) =>
|
|
84
|
+
`/property_manager/devices/${id}/remove_from_dashboard/`,
|
|
78
85
|
ADD_TO_FAVOURITES: (id) =>
|
|
79
86
|
`/property_manager/devices/${id}/add_to_favourites/`,
|
|
80
87
|
REMOVE_FROM_FAVOURITES: (id) =>
|
|
@@ -40,6 +40,7 @@ export default {
|
|
|
40
40
|
MY_UNIT_GO_TO_DETAIL: 'MY_UNIT_GO_TO_DETAIL',
|
|
41
41
|
MY_UNIT_NO_UNIT: 'MY_UNIT_NO_UNIT',
|
|
42
42
|
ITEM_UNIT: 'ITEM_UNIT',
|
|
43
|
+
UNIT_GO_TO_DETAIL: 'UNIT_GO_TO_DETAIL',
|
|
43
44
|
|
|
44
45
|
// ConfirmUnitDeletion
|
|
45
46
|
CONFIRM_UNIT_DELETION_BUTTON: 'CONFIRM_UNIT_DELETION_BUTTON',
|
|
@@ -270,6 +271,7 @@ export default {
|
|
|
270
271
|
PARKING_SPOT_TEXT_RESULT: 'PARKING_SPOT_TEXT_RESULT',
|
|
271
272
|
|
|
272
273
|
// Header Device
|
|
274
|
+
HEADER_DEVICE_BUTTON_PIN: 'HEADER_DEVICE_BUTTON_PIN',
|
|
273
275
|
HEADER_DEVICE_BUTTON_STAR: 'HEADER_DEVICE_BUTTON_STAR',
|
|
274
276
|
HEADER_SCRIPT_DETAIL_BUTTON_STAR: 'HEADER_SCRIPT_DETAIL_BUTTON_STAR',
|
|
275
277
|
HEADER_DEVICE_BUTTON_MORE: 'HEADER_DEVICE_BUTTON_MORE',
|
|
@@ -12,6 +12,9 @@ export const Action = {
|
|
|
12
12
|
SET_NETWORK_CONNECTED: 'SET_NETWORK_CONNECTED',
|
|
13
13
|
CAMERA_STATUS_CHANGE: 'CAMERA_STATUS_CHANGE',
|
|
14
14
|
CLOSE_ALL_CAMERA: 'CLOSE_ALL_CAMERA',
|
|
15
|
+
SET_DASHBOARD_DEVICES: 'SET_DASHBOARD_DEVICES',
|
|
16
|
+
ADD_DEVICES_TO_DASHBOARD: 'ADD_DEVICE_TO_DASHBOARD',
|
|
17
|
+
REMOVE_DEVICES_FROM_DASHBOARD: 'REMOVE_DEVICE_FROM_DASHBOARD',
|
|
15
18
|
SET_FAVORITE_DEVICES: 'SET_FAVORITE_DEVICES',
|
|
16
19
|
ADD_DEVICES_TO_FAVORITES: 'ADD_DEVICE_TO_FAVORITES',
|
|
17
20
|
REMOVE_DEVICES_FROM_FAVORITES: 'REMOVE_DEVICE_FROM_FAVORITES',
|
|
@@ -78,6 +81,7 @@ export type ListAction = {
|
|
|
78
81
|
}[];
|
|
79
82
|
|
|
80
83
|
export type UnitType = {
|
|
84
|
+
dashboardDeviceIds: [];
|
|
81
85
|
favoriteDeviceIds: [];
|
|
82
86
|
};
|
|
83
87
|
|
package/src/context/mockStore.ts
CHANGED
|
@@ -27,6 +27,7 @@ export const mockDataStore: ContextData = {
|
|
|
27
27
|
listAction: [],
|
|
28
28
|
myUnits: [],
|
|
29
29
|
unit: {
|
|
30
|
+
dashboardDeviceIds: [],
|
|
30
31
|
favoriteDeviceIds: [],
|
|
31
32
|
},
|
|
32
33
|
automate: {
|
|
@@ -103,6 +104,10 @@ export const mockSCStore = (data: ContextData): ContextData => {
|
|
|
103
104
|
},
|
|
104
105
|
myUnits: [...mockDataStore.myUnits, ...(data?.myUnits || [])],
|
|
105
106
|
unit: {
|
|
107
|
+
dashboardDeviceIds: [
|
|
108
|
+
...mockDataStore.unit.dashboardDeviceIds,
|
|
109
|
+
...(data?.unit?.dashboardDeviceIds || []),
|
|
110
|
+
],
|
|
106
111
|
favoriteDeviceIds: [
|
|
107
112
|
...mockDataStore.unit.favoriteDeviceIds,
|
|
108
113
|
...(data?.unit?.favoriteDeviceIds || []),
|