@sapui5/sap.suite.ui.generic.template 1.127.3 → 1.127.5
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/sap/suite/ui/generic/template/.library +1 -1
- package/src/sap/suite/ui/generic/template/AnalyticalListPage/controller/VisualFilterDialogController.js +1 -1
- package/src/sap/suite/ui/generic/template/AnalyticalListPage/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/ObjectPage/templateSpecificPreparationHelper.js +90 -42
- package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/genericUtilities/utils.js +48 -39
- package/src/sap/suite/ui/generic/template/lib/AppComponent.js +1 -1
- package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +42 -5
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es.properties +2 -2
- package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +1 -1
- package/src/sap/suite/ui/generic/template/library.js +1 -1
package/package.json
CHANGED
|
@@ -424,7 +424,7 @@ sap.ui.define([
|
|
|
424
424
|
oVisualFilterDialogModelClone.setProperty('/filterCompList/' + idx + '/searchVisible', bVisible);
|
|
425
425
|
oVisualFilterDialogModel.setData(oVisualFilterDialogModelClone.getData());
|
|
426
426
|
//update config object when VFConfig model is updated
|
|
427
|
-
this.oConfig = oVisualFilterDialogModel.
|
|
427
|
+
this.oConfig = oVisualFilterDialogModel.getData();
|
|
428
428
|
//to enable Restore button on change of chart type, sort order, measure field and show in filter bar changes
|
|
429
429
|
this.oState.oSmartFilterbar._oVariantManagement.currentVariantSetModified(true);
|
|
430
430
|
},
|
|
@@ -331,62 +331,110 @@ sap.ui.define([
|
|
|
331
331
|
fnSetTargetEntity(oEntitySet);
|
|
332
332
|
|
|
333
333
|
var bToolbarButtonVisible = fnGetTableToolbarButtonVisibility(oSettings, oEntitySet, oResult.type);
|
|
334
|
-
var oPathforRestriction = fnGetRestrictionForPasteButton(oEntitySet);
|
|
335
334
|
/* Workaround fix for non draft apps with no section settings defined in the manifest. In UI5v1.93, the export to excel button is displayed by default because of a code gap in
|
|
336
335
|
FE which later got fixed with a change related to paste button in UI5v1.96 wherein the export button is not displayed by default. This looks like a regression issue to customers
|
|
337
336
|
for which we have provided this temporary solution which shall get removed soon. */
|
|
338
337
|
oResult.bExportToExcel = (!oComponentUtils.isDraftEnabled() && !oSettings.sections) || bToolbarButtonVisible;
|
|
339
|
-
|
|
340
|
-
var sPathforRestriction = "";
|
|
341
|
-
if (oPathforRestriction.insertable) {
|
|
342
|
-
sPathforRestriction = "${" + oPathforRestriction.insertable + "}";
|
|
343
|
-
}
|
|
344
|
-
if (oPathforRestriction.updatable) {
|
|
345
|
-
sPathforRestriction = sPathforRestriction ? sPathforRestriction + " || ${" + oPathforRestriction.updatable + "}" : "${" + oPathforRestriction.updatable + "}";
|
|
346
|
-
}
|
|
347
|
-
sPathforRestriction = sPathforRestriction && "(" + sPathforRestriction + ")";
|
|
348
|
-
oResult.vShowPasteButton = bToolbarButtonVisible ? "{= ${ui>/editable} && " + sPathforRestriction + "}" : false;
|
|
349
|
-
} else {
|
|
350
|
-
oResult.vShowPasteButton = bToolbarButtonVisible ? "{ui>/editable}" : false;
|
|
351
|
-
}
|
|
352
|
-
|
|
338
|
+
oResult.vShowPasteButton = fnGetPasteButtonVisibility(oEntitySet);
|
|
353
339
|
oResult.commandExecution = fnGetTableLevelStandardActions();
|
|
354
340
|
oResult.persistencyKeyState = fnGetPersistencyKeyState(oSettings.tableSettings);
|
|
355
341
|
|
|
356
342
|
return oResult;
|
|
357
343
|
}
|
|
358
|
-
|
|
359
|
-
// fnGetRestrictionForPasteButton return object contains updatable and insertable restriction for the given Entity Set.
|
|
360
|
-
function fnGetRestrictionForPasteButton(oEntitySet) {
|
|
361
|
-
var oLeadingEntitySet = oMetaModel.getODataEntitySet(sLeadingEntitySet);
|
|
362
|
-
var oInsertableAnnotation, oUpdatableAnnotation;
|
|
363
|
-
|
|
364
|
-
var oInsertRestrictionSetViaNavRestrictions = AnnotationHelper.handleNavigationRestrictions(oMetaModel, oLeadingEntitySet, oEntitySet, 'Insertable');
|
|
365
|
-
if (oInsertRestrictionSetViaNavRestrictions) {
|
|
366
|
-
oInsertableAnnotation = oInsertRestrictionSetViaNavRestrictions['Insertable'];
|
|
367
|
-
} else {
|
|
368
|
-
var oSectionInsertRestriction = oEntitySet['Org.OData.Capabilities.V1.InsertRestrictions'];
|
|
369
|
-
oInsertableAnnotation = oSectionInsertRestriction && oSectionInsertRestriction['Insertable'];
|
|
370
|
-
}
|
|
371
344
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
345
|
+
/**
|
|
346
|
+
* Finds out the paste button visibility. It can be visible when,
|
|
347
|
+
* 1. The object page is editable AND
|
|
348
|
+
* 2. Either the table should be insertable OR updatable
|
|
349
|
+
* @param {object} oEntitySet Table's entity set info
|
|
350
|
+
* @returns {boolean|string} Returns a boolean value for visibility or binding expression
|
|
351
|
+
*/
|
|
352
|
+
function fnGetPasteButtonVisibility (oEntitySet) {
|
|
353
|
+
var vInsertRestriction = fnGetRestrictionForPaste(oEntitySet, "Insertable");
|
|
354
|
+
var vUpdateRestriction = fnGetRestrictionForPaste(oEntitySet, "Updatable");
|
|
355
|
+
|
|
356
|
+
// If both the restrictions are boolean and falsy, paste button should be hidden.
|
|
357
|
+
// Hence, immediately return false
|
|
358
|
+
if (!(vInsertRestriction || vUpdateRestriction)) {
|
|
359
|
+
return false;
|
|
378
360
|
}
|
|
379
361
|
|
|
380
|
-
|
|
381
|
-
|
|
362
|
+
// As we are going to combine insertable and updatable by OR condition, if there's any boolean value "true" found, it will be always evaluated to true
|
|
363
|
+
// Hence, no need to include them in the binding and just return the binding expression "ui>/editable"
|
|
364
|
+
var bAnyBooleanTrue = [vInsertRestriction, vUpdateRestriction].some(function (vRestriction) {
|
|
365
|
+
return vRestriction === true;
|
|
366
|
+
});
|
|
367
|
+
if (bAnyBooleanTrue) {
|
|
368
|
+
return "{ui>/editable}";
|
|
369
|
+
}
|
|
382
370
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
371
|
+
// Now the remaining cases are either
|
|
372
|
+
// 1. Both are path expressions or
|
|
373
|
+
// 2. One path expression and one boolean value "false"
|
|
374
|
+
//
|
|
375
|
+
// While building OR expression, "${expression} || false" will always be evaluated to "${expression}"
|
|
376
|
+
// Hence, we can omit the "false" values and build binding expression with "Path" values
|
|
377
|
+
var sPathRestriction = [vInsertRestriction, vUpdateRestriction].filter(function (vRestriction) {
|
|
378
|
+
return (typeof vRestriction === "string");
|
|
379
|
+
}).map(function (sPath) {
|
|
380
|
+
return "${" + sPath + "}";
|
|
381
|
+
}).join(" || ");
|
|
382
|
+
|
|
383
|
+
// Add "editable" with "path" expression
|
|
384
|
+
return "{= ${ui>/editable} && ( " + sPathRestriction + " )}";
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Checks the navigation restriction on the parent entity set or current entity set
|
|
389
|
+
* and returns the boolean value or path for the restriction
|
|
390
|
+
*
|
|
391
|
+
* 1. If NavigationRestriction is available on parent entity set
|
|
392
|
+
* a. Restricted by boolean value - returns the boolean value
|
|
393
|
+
* b. Restricted by path - Checks the data type of path and returns it
|
|
394
|
+
*
|
|
395
|
+
* 2. If Restriction is available on table's entity set
|
|
396
|
+
* a. Restricted by boolean value - returns the boolean value
|
|
397
|
+
* b. Restricted by path - ignores it
|
|
398
|
+
* Important: Reason for ignoring the path. As path value refers to the individual records on the table, it can't control the whole table's paste functionality
|
|
399
|
+
*
|
|
400
|
+
* 3. If no restriction available, returns true
|
|
401
|
+
*
|
|
402
|
+
* @param {object} oEntitySet Table's entity set info
|
|
403
|
+
* @param {string} sRestrictionType "Insertable" or "Updatable"
|
|
404
|
+
* @returns {boolean|string} Boolean value or path for the restriction
|
|
405
|
+
*/
|
|
406
|
+
function fnGetRestrictionForPaste (oEntitySet, sRestrictionType) {
|
|
407
|
+
var mAnnotation = {
|
|
408
|
+
Insertable: "Org.OData.Capabilities.V1.InsertRestrictions",
|
|
409
|
+
Updatable: "Org.OData.Capabilities.V1.UpdateRestrictions"
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// Navigation restriction on parent entity set
|
|
413
|
+
var oLeadingEntitySet = oMetaModel.getODataEntitySet(sLeadingEntitySet);
|
|
414
|
+
var oNavRestriction = AnnotationHelper.handleNavigationRestrictions(oMetaModel, oLeadingEntitySet, oEntitySet, sRestrictionType);
|
|
415
|
+
var oNavRestrictionAnnotation = oNavRestriction && oNavRestriction[sRestrictionType];
|
|
416
|
+
|
|
417
|
+
// Restriction on table entity set
|
|
418
|
+
var oSectionRestriction = oEntitySet[mAnnotation[sRestrictionType]];
|
|
419
|
+
var oSectionRestrictionAnnotation = oSectionRestriction && oSectionRestriction[sRestrictionType];
|
|
420
|
+
|
|
421
|
+
// Check for navigation restriction
|
|
422
|
+
if (oNavRestrictionAnnotation) {
|
|
423
|
+
if (oNavRestrictionAnnotation.Bool) {
|
|
424
|
+
return oNavRestrictionAnnotation.Bool !== "false";
|
|
425
|
+
} else if (oNavRestrictionAnnotation.Path) {
|
|
426
|
+
var bIsBooleanPath = AnnotationHelper._isPropertyPathBoolean(oMetaModel, oLeadingEntitySet.entityType, oNavRestrictionAnnotation.Path);
|
|
427
|
+
if (!bIsBooleanPath) {
|
|
428
|
+
oLogger.error("Service Broken: Restrictions annotations for entity type " + sLeadingEntitySet + " for section '" + sRestrictionType + "' are invalid.");
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
return oNavRestrictionAnnotation.Path;
|
|
432
|
+
}
|
|
433
|
+
} else if (oSectionRestrictionAnnotation && oSectionRestrictionAnnotation.Bool) {
|
|
434
|
+
return oSectionRestrictionAnnotation.Bool !== "false";
|
|
388
435
|
}
|
|
389
|
-
return
|
|
436
|
+
// If no annotation found, return true
|
|
437
|
+
return true;
|
|
390
438
|
}
|
|
391
439
|
|
|
392
440
|
// used in the process of determining the visibility of export to excel and paste button depending on certain restrictions/conditions.
|
|
@@ -2,50 +2,59 @@
|
|
|
2
2
|
sap.ui.define([], function() {
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
var bIsIcon = sImageUrl.startsWith("sap-icon://");
|
|
14
|
-
if (bSuppressIcons && bIsIcon) {
|
|
15
|
-
return "";
|
|
16
|
-
}
|
|
17
|
-
if (bIsIcon || sImageUrl.startsWith("/") || sImageUrl.startsWith("http://") || sImageUrl.startsWith("https://")) {
|
|
18
|
-
return sImageUrl; // Absolute URL, nothing has to be changed
|
|
19
|
-
}
|
|
20
|
-
// Relative URL, has to be adjusted
|
|
21
|
-
return sap.ui.require.toUrl(sAppComponentName.replace(/\./g, "/")) + "/" + sImageUrl; //replacing dots by slashes before calling sap.ui.require.toUrl method. com.xyz.abc to com/xyz/abc
|
|
5
|
+
// If images are included in the UI app they need to specify the path relatively (e.g. images/image.jpg) to support
|
|
6
|
+
// different platforms like ABAP and HCP. The relative path has to be used because the absolute paths differ from platform
|
|
7
|
+
// to platform. The rule is if the image url doesn't start with a / or sap-icon:// or http(s):// then it's a relative url and the absolute
|
|
8
|
+
// path has to be added by the framework. This path can be retrieved with sap.ui.require.toUrl and the component name.
|
|
9
|
+
function fnAdjustImageUrlPath(sImageUrl, sAppComponentName, bSuppressIcons) {
|
|
10
|
+
if (!sImageUrl) {
|
|
11
|
+
return "";
|
|
22
12
|
}
|
|
13
|
+
var bIsIcon = sImageUrl.startsWith("sap-icon://");
|
|
14
|
+
if (bSuppressIcons && bIsIcon) {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
if (bIsIcon || sImageUrl.startsWith("/") || sImageUrl.startsWith("http://") || sImageUrl.startsWith("https://")) {
|
|
18
|
+
return sImageUrl; // Absolute URL, nothing has to be changed
|
|
19
|
+
}
|
|
20
|
+
// Relative URL, has to be adjusted
|
|
21
|
+
return sap.ui.require.toUrl(sAppComponentName.replace(/\./g, "/")) + "/" + sImageUrl; //replacing dots by slashes before calling sap.ui.require.toUrl method. com.xyz.abc to com/xyz/abc
|
|
22
|
+
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
if (a.length > b.length) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
return a.every(function(entry) {
|
|
43
|
-
return b.includes(entry);
|
|
44
|
-
});
|
|
24
|
+
// Function check is B array values is a subset of A array values.
|
|
25
|
+
// A = [], B = ["1", "2", "3"] -> true
|
|
26
|
+
// A = ["4"], B = ["1", "2", "3"] -> false
|
|
27
|
+
// A = ["1"], B = ["1", "2", "3"] -> true
|
|
28
|
+
// A = ["1", "3"], B = ["1", "2", "3"] -> true
|
|
29
|
+
// A = ["3", "2", "1"], B = ["1", "2", "3"] -> true
|
|
30
|
+
// A = ["1", "4"], B = ["1", "2", "3"] -> false
|
|
31
|
+
// A = ["1", "2", "3", "4"], B = ["1", "2", "3"] -> false
|
|
32
|
+
function fnIsASubsetOfB(a, b) {
|
|
33
|
+
if (a === b) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
if (!a || !b) {
|
|
37
|
+
return false;
|
|
45
38
|
}
|
|
39
|
+
if (a.length > b.length) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return a.every(function(entry) {
|
|
43
|
+
return b.includes(entry);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Function to check if a string contains only ASCII characters only. Regular expression
|
|
48
|
+
// used consider [SPACE] to ~ (ASCII 32 to 126) printable ASCII characters. Control characters
|
|
49
|
+
// (ASCII 0 to 31) and DEL character (ASCII 127) are not considered as they could not be part
|
|
50
|
+
// of the string. Method returns true if the string contains only ASCII characters else false.
|
|
51
|
+
function fnIsASCII(sString) {
|
|
52
|
+
return /^[\x20-\x7E]*$/.test(sString);
|
|
53
|
+
}
|
|
46
54
|
|
|
47
55
|
return {
|
|
48
56
|
adjustImageUrlPath: fnAdjustImageUrlPath,
|
|
49
|
-
isASubsetOfB: fnIsASubsetOfB
|
|
57
|
+
isASubsetOfB: fnIsASubsetOfB,
|
|
58
|
+
isASCII: fnIsASCII
|
|
50
59
|
};
|
|
51
60
|
});
|
|
@@ -943,7 +943,7 @@ sap.ui.define([
|
|
|
943
943
|
* @public
|
|
944
944
|
* @extends sap.ui.core.UIComponent
|
|
945
945
|
* @author SAP SE
|
|
946
|
-
* @version 1.127.
|
|
946
|
+
* @version 1.127.5
|
|
947
947
|
* @name sap.suite.ui.generic.template.lib.AppComponent
|
|
948
948
|
*/
|
|
949
949
|
var oAppComponent = UIComponent.extend("sap.suite.ui.generic.template.lib.AppComponent", {
|
|
@@ -27,9 +27,38 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
27
27
|
'sap/ui/performance/trace/FESRHelper',
|
|
28
28
|
"sap/ui/core/CustomData",
|
|
29
29
|
"sap/m/VBox",
|
|
30
|
-
"sap/
|
|
31
|
-
], function(
|
|
32
|
-
|
|
30
|
+
"sap/suite/ui/generic/template/genericUtilities/utils"
|
|
31
|
+
], function(
|
|
32
|
+
BaseObject,
|
|
33
|
+
Event,
|
|
34
|
+
MessageBox,
|
|
35
|
+
Sorter,
|
|
36
|
+
controlHelper,
|
|
37
|
+
expressionHelper,
|
|
38
|
+
testableHelper,
|
|
39
|
+
oDataModelHelper,
|
|
40
|
+
JSONModel,
|
|
41
|
+
AnnotationHelper,
|
|
42
|
+
Controller,
|
|
43
|
+
FeLogger,
|
|
44
|
+
MessageUtils,
|
|
45
|
+
SideEffectUtil,
|
|
46
|
+
extend,
|
|
47
|
+
isEmptyObject,
|
|
48
|
+
deepExtend,
|
|
49
|
+
CRUDHelper,
|
|
50
|
+
XMLView,
|
|
51
|
+
FormatUtil,
|
|
52
|
+
FileUploaderParameter,
|
|
53
|
+
IconPool,
|
|
54
|
+
ServiceContainer,
|
|
55
|
+
ContactCardDetailHelper,
|
|
56
|
+
mLibrary,
|
|
57
|
+
Button,
|
|
58
|
+
FESRHelper,
|
|
59
|
+
CustomData,
|
|
60
|
+
VBox,
|
|
61
|
+
genericUtils) {
|
|
33
62
|
"use strict";
|
|
34
63
|
|
|
35
64
|
var oLogger = new FeLogger("lib.CommonEventHandlers").getLogger();
|
|
@@ -1927,7 +1956,11 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
1927
1956
|
}
|
|
1928
1957
|
if (oFileUploader.FUEl.files[0].name){
|
|
1929
1958
|
var headerParameterContentDispositionToken = new FileUploaderParameter();
|
|
1930
|
-
var
|
|
1959
|
+
var sUploadedFileName = oFileUploader.FUEl.files[0].name;
|
|
1960
|
+
if (!genericUtils.isASCII(sUploadedFileName)) {
|
|
1961
|
+
sUploadedFileName = encodeURIComponent(sUploadedFileName);
|
|
1962
|
+
}
|
|
1963
|
+
var fileName = "filename=" + sUploadedFileName;
|
|
1931
1964
|
headerParameterContentDispositionToken.setName("Content-Disposition");
|
|
1932
1965
|
headerParameterContentDispositionToken.setValue(fileName);
|
|
1933
1966
|
oFileUploader.addHeaderParameter(headerParameterContentDispositionToken);
|
|
@@ -1987,11 +2020,15 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
1987
2020
|
oPrivModel.setProperty("/generic/controlProperties/" + "fileUploader/" + sEntitySet, oFileUploaderSettings);
|
|
1988
2021
|
}
|
|
1989
2022
|
|
|
1990
|
-
|
|
2023
|
+
// URLEncoded filenames are decoded by Chrome, Firefox browsers but Safari doesn't do this automatically.
|
|
2024
|
+
// Therefore, FE decodes it on our side & ensure actual file name is used for further processing.
|
|
2025
|
+
oFileUploaderSettings.fileName = decodeURIComponent(oEvent.mParameters.fileName);
|
|
1991
2026
|
var fileType = oEvent.mParameters.requestHeaders.find(function(requestHeader) {
|
|
1992
2027
|
if (requestHeader.name === "Content-Type") {
|
|
1993
2028
|
return requestHeader;
|
|
1994
2029
|
}
|
|
2030
|
+
|
|
2031
|
+
return undefined;
|
|
1995
2032
|
});
|
|
1996
2033
|
oFileUploaderSettings.fileType = fileType.value;
|
|
1997
2034
|
var bIcon = IconPool.getIconForMimeType(fileType.value);
|
|
@@ -25,9 +25,9 @@ ST_SUCCESS=Con \u00E9xito
|
|
|
25
25
|
|
|
26
26
|
ST_CHANGES_APPLIED=Se han aplicado las modificaciones
|
|
27
27
|
|
|
28
|
-
DATA_LOSS_MESSAGE=
|
|
28
|
+
DATA_LOSS_MESSAGE=Sus entradas se perder\u00E1n al abandonar esta p\u00E1gina.
|
|
29
29
|
|
|
30
|
-
DATA_LOSS_GENERAL_MESSAGE=Si
|
|
30
|
+
DATA_LOSS_GENERAL_MESSAGE=Si contin\u00FAa se perder\u00E1n sus entradas.
|
|
31
31
|
|
|
32
32
|
PROCEED=Continuar
|
|
33
33
|
|
|
@@ -3149,7 +3149,7 @@ sap.ui.define(["sap/ui/base/Object",
|
|
|
3149
3149
|
* @param {sap.suite.ui.generic.template.lib.AppComponent} oAppComponent The AppComponent instance
|
|
3150
3150
|
* @public
|
|
3151
3151
|
* @extends sap.ui.base.Object
|
|
3152
|
-
* @version 1.127.
|
|
3152
|
+
* @version 1.127.5
|
|
3153
3153
|
* @since 1.30.0
|
|
3154
3154
|
* @alias sap.suite.ui.generic.template.lib.NavigationController
|
|
3155
3155
|
*/
|