@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.
@@ -1,6 +1,6 @@
1
- import { SecurityContext, Component, ViewChild, Input, NgModule } from '@angular/core';
1
+ import { SecurityContext, Component, ChangeDetectorRef, NgZone, Input, NgModule } from '@angular/core';
2
2
  import { DomSanitizer } from '@angular/platform-browser';
3
- import { generateUuid, buildImportUrl, classifyStructuredMessage, buildInitPayload } from '@sumit_yewale/adapter-core';
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 appVersion = '1.1.16';
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
- * @param {?} event
391
+ window.addEventListener("message", this.messageListener, false);
392
+ this.syncBlocked();
393
+ this.unsubscribeOpenImporters = subscribeOpenImporters((/**
113
394
  * @return {?}
114
395
  */
115
- function (event) {
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.isModalShown = true;
249
- if (this.holder)
250
- this.holder.style.display = 'block';
251
- if (this.iframe && this.iframe.contentWindow) {
252
- this.iframe.contentWindow.postMessage('openModal', '*');
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\" #initiator (click)=\"openModal()\" [attr.data-csvbox-token]=\"uuid\">\n <ng-content></ng-content>\n </button>\n </div>\n "
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
  /**