@eohjsc/react-native-smart-city 0.3.93 → 0.3.95
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 +1 -1
- package/src/commons/ActionGroup/OnOffTemplate/index.js +20 -17
- package/src/commons/ActionGroup/__test__/OnOffButtonTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +5 -24
- package/src/commons/SubUnit/OneTap/ItemOneTap.js +83 -85
- package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +68 -24
- package/src/commons/SubUnit/OneTap/index.js +21 -1
- package/src/configs/API.js +1 -0
- package/src/screens/ActivityLog/__test__/index.test.js +60 -2
- package/src/screens/ActivityLog/hooks/__test__/index.test.js +5 -0
- package/src/screens/ActivityLog/hooks/index.js +11 -0
- package/src/screens/AddLocationMaps/index.js +1 -1
- package/src/screens/AddNewGateway/ConnectingDevice.js +7 -0
- package/src/screens/AddNewGateway/ConnectingWifiDevice.js +6 -4
- package/src/screens/AddNewGateway/ConnectingWifiGuide.js +0 -1
- package/src/screens/AddNewGateway/RenameNewDevices.js +2 -2
- package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +1 -6
- package/src/screens/AddNewGateway/SelectDeviceType.js +67 -9
- package/src/screens/AddNewGateway/ShareWifiPassword.js +20 -3
- package/src/screens/AddNewGateway/__test__/ConnectingZigbeeDevice.test.js +35 -0
- package/src/screens/AddNewGateway/__test__/ScanWifiDeviceQR.test.js +0 -10
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +183 -29
- package/src/screens/AllGateway/GatewayInfo/index.js +3 -3
- package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +0 -1
- package/src/screens/Automate/MultiUnits.js +32 -18
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +36 -2
- package/src/screens/Automate/ScriptDetail/index.js +17 -3
- package/src/screens/Automate/Styles/MultiUnitsStyles.js +1 -1
- package/src/screens/Automate/__test__/MultiUnits.test.js +125 -8
- package/src/screens/Automate/__test__/index.test.js +95 -11
- package/src/screens/Automate/index.js +62 -38
- package/src/screens/Device/hooks/__test__/useEvaluateValue.test.js +24 -1
- 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/SubUnit/AddSubUnit.js +1 -1
- package/src/screens/SubUnit/__test__/AddSubUnit.test.js +16 -3
- package/src/screens/Unit/AddMenu.js +42 -19
- package/src/screens/Unit/__test__/AddMenu.test.js +68 -15
- package/src/screens/Unit/components/AutomateScript/index.js +1 -1
- package/src/utils/I18n/translations/en.js +1409 -0
- package/src/utils/I18n/translations/vi.js +1414 -0
- package/src/utils/I18n/translations.ts +2 -2
- package/src/utils/Permission/backend.js +7 -0
- package/src/screens/Sharing/__test__/MemberList2.test.js +0 -74
- package/src/utils/I18n/translations/en.json +0 -1142
- package/src/utils/I18n/translations/vi.json +0 -1139
|
@@ -17,20 +17,17 @@ import { AUTOMATE_TABS, AUTOMATE_TYPE } from '../../configs/Constants';
|
|
|
17
17
|
import ItemOneTap from '../../commons/SubUnit/OneTap/ItemOneTap';
|
|
18
18
|
import Routes from '../../utils/Route';
|
|
19
19
|
import ItemAddNew from '../../commons/Device/ItemAddNew';
|
|
20
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
21
|
+
import { useBackendPermission } from '../../utils/Permission/backend';
|
|
20
22
|
|
|
21
23
|
const MultiUnits = () => {
|
|
22
24
|
const t = useTranslations();
|
|
23
25
|
const isFocused = useIsFocused();
|
|
24
26
|
const { navigate } = useNavigation();
|
|
25
27
|
const { params = {}, name: currentRouteName } = useRoute();
|
|
26
|
-
const {
|
|
27
|
-
isMultiUnits = false,
|
|
28
|
-
unitName = '',
|
|
29
|
-
unit,
|
|
30
|
-
isOwner,
|
|
31
|
-
newAutomate,
|
|
32
|
-
} = params;
|
|
28
|
+
const { unit, newAutomate } = params;
|
|
33
29
|
const [data, setData] = useState([]);
|
|
30
|
+
const permissions = useBackendPermission();
|
|
34
31
|
|
|
35
32
|
const [tabActive, setTabActive] = useState(AUTOMATE_TABS.SCENARIO);
|
|
36
33
|
|
|
@@ -40,20 +37,20 @@ const MultiUnits = () => {
|
|
|
40
37
|
|
|
41
38
|
const getData = useCallback(
|
|
42
39
|
async (fetchParams) => {
|
|
43
|
-
if (
|
|
40
|
+
if (unit?.id) {
|
|
41
|
+
await fetchWithCache(API.UNIT.AUTOMATE(unit?.id), {}, (response) => {
|
|
42
|
+
const { success, data: automateData } = response;
|
|
43
|
+
success && setData(automateData);
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
44
46
|
const { success, data: automateData } = await axiosGet(
|
|
45
47
|
API.AUTOMATE.GET_MULTI_UNITS(),
|
|
46
48
|
fetchParams
|
|
47
49
|
);
|
|
48
50
|
success && setData(automateData);
|
|
49
|
-
} else {
|
|
50
|
-
await fetchWithCache(API.UNIT.AUTOMATE(unit?.id), {}, (response) => {
|
|
51
|
-
const { success, data: automateData } = response;
|
|
52
|
-
success && setData(automateData);
|
|
53
|
-
});
|
|
54
51
|
}
|
|
55
52
|
},
|
|
56
|
-
[
|
|
53
|
+
[unit?.id]
|
|
57
54
|
);
|
|
58
55
|
|
|
59
56
|
const onPressTabName = (tab) => () => {
|
|
@@ -79,6 +76,15 @@ const MultiUnits = () => {
|
|
|
79
76
|
}, [newAutomate, onPressItem]);
|
|
80
77
|
|
|
81
78
|
const handleOnAddNew = useCallback(() => {
|
|
79
|
+
if (unit?.id) {
|
|
80
|
+
if (permissions?.max_automations_per_unit <= data.length) {
|
|
81
|
+
ToastBottomHelper.error(t('reach_max_automations_per_unit'));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
} else if (!permissions?.smart_script_for_multi_unit) {
|
|
85
|
+
ToastBottomHelper.error(t('no_permission_smart_script_for_multi_unit'));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
82
88
|
if (tabActive === AUTOMATE_TABS.SCENARIO) {
|
|
83
89
|
navigate(Routes.UnitStack, {
|
|
84
90
|
screen: Routes.ScenarioName,
|
|
@@ -97,7 +103,16 @@ const MultiUnits = () => {
|
|
|
97
103
|
closeScreen: currentRouteName,
|
|
98
104
|
},
|
|
99
105
|
});
|
|
100
|
-
}, [
|
|
106
|
+
}, [
|
|
107
|
+
currentRouteName,
|
|
108
|
+
data.length,
|
|
109
|
+
navigate,
|
|
110
|
+
permissions?.max_automations_per_unit,
|
|
111
|
+
permissions?.smart_script_for_multi_unit,
|
|
112
|
+
t,
|
|
113
|
+
tabActive,
|
|
114
|
+
unit?.id,
|
|
115
|
+
]);
|
|
101
116
|
|
|
102
117
|
const renderContent = useMemo(() => {
|
|
103
118
|
const listItems = data.filter((item) =>
|
|
@@ -116,11 +131,10 @@ const MultiUnits = () => {
|
|
|
116
131
|
{sortedListItems.map((item, index) => (
|
|
117
132
|
<ItemOneTap
|
|
118
133
|
key={(item?.id || index).toString()}
|
|
119
|
-
isOwner={isOwner}
|
|
120
134
|
automate={item}
|
|
121
135
|
wrapSyles={[
|
|
122
136
|
styles.wrapAutomateItem,
|
|
123
|
-
index % 2 === 0 && styles.
|
|
137
|
+
index % 2 === 0 && styles.itemOneTapMargin,
|
|
124
138
|
]}
|
|
125
139
|
onPressItem={() => onPressItem(item)}
|
|
126
140
|
/>
|
|
@@ -142,7 +156,7 @@ const MultiUnits = () => {
|
|
|
142
156
|
return (
|
|
143
157
|
<View style={styles.wrap}>
|
|
144
158
|
<WrapHeaderScrollable
|
|
145
|
-
title={
|
|
159
|
+
title={unit?.id ? unit?.name : t('multi_units_automate')}
|
|
146
160
|
headerAniStyle={styles.headerAniStyle}
|
|
147
161
|
>
|
|
148
162
|
<View style={styles.wrapContent}>
|
|
@@ -24,8 +24,8 @@ import Text from '../../../../commons/Text';
|
|
|
24
24
|
import { ToastBottomHelper } from '../../../../utils/Utils';
|
|
25
25
|
import { getTranslate } from '../../../../utils/I18n';
|
|
26
26
|
|
|
27
|
-
const wrapComponent = (route) => (
|
|
28
|
-
<SCProvider initState={mockSCStore(
|
|
27
|
+
const wrapComponent = (route, storeData = {}) => (
|
|
28
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
29
29
|
<ScriptDetail route={route} />
|
|
30
30
|
</SCProvider>
|
|
31
31
|
);
|
|
@@ -241,6 +241,40 @@ describe('Test ScriptDetail', () => {
|
|
|
241
241
|
});
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
+
it('test press add action reach limit', async () => {
|
|
245
|
+
mock.onGet(API.AUTOMATE.SCRIPT(1)).reply(200, data);
|
|
246
|
+
await act(async () => {
|
|
247
|
+
tree = await create(
|
|
248
|
+
wrapComponent(route, {
|
|
249
|
+
auth: {
|
|
250
|
+
account: {
|
|
251
|
+
user: {
|
|
252
|
+
permissions: {
|
|
253
|
+
max_actions_per_automation: 0,
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
})
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
const instance = tree.root;
|
|
262
|
+
const button = instance.find(
|
|
263
|
+
(el) =>
|
|
264
|
+
el.props.accessibilityLabel ===
|
|
265
|
+
AccessibilityLabel.BUTTON_ADD_SCRIPT_ACTION &&
|
|
266
|
+
el.type === TouchableOpacity
|
|
267
|
+
);
|
|
268
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
269
|
+
await act(async () => {
|
|
270
|
+
await button.props.onPress();
|
|
271
|
+
});
|
|
272
|
+
expect(mockNavigate).not.toBeCalled();
|
|
273
|
+
expect(spyToastError).toBeCalledWith(
|
|
274
|
+
getTranslate('en', 'reach_max_actions_per_automation')
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
|
|
244
278
|
it('test not see add action', async () => {
|
|
245
279
|
route.params.preAutomate.can_edit = false;
|
|
246
280
|
mock.onGet(API.AUTOMATE.SCRIPT(1)).reply(200, data);
|
|
@@ -30,6 +30,7 @@ import { AccessibilityLabel, AUTOMATE_TYPE } from '../../../configs/Constants';
|
|
|
30
30
|
import RenameScript from './Components/RenameScript';
|
|
31
31
|
import DeleteScript from './Components/DeleteScript';
|
|
32
32
|
import Images from '../../../configs/Images';
|
|
33
|
+
import { useBackendPermission } from '../../../utils/Permission/backend';
|
|
33
34
|
|
|
34
35
|
const PreventDoubleTouch = withPreventDoubleClick(TouchableOpacity);
|
|
35
36
|
|
|
@@ -122,9 +123,9 @@ const ScriptDetail = ({ route }) => {
|
|
|
122
123
|
const handleScriptAction = useCallback(async () => {
|
|
123
124
|
const { success } = await axiosPost(API.AUTOMATE.ACTION_ONE_TAP(id));
|
|
124
125
|
if (success) {
|
|
125
|
-
ToastBottomHelper.success(t('
|
|
126
|
+
ToastBottomHelper.success(t('activated_successfully'));
|
|
126
127
|
} else {
|
|
127
|
-
ToastBottomHelper.error(t('
|
|
128
|
+
ToastBottomHelper.error(t('activation_failed'));
|
|
128
129
|
}
|
|
129
130
|
}, [id, t]);
|
|
130
131
|
|
|
@@ -296,9 +297,14 @@ const Item = ({ item, index }) => {
|
|
|
296
297
|
const ItemAdd = ({ automate, index }) => {
|
|
297
298
|
const t = useTranslations();
|
|
298
299
|
const { navigate } = useNavigation();
|
|
300
|
+
const permissions = useBackendPermission();
|
|
299
301
|
const { name: currentScreenName } = useRoute();
|
|
300
302
|
|
|
301
303
|
const onPressAddAction = useCallback(() => {
|
|
304
|
+
if (permissions?.max_actions_per_automation <= index) {
|
|
305
|
+
ToastBottomHelper.error(t('reach_max_actions_per_automation'));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
302
308
|
const navParams = {
|
|
303
309
|
unitId: automate.unit,
|
|
304
310
|
automateId: automate.id,
|
|
@@ -309,7 +315,15 @@ const ItemAdd = ({ automate, index }) => {
|
|
|
309
315
|
automate.unit ? Routes.SelectControlDevices : Routes.SelectUnit,
|
|
310
316
|
navParams
|
|
311
317
|
);
|
|
312
|
-
}, [
|
|
318
|
+
}, [
|
|
319
|
+
permissions?.max_actions_per_automation,
|
|
320
|
+
index,
|
|
321
|
+
automate.unit,
|
|
322
|
+
automate.id,
|
|
323
|
+
currentScreenName,
|
|
324
|
+
navigate,
|
|
325
|
+
t,
|
|
326
|
+
]);
|
|
313
327
|
|
|
314
328
|
return (
|
|
315
329
|
<View style={styles.wrapItem}>
|
|
@@ -15,11 +15,12 @@ import { getTranslate } from '../../../utils/I18n';
|
|
|
15
15
|
import { AUTOMATE_TYPE } from '../../../configs/Constants';
|
|
16
16
|
import api from '../../../utils/Apis/axios';
|
|
17
17
|
import { API } from '../../../configs';
|
|
18
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
18
19
|
|
|
19
20
|
const mock = new MockAdapter(api.axiosInstance);
|
|
20
21
|
|
|
21
|
-
const wrapComponent = () => (
|
|
22
|
-
<SCProvider initState={mockSCStore(
|
|
22
|
+
const wrapComponent = (storeData = {}) => (
|
|
23
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
23
24
|
<MultiUnits />
|
|
24
25
|
</SCProvider>
|
|
25
26
|
);
|
|
@@ -31,6 +32,7 @@ describe('Test MultiUnits', () => {
|
|
|
31
32
|
beforeEach(() => {
|
|
32
33
|
mockedNavigate.mockClear();
|
|
33
34
|
useRoute.mockClear();
|
|
35
|
+
mock.reset();
|
|
34
36
|
});
|
|
35
37
|
|
|
36
38
|
it('Test is multi unit and current is Automation tab', async () => {
|
|
@@ -78,7 +80,19 @@ describe('Test MultiUnits', () => {
|
|
|
78
80
|
},
|
|
79
81
|
});
|
|
80
82
|
await act(async () => {
|
|
81
|
-
tree = await create(
|
|
83
|
+
tree = await create(
|
|
84
|
+
wrapComponent({
|
|
85
|
+
auth: {
|
|
86
|
+
account: {
|
|
87
|
+
user: {
|
|
88
|
+
permissions: {
|
|
89
|
+
smart_script_for_multi_unit: true,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
);
|
|
82
96
|
});
|
|
83
97
|
const instance = tree.root;
|
|
84
98
|
const WrapHeaderScrollables = instance.findAllByType(WrapHeaderScrollable);
|
|
@@ -151,13 +165,23 @@ describe('Test MultiUnits', () => {
|
|
|
151
165
|
mock.onGet(API.AUTOMATE.GET_MULTI_UNITS()).reply(200, response);
|
|
152
166
|
useRoute.mockReturnValue({
|
|
153
167
|
params: {
|
|
154
|
-
|
|
155
|
-
unitName: null,
|
|
156
|
-
unit: null,
|
|
168
|
+
unit: {},
|
|
157
169
|
},
|
|
158
170
|
});
|
|
159
171
|
await act(async () => {
|
|
160
|
-
tree = await create(
|
|
172
|
+
tree = await create(
|
|
173
|
+
wrapComponent({
|
|
174
|
+
auth: {
|
|
175
|
+
account: {
|
|
176
|
+
user: {
|
|
177
|
+
permissions: {
|
|
178
|
+
smart_script_for_multi_unit: true,
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
})
|
|
184
|
+
);
|
|
161
185
|
});
|
|
162
186
|
const instance = tree.root;
|
|
163
187
|
const WrapHeaderScrollables = instance.findAllByType(WrapHeaderScrollable);
|
|
@@ -180,9 +204,102 @@ describe('Test MultiUnits', () => {
|
|
|
180
204
|
});
|
|
181
205
|
});
|
|
182
206
|
|
|
207
|
+
it('create new smart but reach max', async () => {
|
|
208
|
+
const response = [
|
|
209
|
+
{
|
|
210
|
+
id: 1,
|
|
211
|
+
user: 223,
|
|
212
|
+
type: 'one_tap',
|
|
213
|
+
config: null,
|
|
214
|
+
value: null,
|
|
215
|
+
activate_at: '2021-09-22T14:16:54Z',
|
|
216
|
+
condition: null,
|
|
217
|
+
script: {
|
|
218
|
+
id: 1,
|
|
219
|
+
name: 'Tap to up down up down coc coc coc coc coc',
|
|
220
|
+
icon: null,
|
|
221
|
+
icon_kit:
|
|
222
|
+
'https://eoh-gateway-backend.eoh.io/_Category_Sensors_Type_Garage_door_StyleC_olorful.png',
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
];
|
|
226
|
+
mock.onGet(API.UNIT.AUTOMATE(1)).reply(200, response);
|
|
227
|
+
useRoute.mockReturnValue({
|
|
228
|
+
params: {
|
|
229
|
+
unit: { id: 1 },
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
await act(async () => {
|
|
233
|
+
tree = await create(
|
|
234
|
+
wrapComponent({
|
|
235
|
+
auth: {
|
|
236
|
+
account: {
|
|
237
|
+
user: {
|
|
238
|
+
permissions: {
|
|
239
|
+
max_automations_per_unit: 0,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
})
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
const instance = tree.root;
|
|
248
|
+
const itemAddNews = instance.findAllByType(ItemAddNew);
|
|
249
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
250
|
+
await act(async () => {
|
|
251
|
+
itemAddNews[0].props.onAddNew();
|
|
252
|
+
});
|
|
253
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
254
|
+
expect(spyToastError).toBeCalledWith(
|
|
255
|
+
getTranslate('en', 'reach_max_automations_per_unit')
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('create new smart multi unit but missing permission', async () => {
|
|
260
|
+
mock.onGet(API.UNIT.AUTOMATE(1)).reply(200, []);
|
|
261
|
+
useRoute.mockReturnValue({
|
|
262
|
+
params: {
|
|
263
|
+
isMultiUnits: true,
|
|
264
|
+
unitName: null,
|
|
265
|
+
unit: null,
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
await act(async () => {
|
|
269
|
+
tree = await create(
|
|
270
|
+
wrapComponent({
|
|
271
|
+
auth: {
|
|
272
|
+
account: {
|
|
273
|
+
user: {
|
|
274
|
+
permissions: {
|
|
275
|
+
smart_script_for_multi_unit: false,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
})
|
|
281
|
+
);
|
|
282
|
+
});
|
|
283
|
+
const instance = tree.root;
|
|
284
|
+
const itemAddNews = instance.findAllByType(ItemAddNew);
|
|
285
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
286
|
+
await act(async () => {
|
|
287
|
+
itemAddNews[0].props.onAddNew();
|
|
288
|
+
});
|
|
289
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
290
|
+
expect(spyToastError).toBeCalledWith(
|
|
291
|
+
getTranslate('en', 'no_permission_smart_script_for_multi_unit')
|
|
292
|
+
);
|
|
293
|
+
});
|
|
294
|
+
|
|
183
295
|
it('Test is not multi unit', async () => {
|
|
184
296
|
useRoute.mockReturnValue({
|
|
185
|
-
params: {
|
|
297
|
+
params: {
|
|
298
|
+
unit: {
|
|
299
|
+
id: 1,
|
|
300
|
+
name: '',
|
|
301
|
+
},
|
|
302
|
+
},
|
|
186
303
|
});
|
|
187
304
|
await act(async () => {
|
|
188
305
|
tree = await create(wrapComponent());
|
|
@@ -13,11 +13,13 @@ import { AccessibilityLabel } from '../../../configs/Constants';
|
|
|
13
13
|
import api from '../../../utils/Apis/axios';
|
|
14
14
|
import { API } from '../../../configs';
|
|
15
15
|
import { useNavigation } from '@react-navigation/native';
|
|
16
|
+
import { getTranslate } from '../../../utils/I18n';
|
|
17
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
16
18
|
|
|
17
19
|
const mock = new MockAdapter(api.axiosInstance);
|
|
18
20
|
|
|
19
|
-
const wrapComponent = () => (
|
|
20
|
-
<SCProvider initState={mockSCStore(
|
|
21
|
+
const wrapComponent = (storeData = {}) => (
|
|
22
|
+
<SCProvider initState={mockSCStore(storeData)}>
|
|
21
23
|
<Automate />
|
|
22
24
|
</SCProvider>
|
|
23
25
|
);
|
|
@@ -79,7 +81,19 @@ describe('Test Automate', () => {
|
|
|
79
81
|
mock.onGet(API.AUTOMATE.GET_SMART()).reply(200, response.data);
|
|
80
82
|
|
|
81
83
|
await act(async () => {
|
|
82
|
-
tree = await create(
|
|
84
|
+
tree = await create(
|
|
85
|
+
wrapComponent({
|
|
86
|
+
auth: {
|
|
87
|
+
account: {
|
|
88
|
+
user: {
|
|
89
|
+
permissions: {
|
|
90
|
+
smart_script_for_multi_unit: true,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
);
|
|
83
97
|
});
|
|
84
98
|
|
|
85
99
|
const instance = tree.root;
|
|
@@ -100,6 +114,44 @@ describe('Test Automate', () => {
|
|
|
100
114
|
});
|
|
101
115
|
});
|
|
102
116
|
|
|
117
|
+
it('onPress onAddNew but reach limit', async () => {
|
|
118
|
+
mock.onGet(API.AUTOMATE.GET_SMART()).reply(200, [
|
|
119
|
+
{
|
|
120
|
+
type: 'MultiUnit',
|
|
121
|
+
unit_id: 1,
|
|
122
|
+
automates: [],
|
|
123
|
+
},
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
await act(async () => {
|
|
127
|
+
tree = await create(
|
|
128
|
+
wrapComponent({
|
|
129
|
+
auth: {
|
|
130
|
+
account: {
|
|
131
|
+
user: {
|
|
132
|
+
permissions: {
|
|
133
|
+
max_automations_per_unit: 0,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const instance = tree.root;
|
|
143
|
+
|
|
144
|
+
const itemAddNew = instance.findByType(ItemAddNew);
|
|
145
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
146
|
+
await act(async () => {
|
|
147
|
+
itemAddNew.props.onAddNew(1, []);
|
|
148
|
+
});
|
|
149
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
150
|
+
expect(spyToastError).toBeCalledWith(
|
|
151
|
+
getTranslate('en', 'reach_max_automations_per_unit')
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
|
|
103
155
|
it('Test success get Automate onPressItem to ScriptDetail', async () => {
|
|
104
156
|
const response = {
|
|
105
157
|
status: 200,
|
|
@@ -193,10 +245,7 @@ describe('Test Automate', () => {
|
|
|
193
245
|
});
|
|
194
246
|
|
|
195
247
|
expect(mockedNavigate).toBeCalledWith(Routes.MultiUnits, {
|
|
196
|
-
|
|
197
|
-
unitName: '',
|
|
198
|
-
unit: { id: undefined },
|
|
199
|
-
isOwner: true,
|
|
248
|
+
unit: { id: undefined, name: '' },
|
|
200
249
|
});
|
|
201
250
|
|
|
202
251
|
mockedNavigate.mockClear();
|
|
@@ -205,10 +254,45 @@ describe('Test Automate', () => {
|
|
|
205
254
|
});
|
|
206
255
|
|
|
207
256
|
expect(mockedNavigate).toBeCalledWith(Routes.MultiUnits, {
|
|
208
|
-
|
|
209
|
-
unitName: 'La Vida',
|
|
210
|
-
unit: { id: 3 },
|
|
211
|
-
isOwner: false,
|
|
257
|
+
unit: { id: 3, name: 'La Vida' },
|
|
212
258
|
});
|
|
213
259
|
});
|
|
260
|
+
|
|
261
|
+
it('onPress onAddNew multi unit script but missing permission', async () => {
|
|
262
|
+
mock.onGet(API.AUTOMATE.GET_SMART()).reply(200, [
|
|
263
|
+
{
|
|
264
|
+
type: 'MultiUnit',
|
|
265
|
+
unit_id: null,
|
|
266
|
+
automates: [],
|
|
267
|
+
},
|
|
268
|
+
]);
|
|
269
|
+
|
|
270
|
+
await act(async () => {
|
|
271
|
+
tree = await create(
|
|
272
|
+
wrapComponent({
|
|
273
|
+
auth: {
|
|
274
|
+
account: {
|
|
275
|
+
user: {
|
|
276
|
+
permissions: {
|
|
277
|
+
smart_script_for_multi_unit: false,
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
})
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const instance = tree.root;
|
|
287
|
+
|
|
288
|
+
const itemAddNew = instance.findByType(ItemAddNew);
|
|
289
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
290
|
+
await act(async () => {
|
|
291
|
+
itemAddNew.props.onAddNew(1, []);
|
|
292
|
+
});
|
|
293
|
+
expect(mockedNavigate).not.toBeCalled();
|
|
294
|
+
expect(spyToastError).toBeCalledWith(
|
|
295
|
+
getTranslate('en', 'no_permission_smart_script_for_multi_unit')
|
|
296
|
+
);
|
|
297
|
+
});
|
|
214
298
|
});
|
|
@@ -25,7 +25,8 @@ import ItemAddNew from '../../commons/Device/ItemAddNew';
|
|
|
25
25
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
26
26
|
import { useGetIdUser } from '../../hooks/Common';
|
|
27
27
|
import { AccessibilityLabel, UNIT_TYPES } from '../../configs/Constants';
|
|
28
|
-
import { keyExtractor } from '../../utils/Utils';
|
|
28
|
+
import { keyExtractor, ToastBottomHelper } from '../../utils/Utils';
|
|
29
|
+
import { useBackendPermission } from '../../utils/Permission/backend';
|
|
29
30
|
|
|
30
31
|
const Automate = () => {
|
|
31
32
|
const t = useTranslations();
|
|
@@ -38,6 +39,7 @@ const Automate = () => {
|
|
|
38
39
|
const starredScriptIds = useSCContextSelector(
|
|
39
40
|
(state) => state.automate.starredScriptIds
|
|
40
41
|
);
|
|
42
|
+
const permissions = useBackendPermission();
|
|
41
43
|
|
|
42
44
|
const sortedAutomateData = useMemo(() => {
|
|
43
45
|
return automatesData.map((unit) => {
|
|
@@ -64,35 +66,57 @@ const Automate = () => {
|
|
|
64
66
|
}, 1000);
|
|
65
67
|
}, []);
|
|
66
68
|
|
|
67
|
-
const onPressItem = (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
const onPressItem = useCallback(
|
|
70
|
+
(item) => {
|
|
71
|
+
navigate(Routes.UnitStack, {
|
|
72
|
+
screen: Routes.ScriptDetail,
|
|
73
|
+
params: {
|
|
74
|
+
id: item?.id,
|
|
75
|
+
closeScreen: currentRouteName,
|
|
76
|
+
preAutomate: item, // pre-loaded automate data
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
[currentRouteName, navigate]
|
|
81
|
+
);
|
|
77
82
|
|
|
78
|
-
const handleOnAddNew = (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
const handleOnAddNew = useCallback(
|
|
84
|
+
(id, automates) => {
|
|
85
|
+
if (id) {
|
|
86
|
+
// only limit per unit
|
|
87
|
+
if (permissions.max_automations_per_unit <= automates.length) {
|
|
88
|
+
ToastBottomHelper.error(t('reach_max_automations_per_unit'));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
} else if (!permissions?.smart_script_for_multi_unit) {
|
|
92
|
+
ToastBottomHelper.error(t('no_permission_smart_script_for_multi_unit'));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
navigate(Routes.UnitStack, {
|
|
96
|
+
screen: Routes.AddUnknownTypeSmart,
|
|
97
|
+
params: {
|
|
98
|
+
automate: { unit: id },
|
|
99
|
+
closeScreen: currentRouteName,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
[
|
|
104
|
+
currentRouteName,
|
|
105
|
+
navigate,
|
|
106
|
+
permissions?.max_automations_per_unit,
|
|
107
|
+
permissions?.smart_script_for_multi_unit,
|
|
108
|
+
t,
|
|
109
|
+
]
|
|
110
|
+
);
|
|
87
111
|
|
|
88
|
-
const onPressArrowRight = (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
const onPressArrowRight = useCallback(
|
|
113
|
+
(unit) => {
|
|
114
|
+
navigate(Routes.MultiUnits, {
|
|
115
|
+
unit,
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
[navigate]
|
|
119
|
+
);
|
|
96
120
|
|
|
97
121
|
const renderItem = useCallback(
|
|
98
122
|
({ item = {} }) => {
|
|
@@ -112,7 +136,7 @@ const Automate = () => {
|
|
|
112
136
|
isOwner={isOwner}
|
|
113
137
|
automate={automate}
|
|
114
138
|
wrapSyles={styles.wrapAutomateItem}
|
|
115
|
-
onPressItem={onPressItem(automate, unit_id, type, isOwner)}
|
|
139
|
+
onPressItem={() => onPressItem(automate, unit_id, type, isOwner)}
|
|
116
140
|
/>
|
|
117
141
|
);
|
|
118
142
|
};
|
|
@@ -124,12 +148,12 @@ const Automate = () => {
|
|
|
124
148
|
{type === UNIT_TYPES.MULTI ? t('multi_unit') : unit_name}
|
|
125
149
|
</Text>
|
|
126
150
|
<TouchableOpacity
|
|
127
|
-
onPress={
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
151
|
+
onPress={() =>
|
|
152
|
+
onPressArrowRight({
|
|
153
|
+
name: unit_name,
|
|
154
|
+
id: unit_id,
|
|
155
|
+
})
|
|
156
|
+
}
|
|
133
157
|
style={styles.arrowRightButton}
|
|
134
158
|
accessibilityLabel={AccessibilityLabel.ICON_ARROW_RIGHT}
|
|
135
159
|
>
|
|
@@ -143,7 +167,7 @@ const Automate = () => {
|
|
|
143
167
|
renderItem={renderItemAutomate}
|
|
144
168
|
showsHorizontalScrollIndicator={false}
|
|
145
169
|
contentContainerStyle={styles.contentContainerStyle2}
|
|
146
|
-
ListFooterComponent={renderListFooterComponent(unit_id)}
|
|
170
|
+
ListFooterComponent={renderListFooterComponent(unit_id, automates)}
|
|
147
171
|
scrollIndicatorInsets={{ right: 1 }}
|
|
148
172
|
/>
|
|
149
173
|
</View>
|
|
@@ -153,10 +177,10 @@ const Automate = () => {
|
|
|
153
177
|
[sortedAutomateData]
|
|
154
178
|
);
|
|
155
179
|
|
|
156
|
-
const renderListFooterComponent = (unitId) => (
|
|
180
|
+
const renderListFooterComponent = (unitId, automates) => (
|
|
157
181
|
<ItemAddNew
|
|
158
182
|
title={t('add_new')}
|
|
159
|
-
onAddNew={handleOnAddNew(unitId)}
|
|
183
|
+
onAddNew={() => handleOnAddNew(unitId, automates)}
|
|
160
184
|
wrapStyle={styles.addNewItem}
|
|
161
185
|
/>
|
|
162
186
|
);
|