@sapui5/sap.suite.ui.generic.template 1.130.1 → 1.131.0

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.
Files changed (109) hide show
  1. package/package.json +1 -1
  2. package/src/sap/suite/ui/generic/template/.library +1 -1
  3. package/src/sap/suite/ui/generic/template/AnalyticalListPage/controller/ControllerImplementation.js +5 -1
  4. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_da.properties +2 -2
  5. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_de.properties +2 -2
  6. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_ko.properties +2 -2
  7. package/src/sap/suite/ui/generic/template/AnalyticalListPage/manifest.json +1 -1
  8. package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
  9. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_de.properties +1 -1
  10. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_es.properties +1 -1
  11. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_hr.properties +1 -1
  12. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_ko.properties +2 -2
  13. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_sl.properties +1 -1
  14. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_th.properties +1 -1
  15. package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
  16. package/src/sap/suite/ui/generic/template/ListReport/view/fragments/SmartTable.fragment.xml +6 -3
  17. package/src/sap/suite/ui/generic/template/ObjectPage/controller/RelatedAppsHandler.js +21 -9
  18. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n_ar.properties +2 -2
  19. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n_da.properties +1 -1
  20. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n_es.properties +4 -4
  21. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n_ko.properties +1 -1
  22. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n_th.properties +1 -1
  23. package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
  24. package/src/sap/suite/ui/generic/template/ObjectPage/view/fragments/Sections.fragment.xml +13 -13
  25. package/src/sap/suite/ui/generic/template/ObjectPage/view/fragments/SmartForm.fragment.xml +5 -5
  26. package/src/sap/suite/ui/generic/template/ObjectPage/view/fragments/SmartTable.fragment.xml +6 -3
  27. package/src/sap/suite/ui/generic/template/QuickCreate/i18n/i18n_fr_CA.properties +1 -1
  28. package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
  29. package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
  30. package/src/sap/suite/ui/generic/template/designtime/controls/DynamicPage.designtime.js +317 -0
  31. package/src/sap/suite/ui/generic/template/designtime/controls/SmartTable.designtime.js +121 -32
  32. package/src/sap/suite/ui/generic/template/designtime/floorplans/AnalyticalListPage.designtime.js +13 -6
  33. package/src/sap/suite/ui/generic/template/designtime/floorplans/ListReport.designtime.js +12 -5
  34. package/src/sap/suite/ui/generic/template/designtime/floorplans/ObjectPage.designtime.js +13 -5
  35. package/src/sap/suite/ui/generic/template/designtime/utils/designtimeHelper.js +53 -81
  36. package/src/sap/suite/ui/generic/template/designtime/utils/designtimeUtils.js +63 -21
  37. package/src/sap/suite/ui/generic/template/detailTemplates/i18n/i18n_es.properties +1 -1
  38. package/src/sap/suite/ui/generic/template/fragments/MessagePopover.fragment.xml +1 -1
  39. package/src/sap/suite/ui/generic/template/fragments/SmartFormDataField.fragment.xml +1 -1
  40. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartTableChartCommon.js +1 -1
  41. package/src/sap/suite/ui/generic/template/js/AnnotationHelper.js +6 -5
  42. package/src/sap/suite/ui/generic/template/js/AnnotationHelperStreamSupport.js +21 -8
  43. package/src/sap/suite/ui/generic/template/lib/AppComponent.js +227 -5
  44. package/src/sap/suite/ui/generic/template/lib/ComponentUtils.js +100 -67
  45. package/src/sap/suite/ui/generic/template/lib/FlexibleColumnLayoutHandler.js +9 -4
  46. package/src/sap/suite/ui/generic/template/lib/RetryAfterHandler.js +154 -54
  47. package/src/sap/suite/ui/generic/template/lib/SideEffectUtil.js +22 -7
  48. package/src/sap/suite/ui/generic/template/lib/StableIdDefinition.js +4 -1
  49. package/src/sap/suite/ui/generic/template/lib/TemplateAssembler.js +39 -41
  50. package/src/sap/suite/ui/generic/template/lib/ViewCreationHelper.js +39 -0
  51. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +2 -6
  52. package/src/sap/suite/ui/generic/template/lib/i18n/i18n.properties +20 -1
  53. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ar.properties +32 -0
  54. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_bg.properties +34 -2
  55. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ca.properties +32 -0
  56. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cnr.properties +32 -0
  57. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cs.properties +32 -0
  58. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cy.properties +32 -0
  59. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_da.properties +33 -1
  60. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_de.properties +34 -2
  61. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_el.properties +32 -0
  62. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en.properties +32 -0
  63. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_GB.properties +32 -0
  64. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_US_saprigi.properties +33 -0
  65. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es.properties +36 -4
  66. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es_MX.properties +32 -0
  67. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_et.properties +32 -0
  68. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fi.properties +32 -0
  69. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr.properties +32 -0
  70. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr_CA.properties +34 -2
  71. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hi.properties +33 -1
  72. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hr.properties +32 -0
  73. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hu.properties +34 -2
  74. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_id.properties +33 -1
  75. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_it.properties +32 -0
  76. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_iw.properties +33 -1
  77. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ja.properties +32 -0
  78. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_kk.properties +32 -0
  79. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ko.properties +34 -2
  80. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lt.properties +32 -0
  81. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lv.properties +32 -0
  82. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_mk.properties +32 -0
  83. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ms.properties +33 -1
  84. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_nl.properties +32 -0
  85. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_no.properties +32 -0
  86. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pl.properties +32 -0
  87. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt.properties +32 -0
  88. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt_PT.properties +32 -0
  89. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ro.properties +32 -0
  90. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ru.properties +32 -0
  91. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sh.properties +32 -0
  92. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sk.properties +32 -0
  93. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sl.properties +32 -0
  94. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sr.properties +32 -0
  95. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sv.properties +33 -1
  96. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_th.properties +32 -0
  97. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_tr.properties +32 -0
  98. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_uk.properties +32 -0
  99. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_vi.properties +32 -0
  100. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_CN.properties +32 -0
  101. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_TW.properties +32 -0
  102. package/src/sap/suite/ui/generic/template/lib/insights/InsightsCardHelper.js +39 -23
  103. package/src/sap/suite/ui/generic/template/lib/insights/InsightsFECardProvider.js +11 -2
  104. package/src/sap/suite/ui/generic/template/lib/multipleViews/MultipleTablesModeHelper.js +2 -1
  105. package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +95 -95
  106. package/src/sap/suite/ui/generic/template/library.js +1 -1
  107. package/src/sap/suite/ui/generic/template/listTemplates/fragments/DetailSmartTable.fragment.xml +6 -3
  108. package/src/sap/suite/ui/generic/template/themes/sap_horizon/ObjectPage.less +6 -0
  109. package/src/sap/suite/ui/generic/template/themes/sap_horizon_dark/ObjectPage.less +6 -0
