@idea-ionic/uncommon 8.2.1

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.
Files changed (80) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +21 -0
  3. package/css/global.scss +15 -0
  4. package/esm2022/idea-ionic-uncommon.mjs +5 -0
  5. package/esm2022/public-api.mjs +35 -0
  6. package/esm2022/src/AWSAPI.service.mjs +430 -0
  7. package/esm2022/src/AWSAPISocket.service.mjs +187 -0
  8. package/esm2022/src/address/address.component.mjs +94 -0
  9. package/esm2022/src/address/address.module.mjs +21 -0
  10. package/esm2022/src/announcement/announcement.component.mjs +41 -0
  11. package/esm2022/src/announcement/announcement.module.mjs +21 -0
  12. package/esm2022/src/cachedResources.service.mjs +55 -0
  13. package/esm2022/src/colors/colorPicker.component.mjs +135 -0
  14. package/esm2022/src/colors/colorPicker.module.mjs +20 -0
  15. package/esm2022/src/contacts/contacts.component.mjs +64 -0
  16. package/esm2022/src/contacts/contacts.module.mjs +21 -0
  17. package/esm2022/src/dateTime/calendarPicker.component.mjs +196 -0
  18. package/esm2022/src/dateTime/dateTime.component.mjs +133 -0
  19. package/esm2022/src/dateTime/dateTime.module.mjs +22 -0
  20. package/esm2022/src/duration/duration.component.mjs +77 -0
  21. package/esm2022/src/duration/duration.module.mjs +21 -0
  22. package/esm2022/src/echo/echo.module.mjs +26 -0
  23. package/esm2022/src/echo/echo.page.mjs +165 -0
  24. package/esm2022/src/errorReporting.service.mjs +68 -0
  25. package/esm2022/src/mde/mde.component.mjs +44 -0
  26. package/esm2022/src/mde/mde.module.mjs +22 -0
  27. package/esm2022/src/mde/mdeToolbar.component.mjs +12 -0
  28. package/esm2022/src/offline/cacheableResource.component.mjs +18 -0
  29. package/esm2022/src/offline/offline.module.mjs +22 -0
  30. package/esm2022/src/offline/offline.service.mjs +62 -0
  31. package/esm2022/src/offline/offlineData.service.mjs +479 -0
  32. package/esm2022/src/offline/offlineIndicator.component.mjs +58 -0
  33. package/esm2022/src/offline/offlineManager.component.mjs +84 -0
  34. package/esm2022/src/pushNotifications.service.mjs +56 -0
  35. package/esm2022/src/sentiment/sentiment.component.mjs +71 -0
  36. package/esm2022/src/sentiment/sentiment.module.mjs +21 -0
  37. package/esm2022/src/timeInterval/fromTimeToTime.component.mjs +155 -0
  38. package/esm2022/src/timeInterval/timeInterval.component.mjs +122 -0
  39. package/esm2022/src/timeInterval/timeInterval.module.mjs +22 -0
  40. package/esm2022/src/tinCan.service.mjs +49 -0
  41. package/fesm2022/idea-ionic-uncommon.mjs +2891 -0
  42. package/fesm2022/idea-ionic-uncommon.mjs.map +1 -0
  43. package/index.d.ts +5 -0
  44. package/package.json +51 -0
  45. package/public-api.d.ts +34 -0
  46. package/src/AWSAPI.service.d.ts +178 -0
  47. package/src/AWSAPISocket.service.d.ts +129 -0
  48. package/src/address/address.component.d.ts +64 -0
  49. package/src/address/address.module.d.ts +11 -0
  50. package/src/announcement/announcement.component.d.ts +23 -0
  51. package/src/announcement/announcement.module.d.ts +11 -0
  52. package/src/cachedResources.service.d.ts +34 -0
  53. package/src/colors/colorPicker.component.d.ts +78 -0
  54. package/src/colors/colorPicker.module.d.ts +10 -0
  55. package/src/contacts/contacts.component.d.ts +31 -0
  56. package/src/contacts/contacts.module.d.ts +11 -0
  57. package/src/dateTime/calendarPicker.component.d.ts +45 -0
  58. package/src/dateTime/dateTime.component.d.ts +81 -0
  59. package/src/dateTime/dateTime.module.d.ts +12 -0
  60. package/src/duration/duration.component.d.ts +68 -0
  61. package/src/duration/duration.module.d.ts +11 -0
  62. package/src/echo/echo.module.d.ts +12 -0
  63. package/src/echo/echo.page.d.ts +34 -0
  64. package/src/errorReporting.service.d.ts +26 -0
  65. package/src/mde/mde.component.d.ts +39 -0
  66. package/src/mde/mde.module.d.ts +12 -0
  67. package/src/mde/mdeToolbar.component.d.ts +5 -0
  68. package/src/offline/cacheableResource.component.d.ts +11 -0
  69. package/src/offline/offline.module.d.ts +12 -0
  70. package/src/offline/offline.service.d.ts +39 -0
  71. package/src/offline/offlineData.service.d.ts +281 -0
  72. package/src/offline/offlineIndicator.component.d.ts +25 -0
  73. package/src/offline/offlineManager.component.d.ts +17 -0
  74. package/src/pushNotifications.service.d.ts +26 -0
  75. package/src/sentiment/sentiment.component.d.ts +35 -0
  76. package/src/sentiment/sentiment.module.d.ts +11 -0
  77. package/src/timeInterval/fromTimeToTime.component.d.ts +61 -0
  78. package/src/timeInterval/timeInterval.component.d.ts +84 -0
  79. package/src/timeInterval/timeInterval.module.d.ts +12 -0
  80. package/src/tinCan.service.d.ts +31 -0
