@sumit_yewale/angular 1.1.18 → 1.1.20
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/README.md +41 -0
- package/bundles/sumit_yewale-angular.umd.js +532 -60
- package/bundles/sumit_yewale-angular.umd.js.map +1 -1
- package/bundles/sumit_yewale-angular.umd.min.js +1 -1
- package/bundles/sumit_yewale-angular.umd.min.js.map +1 -1
- package/esm2015/lib/csvbox-button.component.js +481 -60
- package/esm2015/public-api.js +1 -2
- package/esm5/lib/csvbox-button.component.js +535 -63
- package/esm5/public-api.js +1 -2
- package/fesm2015/sumit_yewale-angular.js +480 -59
- package/fesm2015/sumit_yewale-angular.js.map +1 -1
- package/fesm5/sumit_yewale-angular.js +534 -62
- package/fesm5/sumit_yewale-angular.js.map +1 -1
- package/lib/csvbox-button.component.d.ts +32 -4
- package/package.json +2 -8
- package/sumit_yewale-angular.metadata.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SecurityContext, Component,
|
|
1
|
+
import { SecurityContext, Component, ChangeDetectorRef, NgZone, Input, NgModule } from '@angular/core';
|
|
2
2
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
3
|
-
import {
|
|
3
|
+
import { createFileSender, classifyLegacyMessage, classifyStructuredMessage, generateUuid, buildImportUrl, buildInitPayload } from '@sumit_yewale/adapter-core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @fileoverview added by tsickle
|
|
@@ -34,11 +34,129 @@ function () {
|
|
|
34
34
|
* Generated from: lib/csvbox-button.component.ts
|
|
35
35
|
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
36
36
|
*/
|
|
37
|
+
// How long we wait for the importer to confirm a file it was sent before giving up on it.
|
|
37
38
|
/** @type {?} */
|
|
38
|
-
var
|
|
39
|
+
var FILE_ACK_TIMEOUT_MS = 8000;
|
|
40
|
+
/**
|
|
41
|
+
* @record
|
|
42
|
+
*/
|
|
43
|
+
function OpenImporterEntry() { }
|
|
44
|
+
if (false) {
|
|
45
|
+
/** @type {?} */
|
|
46
|
+
OpenImporterEntry.prototype.getHolder;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @record
|
|
50
|
+
*/
|
|
51
|
+
function OpenImporters() { }
|
|
52
|
+
if (false) {
|
|
53
|
+
/** @type {?} */
|
|
54
|
+
OpenImporters.prototype.open;
|
|
55
|
+
/** @type {?} */
|
|
56
|
+
OpenImporters.prototype.listeners;
|
|
57
|
+
}
|
|
58
|
+
/** @type {?} */
|
|
59
|
+
var OPEN_IMPORTERS_KEY = '__csvboxOpenImporters';
|
|
60
|
+
/** @type {?} */
|
|
61
|
+
var TOP_Z_INDEX = 2147483647;
|
|
62
|
+
/**
|
|
63
|
+
* @return {?}
|
|
64
|
+
*/
|
|
65
|
+
function openImporters() {
|
|
66
|
+
/** @type {?} */
|
|
67
|
+
var w = (/** @type {?} */ (window));
|
|
68
|
+
if (!w[OPEN_IMPORTERS_KEY])
|
|
69
|
+
w[OPEN_IMPORTERS_KEY] = { open: [], listeners: [] };
|
|
70
|
+
return w[OPEN_IMPORTERS_KEY];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* @param {?} reg
|
|
74
|
+
* @return {?}
|
|
75
|
+
*/
|
|
76
|
+
function restackOpenImporters(reg) {
|
|
77
|
+
reg.open.forEach((/**
|
|
78
|
+
* @param {?} entry
|
|
79
|
+
* @param {?} i
|
|
80
|
+
* @return {?}
|
|
81
|
+
*/
|
|
82
|
+
function (entry, i) {
|
|
83
|
+
/** @type {?} */
|
|
84
|
+
var holder = entry.getHolder();
|
|
85
|
+
if (holder)
|
|
86
|
+
holder.style.zIndex = String(TOP_Z_INDEX - (reg.open.length - 1 - i));
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* @param {?} entry
|
|
91
|
+
* @return {?}
|
|
92
|
+
*/
|
|
93
|
+
function registerOpenImporter(entry) {
|
|
94
|
+
/** @type {?} */
|
|
95
|
+
var reg = openImporters();
|
|
96
|
+
if (reg.open.indexOf(entry) >= 0)
|
|
97
|
+
return;
|
|
98
|
+
reg.open.push(entry);
|
|
99
|
+
restackOpenImporters(reg);
|
|
100
|
+
reg.listeners.slice().forEach((/**
|
|
101
|
+
* @param {?} fn
|
|
102
|
+
* @return {?}
|
|
103
|
+
*/
|
|
104
|
+
function (fn) { return fn(); }));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* @param {?} entry
|
|
108
|
+
* @return {?}
|
|
109
|
+
*/
|
|
110
|
+
function unregisterOpenImporter(entry) {
|
|
111
|
+
/** @type {?} */
|
|
112
|
+
var reg = openImporters();
|
|
113
|
+
/** @type {?} */
|
|
114
|
+
var i = reg.open.indexOf(entry);
|
|
115
|
+
if (i < 0)
|
|
116
|
+
return;
|
|
117
|
+
reg.open.splice(i, 1);
|
|
118
|
+
restackOpenImporters(reg);
|
|
119
|
+
reg.listeners.slice().forEach((/**
|
|
120
|
+
* @param {?} fn
|
|
121
|
+
* @return {?}
|
|
122
|
+
*/
|
|
123
|
+
function (fn) { return fn(); }));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* @param {?} entry
|
|
127
|
+
* @return {?}
|
|
128
|
+
*/
|
|
129
|
+
function isBlockedByOpenImporter(entry) {
|
|
130
|
+
/** @type {?} */
|
|
131
|
+
var reg = openImporters();
|
|
132
|
+
return reg.open.length > 0 && reg.open.indexOf(entry) < 0;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* @param {?} fn
|
|
136
|
+
* @return {?}
|
|
137
|
+
*/
|
|
138
|
+
function subscribeOpenImporters(fn) {
|
|
139
|
+
/** @type {?} */
|
|
140
|
+
var reg = openImporters();
|
|
141
|
+
reg.listeners.push(fn);
|
|
142
|
+
return (/**
|
|
143
|
+
* @return {?}
|
|
144
|
+
*/
|
|
145
|
+
function () {
|
|
146
|
+
/** @type {?} */
|
|
147
|
+
var i = reg.listeners.indexOf(fn);
|
|
148
|
+
if (i >= 0)
|
|
149
|
+
reg.listeners.splice(i, 1);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/** @type {?} */
|
|
153
|
+
var appVersion = '1.1.20';
|
|
39
154
|
var CSVBoxButtonComponent = /** @class */ (function () {
|
|
40
|
-
function CSVBoxButtonComponent(sanitizer) {
|
|
155
|
+
function CSVBoxButtonComponent(sanitizer, cdr, zone) {
|
|
156
|
+
var _this = this;
|
|
41
157
|
this.sanitizer = sanitizer;
|
|
158
|
+
this.cdr = cdr;
|
|
159
|
+
this.zone = zone;
|
|
42
160
|
this.isModalShown = false;
|
|
43
161
|
this.licenseKey = null;
|
|
44
162
|
this.uuid = null;
|
|
@@ -51,6 +169,165 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
51
169
|
this.lazy = false;
|
|
52
170
|
this.iframe = null;
|
|
53
171
|
this.disabled = true;
|
|
172
|
+
// True while a different importer on the page is open: the button stays disabled.
|
|
173
|
+
this.blockedByOther = false;
|
|
174
|
+
this.registryEntry = { getHolder: (/**
|
|
175
|
+
* @return {?}
|
|
176
|
+
*/
|
|
177
|
+
function () { return _this.holder; }) };
|
|
178
|
+
this.fileSender = createFileSender({
|
|
179
|
+
getIframe: (/**
|
|
180
|
+
* @return {?}
|
|
181
|
+
*/
|
|
182
|
+
function () { return _this.iframe; }),
|
|
183
|
+
getToken: (/**
|
|
184
|
+
* @return {?}
|
|
185
|
+
*/
|
|
186
|
+
function () { return (/** @type {?} */ (_this.uuid)); }),
|
|
187
|
+
getTargetOrigin: (/**
|
|
188
|
+
* @return {?}
|
|
189
|
+
*/
|
|
190
|
+
function () { return (/** @type {?} */ (_this.targetOrigin)); }),
|
|
191
|
+
getBaseDomain: (/**
|
|
192
|
+
* @return {?}
|
|
193
|
+
*/
|
|
194
|
+
function () { return _this.baseDomain; }),
|
|
195
|
+
takeFile: (/**
|
|
196
|
+
* @return {?}
|
|
197
|
+
*/
|
|
198
|
+
function () {
|
|
199
|
+
/** @type {?} */
|
|
200
|
+
var file = _this.pendingFile;
|
|
201
|
+
_this.pendingFile = null;
|
|
202
|
+
return file;
|
|
203
|
+
}),
|
|
204
|
+
onSent: (/**
|
|
205
|
+
* @return {?}
|
|
206
|
+
*/
|
|
207
|
+
function () { return _this.startFileAckTimer(); })
|
|
208
|
+
});
|
|
209
|
+
this.unsubscribeOpenImporters = null;
|
|
210
|
+
this.pendingFile = null;
|
|
211
|
+
// Data-location sheets redirect to another host, so the iframe origin can differ from
|
|
212
|
+
// targetOrigin. baseDomain is used to check the real origin before trusting it.
|
|
213
|
+
this.baseDomain = "app.csvbox.io";
|
|
214
|
+
this.fileAckTimer = null;
|
|
215
|
+
this.messageListener = (/**
|
|
216
|
+
* @param {?} event
|
|
217
|
+
* @return {?}
|
|
218
|
+
*/
|
|
219
|
+
function (event) {
|
|
220
|
+
// Older importers send these as bare strings, without a token.
|
|
221
|
+
/** @type {?} */
|
|
222
|
+
var legacy = classifyLegacyMessage(event.data);
|
|
223
|
+
if (legacy) {
|
|
224
|
+
// Legacy messages carry no token, so the only way to tell which importer sent one is its
|
|
225
|
+
// window. Ignore those that came from another instance's iframe (or anywhere else).
|
|
226
|
+
if (!_this.iframe || event.source !== _this.iframe.contentWindow) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (legacy.type === "mainModalHidden") {
|
|
230
|
+
_this.handleModalClosed();
|
|
231
|
+
}
|
|
232
|
+
else if (legacy.type === "uploadSuccessful") {
|
|
233
|
+
if (_this.onImport)
|
|
234
|
+
_this.onImport(true);
|
|
235
|
+
if (_this.isImported)
|
|
236
|
+
_this.isImported(true);
|
|
237
|
+
if (_this.imported)
|
|
238
|
+
_this.imported(true);
|
|
239
|
+
}
|
|
240
|
+
else if (legacy.type === "uploadFailed") {
|
|
241
|
+
if (_this.onImport)
|
|
242
|
+
_this.onImport(false);
|
|
243
|
+
if (_this.isImported)
|
|
244
|
+
_this.isImported(false);
|
|
245
|
+
if (_this.imported)
|
|
246
|
+
_this.imported(false);
|
|
247
|
+
}
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
// Set-file handshake messages. The shared core does not classify these, so they are
|
|
251
|
+
// read here, behind the same unique_token check the core applies.
|
|
252
|
+
/** @type {?} */
|
|
253
|
+
var raw = event.data;
|
|
254
|
+
if (raw && typeof raw === "object" && raw.data && raw.data.unique_token == _this.uuid) {
|
|
255
|
+
_this.fileSender.learnOrigin(event);
|
|
256
|
+
if (raw.type === "csvbox-set-file-rejected" && raw.data.reason === "not-a-file") {
|
|
257
|
+
// Reply to our probe (it has no file). It only tells us the origin, so do nothing.
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (raw.type === "csvbox-modal-shown") {
|
|
261
|
+
_this.clearFileAckTimer();
|
|
262
|
+
registerOpenImporter(_this.registryEntry);
|
|
263
|
+
// What the file path in openModal() is waiting for. display as well as
|
|
264
|
+
// pointer-events: a second file declined while the first was still opening the
|
|
265
|
+
// modal has put the holder away in the meantime.
|
|
266
|
+
_this.isModalShown = true;
|
|
267
|
+
if (_this.holder) {
|
|
268
|
+
_this.holder.style.display = 'block';
|
|
269
|
+
_this.holder.style.pointerEvents = 'auto';
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (raw.type === "csvbox-set-file-rejected") {
|
|
274
|
+
_this.clearFileAckTimer();
|
|
275
|
+
// The importer has the file and will not take it. Put the holder away only if the
|
|
276
|
+
// modal was never confirmed up: a file declined while it is open leaves that modal
|
|
277
|
+
// where it is, and its own 'csvbox-modal-hidden' will put the holder away.
|
|
278
|
+
if (!_this.isModalShown && _this.holder) {
|
|
279
|
+
_this.holder.style.display = 'none';
|
|
280
|
+
_this.holder.style.pointerEvents = 'auto';
|
|
281
|
+
unregisterOpenImporter(_this.registryEntry);
|
|
282
|
+
}
|
|
283
|
+
console.warn("[csvbox] importer declined the supplied file: " + raw.data.reason);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/** @type {?} */
|
|
288
|
+
var message = classifyStructuredMessage(event.data, (/** @type {?} */ (_this.uuid)));
|
|
289
|
+
if (!message) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (message.type === "data-on-submit") {
|
|
293
|
+
if (_this.onSubmit)
|
|
294
|
+
_this.onSubmit(message.metadata);
|
|
295
|
+
if (_this.isSubmitted)
|
|
296
|
+
_this.isSubmitted(message.metadata);
|
|
297
|
+
if (_this.submitted)
|
|
298
|
+
_this.submitted(message.metadata);
|
|
299
|
+
}
|
|
300
|
+
else if (message.type === "data-push-status") {
|
|
301
|
+
if (!message.success) {
|
|
302
|
+
delete message.metadata["unique_token"];
|
|
303
|
+
}
|
|
304
|
+
if (_this.onImport)
|
|
305
|
+
_this.onImport(message.success, message.metadata);
|
|
306
|
+
if (_this.isImported)
|
|
307
|
+
_this.isImported(message.success, message.metadata);
|
|
308
|
+
if (_this.imported)
|
|
309
|
+
_this.imported(message.success, message.metadata);
|
|
310
|
+
}
|
|
311
|
+
else if (message.type === "csvbox-modal-hidden") {
|
|
312
|
+
_this.handleModalClosed();
|
|
313
|
+
}
|
|
314
|
+
else if (message.type === "csvbox-upload-successful") {
|
|
315
|
+
if (_this.onImport)
|
|
316
|
+
_this.onImport(true);
|
|
317
|
+
if (_this.isImported)
|
|
318
|
+
_this.isImported(true);
|
|
319
|
+
if (_this.imported)
|
|
320
|
+
_this.imported(true);
|
|
321
|
+
}
|
|
322
|
+
else if (message.type === "csvbox-upload-failed") {
|
|
323
|
+
if (_this.onImport)
|
|
324
|
+
_this.onImport(false);
|
|
325
|
+
if (_this.isImported)
|
|
326
|
+
_this.isImported(false);
|
|
327
|
+
if (_this.imported)
|
|
328
|
+
_this.imported(false);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
54
331
|
}
|
|
55
332
|
/**
|
|
56
333
|
* @return {?}
|
|
@@ -69,6 +346,9 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
69
346
|
theme: this.theme,
|
|
70
347
|
environment: this.environment
|
|
71
348
|
}, "angular", appVersion);
|
|
349
|
+
// Default place to send the file. A file is only ever sent to a named origin, never "*".
|
|
350
|
+
this.targetOrigin = new URL(iframeUrl).origin;
|
|
351
|
+
this.baseDomain = this.customDomain || "app.csvbox.io";
|
|
72
352
|
this.safeUrl = this.sanitizer.sanitize(SecurityContext.RESOURCE_URL, this.sanitizer.bypassSecurityTrustResourceUrl(iframeUrl));
|
|
73
353
|
};
|
|
74
354
|
/**
|
|
@@ -108,55 +388,12 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
108
388
|
*/
|
|
109
389
|
function () {
|
|
110
390
|
var _this = this;
|
|
111
|
-
window.addEventListener("message",
|
|
112
|
-
|
|
391
|
+
window.addEventListener("message", this.messageListener, false);
|
|
392
|
+
this.syncBlocked();
|
|
393
|
+
this.unsubscribeOpenImporters = subscribeOpenImporters((/**
|
|
113
394
|
* @return {?}
|
|
114
395
|
*/
|
|
115
|
-
function (
|
|
116
|
-
/** @type {?} */
|
|
117
|
-
var message = classifyStructuredMessage(event.data, (/** @type {?} */ (_this.uuid)));
|
|
118
|
-
if (!message) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
if (message.type === "data-on-submit") {
|
|
122
|
-
if (_this.onSubmit)
|
|
123
|
-
_this.onSubmit(message.metadata);
|
|
124
|
-
if (_this.isSubmitted)
|
|
125
|
-
_this.isSubmitted(message.metadata);
|
|
126
|
-
if (_this.submitted)
|
|
127
|
-
_this.submitted(message.metadata);
|
|
128
|
-
}
|
|
129
|
-
else if (message.type === "data-push-status") {
|
|
130
|
-
if (!message.success) {
|
|
131
|
-
delete message.metadata["unique_token"];
|
|
132
|
-
}
|
|
133
|
-
if (_this.onImport)
|
|
134
|
-
_this.onImport(message.success, message.metadata);
|
|
135
|
-
if (_this.isImported)
|
|
136
|
-
_this.isImported(message.success, message.metadata);
|
|
137
|
-
if (_this.imported)
|
|
138
|
-
_this.imported(message.success, message.metadata);
|
|
139
|
-
}
|
|
140
|
-
else if (message.type === "csvbox-modal-hidden") {
|
|
141
|
-
_this.handleModalClosed();
|
|
142
|
-
}
|
|
143
|
-
else if (message.type === "csvbox-upload-successful") {
|
|
144
|
-
if (_this.onImport)
|
|
145
|
-
_this.onImport(true);
|
|
146
|
-
if (_this.isImported)
|
|
147
|
-
_this.isImported(true);
|
|
148
|
-
if (_this.imported)
|
|
149
|
-
_this.imported(true);
|
|
150
|
-
}
|
|
151
|
-
else if (message.type === "csvbox-upload-failed") {
|
|
152
|
-
if (_this.onImport)
|
|
153
|
-
_this.onImport(false);
|
|
154
|
-
if (_this.isImported)
|
|
155
|
-
_this.isImported(false);
|
|
156
|
-
if (_this.imported)
|
|
157
|
-
_this.imported(false);
|
|
158
|
-
}
|
|
159
|
-
}), false);
|
|
396
|
+
function () { return _this.syncBlocked(); }));
|
|
160
397
|
if (this.lazy) {
|
|
161
398
|
this.disabled = false;
|
|
162
399
|
}
|
|
@@ -172,8 +409,10 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
172
409
|
* @return {?}
|
|
173
410
|
*/
|
|
174
411
|
function () {
|
|
175
|
-
if (this.holder)
|
|
412
|
+
if (this.holder) {
|
|
176
413
|
this.holder.style.display = 'none';
|
|
414
|
+
this.holder.style.pointerEvents = 'auto';
|
|
415
|
+
}
|
|
177
416
|
this.isModalShown = false;
|
|
178
417
|
this.isIframeLoaded = false;
|
|
179
418
|
this.openModalOnIframeLoad = false;
|
|
@@ -181,6 +420,9 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
181
420
|
this.holder.remove();
|
|
182
421
|
this.holder = null;
|
|
183
422
|
this.iframe = null;
|
|
423
|
+
// A new iframe is built on the next open, so the origin is learned again.
|
|
424
|
+
this.clearProbeTimer();
|
|
425
|
+
unregisterOpenImporter(this.registryEntry);
|
|
184
426
|
if (this.onClose)
|
|
185
427
|
this.onClose();
|
|
186
428
|
if (this.isClosed)
|
|
@@ -203,6 +445,7 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
203
445
|
var iframe = document.createElement("iframe");
|
|
204
446
|
this.iframe = iframe;
|
|
205
447
|
iframe.setAttribute("src", this.safeUrl);
|
|
448
|
+
iframe.setAttribute("allow", "clipboard-read; clipboard-write *");
|
|
206
449
|
iframe.frameBorder = "0";
|
|
207
450
|
/** @type {?} */
|
|
208
451
|
var self = this;
|
|
@@ -230,6 +473,8 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
230
473
|
this.holder.setAttribute('id', "csvbox-embed-" + this.uuid);
|
|
231
474
|
this.holder.appendChild(iframe);
|
|
232
475
|
document.body.insertAdjacentElement('beforeend', this.holder);
|
|
476
|
+
// The holder did not exist yet if openModal() asked for the importer before it was built.
|
|
477
|
+
restackOpenImporters(openImporters());
|
|
233
478
|
};
|
|
234
479
|
/**
|
|
235
480
|
* @return {?}
|
|
@@ -238,6 +483,9 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
238
483
|
* @return {?}
|
|
239
484
|
*/
|
|
240
485
|
function () {
|
|
486
|
+
// Counts as open from the moment it is requested, so the other buttons are disabled while
|
|
487
|
+
// this importer is still loading, and so it is stacked above any importer opened earlier.
|
|
488
|
+
registerOpenImporter(this.registryEntry);
|
|
241
489
|
if (!this.iframe) {
|
|
242
490
|
this.openModalOnIframeLoad = true;
|
|
243
491
|
this.initImporter();
|
|
@@ -245,11 +493,36 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
245
493
|
}
|
|
246
494
|
if (!this.isModalShown) {
|
|
247
495
|
if (this.isIframeLoaded) {
|
|
248
|
-
this.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
496
|
+
if (this.pendingFile) {
|
|
497
|
+
// The importer opens its own modal once it has the file, so that it can inject on
|
|
498
|
+
// 'shown.bs.modal'. Sending 'openModal' as well would race that.
|
|
499
|
+
//
|
|
500
|
+
// It can also decline: wrong step, an import file URL configured on the sheet, or
|
|
501
|
+
// an importer too old to know the message at all. So the holder goes up
|
|
502
|
+
// click-through and stays that way until 'csvbox-modal-shown' confirms the modal
|
|
503
|
+
// is really up. It covers the viewport at z-index 2147483647 and the importer
|
|
504
|
+
// renders transparent with its modal closed, so arming it on an unanswered message
|
|
505
|
+
// leaves an invisible sheet over the host page eating every click.
|
|
506
|
+
//
|
|
507
|
+
// display:block regardless, so the iframe lays out and animates normally; only
|
|
508
|
+
// pointer-events is held back. isModalShown likewise waits for the confirmation,
|
|
509
|
+
// or a declined file would latch the importer shut for good.
|
|
510
|
+
if (this.holder) {
|
|
511
|
+
this.holder.style.pointerEvents = 'none';
|
|
512
|
+
this.holder.style.display = 'block';
|
|
513
|
+
}
|
|
514
|
+
this.fileSender.send();
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
this.isModalShown = true;
|
|
518
|
+
if (this.holder) {
|
|
519
|
+
// Explicit: a previously declined file leaves the holder click-through.
|
|
520
|
+
this.holder.style.pointerEvents = 'auto';
|
|
521
|
+
this.holder.style.display = 'block';
|
|
522
|
+
}
|
|
523
|
+
if (this.iframe && this.iframe.contentWindow) {
|
|
524
|
+
this.iframe.contentWindow.postMessage('openModal', '*');
|
|
525
|
+
}
|
|
253
526
|
}
|
|
254
527
|
}
|
|
255
528
|
else {
|
|
@@ -257,18 +530,176 @@ var CSVBoxButtonComponent = /** @class */ (function () {
|
|
|
257
530
|
}
|
|
258
531
|
}
|
|
259
532
|
};
|
|
533
|
+
/**
|
|
534
|
+
* Open the importer on a File the host page already has, instead of the file picker.
|
|
535
|
+
*
|
|
536
|
+
* Reachable through a template reference (`#importer` then `importer.openModalWithFile(file)`)
|
|
537
|
+
* or `@ViewChild(CSVBoxButtonComponent)`.
|
|
538
|
+
*
|
|
539
|
+
* The File crosses to the iframe by structured clone, so the importer receives the real
|
|
540
|
+
* object and applies its own extension, worksheet and size rules to it -- this does not
|
|
541
|
+
* bypass any of them. Pass a File; a Blob has no name for the importer to read an
|
|
542
|
+
* extension from.
|
|
543
|
+
*/
|
|
544
|
+
/**
|
|
545
|
+
* Open the importer on a File the host page already has, instead of the file picker.
|
|
546
|
+
*
|
|
547
|
+
* Reachable through a template reference (`#importer` then `importer.openModalWithFile(file)`)
|
|
548
|
+
* or `\@ViewChild(CSVBoxButtonComponent)`.
|
|
549
|
+
*
|
|
550
|
+
* The File crosses to the iframe by structured clone, so the importer receives the real
|
|
551
|
+
* object and applies its own extension, worksheet and size rules to it -- this does not
|
|
552
|
+
* bypass any of them. Pass a File; a Blob has no name for the importer to read an
|
|
553
|
+
* extension from.
|
|
554
|
+
* @param {?} file
|
|
555
|
+
* @return {?}
|
|
556
|
+
*/
|
|
557
|
+
CSVBoxButtonComponent.prototype.openModalWithFile = /**
|
|
558
|
+
* Open the importer on a File the host page already has, instead of the file picker.
|
|
559
|
+
*
|
|
560
|
+
* Reachable through a template reference (`#importer` then `importer.openModalWithFile(file)`)
|
|
561
|
+
* or `\@ViewChild(CSVBoxButtonComponent)`.
|
|
562
|
+
*
|
|
563
|
+
* The File crosses to the iframe by structured clone, so the importer receives the real
|
|
564
|
+
* object and applies its own extension, worksheet and size rules to it -- this does not
|
|
565
|
+
* bypass any of them. Pass a File; a Blob has no name for the importer to read an
|
|
566
|
+
* extension from.
|
|
567
|
+
* @param {?} file
|
|
568
|
+
* @return {?}
|
|
569
|
+
*/
|
|
570
|
+
function (file) {
|
|
571
|
+
if (typeof File === 'undefined' || !(file instanceof File)) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
this.pendingFile = file;
|
|
575
|
+
// Already open: hand it over now rather than holding it for the next open. The importer
|
|
576
|
+
// takes it only while it is still on the upload step, and ignores it once the user has a
|
|
577
|
+
// dataset and a mapping in progress.
|
|
578
|
+
if (this.isModalShown && this.iframe && this.isIframeLoaded) {
|
|
579
|
+
this.fileSender.send();
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
this.openModal();
|
|
583
|
+
};
|
|
584
|
+
/**
|
|
585
|
+
* @return {?}
|
|
586
|
+
*/
|
|
587
|
+
CSVBoxButtonComponent.prototype.clearProbeTimer = /**
|
|
588
|
+
* @return {?}
|
|
589
|
+
*/
|
|
590
|
+
function () {
|
|
591
|
+
this.clearFileAckTimer();
|
|
592
|
+
this.fileSender.reset();
|
|
593
|
+
};
|
|
594
|
+
/**
|
|
595
|
+
* @return {?}
|
|
596
|
+
*/
|
|
597
|
+
CSVBoxButtonComponent.prototype.startFileAckTimer = /**
|
|
598
|
+
* @return {?}
|
|
599
|
+
*/
|
|
600
|
+
function () {
|
|
601
|
+
var _this = this;
|
|
602
|
+
this.clearFileAckTimer();
|
|
603
|
+
this.fileAckTimer = setTimeout((/**
|
|
604
|
+
* @return {?}
|
|
605
|
+
*/
|
|
606
|
+
function () {
|
|
607
|
+
_this.fileAckTimer = null;
|
|
608
|
+
_this.giveUpOnFile();
|
|
609
|
+
}), FILE_ACK_TIMEOUT_MS);
|
|
610
|
+
};
|
|
611
|
+
/**
|
|
612
|
+
* @return {?}
|
|
613
|
+
*/
|
|
614
|
+
CSVBoxButtonComponent.prototype.clearFileAckTimer = /**
|
|
615
|
+
* @return {?}
|
|
616
|
+
*/
|
|
617
|
+
function () {
|
|
618
|
+
if (this.fileAckTimer) {
|
|
619
|
+
clearTimeout(this.fileAckTimer);
|
|
620
|
+
this.fileAckTimer = null;
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
// The importer never confirmed the file it was sent (an origin we do not trust, or an importer too
|
|
624
|
+
// old to know the message). Without this the holder would stay up, invisible and click-through,
|
|
625
|
+
// and the other instances' buttons would stay disabled for good.
|
|
626
|
+
// The importer never confirmed the file it was sent (an origin we do not trust, or an importer too
|
|
627
|
+
// old to know the message). Without this the holder would stay up, invisible and click-through,
|
|
628
|
+
// and the other instances' buttons would stay disabled for good.
|
|
629
|
+
/**
|
|
630
|
+
* @return {?}
|
|
631
|
+
*/
|
|
632
|
+
CSVBoxButtonComponent.prototype.giveUpOnFile =
|
|
633
|
+
// The importer never confirmed the file it was sent (an origin we do not trust, or an importer too
|
|
634
|
+
// old to know the message). Without this the holder would stay up, invisible and click-through,
|
|
635
|
+
// and the other instances' buttons would stay disabled for good.
|
|
636
|
+
/**
|
|
637
|
+
* @return {?}
|
|
638
|
+
*/
|
|
639
|
+
function () {
|
|
640
|
+
if (this.isModalShown) {
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
/** @type {?} */
|
|
644
|
+
var holder = this.holder;
|
|
645
|
+
if (holder) {
|
|
646
|
+
holder.style.display = 'none';
|
|
647
|
+
holder.style.pointerEvents = 'auto';
|
|
648
|
+
}
|
|
649
|
+
unregisterOpenImporter(this.registryEntry);
|
|
650
|
+
console.warn("[csvbox] the importer did not respond to the supplied file");
|
|
651
|
+
};
|
|
652
|
+
/**
|
|
653
|
+
* @private
|
|
654
|
+
* @return {?}
|
|
655
|
+
*/
|
|
656
|
+
CSVBoxButtonComponent.prototype.syncBlocked = /**
|
|
657
|
+
* @private
|
|
658
|
+
* @return {?}
|
|
659
|
+
*/
|
|
660
|
+
function () {
|
|
661
|
+
var _this = this;
|
|
662
|
+
/** @type {?} */
|
|
663
|
+
var blocked = isBlockedByOpenImporter(this.registryEntry);
|
|
664
|
+
if (blocked !== this.blockedByOther) {
|
|
665
|
+
// The registry can call back from outside Angular's zone (another instance, another app).
|
|
666
|
+
this.zone.run((/**
|
|
667
|
+
* @return {?}
|
|
668
|
+
*/
|
|
669
|
+
function () {
|
|
670
|
+
_this.blockedByOther = blocked;
|
|
671
|
+
_this.cdr.markForCheck();
|
|
672
|
+
}));
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
/**
|
|
676
|
+
* @return {?}
|
|
677
|
+
*/
|
|
678
|
+
CSVBoxButtonComponent.prototype.ngOnDestroy = /**
|
|
679
|
+
* @return {?}
|
|
680
|
+
*/
|
|
681
|
+
function () {
|
|
682
|
+
this.clearProbeTimer();
|
|
683
|
+
window.removeEventListener("message", this.messageListener);
|
|
684
|
+
unregisterOpenImporter(this.registryEntry);
|
|
685
|
+
if (this.unsubscribeOpenImporters) {
|
|
686
|
+
this.unsubscribeOpenImporters();
|
|
687
|
+
this.unsubscribeOpenImporters = null;
|
|
688
|
+
}
|
|
689
|
+
};
|
|
260
690
|
CSVBoxButtonComponent.decorators = [
|
|
261
691
|
{ type: Component, args: [{
|
|
262
692
|
selector: 'csvbox-button',
|
|
263
|
-
template: "\n <div>\n <button [disabled]=\"disabled\"
|
|
693
|
+
template: "\n <div>\n <button [disabled]=\"disabled || blockedByOther\" (click)=\"openModal()\" [attr.data-csvbox-token]=\"uuid\">\n <ng-content></ng-content>\n </button>\n </div>\n "
|
|
264
694
|
}] }
|
|
265
695
|
];
|
|
266
696
|
/** @nocollapse */
|
|
267
697
|
CSVBoxButtonComponent.ctorParameters = function () { return [
|
|
268
|
-
{ type: DomSanitizer }
|
|
698
|
+
{ type: DomSanitizer },
|
|
699
|
+
{ type: ChangeDetectorRef },
|
|
700
|
+
{ type: NgZone }
|
|
269
701
|
]; };
|
|
270
702
|
CSVBoxButtonComponent.propDecorators = {
|
|
271
|
-
initiator: [{ type: ViewChild, args: ['initiator', { static: false },] }],
|
|
272
703
|
onImport: [{ type: Input }],
|
|
273
704
|
onReady: [{ type: Input }],
|
|
274
705
|
onClose: [{ type: Input }],
|
|
@@ -303,8 +734,6 @@ if (false) {
|
|
|
303
734
|
/** @type {?} */
|
|
304
735
|
CSVBoxButtonComponent.prototype.isModalShown;
|
|
305
736
|
/** @type {?} */
|
|
306
|
-
CSVBoxButtonComponent.prototype.initiator;
|
|
307
|
-
/** @type {?} */
|
|
308
737
|
CSVBoxButtonComponent.prototype.onImport;
|
|
309
738
|
/** @type {?} */
|
|
310
739
|
CSVBoxButtonComponent.prototype.onReady;
|
|
@@ -363,9 +792,52 @@ if (false) {
|
|
|
363
792
|
/** @type {?} */
|
|
364
793
|
CSVBoxButtonComponent.prototype.disabled;
|
|
365
794
|
/** @type {?} */
|
|
795
|
+
CSVBoxButtonComponent.prototype.blockedByOther;
|
|
796
|
+
/**
|
|
797
|
+
* @type {?}
|
|
798
|
+
* @private
|
|
799
|
+
*/
|
|
800
|
+
CSVBoxButtonComponent.prototype.registryEntry;
|
|
801
|
+
/**
|
|
802
|
+
* @type {?}
|
|
803
|
+
* @private
|
|
804
|
+
*/
|
|
805
|
+
CSVBoxButtonComponent.prototype.fileSender;
|
|
806
|
+
/**
|
|
807
|
+
* @type {?}
|
|
808
|
+
* @private
|
|
809
|
+
*/
|
|
810
|
+
CSVBoxButtonComponent.prototype.unsubscribeOpenImporters;
|
|
811
|
+
/** @type {?} */
|
|
366
812
|
CSVBoxButtonComponent.prototype.holder;
|
|
367
813
|
/** @type {?} */
|
|
814
|
+
CSVBoxButtonComponent.prototype.pendingFile;
|
|
815
|
+
/** @type {?} */
|
|
816
|
+
CSVBoxButtonComponent.prototype.targetOrigin;
|
|
817
|
+
/** @type {?} */
|
|
818
|
+
CSVBoxButtonComponent.prototype.baseDomain;
|
|
819
|
+
/**
|
|
820
|
+
* @type {?}
|
|
821
|
+
* @private
|
|
822
|
+
*/
|
|
823
|
+
CSVBoxButtonComponent.prototype.fileAckTimer;
|
|
824
|
+
/**
|
|
825
|
+
* @type {?}
|
|
826
|
+
* @private
|
|
827
|
+
*/
|
|
828
|
+
CSVBoxButtonComponent.prototype.messageListener;
|
|
829
|
+
/** @type {?} */
|
|
368
830
|
CSVBoxButtonComponent.prototype.sanitizer;
|
|
831
|
+
/**
|
|
832
|
+
* @type {?}
|
|
833
|
+
* @private
|
|
834
|
+
*/
|
|
835
|
+
CSVBoxButtonComponent.prototype.cdr;
|
|
836
|
+
/**
|
|
837
|
+
* @type {?}
|
|
838
|
+
* @private
|
|
839
|
+
*/
|
|
840
|
+
CSVBoxButtonComponent.prototype.zone;
|
|
369
841
|
}
|
|
370
842
|
|
|
371
843
|
/**
|