@eohjsc/react-native-smart-city 0.7.24 → 0.7.26
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/Images/Common/search-menu.svg +7 -0
- package/src/commons/ActionGroup/OnOffTemplate/OnOffButtonTemplateStyle.js +2 -1
- package/src/commons/ActionGroup/OneBigButtonTemplateStyle.js +1 -2
- package/src/commons/ActionGroup/SliderRangeTemplate.js +1 -3
- package/src/commons/ActionGroup/TerminalBoxTemplate.js +1 -4
- package/src/commons/ActionGroup/TextBoxTemplate.js +1 -5
- package/src/commons/ActionGroup/ThreeButtonTemplate/components/ThreeButtonDefaultStyles.js +1 -1
- package/src/commons/ActionGroup/__test__/index.test.js +51 -0
- package/src/commons/ActionGroup/index.js +4 -0
- 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/Dashboard/MyPinnedSharedUnit/index.js +0 -10
- package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +114 -48
- package/src/commons/Dashboard/MyUnit/index.js +74 -27
- package/src/commons/Dashboard/MyUnit/styles.js +16 -1
- package/src/commons/DateTimeRangeChange/index.js +1 -1
- package/src/commons/Device/ItemDevice.js +12 -3
- package/src/commons/Device/ItemDeviceWrapper.js +10 -2
- package/src/commons/SelectUnit/index.js +19 -5
- package/src/commons/SelectUnit/styles.js +0 -1
- package/src/commons/SubUnit/DeviceTemplate/DeviceTemplate.js +8 -3
- package/src/commons/Widgets/IFrame/IFrameStyles.js +1 -0
- package/src/commons/Widgets/IFrameWithConfig/IFrameWithConfigStyles.js +1 -0
- package/src/configs/API.js +11 -0
- package/src/configs/AccessibilityLabel.js +2 -0
- package/src/configs/Constants.js +3 -0
- package/src/context/actionType.ts +4 -0
- package/src/context/mockStore.ts +5 -0
- package/src/context/reducer.ts +30 -5
- package/src/iot/mqtt.js +163 -47
- package/src/navigations/UnitStack.js +22 -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/__test__/sensorDisplayItem.test.js +27 -0
- package/src/screens/Device/components/DonutChart.js +5 -14
- package/src/screens/Device/components/SensorDisplayItem.js +92 -61
- package/src/screens/Device/components/VisualChart.js +0 -12
- package/src/screens/Device/detail.js +50 -14
- package/src/screens/Device/hooks/useDashboardDevice.js +34 -0
- package/src/screens/Device/styles.js +16 -0
- package/src/screens/SubUnit/AddSubUnit.js +18 -8
- package/src/screens/SubUnit/__test__/AddSubUnit.test.js +5 -3
- package/src/screens/Unit/GoToDetailUnit.js +30 -0
- package/src/screens/Unit/__test__/GoToDetailUnit.test.js +103 -0
- package/src/utils/FactoryGateway.js +105 -0
- package/src/utils/I18n/translations/en.js +4 -0
- package/src/utils/I18n/translations/vi.js +4 -0
- package/src/utils/Route/index.js +1 -0
- package/src/utils/Storage.js +18 -4
- package/src/utils/Utils.js +2 -1
- package/src/utils/Functions/preloadImages.js +0 -38
|
@@ -18,6 +18,7 @@ import MockAdapter from 'axios-mock-adapter';
|
|
|
18
18
|
import api from '../../../utils/Apis/axios';
|
|
19
19
|
import CurrentRainSensor from '../../../commons/Device/RainningSensor/CurrentRainSensor';
|
|
20
20
|
import LabelValue from '../../../commons/Device/LabelValue';
|
|
21
|
+
import Text from '../../../commons/Text';
|
|
21
22
|
|
|
22
23
|
jest.mock('../../../iot/states', () => ({
|
|
23
24
|
useConfigGlobalState: () => [{}, null],
|
|
@@ -51,6 +52,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
51
52
|
},
|
|
52
53
|
],
|
|
53
54
|
},
|
|
55
|
+
label: 'Chart',
|
|
54
56
|
is_configuration_ready: true,
|
|
55
57
|
};
|
|
56
58
|
|
|
@@ -65,6 +67,8 @@ describe('Test SensorDisplayItem', () => {
|
|
|
65
67
|
const instance = tree.root;
|
|
66
68
|
const visualChart = instance.findAllByType(VisualChart);
|
|
67
69
|
expect(visualChart).toHaveLength(1);
|
|
70
|
+
const labels = instance.findAllByType(Text);
|
|
71
|
+
expect(labels[0].props.children).toEqual('Chart');
|
|
68
72
|
});
|
|
69
73
|
|
|
70
74
|
it('render ActionGroup', async () => {
|
|
@@ -82,6 +86,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
82
86
|
},
|
|
83
87
|
],
|
|
84
88
|
},
|
|
89
|
+
label: 'LED',
|
|
85
90
|
is_configuration_ready: true,
|
|
86
91
|
};
|
|
87
92
|
|
|
@@ -96,6 +101,8 @@ describe('Test SensorDisplayItem', () => {
|
|
|
96
101
|
const instance = tree.root;
|
|
97
102
|
const actionGroup = instance.findAllByType(ActionGroup);
|
|
98
103
|
expect(actionGroup).toHaveLength(1);
|
|
104
|
+
const labels = instance.findAllByType(Text);
|
|
105
|
+
expect(labels[0].props.children).toEqual('LED');
|
|
99
106
|
});
|
|
100
107
|
|
|
101
108
|
it('render camera', async () => {
|
|
@@ -113,6 +120,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
113
120
|
},
|
|
114
121
|
],
|
|
115
122
|
},
|
|
123
|
+
label: 'Camera',
|
|
116
124
|
is_configuration_ready: true,
|
|
117
125
|
};
|
|
118
126
|
|
|
@@ -127,6 +135,8 @@ describe('Test SensorDisplayItem', () => {
|
|
|
127
135
|
const instance = tree.root;
|
|
128
136
|
const mediaPlayerDetail = instance.findAllByType(MediaPlayerDetail);
|
|
129
137
|
expect(mediaPlayerDetail).toHaveLength(1);
|
|
138
|
+
const labels = instance.findAllByType(Text);
|
|
139
|
+
expect(labels[0].props.children).toEqual('Camera');
|
|
130
140
|
});
|
|
131
141
|
|
|
132
142
|
it('render flat_list', async () => {
|
|
@@ -213,6 +223,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
213
223
|
configuration: {
|
|
214
224
|
template: 'gauge',
|
|
215
225
|
},
|
|
226
|
+
label: 'Gauge',
|
|
216
227
|
is_configuration_ready: true,
|
|
217
228
|
};
|
|
218
229
|
|
|
@@ -227,6 +238,8 @@ describe('Test SensorDisplayItem', () => {
|
|
|
227
238
|
const instance = tree.root;
|
|
228
239
|
const flatListItems = instance.findAllByType(Anemometer);
|
|
229
240
|
expect(flatListItems).toHaveLength(1);
|
|
241
|
+
const labels = instance.findAllByType(Text);
|
|
242
|
+
expect(labels[0].props.children).toEqual('Gauge');
|
|
230
243
|
});
|
|
231
244
|
|
|
232
245
|
it('test render progress_bar', async () => {
|
|
@@ -237,6 +250,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
237
250
|
configuration: {
|
|
238
251
|
template: 'progress_bar',
|
|
239
252
|
},
|
|
253
|
+
label: 'Brightness',
|
|
240
254
|
is_configuration_ready: true,
|
|
241
255
|
};
|
|
242
256
|
|
|
@@ -251,6 +265,8 @@ describe('Test SensorDisplayItem', () => {
|
|
|
251
265
|
const instance = tree.root;
|
|
252
266
|
const flatListItems = instance.findAllByType(ProgressBar);
|
|
253
267
|
expect(flatListItems).toHaveLength(1);
|
|
268
|
+
const labels = instance.findAllByType(Text);
|
|
269
|
+
expect(labels[0].props.children).toEqual('Brightness');
|
|
254
270
|
});
|
|
255
271
|
|
|
256
272
|
it('test render Compass', async () => {
|
|
@@ -261,6 +277,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
261
277
|
configuration: {
|
|
262
278
|
template: 'compass',
|
|
263
279
|
},
|
|
280
|
+
label: 'Compass',
|
|
264
281
|
is_configuration_ready: true,
|
|
265
282
|
};
|
|
266
283
|
|
|
@@ -275,6 +292,8 @@ describe('Test SensorDisplayItem', () => {
|
|
|
275
292
|
const instance = tree.root;
|
|
276
293
|
const flatListItems = instance.findAllByType(Compass);
|
|
277
294
|
expect(flatListItems).toHaveLength(1);
|
|
295
|
+
const labels = instance.findAllByType(Text);
|
|
296
|
+
expect(labels[0].props.children).toEqual('Compass');
|
|
278
297
|
});
|
|
279
298
|
|
|
280
299
|
it('test render alert_status', async () => {
|
|
@@ -314,6 +333,8 @@ describe('Test SensorDisplayItem', () => {
|
|
|
314
333
|
|
|
315
334
|
const currentRainSensor = instance.findByType(CurrentRainSensor);
|
|
316
335
|
expect(currentRainSensor.props).toEqual(expectProps);
|
|
336
|
+
const labels = instance.findAllByType(Text);
|
|
337
|
+
expect(labels[0].props.children).toEqual('Circle');
|
|
317
338
|
};
|
|
318
339
|
|
|
319
340
|
it('render circle_mini', async () => {
|
|
@@ -332,6 +353,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
332
353
|
color: 'blue',
|
|
333
354
|
},
|
|
334
355
|
},
|
|
356
|
+
label: 'Circle',
|
|
335
357
|
is_configuration_ready: true,
|
|
336
358
|
};
|
|
337
359
|
|
|
@@ -371,6 +393,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
371
393
|
color: 'blue',
|
|
372
394
|
},
|
|
373
395
|
},
|
|
396
|
+
label: 'Circle',
|
|
374
397
|
is_configuration_ready: true,
|
|
375
398
|
};
|
|
376
399
|
|
|
@@ -400,6 +423,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
400
423
|
configuration: {
|
|
401
424
|
config: null,
|
|
402
425
|
},
|
|
426
|
+
label: 'Circle',
|
|
403
427
|
is_configuration_ready: true,
|
|
404
428
|
};
|
|
405
429
|
|
|
@@ -417,6 +441,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
417
441
|
order: 0,
|
|
418
442
|
template: 'LabelValue',
|
|
419
443
|
configuration: {},
|
|
444
|
+
label: 'Label',
|
|
420
445
|
is_configuration_ready: true,
|
|
421
446
|
};
|
|
422
447
|
|
|
@@ -431,5 +456,7 @@ describe('Test SensorDisplayItem', () => {
|
|
|
431
456
|
const instance = tree.root;
|
|
432
457
|
const displayItems = instance.findAllByType(LabelValue);
|
|
433
458
|
expect(displayItems).toHaveLength(1);
|
|
459
|
+
const labels = instance.findAllByType(Text);
|
|
460
|
+
expect(labels[0].props.children).toEqual('Label');
|
|
434
461
|
});
|
|
435
462
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
3
|
import { Colors } from '../../../configs';
|
|
4
|
-
import Text from '../../../commons/Text';
|
|
5
4
|
import Highcharts from '../../../commons/Highcharts';
|
|
6
5
|
import { useConfigGlobalState } from '../../../iot/states';
|
|
7
6
|
|
|
@@ -63,7 +62,7 @@ const chartOptions = {
|
|
|
63
62
|
};
|
|
64
63
|
|
|
65
64
|
const DonutCharts = ({ item, isWidgetOrder }) => {
|
|
66
|
-
const { configuration
|
|
65
|
+
const { configuration } = item;
|
|
67
66
|
const { configs = [] } = configuration;
|
|
68
67
|
const [configValues] = useConfigGlobalState('configValues');
|
|
69
68
|
const [highchartsWebviewRef, setHighchartsWebviewRef] = useState(null);
|
|
@@ -92,13 +91,7 @@ const DonutCharts = ({ item, isWidgetOrder }) => {
|
|
|
92
91
|
}, [configs, getConfigValue, highchartsWebviewRef]);
|
|
93
92
|
|
|
94
93
|
return (
|
|
95
|
-
<View>
|
|
96
|
-
<View style={styles.titleHistory}>
|
|
97
|
-
<Text type="H3" semibold color={Colors.Gray9}>
|
|
98
|
-
{label}
|
|
99
|
-
</Text>
|
|
100
|
-
</View>
|
|
101
|
-
|
|
94
|
+
<View style={styles.wrapDonut}>
|
|
102
95
|
<Highcharts
|
|
103
96
|
setRef={setHighchartsWebviewRef}
|
|
104
97
|
options={chartOptions}
|
|
@@ -113,15 +106,13 @@ const DonutCharts = ({ item, isWidgetOrder }) => {
|
|
|
113
106
|
};
|
|
114
107
|
|
|
115
108
|
const styles = StyleSheet.create({
|
|
109
|
+
wrapDonut: {
|
|
110
|
+
marginBottom: 16,
|
|
111
|
+
},
|
|
116
112
|
chartStyle: {
|
|
117
113
|
backgroundColor: Colors.White,
|
|
118
114
|
flex: 1,
|
|
119
115
|
},
|
|
120
|
-
titleHistory: {
|
|
121
|
-
flexDirection: 'row',
|
|
122
|
-
justifyContent: 'space-between',
|
|
123
|
-
paddingHorizontal: 16,
|
|
124
|
-
},
|
|
125
116
|
webviewStyle: {
|
|
126
117
|
flex: 1,
|
|
127
118
|
minHeight: 200,
|
|
@@ -15,7 +15,7 @@ import Compass from '../../../commons/Device/WindDirection/Compass';
|
|
|
15
15
|
import Anemometer from '../../../commons/Device/WindSpeed/Anemometer';
|
|
16
16
|
import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
|
|
17
17
|
import IFrame from '../../../commons/Widgets/IFrame/IFrame';
|
|
18
|
-
import
|
|
18
|
+
import Text from '../../../commons/Text';
|
|
19
19
|
import { Device } from '../../../configs';
|
|
20
20
|
import { AccessibilityLabel, WIDGET_TYPE } from '../../../configs/Constants';
|
|
21
21
|
import { useSCContextSelector } from '../../../context';
|
|
@@ -44,7 +44,7 @@ export const SensorDisplayItem = ({
|
|
|
44
44
|
isWidgetOrder,
|
|
45
45
|
}) => {
|
|
46
46
|
const userId = useSCContextSelector((state) => state.auth.account.user.id);
|
|
47
|
-
const { configuration = {}, id: idTemplate } = item;
|
|
47
|
+
const { configuration = {}, id: idTemplate, label } = item;
|
|
48
48
|
const { type, template, uri, id, name, title, value_evaluation } =
|
|
49
49
|
configuration;
|
|
50
50
|
|
|
@@ -137,6 +137,7 @@ export const SensorDisplayItem = ({
|
|
|
137
137
|
<View
|
|
138
138
|
style={[styles.mediaContainer, isWidgetOrder && styles.cameraOrder]}
|
|
139
139
|
>
|
|
140
|
+
<Text style={styles.widgetLabelCamera}>{label}</Text>
|
|
140
141
|
<MediaPlayerDetail
|
|
141
142
|
uri={uri}
|
|
142
143
|
thumbnail={{
|
|
@@ -169,92 +170,117 @@ export const SensorDisplayItem = ({
|
|
|
169
170
|
case 'switch_button_action_template':
|
|
170
171
|
case 'TextBoxTemplate':
|
|
171
172
|
case 'TerminalBoxTemplate':
|
|
173
|
+
case WIDGET_TYPE.iframeWithConfig:
|
|
172
174
|
return (
|
|
173
|
-
<
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
<View>
|
|
176
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
177
|
+
<ActionGroup
|
|
178
|
+
accessibilityLabel={AccessibilityLabel.DEVICE_DETAIL_ACTION_GROUP}
|
|
179
|
+
doAction={doAction}
|
|
180
|
+
sensor={sensor}
|
|
181
|
+
id={idTemplate}
|
|
182
|
+
item={item}
|
|
183
|
+
isWidgetOrder={isWidgetOrder}
|
|
184
|
+
/>
|
|
185
|
+
</View>
|
|
181
186
|
);
|
|
182
187
|
case WIDGET_TYPE.iframe:
|
|
183
188
|
return (
|
|
184
|
-
<
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<IFrameWithConfig
|
|
195
|
-
doAction={doAction}
|
|
196
|
-
sensor={sensor}
|
|
197
|
-
id={idTemplate}
|
|
198
|
-
item={item}
|
|
199
|
-
isWidgetOrder={isWidgetOrder}
|
|
200
|
-
/>
|
|
189
|
+
<View>
|
|
190
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
191
|
+
<IFrame
|
|
192
|
+
doAction={doAction}
|
|
193
|
+
sensor={sensor}
|
|
194
|
+
id={idTemplate}
|
|
195
|
+
item={item}
|
|
196
|
+
isWidgetOrder={isWidgetOrder}
|
|
197
|
+
/>
|
|
198
|
+
</View>
|
|
201
199
|
);
|
|
202
200
|
case 'history':
|
|
203
201
|
return (
|
|
204
|
-
<
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
<View>
|
|
203
|
+
<Text style={styles.widgetLabelHistory}>{label}</Text>
|
|
204
|
+
<VisualChart
|
|
205
|
+
item={item}
|
|
206
|
+
sensor={sensor}
|
|
207
|
+
isWidgetOrder={isWidgetOrder}
|
|
208
|
+
/>
|
|
209
|
+
</View>
|
|
209
210
|
);
|
|
210
211
|
case 'circle_mini':
|
|
211
212
|
return (
|
|
212
|
-
<
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
213
|
+
<View>
|
|
214
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
215
|
+
<CurrentRainSensor
|
|
216
|
+
size={120}
|
|
217
|
+
textType="H4"
|
|
218
|
+
iconSize={25}
|
|
219
|
+
data={getDataCircleMini(item)}
|
|
220
|
+
isWidgetOrder={isWidgetOrder}
|
|
221
|
+
/>
|
|
222
|
+
</View>
|
|
219
223
|
);
|
|
220
224
|
// use the same method to get data for circle_mini
|
|
221
225
|
case 'LabelValue':
|
|
222
226
|
return (
|
|
223
|
-
<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
<View>
|
|
228
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
229
|
+
<LabelValue
|
|
230
|
+
data={getDataCircleMini(item)}
|
|
231
|
+
item={item}
|
|
232
|
+
isWidgetOrder={isWidgetOrder}
|
|
233
|
+
/>
|
|
234
|
+
</View>
|
|
228
235
|
);
|
|
229
236
|
case 'value':
|
|
230
237
|
switch (type || template) {
|
|
231
238
|
case 'circle':
|
|
232
239
|
return (
|
|
233
|
-
<
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
240
|
+
<View>
|
|
241
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
242
|
+
<CurrentRainSensor
|
|
243
|
+
data={getData(item)}
|
|
244
|
+
isWidgetOrder={isWidgetOrder}
|
|
245
|
+
/>
|
|
246
|
+
</View>
|
|
237
247
|
);
|
|
238
248
|
case 'simple_list':
|
|
239
249
|
return (
|
|
240
|
-
<
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
250
|
+
<View>
|
|
251
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
252
|
+
<PMSensorIndicator
|
|
253
|
+
data={getData(item)}
|
|
254
|
+
style={styles.simpleList}
|
|
255
|
+
isWidgetOrder={isWidgetOrder}
|
|
256
|
+
/>
|
|
257
|
+
</View>
|
|
245
258
|
);
|
|
246
259
|
case 'gauge':
|
|
247
|
-
return
|
|
260
|
+
return (
|
|
261
|
+
<View>
|
|
262
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
263
|
+
<Anemometer data={getData(item)} item={item} />
|
|
264
|
+
</View>
|
|
265
|
+
);
|
|
248
266
|
case 'progress_bar':
|
|
249
267
|
return (
|
|
250
|
-
<
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
268
|
+
<View>
|
|
269
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
270
|
+
<ProgressBar
|
|
271
|
+
data={getData(item)}
|
|
272
|
+
item={item}
|
|
273
|
+
isWidgetOrder={isWidgetOrder}
|
|
274
|
+
/>
|
|
275
|
+
</View>
|
|
255
276
|
);
|
|
256
277
|
case 'compass':
|
|
257
|
-
return
|
|
278
|
+
return (
|
|
279
|
+
<View>
|
|
280
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
281
|
+
<Compass data={getData(item)} isWidgetOrder={isWidgetOrder} />
|
|
282
|
+
</View>
|
|
283
|
+
);
|
|
258
284
|
case 'alert_status':
|
|
259
285
|
return (
|
|
260
286
|
<DeviceAlertStatus
|
|
@@ -274,7 +300,12 @@ export const SensorDisplayItem = ({
|
|
|
274
300
|
/>
|
|
275
301
|
);
|
|
276
302
|
case 'donut_chart_race':
|
|
277
|
-
return
|
|
303
|
+
return (
|
|
304
|
+
<View>
|
|
305
|
+
<Text style={styles.widgetLabel}>{label}</Text>
|
|
306
|
+
<DonutCharts item={item} isWidgetOrder={isWidgetOrder} />
|
|
307
|
+
</View>
|
|
308
|
+
);
|
|
278
309
|
default:
|
|
279
310
|
return <ListQualityIndicator data={getData(item)} />;
|
|
280
311
|
}
|
|
@@ -13,7 +13,6 @@ import { useFetchConfigHistory } from '../../../commons/UnitSummary/ConfigHistor
|
|
|
13
13
|
import { StyleSheet, View } from 'react-native';
|
|
14
14
|
import { Colors } from '../../../configs';
|
|
15
15
|
import ChartAggregationOption from '../../../commons/ChartAggregationOption';
|
|
16
|
-
import Text from '../../../commons/Text';
|
|
17
16
|
import { CHART_GROUP_TYPE, CHART_TIME } from '../../../configs/Constants';
|
|
18
17
|
import { getDateRangeOfWeek } from '../../../utils/Utils';
|
|
19
18
|
import Highcharts from '../../../commons/Highcharts';
|
|
@@ -113,16 +112,10 @@ const styles = StyleSheet.create({
|
|
|
113
112
|
backgroundColor: Colors.White,
|
|
114
113
|
flex: 1,
|
|
115
114
|
},
|
|
116
|
-
titleHistory: {
|
|
117
|
-
flexDirection: 'row',
|
|
118
|
-
justifyContent: 'space-between',
|
|
119
|
-
paddingHorizontal: 16,
|
|
120
|
-
},
|
|
121
115
|
aggregationView: {
|
|
122
116
|
flexDirection: 'row',
|
|
123
117
|
justifyContent: 'space-between',
|
|
124
118
|
paddingHorizontal: 16,
|
|
125
|
-
paddingTop: 8,
|
|
126
119
|
alignSelf: 'flex-end',
|
|
127
120
|
},
|
|
128
121
|
webviewStyle: {
|
|
@@ -312,11 +305,6 @@ const VisualChart = ({ item, isDemo = false, isWidgetOrder }) => {
|
|
|
312
305
|
|
|
313
306
|
return (
|
|
314
307
|
<View style={styles.container}>
|
|
315
|
-
<View style={styles.titleHistory}>
|
|
316
|
-
<Text type="H3" semibold color={Colors.Gray9}>
|
|
317
|
-
{item.label}
|
|
318
|
-
</Text>
|
|
319
|
-
</View>
|
|
320
308
|
<View style={styles.aggregationView}>
|
|
321
309
|
{canChooseGroup && (
|
|
322
310
|
<ChartAggregationOption
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
useAlertResolveEmergency,
|
|
22
22
|
useEmergencyButton,
|
|
23
23
|
} from './hooks/useEmergencyButton';
|
|
24
|
+
import { useDashboardDevice } from './hooks/useDashboardDevice';
|
|
24
25
|
import { useFavoriteDevice } from './hooks/useFavoriteDevice';
|
|
25
26
|
import { usePopover } from '../../hooks/Common';
|
|
26
27
|
import { setConfigGlobalState, getConfigGlobalState } from '../../iot/states';
|
|
@@ -172,6 +173,9 @@ const DeviceDetail = ({ route }) => {
|
|
|
172
173
|
[display.items]
|
|
173
174
|
);
|
|
174
175
|
|
|
176
|
+
const { isPinnedDashboard, addToDashboard, removeFromDashboard } =
|
|
177
|
+
useDashboardDevice(device);
|
|
178
|
+
|
|
175
179
|
const { isFavorite, addToFavorites, removeFromFavorites } =
|
|
176
180
|
useFavoriteDevice(device);
|
|
177
181
|
|
|
@@ -333,6 +337,30 @@ const DeviceDetail = ({ route }) => {
|
|
|
333
337
|
|
|
334
338
|
const listMenuItem = useMemo(() => {
|
|
335
339
|
const menuItems = [];
|
|
340
|
+
|
|
341
|
+
if (!isPinnedDashboard) {
|
|
342
|
+
menuItems.push({
|
|
343
|
+
doAction: addToDashboard,
|
|
344
|
+
text: t('add_to_dashboard'),
|
|
345
|
+
});
|
|
346
|
+
} else {
|
|
347
|
+
menuItems.push({
|
|
348
|
+
doAction: removeFromDashboard,
|
|
349
|
+
text: t('remove_from_dashboard'),
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
if (!isFavorite) {
|
|
353
|
+
menuItems.push({
|
|
354
|
+
doAction: addToFavorites,
|
|
355
|
+
text: t('add_to_favorites'),
|
|
356
|
+
});
|
|
357
|
+
} else {
|
|
358
|
+
menuItems.push({
|
|
359
|
+
doAction: removeFromFavorites,
|
|
360
|
+
text: t('remove_from_favorites'),
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
336
364
|
if (display.items.some((i) => getActionComponent(i.template))) {
|
|
337
365
|
menuItems.push({
|
|
338
366
|
route: Routes.ActivityLog,
|
|
@@ -443,17 +471,6 @@ const DeviceDetail = ({ route }) => {
|
|
|
443
471
|
text: t('passcode_list'),
|
|
444
472
|
});
|
|
445
473
|
}
|
|
446
|
-
if (!isFavorite) {
|
|
447
|
-
menuItems.unshift({
|
|
448
|
-
doAction: addToFavorites,
|
|
449
|
-
text: t('add_to_favorites'),
|
|
450
|
-
});
|
|
451
|
-
} else {
|
|
452
|
-
menuItems.unshift({
|
|
453
|
-
doAction: removeFromFavorites,
|
|
454
|
-
text: t('remove_from_favorites'),
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
474
|
return [...menuItems];
|
|
458
475
|
}, [
|
|
459
476
|
display,
|
|
@@ -462,6 +479,7 @@ const DeviceDetail = ({ route }) => {
|
|
|
462
479
|
sideMenu,
|
|
463
480
|
t,
|
|
464
481
|
isShowSetUpSmartLock,
|
|
482
|
+
isPinnedDashboard,
|
|
465
483
|
isFavorite,
|
|
466
484
|
device,
|
|
467
485
|
unit,
|
|
@@ -471,7 +489,9 @@ const DeviceDetail = ({ route }) => {
|
|
|
471
489
|
fetchDataDeviceDetail,
|
|
472
490
|
isMyUnitDeviceScreen,
|
|
473
491
|
emergencyDeviceId,
|
|
492
|
+
addToDashboard,
|
|
474
493
|
addToFavorites,
|
|
494
|
+
removeFromDashboard,
|
|
475
495
|
removeFromFavorites,
|
|
476
496
|
]);
|
|
477
497
|
|
|
@@ -729,6 +749,19 @@ const DeviceDetail = ({ route }) => {
|
|
|
729
749
|
const HeaderRight = useMemo(
|
|
730
750
|
() => (
|
|
731
751
|
<View style={styles.headerRight}>
|
|
752
|
+
<TouchableOpacity
|
|
753
|
+
onPress={isPinnedDashboard ? removeFromDashboard : addToDashboard}
|
|
754
|
+
accessibilityLabel={AccessibilityLabel.HEADER_DEVICE_BUTTON_PIN}
|
|
755
|
+
>
|
|
756
|
+
<View style={styles.buttonStar}>
|
|
757
|
+
{isPinnedDashboard ? (
|
|
758
|
+
<IconFill name="pushpin" size={25} color={Colors.Yellow6} />
|
|
759
|
+
) : (
|
|
760
|
+
<IconOutline name="pushpin" size={25} />
|
|
761
|
+
)}
|
|
762
|
+
</View>
|
|
763
|
+
</TouchableOpacity>
|
|
764
|
+
|
|
732
765
|
<TouchableOpacity
|
|
733
766
|
onPress={isFavorite ? removeFromFavorites : addToFavorites}
|
|
734
767
|
accessibilityLabel={AccessibilityLabel.HEADER_DEVICE_BUTTON_STAR}
|
|
@@ -761,12 +794,15 @@ const DeviceDetail = ({ route }) => {
|
|
|
761
794
|
</View>
|
|
762
795
|
),
|
|
763
796
|
[
|
|
797
|
+
isPinnedDashboard,
|
|
764
798
|
isFavorite,
|
|
765
|
-
removeFromFavorites,
|
|
766
|
-
addToFavorites,
|
|
767
799
|
isShowSetupEmergencyContact,
|
|
768
|
-
|
|
800
|
+
addToDashboard,
|
|
801
|
+
addToFavorites,
|
|
802
|
+
removeFromDashboard,
|
|
803
|
+
removeFromFavorites,
|
|
769
804
|
handleShowMenuAction,
|
|
805
|
+
onPressSetting,
|
|
770
806
|
]
|
|
771
807
|
);
|
|
772
808
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useContext, useCallback } from 'react';
|
|
2
|
+
import { API } from '../../../configs';
|
|
3
|
+
import { SCContext, useSCContextSelector } from '../../../context';
|
|
4
|
+
import { Action } from '../../../context/actionType';
|
|
5
|
+
import { axiosPost } from '../../../utils/Apis/axios';
|
|
6
|
+
|
|
7
|
+
export const useDashboardDevice = (device) => {
|
|
8
|
+
const { setAction } = useContext(SCContext);
|
|
9
|
+
const dashboardDeviceIds = useSCContextSelector(
|
|
10
|
+
(state) => state.unit.dashboardDeviceIds
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const isPinnedDashboard = dashboardDeviceIds.includes(device.id);
|
|
14
|
+
|
|
15
|
+
const addToDashboard = useCallback(async () => {
|
|
16
|
+
const { success } = await axiosPost(API.DEVICE.ADD_TO_DASHBOARD(device.id));
|
|
17
|
+
success && setAction(Action.ADD_DEVICES_TO_DASHBOARD, [device.id]);
|
|
18
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
19
|
+
}, [device.id]);
|
|
20
|
+
|
|
21
|
+
const removeFromDashboard = useCallback(async () => {
|
|
22
|
+
const { success } = await axiosPost(
|
|
23
|
+
API.DEVICE.REMOVE_FROM_DASHBOARD(device.id)
|
|
24
|
+
);
|
|
25
|
+
success && setAction(Action.REMOVE_DEVICES_FROM_DASHBOARD, [device.id]);
|
|
26
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
|
+
}, [device.id]);
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
isPinnedDashboard,
|
|
31
|
+
addToDashboard,
|
|
32
|
+
removeFromDashboard,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -99,4 +99,20 @@ export default StyleSheet.create({
|
|
|
99
99
|
marginLeft: 16,
|
|
100
100
|
marginBottom: 16,
|
|
101
101
|
},
|
|
102
|
+
widgetLabel: {
|
|
103
|
+
fontSize: 16,
|
|
104
|
+
color: Colors.Black,
|
|
105
|
+
marginHorizontal: 20,
|
|
106
|
+
marginBottom: 4,
|
|
107
|
+
},
|
|
108
|
+
widgetLabelCamera: {
|
|
109
|
+
fontSize: 16,
|
|
110
|
+
color: Colors.Black,
|
|
111
|
+
marginBottom: 4,
|
|
112
|
+
},
|
|
113
|
+
widgetLabelHistory: {
|
|
114
|
+
fontSize: 16,
|
|
115
|
+
color: Colors.Black,
|
|
116
|
+
marginHorizontal: 20,
|
|
117
|
+
},
|
|
102
118
|
});
|