@eohjsc/react-native-smart-city 0.3.92 → 0.3.94
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/package.json +5 -1
- package/src/commons/ActionGroup/SliderRangeTemplate.js +2 -2
- package/src/commons/AlertAction/index.js +5 -0
- package/src/commons/BottomButtonView/index.js +22 -4
- package/src/commons/Button/index.js +5 -0
- package/src/commons/Device/ConnectedViewHeader.js +0 -1
- package/src/commons/Device/Emergency/EmergencyDetail.js +4 -2
- package/src/commons/Device/Emergency/__test__/EmergencyDetail.test.js +4 -2
- package/src/commons/Device/ProgressBar/index.js +3 -1
- package/src/commons/Device/ProgressBar/styles.js +1 -4
- package/src/commons/Device/WindSpeed/Anemometer/index.js +1 -1
- package/src/commons/Header/HeaderCustom.js +8 -18
- package/src/commons/SubUnit/OneTap/ItemOneTap.js +84 -129
- package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +74 -39
- package/src/commons/SubUnit/OneTap/index.js +24 -4
- package/src/commons/ViewButtonBottom/index.js +32 -4
- package/src/configs/API.js +4 -0
- package/src/configs/AccessibilityLabel.js +1 -0
- package/src/configs/BLE.js +1 -0
- package/src/context/actionType.ts +2 -1
- package/src/context/mockStore.ts +1 -0
- package/src/context/reducer.ts +12 -1
- package/src/hooks/Explore/useKeyboardAnimated.js +10 -4
- package/src/hooks/IoT/useBluetoothConnection.js +14 -26
- package/src/hooks/useMqtt.js +95 -0
- package/src/iot/Monitor.js +2 -1
- package/src/iot/RemoteControl/Bluetooth.js +56 -19
- package/src/iot/RemoteControl/__test__/Bluetooth.test.js +140 -0
- package/src/iot/mqtt.js +233 -0
- package/src/navigations/UnitStack.js +11 -3
- package/src/screens/AddLocationMaps/index.js +18 -16
- package/src/screens/AddLocationMaps/indexStyle.js +3 -0
- package/src/screens/AddNewGateway/ConnectingDevice.js +7 -0
- package/src/screens/AddNewGateway/RenameNewDevices.js +2 -2
- package/src/screens/AddNewGateway/SelectDeviceType.js +67 -9
- package/src/screens/AddNewGateway/__test__/ConnectingZigbeeDevice.test.js +35 -0
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +183 -29
- package/src/screens/Automate/AddNewAction/NewActionWrapper.js +3 -6
- package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +29 -29
- package/src/screens/Automate/AddNewAction/__test__/SetupSensor.test.js +45 -39
- package/src/screens/Automate/AddNewAutoSmart/AddAutomationTypeSmart.js +25 -0
- package/src/screens/{AddNewAutoSmart/index.js → Automate/AddNewAutoSmart/AddTypeSmart.js} +16 -51
- package/src/screens/Automate/AddNewAutoSmart/AddUnknownTypeSmart.js +29 -0
- package/src/screens/{AddNewAutoSmart → Automate/AddNewAutoSmart}/__test__/AddNewAutoSmart.test.js +11 -11
- package/src/screens/{AddNewAutoSmart → Automate/AddNewAutoSmart}/styles/AddNewAutoSmartStyles.js +1 -1
- package/src/screens/Automate/Components/InputNameStyles.js +1 -1
- package/src/screens/Automate/EditActionsList/__tests__/index.test.js +11 -25
- package/src/screens/Automate/EditActionsList/index.js +32 -33
- package/src/screens/Automate/MultiUnits.js +29 -19
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +78 -5
- package/src/screens/Automate/ScriptDetail/index.js +38 -10
- package/src/screens/Automate/Styles/MultiUnitsStyles.js +1 -1
- package/src/screens/Automate/__test__/MultiUnits.test.js +64 -7
- package/src/screens/Automate/__test__/index.test.js +45 -11
- package/src/screens/Automate/index.js +53 -38
- package/src/screens/Device/__test__/detail.test.js +1 -1
- package/src/screens/Device/__test__/mqttDetail.test.js +599 -0
- package/src/screens/Device/components/SensorDisplayItem.js +1 -7
- package/src/screens/Device/detail.js +64 -30
- package/src/screens/Device/hooks/__test__/useEvaluateValue.test.js +24 -1
- package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +13 -3
- package/src/screens/SelectUnit/__test__/index.test.js +8 -13
- package/src/screens/Sharing/InfoMemberUnit.js +2 -2
- package/src/screens/Sharing/MemberList.js +28 -7
- package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +32 -18
- package/src/screens/Sharing/__test__/MemberList.test.js +37 -4
- package/src/screens/SmartAccount/__test__/SmartAccount.test.js +8 -4
- package/src/screens/SmartAccount/index.js +8 -9
- package/src/screens/SmartAccount/style.js +8 -7
- package/src/screens/Unit/AddMenu.js +42 -19
- package/src/screens/Unit/Detail.js +4 -19
- package/src/screens/Unit/Summaries.js +6 -17
- package/src/screens/Unit/__test__/AddMenu.test.js +68 -15
- package/src/screens/Unit/__test__/Summaries.test.js +2 -2
- package/src/screens/Unit/components/AutomateScript/index.js +1 -1
- package/src/utils/FactoryGateway.js +525 -0
- package/src/utils/I18n/translations/en.js +1409 -0
- package/src/utils/I18n/translations/vi.js +1411 -0
- package/src/utils/I18n/translations.ts +2 -2
- package/src/utils/Permission/backend.js +7 -0
- package/src/utils/Route/index.js +2 -1
- package/src/utils/Utils.js +11 -0
- package/src/commons/Device/SensorConnectedStatus.js +0 -56
- package/src/commons/Device/__test__/SensorConnectedStatus.test.js +0 -29
- package/src/screens/Sharing/__test__/MemberList2.test.js +0 -74
- package/src/utils/I18n/translations/en.json +0 -1138
- package/src/utils/I18n/translations/vi.json +0 -1136
|
@@ -14,13 +14,19 @@ import AddZigbeeDeviceIcon from '../../../assets/images/AddNewDevice/add-zigbee-
|
|
|
14
14
|
import styles from './SelectDeviceTypeStyles';
|
|
15
15
|
import AccessibilityLabel from '../../configs/AccessibilityLabel';
|
|
16
16
|
import { DEVICE_TYPE } from '../../configs/Constants';
|
|
17
|
+
import { useBackendPermission } from '../../utils/Permission/backend';
|
|
18
|
+
import { axiosGet } from '../../utils/Apis/axios';
|
|
19
|
+
import API from '../../configs/API';
|
|
20
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
17
21
|
|
|
18
22
|
const SelectDeviceGrid = ({ options, onSelect }) => {
|
|
19
23
|
const [selectIndexes, setSelectIndexes] = useState();
|
|
20
24
|
const onSelectOption = useCallback(
|
|
21
25
|
(value) => () => {
|
|
26
|
+
if (onSelect(value) === false) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
22
29
|
setSelectIndexes(value);
|
|
23
|
-
onSelect(value);
|
|
24
30
|
},
|
|
25
31
|
[onSelect]
|
|
26
32
|
);
|
|
@@ -51,17 +57,33 @@ const SelectDeviceGrid = ({ options, onSelect }) => {
|
|
|
51
57
|
);
|
|
52
58
|
};
|
|
53
59
|
|
|
60
|
+
const getPermissionCode = (deviceType) => {
|
|
61
|
+
switch (deviceType) {
|
|
62
|
+
case 'gateway_qr':
|
|
63
|
+
return 'plug_and_play_gateway';
|
|
64
|
+
case 'wifi_device_qr':
|
|
65
|
+
return 'plug_and_play_wifi';
|
|
66
|
+
case 'modbus_device_qr':
|
|
67
|
+
return 'plug_and_play_modbus';
|
|
68
|
+
case 'zigbee':
|
|
69
|
+
default:
|
|
70
|
+
return 'plug_and_play_zigbee';
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
54
74
|
const SelectDeviceType = ({ route }) => {
|
|
55
75
|
const t = useTranslations();
|
|
56
76
|
const { unit, subUnit } = route?.params || {};
|
|
57
77
|
const { navigate, goBack } = useNavigation();
|
|
78
|
+
const [unitCountSummary, setUnitCountSummary] = useState();
|
|
58
79
|
const [addType, setAddType] = useState();
|
|
59
80
|
const [selectedAddType, setSelectedAddType] = useState();
|
|
81
|
+
const permissions = useBackendPermission();
|
|
60
82
|
|
|
61
83
|
const listDeviceType = useMemo(() => {
|
|
62
84
|
const list = [
|
|
63
85
|
{
|
|
64
|
-
id:
|
|
86
|
+
id: 'gateway_qr',
|
|
65
87
|
image: <AddGatewayIcon width={60} height={60} />,
|
|
66
88
|
route: Routes.ScanGatewayQR,
|
|
67
89
|
data: {
|
|
@@ -71,7 +93,7 @@ const SelectDeviceType = ({ route }) => {
|
|
|
71
93
|
subtitle: t('central_controller'),
|
|
72
94
|
},
|
|
73
95
|
{
|
|
74
|
-
id:
|
|
96
|
+
id: 'wifi_device_qr',
|
|
75
97
|
image: <AddWifiDeviceIcon width={60} height={60} />,
|
|
76
98
|
route: subUnit?.id
|
|
77
99
|
? Routes.ScanWifiDeviceQR
|
|
@@ -85,7 +107,7 @@ const SelectDeviceType = ({ route }) => {
|
|
|
85
107
|
subtitle: t('device_connect_without_gateway'),
|
|
86
108
|
},
|
|
87
109
|
{
|
|
88
|
-
id:
|
|
110
|
+
id: 'modbus_device_qr',
|
|
89
111
|
image: <AddModbusDeviceIcon width={60} height={60} />,
|
|
90
112
|
route: subUnit?.id ? Routes.ScanModbusQR : Routes.SelectDeviceSubUnit,
|
|
91
113
|
data: {
|
|
@@ -97,7 +119,7 @@ const SelectDeviceType = ({ route }) => {
|
|
|
97
119
|
subtitle: t('device_connect_directly_to_the_gateway'),
|
|
98
120
|
},
|
|
99
121
|
{
|
|
100
|
-
id:
|
|
122
|
+
id: 'zigbee',
|
|
101
123
|
image: <AddZigbeeDeviceIcon width={60} height={60} />,
|
|
102
124
|
route: subUnit?.id
|
|
103
125
|
? Routes.ConnectRouterGuide
|
|
@@ -111,19 +133,43 @@ const SelectDeviceType = ({ route }) => {
|
|
|
111
133
|
subtitle: t('device_connect_remotely_to_the_gateway'),
|
|
112
134
|
},
|
|
113
135
|
];
|
|
114
|
-
if (
|
|
136
|
+
if (subUnit?.id) {
|
|
115
137
|
list.shift();
|
|
116
138
|
}
|
|
117
139
|
return list;
|
|
118
140
|
}, [unit, t, subUnit]);
|
|
119
141
|
|
|
120
142
|
const onRight = useCallback(() => {
|
|
121
|
-
if (selectedAddType?.route
|
|
122
|
-
|
|
143
|
+
if (!selectedAddType?.route) {
|
|
144
|
+
return;
|
|
123
145
|
}
|
|
146
|
+
|
|
147
|
+
navigate(selectedAddType?.route, selectedAddType?.data);
|
|
124
148
|
}, [navigate, selectedAddType?.data, selectedAddType?.route]);
|
|
125
149
|
|
|
126
150
|
const handleOnSelect = (itemSelect) => {
|
|
151
|
+
const needPermission = getPermissionCode(itemSelect);
|
|
152
|
+
if (!permissions?.[needPermission]) {
|
|
153
|
+
ToastBottomHelper.error(t(`no_permission_${needPermission}`));
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (['gateway_qr', 'wifi_device_qr'].includes(itemSelect)) {
|
|
158
|
+
if (permissions?.max_chips_per_unit <= unitCountSummary?.total_chips) {
|
|
159
|
+
ToastBottomHelper.error(t('reach_max_chips_per_unit'));
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (['wifi_device_qr', 'modbus_device_qr', 'zigbee'].includes(itemSelect)) {
|
|
165
|
+
if (
|
|
166
|
+
permissions?.max_configs_per_unit <= unitCountSummary?.total_configs
|
|
167
|
+
) {
|
|
168
|
+
ToastBottomHelper.error(t('reach_max_configs_per_unit'));
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
127
173
|
setAddType(itemSelect);
|
|
128
174
|
};
|
|
129
175
|
|
|
@@ -131,6 +177,18 @@ const SelectDeviceType = ({ route }) => {
|
|
|
131
177
|
setSelectedAddType(listDeviceType.find((item) => item.id === addType));
|
|
132
178
|
}, [addType, listDeviceType]);
|
|
133
179
|
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
const fetchCountSummary = async () => {
|
|
182
|
+
const { success, data } = await axiosGet(API.DEV_MODE.GATEWAY.COUNT(), {
|
|
183
|
+
unit: unit?.id,
|
|
184
|
+
});
|
|
185
|
+
if (success) {
|
|
186
|
+
setUnitCountSummary(data);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
fetchCountSummary();
|
|
190
|
+
}, [unit?.id]);
|
|
191
|
+
|
|
134
192
|
return (
|
|
135
193
|
<View style={styles.container}>
|
|
136
194
|
<HeaderCustom title={t('choose_type_of_device')} isShowSeparator />
|
|
@@ -141,7 +199,7 @@ const SelectDeviceType = ({ route }) => {
|
|
|
141
199
|
leftTitle={t('cancel')}
|
|
142
200
|
onLeftClick={goBack}
|
|
143
201
|
rightTitle={t('text_next')}
|
|
144
|
-
rightDisabled={!addType}
|
|
202
|
+
rightDisabled={!unitCountSummary || !addType}
|
|
145
203
|
onRightClick={onRight}
|
|
146
204
|
/>
|
|
147
205
|
</View>
|
|
@@ -121,4 +121,39 @@ describe('Test connecting modbus device', () => {
|
|
|
121
121
|
sensorId: 1,
|
|
122
122
|
});
|
|
123
123
|
});
|
|
124
|
+
|
|
125
|
+
it('receive sensor from channel after rejoin zigbee', async () => {
|
|
126
|
+
mock.onPost().reply(200, {});
|
|
127
|
+
await act(async () => {
|
|
128
|
+
tree = await create(wrapComponent(route));
|
|
129
|
+
});
|
|
130
|
+
const channels = getPusher().channels;
|
|
131
|
+
let channel;
|
|
132
|
+
for (const key in channels) {
|
|
133
|
+
if (key.indexOf('cache-') === 0) {
|
|
134
|
+
channel = channels[key];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
await act(async () => {
|
|
138
|
+
await channel.trigger('progress', {
|
|
139
|
+
data: { sensor: { id: 1, name: 'sensor' }, type: 'rejoin' },
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
await act(async () => {
|
|
143
|
+
await channel.trigger('progress', { success: 1 });
|
|
144
|
+
});
|
|
145
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.RenameNewDevices, {
|
|
146
|
+
addDeviceType: undefined,
|
|
147
|
+
unit: {
|
|
148
|
+
id: 1,
|
|
149
|
+
},
|
|
150
|
+
subUnit: {
|
|
151
|
+
id: 2,
|
|
152
|
+
station: 'Station 2',
|
|
153
|
+
},
|
|
154
|
+
chipId: 3,
|
|
155
|
+
sensorId: 1,
|
|
156
|
+
isRejoin: true,
|
|
157
|
+
});
|
|
158
|
+
});
|
|
124
159
|
});
|
|
@@ -8,36 +8,30 @@ import Routes from '../../../utils/Route';
|
|
|
8
8
|
import { TouchableOpacity } from 'react-native';
|
|
9
9
|
import AccessibilityLabel from '../../../configs/AccessibilityLabel';
|
|
10
10
|
import { ViewButtonBottom } from '../../../commons';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
import { useNavigation } from '@react-navigation/native';
|
|
12
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
13
|
+
import api from '../../../utils/Apis/axios';
|
|
14
|
+
import API from '../../../configs/API';
|
|
15
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
16
|
+
import { getTranslate } from '../../../utils/I18n';
|
|
17
|
+
const wrapComponent = (route, storeData = {}) => (
|
|
18
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
14
19
|
<SelectDeviceType route={route} />
|
|
15
20
|
</SCProvider>
|
|
16
21
|
);
|
|
17
22
|
|
|
18
|
-
const
|
|
19
|
-
const mockedGoBack = jest.fn();
|
|
20
|
-
|
|
21
|
-
jest.mock('@react-navigation/native', () => {
|
|
22
|
-
return {
|
|
23
|
-
...jest.requireActual('@react-navigation/native'),
|
|
24
|
-
useNavigation: () => ({
|
|
25
|
-
navigate: mockedNavigate,
|
|
26
|
-
goBack: mockedGoBack,
|
|
27
|
-
}),
|
|
28
|
-
useIsFocused: () => true,
|
|
29
|
-
};
|
|
30
|
-
});
|
|
23
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
31
24
|
|
|
32
25
|
describe('Test select device type', () => {
|
|
33
26
|
let tree;
|
|
34
27
|
let route;
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
29
|
+
const mockedNavigate = useNavigation().navigate;
|
|
30
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
39
31
|
|
|
40
32
|
beforeEach(() => {
|
|
33
|
+
spyToastError.mockClear();
|
|
34
|
+
mockedNavigate.mockClear();
|
|
41
35
|
route = {
|
|
42
36
|
params: {
|
|
43
37
|
unitId: 1,
|
|
@@ -81,9 +75,9 @@ describe('Test select device type', () => {
|
|
|
81
75
|
expect(deviceTypeItems).toHaveLength(3);
|
|
82
76
|
});
|
|
83
77
|
|
|
84
|
-
const selectDeviceType = async (index) => {
|
|
78
|
+
const selectDeviceType = async (index, storeData = {}) => {
|
|
85
79
|
await act(async () => {
|
|
86
|
-
tree = await create(wrapComponent(route));
|
|
80
|
+
tree = await create(wrapComponent(route, storeData));
|
|
87
81
|
});
|
|
88
82
|
const instance = tree.root;
|
|
89
83
|
const deviceTypeItems = instance.findAll(
|
|
@@ -99,24 +93,184 @@ describe('Test select device type', () => {
|
|
|
99
93
|
await act(async () => {
|
|
100
94
|
submitButton.props.onRightClick();
|
|
101
95
|
});
|
|
102
|
-
|
|
103
|
-
expect(mockedNavigate).toBeCalled();
|
|
104
96
|
};
|
|
105
97
|
|
|
106
98
|
it('select modbus', async () => {
|
|
107
|
-
await selectDeviceType(
|
|
108
|
-
|
|
99
|
+
await selectDeviceType(2, {
|
|
100
|
+
auth: {
|
|
101
|
+
account: {
|
|
102
|
+
user: {
|
|
103
|
+
permissions: {
|
|
104
|
+
plug_and_play_modbus: true,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
expect(mockedNavigate).toBeCalled();
|
|
111
|
+
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
|
|
109
112
|
});
|
|
113
|
+
|
|
110
114
|
it('select zigbee', async () => {
|
|
111
|
-
await selectDeviceType(
|
|
115
|
+
await selectDeviceType(3, {
|
|
116
|
+
auth: {
|
|
117
|
+
account: {
|
|
118
|
+
user: {
|
|
119
|
+
permissions: {
|
|
120
|
+
plug_and_play_zigbee: true,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
expect(mockedNavigate).toBeCalled();
|
|
112
127
|
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
|
|
113
128
|
});
|
|
129
|
+
|
|
130
|
+
it('select zigbee reach limit', async () => {
|
|
131
|
+
mock.onGet(API.DEV_MODE.GATEWAY.COUNT()).reply(200, {
|
|
132
|
+
total_chips: 1,
|
|
133
|
+
total_configs: 1,
|
|
134
|
+
});
|
|
135
|
+
await selectDeviceType(3, {
|
|
136
|
+
auth: {
|
|
137
|
+
account: {
|
|
138
|
+
user: {
|
|
139
|
+
permissions: {
|
|
140
|
+
max_chips_per_unit: 1,
|
|
141
|
+
max_configs_per_unit: 1,
|
|
142
|
+
plug_and_play_zigbee: true,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
149
|
+
expect(spyToastError).toBeCalledWith(
|
|
150
|
+
getTranslate('en', 'reach_max_configs_per_unit')
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
114
154
|
it('select gateway', async () => {
|
|
115
|
-
await selectDeviceType(
|
|
116
|
-
|
|
155
|
+
await selectDeviceType(0, {
|
|
156
|
+
auth: {
|
|
157
|
+
account: {
|
|
158
|
+
user: {
|
|
159
|
+
permissions: {
|
|
160
|
+
plug_and_play_gateway: true,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
expect(mockedNavigate).toBeCalled();
|
|
167
|
+
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.ScanGatewayQR);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('select gateway reach limit', async () => {
|
|
171
|
+
mock.onGet(API.DEV_MODE.GATEWAY.COUNT()).reply(200, {
|
|
172
|
+
total_chips: 1,
|
|
173
|
+
total_configs: 1,
|
|
174
|
+
});
|
|
175
|
+
await selectDeviceType(0, {
|
|
176
|
+
auth: {
|
|
177
|
+
account: {
|
|
178
|
+
user: {
|
|
179
|
+
permissions: {
|
|
180
|
+
max_chips_per_unit: 1,
|
|
181
|
+
plug_and_play_gateway: true,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
188
|
+
expect(spyToastError).toBeCalledWith(
|
|
189
|
+
getTranslate('en', 'reach_max_chips_per_unit')
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('select gateway without permission', async () => {
|
|
194
|
+
await selectDeviceType(0, {
|
|
195
|
+
auth: {
|
|
196
|
+
account: {
|
|
197
|
+
user: {
|
|
198
|
+
permissions: {
|
|
199
|
+
plug_and_play_gateway: false,
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
expect(spyToastError).toBeCalledWith(
|
|
206
|
+
getTranslate('en', 'no_permission_plug_and_play_gateway')
|
|
207
|
+
);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('select zigbee without permission', async () => {
|
|
211
|
+
await selectDeviceType(3, {
|
|
212
|
+
auth: {
|
|
213
|
+
account: {
|
|
214
|
+
user: {
|
|
215
|
+
permissions: {
|
|
216
|
+
plug_and_play_zigbee: false,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
expect(spyToastError).toBeCalledWith(
|
|
223
|
+
getTranslate('en', 'no_permission_plug_and_play_zigbee')
|
|
224
|
+
);
|
|
117
225
|
});
|
|
226
|
+
|
|
227
|
+
it('select wifi without permission', async () => {
|
|
228
|
+
await selectDeviceType(1, {
|
|
229
|
+
auth: {
|
|
230
|
+
account: {
|
|
231
|
+
user: {
|
|
232
|
+
permissions: {
|
|
233
|
+
plug_and_play_wifi: false,
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
expect(spyToastError).toBeCalledWith(
|
|
240
|
+
getTranslate('en', 'no_permission_plug_and_play_wifi')
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('select modbus without permission', async () => {
|
|
245
|
+
await selectDeviceType(2, {
|
|
246
|
+
auth: {
|
|
247
|
+
account: {
|
|
248
|
+
user: {
|
|
249
|
+
permissions: {
|
|
250
|
+
plug_and_play_modbus: false,
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
expect(spyToastError).toBeCalledWith(
|
|
257
|
+
getTranslate('en', 'no_permission_plug_and_play_modbus')
|
|
258
|
+
);
|
|
259
|
+
});
|
|
260
|
+
|
|
118
261
|
it('select wifi', async () => {
|
|
119
|
-
await selectDeviceType(
|
|
262
|
+
await selectDeviceType(1, {
|
|
263
|
+
auth: {
|
|
264
|
+
account: {
|
|
265
|
+
user: {
|
|
266
|
+
permissions: {
|
|
267
|
+
plug_and_play_wifi: true,
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
expect(mockedNavigate).toBeCalled();
|
|
120
274
|
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
|
|
121
275
|
});
|
|
122
276
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useMemo } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { TouchableOpacity, View } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import styles from './Styles/SelectActionStyles';
|
|
5
5
|
import WrapHeaderScrollable from '../../../commons/Sharing/WrapHeaderScrollable';
|
|
@@ -32,10 +32,7 @@ const NewActionWrapper = ({ name, children, canNext, onNext, nextTitle }) => {
|
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<
|
|
36
|
-
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
37
|
-
style={styles.wrap}
|
|
38
|
-
>
|
|
35
|
+
<View style={styles.wrap}>
|
|
39
36
|
<WrapHeaderScrollable
|
|
40
37
|
title={name}
|
|
41
38
|
headerAniStyle={styles.headerAniStyle}
|
|
@@ -49,7 +46,7 @@ const NewActionWrapper = ({ name, children, canNext, onNext, nextTitle }) => {
|
|
|
49
46
|
onPressMain={onNext}
|
|
50
47
|
typeMain={canNext ? 'primary' : 'disabled'}
|
|
51
48
|
/>
|
|
52
|
-
</
|
|
49
|
+
</View>
|
|
53
50
|
);
|
|
54
51
|
};
|
|
55
52
|
|
|
@@ -7,11 +7,11 @@ import { Colors, Images } from '../../../configs';
|
|
|
7
7
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
8
8
|
import { ModalCustom } from '../../../commons/Modal';
|
|
9
9
|
import Text from '../../../commons/Text';
|
|
10
|
-
import { HorizontalPicker } from '../../../commons';
|
|
11
10
|
import { setStatusBarPreview } from '../../../hooks/Common/useStatusBar';
|
|
12
11
|
import Routes from '../../../utils/Route';
|
|
13
12
|
import NewActionWrapper from './NewActionWrapper';
|
|
14
13
|
import _TextInput from '../../../commons/Form/TextInput';
|
|
14
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
15
15
|
|
|
16
16
|
const SetupConfigCondition = () => {
|
|
17
17
|
const t = useTranslations();
|
|
@@ -22,7 +22,7 @@ const SetupConfigCondition = () => {
|
|
|
22
22
|
|
|
23
23
|
const [isShowModal, setIsShowModal] = useState(false);
|
|
24
24
|
const [itemActiveModal, setItemActiveModal] = useState(defaultCondition);
|
|
25
|
-
const [value, setValue] = useState(defaultCondition?.value);
|
|
25
|
+
const [value, setValue] = useState(defaultCondition?.value || '');
|
|
26
26
|
|
|
27
27
|
const hasNoValueEvaluation = !item?.evaluate_configuration;
|
|
28
28
|
|
|
@@ -68,6 +68,27 @@ const SetupConfigCondition = () => {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
const onSave = useCallback(() => {
|
|
71
|
+
const conditionValue = parseFloat(itemActiveModal?.value);
|
|
72
|
+
if (isNaN(conditionValue)) {
|
|
73
|
+
ToastBottomHelper.error(t('value_must_be_a_number'));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (['<', '>', '='].includes(itemActiveModal?.condition)) {
|
|
78
|
+
if (item.range_min !== null && conditionValue < item.range_min) {
|
|
79
|
+
ToastBottomHelper.error(
|
|
80
|
+
t('value_must_be_greater_than_min', { min: item.range_min })
|
|
81
|
+
);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (item.range_max !== null && conditionValue > item.range_max) {
|
|
85
|
+
ToastBottomHelper.error(
|
|
86
|
+
t('value_must_be_less_than_max', { max: item.range_max })
|
|
87
|
+
);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
71
92
|
navigate({
|
|
72
93
|
name: Routes.ChooseConfig,
|
|
73
94
|
merge: true,
|
|
@@ -78,7 +99,7 @@ const SetupConfigCondition = () => {
|
|
|
78
99
|
},
|
|
79
100
|
},
|
|
80
101
|
});
|
|
81
|
-
}, [item.id, itemActiveModal, navigate]);
|
|
102
|
+
}, [item.id, item.range_max, item.range_min, itemActiveModal, navigate, t]);
|
|
82
103
|
|
|
83
104
|
useEffect(() => {
|
|
84
105
|
!hasNoValueEvaluation && setValue(1);
|
|
@@ -98,12 +119,9 @@ const SetupConfigCondition = () => {
|
|
|
98
119
|
);
|
|
99
120
|
}, [isShowModal]);
|
|
100
121
|
|
|
101
|
-
const onChangeValue = useCallback((
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
setValue(newValue);
|
|
105
|
-
setItemActiveModal((prev) => ({ ...prev, value: newValue }));
|
|
106
|
-
}
|
|
122
|
+
const onChangeValue = useCallback((newValue) => {
|
|
123
|
+
setValue(newValue);
|
|
124
|
+
setItemActiveModal((prev) => ({ ...prev, value: newValue }));
|
|
107
125
|
}, []);
|
|
108
126
|
|
|
109
127
|
return (
|
|
@@ -136,7 +154,8 @@ const SetupConfigCondition = () => {
|
|
|
136
154
|
<_TextInput
|
|
137
155
|
textInputStyle={styles.value}
|
|
138
156
|
wrapStyle={styles.wrapValue}
|
|
139
|
-
value={value
|
|
157
|
+
value={value}
|
|
158
|
+
keyboardType={'numeric'}
|
|
140
159
|
onChange={onChangeValue}
|
|
141
160
|
/>
|
|
142
161
|
</View>
|
|
@@ -144,25 +163,6 @@ const SetupConfigCondition = () => {
|
|
|
144
163
|
{item?.unit}
|
|
145
164
|
</Text>
|
|
146
165
|
</View>
|
|
147
|
-
<HorizontalPicker
|
|
148
|
-
minimum={item?.range_min}
|
|
149
|
-
maximum={item?.range_max}
|
|
150
|
-
segmentSpacing={8}
|
|
151
|
-
segmentWidth={8}
|
|
152
|
-
step={
|
|
153
|
-
item?.decimal_behind
|
|
154
|
-
? 1 / Math.pow(10, item?.decimal_behind)
|
|
155
|
-
: 1
|
|
156
|
-
}
|
|
157
|
-
normalHeight={4}
|
|
158
|
-
normalWidth={4}
|
|
159
|
-
stepHeight={12}
|
|
160
|
-
stepWidth={12}
|
|
161
|
-
stepColor={Colors.Gray6}
|
|
162
|
-
normalColor={Colors.Gray6}
|
|
163
|
-
onChangeValue={onChangeValue}
|
|
164
|
-
value={value}
|
|
165
|
-
/>
|
|
166
166
|
</>
|
|
167
167
|
)}
|
|
168
168
|
</NewActionWrapper>
|