@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.
- package/package.json +1 -1
- package/src/sap/ui/export/.library +1 -1
- package/src/sap/ui/export/ExportBase.js +1 -1
- package/src/sap/ui/export/ExportDialog.js +1 -1
- package/src/sap/ui/export/ExportHandler.js +294 -319
- package/src/sap/ui/export/ExportUtils.js +108 -107
- package/src/sap/ui/export/PortableDocument.js +175 -167
- package/src/sap/ui/export/Spreadsheet.js +8 -3
- package/src/sap/ui/export/SpreadsheetExport.js +1 -1
- package/src/sap/ui/export/fragments/SettingsDialog.fragment.xml +2 -2
- package/src/sap/ui/export/library.js +2 -2
- package/src/sap/ui/export/messagebundle_da.properties +1 -1
- package/src/sap/ui/export/messagebundle_ru.properties +1 -1
- package/src/sap/ui/export/provider/DataProviderBase.js +22 -2
- package/src/sap/ui/export/util/Filter.js +1 -1
- package/src/sap/ui/export/util/PDFCapabilities.js +4 -2
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
* SAPUI5
|
|
3
3
|
* (c) Copyright 2009-2024 SAP SE. All rights reserved.
|
|
4
4
|
*/
|
|
5
|
-
sap.ui.define([
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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.
|
|
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
|
-
|
|
37
|
+
const ExportHandler = EventProvider.extend("sap.ui.export.ExportHandler", {
|
|
29
38
|
constructor: function(mCapabilities) {
|
|
30
|
-
|
|
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
|
-
|
|
47
|
+
const oCapabilities = this._mCapabilities.PDF;
|
|
39
48
|
|
|
40
|
-
if (
|
|
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(
|
|
51
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
142
|
-
|
|
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.
|
|
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
|
-
|
|
177
|
-
if (!oModel) {
|
|
178
|
-
return Promise.resolve([]);
|
|
179
|
-
}
|
|
177
|
+
ExportHandler.prototype.getFileShareContexts = async function() {
|
|
178
|
+
const oModel = await this.getFileShareModel();
|
|
180
179
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
180
|
+
if (!oModel) {
|
|
181
|
+
return Promise.resolve([]);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!this._oFileShareBinding) {
|
|
185
|
+
this._oFileShareBinding = oModel.bindList("/FileShares");
|
|
186
|
+
}
|
|
184
187
|
|
|
185
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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
|
-
|
|
262
|
+
ExportHandler.prototype.getExportInstance = async function(mExportSettings, mCustomSettings, mCloudFileInfo) {
|
|
263
|
+
const that = this;
|
|
270
264
|
|
|
271
|
-
|
|
265
|
+
const [oResourceBundle, oExportInstance] = await Promise.all([
|
|
272
266
|
ExportUtils.getResourceBundle(),
|
|
273
|
-
ExportUtils.getExportInstance(mExportSettings, this._mCapabilities)
|
|
274
|
-
])
|
|
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
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
-
|
|
279
|
+
if (!oContext) {
|
|
280
|
+
oContext = mExportSettings.workbook.context = {
|
|
281
|
+
metainfo: []
|
|
282
|
+
};
|
|
297
283
|
}
|
|
298
284
|
|
|
299
|
-
|
|
300
|
-
|
|
285
|
+
aFilters = ExportUtils.getFilters(mExportSettings.dataSource);
|
|
286
|
+
oContext.metaSheetName = oFilterConfig.name;
|
|
301
287
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
userExportSettings: mCustomSettings || {},
|
|
305
|
-
filterSettings: aFilters
|
|
306
|
-
}, true, false);
|
|
288
|
+
oContext.metainfo.push(oFilterConfig);
|
|
289
|
+
}
|
|
307
290
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
var sFirst = firstElement.getLabel().toLowerCase();
|
|
318
|
-
var sSecond = secondElement.getLabel().toLowerCase();
|
|
298
|
+
if (!bExecuteDefaultAction) {
|
|
299
|
+
oEvent.preventDefault();
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
319
302
|
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
|
|
325
|
-
|
|
326
|
-
|
|
310
|
+
if (sFirst > sSecond) {
|
|
311
|
+
return 1;
|
|
312
|
+
}
|
|
327
313
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
342
|
-
|
|
343
|
-
mCloudFileInfo['FileShareItemContentType'] = oExportInstance.getMimeType();
|
|
344
|
-
mCloudFileInfo['FileShareItemConvertToMimeType'] = oExportInstance.getMimeType();
|
|
332
|
+
mCloudFileInfo.FileShareItemContentType = oExportInstance.getMimeType();
|
|
333
|
+
mCloudFileInfo.FileShareItemConvertToMimeType = oExportInstance.getMimeType();
|
|
345
334
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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
|
-
|
|
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
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
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
|
-
|
|
421
|
-
|
|
422
|
-
}
|
|
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(
|
|
425
|
+
return new Promise((fnResolve, fnReject) => {
|
|
441
426
|
function fnCreateCompleted(oEvent) {
|
|
442
|
-
|
|
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(
|
|
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(
|
|
459
|
+
Promise.reject("ExportHandler must not be used after calling #destroy");
|
|
477
460
|
}
|
|
478
461
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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
|
-
|
|
487
|
+
throw new Error("ExportHandler must not be used after calling #destroy");
|
|
506
488
|
}
|
|
507
489
|
|
|
508
|
-
|
|
509
|
-
mExportSettings = Object.assign({}, oSettings, that._mDialogSettings);
|
|
490
|
+
await this.initialized();
|
|
510
491
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
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
|
-
|
|
517
|
-
|
|
497
|
+
/* Cache dialog settings */
|
|
498
|
+
this._mDialogSettings = mDialogSettings;
|
|
518
499
|
|
|
519
|
-
|
|
520
|
-
|
|
500
|
+
/* Merge export settings with user settings from the dialog */
|
|
501
|
+
Object.assign(mExportSettings, mDialogSettings);
|
|
521
502
|
|
|
522
|
-
|
|
503
|
+
ExportUtils.validateFileSettings(mExportSettings);
|
|
523
504
|
|
|
524
|
-
|
|
525
|
-
|
|
505
|
+
const mUserSettings = {
|
|
506
|
+
splitCells: mDialogSettings.splitCells,
|
|
507
|
+
includeFilterSettings: mDialogSettings.includeFilterSettings
|
|
508
|
+
};
|
|
526
509
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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
|
-
|
|
536
|
-
}
|
|
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
|
-
|
|
541
|
-
oContext = mExportSettings.workbook.context = {};
|
|
542
|
-
}
|
|
526
|
+
let mCloudFileInfo;
|
|
543
527
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
}
|
|
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
|
-
|
|
552
|
-
|
|
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
|
-
|
|
555
|
-
|
|
556
|
-
|
|
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
|
-
|
|
560
|
-
if (mExportSettings.fileType === FileType.GSHEET) {
|
|
561
|
-
return that.validateFileShare(mCloudFileInfo);
|
|
562
|
-
}
|
|
542
|
+
const oExportInstance = await this.getExportInstance(mExportSettings, mUserSettings, mCloudFileInfo);
|
|
563
543
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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(
|
|
589
|
-
|
|
590
|
-
|
|
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(
|
|
597
|
-
}
|
|
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
|
|
588
|
+
return this._oModel;
|
|
612
589
|
}
|
|
613
590
|
|
|
614
|
-
|
|
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
|
-
|
|
623
|
-
|
|
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
|
-
|
|
635
|
-
|
|
636
|
-
|
|
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
|
-
|
|
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 ===
|
|
654
|
-
|| (typeof sDescription ===
|
|
628
|
+
return sVendorType === "GOOGLE"
|
|
629
|
+
|| (typeof sDescription === "string" && sDescription.indexOf("Google") > -1);
|
|
655
630
|
};
|
|
656
631
|
|
|
657
632
|
return ExportHandler;
|