@@ -0,0 +1,479 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import { IDEAStorageService, IDEATranslationsService } from '@idea-ionic/common';
3
+ import { IDEAAWSAPIService } from '../AWSAPI.service';
4
+ import { IDEAOfflineService } from './offline.service';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * After how much time we need to request a synchronisation to keep the contents up-to-date.
8
+ */
9
+ export const SYNC_EXPIRATION_INTERVAL = 1000 * 60 * 60 * 24; // a day
10
+ /**
11
+ * Prefix for the key of the API requests queue info in the local storage.
12
+ */
13
+ export const QUEUE_API_REQUESTS_KEY = 'IDEAOfflineService.queueAPIrequests';
14
+ /**
15
+ * Prefix for the key of the last sync time info in the local storage.
16
+ */
17
+ export const LAST_SYNC_KEY = 'IDEAOfflineService.lastSyncAt';
18
+ /**
19
+ * The max number of elements per resource to synchronize during the first analysis of a synchronisation.
20
+ * If the number of elements exceeds (there is more data after the 1st page), the operation require manual confirmation.
21
+ */
22
+ export const NUM_ELEMENTS_WITHOUT_MANUAL_SYNC = 100;
23
+ /**
24
+ * The max number of elements per resource to request at the same time during a normal synchronisation.
25
+ */
26
+ export const NUM_ELEMENTS_WITH_MANUAL_SYNC = 300;
27
+ /**
28
+ * Manage the offline functioning of the app's data (upload/download/synchronization).
29
+ * Note: it includes all the methods of IDEAOfflineService.
30
+ *
31
+ * Download: it works through the **Delta** mechanism on back-end resources.
32
+ * Practically, the service prepares each possible API GET requests for each of the involved resources.
33
+ * In this way, if offline, the API service can hit an element by URL in the cache (storage offline).
34
+ *
35
+ * **How to use it**. Configure the sync mechanism in the main app.component as it follows:
36
+ *
37
+ * 1. Implement a CacheableResource class for each DeltaResource you want to cache offline.
38
+ * 2. Set up the service (`setUpOfflineData`).
39
+ * 3. Run a synchronization.
40
+ * 4. Add the navigation to the Offline Manager (UI).
41
+ * 5. Optionally, push offline API requests to the queue when offline.
42
+ *
43
+ * e.g. of CacheableResource classes:
44
+ * ```
45
+ * class CustomerCR extends CacheableResource {
46
+ * constructor(description: string) {
47
+ * super(DeltaResources.CUSTOMERS, description);
48
+ * }
49
+ * public listURL(element: any): string {
50
+ * return `teams/${element.teamId}/customers`;
51
+ * }
52
+ * public elementURL(element: any): string {
53
+ * return `teams/${element.teamId}/customers/${element.customerId}`;
54
+ * }
55
+ * public findIndexInList(list: Array<any>, element: any): number {
56
+ * return list.findIndex(x => x.customerId === element.customerId);
57
+ * }
58
+ * public sort(a: any, b: any): number {
59
+ * return a.name.localeCompare(b.name);
60
+ * }
61
+ * }
62
+ */
63
+ export class IDEAOfflineDataService {
64
+ constructor() {
65
+ this._storage = inject(IDEAStorageService);
66
+ this._translate = inject(IDEATranslationsService);
67
+ this._offline = inject(IDEAOfflineService);
68
+ this._API = inject(IDEAAWSAPIService);
69
+ this.queueAPIRequests = new Array();
70
+ this.resources = new Array();
71
+ this.cacheableResources = {};
72
+ // subscribe to network changes
73
+ this._offline.subscribe(isOnline => {
74
+ if (isOnline) {
75
+ // try a synchronization if needed or if the last one failed
76
+ if (this.errorInLastSync)
77
+ this.synchronize();
78
+ else
79
+ this.synchronizeIfNeeded();
80
+ }
81
+ });
82
+ }
83
+ //
84
+ // NETWORK STATUS from IDEAOfflineService
85
+ //
86
+ /**
87
+ * Quickly check the connection status.
88
+ */
89
+ isOnline() {
90
+ return this._offline.isOnline();
91
+ }
92
+ /**
93
+ * Quickly check the connection status.
94
+ */
95
+ isOffline() {
96
+ return this._offline.isOffline();
97
+ }
98
+ /**
99
+ * Subscribe to the service to be notified when the connection status changes.
100
+ */
101
+ subscribe(callback) {
102
+ return this._offline.subscribe(callback);
103
+ }
104
+ /**
105
+ * Quickly check for online connection.
106
+ */
107
+ check() {
108
+ return this._offline.check();
109
+ }
110
+ //
111
+ // CONFIGURATION
112
+ //
113
+ /**
114
+ * Whether the offline mode is allowed. You can customize this function, if needed.
115
+ */
116
+ isAllowed() {
117
+ return !!this.resources.length;
118
+ }
119
+ /**
120
+ * Set up the service to use and sync offline data.
121
+ */
122
+ setUpOfflineData(teamId, useQueueAPIRequests, cacheableResources) {
123
+ // set the team
124
+ this.teamId = teamId;
125
+ // decide if to allow certain API request while offline
126
+ this.useQueueAPIRequests = useQueueAPIRequests;
127
+ // load the API request pending queue, if any
128
+ this.queueAPIRequestKey = this.teamId ? `${QUEUE_API_REQUESTS_KEY}_${this.teamId}` : QUEUE_API_REQUESTS_KEY;
129
+ this.loadQueueAPIRequest();
130
+ // load the lastSyncAt information for the team
131
+ this.lastSyncKey = this.teamId ? `${LAST_SYNC_KEY}_${this.teamId}` : LAST_SYNC_KEY;
132
+ this.loadLastSyncAt();
133
+ // load the cacheable resources
134
+ this.resources = new Array();
135
+ this.cacheableResources = {};
136
+ cacheableResources.forEach(r => this.addCacheableResource(r));
137
+ }
138
+ /**
139
+ * Load from the local storage the last sync at information.
140
+ */
141
+ loadLastSyncAt() {
142
+ return new Promise(resolve => {
143
+ this._storage.get(this.lastSyncKey).then((lastSyncAt) => {
144
+ this.lastSyncAt = lastSyncAt ? Number(lastSyncAt) : null;
145
+ resolve(this.lastSyncAt);
146
+ });
147
+ });
148
+ }
149
+ /**
150
+ * Update last sync at info in the local storage.
151
+ */
152
+ saveLastSyncAt(lastSyncAt) {
153
+ this.lastSyncAt = lastSyncAt;
154
+ return this._storage.set(this.lastSyncKey, lastSyncAt);
155
+ }
156
+ /**
157
+ * Add a CacheableResource.
158
+ */
159
+ addCacheableResource(cacheableResource) {
160
+ if (this.teamId)
161
+ cacheableResource.teamId = this.teamId;
162
+ this.cacheableResources[cacheableResource.resource] = cacheableResource;
163
+ this.resources.push(cacheableResource.resource);
164
+ }
165
+ /**
166
+ * Remove a CacheableResource by its DeltaResource.
167
+ */
168
+ removeCacheableResource(resource) {
169
+ delete this.cacheableResources[resource];
170
+ this.resources.splice(this.resources.indexOf(resource), 1);
171
+ }
172
+ /**
173
+ * Get the the DeltaResourced configured.
174
+ */
175
+ getResources() {
176
+ return this.resources;
177
+ }
178
+ /**
179
+ * Get a CacheableResource by its DeltaResource.
180
+ */
181
+ getCacheableResource(resource) {
182
+ return this.cacheableResources[resource];
183
+ }
184
+ //
185
+ // UPLOAD
186
+ //
187
+ /**
188
+ * Execute all the API requests in the queue; the requests terminated with an error will remain in the queue.
189
+ */
190
+ runQueueAPIRequests() {
191
+ return new Promise((resolve, reject) => {
192
+ if (!this.useQueueAPIRequests || this.isOffline() || !this.queueAPIRequests.length)
193
+ return resolve();
194
+ this.queueAPIRequests.forEach(async (request) => {
195
+ const options = {};
196
+ if (request.resourceId)
197
+ options.resourceId = request.resourceId;
198
+ if (request.body)
199
+ options.body = request.body;
200
+ let promise;
201
+ try {
202
+ switch (request.method.toUpperCase()) {
203
+ case 'POST':
204
+ promise = await this._API.postResource(request.resource, options);
205
+ break;
206
+ case 'PUT':
207
+ promise = await this._API.putResource(request.resource, options);
208
+ break;
209
+ case 'PATCH':
210
+ promise = await this._API.patchResource(request.resource, options);
211
+ break;
212
+ }
213
+ if (!promise)
214
+ request.error = 'INVALID_METHOD';
215
+ else
216
+ request.error = null;
217
+ }
218
+ catch (err) {
219
+ request.error = err.message || 'UNKNOWN_ERROR';
220
+ }
221
+ });
222
+ // keep the requests NOT successfully executed
223
+ this.saveQueueAPIRequest(this.queueAPIRequests.filter(x => x.error)).then(() => {
224
+ // if the queue is empty, the entire operation was successful
225
+ if (this.queueAPIRequests.length)
226
+ reject();
227
+ else
228
+ resolve();
229
+ });
230
+ });
231
+ }
232
+ /**
233
+ * Load from the local storage the API requests queue.
234
+ */
235
+ loadQueueAPIRequest() {
236
+ return new Promise(resolve => {
237
+ if (!this.useQueueAPIRequests)
238
+ return resolve([]);
239
+ this._storage.get(this.queueAPIRequestKey).then((queue) => {
240
+ this.queueAPIRequests = queue || [];
241
+ resolve(this.queueAPIRequests);
242
+ });
243
+ });
244
+ }
245
+ /**
246
+ * Update the queue in memory and also save the copy in the local storage.
247
+ */
248
+ saveQueueAPIRequest(queue) {
249
+ if (!this.isAllowed())
250
+ return Promise.reject();
251
+ this.queueAPIRequests = queue || this.queueAPIRequests;
252
+ return this._storage.set(this.queueAPIRequestKey, this.queueAPIRequests);
253
+ }
254
+ /**
255
+ * Delete a request stuck in an error.
256
+ */
257
+ deleteRequest(request) {
258
+ if (!this.isAllowed())
259
+ return Promise.reject();
260
+ if (request) {
261
+ this.queueAPIRequests.splice(this.queueAPIRequests.indexOf(request), 1);
262
+ this.saveQueueAPIRequest();
263
+ }
264
+ }
265
+ //
266
+ // DOWNLOAD
267
+ //
268
+ /**
269
+ * Save the records of a delta and, if the latter has more pages, go recursive.
270
+ */
271
+ async syncDeltaRecords(delta, done) {
272
+ // for each resource, we reset the status; if a resource still need to be synchronized, it will be flagged below
273
+ this.resources.forEach(resource => {
274
+ this.cacheableResources[resource].error = false;
275
+ this.cacheableResources[resource].synchronizing = false;
276
+ });
277
+ try {
278
+ // synchronze each of the resources included in the delta; this execution can go in parallel
279
+ await Promise.all(delta.resources.map(async (resource) => {
280
+ const cr = this.cacheableResources[resource];
281
+ if (cr) {
282
+ // synchronize the delta records; note: the executuion inside a resource must go in series
283
+ cr.synchronizing = true;
284
+ const success = await this.syncResourceDeltaRecords(resource, delta.records[resource]);
285
+ if (!success)
286
+ this.errorInLastSync = true;
287
+ }
288
+ }));
289
+ // if there were error of if there is nothing left to sync, we are done
290
+ if (this.errorInLastSync || !delta.next)
291
+ return done();
292
+ // otherwise, get the next page of the delta and go recursive until we are done
293
+ const params = { next: delta.next, limit: NUM_ELEMENTS_WITH_MANUAL_SYNC };
294
+ if (this.lastSyncAt)
295
+ params.since = this.lastSyncAt;
296
+ const newDelta = await this._API.getResource(this.teamId ? `teams/${this.teamId}/delta` : 'delta', { params });
297
+ this.syncDeltaRecords(newDelta, done);
298
+ }
299
+ catch (err) {
300
+ // if something went wrong, stops the operation, since we need to make sure the entire flow is consistent
301
+ this.errorInLastSync = true;
302
+ return done();
303
+ }
304
+ }
305
+ /**
306
+ * Save offline a list of DeltaRecords for this resource, creating a map of all the corresponding API GET requests.
307
+ */
308
+ async syncResourceDeltaRecords(resource, records) {
309
+ // acquire the info an a cacheable resource
310
+ const cr = this.cacheableResources[resource];
311
+ if (!cr)
312
+ return Promise.resolve(true);
313
+ try {
314
+ // prepare helpers to group executions of elements of the same list
315
+ let list = null, oldListURL = null;
316
+ for (const r of records) {
317
+ // calculate the URL to access the API request key for this element
318
+ const elementURL = cr.elementURL(r.element);
319
+ // if the element was deleted (based on delta), delete its corresponding API GET request
320
+ if (r.deleted)
321
+ await this._API.deleteFromCache(elementURL);
322
+ // otherwise, update it
323
+ else
324
+ await this._API.putInCache(elementURL, r.element);
325
+ // calculate the URLs to access the API request key for this element's list
326
+ const listURL = cr.listURL(r.element);
327
+ // to improve the performance, get/sort/save the list only when it changes from the previous element's one.
328
+ if (listURL !== oldListURL) {
329
+ // skip first cycle (oldListURL === null)
330
+ if (oldListURL) {
331
+ // re-sort the list; note: it should be sorted from the last time, so we only manage the new element
332
+ list = list.sort(cr.sort);
333
+ // save the updated list
334
+ await this._API.putInCache(oldListURL, list);
335
+ }
336
+ // get the list of elements from the local storage by the calculated URL
337
+ list = await this._API.getFromCache(listURL);
338
+ // save the reference to the list for the next cycle
339
+ oldListURL = listURL;
340
+ }
341
+ // find in the list the element we want to manage
342
+ const index = cr.findIndexInList(list, r.element);
343
+ // delete the element from the list
344
+ if (index !== -1)
345
+ list.splice(index, 1);
346
+ // if the element wasn't deleted (following the delta record information), insert the new version
347
+ if (!r.deleted)
348
+ list.push(r.element);
349
+ }
350
+ // in case there were elements, save the last element's list
351
+ if (oldListURL) {
352
+ // re-sort the list; note: it should be sorted from the last time, so we only manage the new element
353
+ list = list.sort(cr.sort);
354
+ // save the updated list
355
+ await this._API.putInCache(oldListURL, list);
356
+ }
357
+ return Promise.resolve(true);
358
+ }
359
+ catch (err) {
360
+ // if something went wrong, stops the operation, since we need to make sure the entire flow is consistent
361
+ cr.error = true;
362
+ return Promise.resolve(false);
363
+ }
364
+ }
365
+ //
366
+ // SYNCHRONISATION (UPLOAD+DOWNLOAD)
367
+ //
368
+ /**
369
+ * Run a sync, but only if needed, i.e. the cached content expired or we have pending API requests in the queue.
370
+ */
371
+ synchronizeIfNeeded() {
372
+ return new Promise((resolve, reject) => {
373
+ if (!this.isAllowed())
374
+ return;
375
+ this.loadLastSyncAt().then(() => this.loadQueueAPIRequest()
376
+ .then(() => {
377
+ if (this.queueAPIRequests.length || Date.now() > this.lastSyncAt + SYNC_EXPIRATION_INTERVAL)
378
+ this.synchronize();
379
+ resolve();
380
+ })
381
+ .catch(err => reject(err)));
382
+ });
383
+ }
384
+ /**
385
+ * Synchronization of the whole set of resources (upload+download).
386
+ * @param manualConfirmation if true, the request comes directly from a user action (not automatic procedures).
387
+ */
388
+ synchronize(manualConfirmation) {
389
+ return new Promise((resolve, reject) => {
390
+ if (!this.isAllowed() || this.synchronizing)
391
+ return resolve();
392
+ this.synchronizing = true;
393
+ this.errorInLastSync = false;
394
+ this.requiresManualConfirmation = false;
395
+ // load the lastSyncAt information
396
+ this.loadLastSyncAt().then(() =>
397
+ // try to run all the pending API requests in the queue, i.e. uploading the offline resources changed
398
+ this.runQueueAPIRequests()
399
+ .then(() => {
400
+ // set this moment in time: if anything happened before the end of the sync, we don't lose fresh data
401
+ const now = Date.now();
402
+ // prepare a first "short" Delta request, to see if there is a lot of data to process
403
+ const params = { limit: NUM_ELEMENTS_WITHOUT_MANUAL_SYNC };
404
+ if (this.lastSyncAt)
405
+ params.since = this.lastSyncAt;
406
+ this._API
407
+ .getResource(this.teamId ? `teams/${this.teamId}/delta` : 'delta', { params })
408
+ .then((delta) => {
409
+ // decide if to proceed with the sync: in case there is another page, it requires a manual confirmation
410
+ if (delta.next && !manualConfirmation) {
411
+ this.requiresManualConfirmation = true;
412
+ this.synchronizing = false;
413
+ return resolve();
414
+ }
415
+ // save the records in the delta and request possible new pages
416
+ this.syncDeltaRecords(delta, () => {
417
+ if (this.errorInLastSync) {
418
+ this.synchronizing = false;
419
+ resolve();
420
+ }
421
+ else {
422
+ // all the resources are succesfully in sync
423
+ this.resources.forEach(resource => (this.cacheableResources[resource].synchronizing = false));
424
+ // update the timestamp of last sync
425
+ this.saveLastSyncAt(now)
426
+ .then(() => {
427
+ this.synchronizing = false;
428
+ resolve();
429
+ })
430
+ .catch(() => {
431
+ // we couldn't save the last sync info
432
+ this.errorInLastSync = true;
433
+ this.synchronizing = false;
434
+ reject();
435
+ });
436
+ }
437
+ });
438
+ })
439
+ .catch(() => {
440
+ // we couldn't acquire new information (Delta)
441
+ this.errorInLastSync = true;
442
+ this.synchronizing = false;
443
+ reject();
444
+ });
445
+ })
446
+ .catch(() => {
447
+ // we stop, since we don't want backend data to override local info not yet uploaded
448
+ this.errorInLastSync = true;
449
+ this.synchronizing = false;
450
+ reject();
451
+ }));
452
+ });
453
+ }
454
+ /**
455
+ * Force a full synchronisation.
456
+ */
457
+ forceFullSync() {
458
+ this._storage.clear().then(() => this.synchronize(true));
459
+ }
460
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineDataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
461
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineDataService }); }
462
+ }
463
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineDataService, decorators: [{
464
+ type: Injectable
465
+ }], ctorParameters: () => [] });
466
+ /**
467
+ * The abstract class to implement for each resource to cache offline from the back-end (DOWNLOAD).
468
+ */
469
+ export class CacheableResource {
470
+ constructor(resource, description) {
471
+ this.resource = resource;
472
+ this.description = description;
473
+ this.synchronizing = false;
474
+ this.error = false;
475
+ // loaded at runtime
476
+ this.teamId = null;
477
+ }
478
+ }
479
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2ZmbGluZURhdGEuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL21vZHVsZXMvdW5jb21tb24vc3JjL29mZmxpbmUvb2ZmbGluZURhdGEuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUduRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVqRixPQUFPLEVBQUUsaUJBQWlCLEVBQW9CLE1BQU0sbUJBQW1CLENBQUM7QUFDeEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7O0FBRXZEOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsSUFBSSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsUUFBUTtBQUNyRTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLHFDQUFxQyxDQUFDO0FBQzVFOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLCtCQUErQixDQUFDO0FBQzdEOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLEdBQUcsQ0FBQztBQUNwRDs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUFHLEdBQUcsQ0FBQztBQUVqRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQ0c7QUFFSCxNQUFNLE9BQU8sc0JBQXNCO0lBcURqQztRQXBEVSxhQUFRLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDdEMsZUFBVSxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQzdDLGFBQVEsR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUN0QyxTQUFJLEdBQUcsTUFB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MkZBQXRCLHNCQUFzQjtrQkFEbEMsVUFBVTs7QUFxZFg7O0dBRUc7QUFDSCxNQUFNLE9BQWdCLGlCQUFpQjtJQXVCckMsWUFBWSxRQUFnQixFQUFFLFdBQW1CO1FBQy9DLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzNCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztJQUNyQixDQUFDO0NBc0JGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IERlbHRhLCBEZWx0YVJlY29yZCwgRGVsdGFSZXNvdXJjZXMsIGVwb2NoRGF0ZVRpbWUgfSBmcm9tICdpZGVhLXRvb2xib3gnO1xuaW1wb3J0IHsgSURFQVN0b3JhZ2VTZXJ2aWNlLCBJREVBVHJhbnNsYXRpb25zU2VydmljZSB9IGZyb20gJ0BpZGVhLWlvbmljL2NvbW1vbic7XG5cbmltcG9ydCB7IElERUFBV1NBUElTZXJ2aWNlLCBBUElSZXF1ZXN0T3B0aW9uIH0gZnJvbSAnLi4vQVdTQVBJLnNlcnZpY2UnO1xuaW1wb3J0IHsgSURFQU9mZmxpbmVTZXJ2aWNlIH0gZnJvbSAnLi9vZmZsaW5lLnNlcnZpY2UnO1xuXG4vKipcbiAqIEFmdGVyIGhvdyBtdWNoIHRpbWUgd2UgbmVlZCB0byByZXF1ZXN0IGEgc3luY2hyb25pc2F0aW9uIHRvIGtlZXAgdGhlIGNvbnRlbnRzIHVwLXRvLWRhdGUuXG4gKi9cbmV4cG9ydCBjb25zdCBTWU5DX0VYUElSQVRJT05fSU5URVJWQUwgPSAxMDAwICogNjAgKiA2MCAqIDI0OyAvLyBhIGRheVxuLyoqXG4gKiBQcmVmaXggZm9yIHRoZSBrZXkgb2YgdGhlIEFQSSByZXF1ZXN0cyBxdWV1ZSBpbmZvIGluIHRoZSBsb2NhbCBzdG9yYWdlLlxuICovXG5leHBvcnQgY29uc3QgUVVFVUVfQVBJX1JFUVVFU1RTX0tFWSA9ICdJREVBT2ZmbGluZVNlcnZpY2UucXVldWVBUElyZXF1ZXN0cyc7XG4vKipcbiAqIFByZWZpeCBmb3IgdGhlIGtleSBvZiB0aGUgbGFzdCBzeW5jIHRpbWUgaW5mbyBpbiB0aGUgbG9jYWwgc3RvcmFnZS5cbiAqL1xuZXhwb3J0IGNvbnN0IExBU1RfU1lOQ19LRVkgPSAnSURFQU9mZmxpbmVTZXJ2aWNlLmxhc3RTeW5jQXQnO1xuLyoqXG4gKiBUaGUgbWF4IG51bWJlciBvZiBlbGVtZW50cyBwZXIgcmVzb3VyY2UgdG8gc3luY2hyb25pemUgZHVyaW5nIHRoZSBmaXJzdCBhbmFseXNpcyBvZiBhIHN5bmNocm9uaXNhdGlvbi5cbiAqIElmIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgZXhjZWVkcyAodGhlcmUgaXMgbW9yZSBkYXRhIGFmdGVyIHRoZSAxc3QgcGFnZSksIHRoZSBvcGVyYXRpb24gcmVxdWlyZSBtYW51YWwgY29uZmlybWF0aW9uLlxuICovXG5leHBvcnQgY29uc3QgTlVNX0VMRU1FTlRTX1dJVEhPVVRfTUFOVUFMX1NZTkMgPSAxMDA7XG4vKipcbiAqIFRoZSBtYXggbnVtYmVyIG9mIGVsZW1lbnRzIHBlciByZXNvdXJjZSB0byByZXF1ZXN0IGF0IHRoZSBzYW1lIHRpbWUgZHVyaW5nIGEgbm9ybWFsIHN5bmNocm9uaXNhdGlvbi5cbiAqL1xuZXhwb3J0IGNvbnN0IE5VTV9FTEVNRU5UU19XSVRIX01BTlVBTF9TWU5DID0gMzAwO1xuXG4vKipcbiAqIE1hbmFnZSB0aGUgb2ZmbGluZSBmdW5jdGlvbmluZyBvZiB0aGUgYXBwJ3MgZGF0YSAodXBsb2FkL2Rvd25sb2FkL3N5bmNocm9uaXphdGlvbikuXG4gKiBOb3RlOiBpdCBpbmNsdWRlcyBhbGwgdGhlIG1ldGhvZHMgb2YgSURFQU9mZmxpbmVTZXJ2aWNlLlxuICpcbiAqIERvd25sb2FkOiBpdCB3b3JrcyB0aHJvdWdoIHRoZSAqKkRlbHRhKiogbWVjaGFuaXNtIG9uIGJhY2stZW5kIHJlc291cmNlcy5cbiAqIFByYWN0aWNhbGx5LCB0aGUgc2VydmljZSBwcmVwYXJlcyBlYWNoIHBvc3NpYmxlIEFQSSBHRVQgcmVxdWVzdHMgZm9yIGVhY2ggb2YgdGhlIGludm9sdmVkIHJlc291cmNlcy5cbiAqIEluIHRoaXMgd2F5LCBpZiBvZmZsaW5lLCB0aGUgQVBJIHNlcnZpY2UgY2FuIGhpdCBhbiBlbGVtZW50IGJ5IFVSTCBpbiB0aGUgY2FjaGUgKHN0b3JhZ2Ugb2ZmbGluZSkuXG4gKlxuICogKipIb3cgdG8gdXNlIGl0KiouIENvbmZpZ3VyZSB0aGUgc3luYyBtZWNoYW5pc20gaW4gdGhlIG1haW4gYXBwLmNvbXBvbmVudCBhcyBpdCBmb2xsb3dzOlxuICpcbiAqICAgIDEuIEltcGxlbWVudCBhIENhY2hlYWJsZVJlc291cmNlIGNsYXNzIGZvciBlYWNoIERlbHRhUmVzb3VyY2UgeW91IHdhbnQgdG8gY2FjaGUgb2ZmbGluZS5cbiAqICAgIDIuIFNldCB1cCB0aGUgc2VydmljZSAoYHNldFVwT2ZmbGluZURhdGFgKS5cbiAqICAgIDMuIFJ1biBhIHN5bmNocm9uaXphdGlvbi5cbiAqICAgIDQuIEFkZCB0aGUgbmF2aWdhdGlvbiB0byB0aGUgT2ZmbGluZSBNYW5hZ2VyIChVSSkuXG4gKiAgICA1LiBPcHRpb25hbGx5LCBwdXNoIG9mZmxpbmUgQVBJIHJlcXVlc3RzIHRvIHRoZSBxdWV1ZSB3aGVuIG9mZmxpbmUuXG4gKlxuICogZS5nLiBvZiBDYWNoZWFibGVSZXNvdXJjZSBjbGFzc2VzOlxuICogYGBgXG4gKiBjbGFzcyBDdXN0b21lckNSIGV4dGVuZHMgQ2FjaGVhYmxlUmVzb3VyY2Uge1xuICogICBjb25zdHJ1Y3RvcihkZXNjcmlwdGlvbjogc3RyaW5nKSB7XG4gKiAgICAgc3VwZXIoRGVsdGFSZXNvdXJjZXMuQ1VTVE9NRVJTLCBkZXNjcmlwdGlvbik7XG4gKiAgIH1cbiAqICAgcHVibGljIGxpc3RVUkwoZWxlbWVudDogYW55KTogc3RyaW5nIHtcbiAqICAgICByZXR1cm4gYHRlYW1zLyR7ZWxlbWVudC50ZWFtSWR9L2N1c3RvbWVyc2A7XG4gKiAgIH1cbiAqICAgcHVibGljIGVsZW1lbnRVUkwoZWxlbWVudDogYW55KTogc3RyaW5nIHtcbiAqICAgICByZXR1cm4gYHRlYW1zLyR7ZWxlbWVudC50ZWFtSWR9L2N1c3RvbWVycy8ke2VsZW1lbnQuY3VzdG9tZXJJZH1gO1xuICogICB9XG4gKiAgIHB1YmxpYyBmaW5kSW5kZXhJbkxpc3QobGlzdDogQXJyYXk8YW55PiwgZWxlbWVudDogYW55KTogbnVtYmVyIHtcbiAqICAgICByZXR1cm4gbGlzdC5maW5kSW5kZXgoeCA9PiB4LmN1c3RvbWVySWQgPT09IGVsZW1lbnQuY3VzdG9tZXJJZCk7XG4gKiAgIH1cbiAqICAgcHVibGljIHNvcnQoYTogYW55LCBiOiBhbnkpOiBudW1iZXIge1xuICogICAgIHJldHVybiBhLm5hbWUubG9jYWxlQ29tcGFyZShiLm5hbWUpO1xuICogICB9XG4gKiB9XG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBJREVBT2ZmbGluZURhdGFTZXJ2aWNlIHtcbiAgcHJvdGVjdGVkIF9zdG9yYWdlID0gaW5qZWN0KElERUFTdG9yYWdlU2VydmljZSk7XG4gIHByb3RlY3RlZCBfdHJhbnNsYXRlID0gaW5qZWN0KElERUFUcmFuc2xhdGlvbnNTZXJ2aWNlKTtcbiAgcHJvdGVjdGVkIF9vZmZsaW5lID0gaW5qZWN0KElERUFPZmZsaW5lU2VydmljZSk7XG4gIHByb3RlY3RlZCBfQVBJID0gaW5qZWN0KElERUFBV1NBUElTZXJ2aWNlKTtcblxuICAvKipcbiAgICogVHJ1ZSB3aGVuIHJ1bm5pbmcgYSBzeW5jaHJvbml6YXRpb24uXG4gICAqL1xuICBzeW5jaHJvbml6aW5nOiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIHRpbWVzdGFtcCBvZiB0aGUgbGFzdCBzeW5jaHJvbml6YXRpb24uXG4gICAqL1xuICBsYXN0U3luY0F0OiBlcG9jaERhdGVUaW1lO1xuICAvKipcbiAgICogVHJ1ZSBpZiBhbiBlcnJvciBoYXBwZW5lZCBpbiB0aGUgbGFzdCBzeW5jaHJvbml6YXRpb24uXG4gICAqL1xuICBlcnJvckluTGFzdFN5bmM6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUcnVlIGlmIHRoZSBzeW5jaHJvbmlzYXRpb24gaXMgdG9vIHZhc3QgYW5kIHNvIHJlcXVpcmUgYSBtYW51YWwgYWN0aW9uIG9mIHRoZSB1c2VyLlxuICAgKi9cbiAgcmVxdWlyZXNNYW51YWxDb25maXJtYXRpb246IGJvb2xlYW47XG4gIC8qKlxuICAgKiBJZiBmYWxzZSwgaWdub3JlIHRoZSBlbnRpcmUgdXBsb2FkIHNjZW5hcmlvLlxuICAgKi9cbiAgdXNlUXVldWVBUElSZXF1ZXN0czogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSBhcnJheSBvZiB0aGUgcmVxdWVzdHMgbm90IGV4ZWN1dGVkIGJlY2F1c2Ugd2UgYXJlL3dlcmUgb2ZmbGluZTsgdGhleSBuZWVkIHRvIHJ1biBvbmNlIG9ubGluZS5cbiAgICovXG4gIHF1ZXVlQVBJUmVxdWVzdHM6IEFQSVJlcXVlc3RbXTtcblxuICAvKipcbiAgICogVGhlIGlkIG9mIHRoZSB0ZWFtIG9mIHdoaWNoIHRvIG1hbmFnZSBkYXRhIG9mZmxpbmUuXG4gICAqIElmIG51bGwsIHRoZSBwcm9qZWN0IGlzbid0IHRlYW1zLWJhc2VkLlxuICAgKi9cbiAgcHJvdGVjdGVkIHRlYW1JZDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGFycmF5IG9mIERlbHRhUmVzb3VyY2VzIHRvIGNhY2hlIG9mZmxpbmUuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVzb3VyY2VzOiAoRGVsdGFSZXNvdXJjZXMgfCBzdHJpbmcpW107XG4gIC8qKlxuICAgKiBIZWxwZXIgc3RydWN0dXJlIHRvIG1hbmFnZSB0aGUgQ2FjaGVhYmxlUmVzb3VyY2UgZm9yIGVhY2ggRGVsdGFSZXNvdXJjZS5cbiAgICovXG4gIHByb3RlY3RlZCBjYWNoZWFibGVSZXNvdXJjZXM6IHsgW3Jlc291cmNlOiBzdHJpbmddOiBDYWNoZWFibGVSZXNvdXJjZSB9O1xuICAvKipcbiAgICogS2V5IHRvIGFjcXVpcmUgZnJvbSB0aGUgc3RvcmFnZSB0aGUgbGFzdFN5bmNBdCBpbmZvcm1hdGlvbiBvZiB0aGUgdGVhbS5cbiAgICovXG4gIHByb3RlY3RlZCBsYXN0U3luY0tleTogc3RyaW5nO1xuICAvKipcbiAgICogS2V5IHRvIGFjcXVpcmUgZnJvbSB0aGUgc3RvcmFnZSB0aGUgbGFzdFN5bmNBdCBpbmZvcm1hdGlvbiBvZiB0aGUgdGVhbS5cbiAgICovXG4gIHByb3RlY3RlZCBxdWV1ZUFQSVJlcXVlc3RLZXk6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnF1ZXVlQVBJUmVxdWVzdHMgPSBuZXcgQXJyYXk8QVBJUmVxdWVzdD4oKTtcbiAgICB0aGlzLnJlc291cmNlcyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gICAgdGhpcy5jYWNoZWFibGVSZXNvdXJjZXMgPSB7fTtcbiAgICAvLyBzdWJzY3JpYmUgdG8gbmV0d29yayBjaGFuZ2VzXG4gICAgdGhpcy5fb2ZmbGluZS5zdWJzY3JpYmUoaXNPbmxpbmUgPT4ge1xuICAgICAgaWYgKGlzT25saW5lKSB7XG4gICAgICAgIC8vIHRyeSBhIHN5bmNocm9uaXphdGlvbiBpZiBuZWVkZWQgb3IgaWYgdGhlIGxhc3Qgb25lIGZhaWxlZFxuICAgICAgICBpZiAodGhpcy5lcnJvckluTGFzdFN5bmMpIHRoaXMuc3luY2hyb25pemUoKTtcbiAgICAgICAgZWxzZSB0aGlzLnN5bmNocm9uaXplSWZOZWVkZWQoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vXG4gIC8vIE5FVFdPUksgU1RBVFVTIGZyb20gSURFQU9mZmxpbmVTZXJ2aWNlXG4gIC8vXG5cbiAgLyoqXG4gICAqIFF1aWNrbHkgY2hlY2sgdGhlIGNvbm5lY3Rpb24gc3RhdHVzLlxuICAgKi9cbiAgaXNPbmxpbmUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX29mZmxpbmUuaXNPbmxpbmUoKTtcbiAgfVxuICAvKipcbiAgICogUXVpY2tseSBjaGVjayB0aGUgY29ubmVjdGlvbiBzdGF0dXMuXG4gICAqL1xuICBpc09mZmxpbmUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX29mZmxpbmUuaXNPZmZsaW5lKCk7XG4gIH1cbiAgLyoqXG4gICAqIFN1YnNjcmliZSB0byB0aGUgc2VydmljZSB0byBiZSBub3RpZmllZCB3aGVuIHRoZSBjb25uZWN0aW9uIHN0YXR1cyBjaGFuZ2VzLlxuICAgKi9cbiAgc3Vic2NyaWJlKGNhbGxiYWNrOiAoaXNPbmxpbmU6IGJvb2xlYW4pID0+IHZvaWQpOiBTdWJzY3JpcHRpb24ge1xuICAgIHJldHVybiB0aGlzLl9vZmZsaW5lLnN1YnNjcmliZShjYWxsYmFjayk7XG4gIH1cbiAgLyoqXG4gICAqIFF1aWNrbHkgY2hlY2sgZm9yIG9ubGluZSBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHVibGljIGNoZWNrKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLl9vZmZsaW5lLmNoZWNrKCk7XG4gIH1cblxuICAvL1xuICAvLyBDT05GSUdVUkFUSU9OXG4gIC8vXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIG9mZmxpbmUgbW9kZSBpcyBhbGxvd2VkLiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGlzIGZ1bmN0aW9uLCBpZiBuZWVkZWQuXG4gICAqL1xuICBpc0FsbG93ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5yZXNvdXJjZXMubGVuZ3RoO1xuICB9XG4gIC8qKlxuICAgKiBTZXQgdXAgdGhlIHNlcnZpY2UgdG8gdXNlIGFuZCBzeW5jIG9mZmxpbmUgZGF0YS5cbiAgICovXG4gIHNldFVwT2ZmbGluZURhdGEodGVhbUlkOiBzdHJpbmcsIHVzZVF1ZXVlQVBJUmVxdWVzdHM6IGJvb2xlYW4sIGNhY2hlYWJsZVJlc291cmNlczogQ2FjaGVhYmxlUmVzb3VyY2VbXSk6IHZvaWQge1xuICAgIC8vIHNldCB0aGUgdGVhbVxuICAgIHRoaXMudGVhbUlkID0gdGVhbUlkO1xuICAgIC8vIGRlY2lkZSBpZiB0byBhbGxvdyBjZXJ0YWluIEFQSSByZXF1ZXN0IHdoaWxlIG9mZmxpbmVcbiAgICB0aGlzLnVzZVF1ZXVlQVBJUmVxdWVzdHMgPSB1c2VRdWV1ZUFQSVJlcXVlc3RzO1xuICAgIC8vIGxvYWQgdGhlIEFQSSByZXF1ZXN0IHBlbmRpbmcgcXVldWUsIGlmIGFueVxuICAgIHRoaXMucXVldWVBUElSZXF1ZXN0S2V5ID0gdGhpcy50ZWFtSWQgPyBgJHtRVUVVRV9BUElfUkVRVUVTVFNfS0VZfV8ke3RoaXMudGVhbUlkfWAgOiBRVUVVRV9BUElfUkVRVUVTVFNfS0VZO1xuICAgIHRoaXMubG9hZFF1ZXVlQVBJUmVxdWVzdCgpO1xuICAgIC8vIGxvYWQgdGhlIGxhc3RTeW5jQXQgaW5mb3JtYXRpb24gZm9yIHRoZSB0ZWFtXG4gICAgdGhpcy5sYXN0U3luY0tleSA9IHRoaXMudGVhbUlkID8gYCR7TEFTVF9TWU5DX0tFWX1fJHt0aGlzLnRlYW1JZH1gIDogTEFTVF9TWU5DX0tFWTtcbiAgICB0aGlzLmxvYWRMYXN0U3luY0F0KCk7XG4gICAgLy8gbG9hZCB0aGUgY2FjaGVhYmxlIHJlc291cmNlc1xuICAgIHRoaXMucmVzb3VyY2VzID0gbmV3IEFycmF5PERlbHRhUmVzb3VyY2VzIHwgc3RyaW5nPigpO1xuICAgIHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzID0ge307XG4gICAgY2FjaGVhYmxlUmVzb3VyY2VzLmZvckVhY2gociA9PiB0aGlzLmFkZENhY2hlYWJsZVJlc291cmNlKHIpKTtcbiAgfVxuICAvKipcbiAgICogTG9hZCBmcm9tIHRoZSBsb2NhbCBzdG9yYWdlIHRoZSBsYXN0IHN5bmMgYXQgaW5mb3JtYXRpb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgbG9hZExhc3RTeW5jQXQoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICB0aGlzLl9zdG9yYWdlLmdldCh0aGlzLmxhc3RTeW5jS2V5KS50aGVuKChsYXN0U3luY0F0OiBudW1iZXIpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5sYXN0U3luY0F0ID0gbGFzdFN5bmNBdCA/IE51bWJlcihsYXN0U3luY0F0KSA6IG51bGw7XG4gICAgICAgIHJlc29sdmUodGhpcy5sYXN0U3luY0F0KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBVcGRhdGUgbGFzdCBzeW5jIGF0IGluZm8gaW4gdGhlIGxvY2FsIHN0b3JhZ2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZUxhc3RTeW5jQXQobGFzdFN5bmNBdDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5sYXN0U3luY0F0ID0gbGFzdFN5bmNBdDtcbiAgICByZXR1cm4gdGhpcy5fc3RvcmFnZS5zZXQodGhpcy5sYXN0U3luY0tleSwgbGFzdFN5bmNBdCk7XG4gIH1cbiAgLyoqXG4gICAqIEFkZCBhIENhY2hlYWJsZVJlc291cmNlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFkZENhY2hlYWJsZVJlc291cmNlKGNhY2hlYWJsZVJlc291cmNlOiBDYWNoZWFibGVSZXNvdXJjZSk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRlYW1JZCkgY2FjaGVhYmxlUmVzb3VyY2UudGVhbUlkID0gdGhpcy50ZWFtSWQ7XG4gICAgdGhpcy5jYWNoZWFibGVSZXNvdXJjZXNbY2FjaGVhYmxlUmVzb3VyY2UucmVzb3VyY2VdID0gY2FjaGVhYmxlUmVzb3VyY2U7XG4gICAgdGhpcy5yZXNvdXJjZXMucHVzaChjYWNoZWFibGVSZXNvdXJjZS5yZXNvdXJjZSk7XG4gIH1cbiAgLyoqXG4gICAqIFJlbW92ZSBhIENhY2hlYWJsZVJlc291cmNlIGJ5IGl0cyBEZWx0YVJlc291cmNlLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlbW92ZUNhY2hlYWJsZVJlc291cmNlKHJlc291cmNlOiBEZWx0YVJlc291cmNlcyB8IHN0cmluZyk6IHZvaWQge1xuICAgIGRlbGV0ZSB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV07XG4gICAgdGhpcy5yZXNvdXJjZXMuc3BsaWNlKHRoaXMucmVzb3VyY2VzLmluZGV4T2YocmVzb3VyY2UpLCAxKTtcbiAgfVxuICAvKipcbiAgICogR2V0IHRoZSB0aGUgRGVsdGFSZXNvdXJjZWQgY29uZmlndXJlZC5cbiAgICovXG4gIGdldFJlc291cmNlcygpOiAoRGVsdGFSZXNvdXJjZXMgfCBzdHJpbmcpW10ge1xuICAgIHJldHVybiB0aGlzLnJlc291cmNlcztcbiAgfVxuICAvKipcbiAgICogR2V0IGEgQ2FjaGVhYmxlUmVzb3VyY2UgYnkgaXRzIERlbHRhUmVzb3VyY2UuXG4gICAqL1xuICBnZXRDYWNoZWFibGVSZXNvdXJjZShyZXNvdXJjZTogRGVsdGFSZXNvdXJjZXMgfCBzdHJpbmcpOiBDYWNoZWFibGVSZXNvdXJjZSB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzW3Jlc291cmNlXTtcbiAgfVxuXG4gIC8vXG4gIC8vIFVQTE9BRFxuICAvL1xuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGFsbCB0aGUgQVBJIHJlcXVlc3RzIGluIHRoZSBxdWV1ZTsgdGhlIHJlcXVlc3RzIHRlcm1pbmF0ZWQgd2l0aCBhbiBlcnJvciB3aWxsIHJlbWFpbiBpbiB0aGUgcXVldWUuXG4gICAqL1xuICBwcm90ZWN0ZWQgcnVuUXVldWVBUElSZXF1ZXN0cygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgaWYgKCF0aGlzLnVzZVF1ZXVlQVBJUmVxdWVzdHMgfHwgdGhpcy5pc09mZmxpbmUoKSB8fCAhdGhpcy5xdWV1ZUFQSVJlcXVlc3RzLmxlbmd0aCkgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgIHRoaXMucXVldWVBUElSZXF1ZXN0cy5mb3JFYWNoKGFzeW5jIHJlcXVlc3QgPT4ge1xuICAgICAgICBjb25zdCBvcHRpb25zOiBBUElSZXF1ZXN0T3B0aW9uID0ge307XG4gICAgICAgIGlmIChyZXF1ZXN0LnJlc291cmNlSWQpIG9wdGlvbnMucmVzb3VyY2VJZCA9IHJlcXVlc3QucmVzb3VyY2VJZDtcbiAgICAgICAgaWYgKHJlcXVlc3QuYm9keSkgb3B0aW9ucy5ib2R5ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICBsZXQgcHJvbWlzZTogUHJvbWlzZTxhbnk+O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHN3aXRjaCAocmVxdWVzdC5tZXRob2QudG9VcHBlckNhc2UoKSkge1xuICAgICAgICAgICAgY2FzZSAnUE9TVCc6XG4gICAgICAgICAgICAgIHByb21pc2UgPSBhd2FpdCB0aGlzLl9BUEkucG9zdFJlc291cmNlKHJlcXVlc3QucmVzb3VyY2UsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ1BVVCc6XG4gICAgICAgICAgICAgIHByb21pc2UgPSBhd2FpdCB0aGlzLl9BUEkucHV0UmVzb3VyY2UocmVxdWVzdC5yZXNvdXJjZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnUEFUQ0gnOlxuICAgICAgICAgICAgICBwcm9taXNlID0gYXdhaXQgdGhpcy5fQVBJLnBhdGNoUmVzb3VyY2UocmVxdWVzdC5yZXNvdXJjZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIXByb21pc2UpIHJlcXVlc3QuZXJyb3IgPSAnSU5WQUxJRF9NRVRIT0QnO1xuICAgICAgICAgIGVsc2UgcmVxdWVzdC5lcnJvciA9IG51bGw7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIHJlcXVlc3QuZXJyb3IgPSAoZXJyIGFzIEVycm9yKS5tZXNzYWdlIHx8ICdVTktOT1dOX0VSUk9SJztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICAvLyBrZWVwIHRoZSByZXF1ZXN0cyBOT1Qgc3VjY2Vzc2Z1bGx5IGV4ZWN1dGVkXG4gICAgICB0aGlzLnNhdmVRdWV1ZUFQSVJlcXVlc3QodGhpcy5xdWV1ZUFQSVJlcXVlc3RzLmZpbHRlcih4ID0+IHguZXJyb3IpKS50aGVuKCgpOiB2b2lkID0+IHtcbiAgICAgICAgLy8gaWYgdGhlIHF1ZXVlIGlzIGVtcHR5LCB0aGUgZW50aXJlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bFxuICAgICAgICBpZiAodGhpcy5xdWV1ZUFQSVJlcXVlc3RzLmxlbmd0aCkgcmVqZWN0KCk7XG4gICAgICAgIGVsc2UgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIExvYWQgZnJvbSB0aGUgbG9jYWwgc3RvcmFnZSB0aGUgQVBJIHJlcXVlc3RzIHF1ZXVlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGxvYWRRdWV1ZUFQSVJlcXVlc3QoKTogUHJvbWlzZTxBUElSZXF1ZXN0W10+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBpZiAoIXRoaXMudXNlUXVldWVBUElSZXF1ZXN0cykgcmV0dXJuIHJlc29sdmUoW10pO1xuICAgICAgdGhpcy5fc3RvcmFnZS5nZXQodGhpcy5xdWV1ZUFQSVJlcXVlc3RLZXkpLnRoZW4oKHF1ZXVlOiBBUElSZXF1ZXN0W10pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzID0gcXVldWUgfHwgW107XG4gICAgICAgIHJlc29sdmUodGhpcy5xdWV1ZUFQSVJlcXVlc3RzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBVcGRhdGUgdGhlIHF1ZXVlIGluIG1lbW9yeSBhbmQgYWxzbyBzYXZlIHRoZSBjb3B5IGluIHRoZSBsb2NhbCBzdG9yYWdlLlxuICAgKi9cbiAgc2F2ZVF1ZXVlQVBJUmVxdWVzdChxdWV1ZT86IEFQSVJlcXVlc3RbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5pc0FsbG93ZWQoKSkgcmV0dXJuIFByb21pc2UucmVqZWN0KCk7XG4gICAgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzID0gcXVldWUgfHwgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzO1xuICAgIHJldHVybiB0aGlzLl9zdG9yYWdlLnNldCh0aGlzLnF1ZXVlQVBJUmVxdWVzdEtleSwgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzKTtcbiAgfVxuICAvKipcbiAgICogRGVsZXRlIGEgcmVxdWVzdCBzdHVjayBpbiBhbiBlcnJvci5cbiAgICovXG4gIGRlbGV0ZVJlcXVlc3QocmVxdWVzdDogQVBJUmVxdWVzdCkge1xuICAgIGlmICghdGhpcy5pc0FsbG93ZWQoKSkgcmV0dXJuIFByb21pc2UucmVqZWN0KCk7XG4gICAgaWYgKHJlcXVlc3QpIHtcbiAgICAgIHRoaXMucXVldWVBUElSZXF1ZXN0cy5zcGxpY2UodGhpcy5xdWV1ZUFQSVJlcXVlc3RzLmluZGV4T2YocmVxdWVzdCksIDEpO1xuICAgICAgdGhpcy5zYXZlUXVldWVBUElSZXF1ZXN0KCk7XG4gICAgfVxuICB9XG5cbiAgLy9cbiAgLy8gRE9XTkxPQURcbiAgLy9cblxuICAvKipcbiAgICogU2F2ZSB0aGUgcmVjb3JkcyBvZiBhIGRlbHRhIGFuZCwgaWYgdGhlIGxhdHRlciBoYXMgbW9yZSBwYWdlcywgZ28gcmVjdXJzaXZlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHN5bmNEZWx0YVJlY29yZHMoZGVsdGE6IERlbHRhLCBkb25lPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAvLyBmb3IgZWFjaCByZXNvdXJjZSwgd2UgcmVzZXQgdGhlIHN0YXR1czsgaWYgYSByZXNvdXJjZSBzdGlsbCBuZWVkIHRvIGJlIHN5bmNocm9uaXplZCwgaXQgd2lsbCBiZSBmbGFnZ2VkIGJlbG93XG4gICAgdGhpcy5yZXNvdXJjZXMuZm9yRWFjaChyZXNvdXJjZSA9PiB7XG4gICAgICB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV0uZXJyb3IgPSBmYWxzZTtcbiAgICAgIHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzW3Jlc291cmNlXS5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgfSk7XG4gICAgdHJ5IHtcbiAgICAgIC8vIHN5bmNocm9uemUgZWFjaCBvZiB0aGUgcmVzb3VyY2VzIGluY2x1ZGVkIGluIHRoZSBkZWx0YTsgdGhpcyBleGVjdXRpb24gY2FuIGdvIGluIHBhcmFsbGVsXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZGVsdGEucmVzb3VyY2VzLm1hcChhc3luYyByZXNvdXJjZSA9PiB7XG4gICAgICAgICAgY29uc3QgY3IgPSB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV07XG4gICAgICAgICAgaWYgKGNyKSB7XG4gICAgICAgICAgICAvLyBzeW5jaHJvbml6ZSB0aGUgZGVsdGEgcmVjb3Jkczsgbm90ZTogdGhlIGV4ZWN1dHVpb24gaW5zaWRlIGEgcmVzb3VyY2UgbXVzdCBnbyBpbiBzZXJpZXNcbiAgICAgICAgICAgIGNyLnN5bmNocm9uaXppbmcgPSB0cnVlO1xuICAgICAgICAgICAgY29uc3Qgc3VjY2VzcyA9IGF3YWl0IHRoaXMuc3luY1Jlc291cmNlRGVsdGFSZWNvcmRzKHJlc291cmNlLCBkZWx0YS5yZWNvcmRzW3Jlc291cmNlXSk7XG4gICAgICAgICAgICBpZiAoIXN1Y2Nlc3MpIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgICAgLy8gaWYgdGhlcmUgd2VyZSBlcnJvciBvZiBpZiB0aGVyZSBpcyBub3RoaW5nIGxlZnQgdG8gc3luYywgd2UgYXJlIGRvbmVcbiAgICAgIGlmICh0aGlzLmVycm9ySW5MYXN0U3luYyB8fCAhZGVsdGEubmV4dCkgcmV0dXJuIGRvbmUoKTtcbiAgICAgIC8vIG90aGVyd2lzZSwgZ2V0IHRoZSBuZXh0IHBhZ2Ugb2YgdGhlIGRlbHRhIGFuZCBnbyByZWN1cnNpdmUgdW50aWwgd2UgYXJlIGRvbmVcbiAgICAgIGNvbnN0IHBhcmFtczogYW55ID0geyBuZXh0OiBkZWx0YS5uZXh0LCBsaW1pdDogTlVNX0VMRU1FTlRTX1dJVEhfTUFOVUFMX1NZTkMgfTtcbiAgICAgIGlmICh0aGlzLmxhc3RTeW5jQXQpIHBhcmFtcy5zaW5jZSA9IHRoaXMubGFzdFN5bmNBdDtcbiAgICAgIGNvbnN0IG5ld0RlbHRhID0gYXdhaXQgdGhpcy5fQVBJLmdldFJlc291cmNlKHRoaXMudGVhbUlkID8gYHRlYW1zLyR7dGhpcy50ZWFtSWR9L2RlbHRhYCA6ICdkZWx0YScsIHsgcGFyYW1zIH0pO1xuICAgICAgdGhpcy5zeW5jRGVsdGFSZWNvcmRzKG5ld0RlbHRhLCBkb25lKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIGlmIHNvbWV0aGluZyB3ZW50IHdyb25nLCBzdG9wcyB0aGUgb3BlcmF0aW9uLCBzaW5jZSB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUgZW50aXJlIGZsb3cgaXMgY29uc2lzdGVudFxuICAgICAgdGhpcy5lcnJvckluTGFzdFN5bmMgPSB0cnVlO1xuICAgICAgcmV0dXJuIGRvbmUoKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIFNhdmUgb2ZmbGluZSBhIGxpc3Qgb2YgRGVsdGFSZWNvcmRzIGZvciB0aGlzIHJlc291cmNlLCBjcmVhdGluZyBhIG1hcCBvZiBhbGwgdGhlIGNvcnJlc3BvbmRpbmcgQVBJIEdFVCByZXF1ZXN0cy5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBzeW5jUmVzb3VyY2VEZWx0YVJlY29yZHMocmVzb3VyY2U6IHN0cmluZywgcmVjb3JkczogRGVsdGFSZWNvcmRbXSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIGFjcXVpcmUgdGhlIGluZm8gYW4gYSBjYWNoZWFibGUgcmVzb3VyY2VcbiAgICBjb25zdCBjciA9IHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzW3Jlc291cmNlXTtcbiAgICBpZiAoIWNyKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuICAgIHRyeSB7XG4gICAgICAvLyBwcmVwYXJlIGhlbHBlcnMgdG8gZ3JvdXAgZXhlY3V0aW9ucyBvZiBlbGVtZW50cyBvZiB0aGUgc2FtZSBsaXN0XG4gICAgICBsZXQgbGlzdDogYW55W10gPSBudWxsLFxuICAgICAgICBvbGRMaXN0VVJMOiBzdHJpbmcgPSBudWxsO1xuICAgICAgZm9yIChjb25zdCByIG9mIHJlY29yZHMpIHtcbiAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBVUkwgdG8gYWNjZXNzIHRoZSBBUEkgcmVxdWVzdCBrZXkgZm9yIHRoaXMgZWxlbWVudFxuICAgICAgICBjb25zdCBlbGVtZW50VVJMID0gY3IuZWxlbWVudFVSTChyLmVsZW1lbnQpO1xuICAgICAgICAvLyBpZiB0aGUgZWxlbWVudCB3YXMgZGVsZXRlZCAoYmFzZWQgb24gZGVsdGEpLCBkZWxldGUgaXRzIGNvcnJlc3BvbmRpbmcgQVBJIEdFVCByZXF1ZXN0XG4gICAgICAgIGlmIChyLmRlbGV0ZWQpIGF3YWl0IHRoaXMuX0FQSS5kZWxldGVGcm9tQ2FjaGUoZWxlbWVudFVSTCk7XG4gICAgICAgIC8vIG90aGVyd2lzZSwgdXBkYXRlIGl0XG4gICAgICAgIGVsc2UgYXdhaXQgdGhpcy5fQVBJLnB1dEluQ2FjaGUoZWxlbWVudFVSTCwgci5lbGVtZW50KTtcbiAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBVUkxzIHRvIGFjY2VzcyB0aGUgQVBJIHJlcXVlc3Qga2V5IGZvciB0aGlzIGVsZW1lbnQncyBsaXN0XG4gICAgICAgIGNvbnN0IGxpc3RVUkwgPSBjci5saXN0VVJMKHIuZWxlbWVudCk7XG4gICAgICAgIC8vIHRvIGltcHJvdmUgdGhlIHBlcmZvcm1hbmNlLCBnZXQvc29ydC9zYXZlIHRoZSBsaXN0IG9ubHkgd2hlbiBpdCBjaGFuZ2VzIGZyb20gdGhlIHByZXZpb3VzIGVsZW1lbnQncyBvbmUuXG4gICAgICAgIGlmIChsaXN0VVJMICE9PSBvbGRMaXN0VVJMKSB7XG4gICAgICAgICAgLy8gc2tpcCBmaXJzdCBjeWNsZSAob2xkTGlzdFVSTCA9PT0gbnVsbClcbiAgICAgICAgICBpZiAob2xkTGlzdFVSTCkge1xuICAgICAgICAgICAgLy8gcmUtc29ydCB0aGUgbGlzdDsgbm90ZTogaXQgc2hvdWxkIGJlIHNvcnRlZCBmcm9tIHRoZSBsYXN0IHRpbWUsIHNvIHdlIG9ubHkgbWFuYWdlIHRoZSBuZXcgZWxlbWVudFxuICAgICAgICAgICAgbGlzdCA9IGxpc3Quc29ydChjci5zb3J0KTtcbiAgICAgICAgICAgIC8vIHNhdmUgdGhlIHVwZGF0ZWQgbGlzdFxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fQVBJLnB1dEluQ2FjaGUob2xkTGlzdFVSTCwgbGlzdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGdldCB0aGUgbGlzdCBvZiBlbGVtZW50cyBmcm9tIHRoZSBsb2NhbCBzdG9yYWdlIGJ5IHRoZSBjYWxjdWxhdGVkIFVSTFxuICAgICAgICAgIGxpc3QgPSBhd2FpdCB0aGlzLl9BUEkuZ2V0RnJvbUNhY2hlKGxpc3RVUkwpO1xuICAgICAgICAgIC8vIHNhdmUgdGhlIHJlZmVyZW5jZSB0byB0aGUgbGlzdCBmb3IgdGhlIG5leHQgY3ljbGVcbiAgICAgICAgICBvbGRMaXN0VVJMID0gbGlzdFVSTDtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaW5kIGluIHRoZSBsaXN0IHRoZSBlbGVtZW50IHdlIHdhbnQgdG8gbWFuYWdlXG4gICAgICAgIGNvbnN0IGluZGV4ID0gY3IuZmluZEluZGV4SW5MaXN0KGxpc3QsIHIuZWxlbWVudCk7XG4gICAgICAgIC8vIGRlbGV0ZSB0aGUgZWxlbWVudCBmcm9tIHRoZSBsaXN0XG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEpIGxpc3Quc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgLy8gaWYgdGhlIGVsZW1lbnQgd2Fzbid0IGRlbGV0ZWQgKGZvbGxvd2luZyB0aGUgZGVsdGEgcmVjb3JkIGluZm9ybWF0aW9uKSwgaW5zZXJ0IHRoZSBuZXcgdmVyc2lvblxuICAgICAgICBpZiAoIXIuZGVsZXRlZCkgbGlzdC5wdXNoKHIuZWxlbWVudCk7XG4gICAgICB9XG4gICAgICAvLyBpbiBjYXNlIHRoZXJlIHdlcmUgZWxlbWVudHMsIHNhdmUgdGhlIGxhc3QgZWxlbWVudCdzIGxpc3RcbiAgICAgIGlmIChvbGRMaXN0VVJMKSB7XG4gICAgICAgIC8vIHJlLXNvcnQgdGhlIGxpc3Q7IG5vdGU6IGl0IHNob3VsZCBiZSBzb3J0ZWQgZnJvbSB0aGUgbGFzdCB0aW1lLCBzbyB3ZSBvbmx5IG1hbmFnZSB0aGUgbmV3IGVsZW1lbnRcbiAgICAgICAgbGlzdCA9IGxpc3Quc29ydChjci5zb3J0KTtcbiAgICAgICAgLy8gc2F2ZSB0aGUgdXBkYXRlZCBsaXN0XG4gICAgICAgIGF3YWl0IHRoaXMuX0FQSS5wdXRJbkNhY2hlKG9sZExpc3RVUkwsIGxpc3QpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIGlmIHNvbWV0aGluZyB3ZW50IHdyb25nLCBzdG9wcyB0aGUgb3BlcmF0aW9uLCBzaW5jZSB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUgZW50aXJlIGZsb3cgaXMgY29uc2lzdGVudFxuICAgICAgY3IuZXJyb3IgPSB0cnVlO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgLy9cbiAgLy8gU1lOQ0hST05JU0FUSU9OIChVUExPQUQrRE9XTkxPQUQpXG4gIC8vXG5cbiAgLyoqXG4gICAqIFJ1biBhIHN5bmMsIGJ1dCBvbmx5IGlmIG5lZWRlZCwgaS5lLiB0aGUgY2FjaGVkIGNvbnRlbnQgZXhwaXJlZCBvciB3ZSBoYXZlIHBlbmRpbmcgQVBJIHJlcXVlc3RzIGluIHRoZSBxdWV1ZS5cbiAgICovXG4gIHN5bmNocm9uaXplSWZOZWVkZWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGlmICghdGhpcy5pc0FsbG93ZWQoKSkgcmV0dXJuO1xuICAgICAgdGhpcy5sb2FkTGFzdFN5bmNBdCgpLnRoZW4oXG4gICAgICAgICgpOiBQcm9taXNlPHZvaWQ+ID0+XG4gICAgICAgICAgdGhpcy5sb2FkUXVldWVBUElSZXF1ZXN0KClcbiAgICAgICAgICAgIC50aGVuKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMucXVldWVBUElSZXF1ZXN0cy5sZW5ndGggfHwgRGF0ZS5ub3coKSA+IHRoaXMubGFzdFN5bmNBdCArIFNZTkNfRVhQSVJBVElPTl9JTlRFUlZBTClcbiAgICAgICAgICAgICAgICB0aGlzLnN5bmNocm9uaXplKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyID0+IHJlamVjdChlcnIpKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogU3luY2hyb25pemF0aW9uIG9mIHRoZSB3aG9sZSBzZXQgb2YgcmVzb3VyY2VzICh1cGxvYWQrZG93bmxvYWQpLlxuICAgKiBAcGFyYW0gbWFudWFsQ29uZmlybWF0aW9uIGlmIHRydWUsIHRoZSByZXF1ZXN0IGNvbWVzIGRpcmVjdGx5IGZyb20gYSB1c2VyIGFjdGlvbiAobm90IGF1dG9tYXRpYyBwcm9jZWR1cmVzKS5cbiAgICovXG4gIHN5bmNocm9uaXplKG1hbnVhbENvbmZpcm1hdGlvbj86IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgaWYgKCF0aGlzLmlzQWxsb3dlZCgpIHx8IHRoaXMuc3luY2hyb25pemluZykgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IHRydWU7XG4gICAgICB0aGlzLmVycm9ySW5MYXN0U3luYyA9IGZhbHNlO1xuICAgICAgdGhpcy5yZXF1aXJlc01hbnVhbENvbmZpcm1hdGlvbiA9IGZhbHNlO1xuICAgICAgLy8gbG9hZCB0aGUgbGFzdFN5bmNBdCBpbmZvcm1hdGlvblxuICAgICAgdGhpcy5sb2FkTGFzdFN5bmNBdCgpLnRoZW4oXG4gICAgICAgICgpOiBQcm9taXNlPHZvaWQ+ID0+XG4gICAgICAgICAgLy8gdHJ5IHRvIHJ1biBhbGwgdGhlIHBlbmRpbmcgQVBJIHJlcXVlc3RzIGluIHRoZSBxdWV1ZSwgaS5lLiB1cGxvYWRpbmcgdGhlIG9mZmxpbmUgcmVzb3VyY2VzIGNoYW5nZWRcbiAgICAgICAgICB0aGlzLnJ1blF1ZXVlQVBJUmVxdWVzdHMoKVxuICAgICAgICAgICAgLnRoZW4oKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgICAvLyBzZXQgdGhpcyBtb21lbnQgaW4gdGltZTogaWYgYW55dGhpbmcgaGFwcGVuZWQgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIHN5bmMsIHdlIGRvbid0IGxvc2UgZnJlc2ggZGF0YVxuICAgICAgICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAvLyBwcmVwYXJlIGEgZmlyc3QgXCJzaG9ydFwiIERlbHRhIHJlcXVlc3QsIHRvIHNlZSBpZiB0aGVyZSBpcyBhIGxvdCBvZiBkYXRhIHRvIHByb2Nlc3NcbiAgICAgICAgICAgICAgY29uc3QgcGFyYW1zOiBhbnkgPSB7IGxpbWl0OiBOVU1fRUxFTUVOVFNfV0lUSE9VVF9NQU5VQUxfU1lOQyB9O1xuICAgICAgICAgICAgICBpZiAodGhpcy5sYXN0U3luY0F0KSBwYXJhbXMuc2luY2UgPSB0aGlzLmxhc3RTeW5jQXQ7XG4gICAgICAgICAgICAgIHRoaXMuX0FQSVxuICAgICAgICAgICAgICAgIC5nZXRSZXNvdXJjZSh0aGlzLnRlYW1JZCA/IGB0ZWFtcy8ke3RoaXMudGVhbUlkfS9kZWx0YWAgOiAnZGVsdGEnLCB7IHBhcmFtcyB9KVxuICAgICAgICAgICAgICAgIC50aGVuKChkZWx0YTogRGVsdGEpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgIC8vIGRlY2lkZSBpZiB0byBwcm9jZWVkIHdpdGggdGhlIHN5bmM6IGluIGNhc2UgdGhlcmUgaXMgYW5vdGhlciBwYWdlLCBpdCByZXF1aXJlcyBhIG1hbnVhbCBjb25maXJtYXRpb25cbiAgICAgICAgICAgICAgICAgIGlmIChkZWx0YS5uZXh0ICYmICFtYW51YWxDb25maXJtYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXF1aXJlc01hbnVhbENvbmZpcm1hdGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgLy8gc2F2ZSB0aGUgcmVjb3JkcyBpbiB0aGUgZGVsdGEgYW5kIHJlcXVlc3QgcG9zc2libGUgbmV3IHBhZ2VzXG4gICAgICAgICAgICAgICAgICB0aGlzLnN5bmNEZWx0YVJlY29yZHMoZGVsdGEsICgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZXJyb3JJbkxhc3RTeW5jKSB7XG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGFsbCB0aGUgcmVzb3VyY2VzIGFyZSBzdWNjZXNmdWxseSBpbiBzeW5jXG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXMuZm9yRWFjaChyZXNvdXJjZSA9PiAodGhpcy5jYWNoZWFibGVSZXNvdXJjZXNbcmVzb3VyY2VdLnN5bmNocm9uaXppbmcgPSBmYWxzZSkpO1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgdGltZXN0YW1wIG9mIGxhc3Qgc3luY1xuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2F2ZUxhc3RTeW5jQXQobm93KVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN5bmNocm9uaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIGNvdWxkbid0IHNhdmUgdGhlIGxhc3Qgc3luYyBpbmZvXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgIC8vIHdlIGNvdWxkbid0IGFjcXVpcmUgbmV3IGluZm9ybWF0aW9uIChEZWx0YSlcbiAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgcmVqZWN0KCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgLy8gd2Ugc3RvcCwgc2luY2Ugd2UgZG9uJ3Qgd2FudCBiYWNrZW5kIGRhdGEgdG8gb3ZlcnJpZGUgbG9jYWwgaW5mbyBub3QgeWV0IHVwbG9hZGVkXG4gICAgICAgICAgICAgIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgICAgICAgICAgdGhpcy5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIEZvcmNlIGEgZnVsbCBzeW5jaHJvbmlzYXRpb24uXG4gICAqL1xuICBmb3JjZUZ1bGxTeW5jKCk6IHZvaWQge1xuICAgIHRoaXMuX3N0b3JhZ2UuY2xlYXIoKS50aGVuKCgpOiBQcm9taXNlPHZvaWQ+ID0+IHRoaXMuc3luY2hyb25pemUodHJ1ZSkpO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGRlc2NyaXB0aW9uIG9mIGFuIEFQSSByZXF1ZXN0IHRvIGEgcmVzb3VyY2UsIHRvIHVzZSB3aXRoIGBJREVBQVdTQVBJYC5cbiAqIFVzZWQgZm9yIHF1ZXVlcyBvZiByZXF1ZXN0cyAoVVBMT0FEKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBUElSZXF1ZXN0IHtcbiAgLyoqXG4gICAqIFJlc291cmNlIHBhdGggKGUuZy4gYHVzZXJzYCBvciBgdGVhbXMvJHt0ZWFtSWR9L3VzZXJzYCkuXG4gICAqL1xuICByZXNvdXJjZTogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGlkIHRvIGlkZW50aWZ5IGEgc3BlY2lmaWMgZWxlbWVudCBvZiB0aGUgcmVzb3VyY2UuXG4gICAqL1xuICByZXNvdXJjZUlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgQVBJIHJlcXVlc3QgbWV0aG9kIChlLmcuIFBPU1QsIFBVVCwgUEFUQ0gpLlxuICAgKi9cbiAgbWV0aG9kOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgYm9keSBvZiB0aGUgcmVxdWVzdC5cbiAgICovXG4gIGJvZHk6IGFueTtcbiAgLyoqXG4gICAqIEEgZGVzY3JpcHRpb24gdG8gc2hvdyBmb3IgdGhlIHJlcXVlc3QuXG4gICAqL1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgLyoqXG4gICAqIElmIG5vdCBudWxsLCB0aGUgcmVxdWVzdCB0cmllZCB0byBydW4gYnV0IGl0IGVuY291bnRlcmVkIHRoZSBlcnJvci5cbiAgICovXG4gIGVycm9yPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBhYnN0cmFjdCBjbGFzcyB0byBpbXBsZW1lbnQgZm9yIGVhY2ggcmVzb3VyY2UgdG8gY2FjaGUgb2ZmbGluZSBmcm9tIHRoZSBiYWNrLWVuZCAoRE9XTkxPQUQpLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQ2FjaGVhYmxlUmVzb3VyY2Uge1xuICAvKipcbiAgICogVGhlIHRlYW0gb3duaW5nIHRoZSByZXNvdXJjZS5cbiAgICogSWYgbnVsbCwgdGhlIHByb2plY3QgaXNuJ3QgdGVhbXMtYmFzZWQuXG4gICAqL1xuICB0ZWFtSWQ6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBpZGVudGlmaWVyIG9mIHRoZSByZXNvdXJjZS5cbiAgICovXG4gIHJlc291cmNlOiBEZWx0YVJlc291cmNlcyB8IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSByZXNvdXJjZSBkZXNjcmlwdGlvbiAodHJhbnNsYXRlZCkgZm9yIHRoZSBVSS5cbiAgICovXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBSdW50aW1lIGF0dHJpYnV0ZSB0byBrbm93IGlmIHRoZSByZXNvdXJjZSBpcyBzeW5jaHJvbml6aW5nLlxuICAgKi9cbiAgc3luY2hyb25pemluZzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRydWUgaWYgb25lIG9mIHRoZSBlbGVtZW50cyBmYWlsZWQgdGhlIGV4ZWN1dGlvbi5cbiAgICovXG4gIGVycm9yOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHJlc291cmNlOiBzdHJpbmcsIGRlc2NyaXB0aW9uOiBzdHJpbmcpIHtcbiAgICB0aGlzLnJlc291cmNlID0gcmVzb3VyY2U7XG4gICAgdGhpcy5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uO1xuICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgIHRoaXMuZXJyb3IgPSBmYWxzZTtcbiAgICAvLyBsb2FkZWQgYXQgcnVudGltZVxuICAgIHRoaXMudGVhbUlkID0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBIb3cgdG8gYnVpbGQgdGhlIHJlbGF0aXZlIFVSTCB0byB0aGUgcmVzb3VyY2UgKGxpc3QpLlxuICAgKiBFLmcuIGB0ZWFtcy8ke2VsZW1lbnQudGVhbUlkfS9jdXN0b21lcnNgIG9yIGBjdXN0b21lcnNgLlxuICAgKi9cbiAgYWJzdHJhY3QgbGlzdFVSTChlbGVtZW50OiBhbnkpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBIb3cgdG8gYnVpbGQgdGhlIHJlbGF0aXZlIFVSTCB0byB0aGUgcmVzb3VyY2UgZWxlbWVudCAoZGV0YWlsKS5cbiAgICogRS5nLiBgdGVhbXMvJHtlbGVtZW50LnRlYW1JZH0vY3VzdG9tZXJzLyR7ZWxlbWVudC5jdXN0b21lcklkfWAgb3IgYGN1c3RvbWVycy8ke2VsZW1lbnQuY3VzdG9tZXJJZH1gLlxuICAgKi9cbiAgYWJzdHJhY3QgZWxlbWVudFVSTChlbGVtZW50OiBhbnkpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBIb3cgdG8gdW5pcXVlbHkgaWRlbnRpZnkgYW4gZWxlbWVudCBpbiB0aGUgbGlzdCAoYnkgaXRzIGlkcykuXG4gICAqIEUuZy4gYHJldHVybiBsaXN0LmZpbmRJbmRleCh4ID0+IHguY3VzdG9tZXJJZCA9PT0gZWxlbWVudC5jdXN0b21lcklkKTtgXG4gICAqL1xuICBhYnN0cmFjdCBmaW5kSW5kZXhJbkxpc3QobGlzdDogYW55W10sIGVsZW1lbnQ6IGFueSk6IG51bWJlcjtcbiAgLyoqXG4gICAqIEhvdyB0byBrZWVwIHRoZSBsaXN0IHNvcnRlZC5cbiAgICogRS5nLiBgcmV0dXJuIGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSk7YFxuICAgKi9cbiAgYWJzdHJhY3Qgc29ydChhOiBhbnksIGI6IGFueSk6IG51bWJlcjtcbn1cbiJdfQ==
@@ -0,0 +1,58 @@
1
+ import { Component, Input, inject } from '@angular/core';
2
+ import { ModalController, AlertController, Platform } from '@ionic/angular';
3
+ import { IDEATranslationsService } from '@idea-ionic/common';
4
+ import { IDEAOfflineManagerComponent } from './offlineManager.component';
5
+ import { IDEAOfflineDataService } from './offlineData.service';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "@ionic/angular";
8
+ export class IDEAOfflineIndicatorComponent {
9
+ constructor() {
10
+ this._alert = inject(AlertController);
11
+ this._modal = inject(ModalController);
12
+ this._translate = inject(IDEATranslationsService);
13
+ this._platform = inject(Platform);
14
+ this._offline = inject(IDEAOfflineDataService);
15
+ /**
16
+ * Vertical position.
17
+ */
18
+ this.vertical = 'bottom';
19
+ /**
20
+ * Horizontal position.
21
+ */
22
+ this.horizontal = 'start';
23
+ /**
24
+ * Whether it is positionated on an edge.
25
+ */
26
+ this.edge = false;
27
+ }
28
+ async showStatus() {
29
+ if (this._offline.isOffline()) {
30
+ const isOnline = await this._offline.check();
31
+ if (!isOnline) {
32
+ const alert = await this._alert.create({
33
+ header: this._translate._('IDEA_UNCOMMON.OFFLINE.YOU_ARE_OFFLINE'),
34
+ message: this._translate._('IDEA_UNCOMMON.OFFLINE.FEATURES_REDUCED_CONTENTS_NOT_UP_TO_DATE'),
35
+ buttons: [this._translate._('COMMON.GOT_IT')]
36
+ });
37
+ alert.present();
38
+ }
39
+ }
40
+ else if (this._offline.isAllowed()) {
41
+ const modal = await this._modal.create({ component: IDEAOfflineManagerComponent });
42
+ modal.present();
43
+ }
44
+ }
45
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
46
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.1", type: IDEAOfflineIndicatorComponent, selector: "idea-offline-indicator", inputs: { vertical: "vertical", horizontal: "horizontal", edge: "edge" }, ngImport: i0, template: "@if (\n _platform.is('mobile') && (_offline.isOffline() || _offline.synchronizing || _offline.requiresManualConfirmation)\n) {\n <ion-fab [vertical]=\"vertical\" [horizontal]=\"horizontal\" [edge]=\"edge\">\n <ion-fab-button color=\"dark\" size=\"small\" (click)=\"showStatus()\">\n <!-- OFFLINE -->\n @if (_offline.isOffline()) {\n <ion-icon name=\"airplane\" />\n }\n <!-- SYNCHRONISING -->\n @if (_offline.isOnline() && _offline.synchronizing) {\n <ion-icon name=\"sync\" />\n }\n <!-- NEED MANAL SYNCHRONISATION -->\n @if (_offline.isOnline() && _offline.requiresManualConfirmation) {\n <ion-icon name=\"pause\" />\n }\n </ion-fab-button>\n </ion-fab>\n}\n", styles: [""], dependencies: [{ kind: "component", type: i1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
47
+ }
48
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineIndicatorComponent, decorators: [{
49
+ type: Component,
50
+ args: [{ selector: 'idea-offline-indicator', template: "@if (\n _platform.is('mobile') && (_offline.isOffline() || _offline.synchronizing || _offline.requiresManualConfirmation)\n) {\n <ion-fab [vertical]=\"vertical\" [horizontal]=\"horizontal\" [edge]=\"edge\">\n <ion-fab-button color=\"dark\" size=\"small\" (click)=\"showStatus()\">\n <!-- OFFLINE -->\n @if (_offline.isOffline()) {\n <ion-icon name=\"airplane\" />\n }\n <!-- SYNCHRONISING -->\n @if (_offline.isOnline() && _offline.synchronizing) {\n <ion-icon name=\"sync\" />\n }\n <!-- NEED MANAL SYNCHRONISATION -->\n @if (_offline.isOnline() && _offline.requiresManualConfirmation) {\n <ion-icon name=\"pause\" />\n }\n </ion-fab-button>\n </ion-fab>\n}\n" }]
51
+ }], propDecorators: { vertical: [{
52
+ type: Input
53
+ }], horizontal: [{
54
+ type: Input
55
+ }], edge: [{
56
+ type: Input
57
+ }] } });
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2ZmbGluZUluZGljYXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9tb2R1bGVzL3VuY29tbW9uL3NyYy9vZmZsaW5lL29mZmxpbmVJbmRpY2F0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vbW9kdWxlcy91bmNvbW1vbi9zcmMvb2ZmbGluZS9vZmZsaW5lSW5kaWNhdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1RSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU3RCxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7O0FBTy9ELE1BQU0sT0FBTyw2QkFBNkI7SUFMMUM7UUFNVSxXQUFNLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ2pDLFdBQU0sR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDakMsZUFBVSxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3JELGNBQVMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0IsYUFBUSxHQUFHLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBRTFDOztXQUVHO1FBQ00sYUFBUSxHQUFHLFFBQVEsQ0FBQztRQUM3Qjs7V0FFRztRQUNNLGVBQVUsR0FBRyxPQUFPLENBQUM7UUFDOUI7O1dBRUc7UUFDTSxTQUFJLEdBQUcsS0FBSyxDQUFDO0tBa0J2QjtJQWhCQyxLQUFLLENBQUMsVUFBVTtRQUNkLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM3QyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ2QsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztvQkFDckMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLHVDQUF1QyxDQUFDO29CQUNsRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsZ0VBQWdFLENBQUM7b0JBQzVGLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDO2lCQUM5QyxDQUFDLENBQUM7Z0JBQ0gsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLENBQUM7UUFDSCxDQUFDO2FBQU0sSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDckMsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLFNBQVMsRUFBRSwyQkFBMkIsRUFBRSxDQUFDLENBQUM7WUFDbkYsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDOzhHQW5DVSw2QkFBNkI7a0dBQTdCLDZCQUE2Qix3SUNaMUMsaXVCQW9CQTs7MkZEUmEsNkJBQTZCO2tCQUx6QyxTQUFTOytCQUNFLHdCQUF3Qjs4QkFjekIsUUFBUTtzQkFBaEIsS0FBSztnQkFJRyxVQUFVO3NCQUFsQixLQUFLO2dCQUlHLElBQUk7c0JBQVosS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTW9kYWxDb250cm9sbGVyLCBBbGVydENvbnRyb2xsZXIsIFBsYXRmb3JtIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuaW1wb3J0IHsgSURFQVRyYW5zbGF0aW9uc1NlcnZpY2UgfSBmcm9tICdAaWRlYS1pb25pYy9jb21tb24nO1xuXG5pbXBvcnQgeyBJREVBT2ZmbGluZU1hbmFnZXJDb21wb25lbnQgfSBmcm9tICcuL29mZmxpbmVNYW5hZ2VyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJREVBT2ZmbGluZURhdGFTZXJ2aWNlIH0gZnJvbSAnLi9vZmZsaW5lRGF0YS5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnaWRlYS1vZmZsaW5lLWluZGljYXRvcicsXG4gIHRlbXBsYXRlVXJsOiAnb2ZmbGluZUluZGljYXRvci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWydvZmZsaW5lSW5kaWNhdG9yLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgSURFQU9mZmxpbmVJbmRpY2F0b3JDb21wb25lbnQge1xuICBwcml2YXRlIF9hbGVydCA9IGluamVjdChBbGVydENvbnRyb2xsZXIpO1xuICBwcml2YXRlIF9tb2RhbCA9IGluamVjdChNb2RhbENvbnRyb2xsZXIpO1xuICBwcml2YXRlIF90cmFuc2xhdGUgPSBpbmplY3QoSURFQVRyYW5zbGF0aW9uc1NlcnZpY2UpO1xuICBfcGxhdGZvcm0gPSBpbmplY3QoUGxhdGZvcm0pO1xuICBfb2ZmbGluZSA9IGluamVjdChJREVBT2ZmbGluZURhdGFTZXJ2aWNlKTtcblxuICAvKipcbiAgICogVmVydGljYWwgcG9zaXRpb24uXG4gICAqL1xuICBASW5wdXQoKSB2ZXJ0aWNhbCA9ICdib3R0b20nO1xuICAvKipcbiAgICogSG9yaXpvbnRhbCBwb3NpdGlvbi5cbiAgICovXG4gIEBJbnB1dCgpIGhvcml6b250YWwgPSAnc3RhcnQnO1xuICAvKipcbiAgICogV2hldGhlciBpdCBpcyBwb3NpdGlvbmF0ZWQgb24gYW4gZWRnZS5cbiAgICovXG4gIEBJbnB1dCgpIGVkZ2UgPSBmYWxzZTtcblxuICBhc3luYyBzaG93U3RhdHVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLl9vZmZsaW5lLmlzT2ZmbGluZSgpKSB7XG4gICAgICBjb25zdCBpc09ubGluZSA9IGF3YWl0IHRoaXMuX29mZmxpbmUuY2hlY2soKTtcbiAgICAgIGlmICghaXNPbmxpbmUpIHtcbiAgICAgICAgY29uc3QgYWxlcnQgPSBhd2FpdCB0aGlzLl9hbGVydC5jcmVhdGUoe1xuICAgICAgICAgIGhlYWRlcjogdGhpcy5fdHJhbnNsYXRlLl8oJ0lERUFfVU5DT01NT04uT0ZGTElORS5ZT1VfQVJFX09GRkxJTkUnKSxcbiAgICAgICAgICBtZXNzYWdlOiB0aGlzLl90cmFuc2xhdGUuXygnSURFQV9VTkNPTU1PTi5PRkZMSU5FLkZFQVRVUkVTX1JFRFVDRURfQ09OVEVOVFNfTk9UX1VQX1RPX0RBVEUnKSxcbiAgICAgICAgICBidXR0b25zOiBbdGhpcy5fdHJhbnNsYXRlLl8oJ0NPTU1PTi5HT1RfSVQnKV1cbiAgICAgICAgfSk7XG4gICAgICAgIGFsZXJ0LnByZXNlbnQoKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRoaXMuX29mZmxpbmUuaXNBbGxvd2VkKCkpIHtcbiAgICAgIGNvbnN0IG1vZGFsID0gYXdhaXQgdGhpcy5fbW9kYWwuY3JlYXRlKHsgY29tcG9uZW50OiBJREVBT2ZmbGluZU1hbmFnZXJDb21wb25lbnQgfSk7XG4gICAgICBtb2RhbC5wcmVzZW50KCk7XG4gICAgfVxuICB9XG59XG4iLCJAaWYgKFxuICBfcGxhdGZvcm0uaXMoJ21vYmlsZScpICYmIChfb2ZmbGluZS5pc09mZmxpbmUoKSB8fCBfb2ZmbGluZS5zeW5jaHJvbml6aW5nIHx8IF9vZmZsaW5lLnJlcXVpcmVzTWFudWFsQ29uZmlybWF0aW9uKVxuKSB7XG4gIDxpb24tZmFiIFt2ZXJ0aWNhbF09XCJ2ZXJ0aWNhbFwiIFtob3Jpem9udGFsXT1cImhvcml6b250YWxcIiBbZWRnZV09XCJlZGdlXCI+XG4gICAgPGlvbi1mYWItYnV0dG9uIGNvbG9yPVwiZGFya1wiIHNpemU9XCJzbWFsbFwiIChjbGljayk9XCJzaG93U3RhdHVzKClcIj5cbiAgICAgIDwhLS0gT0ZGTElORSAtLT5cbiAgICAgIEBpZiAoX29mZmxpbmUuaXNPZmZsaW5lKCkpIHtcbiAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJhaXJwbGFuZVwiIC8+XG4gICAgICB9XG4gICAgICA8IS0tIFNZTkNIUk9OSVNJTkcgLS0+XG4gICAgICBAaWYgKF9vZmZsaW5lLmlzT25saW5lKCkgJiYgX29mZmxpbmUuc3luY2hyb25pemluZykge1xuICAgICAgICA8aW9uLWljb24gbmFtZT1cInN5bmNcIiAvPlxuICAgICAgfVxuICAgICAgPCEtLSBORUVEIE1BTkFMIFNZTkNIUk9OSVNBVElPTiAtLT5cbiAgICAgIEBpZiAoX29mZmxpbmUuaXNPbmxpbmUoKSAmJiBfb2ZmbGluZS5yZXF1aXJlc01hbnVhbENvbmZpcm1hdGlvbikge1xuICAgICAgICA8aW9uLWljb24gbmFtZT1cInBhdXNlXCIgLz5cbiAgICAgIH1cbiAgICA8L2lvbi1mYWItYnV0dG9uPlxuICA8L2lvbi1mYWI+XG59XG4iXX0=