@sapui5/sap.ui.export 1.128.0 → 1.130.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.
@@ -2,11 +2,20 @@
2
2
  * SAPUI5
3
3
  * (c) Copyright 2009-2024 SAP SE. All rights reserved.
4
4
  */
5
- sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabilities', 'sap/m/MessageToast', 'sap/ui/core/Core', 'sap/ui/base/EventProvider', 'sap/ui/model/odata/v4/ODataModel', 'sap/ui/util/openWindow'], function(library, ExportUtils, ExportDialog, PDFCapabilities, MessageToast, Core, EventProvider, ODataModel, openWindow) {
6
- 'use strict';
7
-
8
- var Destination = library.Destination;
9
- var FileType = library.FileType;
5
+ sap.ui.define([
6
+ "./library",
7
+ "./ExportUtils",
8
+ "./ExportDialog",
9
+ "./util/PDFCapabilities",
10
+ "sap/m/MessageToast",
11
+ "sap/ui/base/EventProvider",
12
+ "sap/ui/model/odata/v4/ODataModel",
13
+ "sap/ui/util/openWindow"
14
+ ], function(library, ExportUtils, ExportDialog, PDFCapabilities, MessageToast, EventProvider, ODataModel, openWindow) {
15
+ "use strict";
16
+
17
+ const Destination = library.Destination;
18
+ const FileType = library.FileType;
10
19
 
11
20
  /**
12
21
  * Any export-related functionality is encapsulated in the <code>ExportHandler</code> that also stores user settings throughout the session.
@@ -18,16 +27,16 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
18
27
  * @class The <code>sap.ui.export.ExportHandler</code> class allows you to export table data from an SAPUI5 application.
19
28
  *
20
29
  * @author SAP SE
21
- * @version 1.128.0
30
+ * @version 1.130.0
22
31
  *
23
32
  * @since 1.102
24
33
  * @alias sap.ui.export.ExportHandler
25
34
  * @extends sap.ui.base.EventProvider
26
35
  * @public
27
36
  */
28
- var ExportHandler = EventProvider.extend('sap.ui.export.ExportHandler', {
37
+ const ExportHandler = EventProvider.extend("sap.ui.export.ExportHandler", {
29
38
  constructor: function(mCapabilities) {
30
- var that = this;
39
+ const that = this;
31
40
 
32
41
  EventProvider.call(this);
33
42
 
@@ -35,9 +44,9 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
35
44
  this._mCapabilities = mCapabilities instanceof Object ? mCapabilities : { XLSX: {} };
36
45
 
37
46
  if (this._mCapabilities.PDF) {
38
- var oCapabilities = this._mCapabilities.PDF;
47
+ const oCapabilities = this._mCapabilities.PDF;
39
48
 
40
- if (typeof oCapabilities.isA !== 'function' || !oCapabilities.isA('sap.ui.export.util.PDFCapabilities')) {
49
+ if (!oCapabilities?.isA?.("sap.ui.export.util.PDFCapabilities")) {
41
50
  this._mCapabilities.PDF = new PDFCapabilities(oCapabilities);
42
51
  }
43
52
 
@@ -47,8 +56,8 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
47
56
  }
48
57
 
49
58
  /* Activate Google Sheet support */
50
- this._initialized = new Promise(function(fnResolve) {
51
- that.isGoogleSheetSupported().then(function(bSupported) {
59
+ this._initialized = new Promise((fnResolve) => {
60
+ this.isGoogleSheetSupported().then((bSupported) => {
52
61
  if (bSupported) {
53
62
  that._mCapabilities[FileType.GSHEET] = {};
54
63
 
@@ -96,7 +105,7 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
96
105
  * @public
97
106
  */
98
107
  ExportHandler.prototype.attachBeforeExport = function(oData, fnHandler, oListener) {
99
- return this.attachEvent('beforeExport', oData, fnHandler, oListener);
108
+ return this.attachEvent("beforeExport", oData, fnHandler, oListener);
100
109
  };
101
110
 
102
111
  /**
@@ -112,7 +121,7 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
112
121
  * @public
113
122
  */
114
123
  ExportHandler.prototype.detachBeforeExport = function(fnHandler, oListener) {
115
- return this.detachEvent('beforeExport', fnHandler, oListener);
124
+ return this.detachEvent("beforeExport", fnHandler, oListener);
116
125
  };
117
126
 
118
127
  /**
@@ -138,27 +147,19 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
138
147
  ExportHandler.prototype.destroy = function() {
139
148
  EventProvider.prototype.destroy.apply(this, arguments);
140
149
 
141
- if (this._oModel) {
142
- this._oModel.destroy();
143
- }
144
-
145
- if (this._oFileShareBinding) {
146
- this._oFileShareBinding.destroy();
147
- }
148
-
149
- if (this._oExportDialog) {
150
- this._oExportDialog.destroy();
151
- }
152
-
153
- if (this._oFilePicker) {
154
- this._oFilePicker.destroy();
155
- }
150
+ this._oExportDialog?.destroy();
151
+ this._oFilePicker?.destroy();
152
+ this._oFileShareBinding?.destroy();
153
+ this._oModel?.destroy();
156
154
 
157
155
  this._mCapabilities = null;
158
- this._oDataSource = null;
159
156
  this._mDialogSettings = null;
160
- this._oModel = null;
157
+ this._oDataSource = null;
158
+ this._oExportDialog = null;
159
+ this._oFilePicker = null;
161
160
  this._oFileShareBinding = null;
161
+ this._oModel = null;
162
+
162
163
  this.bIsDestroyed = true;
163
164
  };
164
165
 
@@ -170,20 +171,21 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
170
171
  *
171
172
  * @returns {Promise<sap.ui.model.odata.v4.Context[]>} <code>Promise</code> that gets resolved with the requested FileShare <code>Context</code> <code>Array</code>
172
173
  *
174
+ * @async
173
175
  * @private
174
176
  */
175
- ExportHandler.prototype.getFileShareContexts = function() {
176
- return this.getFileShareModel().then(function(oModel) {
177
- if (!oModel) {
178
- return Promise.resolve([]);
179
- }
177
+ ExportHandler.prototype.getFileShareContexts = async function() {
178
+ const oModel = await this.getFileShareModel();
180
179
 
181
- if (!this._oFileShareBinding) {
182
- this._oFileShareBinding = oModel.bindList('/FileShares');
183
- }
180
+ if (!oModel) {
181
+ return Promise.resolve([]);
182
+ }
183
+
184
+ if (!this._oFileShareBinding) {
185
+ this._oFileShareBinding = oModel.bindList("/FileShares");
186
+ }
184
187
 
185
- return this._oFileShareBinding.requestContexts(0);
186
- }.bind(this));
188
+ return this._oFileShareBinding.requestContexts(0);
187
189
  };
188
190
 
189
191
  /**
@@ -195,61 +197,52 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
195
197
  * @param {string} [sFileName] Suggested name of the file including file extension
196
198
  * @returns {Promise} Resolves with the file location selected in the <code>CloudFilePicker</code>
197
199
  *
200
+ * @async
198
201
  * @private
199
202
  */
200
- ExportHandler.prototype.getRemoteFileLocation = function(sFileName) {
201
- var that = this;
202
-
203
- return new Promise(function(fnResolve, fnReject) {
204
- Promise.all([
205
- ExportUtils.getResourceBundle(),
206
- that.getFileShareModel()
207
- ]).then(function(aResolve) {
208
- var oResourceBundle = aResolve[0];
209
- var oModel = aResolve[1];
210
-
211
- sap.ui.require(['sap/suite/ui/commons/CloudFilePicker'], function(CloudFilePicker) {
212
- var oFilePicker;
213
-
214
- that._oFilePicker = oFilePicker = new CloudFilePicker({
215
- sharedModel: oModel,
216
- suggestedFileName: sFileName,
217
- enableDuplicateCheck: true,
218
- fileNameMandatory: true,
219
- confirmButtonText: oResourceBundle.getText('EXPORT_BUTTON'),
220
- title: oResourceBundle.getText('DESTINATION_DIALOG_TITLE')
221
- });
222
-
223
- oFilePicker.attachSelect(function(oEvent) {
224
- var aSelectedFiles, oSelectedFolder, bReplaceFile, mCloudFileInfo = {};
225
-
226
- aSelectedFiles = oEvent.getParameter('selectedFiles');
227
- oSelectedFolder = oEvent.getParameter('selectedFolder');
228
- bReplaceFile = oEvent.getParameter('replaceExistingFile');
229
-
230
- mCloudFileInfo = {};
231
- mCloudFileInfo['FileShare'] = oSelectedFolder.getFileShareId();
232
- mCloudFileInfo['FileShareItemKind'] = 'document';
233
- mCloudFileInfo['FileShareItemName'] = oEvent.getParameter('selectedFileName');
234
- mCloudFileInfo['ParentFileShareItem'] = oSelectedFolder.getFileShareItemId();
235
-
236
- if (bReplaceFile && Array.isArray(aSelectedFiles) && aSelectedFiles.length > 0) {
237
- var oCloudFile = aSelectedFiles.shift();
238
-
239
- mCloudFileInfo['FileShareItem'] = oCloudFile.getFileShareItemId();
240
- }
241
-
242
- /* Check whether the user has selected a valid FileShare */
243
- if (!mCloudFileInfo['FileShare']) {
244
- fnReject(oResourceBundle.getText('DESTINATION_SELECTION_INCOMPLETE'));
245
- }
246
-
247
- fnResolve(mCloudFileInfo);
248
- });
249
-
250
- oFilePicker.open();
251
- });
203
+ ExportHandler.prototype.getRemoteFileLocation = async function(sFileName) {
204
+ const [oResourceBundle, oModel, CloudFilePicker] = await Promise.all([
205
+ ExportUtils.getResourceBundle(),
206
+ this.getFileShareModel(),
207
+ ExportUtils.loadClass("sap/suite/ui/commons/CloudFilePicker")
208
+ ]);
209
+
210
+ const oFilePicker = this._oFilePicker = new CloudFilePicker({
211
+ sharedModel: oModel,
212
+ suggestedFileName: sFileName,
213
+ enableDuplicateCheck: true,
214
+ fileNameMandatory: true,
215
+ confirmButtonText: oResourceBundle.getText("EXPORT_BUTTON"),
216
+ title: oResourceBundle.getText("DESTINATION_DIALOG_TITLE")
217
+ });
218
+
219
+ return new Promise((fnResolve, fnReject) => {
220
+ oFilePicker.attachSelect(function(oEvent) {
221
+ const aSelectedFiles = oEvent.getParameter("selectedFiles");
222
+ const oSelectedFolder = oEvent.getParameter("selectedFolder");
223
+ const bReplaceFile = oEvent.getParameter("replaceExistingFile");
224
+
225
+ const mCloudFileInfo = {
226
+ FileShare: oSelectedFolder.getFileShareId(),
227
+ FileShareItemKind: "document",
228
+ FileShareItemName: oEvent.getParameter("selectedFileName"),
229
+ ParentFileShareItem: oSelectedFolder.getFileShareItemId()
230
+ };
231
+
232
+ if (bReplaceFile && Array.isArray(aSelectedFiles) && aSelectedFiles.length > 0) {
233
+ const oCloudFile = aSelectedFiles.shift();
234
+
235
+ mCloudFileInfo.FileShareItem = oCloudFile.getFileShareItemId();
236
+ }
237
+
238
+ if (!mCloudFileInfo.FileShare) {
239
+ fnReject(oResourceBundle.getText("DESTINATION_SELECTION_INCOMPLETE"));
240
+ }
241
+
242
+ fnResolve(mCloudFileInfo);
252
243
  });
244
+
245
+ oFilePicker.open();
253
246
  });
254
247
  };
255
248
 
@@ -263,113 +256,109 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
263
256
  * @param {object} mCloudFileInfo FileShareItem representation of the file
264
257
  * @returns {Promise} A <code>Promise</code> that resolves with the desired export instance
265
258
  *
259
+ * @async
266
260
  * @private
267
261
  */
268
- ExportHandler.prototype.getExportInstance = function(mExportSettings, mCustomSettings, mCloudFileInfo) {
269
- var that = this;
262
+ ExportHandler.prototype.getExportInstance = async function(mExportSettings, mCustomSettings, mCloudFileInfo) {
263
+ const that = this;
270
264
 
271
- return Promise.all([
265
+ const [oResourceBundle, oExportInstance] = await Promise.all([
272
266
  ExportUtils.getResourceBundle(),
273
- ExportUtils.getExportInstance(mExportSettings, this._mCapabilities)
274
- ]).then(function(aResolve) {
275
- var oResourceBundle = aResolve[0];
276
- var oExportInstance = aResolve[1];
277
- var aFilters = [];
278
- var oFilterConfig;
279
-
280
- if (mCustomSettings && mCustomSettings.includeFilterSettings) {
281
- var oContext = mExportSettings.workbook.context;
282
-
283
- if (!oContext) {
284
- oContext = mExportSettings.workbook.context = {
285
- metainfo: []
286
- };
287
- }
267
+ ExportUtils.getExportInstance(mExportSettings, this._mCapabilities, mCloudFileInfo)
268
+ ]);
288
269
 
289
- oFilterConfig = {
290
- name: oResourceBundle.getText('FILTER_HEADER'),
291
- items: []
292
- };
293
- aFilters = mCustomSettings.includeFilterSettings ? ExportUtils.getFilters(mExportSettings.dataSource) : [];
294
- oContext.metaSheetName = oFilterConfig.name;
270
+ let aFilters = [];
271
+ const oFilterConfig = {
272
+ name: oResourceBundle.getText("FILTER_HEADER"),
273
+ items: []
274
+ };
275
+
276
+ if (mCustomSettings?.includeFilterSettings) {
277
+ let oContext = mExportSettings.workbook.context;
295
278
 
296
- oContext.metainfo.push(oFilterConfig);
279
+ if (!oContext) {
280
+ oContext = mExportSettings.workbook.context = {
281
+ metainfo: []
282
+ };
297
283
  }
298
284
 
299
- oExportInstance.attachBeforeExport(function(oEvent) {
300
- var mEventExportSettings = oEvent.getParameter('exportSettings');
285
+ aFilters = ExportUtils.getFilters(mExportSettings.dataSource);
286
+ oContext.metaSheetName = oFilterConfig.name;
301
287
 
302
- const bExecuteDefaultAction = that.fireEvent('beforeExport', {
303
- exportSettings: mEventExportSettings,
304
- userExportSettings: mCustomSettings || {},
305
- filterSettings: aFilters
306
- }, true, false);
288
+ oContext.metainfo.push(oFilterConfig);
289
+ }
307
290
 
308
- if (!bExecuteDefaultAction) {
309
- oEvent.preventDefault();
310
- return;
311
- }
291
+ oExportInstance.attachBeforeExport(function(oEvent) {
292
+ const bExecuteDefaultAction = that.fireEvent("beforeExport", {
293
+ exportSettings: oEvent.getParameter("exportSettings"),
294
+ userExportSettings: mCustomSettings || {},
295
+ filterSettings: aFilters
296
+ }, true, false);
312
297
 
313
- /* Sort filterSettings and write to metainfo */
314
- aFilters.filter(function(oFilter) {
315
- return oFilter && typeof oFilter.isA === 'function' && oFilter.isA('sap.ui.export.util.Filter');
316
- }).sort(function(firstElement, secondElement) {
317
- var sFirst = firstElement.getLabel().toLowerCase();
318
- var sSecond = secondElement.getLabel().toLowerCase();
298
+ if (!bExecuteDefaultAction) {
299
+ oEvent.preventDefault();
300
+ return;
301
+ }
319
302
 
320
- if (sFirst > sSecond) {
321
- return 1;
322
- }
303
+ /* Sort filterSettings and write to metainfo */
304
+ aFilters.filter((oFilter) => {
305
+ return oFilter?.isA?.("sap.ui.export.util.Filter");
306
+ }).sort((firstElement, secondElement) => {
307
+ const sFirst = firstElement.getLabel().toLowerCase();
308
+ const sSecond = secondElement.getLabel().toLowerCase();
323
309
 
324
- if (sFirst < sSecond) {
325
- return -1;
326
- }
310
+ if (sFirst > sSecond) {
311
+ return 1;
312
+ }
327
313
 
328
- return 0;
329
- }).forEach(function(oFilter) {
330
- oFilterConfig.items.push({
331
- key: oFilter.getLabel(),
332
- value: oFilter.getValue()
333
- });
314
+ if (sFirst < sSecond) {
315
+ return -1;
316
+ }
317
+
318
+ return 0;
319
+ }).forEach((oFilter) => {
320
+ oFilterConfig.items.push({
321
+ key: oFilter.getLabel(),
322
+ value: oFilter.getValue()
334
323
  });
335
324
  });
325
+ });
336
326
 
337
- if (mCloudFileInfo && typeof oExportInstance.attachBeforeSave === 'function') {
338
- oExportInstance.attachBeforeSave(function(oEvent) {
339
- var aArrayBuffer, oExportDialog;
327
+ if (mCloudFileInfo && typeof oExportInstance.attachBeforeSave === "function") {
328
+ oExportInstance.attachBeforeSave(function(oEvent) {
329
+ const aArrayBuffer = oEvent.getParameter("data");
330
+ const oExportDialog = oEvent.getParameter("exportDialog");
340
331
 
341
- aArrayBuffer = oEvent.getParameter('data');
342
- oExportDialog = oEvent.getParameter('exportDialog');
343
- mCloudFileInfo['FileShareItemContentType'] = oExportInstance.getMimeType();
344
- mCloudFileInfo['FileShareItemConvertToMimeType'] = oExportInstance.getMimeType();
332
+ mCloudFileInfo.FileShareItemContentType = oExportInstance.getMimeType();
333
+ mCloudFileInfo.FileShareItemConvertToMimeType = oExportInstance.getMimeType();
345
334
 
346
- /* Enforce file conversion for Google Sheet */
347
- if (mExportSettings.fileType === FileType.GSHEET) {
348
- mCloudFileInfo['FileShareItemConvertToMimeType'] = 'application/vnd.google-apps.spreadsheet';
349
- }
335
+ /* Enforce file conversion for Google Sheet */
336
+ if (mExportSettings.fileType === FileType.GSHEET) {
337
+ mCloudFileInfo.FileShareItemConvertToMimeType = "application/vnd.google-apps.spreadsheet";
338
+ }
350
339
 
351
- var uInt8Array = new Uint8Array(aArrayBuffer);
352
- var stringArray = new Array(uInt8Array.length);
353
- for (var i = 0; i < uInt8Array.length; i++) {
354
- stringArray[i] = String.fromCharCode(uInt8Array[i]); // often a bit faster, especially with huge files, than string concatenation
355
- }
356
- mCloudFileInfo['FileShareItemContent'] = btoa(stringArray.join(""));
357
-
358
- oExportDialog.updateStatus(oResourceBundle.getText('DESTINATION_DIALOG_STATUS'));
359
- oEvent.preventDefault();
360
-
361
- that.uploadFile(mCloudFileInfo).then(function() {
362
- MessageToast.show(oResourceBundle.getText('DESTINATION_TRANSFER_SUCCESS'));
363
- }).catch(function() {
364
- ExportDialog.showErrorMessage(oResourceBundle.getText('DESTINATION_TRANSFER_ERROR'));
365
- }).finally(function() {
366
- oExportDialog.finish();
367
- });
340
+ const uInt8Array = new Uint8Array(aArrayBuffer);
341
+ const stringArray = new Array(uInt8Array.length);
342
+
343
+ for (let i = 0; i < uInt8Array.length; i++) {
344
+ stringArray[i] = String.fromCharCode(uInt8Array[i]); // often a bit faster, especially with huge files, than string concatenation
345
+ }
346
+ mCloudFileInfo.FileShareItemContent = btoa(stringArray.join(""));
347
+
348
+ oExportDialog.updateStatus(oResourceBundle.getText("DESTINATION_DIALOG_STATUS"));
349
+ oEvent.preventDefault();
350
+
351
+ this.uploadFile(mCloudFileInfo).then(() => {
352
+ MessageToast.show(oResourceBundle.getText("DESTINATION_TRANSFER_SUCCESS"));
353
+ }).catch(() => {
354
+ ExportDialog.showErrorMessage(oResourceBundle.getText("DESTINATION_TRANSFER_ERROR"));
355
+ }).finally(() => {
356
+ oExportDialog.finish();
368
357
  });
369
- }
358
+ }, this);
359
+ }
370
360
 
371
- return oExportInstance;
372
- });
361
+ return oExportInstance;
373
362
  };
374
363
 
375
364
  /**
@@ -378,52 +367,48 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
378
367
  * @param {object} mCloudFileInfo FileShareItem representation of the file
379
368
  * @returns {Promise} A <code>Promise</code> that gets resolved after the generated file has been transferred to the FileShareSupport OData service
380
369
  *
370
+ * @async
381
371
  * @private
382
372
  */
383
- ExportHandler.prototype.uploadFile = function(mCloudFileInfo) {
384
- return this.getFileShareModel().then(function(oModel) {
385
- var oBinding, oContext, sContentProperty, sTypeProperty, sPath;
386
-
387
- sContentProperty = 'FileShareItemContent';
388
- sTypeProperty = 'FileShareItemContentType';
389
-
390
- /* Overwrite existing file */
391
- if (mCloudFileInfo['FileShareItem']) {
392
- oContext = oModel.getKeepAliveContext("/FileShareItems(FileShare='" + mCloudFileInfo.FileShare + "',FileShareItem='" + mCloudFileInfo.FileShareItem + "')");
393
-
394
- /*
395
- * We have to set the FileShareItemContentLink as well
396
- * as the FileShareItemContentType property explicitly
397
- * to ensure that the properties will be filled with
398
- * the content of the PATCH response when updating the
399
- * FileShareItemContent. Adding the <code>null</code>
400
- * prevents an additional PATCH for the link. It is also
401
- * important to set all properties without waiting for
402
- * the <code>Promise</code> to resolve. This allows the
403
- * binding to bundle multiple PATCH requests into a
404
- * single $batch.
405
- */
406
- oContext.setProperty('FileShareItemContentLink', '', null);
407
- oContext.setProperty(sTypeProperty, mCloudFileInfo[sTypeProperty]);
408
- return oContext.setProperty(sContentProperty, mCloudFileInfo[sContentProperty]).then(function() {
409
- return oContext.getProperty('FileShareItemContentLink');
410
- });
411
- }
412
-
413
- /* Creating new file in specific folder or _Root */
414
- if (mCloudFileInfo.ParentFileShareItem) {
415
- sPath = "/FileShareItems(FileShare='" + mCloudFileInfo.FileShare + "',FileShareItem='" + mCloudFileInfo.ParentFileShareItem + "')/_Children";
416
- } else {
417
- sPath = "/FileShares(FileShare='" + mCloudFileInfo.FileShare + "')/_Root/_Children";
418
- }
373
+ ExportHandler.prototype.uploadFile = async function(mCloudFileInfo) {
374
+ let sUrl;
375
+ const oModel = await this.getFileShareModel();
376
+
377
+ const sContentProperty = "FileShareItemContent";
378
+ const sTypeProperty = "FileShareItemContentType";
379
+
380
+ if (mCloudFileInfo.FileShareItem) { // Overwrite existing file
381
+ const oContext = oModel.getKeepAliveContext(`/FileShareItems(FileShare='${mCloudFileInfo.FileShare}',FileShareItem='${mCloudFileInfo.FileShareItem}')`);
382
+
383
+ /*
384
+ * We have to set the FileShareItemContentLink as well
385
+ * as the FileShareItemContentType property explicitly
386
+ * to ensure that the properties will be filled with
387
+ * the content of the PATCH response when updating the
388
+ * FileShareItemContent. Adding the <code>null</code>
389
+ * prevents an additional PATCH for the link. It is also
390
+ * important to set all properties without waiting for
391
+ * the <code>Promise</code> to resolve. This allows the
392
+ * binding to bundle multiple PATCH requests into a
393
+ * single $batch.
394
+ */
395
+ oContext.setProperty("FileShareItemContentLink", "", null);
396
+ oContext.setProperty(sTypeProperty, mCloudFileInfo[sTypeProperty]);
397
+ await oContext.setProperty(sContentProperty, mCloudFileInfo[sContentProperty]);
398
+
399
+ sUrl = oContext.getProperty("FileShareItemContentLink");
400
+
401
+ } else { // Creating new file in specific folder or _Root
402
+ const sPath = mCloudFileInfo.ParentFileShareItem ?
403
+ `/FileShareItems(FileShare='${mCloudFileInfo.FileShare}',FileShareItem='${mCloudFileInfo.ParentFileShareItem}')/_Children` : `/FileShares(FileShare='${mCloudFileInfo.FileShare}')/_Root/_Children`;
404
+
405
+ const oBinding = oModel.bindList(sPath);
406
+ sUrl = await this._createFile(oBinding, mCloudFileInfo);
407
+ }
419
408
 
420
- oBinding = oModel.bindList(sPath);
421
- return this._createFile(oBinding, mCloudFileInfo);
422
- }.bind(this)).then(function(sUrl) {
423
- if (sUrl) {
424
- openWindow(sUrl);
425
- }
426
- });
409
+ if (sUrl) {
410
+ openWindow(sUrl);
411
+ }
427
412
  };
428
413
 
429
414
  /**
@@ -437,16 +422,13 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
437
422
  * @private
438
423
  */
439
424
  ExportHandler.prototype._createFile = function(oBinding, mCloudFileInfo) {
440
- return new Promise(function(fnResolve, fnReject) {
425
+ return new Promise((fnResolve, fnReject) => {
441
426
  function fnCreateCompleted(oEvent) {
442
- var bSuccess, oContext;
443
-
444
- bSuccess = oEvent.getParameter('success');
445
- oContext = oEvent.getParameter('context');
427
+ const { success: bSuccess, context: oContext } = oEvent.getParameters();
446
428
 
447
429
  if (bSuccess) {
448
430
  oBinding.detachCreateCompleted(fnCreateCompleted);
449
- fnResolve(oContext.getProperty('FileShareItemContentLink'));
431
+ fnResolve(oContext.getProperty("FileShareItemContentLink"));
450
432
  } else {
451
433
  oContext.destroy();
452
434
  fnReject();
@@ -469,18 +451,21 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
469
451
  * @returns {Promise} A <code>Promise</code> that gets resolved after the export process has been finished
470
452
  *
471
453
  * @since 1.102
454
+ * @async
472
455
  * @public
473
456
  */
474
- ExportHandler.prototype.export = function(mExportSettings) {
457
+ ExportHandler.prototype.export = async function(mExportSettings) {
475
458
  if (this.bIsDestroyed) {
476
- Promise.reject('ExportHandler must not be used after calling #destroy');
459
+ Promise.reject("ExportHandler must not be used after calling #destroy");
477
460
  }
478
461
 
479
- return this.getExportInstance(mExportSettings).then(function(oExportInstance) {
480
- return oExportInstance.build().finally(function() {
481
- oExportInstance.destroy();
482
- });
483
- });
462
+ const oExportInstance = await this.getExportInstance(mExportSettings);
463
+
464
+ try {
465
+ await oExportInstance.build();
466
+ } finally {
467
+ oExportInstance.destroy();
468
+ }
484
469
  };
485
470
 
486
471
  /**
@@ -494,81 +479,75 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
494
479
  * @returns {Promise} A <code>Promise</code> that resolves once the data has been exported
495
480
  *
496
481
  * @since 1.102
482
+ * @async
497
483
  * @public
498
484
  */
499
- ExportHandler.prototype.exportAs = function(oSettings, fnResolveColumnLabel) {
500
- var that = this;
501
- var mExportSettings;
502
- var mUserSettings = {};
503
-
485
+ ExportHandler.prototype.exportAs = async function(oSettings, fnResolveColumnLabel) {
504
486
  if (this.bIsDestroyed) {
505
- return Promise.reject('ExportHandler must not be used after calling #destroy');
487
+ throw new Error("ExportHandler must not be used after calling #destroy");
506
488
  }
507
489
 
508
- return this.initialized().then(function() {
509
- mExportSettings = Object.assign({}, oSettings, that._mDialogSettings);
490
+ await this.initialized();
510
491
 
511
- return that.getFileShareContexts();
512
- }).then(function(aContexts) {
513
- return ExportUtils.getExportSettingsViaDialog(mExportSettings, that._mCapabilities, aContexts.length > 0, function(oDialog) { that._oExportDialog = oDialog; });
514
- }).then(function(mDialogSettings) {
492
+ const mExportSettings = Object.assign({}, oSettings, this._mDialogSettings);
493
+ const aContexts = await this.getFileShareContexts();
494
+ const mDialogSettings =
495
+ await ExportUtils.getExportSettingsViaDialog(mExportSettings, this._mCapabilities, aContexts.length > 0, (oDialog) => { this._oExportDialog = oDialog; });
515
496
 
516
- /* Cache settings dialog settings */
517
- that._mDialogSettings = mDialogSettings;
497
+ /* Cache dialog settings */
498
+ this._mDialogSettings = mDialogSettings;
518
499
 
519
- /* Merge export settings with user settings from the dialog */
520
- Object.assign(mExportSettings, mDialogSettings);
500
+ /* Merge export settings with user settings from the dialog */
501
+ Object.assign(mExportSettings, mDialogSettings);
521
502
 
522
- ExportUtils.validateFileSettings(mExportSettings);
503
+ ExportUtils.validateFileSettings(mExportSettings);
523
504
 
524
- mUserSettings.splitCells = mDialogSettings.splitCells;
525
- mUserSettings.includeFilterSettings = mDialogSettings.includeFilterSettings;
505
+ const mUserSettings = {
506
+ splitCells: mDialogSettings.splitCells,
507
+ includeFilterSettings: mDialogSettings.includeFilterSettings
508
+ };
526
509
 
527
- /* Enforce split cells option for fileType PDF without persisting the value in the settings dialog */
528
- if (mExportSettings.fileType === FileType.PDF || mDialogSettings.splitCells) {
529
- mExportSettings.workbook.columns = ExportUtils.splitColumns(mExportSettings.workbook.columns, fnResolveColumnLabel);
530
- }
531
- if (mExportSettings.includeFilterSettings) {
532
- return ExportUtils.parseTechnicalConfiguration();
510
+ /* Enforce split cells option for fileType PDF without persisting the value in the settings dialog */
511
+ if (mExportSettings.fileType === FileType.PDF || mDialogSettings.splitCells) {
512
+ mExportSettings.workbook.columns = ExportUtils.splitColumns(mExportSettings.workbook.columns, fnResolveColumnLabel);
513
+ }
514
+
515
+ if (mExportSettings.includeFilterSettings) {
516
+ const oUserConfig = await ExportUtils.parseTechnicalConfiguration();
517
+ let oContext = mExportSettings.workbook.context;
518
+
519
+ if (!oContext) {
520
+ oContext = mExportSettings.workbook.context = {};
533
521
  }
534
522
 
535
- return Promise.resolve();
536
- }).then(function(oUserConfig) {
537
- if (oUserConfig) {
538
- var oContext = mExportSettings.workbook.context;
523
+ oContext.metainfo = Array.isArray(oContext.metainfo) ? oContext.metainfo.push(oUserConfig) : [oUserConfig];
524
+ }
539
525
 
540
- if (!oContext) {
541
- oContext = mExportSettings.workbook.context = {};
542
- }
526
+ let mCloudFileInfo;
543
527
 
544
- oContext.metainfo = Array.isArray(oContext.metainfo) ? oContext.metainfo.push(oUserConfig) : [oUserConfig];
545
- }
546
- }).then(function() {
547
- if (mExportSettings.destination === Destination.LOCAL) {
548
- return Promise.resolve();
549
- }
528
+ if (mExportSettings.destination === Destination.REMOTE) {
529
+ mCloudFileInfo = await this.getRemoteFileLocation(mExportSettings.fileName);
530
+ }
550
531
 
551
- return that.getRemoteFileLocation(mExportSettings.fileName);
552
- }).then(function(mCloudFileInfo) {
532
+ /* Validate file name only if file does not exist */
533
+ if (mCloudFileInfo && !mCloudFileInfo.FileShareItem) {
534
+ mCloudFileInfo.FileShareItemName = ExportUtils.validateFileName(mCloudFileInfo.FileShareItemName, mExportSettings.fileType);
535
+ }
553
536
 
554
- /* Validate file name only if file does not exist */
555
- if (mCloudFileInfo && !mCloudFileInfo['FileShareItem']) {
556
- mCloudFileInfo.FileShareItemName = ExportUtils.validateFileName(mCloudFileInfo.FileShareItemName, mExportSettings.fileType);
557
- }
537
+ /* Verify that selected FileShare is a Google Workspace */
538
+ if (mExportSettings.fileType === FileType.GSHEET) {
539
+ await this.validateFileShare(mCloudFileInfo);
540
+ }
558
541
 
559
- /* Verify that selected FileShare is a Google Workspace */
560
- if (mExportSettings.fileType === FileType.GSHEET) {
561
- return that.validateFileShare(mCloudFileInfo);
562
- }
542
+ const oExportInstance = await this.getExportInstance(mExportSettings, mUserSettings, mCloudFileInfo);
563
543
 
564
- return mCloudFileInfo;
565
- }).then(function(mCloudFileInfo) {
566
- return that.getExportInstance(mExportSettings, mUserSettings, mCloudFileInfo).then(function(oExportInstance) {
567
- return oExportInstance.build().finally(function() {
568
- oExportInstance.destroy();
569
- });
570
- });
571
- }).catch(ExportDialog.showErrorMessage);
544
+ try {
545
+ await oExportInstance.build();
546
+ } catch (oError) {
547
+ ExportDialog.showErrorMessage(oError);
548
+ } finally {
549
+ oExportInstance.destroy();
550
+ }
572
551
  };
573
552
 
574
553
  /**
@@ -585,16 +564,14 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
585
564
  return Promise.all([
586
565
  ExportUtils.getResourceBundle(),
587
566
  this.getFileShareContexts()
588
- ]).then(function(aResolve) {
589
- var oResourceBundle = aResolve[0];
590
- var aContexts = aResolve[1];
591
-
592
- var oFileShareContext = aContexts.find(function(oContext) {
593
- return oContext.getProperty('FileShare') === mCloudFileInfo.FileShare;
567
+ ]).then((aResolve) => {
568
+ const [oResourceBundle, aContexts] = aResolve;
569
+ const oFileShareContext = aContexts.find((oContext) => {
570
+ return oContext.getProperty("FileShare") === mCloudFileInfo.FileShare;
594
571
  });
595
572
 
596
- return this.isGoogleWorkspace(oFileShareContext) ? mCloudFileInfo : Promise.reject(oResourceBundle.getText('DESTINATION_ERROR_NOT_GOOGLE'));
597
- }.bind(this));
573
+ return this.isGoogleWorkspace(oFileShareContext) ? mCloudFileInfo : Promise.reject(oResourceBundle.getText("DESTINATION_ERROR_NOT_GOOGLE"));
574
+ });
598
575
  };
599
576
 
600
577
  /**
@@ -605,22 +582,22 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
605
582
  *
606
583
  * @private
607
584
  */
608
- ExportHandler.prototype.getFileShareModel = function() {
585
+ ExportHandler.prototype.getFileShareModel = async function() {
609
586
 
610
587
  if (this._oModel) {
611
- return Promise.resolve(this._oModel);
588
+ return this._oModel;
612
589
  }
613
590
 
614
- return ExportUtils.fetchDataSource().then(function(oDataSource) {
615
- if (oDataSource) {
616
- this._oModel = new ODataModel({
617
- serviceUrl: oDataSource.uri,
618
- autoExpandSelect: true
619
- });
620
- }
591
+ const oDataSource = await ExportUtils.fetchDataSource();
621
592
 
622
- return this._oModel;
623
- }.bind(this));
593
+ if (oDataSource) {
594
+ this._oModel = new ODataModel({
595
+ serviceUrl: oDataSource.uri,
596
+ autoExpandSelect: true
597
+ });
598
+ }
599
+
600
+ return this._oModel;
624
601
  };
625
602
 
626
603
  /**
@@ -630,10 +607,10 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
630
607
  *
631
608
  * @private
632
609
  */
633
- ExportHandler.prototype.isGoogleSheetSupported = function() {
634
- return this.getFileShareContexts().then(function(aContexts) {
635
- return aContexts.some(this.isGoogleWorkspace);
636
- }.bind(this));
610
+ ExportHandler.prototype.isGoogleSheetSupported = async function() {
611
+ const aContexts = await this.getFileShareContexts();
612
+
613
+ return aContexts.some(this.isGoogleWorkspace);
637
614
  };
638
615
 
639
616
  /**
@@ -645,13 +622,11 @@ sap.ui.define(['./library', './ExportUtils', './ExportDialog', './util/PDFCapabi
645
622
  * @private
646
623
  */
647
624
  ExportHandler.prototype.isGoogleWorkspace = function(oContext) {
648
- var sDescription, sVendorType;
649
-
650
- sVendorType = oContext.getProperty('FileShareVendorType');
651
- sDescription = oContext.getProperty('FileShareDescription');
625
+ const sVendorType = oContext.getProperty("FileShareVendorType");
626
+ const sDescription = oContext.getProperty("FileShareDescription");
652
627
 
653
- return sVendorType === 'GOOGLE'
654
- || (typeof sDescription === 'string' && sDescription.indexOf('Google') > -1);
628
+ return sVendorType === "GOOGLE"
629
+ || (typeof sDescription === "string" && sDescription.indexOf("Google") > -1);
655
630
  };
656
631
 
657
632
  return ExportHandler;