@eohjsc/react-native-smart-city 0.7.30 → 0.7.32

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.
@@ -10,10 +10,10 @@
10
10
  // original location:
11
11
  // - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/app/build.gradle
12
12
 
13
- def DEFAULT_COMPILE_SDK_VERSION = 32
14
- def DEFAULT_BUILD_TOOLS_VERSION = '28.0.3'
13
+ def DEFAULT_COMPILE_SDK_VERSION = 34
14
+ def DEFAULT_BUILD_TOOLS_VERSION = '34.0.0'
15
15
  def DEFAULT_MIN_SDK_VERSION = 24
16
- def DEFAULT_TARGET_SDK_VERSION = 32
16
+ def DEFAULT_TARGET_SDK_VERSION = 34
17
17
 
18
18
  def safeExtGet(prop, fallback) {
19
19
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
@@ -111,12 +111,12 @@ afterEvaluate { project ->
111
111
  }
112
112
 
113
113
  task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
114
- classifier = 'javadoc'
114
+ archiveClassifier = 'javadoc'
115
115
  from androidJavadoc.destinationDir
116
116
  }
117
117
 
118
118
  task androidSourcesJar(type: Jar) {
119
- classifier = 'sources'
119
+ archiveClassifier = 'sources'
120
120
  from android.sourceSets.main.java.srcDirs
121
121
  include '**/*.java'
122
122
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eohjsc/react-native-smart-city",
3
3
  "title": "React Native Smart Home",
4
- "version": "0.7.30",
4
+ "version": "0.7.32",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -149,6 +149,8 @@ const API = {
149
149
  CREATE_AUTOMATE_V2: () => '/property_manager/automate_v2/',
150
150
  UPDATE_AUTOMATE: (automateId) =>
151
151
  `/property_manager/automate/${automateId}/`,
152
+ ENABLE_NOTIFICATIONS: (automateId) =>
153
+ `/property_manager/automate/${automateId}/enable_notifications/`,
152
154
  ENABLE_SCRIPT: (automateId) =>
153
155
  `/property_manager/automate/${automateId}/enable_script/`,
154
156
  STAR_SCRIPT: (id) => `/property_manager/automate/${id}/star_script/`,
@@ -262,6 +262,8 @@ export default {
262
262
  AUTOMATE_SELECT_CONDITION: 'AUTOMATE_SELECT_CONDITION',
263
263
  AUTOMATE_DELETE_CONDITION: 'AUTOMATE_DELETE_CONDITION',
264
264
  AUTOMATE_NUMBER_CONDITION: 'AUTOMATE_NUMBER_CONDITION',
265
+ SWITCH_ENABLE_SCRIPT: 'SWITCH_ENABLE_SCRIPT',
266
+ SWITCH_ENABLE_NOTIFICATIONS_SCRIPT: 'SWITCH_ENABLE_NOTIFICATIONS_SCRIPT',
265
267
 
266
268
  // Parking input maunaly spot
267
269
  PARKING_SPOT_INFO_BUTTON: 'PARKING_SPOT_INFO_BUTTON',
@@ -10,6 +10,7 @@ import BottomButtonView from '../../../commons/BottomButtonView';
10
10
  import { Search } from '../../../commons/DevMode';
11
11
  import { convertToSlug } from '../../../utils/Functions/Search';
12
12
  import { axiosGet } from '../../../utils/Apis/axios';
13
+ import { shortEmailName } from '../../../utils/Utils';
13
14
  import { API, Colors } from '../../../configs';
14
15
  import { useSCContextSelector } from '../../../context';
15
16
  import { Image } from 'react-native';
@@ -111,7 +112,7 @@ const ReceiverSelect = ({
111
112
  );
112
113
 
113
114
  const RowMember = memo(({ member, index, onValueChange }) => {
114
- const { id, name, avatar, share_id, label, invalidLabel, disabled } =
115
+ const { id, name, email, avatar, share_id, label, invalidLabel, disabled } =
115
116
  member;
116
117
  const [role, roleColor] = useMemo(() => {
117
118
  if (!share_id) {
@@ -124,8 +125,9 @@ const ReceiverSelect = ({
124
125
  }, [share_id, id]);
125
126
 
126
127
  const firstWordsInName = useMemo(() => {
127
- return name.charAt();
128
- }, [name]);
128
+ const nameTemp = name || shortEmailName(email);
129
+ return nameTemp?.charAt() || '';
130
+ }, [email, name]);
129
131
 
130
132
  const circleColor = arrColor[index % arrColor.length];
131
133
 
@@ -8,7 +8,7 @@ import { useTranslations } from '../../../hooks/Common/useTranslations';
8
8
  import BottomButtonView from '../../../commons/BottomButtonView';
9
9
  import { axiosPut, axiosGet } from '../../../utils/Apis/axios';
10
10
  import { API, Colors } from '../../../configs';
11
- import { ToastBottomHelper } from '../../../utils/Utils';
11
+ import { ToastBottomHelper, shortEmailName } from '../../../utils/Utils';
12
12
  import Routes from '../../../utils/Route';
13
13
  import moment from 'moment';
14
14
  import CheckBox from '@react-native-community/checkbox';
@@ -110,8 +110,9 @@ const UpdateReceiverEmailScript = ({ route }) => {
110
110
  }, [share_id, id]);
111
111
 
112
112
  const firstWordsInName = useMemo(() => {
113
- return name.charAt();
114
- }, [name]);
113
+ const nameTemp = name || shortEmailName(email);
114
+ return nameTemp?.charAt() || '';
115
+ }, [email, name]);
115
116
 
116
117
  const circleColor = arrColor[index % arrColor.length];
117
118
 
@@ -8,7 +8,7 @@ import { useTranslations } from '../../../hooks/Common/useTranslations';
8
8
  import BottomButtonView from '../../../commons/BottomButtonView/index.js';
9
9
  import { axiosPut, axiosGet } from '../../../utils/Apis/axios.js';
10
10
  import { API, Colors } from '../../../configs/index.js';
11
- import { ToastBottomHelper } from '../../../utils/Utils.js';
11
+ import { ToastBottomHelper, shortEmailName } from '../../../utils/Utils.js';
12
12
  import Routes from '../../../utils/Route/index.js';
13
13
  import moment from 'moment';
14
14
  import CheckBox from '@react-native-community/checkbox';
@@ -96,7 +96,7 @@ const UpdateReceiverSmsScript = ({ route }) => {
96
96
  );
97
97
 
98
98
  const RowMember = memo(({ member, index, onValueChange }) => {
99
- const { id, name, avatar, share_id, phone_number } = member;
99
+ const { id, name, email, avatar, share_id, phone_number } = member;
100
100
  const [role, roleColor] = useMemo(() => {
101
101
  if (!share_id) {
102
102
  return [t('owner'), Colors.Primary];
@@ -108,8 +108,9 @@ const UpdateReceiverSmsScript = ({ route }) => {
108
108
  }, [share_id, id]);
109
109
 
110
110
  const firstWordsInName = useMemo(() => {
111
- return name.charAt();
112
- }, [name]);
111
+ const nameTemp = name || shortEmailName(email);
112
+ return nameTemp?.charAt() || '';
113
+ }, [email, name]);
113
114
 
114
115
  const circleColor = arrColor[index % arrColor.length];
115
116
 
@@ -53,7 +53,7 @@ export default StyleSheet.create({
53
53
  flexDirection: 'row',
54
54
  alignItems: 'center',
55
55
  justifyContent: 'space-between',
56
- marginBottom: 7,
56
+ marginBottom: 16,
57
57
  },
58
58
  editButton: {
59
59
  height: 40,
@@ -3,7 +3,7 @@ import { BackHandler, Platform } from 'react-native';
3
3
  import { create, act } from 'react-test-renderer';
4
4
  import Toast from 'react-native-toast-message';
5
5
  import { useNavigation } from '@react-navigation/native';
6
- import { Switch, TouchableOpacity } from 'react-native';
6
+ import { TouchableOpacity } from 'react-native';
7
7
  import MockAdapter from 'axios-mock-adapter';
8
8
 
9
9
  import { SCProvider } from '../../../../context';
@@ -92,6 +92,7 @@ describe('Test ScriptDetail', () => {
92
92
  script: {
93
93
  name: 'name',
94
94
  enable: true,
95
+ enabled_notifications: true,
95
96
  },
96
97
  },
97
98
  },
@@ -920,7 +921,9 @@ describe('Test ScriptDetail', () => {
920
921
  tree = await create(wrapComponent(route));
921
922
  });
922
923
  const instance = tree.root;
923
- const switchButton = instance.findByType(Switch);
924
+ const switchButton = instance.findByProps({
925
+ accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_SCRIPT,
926
+ });
924
927
  await act(async () => {
925
928
  await switchButton.props.onValueChange(false);
926
929
  });
@@ -939,6 +942,116 @@ describe('Test ScriptDetail', () => {
939
942
  el.type === TouchableOpacity
940
943
  );
941
944
  expect(buttonEditScript).toHaveLength(0);
945
+ expect(mock.history.post).toHaveLength(1);
946
+ expect(mock.history.post[0].url).toEqual(API.AUTOMATE.ENABLE_SCRIPT(1));
947
+ });
948
+
949
+ it('test press disable script false', async () => {
950
+ mock.onGet(API.AUTOMATE.SCRIPT_ITEMS(1)).reply(200, data);
951
+ mock.onPost(API.AUTOMATE.ENABLE_SCRIPT(1)).reply(400);
952
+ await act(async () => {
953
+ tree = await create(wrapComponent(route));
954
+ });
955
+ const instance = tree.root;
956
+ const switchButton = instance.findByProps({
957
+ accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_SCRIPT,
958
+ });
959
+ expect(switchButton.props.value).toBeTruthy();
960
+
961
+ await act(async () => {
962
+ await switchButton.props.onValueChange(false);
963
+ });
964
+ expect(switchButton.props.value).toBeTruthy();
965
+ const buttonAddScript = instance.findAll(
966
+ (el) =>
967
+ el.props.accessibilityLabel ===
968
+ AccessibilityLabel.BUTTON_ADD_SCRIPT_ACTION &&
969
+ el.type === TouchableOpacity
970
+ );
971
+ expect(buttonAddScript).toHaveLength(1);
972
+
973
+ const buttonEditScript = instance.findAll(
974
+ (el) =>
975
+ el.props.accessibilityLabel ===
976
+ AccessibilityLabel.BUTTON_EDIT_SCRIPT_ACTION &&
977
+ el.type === TouchableOpacity
978
+ );
979
+ expect(buttonEditScript).toHaveLength(1);
980
+ expect(mock.history.post).toHaveLength(1);
981
+ expect(mock.history.post[0].url).toEqual(API.AUTOMATE.ENABLE_SCRIPT(1));
982
+ });
983
+
984
+ it('test enable notifications for script', async () => {
985
+ mock.onGet(API.AUTOMATE.SCRIPT_ITEMS(1)).reply(200, data);
986
+ mock.onPost(API.AUTOMATE.ENABLE_NOTIFICATIONS(1)).reply(200);
987
+ await act(async () => {
988
+ tree = await create(wrapComponent(route));
989
+ });
990
+
991
+ const instance = tree.root;
992
+ const enableNotificationsSwitch = instance.findByProps({
993
+ accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT,
994
+ });
995
+ expect(enableNotificationsSwitch.props.value).toBeTruthy();
996
+
997
+ await act(async () => {
998
+ await enableNotificationsSwitch.props.onValueChange(false);
999
+ });
1000
+ expect(enableNotificationsSwitch.props.value).toBeFalsy();
1001
+ expect(mock.history.post).toHaveLength(1);
1002
+ expect(mock.history.post[0].url).toEqual(
1003
+ API.AUTOMATE.ENABLE_NOTIFICATIONS(1)
1004
+ );
1005
+ });
1006
+
1007
+ it('test enable notifications for script fail', async () => {
1008
+ mock.onGet(API.AUTOMATE.SCRIPT_ITEMS(1)).reply(200, data);
1009
+ mock.onPost(API.AUTOMATE.ENABLE_NOTIFICATIONS(1)).reply(400);
1010
+ await act(async () => {
1011
+ tree = await create(wrapComponent(route));
1012
+ });
1013
+
1014
+ const instance = tree.root;
1015
+ const enableNotificationsSwitch = instance.findByProps({
1016
+ accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT,
1017
+ });
1018
+ expect(enableNotificationsSwitch.props.value).toBeTruthy();
1019
+
1020
+ await act(async () => {
1021
+ await enableNotificationsSwitch.props.onValueChange(false);
1022
+ });
1023
+ expect(enableNotificationsSwitch.props.value).toBeTruthy();
1024
+ expect(mock.history.post).toHaveLength(1);
1025
+ expect(mock.history.post[0].url).toEqual(
1026
+ API.AUTOMATE.ENABLE_NOTIFICATIONS(1)
1027
+ );
1028
+ });
1029
+
1030
+ it('test hidden enable notifications switch when disable script', async () => {
1031
+ mock.onGet(API.AUTOMATE.SCRIPT_ITEMS(1)).reply(200, data);
1032
+ mock.onPost(API.AUTOMATE.ENABLE_SCRIPT(1)).reply(200, data);
1033
+ await act(async () => {
1034
+ tree = await create(wrapComponent(route));
1035
+ });
1036
+
1037
+ const instance = tree.root;
1038
+ const enableSwitch = instance.findByProps({
1039
+ accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_SCRIPT,
1040
+ });
1041
+ let enableNotificationsSwitchs = instance.findAllByProps({
1042
+ accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT,
1043
+ });
1044
+ expect(enableSwitch.props.value).toBeTruthy();
1045
+ expect(enableNotificationsSwitchs).toHaveLength(1);
1046
+
1047
+ await act(async () => {
1048
+ await enableSwitch.props.onValueChange(false);
1049
+ });
1050
+ expect(enableSwitch.props.value).toBeFalsy();
1051
+ enableNotificationsSwitchs = instance.findAllByProps({
1052
+ accessibilityLabel: AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT,
1053
+ });
1054
+ expect(enableNotificationsSwitchs).toHaveLength(0);
942
1055
  });
943
1056
 
944
1057
  it('test press add action reach limit', async () => {
@@ -1068,6 +1181,7 @@ describe('Test ScriptDetail', () => {
1068
1181
  script: {
1069
1182
  name: 'name',
1070
1183
  enable: true,
1184
+ enabled_notifications: true,
1071
1185
  },
1072
1186
  };
1073
1187
  route.params = {
@@ -108,10 +108,14 @@ const ScriptDetail = ({ route }) => {
108
108
  chip_local_control,
109
109
  is_local_control,
110
110
  chip_id_local_control,
111
+ enabled_notifications,
111
112
  } = script || {};
112
113
 
113
114
  const [local_control, setLocalControl] = useState({});
114
115
  const [enableScript, setEnableScript] = useState(enable);
116
+ const [enableNotificationsScript, setEnableNotificationsScript] = useState(
117
+ enabled_notifications
118
+ );
115
119
  const [listMenuItemCondition, setListMenuItemCondition] = useState([]);
116
120
  const [isShowAddCondition, setIsShowAddCondition] = useState(false);
117
121
  const permissions = useBackendPermission();
@@ -289,6 +293,7 @@ const ScriptDetail = ({ route }) => {
289
293
  if (success) {
290
294
  setAutomate(automateData);
291
295
  setEnableScript(automateData.script.enable);
296
+ setEnableNotificationsScript(automateData.script.enabled_notifications);
292
297
  setNeedAllCondition(automateData.is_need_all_conditions);
293
298
  }
294
299
  }, [automateId]);
@@ -330,7 +335,6 @@ const ScriptDetail = ({ route }) => {
330
335
 
331
336
  const onChangeSwitch = useCallback(
332
337
  async (checked) => {
333
- setEnableScript(checked);
334
338
  const { success } = await axiosPost(
335
339
  API.AUTOMATE.ENABLE_SCRIPT(automateId),
336
340
  {
@@ -338,8 +342,24 @@ const ScriptDetail = ({ route }) => {
338
342
  }
339
343
  );
340
344
  if (success) {
341
- ToastBottomHelper.success(t('update_successfully'));
342
345
  setEnableScript(checked);
346
+ ToastBottomHelper.success(t('update_successfully'));
347
+ }
348
+ },
349
+ [automateId, t]
350
+ );
351
+
352
+ const onChangeNotificationsSwitch = useCallback(
353
+ async (checked) => {
354
+ const { success } = await axiosPost(
355
+ API.AUTOMATE.ENABLE_NOTIFICATIONS(automateId),
356
+ {
357
+ enable: checked,
358
+ }
359
+ );
360
+ if (success) {
361
+ setEnableNotificationsScript(checked);
362
+ ToastBottomHelper.success(t('update_successfully'));
343
363
  }
344
364
  },
345
365
  [automateId, t]
@@ -680,7 +700,25 @@ const ScriptDetail = ({ route }) => {
680
700
  <Text type="H3" semibold>
681
701
  {t('enable_this_script')}
682
702
  </Text>
683
- <Switch value={enableScript} onValueChange={onChangeSwitch} />
703
+ <Switch
704
+ value={enableScript}
705
+ onValueChange={onChangeSwitch}
706
+ accessibilityLabel={AccessibilityLabel.SWITCH_ENABLE_SCRIPT}
707
+ />
708
+ </View>
709
+ )}
710
+ {!!enableScript && (
711
+ <View style={styles.row}>
712
+ <Text type="H3" semibold>
713
+ {t('enable_notifications_for_this_script')}
714
+ </Text>
715
+ <Switch
716
+ value={enableNotificationsScript}
717
+ onValueChange={onChangeNotificationsSwitch}
718
+ accessibilityLabel={
719
+ AccessibilityLabel.SWITCH_ENABLE_NOTIFICATIONS_SCRIPT
720
+ }
721
+ />
684
722
  </View>
685
723
  )}
686
724
  {renderLocalControl}
@@ -1109,6 +1109,7 @@ export default {
1109
1109
  automate: 'Automate',
1110
1110
  smart: 'Smart',
1111
1111
  enable_this_script: 'Enable this script',
1112
+ enable_notifications_for_this_script: 'Enable notifications for this script',
1112
1113
  local_control: 'Local control',
1113
1114
  local_control_update_success: 'Local control update successful',
1114
1115
  choose_gateway: 'Choose gateway',
@@ -1118,6 +1118,7 @@ export default {
1118
1118
  automate: 'Tự động',
1119
1119
  smart: 'Thông minh',
1120
1120
  enable_this_script: 'Kích hoạt kịch bản này',
1121
+ enable_notifications_for_this_script: 'Bật thông báo cho kịch bản này',
1121
1122
  local_control: 'Điều khiển tại biên',
1122
1123
  local_control_update_success: 'Cập nhật điều khiển tại biên thành công',
1123
1124
  choose_gateway: 'Chọn gateway',