@@ -7,14 +7,24 @@ sap.ui.define(["sap/ui/base/Object",
7
7
  "sap/m/Text",
8
8
  "sap/m/library",
9
9
  "sap/ui/core/format/DateFormat",
10
- "sap/ui/core/library"
11
- ], function (BaseObject, extend, Formatting, Button, Dialog, ProgressIndicator, Text, mobileLibrary, DateFormat, coreLibrary) {
10
+ "sap/ui/core/library",
11
+ "sap/ui/core/Messaging",
12
+ "sap/ui/model/Filter",
13
+ "sap/ui/model/FilterOperator",
14
+ "sap/ui/model/json/JSONModel",
15
+ "sap/suite/ui/generic/template/genericUtilities/testableHelper"
16
+ ], function (BaseObject, extend, Formatting, Button, Dialog, ProgressIndicator, Text, mobileLibrary, DateFormat, coreLibrary,
17
+ Messaging, Filter, FilterOperator, JSONModel, testableHelper) {
12
18
  "use strict";
13
19
 
14
20
  /**
15
- * This class handles the 503 error (service unavailable) response which includes "retry-after" header.
21
+ * This class handles the 503 error (service unavailable) response.
16
22
  *
17
- * Whenever the server throws 503 error, it adds "retry-after" (minimum number of seconds need to be waited before the next server call)
23
+ * ///////////////////////////////////////
24
+ * Response includes "retry-after" header
25
+ * ///////////////////////////////////////
26
+ *
27
+ * When the server throws 503 error, sometimes it adds "retry-after" (minimum number of seconds need to be waited before the next server call)
18
28
  * to the response header. The model intercepts the error and invokes the error handler registered on "setRetryAfterHandler" method.
19
29
  * Model takes care of converting the "retry-after" value to the Date value.
20
30
  *
@@ -25,14 +35,27 @@ sap.ui.define(["sap/ui/base/Object",
25
35
  * - If the promise is rejected, it aborts the batch call.
26
36
  *
27
37
  * Cases handled here.
28
- * 1. When the retry after time is <= 600 seconds
38
+ * 1. When the retry after time is < 5 seconds
39
+ * Shows the busy indicator until retry after time and retries the HTTP request automatically
40
+ * 2. When the retry after time is <= 600 seconds
29
41
  * Opens up dialog with progress indicator. Once the retry after time is reached, the dialog is automatically closed and the action is retried.
30
- * 2. When the retry after time is same day as today, navigate to message page
42
+ * 3. When the retry after time is more than 600 seconds, navigate to message page
43
+ * a. If the service will be available on same day as today
31
44
  * (Message shown: We expect it to be available again at 7:00 AM)
32
- * 3. When the retry after time is some other day in the same year, navigate to message page
45
+ * b. If the service will be available on different day in the same year
33
46
  * (Message shown: We expect it to be available again on October 1 at 7:00 AM)
34
- * 4. When the retry after time is in different year (Possibly Jan 01 of next year), navigate to message page
47
+ * c. If the service will be available on next year (Possibly Jan 01 of next year)
35
48
  * (Message shown: We expect it to be available again on January 1, 2022 at 12:00 PM)
49
+ *
50
+ * ///////////////////////////////////////////
51
+ * Response doesn't have "retry-after" header
52
+ * ///////////////////////////////////////////
53
+ *
54
+ * When the 503 error response doesn't have "retry-after" header, the model adds a new technical message to the message model.
55
+ * The message's technical detail contains "statusCode" value as 503.
56
+ *
57
+ * If such message is added to message model, we need to intercept that and navigate to message page.
58
+ * The message page would show the message "Please try again later."
36
59
  */
37
60
 
38
61
  function getMethods(oTemplateContract, oAppComponent) {
@@ -47,9 +70,12 @@ sap.ui.define(["sap/ui/base/Object",
47
70
  // Shortcut for getting i18n text
48
71
  var getText = oTemplateContract.getText;
49
72
 
50
- // Get user's time pattern. If no pattern available on user's settings, use "HH:mm a"
51
- var sTimePattern = Formatting.getTimePattern("short") || "HH:mm a";
73
+ // Get user's time pattern. If no pattern available on user's settings, use "hh:mm a"
74
+ var sTimePattern = Formatting.getTimePattern("short") || "hh:mm a";
52
75
 
76
+ /**
77
+ * Section handles retry-after header
78
+ */
53
79
  function fnRetryAfterHandler (oError) {
54
80
  var sErrorMessage = oError.message;
55
81
  var sAdditionalMessage;
@@ -64,19 +90,29 @@ sap.ui.define(["sap/ui/base/Object",
64
90
  var iDifferenceInSeconds = Math.ceil(iDifferenceInMilliSeconds / 1000);
65
91
 
66
92
  return new Promise((fnResolve, fnReject) => {
67
- var sMessagePageText = null,
68
- sMessagePageDescription = null;
69
- if (iDifferenceInSeconds <= 600) {
70
- fnOpenAutoRetryDialog(oRetryAfterDate.getTime(), iDifferenceInSeconds, fnResolve, fnReject);
93
+ if (iDifferenceInSeconds < 5) {
94
+ fnShowBusyIndicator(iDifferenceInSeconds, fnResolve);
95
+ } else if (iDifferenceInSeconds <= 600) {
96
+ fnOpenAutoRetryDialog(oNow, oRetryAfterDate, iDifferenceInSeconds, sAdditionalMessage, fnResolve, fnReject);
71
97
  } else {
72
- sMessagePageText = getText("ST_GENERIC_503_SERVICE_UNAVAILABLE");
73
- sMessagePageDescription = fnGetErrorMessageWithTime(oNow, oRetryAfterDate);
74
- fnNavigateToMessagePage(sMessagePageText, sMessagePageDescription, sAdditionalMessage);
98
+ fnNavigateToMessagePage(oNow, oRetryAfterDate, sAdditionalMessage);
75
99
  fnReject();
76
100
  }
77
101
  });
78
102
  }
79
103
 
104
+ function fnShowBusyIndicator(iSecondsToRetryAfter, fnResolveRetry) {
105
+ var oBusyHandlingPromise = new Promise(function (fnResolve) {
106
+ setTimeout(function () {
107
+ fnResolve();
108
+ }, iSecondsToRetryAfter * 1000);
109
+ });
110
+ oTemplateContract.oBusyHelper.setBusy(oBusyHandlingPromise, undefined, undefined, true);
111
+ oBusyHandlingPromise.then(function() {
112
+ fnResolveRetry();
113
+ });
114
+ }
115
+
80
116
  /**
81
117
  * Opens the auto retry dialog. Dialog contains
82
118
  * - a text containing the number of seconds remaining to retry the action
@@ -88,45 +124,53 @@ sap.ui.define(["sap/ui/base/Object",
88
124
  *
89
125
  * If the user presses "Cancel" button, it opens a new confirmation dialog which does the following:
90
126
  * - if user presses "Retry" button, it closes the confirmation dialog and opens the auto retry dialog.
91
- * - if user presses "Cancel" button, it rejects the promise for retry (Retry operation will be aborted)
127
+ * - if user presses "Cancel" button, it rejects the promise for retry (Retry operation will be aborted) and navigates to message page
92
128
  *
93
- * @param {number} iRetryAfterTimeInMillis Retry after time in milliseconds
94
- * @param {number} iSecondsToRetryAfter Number of seconds to reach the retry-after time from now
95
- * @param {function} fnResolve Resolve function for retry promise
96
- * @param {function} fnReject Reject function for retry promise
129
+ * @param {Date} oNow Current date
130
+ * @param {Date} oRetryAfterDate Retry after date
131
+ * @param {number} iInitialSecondsToRetryAfter Number of seconds to reach the retry-after time from now
132
+ * @param {function} fnResolveRetry Resolve function for retry promise
133
+ * @param {function} fnRejectRetry Reject function for retry promise
97
134
  */
98
- function fnOpenAutoRetryDialog (iRetryAfterTimeInMillis, iSecondsToRetryAfter, fnResolve, fnReject) {
135
+ function fnOpenAutoRetryDialog (oNow, oRetryAfterDate, iInitialSecondsToRetryAfter, sAdditionalMessage, fnResolveRetry, fnRejectRetry) {
136
+ var iRetryAfterTime = oRetryAfterDate.getTime();
137
+ var oAutoRetryModel = new JSONModel({
138
+ lapsedSeconds: 0
139
+ });
99
140
  var oAutoRetryDialog = null;
100
141
  var oConfirmRetryDialog = null;
101
142
  var oAutoRetryProgressIndicator = null;
102
143
  var oAutoRetryText = null;
144
+ var iAutoRetryInterval = -1;
103
145
 
104
146
  function getAutoRetryText (iSeconds) {
105
147
  return getText("ST_GENERIC_503_SERVICE_UNAVAILABLE") + " " + getText("ST_GENERIC_503_AUTO_RETRY_MSG", [iSeconds]);
106
148
  }
107
-
108
- function updateAutoRetryStatus (iLapsedSeconds) {
109
- var iSecondsUntilRetryAfter = iSecondsToRetryAfter - iLapsedSeconds;
110
- oAutoRetryProgressIndicator.setPercentValue(iLapsedSeconds / iSecondsToRetryAfter * 100);
111
- oAutoRetryText.setText( getAutoRetryText(iSecondsUntilRetryAfter) );
112
-
113
- // Updating the progress indicator state every second
114
- if (iRetryAfterTimeInMillis > new Date().getTime()) {
115
- setTimeout(() => {
116
- updateAutoRetryStatus(iLapsedSeconds + 1);
117
- }, 1000);
118
- }
119
- }
120
-
149
+ // Creating the text (which shows the remaining time) and binding with model
121
150
  oAutoRetryText = new Text({
122
- text: getAutoRetryText(iSecondsToRetryAfter)
151
+ text: getAutoRetryText(iInitialSecondsToRetryAfter)
123
152
  });
124
-
153
+ oAutoRetryText.setModel(oAutoRetryModel);
154
+ oAutoRetryText.bindText({
155
+ path: "/lapsedSeconds",
156
+ formatter: function (iLapsedSeconds) {
157
+ var iSecondsUntilRetryAfter = iInitialSecondsToRetryAfter - iLapsedSeconds;
158
+ return getAutoRetryText(iSecondsUntilRetryAfter);
159
+ }
160
+ });
161
+ // Progress indicator
125
162
  oAutoRetryProgressIndicator = new ProgressIndicator({
126
163
  percentValue : 0,
127
164
  state : ValueState.None
128
165
  });
129
-
166
+ oAutoRetryProgressIndicator.setModel(oAutoRetryModel);
167
+ oAutoRetryProgressIndicator.bindProperty("percentValue", {
168
+ path: "/lapsedSeconds",
169
+ formatter: function (iLapsedSeconds) {
170
+ return iLapsedSeconds / iInitialSecondsToRetryAfter * 100;
171
+ }
172
+ });
173
+ // Auto retry dialog which contains the above text and progress indicator
130
174
  oAutoRetryDialog = new Dialog({
131
175
  type : DialogType.Message,
132
176
  state : ValueState.Warning,
@@ -144,7 +188,7 @@ sap.ui.define(["sap/ui/base/Object",
144
188
  })
145
189
  ]
146
190
  });
147
-
191
+ // Confirmation dialog
148
192
  oConfirmRetryDialog = new Dialog({
149
193
  type : DialogType.Message,
150
194
  state : ValueState.Warning,
@@ -166,38 +210,66 @@ sap.ui.define(["sap/ui/base/Object",
166
210
  text: getText("CANCEL"),
167
211
  press: function () {
168
212
  // Abort retry and close the confirmation dialog
169
- fnReject(new Error("Request(s) canceled by user"));
213
+ fnRejectRetry(new Error("Request(s) canceled by user"));
170
214
  oConfirmRetryDialog.close();
215
+ // Clear the interval for updating the auto-retry model
216
+ clearInterval(iAutoRetryInterval);
217
+ // Navigate to message page
218
+ fnNavigateToMessagePage(oNow, oRetryAfterDate, sAdditionalMessage);
171
219
  }
172
220
  })
173
221
  ]
174
222
  });
175
223
 
176
- //Start the progress indicator and open the auto-retry dialog
177
- updateAutoRetryStatus(0);
224
+ // Open the dialog
178
225
  oAutoRetryDialog.open();
179
- // Once the retry time is reached, resolve the promise which will trigger retry
180
- // and close the dialog.
181
- setTimeout(function () {
182
- fnResolve();
183
- oAutoRetryDialog.close();
184
- }, iSecondsToRetryAfter * 1000);
226
+ // Updates the model on every 1 second
227
+ var iAutoRetryInterval = setInterval(function () {
228
+ var iLapsedSeconds = oAutoRetryModel.getProperty("/lapsedSeconds");
229
+ oAutoRetryModel.setProperty("/lapsedSeconds", iLapsedSeconds + 1);
230
+ // When the retry after time is reached
231
+ // 1. Clear the interval
232
+ // 2. Resolve the promise to retry the request
233
+ // 3. Close the auto retry dialog
234
+ if (new Date().getTime() > iRetryAfterTime) {
235
+ clearInterval(iAutoRetryInterval);
236
+ fnResolveRetry();
237
+ oAutoRetryDialog.close();
238
+ }
239
+ }, 1000);
185
240
  }
186
241
 
187
- function fnNavigateToMessagePage (sText, sDescription, sAdditionalMessage) {
242
+ /**
243
+ * This function navigates the user to message page.
244
+ * - The message page's text is a constant
245
+ * - The description is calculated based on the retry after time
246
+ *
247
+ * @param {Date} oNow Current date
248
+ * @param {Date} oRetryAfterDate Retry after date
249
+ * @param {string} sAdditionalMessage Additional message to be shown below the description
250
+ */
251
+ function fnNavigateToMessagePage (oNow, oRetryAfterDate, sAdditionalMessage) {
188
252
  var aAdditionalContent = [];
189
253
  if (sAdditionalMessage) {
190
254
  aAdditionalContent.push(new Text({text: sAdditionalMessage}));
191
255
  }
256
+
192
257
  oTemplateContract.oNavigationControllerProxy.navigateToMessagePage({
193
- title: getText("ST_GENERIC_ERROR_TITLE"),
194
- text: sText,
195
258
  messageType: IllustratedMessageType.UnableToLoad,
196
- description: sDescription,
259
+ title: getText("ST_GENERIC_ERROR_TITLE"),
260
+ text: getText("ST_GENERIC_503_SERVICE_UNAVAILABLE"),
261
+ description: fnGetErrorMessageWithTime(oNow, oRetryAfterDate),
197
262
  additionalContent: aAdditionalContent
198
263
  });
199
264
  }
200
265
 
266
+ /**
267
+ * It derives the retry after message based on the time difference between the current date and retry after date.
268
+ *
269
+ * @param {Date} oNow Current date
270
+ * @param {Date} oRetryAfterDate Retry after date
271
+ * @returns {string} Message with the retry after date/time
272
+ */
201
273
  function fnGetErrorMessageWithTime (oNow, oRetryAfterDate) {
202
274
  var sResultMessage = null;
203
275
  // Date format varies from case to case
@@ -235,6 +307,34 @@ sap.ui.define(["sap/ui/base/Object",
235
307
  var oModel = oAppComponent.getModel();
236
308
  oModel.setRetryAfterHandler(fnRetryAfterHandler);
237
309
  }
310
+
311
+ /**
312
+ * When the response doesn't have "retry-after" header
313
+ */
314
+ var oMessageModel = Messaging.getMessageModel();
315
+ var a503MessageFilters = [
316
+ new Filter("technical", FilterOperator.EQ, true), // technical message
317
+ new Filter("technicalDetails/statusCode", FilterOperator.EQ, 503) // status code as 503
318
+ ];
319
+ var oMessageListBinding = oMessageModel.bindList("/", null, null, a503MessageFilters);
320
+ oMessageListBinding.attachChange((oEvent) => {
321
+ var oMessageBinding = oEvent.getSource();
322
+ // Navigate to message page when
323
+ // 1. There's exactly one message with the status code 503 (and)
324
+ // 2. There's exactly one message present in the message model
325
+ if (oMessageBinding.getLength() === 1 && oMessageModel.getData()?.length === 1) {
326
+ oTemplateContract.oNavigationControllerProxy.navigateToMessagePage({
327
+ messageType: IllustratedMessageType.UnableToLoad,
328
+ title: getText("ST_GENERIC_ERROR_TITLE"),
329
+ text: getText("ST_GENERIC_503_SERVICE_UNAVAILABLE"),
330
+ description: getText("ST_GENERIC_503_RETRY_MSG_TIME_UNKNOWN")
331
+ });
332
+ }
333
+ });
334
+
335
+ /* eslint-disable */
336
+ testableHelper.testable(fnGetErrorMessageWithTime, "fnGetErrorMessageWithTime");
337
+ /* eslint-enable */
238
338
 
239
339
  return {
240
340
  registerRetryAfterHandler: fnRegisterRetryAfterHandler
@@ -138,11 +138,14 @@ sap.ui.define(["sap/suite/ui/generic/template/js/AnnotationHelper",
138
138
  * Returns the EntitySet name, EntityType name, PropertyName for a given link field
139
139
  * @param {sap.ui.model.odata.ODataMetaModel.EntitySet} oEntitySet
140
140
  * @param {object} oTarget
141
+ * @param {string} sFieldName
141
142
  */
142
- function fnGetPropsForLinkFields (oEntitySet, oTarget) {
143
- var sLinkProperty = oTarget && oTarget.Value && oTarget.Value.Path;
144
- if (!sLinkProperty) {
145
- return null;
143
+ function fnGetPropsForLinkFields (oEntitySet, oTarget, sFieldName) {
144
+ var sLinkProperty;
145
+ if (oTarget && oTarget.Value && oTarget.Value.Path){
146
+ sLinkProperty = oTarget.Value.Path;
147
+ } else {
148
+ sLinkProperty = oTarget.Target.AnnotationPath.split("/")[0] + "/" + sFieldName;
146
149
  }
147
150
  var oCustomData = {
148
151
  "sEntitySetName": oEntitySet.name,
@@ -174,6 +177,7 @@ sap.ui.define(["sap/suite/ui/generic/template/js/AnnotationHelper",
174
177
  return;
175
178
  }
176
179
 
180
+ var oControl = oLink;
177
181
  var oEntityType = oMetaModel.getODataEntityType(sEntityTypeName);
178
182
  var oEntitySet = oMetaModel.getODataEntitySet(sEntitySetName);
179
183
  var oProperty = metadataAnalyser.getPropertyMetadata(oMetaModel, sEntityTypeName, sLinkProperty);
@@ -186,9 +190,20 @@ sap.ui.define(["sap/suite/ui/generic/template/js/AnnotationHelper",
186
190
  }
187
191
  };
188
192
 
189
- //The method SharedUtil.applyFieldGroupIDs takes in the control and its metadata, reads the Side Effect annotations configured for it
190
- //and assigns the fieldGroupID accordingly.
191
- SharedUtil.applyFieldGroupIDs(oLink, oMetaData);
193
+ if (sLinkProperty.includes("/")){
194
+ while (!oControl.isA("sap.ui.comp.smartform.Group")) {
195
+ oControl = oControl.getParent();
196
+ }
197
+ //The method SharedUtil.applyFieldGroupIDs takes in the control and its metadata
198
+ //It then reads the Side Effect annotations configured for it, calculates fieldGroupIds and assigns them to the field
199
+
200
+ //For navigation path link fields, we pass the oLink's parent Group control's binding context when calculating the fieldGroupIds
201
+ //This makes sure the calculated fieldGroupIds are consistent with the other source fields
202
+ SharedUtil.applyFieldGroupIDs(oLink, oMetaData, null, oControl.getBindingContext());
203
+ } else {
204
+ //For non navigation path link fields, we just pass the oLink along with its metadata
205
+ SharedUtil.applyFieldGroupIDs(oLink, oMetaData);
206
+ }
192
207
  }
193
208
  }
194
209
 
@@ -524,7 +524,10 @@ sap.ui.define(["sap/suite/ui/generic/template/genericUtilities/FeError"],functio
524
524
  TableColumn: {
525
525
  DataField: {
526
526
  parameters: ["sSmartTableId", "sProperty"],
527
- value: function(oParams){return oParams.sSmartTableId + "-" + oParams.sProperty.replace("/", "_");}
527
+ // '/' is replaced by '_' instead of encoding it to match the logic in the SmartTable
528
+ // replaceAll function must be used to replace all occurrences of '/' in the property name
529
+ // not doing so right now, as it is not breaking anything
530
+ value: function (oParams) { return oParams.sSmartTableId + "-" + oParams.sProperty.replace("/", "_"); }
528
531
  },
529
532
  DataFieldWithNavigationPath: {
530
533
  parameters: ["sSmartTableId", "sProperty", "sTarget"]
@@ -6,25 +6,43 @@
6
6
  // Note that this method cannot be used by any other class.
7
7
  // - getExtensionAPIPromise provides access to the instance of the extensionAPI suitable for a certain control
8
8
 
9
- sap.ui.define(["sap/ui/core/mvc/ControllerExtension",
10
- "sap/ui/core/mvc/OverrideExecution",
11
- "sap/ui/core/mvc/View",
12
- "sap/ui/model/base/ManagedObjectModel",
13
- "sap/suite/ui/generic/template/lib/TemplateViewController",
14
- "sap/suite/ui/generic/template/lib/TemplateComponent",
15
- "sap/suite/ui/generic/template/lib/CRUDManager",
16
- "sap/suite/ui/generic/template/lib/CommonUtils",
17
- "sap/suite/ui/generic/template/lib/ComponentUtils",
18
- "sap/suite/ui/generic/template/lib/CommonEventHandlers",
19
- "sap/suite/ui/generic/template/genericUtilities/testableHelper",
20
- "sap/suite/ui/generic/template/support/lib/CommonMethods",
21
- "sap/suite/ui/generic/template/genericUtilities/FeLogger",
22
- "sap/base/util/deepExtend",
23
- "sap/suite/ui/generic/template/lib/presentationControl/PresentationControlHandlerFactory",
24
- "sap/suite/ui/generic/template/lib/info/InfoObjectHandler",
25
- "sap/m/IllustratedMessageType"
26
- ], function(ControllerExtension, OverrideExecution, View, ManagedObjectModel, TemplateViewController, TemplateComponent, CRUDManager, CommonUtils,
27
- ComponentUtils, CommonEventHandlers, testableHelper, CommonMethods, FeLogger, deepExtend, PresentationControlHandlerFactory, InfoObjectHandler, IllustratedMessageType) {
9
+ sap.ui.define([
10
+ "sap/ui/core/mvc/ControllerExtension",
11
+ "sap/ui/core/mvc/OverrideExecution",
12
+ "sap/ui/core/mvc/View",
13
+ "sap/ui/model/base/ManagedObjectModel",
14
+ "sap/suite/ui/generic/template/lib/TemplateViewController",
15
+ "sap/suite/ui/generic/template/lib/TemplateComponent",
16
+ "sap/suite/ui/generic/template/lib/CRUDManager",
17
+ "sap/suite/ui/generic/template/lib/CommonUtils",
18
+ "sap/suite/ui/generic/template/lib/ComponentUtils",
19
+ "sap/suite/ui/generic/template/lib/CommonEventHandlers",
20
+ "sap/suite/ui/generic/template/genericUtilities/testableHelper",
21
+ "sap/suite/ui/generic/template/genericUtilities/FeLogger",
22
+ "sap/base/util/deepExtend",
23
+ "sap/suite/ui/generic/template/lib/presentationControl/PresentationControlHandlerFactory",
24
+ "sap/suite/ui/generic/template/lib/info/InfoObjectHandler",
25
+ "sap/m/IllustratedMessageType",
26
+ "sap/suite/ui/generic/template/lib/ViewCreationHelper"
27
+ ], function(
28
+ ControllerExtension,
29
+ OverrideExecution,
30
+ View,
31
+ ManagedObjectModel,
32
+ TemplateViewController,
33
+ TemplateComponent,
34
+ CRUDManager,
35
+ CommonUtils,
36
+ ComponentUtils,
37
+ CommonEventHandlers,
38
+ testableHelper,
39
+ FeLogger,
40
+ deepExtend,
41
+ PresentationControlHandlerFactory,
42
+ InfoObjectHandler,
43
+ IllustratedMessageType,
44
+ ViewCreationHelper
45
+ ) {
28
46
  "use strict";
29
47
  var oLogger = new FeLogger("lib.TemplateAssembler").getLogger();
30
48
 
@@ -378,28 +396,8 @@ sap.ui.define(["sap/ui/core/mvc/ControllerExtension",
378
396
  var oComponentRegistryEntry = oComponentData.registryEntry;
379
397
  var oAppRegistryEntry = getAppRegistryEntry(oComponentRegistryEntry.oAppComponent);
380
398
  var oTemplateContract = oAppRegistryEntry.oTemplateContract;
381
- var oTreeNode = oAppRegistryEntry.oTemplateContract.mRoutingTree[oComponentRegistryEntry.route];
382
- oComponentRegistryEntry.viewRegistered = new Promise(function(fnResolve, fnReject) {
383
- // Note: oError is faulty in regular situations
384
- oComponentRegistryEntry.fnViewRegisteredResolve = function(oError){
385
- if (oError){
386
- oComponentRegistryEntry.fnViewRegisteredResolve = Function.prototype;
387
- fnReject(oError);
388
- } else {
389
- delete oComponentRegistryEntry.fnViewRegisteredResolve;
390
- fnResolve();
391
- }
392
- };
393
- });
394
- oComponentRegistryEntry.oViewRenderedPromise = new Promise(function(fnResolve) {
395
- oComponentRegistryEntry.fnViewRenderdResolve = fnResolve;
396
- });
397
- oComponentRegistryEntry.oViewRenderedPromise.then(function () {
398
- // Application status needs to be handled here to support use cases where Diagnostics Tool gets loaded after the app itself.
399
- CommonMethods.setApplicationStatus(CommonMethods.mApplicationStatus.RENDERED);
400
- // When view rendering has finished, publish global event "GetData" at channel "elements".
401
- CommonMethods.publishEvent("elements", "ViewRendered", {});
402
- });
399
+ var oTreeNode = oAppRegistryEntry.oTemplateContract.mRoutingTree[oComponentRegistryEntry.route];
400
+ ViewCreationHelper.initializeViewCreation(oComponentRegistryEntry);
403
401
  oComponentRegistryEntry.componentName = sComponentNameFull;
404
402
  oComponentRegistryEntry.oComponent = this;
405
403
  oComponentRegistryEntry.aKeys = [];
@@ -0,0 +1,39 @@
1
+ sap.ui.define([
2
+ "sap/suite/ui/generic/template/support/lib/CommonMethods"
3
+ ], function(CommonMethods) {
4
+ "use strict";
5
+
6
+ // This class contain methods which plays role in view creation of Template Component.
7
+ return {
8
+ initializeViewCreation: function(oComponentRegistryEntry) {
9
+ // Set the creation view started flag to false, to indicate that the view creation has not started yet.
10
+ oComponentRegistryEntry.createViewStarted = false;
11
+
12
+ // Create a promise for the view registration. This promise will be resolved when the view is registered.
13
+ oComponentRegistryEntry.viewRegistered = new Promise(function(fnResolve, fnReject) {
14
+ // Note: oError is faulty in regular situations
15
+ oComponentRegistryEntry.fnViewRegisteredResolve = function(oError){
16
+ if (oError){
17
+ oComponentRegistryEntry.fnViewRegisteredResolve = Function.prototype;
18
+ fnReject(oError);
19
+ } else {
20
+ delete oComponentRegistryEntry.fnViewRegisteredResolve;
21
+ fnResolve();
22
+ }
23
+ };
24
+ });
25
+
26
+ // Create a promise for the view rendering. This promise will be resolved when the view is rendered.
27
+ oComponentRegistryEntry.oViewRenderedPromise = new Promise(function(fnResolve) {
28
+ oComponentRegistryEntry.fnViewRenderdResolve = fnResolve;
29
+ // Application status needs to be handled here to support use cases where Diagnostics Tool gets loaded after the app itself.
30
+ CommonMethods.setApplicationStatus(CommonMethods.mApplicationStatus.RENDERED);
31
+ // When view rendering has finished, publish global event "GetData" at channel "elements".
32
+ CommonMethods.publishEvent("elements", "ViewRendered", {});
33
+ });
34
+
35
+ // Returns view registered promise as the view creation is completed and process can continue.
36
+ return oComponentRegistryEntry.viewRegistered;
37
+ }
38
+ };
39
+ });
@@ -82,6 +82,7 @@ sap.ui.define([
82
82
  sortable: false,
83
83
  codeList : bIsCodeListRequired,
84
84
  type: sTokenType,
85
+ unit: oProperty["sap:unit"] || "",
85
86
  required: oProperty["sap:required-in-filter"] ? true : false
86
87
  };
87
88
  }
@@ -372,13 +373,8 @@ sap.ui.define([
372
373
  var oSmartFilterbar = oState.oSmartFilterbar;
373
374
  fnValueHelpPromiseResolve = oEvent.getParameter("resolve");
374
375
  oSmartFilterbar.associateValueLists();
375
- var oInputField = oSmartFilterbar.getAllFilterItems().find(function(oFilterItem) {
376
- if (oFilterItem.getName() === oEvent.getParameter("key")) {
377
- return oFilterItem;
378
- }
379
- });
380
376
  try {
381
- oInputField.getControl().fireValueHelpRequest();
377
+ oSmartFilterbar.openValueHelpRequestForFilterItem(oEvent.getParameter("key"));
382
378
  } catch (error) {
383
379
  oLogger.error("Value help cannot be triggered for the field " + oEvent.getParameter("key"));
384
380
  }
@@ -510,9 +510,28 @@ ST_GENERIC_503_RETRY_MSG_SAME_DAY=We expect it to be available again at {0}.
510
510
  ST_GENERIC_503_RETRY_MSG_OTHER_DAY=We expect it to be available again on {0} at {1}.
511
511
 
512
512
  # XMSG: Description of the 503 Error Message Page (Unknown time)
513
- ST_GENERIC_503_RETRY_MSG_TIME_UNKNWON=Please try again later.
513
+ ST_GENERIC_503_RETRY_MSG_TIME_UNKNOWN=Please try again later.
514
514
 
515
515
  #XMSG: Label for the error message provided by server
516
516
  ST_GENERIC_503_SOURCE_MESSAGE=Source message:
517
517
 
518
518
  #---End of final block: texts to be redefined by the application ----------------------------------------
519
+
520
+ #---Texts RTA for Adaptation Projects"----------------------------------------
521
+
522
+ # XTIT: Title text on Configurations dialog for Table
523
+ RTA_CONFIGURATION_TITLE_TABLE=Configure Table
524
+
525
+ # XTIT: Title text on Configurations dialog for List Report
526
+ RTA_CONFIGURATION_TITLE_LIST_REPORT=Configure List Report
527
+
528
+
529
+ # XMSG: Warning message text in Configurations dialog
530
+ RTA_CONFIGURATION_INFO_MESSAGE=Some settings can only be applied to certain table types. Changes will only be visible after the application reloads.
531
+
532
+ # XBUT: Button text for Cancel on Configurations dialog
533
+ RTA_CONFIGURATION_CANCEL=Cancel
534
+
535
+ # XBUT: Button text for Apply on Configurations dialog
536
+ RTA_CONFIGURATION_APPLY=Apply
537
+
@@ -205,6 +205,8 @@ ST_EASY_FILTER_INPUT_PLACEHOLDER=\u0623\u062F\u062E\u0644 \u0627\u0633\u062A\u06
205
205
  ST_EASY_FILTER_GO_BUTTON_TEXT=\u0627\u0646\u062A\u0642\u0627\u0644
206
206
 
207
207
 
208
+ ST_AI_EE_BUTTON_LABEL=\u0625\u0646\u0634\u0627\u0621 \u062A\u0648\u0636\u064A\u062D
209
+
208
210
 
209
211
 
210
212
  ST_GENERIC_DRAFT_LOCKED_BY_USER=\u0642\u0627\u0645 \u0645\u0633\u062A\u062E\u062F\u0645 \u0622\u062E\u0631 \u0628\u062A\u062D\u0631\u064A\u0631 \u0647\u0630\u0627 \u0627\u0644\u0643\u0627\u0626\u0646 \u0628\u062F\u0648\u0646 \u062D\u0641\u0638 \u0627\u0644\u062A\u063A\u064A\u064A\u0631\u0627\u062A\: \n{1} \n\u0641\u064A \u062D\u0627\u0644\u0629 \u0627\u0644\u0645\u062A\u0627\u0628\u0639\u0629\u060C \u0641\u0633\u064A\u062A\u0645 \u0641\u0642\u062F\u0627\u0646 \u0623\u064A \u062A\u063A\u064A\u064A\u0631\u0627\u062A.
@@ -316,3 +318,33 @@ DIALOG_ACTION_BUTTON_NEW_ACTION_FOR_CREATE=\u0645\u062A\u0627\u0628\u0639\u0629
316
318
 
317
319
  CONTENT_SWITCH=\u0645\u0641\u062A\u0627\u062D \u062A\u0628\u062F\u064A\u0644 \u0627\u0644\u0645\u062D\u062A\u0648\u0649
318
320
 
321
+
322
+ ST_GENERIC_503_SERVICE_UNAVAILABLE=\u0639\u0630\u0631\u064B\u0627\u060C \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 \u063A\u064A\u0631 \u0645\u062A\u0648\u0641\u0631\u0629 \u0645\u0624\u0642\u062A\u064B\u0627.
323
+
324
+ ST_GENERIC_503_AUTO_RETRY_MSG=\u0623\u0639\u062F \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u062A\u0644\u0642\u0627\u0626\u064A\u064B\u0627 \u062E\u0644\u0627\u0644 {0} \u0645\u0646 \u0627\u0644\u062B\u0648\u0627\u0646\u064A.
325
+
326
+ ST_GENERIC_503_CANCEL_RETRY=\u0639\u0630\u0631\u064B\u0627\u060C \u0644\u0627 \u062A\u0632\u0627\u0644 \u0647\u0630\u0647 \u0627\u0644\u062E\u062F\u0645\u0629 \u063A\u064A\u0631 \u0645\u062A\u0648\u0641\u0631\u0629. \u0647\u0644 \u062A\u0631\u064A\u062F \u0625\u0639\u0627\u062F\u0629 \u0645\u062D\u0627\u0648\u0644\u0629 \u0627\u0644\u0625\u062C\u0631\u0627\u0621 \u0623\u0648 \u0625\u0644\u063A\u0627\u0624\u0647\u061F
327
+
328
+ RETRY=\u0625\u0639\u0627\u062F\u0629 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629
329
+
330
+ ST_GENERIC_503_RETRY_MSG_SAME_DAY=\u0646\u062A\u0648\u0642\u0639 \u0623\u0646 \u064A\u0643\u0648\u0646 \u0645\u062A\u0648\u0641\u0631\u064B\u0627 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649 \u0641\u064A {0}.
331
+
332
+ ST_GENERIC_503_RETRY_MSG_OTHER_DAY=\u0646\u062A\u0648\u0642\u0639 \u0623\u0646 \u064A\u0643\u0648\u0646 \u0645\u062A\u0648\u0641\u0631\u064B\u0627 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649 \u0641\u064A {0} \u0641\u064A {1}.
333
+
334
+ ST_GENERIC_503_RETRY_MSG_TIME_UNKNOWN=\u0627\u0644\u0631\u062C\u0627\u0621 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649 \u0644\u0627\u062D\u0642\u064B\u0627.
335
+
336
+ ST_GENERIC_503_SOURCE_MESSAGE=\u0631\u0633\u0627\u0644\u0629 \u0627\u0644\u0645\u0635\u062F\u0631\:
337
+
338
+
339
+
340
+ RTA_CONFIGURATION_TITLE_TABLE=\u062A\u0643\u0648\u064A\u0646 \u0627\u0644\u062C\u062F\u0648\u0644
341
+
342
+ RTA_CONFIGURATION_TITLE_LIST_REPORT=\u062A\u0643\u0648\u064A\u0646 \u062A\u0642\u0631\u064A\u0631 \u0627\u0644\u0642\u0627\u0626\u0645\u0629
343
+
344
+
345
+ RTA_CONFIGURATION_INFO_MESSAGE=\u0644\u0627 \u064A\u0645\u0643\u0646 \u062A\u0637\u0628\u064A\u0642 \u0628\u0639\u0636 \u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0625\u0644\u0627 \u0639\u0644\u0649 \u0623\u0646\u0648\u0627\u0639 \u062C\u062F\u0627\u0648\u0644 \u0645\u0639\u064A\u0646\u0629. \u0648\u0644\u0646 \u062A\u0643\u0648\u0646 \u0627\u0644\u062A\u063A\u064A\u064A\u0631\u0627\u062A \u0645\u0631\u0626\u064A\u0629 \u0625\u0644\u0627 \u0628\u0639\u062F \u0625\u0639\u0627\u062F\u0629 \u062A\u062D\u0645\u064A\u0644 \u0627\u0644\u062A\u0637\u0628\u064A\u0642.
346
+
347
+ RTA_CONFIGURATION_CANCEL=\u0625\u0644\u063A\u0627\u0621
348
+
349
+ RTA_CONFIGURATION_APPLY=\u062A\u0637\u0628\u064A\u0642
350
+