http-request-manager 0.0.20 → 4.1.2
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 +44 -253
- package/esm2022/lib/http-request-manager.module.mjs +145 -0
- package/esm2022/lib/http-request-services-demo/http-request-services-demo.component.mjs +41 -0
- package/esm2022/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.mjs +175 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.mjs +80 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/file-download.module.mjs +42 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.mjs +85 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/models/download-labels-model.mjs +11 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.mjs +29 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/models/sample-ai-prompt.mjs +9 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/models/sample-client-info.mjs +12 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/models/sample-mapper-client-info.mjs +10 -0
- package/esm2022/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.mjs +276 -0
- package/esm2022/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.mjs +268 -0
- package/esm2022/lib/http-request-services-demo/request-manager-state-demo/services/state-manager-demo.service.mjs +75 -0
- package/esm2022/lib/index.mjs +4 -0
- package/esm2022/lib/interceptors/proxy-debugger.interceptor.mjs +47 -0
- package/esm2022/lib/interceptors/request-error.interceptor.mjs +5 -5
- package/esm2022/lib/models/config-http-options.model.mjs +18 -0
- package/esm2022/lib/models/config-local-storage-options.model.mjs +12 -0
- package/esm2022/lib/models/config-options.model.mjs +12 -0
- package/esm2022/lib/models/config-token.model.mjs +8 -0
- package/esm2022/lib/models/index.mjs +4 -1
- package/esm2022/lib/models/retry-options.model.mjs +3 -3
- package/esm2022/lib/services/index.mjs +1 -1
- package/esm2022/lib/services/local-storage-manager-service/local-storage-manager.service.mjs +34 -9
- package/esm2022/lib/services/local-storage-manager-service/models/index.mjs +1 -2
- package/esm2022/lib/services/local-storage-manager-service/models/setting-options.model.mjs +2 -2
- package/esm2022/lib/services/local-storage-manager-service/models/storage-option.model.mjs +3 -3
- package/esm2022/lib/services/request-manager-services/http-manager.service.mjs +87 -51
- package/esm2022/lib/services/request-manager-services/request.service.mjs +70 -28
- package/esm2022/lib/services/request-manager-services/rxjs-operators/delay-retry.mjs +7 -5
- package/esm2022/lib/services/request-manager-services/rxjs-operators/request-streaming.mjs +1 -1
- package/esm2022/lib/services/request-manager-state-service/http-manager-state.store.mjs +6 -39
- package/esm2022/lib/services/utils/app.service.mjs +7 -1
- package/esm2022/lib/services/utils/object-merger.service.mjs +34 -0
- package/esm2022/lib/services/utils/path-query.service.mjs +2 -1
- package/esm2022/lib/services/utils/utils.service.mjs +23 -2
- package/esm2022/public-api.mjs +4 -4
- package/fesm2022/http-request-manager.mjs +1782 -435
- package/fesm2022/http-request-manager.mjs.map +1 -1
- package/http-request-manager-4.1.2.tgz +0 -0
- package/lib/http-request-manager.module.d.ts +33 -0
- package/lib/http-request-services-demo/http-request-services-demo.component.d.ts +24 -0
- package/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.d.ts +56 -0
- package/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.d.ts +26 -0
- package/lib/http-request-services-demo/request-manager-demo/file-downloader/file-download.module.d.ts +13 -0
- package/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.d.ts +26 -0
- package/lib/http-request-services-demo/request-manager-demo/file-downloader/models/download-labels-model.d.ts +12 -0
- package/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.d.ts +16 -0
- package/lib/http-request-services-demo/request-manager-demo/models/sample-ai-prompt.d.ts +8 -0
- package/lib/http-request-services-demo/request-manager-demo/models/sample-client-info.d.ts +14 -0
- package/lib/http-request-services-demo/request-manager-demo/models/sample-mapper-client-info.d.ts +10 -0
- package/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.d.ts +98 -0
- package/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.d.ts +110 -0
- package/lib/http-request-services-demo/request-manager-state-demo/services/state-manager-demo.service.d.ts +16 -0
- package/lib/index.d.ts +3 -0
- package/lib/interceptors/proxy-debugger.interceptor.d.ts +12 -0
- package/lib/interceptors/request-error.interceptor.d.ts +1 -1
- package/lib/models/config-http-options.model.d.ts +21 -0
- package/lib/models/config-local-storage-options.model.d.ts +13 -0
- package/lib/models/config-options.model.d.ts +12 -0
- package/lib/models/config-token.model.d.ts +8 -0
- package/lib/models/index.d.ts +3 -0
- package/lib/services/local-storage-manager-service/local-storage-manager.service.d.ts +7 -2
- package/lib/services/local-storage-manager-service/models/index.d.ts +0 -1
- package/lib/services/local-storage-manager-service/models/setting-options.model.d.ts +2 -2
- package/lib/services/local-storage-manager-service/models/storage-option.model.d.ts +4 -4
- package/lib/services/request-manager-services/http-manager.service.d.ts +12 -7
- package/lib/services/request-manager-services/request.service.d.ts +1 -0
- package/lib/services/request-manager-services/rxjs-operators/delay-retry.d.ts +1 -1
- package/lib/services/request-manager-state-service/http-manager-state.store.d.ts +11 -15
- package/lib/services/utils/object-merger.service.d.ts +7 -0
- package/lib/services/utils/utils.service.d.ts +1 -1
- package/package.json +27 -18
- package/public-api.d.ts +3 -3
- package/esm2022/lib/services/local-storage-manager-service/models/storage-option-settings.model.mjs +0 -13
- package/http-request-manager-0.0.20.tgz +0 -0
- package/lib/services/local-storage-manager-service/models/storage-option-settings.model.d.ts +0 -15
|
@@ -1,13 +1,47 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable, APP_ID, Inject, Injector,
|
|
2
|
+
import { inject, Injectable, APP_ID, Inject, InjectionToken, Injector, Optional, EventEmitter, Component, ViewEncapsulation, Input, Output, NgModule, ViewChild } from '@angular/core';
|
|
3
3
|
import { ComponentStore } from '@ngrx/component-store';
|
|
4
|
-
import {
|
|
5
|
-
import { HttpClient, HttpHeaders, HttpEventType, HttpErrorResponse } from '@angular/common/http';
|
|
4
|
+
import { map, catchError, filter, finalize, takeWhile, retry, startWith, tap, mergeMap, takeUntil, withLatestFrom, switchMap, concatMap, scan, distinctUntilChanged } from 'rxjs/operators';
|
|
5
|
+
import { HttpClient, HttpHeaders, HttpEventType, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
6
6
|
import * as CryptoJS from 'crypto-js';
|
|
7
|
-
import {
|
|
8
|
-
import { ToastDisplay, ToastColors,
|
|
9
|
-
import { ToastMessageService } from 'toast-message-display';
|
|
7
|
+
import { from, BehaviorSubject, EMPTY, throwError, defer, interval, timer, Subject, of, Subscription, catchError as catchError$1 } from 'rxjs';
|
|
8
|
+
import { ToastMessageService, ToastDisplay, ToastColors, ToastMessageModule } from 'toast-message-display';
|
|
10
9
|
import * as i1 from '@ngx-translate/core';
|
|
10
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
11
|
+
import * as i1$1 from '@angular/common';
|
|
12
|
+
import { CommonModule } from '@angular/common';
|
|
13
|
+
import * as i2 from '@angular/forms';
|
|
14
|
+
import { FormBuilder, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
15
|
+
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
|
16
|
+
import * as i3$1 from '@angular/material/button';
|
|
17
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
18
|
+
import { MatChipsModule } from '@angular/material/chips';
|
|
19
|
+
import * as i11 from '@angular/material/divider';
|
|
20
|
+
import { MatDividerModule } from '@angular/material/divider';
|
|
21
|
+
import * as i4 from '@angular/material/form-field';
|
|
22
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
23
|
+
import * as i7 from '@angular/material/icon';
|
|
24
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
25
|
+
import * as i12 from '@angular/material/input';
|
|
26
|
+
import { MatInputModule } from '@angular/material/input';
|
|
27
|
+
import * as i9 from '@angular/material/progress-bar';
|
|
28
|
+
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
29
|
+
import * as i5 from '@angular/material/select';
|
|
30
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
31
|
+
import { MatSidenavModule } from '@angular/material/sidenav';
|
|
32
|
+
import * as i10$1 from '@angular/material/slide-toggle';
|
|
33
|
+
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
34
|
+
import * as i3$2 from '@angular/material/menu';
|
|
35
|
+
import { MatMenuModule } from '@angular/material/menu';
|
|
36
|
+
import * as i4$1 from '@angular/material/toolbar';
|
|
37
|
+
import { MatToolbarModule } from '@angular/material/toolbar';
|
|
38
|
+
import * as i8 from '@angular/material/table';
|
|
39
|
+
import { MatTableModule } from '@angular/material/table';
|
|
40
|
+
import * as i10 from '@angular/material/button-toggle';
|
|
41
|
+
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
42
|
+
import * as i3 from '@angular/material/progress-spinner';
|
|
43
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
44
|
+
import * as i6 from '@angular/material/core';
|
|
11
45
|
|
|
12
46
|
var StorageType;
|
|
13
47
|
(function (StorageType) {
|
|
@@ -16,15 +50,15 @@ var StorageType;
|
|
|
16
50
|
StorageType[StorageType["DB"] = 2] = "DB";
|
|
17
51
|
})(StorageType || (StorageType = {}));
|
|
18
52
|
|
|
19
|
-
class
|
|
20
|
-
constructor(storage
|
|
53
|
+
class SettingOptions {
|
|
54
|
+
constructor(storage, expires, expiresIn, encrypted) {
|
|
21
55
|
this.storage = storage;
|
|
22
56
|
this.expires = expires;
|
|
23
57
|
this.expiresIn = expiresIn;
|
|
24
58
|
this.encrypted = encrypted;
|
|
25
59
|
}
|
|
26
60
|
static adapt(item) {
|
|
27
|
-
return new
|
|
61
|
+
return new SettingOptions((item?.storage) ? item.storage : StorageType.GLOBAL, (item?.expires) ? item.expires : 0, (item?.expiresIn) ? item.expiresIn : '', (item?.encrypted) ? item?.encrypted : false);
|
|
28
62
|
}
|
|
29
63
|
}
|
|
30
64
|
|
|
@@ -35,7 +69,7 @@ class StorageOption {
|
|
|
35
69
|
this.options = options;
|
|
36
70
|
}
|
|
37
71
|
static adapt(item) {
|
|
38
|
-
return new StorageOption((item?.id) ? item.id : crypto.randomUUID(), item?.name, (item?.options) ?
|
|
72
|
+
return new StorageOption((item?.id) ? item.id : crypto.randomUUID(), item?.name, (item?.options) ? SettingOptions.adapt(item.options) : SettingOptions.adapt());
|
|
39
73
|
}
|
|
40
74
|
}
|
|
41
75
|
|
|
@@ -51,18 +85,6 @@ class GlobalStoreOptions {
|
|
|
51
85
|
}
|
|
52
86
|
}
|
|
53
87
|
|
|
54
|
-
class SettingOptions {
|
|
55
|
-
constructor(storage = StorageType.GLOBAL, expires, expiresIn, encrypted) {
|
|
56
|
-
this.storage = storage;
|
|
57
|
-
this.expires = expires;
|
|
58
|
-
this.expiresIn = expiresIn;
|
|
59
|
-
this.encrypted = encrypted;
|
|
60
|
-
}
|
|
61
|
-
static adapt(item) {
|
|
62
|
-
return new SettingOptions((item?.storage) ? item.storage : StorageType.GLOBAL, (item?.expires) ? item.expires : 0, (item?.expiresIn) ? item.expiresIn : '', (item?.encrypted) ? item?.encrypted : false);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
88
|
class StorageData {
|
|
67
89
|
constructor(id, data) {
|
|
68
90
|
this.id = id;
|
|
@@ -140,6 +162,7 @@ class UtilsService {
|
|
|
140
162
|
return hex.padStart(32, '0').substr(0, 32);
|
|
141
163
|
}
|
|
142
164
|
// y = years, m = months, w = weeks, d = days, hr = hours, mn = minutes else seconds
|
|
165
|
+
// returns epoch time corresponding to the expiry type
|
|
143
166
|
expires(str) {
|
|
144
167
|
if (!str)
|
|
145
168
|
return;
|
|
@@ -192,7 +215,27 @@ class UtilsService {
|
|
|
192
215
|
if (!expiryDate)
|
|
193
216
|
return;
|
|
194
217
|
const now = Math.floor(new Date().getTime() / 1000);
|
|
195
|
-
|
|
218
|
+
let diff = expiryDate - now;
|
|
219
|
+
if (diff <= 0)
|
|
220
|
+
return "Expired";
|
|
221
|
+
const units = [
|
|
222
|
+
{ label: 'y', seconds: 31536000 },
|
|
223
|
+
{ label: 'm', seconds: 2592000 },
|
|
224
|
+
{ label: 'w', seconds: 604800 },
|
|
225
|
+
{ label: 'd', seconds: 86400 },
|
|
226
|
+
{ label: 'h', seconds: 3600 },
|
|
227
|
+
{ label: 'min', seconds: 60 },
|
|
228
|
+
{ label: '', seconds: 1 },
|
|
229
|
+
];
|
|
230
|
+
let result = [];
|
|
231
|
+
for (const unit of units) {
|
|
232
|
+
if (diff >= unit.seconds) {
|
|
233
|
+
const value = Math.floor(diff / unit.seconds);
|
|
234
|
+
diff %= unit.seconds;
|
|
235
|
+
result.push(`${value}${unit.label}${value > 1 ? 's' : ''}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return result.join(', ');
|
|
196
239
|
}
|
|
197
240
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
198
241
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UtilsService, providedIn: 'root' }); }
|
|
@@ -256,6 +299,12 @@ const UUID = () => {
|
|
|
256
299
|
return self.crypto.randomUUID();
|
|
257
300
|
};
|
|
258
301
|
|
|
302
|
+
// Must provide a value for APP_ID in AppModule->Providers
|
|
303
|
+
// providers: [
|
|
304
|
+
// {
|
|
305
|
+
// provide: APP_ID,
|
|
306
|
+
// useValue: "056991ac-3537-43ab-b5b9-83edf6554eff",
|
|
307
|
+
// },
|
|
259
308
|
class AppService {
|
|
260
309
|
constructor(id) {
|
|
261
310
|
this.id = id;
|
|
@@ -379,273 +428,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
379
428
|
}]
|
|
380
429
|
}], ctorParameters: function () { return []; } });
|
|
381
430
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
timer$.subscribe();
|
|
404
|
-
}
|
|
405
|
-
constructor() {
|
|
406
|
-
super(storage);
|
|
407
|
-
this.storageName = 'storage';
|
|
408
|
-
this.storageSettingsName = 'global-storage';
|
|
409
|
-
this.stateRetrieved = false;
|
|
410
|
-
this.encrypted = false;
|
|
411
|
-
this.app = inject(AppService);
|
|
412
|
-
this.utils = inject(UtilsService);
|
|
413
|
-
this.encryption = inject(SymmetricalEncryptionService);
|
|
414
|
-
this.encryptionTest = inject(EncryptionTestService);
|
|
415
|
-
// SELECTORS
|
|
416
|
-
this.data$ = this.select((state) => state);
|
|
417
|
-
this.stores$ = this.select((state) => state.settings);
|
|
418
|
-
this.storeExists$ = (store) => this.select(this.data$, (data) => data.settings.find(item => item.name === store) ? true : false);
|
|
419
|
-
this.store$ = (store) => this.select(this.data$, (data) => {
|
|
420
|
-
const foundStore = data.settings.find(item => item.name === store);
|
|
421
|
-
if (foundStore) {
|
|
422
|
-
const options = SettingOptions.adapt(foundStore.options);
|
|
423
|
-
const found = foundStore.options?.storage === StorageType.GLOBAL
|
|
424
|
-
? data.localStores.find(item => item.id === foundStore.id)
|
|
425
|
-
: data.sessionStores.find(item => item.id === foundStore.id);
|
|
426
|
-
if (!found) {
|
|
427
|
-
this.deleteStore({ name: store });
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
const storageData = (options.encrypted) ? this.encryption.decrypt(found.data, this.app.appID) : found.data;
|
|
431
|
-
return (this.isString(storageData)) ? JSON.parse(storageData) : storageData;
|
|
432
|
-
}
|
|
433
|
-
else {
|
|
434
|
-
return null;
|
|
435
|
-
}
|
|
436
|
-
});
|
|
437
|
-
this.settings$ = this.select((state) => state.settings);
|
|
438
|
-
this.setting$ = (store) => this.select(this.data$, (state) => {
|
|
439
|
-
const foundSetting = state.settings.find(item => item.name === store);
|
|
440
|
-
return (foundSetting) ? foundSetting : null;
|
|
441
|
-
});
|
|
442
|
-
this.persistence$ = this.data$
|
|
443
|
-
.subscribe(data => {
|
|
444
|
-
if (this.stateRetrieved)
|
|
445
|
-
this.persistState(data);
|
|
446
|
-
});
|
|
447
|
-
this.updateState = this.updater((state, updatedState) => ({
|
|
448
|
-
...updatedState,
|
|
449
|
-
}));
|
|
450
|
-
this.setStore = this.updater((state, store) => {
|
|
451
|
-
const settings = StorageOption.adapt(store);
|
|
452
|
-
const type = store.options.storage;
|
|
453
|
-
const hasStore = this.hasGlobalStorage(type, store.id);
|
|
454
|
-
store.name = this.validStoreName(store.name);
|
|
455
|
-
if (!hasStore) {
|
|
456
|
-
console.warn(`No such Store: ${store.name}`);
|
|
457
|
-
return state;
|
|
458
|
-
}
|
|
459
|
-
else {
|
|
460
|
-
const str = this.encryptionTest.isEncrypted(store.data) ? store.data : JSON.stringify(store.data);
|
|
461
|
-
const dataStr = (this.isObjectOrArray(str)) ? (store.options.encrypted) ? this.encryption.encrypt(str, this.app.appID) : store.data : store.data;
|
|
462
|
-
const localData = (dataStr && settings.options?.storage === StorageType.GLOBAL) ? [{ data: dataStr, id: settings.id }] : [];
|
|
463
|
-
const sessionData = (dataStr && settings.options?.storage === StorageType.SESSION) ? [{ data: dataStr, id: settings.id }] : [];
|
|
464
|
-
return {
|
|
465
|
-
...state,
|
|
466
|
-
localStores: [...state.localStores, ...localData],
|
|
467
|
-
sessionStores: [...state.sessionStores, ...sessionData],
|
|
468
|
-
settings: [...state.settings, ...[settings]],
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
});
|
|
472
|
-
this.createStore = this.updater((state, store) => {
|
|
473
|
-
const settings = StorageOption.adapt(store);
|
|
474
|
-
const foundStore = state?.settings.some(item => item.name === store.name);
|
|
475
|
-
const expires = (settings.options?.expiresIn) ? this.utils.expires(settings.options?.expiresIn) : 0;
|
|
476
|
-
if (settings.options)
|
|
477
|
-
settings.options.expires = expires;
|
|
478
|
-
store.name = this.validStoreName(store.name);
|
|
479
|
-
if (foundStore) {
|
|
480
|
-
return state;
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
if (!this.isObjectOrArray(store.data)) {
|
|
484
|
-
console.warn('Data must ba an Object or Array');
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
store.data = (this.isString(store.data)) ? JSON.parse(store.data) : store.data;
|
|
488
|
-
const dataStr = (store.options.encrypted) ? this.encryption.encrypt(store.data, this.app.appID) : store.data;
|
|
489
|
-
const localData = (settings.options?.storage === StorageType.GLOBAL) ? [{ data: dataStr, id: settings.id }] : [];
|
|
490
|
-
const sessionData = (settings.options?.storage === StorageType.SESSION) ? [{ data: dataStr, id: settings.id }] : [];
|
|
491
|
-
return {
|
|
492
|
-
...state,
|
|
493
|
-
localStores: [...state.localStores, ...localData],
|
|
494
|
-
sessionStores: [...state.sessionStores, ...sessionData],
|
|
495
|
-
settings: [...state.settings, ...[settings]],
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
});
|
|
499
|
-
this.updateStore = this.updater((state, store) => {
|
|
500
|
-
store.name = this.validStoreName(store.name);
|
|
501
|
-
const settings = state.settings.find(item => item.name === store.name);
|
|
502
|
-
if (settings) {
|
|
503
|
-
const type = settings.options?.storage;
|
|
504
|
-
const hasStore = this.hasGlobalStorage(type, settings.id || '');
|
|
505
|
-
if (!hasStore) {
|
|
506
|
-
console.warn(`No such Store: ${store.name}`);
|
|
507
|
-
}
|
|
508
|
-
else {
|
|
509
|
-
const dataStr = (settings.options?.encrypted) ? this.encryption.encrypt(store.data, this.app.appID) : store.data;
|
|
510
|
-
const localData = (dataStr && settings.options?.storage === StorageType.GLOBAL) ? [{ data: dataStr, id: settings.id }] : [];
|
|
511
|
-
const sessionData = (dataStr && settings.options?.storage === StorageType.SESSION) ? [{ data: dataStr, id: settings.id }] : [];
|
|
512
|
-
state.localStores = state.localStores.filter(item => item.id !== settings.id);
|
|
513
|
-
state.sessionStores = state.sessionStores.filter(item => item.id !== settings.id);
|
|
514
|
-
return {
|
|
515
|
-
...state,
|
|
516
|
-
localStores: [...state.localStores, ...localData],
|
|
517
|
-
sessionStores: [...state.sessionStores, ...sessionData],
|
|
518
|
-
};
|
|
431
|
+
/**
|
|
432
|
+
* An injection token that provides the configuration settings for the application.
|
|
433
|
+
* This token can be used to inject the `ConfigSettings` instance into components or services
|
|
434
|
+
* that require access to the application configuration.
|
|
435
|
+
*/
|
|
436
|
+
const CONFIG_SETTINGS_TOKEN = new InjectionToken('http.config');
|
|
437
|
+
|
|
438
|
+
class ObjectMergerService {
|
|
439
|
+
mergeOptions(options, configForRoot) {
|
|
440
|
+
const merged = configForRoot ? { ...configForRoot } : {};
|
|
441
|
+
for (const key in options) {
|
|
442
|
+
if (Object.prototype.hasOwnProperty.call(options, key)) {
|
|
443
|
+
const value = options[key];
|
|
444
|
+
if (value !== null &&
|
|
445
|
+
value !== undefined &&
|
|
446
|
+
!(typeof value === 'number') &&
|
|
447
|
+
!(typeof value === 'boolean') &&
|
|
448
|
+
!(this.isNonEmptyString(value)) &&
|
|
449
|
+
!(Array.isArray(value) && value.length === 0) &&
|
|
450
|
+
!(typeof value === 'object' && !Array.isArray(value))) {
|
|
451
|
+
merged[key] = value;
|
|
519
452
|
}
|
|
520
453
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
this.deleteStore = this.updater((state, store) => {
|
|
524
|
-
store.name = this.validStoreName(store.name);
|
|
525
|
-
const id = state.settings.find(item => item.name === store.name)?.id;
|
|
526
|
-
if (id) {
|
|
527
|
-
const settings = state.settings.filter(item => item.id !== id);
|
|
528
|
-
const localData = state.localStores.filter(item => item.id !== id);
|
|
529
|
-
const sessionData = state.sessionStores.filter(item => item.id !== id);
|
|
530
|
-
return {
|
|
531
|
-
...state,
|
|
532
|
-
localStores: [...localData],
|
|
533
|
-
sessionStores: [...sessionData],
|
|
534
|
-
settings: [...settings],
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
else {
|
|
538
|
-
console.warn(`No such Store: ${store.name}`);
|
|
539
|
-
return state;
|
|
540
|
-
}
|
|
541
|
-
});
|
|
542
|
-
this.isObjectOrArray = (obj) => {
|
|
543
|
-
try {
|
|
544
|
-
//obj = (Object.prototype.toString.call(obj) === '[object Object]') ? JSON.parse(obj) : obj
|
|
545
|
-
return typeof obj === 'object' || Array.isArray(obj);
|
|
546
|
-
}
|
|
547
|
-
catch (error) {
|
|
548
|
-
return false;
|
|
549
|
-
}
|
|
550
|
-
};
|
|
551
|
-
this.retrieveState();
|
|
552
|
-
this.startTimer();
|
|
454
|
+
}
|
|
455
|
+
return merged;
|
|
553
456
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
localStores: [],
|
|
557
|
-
sessionStores: [],
|
|
558
|
-
settings: [],
|
|
559
|
-
};
|
|
560
|
-
this.updateState(newState);
|
|
561
|
-
this.persistState(newState);
|
|
457
|
+
isNonEmptyString(value) {
|
|
458
|
+
return typeof value === 'string' && value.length === 0;
|
|
562
459
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
460
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ObjectMergerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
461
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ObjectMergerService, providedIn: 'root' }); }
|
|
462
|
+
}
|
|
463
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ObjectMergerService, decorators: [{
|
|
464
|
+
type: Injectable,
|
|
465
|
+
args: [{
|
|
466
|
+
providedIn: 'root'
|
|
467
|
+
}]
|
|
468
|
+
}] });
|
|
469
|
+
|
|
470
|
+
class ApiRequest {
|
|
471
|
+
constructor(server = '', path = [], headers = {}, adapter, mapper, polling, retry = RetryOptions.adapt(), stream = false, displayError = false) {
|
|
472
|
+
this.server = server;
|
|
473
|
+
this.path = path;
|
|
474
|
+
this.headers = headers;
|
|
475
|
+
this.adapter = adapter;
|
|
476
|
+
this.mapper = mapper;
|
|
477
|
+
this.polling = polling;
|
|
478
|
+
this.retry = retry;
|
|
479
|
+
this.stream = stream;
|
|
480
|
+
this.displayError = displayError;
|
|
572
481
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
return
|
|
482
|
+
static adapt(item) {
|
|
483
|
+
const server = Array.isArray(item?.server) ? item.server.join('/') : item?.server || '';
|
|
484
|
+
const retryOptions = item?.retry ? RetryOptions.adapt(item.retry) : RetryOptions.adapt();
|
|
485
|
+
return new ApiRequest(server, item?.path, (item?.headers) ? item.headers : {}, item?.adapter, item?.mapper, item?.polling ? Math.floor(item.polling) : 0, retryOptions, item?.stream, item?.displayError);
|
|
577
486
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
const sessionData = (sessionStr) ? JSON.parse(sessionStr) : null;
|
|
584
|
-
const decryptedStr = str ? this.encryption.decrypt(str, this.app.appID) : null;
|
|
585
|
-
const settings = (decryptedStr && decryptedStr !== null) ? JSON.parse(decryptedStr) : [];
|
|
586
|
-
settings.forEach(store => {
|
|
587
|
-
const expired = (store.options?.expires || 0) > 0 && this.utils.hasExpired(store.options?.expires || 0);
|
|
588
|
-
if (!expired) {
|
|
589
|
-
const hasStorage = this.hasGlobalStorage(store.options?.storage, store.id || '');
|
|
590
|
-
if (!hasStorage) {
|
|
591
|
-
this.createStore({ id: store.id, name: store.name, data: [], options: SettingOptions.adapt(store.options) });
|
|
592
|
-
}
|
|
593
|
-
else {
|
|
594
|
-
const storeData = (store.options?.storage === StorageType.GLOBAL) ? localData.find(item => item.id === store.id) : sessionData.find(item => item.id === store.id);
|
|
595
|
-
this.setStore({ id: store.id || '', name: store.name, data: storeData?.data, options: SettingOptions.adapt(store.options) });
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
});
|
|
599
|
-
this.stateRetrieved = true;
|
|
600
|
-
}
|
|
601
|
-
isString(obj) {
|
|
602
|
-
return (Object.prototype.toString.call(obj) === '[object String]');
|
|
603
|
-
}
|
|
604
|
-
fixAndParseJSON(jsonString) {
|
|
605
|
-
const fixedString = jsonString
|
|
606
|
-
.replace(/'/g, '"')
|
|
607
|
-
.replace(/([{,]\s*)(\w+)\s*:/g, '$1"$2":')
|
|
608
|
-
.replace(/,\s*(\}|\])/g, '$1');
|
|
609
|
-
try {
|
|
610
|
-
return JSON.parse(fixedString);
|
|
611
|
-
}
|
|
612
|
-
catch (error) {
|
|
613
|
-
throw new Error('Failed to parse JSON: ' + error.message);
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
validStoreName(str) {
|
|
617
|
-
return str
|
|
618
|
-
.toLowerCase() // Convert to lowercase
|
|
619
|
-
.replace(/\s+/g, '_') // Replace spaces with underscores
|
|
620
|
-
.replace(/[^ -~]/g, ''); // Remove non-ASCII characters
|
|
621
|
-
}
|
|
622
|
-
hasGlobalStorage(type = StorageType.GLOBAL, id) {
|
|
623
|
-
const strData = [];
|
|
624
|
-
if (type === StorageType.GLOBAL) {
|
|
625
|
-
const str = localStorage.getItem(this.storageName);
|
|
626
|
-
strData.push(...(str ? JSON.parse(str) : []));
|
|
627
|
-
}
|
|
628
|
-
else {
|
|
629
|
-
const str = sessionStorage.getItem(this.storageName);
|
|
630
|
-
strData.push(...(str ? JSON.parse(str) : []));
|
|
631
|
-
}
|
|
632
|
-
const found = strData.find(store => store.id === id);
|
|
633
|
-
return (found) ? true : false;
|
|
634
|
-
}
|
|
635
|
-
ngOnDestroy() {
|
|
636
|
-
this.persistence$.unsubscribe();
|
|
637
|
-
}
|
|
638
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalStorageManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
639
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalStorageManagerService, providedIn: 'root' }); }
|
|
640
|
-
}
|
|
641
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalStorageManagerService, decorators: [{
|
|
642
|
-
type: Injectable,
|
|
643
|
-
args: [{ providedIn: 'root' }]
|
|
644
|
-
}], ctorParameters: function () { return []; } });
|
|
645
|
-
|
|
646
|
-
class HeadersService {
|
|
647
|
-
constructor() {
|
|
648
|
-
this.headers = {};
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
class HeadersService {
|
|
490
|
+
constructor() {
|
|
491
|
+
this.headers = {};
|
|
649
492
|
}
|
|
650
493
|
generateHeaders(headers) {
|
|
651
494
|
const allHeaders = headers ? { ...this.headers, ...headers } : {};
|
|
@@ -681,6 +524,7 @@ class PathQueryService {
|
|
|
681
524
|
return (Object.keys(query).length > 0) ? path + '?' + this.buildQueryPath(query) : path;
|
|
682
525
|
}
|
|
683
526
|
buildRestPath(server, params) {
|
|
527
|
+
server = (server) ? server : '';
|
|
684
528
|
server = (server.charAt(0) === '/') ? server.substring(1) : server;
|
|
685
529
|
return this.cleanUrlPath(server + '/' + params.join('/'));
|
|
686
530
|
}
|
|
@@ -922,32 +766,32 @@ class RequestService {
|
|
|
922
766
|
this.progress$ = this.progress.asObservable();
|
|
923
767
|
}
|
|
924
768
|
getRecordRequest(options) {
|
|
925
|
-
this.isPending.next(true);
|
|
926
769
|
const urlPath = this.buildUrlPath(options);
|
|
927
770
|
const headers = this.buildCombinedHeaders(options);
|
|
771
|
+
this.isPending.next(true);
|
|
928
772
|
return (options.stream)
|
|
929
773
|
? this.http.get(urlPath, headers).pipe(requestStreaming(), this.handleFinalize())
|
|
930
|
-
: this.http.get(urlPath, headers).pipe(this.request(options)
|
|
774
|
+
: this.http.get(urlPath, headers).pipe(this.request(options));
|
|
931
775
|
}
|
|
932
776
|
createRecordRequest(options, data) {
|
|
933
|
-
this.isPending.next(true);
|
|
934
777
|
const urlPath = this.buildUrlPath(options);
|
|
935
778
|
const headers = this.buildCombinedHeaders(options);
|
|
779
|
+
this.isPending.next(true);
|
|
936
780
|
return (options.stream)
|
|
937
781
|
? this.http.post(urlPath, data, headers).pipe(requestStreaming(), this.handleFinalize())
|
|
938
|
-
: this.http.post(urlPath, data, headers).pipe(this.request(options)
|
|
782
|
+
: this.http.post(urlPath, data, headers).pipe(this.request(options));
|
|
939
783
|
}
|
|
940
784
|
updateRecordRequest(options, data) {
|
|
941
|
-
this.isPending.next(true);
|
|
942
785
|
const urlPath = this.buildUrlPath(options);
|
|
943
786
|
const headers = this.buildHeaders(options);
|
|
944
|
-
|
|
787
|
+
this.isPending.next(true);
|
|
788
|
+
return this.http.put(urlPath, data, headers).pipe(this.request(options));
|
|
945
789
|
}
|
|
946
790
|
deleteRecordRequest(options) {
|
|
947
|
-
this.isPending.next(true);
|
|
948
791
|
const urlPath = this.buildUrlPath(options);
|
|
949
792
|
const headers = this.buildHeaders(options);
|
|
950
|
-
|
|
793
|
+
this.isPending.next(true);
|
|
794
|
+
return this.http.delete(urlPath, headers).pipe(this.request(options));
|
|
951
795
|
}
|
|
952
796
|
// Helper functions
|
|
953
797
|
buildUrlPath(options) {
|
|
@@ -957,13 +801,13 @@ class RequestService {
|
|
|
957
801
|
return this.headersService.generateHeaders(options.headers);
|
|
958
802
|
}
|
|
959
803
|
buildCombinedHeaders(options) {
|
|
960
|
-
const headers = this.
|
|
961
|
-
return this.
|
|
804
|
+
const headers = this.combineHeaders(options.headers, options.stream);
|
|
805
|
+
return this.headersService.generateHeaders(headers);
|
|
962
806
|
}
|
|
963
807
|
request(options) {
|
|
964
808
|
return (source$) => {
|
|
965
809
|
return source$.pipe(map(data => {
|
|
966
|
-
if (options
|
|
810
|
+
if (options?.adapter) {
|
|
967
811
|
return Array.isArray(data)
|
|
968
812
|
? data.map((item) => options.adapter(item))
|
|
969
813
|
: options.adapter(data);
|
|
@@ -978,23 +822,62 @@ class RequestService {
|
|
|
978
822
|
return this.http.get(urlPath, { responseType: 'blob', observe: 'events', reportProgress: true })
|
|
979
823
|
.pipe(map((event) => {
|
|
980
824
|
this.isPending.next(true);
|
|
825
|
+
const info = event;
|
|
981
826
|
switch (event.type) {
|
|
982
827
|
case HttpEventType.DownloadProgress:
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
828
|
+
if (info.status !== 200) {
|
|
829
|
+
this.isPending.next(false);
|
|
830
|
+
throw new Error('Download failed');
|
|
831
|
+
return 0;
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
const status = (event.total) ? Math.round(event.loaded / (event.total || 1) * 100) : 100;
|
|
835
|
+
this.progress.next(status);
|
|
836
|
+
return status;
|
|
837
|
+
}
|
|
986
838
|
case HttpEventType.Response:
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
839
|
+
try {
|
|
840
|
+
const header_content = event.headers.get('Content-Disposition') || '';
|
|
841
|
+
const fd = this.fileDetails(options.path);
|
|
842
|
+
if (!fd) {
|
|
843
|
+
this.isPending.next(false);
|
|
844
|
+
throw new Error('Save File: (file name and extension) not found in Headers or Path');
|
|
845
|
+
}
|
|
846
|
+
// checks if header_content is not empty and splits the header_content to get the file name
|
|
847
|
+
// otherwise, it will use the fileDownload - contains the file name and extension
|
|
848
|
+
const file = (header_content) ? header_content.split('=')[1].substring(0, header_content.split('=')[1].length) : `${fd.file}.${fd.ext}`;
|
|
849
|
+
this.downloadFile(file, event.body);
|
|
850
|
+
this.isPending.next(false);
|
|
851
|
+
return 100;
|
|
852
|
+
}
|
|
853
|
+
catch (error) {
|
|
854
|
+
throw new Error('Download failed');
|
|
855
|
+
}
|
|
992
856
|
default:
|
|
993
857
|
this.isPending.next(false);
|
|
994
858
|
return 0;
|
|
995
859
|
}
|
|
860
|
+
}), catchError(err => {
|
|
861
|
+
return throwError(() => err);
|
|
996
862
|
}));
|
|
997
863
|
}
|
|
864
|
+
fileDetails(path) {
|
|
865
|
+
const combinedPath = Array.isArray(path) ? path.join('/') : path;
|
|
866
|
+
if (!combinedPath || combinedPath.trim() === '') {
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
const segments = combinedPath.split('/');
|
|
870
|
+
const fileNameWithExt = segments.pop() || '';
|
|
871
|
+
if (!fileNameWithExt.includes('.'))
|
|
872
|
+
return;
|
|
873
|
+
const dotIndex = fileNameWithExt.lastIndexOf('.');
|
|
874
|
+
if (fileNameWithExt.lastIndexOf('.') < 1)
|
|
875
|
+
return;
|
|
876
|
+
return {
|
|
877
|
+
file: fileNameWithExt.substring(0, dotIndex),
|
|
878
|
+
ext: fileNameWithExt.substring(dotIndex + 1),
|
|
879
|
+
};
|
|
880
|
+
}
|
|
998
881
|
handleFinalize() {
|
|
999
882
|
return finalize(() => this.isPending.next(false));
|
|
1000
883
|
}
|
|
@@ -1046,12 +929,15 @@ class RequestService {
|
|
|
1046
929
|
return fileType;
|
|
1047
930
|
}
|
|
1048
931
|
combineHeaders(headers, isStreaming) {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
932
|
+
return (isStreaming) ?
|
|
933
|
+
{
|
|
934
|
+
...headers,
|
|
935
|
+
observe: 'events',
|
|
936
|
+
responseType: 'text',
|
|
937
|
+
reportProgress: true,
|
|
938
|
+
Accept: 'text/event-stream'
|
|
939
|
+
}
|
|
940
|
+
: headers;
|
|
1055
941
|
}
|
|
1056
942
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RequestService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1057
943
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RequestService, providedIn: 'root' }); }
|
|
@@ -1072,8 +958,10 @@ function countdown(duration) {
|
|
|
1072
958
|
|
|
1073
959
|
const DEFAULT_MAX_RETRIES = 3;
|
|
1074
960
|
function delayedRetry(delayMs, maxRetry = DEFAULT_MAX_RETRIES) {
|
|
1075
|
-
|
|
1076
|
-
|
|
961
|
+
return (src) => src.pipe(retry({
|
|
962
|
+
count: maxRetry,
|
|
963
|
+
delay: () => timer(delayMs)
|
|
964
|
+
}));
|
|
1077
965
|
}
|
|
1078
966
|
|
|
1079
967
|
/**
|
|
@@ -1088,11 +976,78 @@ function requestPolling(pollInterval, stopCondition$, isPending$) {
|
|
|
1088
976
|
};
|
|
1089
977
|
}
|
|
1090
978
|
|
|
979
|
+
class DatabaseStorage {
|
|
980
|
+
constructor(table = '', expiresIn) {
|
|
981
|
+
this.table = table;
|
|
982
|
+
this.expiresIn = expiresIn;
|
|
983
|
+
}
|
|
984
|
+
static adapt(item) {
|
|
985
|
+
return new DatabaseStorage(item?.table, item?.expiresIn);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
class RetryOptions {
|
|
990
|
+
constructor(times = 0, delay = 3) {
|
|
991
|
+
this.times = times;
|
|
992
|
+
this.delay = delay;
|
|
993
|
+
}
|
|
994
|
+
static adapt(item) {
|
|
995
|
+
return new RetryOptions(item?.times, item?.delay);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
var DataType;
|
|
1000
|
+
(function (DataType) {
|
|
1001
|
+
DataType[DataType["ANY"] = 0] = "ANY";
|
|
1002
|
+
DataType[DataType["ARRAY"] = 1] = "ARRAY";
|
|
1003
|
+
DataType[DataType["OBJECT"] = 2] = "OBJECT";
|
|
1004
|
+
})(DataType || (DataType = {}));
|
|
1005
|
+
|
|
1006
|
+
class ConfigHTTPOptions {
|
|
1007
|
+
constructor(server = '', path, headers, polling, retry, stream, displayError) {
|
|
1008
|
+
this.server = server;
|
|
1009
|
+
this.path = path;
|
|
1010
|
+
this.headers = headers;
|
|
1011
|
+
this.polling = polling;
|
|
1012
|
+
this.retry = retry;
|
|
1013
|
+
this.stream = stream;
|
|
1014
|
+
this.displayError = displayError;
|
|
1015
|
+
}
|
|
1016
|
+
static adapt(item) {
|
|
1017
|
+
const server = Array.isArray(item?.server) ? item.server.join('/') : item?.server || '';
|
|
1018
|
+
const retryOptions = item?.retry ? RetryOptions.adapt(item.retry) : RetryOptions.adapt();
|
|
1019
|
+
return new ConfigHTTPOptions(server, (item?.path) ? item.path : [], (item?.headers) ? item.headers : {}, item?.polling ? Math.floor(item.polling) : 0, retryOptions, (item?.stream) ? item.stream : false, (item?.displayError) ? item.displayError : false);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
class LocalStorageOptions {
|
|
1024
|
+
constructor(storageName, storageSettingsName, options) {
|
|
1025
|
+
this.storageName = storageName;
|
|
1026
|
+
this.storageSettingsName = storageSettingsName;
|
|
1027
|
+
this.options = options;
|
|
1028
|
+
}
|
|
1029
|
+
static adapt(item) {
|
|
1030
|
+
return new LocalStorageOptions((item?.storageName) ? item.storageName : 'storage', (item?.storageSettingsName) ? item.storageSettingsName : 'global-storage', (item?.options) ? SettingOptions.adapt(item.options) : SettingOptions.adapt());
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
class ConfigOptions {
|
|
1035
|
+
constructor(httpRequestOptions, LocalStorageOptions) {
|
|
1036
|
+
this.httpRequestOptions = httpRequestOptions;
|
|
1037
|
+
this.LocalStorageOptions = LocalStorageOptions;
|
|
1038
|
+
}
|
|
1039
|
+
static adapt(item) {
|
|
1040
|
+
return new ConfigOptions((item?.httpRequestOptions) ? ConfigHTTPOptions.adapt(item.httpRequestOptions) : undefined, (item?.LocalStorageOptions) ? LocalStorageOptions.adapt(item.LocalStorageOptions) : undefined);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1091
1044
|
class HTTPManagerService extends RequestService {
|
|
1092
|
-
constructor() {
|
|
1045
|
+
constructor(configOptions) {
|
|
1093
1046
|
super();
|
|
1047
|
+
this.configOptions = configOptions;
|
|
1094
1048
|
this.toastMessage = inject(ToastMessageService);
|
|
1095
1049
|
this.ng_injector = inject(Injector);
|
|
1050
|
+
this.objectMergerService = inject(ObjectMergerService);
|
|
1096
1051
|
this.countdown = new BehaviorSubject(0);
|
|
1097
1052
|
this.countdown$ = this.countdown.asObservable();
|
|
1098
1053
|
this.error = new BehaviorSubject(false);
|
|
@@ -1100,62 +1055,87 @@ class HTTPManagerService extends RequestService {
|
|
|
1100
1055
|
this.data = new BehaviorSubject(null);
|
|
1101
1056
|
this.data$ = this.data.asObservable();
|
|
1102
1057
|
this.polling$ = new Subject();
|
|
1058
|
+
this.config = ConfigOptions.adapt();
|
|
1059
|
+
this.config = (configOptions) ? ConfigOptions.adapt(configOptions) : ConfigOptions.adapt();
|
|
1103
1060
|
}
|
|
1104
1061
|
// REQUESTS
|
|
1105
1062
|
getRequest(options, params) {
|
|
1063
|
+
this.isPending.next(true);
|
|
1106
1064
|
this.data.next(null);
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
path: params ? [...options.path, ...params] : options.path,
|
|
1110
|
-
};
|
|
1065
|
+
options = (options) ? options : ApiRequest.adapt();
|
|
1066
|
+
const updatedOptions = this.objectMergerService.mergeOptions(options, this.config.httpRequestOptions);
|
|
1111
1067
|
const func = this.getRecordRequest;
|
|
1112
1068
|
const requests = this.createRequest(func, updatedOptions);
|
|
1113
|
-
return this.createObservable(
|
|
1069
|
+
return this.createObservable(updatedOptions, requests, func.name).pipe(tap(data => this.data.next(data)))
|
|
1070
|
+
.pipe(finalize(() => this.isPending.next(false)), catchError((err) => {
|
|
1071
|
+
if (updatedOptions.displayError)
|
|
1072
|
+
this.handleErrorWithSnackBar(err);
|
|
1073
|
+
this.isPending.next(false);
|
|
1074
|
+
return this.handleError(err);
|
|
1075
|
+
}));
|
|
1114
1076
|
}
|
|
1115
1077
|
postRequest(data, options, params) {
|
|
1078
|
+
this.isPending.next(true);
|
|
1116
1079
|
this.data.next(null);
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
path: params ? [...options.path, ...params] : options.path,
|
|
1120
|
-
};
|
|
1080
|
+
options = (options) ? options : ApiRequest.adapt();
|
|
1081
|
+
const updatedOptions = this.objectMergerService.mergeOptions(options, this.config.httpRequestOptions);
|
|
1121
1082
|
const func = this.createRecordRequest;
|
|
1122
1083
|
const requests = this.createRequest(func, updatedOptions, data);
|
|
1123
|
-
return this.createObservable(
|
|
1084
|
+
return this.createObservable(updatedOptions, requests, func.name).pipe(tap(data => this.data.next(data)))
|
|
1085
|
+
.pipe(finalize(() => this.isPending.next(false)), catchError((err) => {
|
|
1086
|
+
if (updatedOptions.displayError)
|
|
1087
|
+
this.handleErrorWithSnackBar(err);
|
|
1088
|
+
this.isPending.next(false);
|
|
1089
|
+
return this.handleError(err);
|
|
1090
|
+
}));
|
|
1124
1091
|
}
|
|
1125
1092
|
putRequest(data, options, params) {
|
|
1093
|
+
this.isPending.next(true);
|
|
1126
1094
|
this.data.next(null);
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
path: params ? [...options.path, ...params] : options.path,
|
|
1130
|
-
};
|
|
1095
|
+
options = (options) ? options : ApiRequest.adapt();
|
|
1096
|
+
const updatedOptions = this.objectMergerService.mergeOptions(options, this.config.httpRequestOptions);
|
|
1131
1097
|
const func = this.updateRecordRequest;
|
|
1132
1098
|
const requests = this.createRequest(func, updatedOptions, data);
|
|
1133
|
-
return this.createObservable(
|
|
1099
|
+
return this.createObservable(updatedOptions, requests, func.name).pipe(tap(data => this.data.next(data)))
|
|
1100
|
+
.pipe(finalize(() => this.isPending.next(false)), catchError((err) => {
|
|
1101
|
+
if (updatedOptions.displayError)
|
|
1102
|
+
this.handleErrorWithSnackBar(err);
|
|
1103
|
+
this.isPending.next(false);
|
|
1104
|
+
return this.handleError(err);
|
|
1105
|
+
}));
|
|
1134
1106
|
}
|
|
1135
1107
|
deleteRequest(options, params) {
|
|
1108
|
+
this.isPending.next(true);
|
|
1136
1109
|
this.data.next(null);
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
path: params ? [...options.path, ...params] : options.path,
|
|
1140
|
-
};
|
|
1110
|
+
options = (options) ? options : ApiRequest.adapt();
|
|
1111
|
+
const updatedOptions = this.objectMergerService.mergeOptions(options, this.config.httpRequestOptions);
|
|
1141
1112
|
const func = this.deleteRecordRequest;
|
|
1142
1113
|
const requests = this.createRequest(func, updatedOptions);
|
|
1143
|
-
return this.createObservable(
|
|
1114
|
+
return this.createObservable(updatedOptions, requests, func.name).pipe(tap(data => this.data.next(data)))
|
|
1115
|
+
.pipe(finalize(() => this.isPending.next(false)), catchError((err) => {
|
|
1116
|
+
if (updatedOptions.displayError)
|
|
1117
|
+
this.handleErrorWithSnackBar(err);
|
|
1118
|
+
this.isPending.next(false);
|
|
1119
|
+
return this.handleError(err);
|
|
1120
|
+
}));
|
|
1144
1121
|
}
|
|
1145
1122
|
downloadRequest(options, params) {
|
|
1123
|
+
this.isPending.next(true);
|
|
1124
|
+
options = (options) ? options : ApiRequest.adapt();
|
|
1125
|
+
const mergedOptions = this.objectMergerService.mergeOptions(options, this.config.httpRequestOptions);
|
|
1146
1126
|
const updatedOptions = {
|
|
1147
|
-
...
|
|
1127
|
+
...mergedOptions,
|
|
1148
1128
|
path: params ? [...options.path, ...params] : options.path,
|
|
1149
1129
|
};
|
|
1150
1130
|
const func = this.downloadFileRequest;
|
|
1151
1131
|
const requests = this.createRequest(func, updatedOptions);
|
|
1152
|
-
return this.createObservable(
|
|
1153
|
-
.pipe(
|
|
1132
|
+
return this.createObservable(updatedOptions, requests, func.name)
|
|
1133
|
+
.pipe(catchError((err) => {
|
|
1154
1134
|
this.error.next(true);
|
|
1155
|
-
|
|
1135
|
+
this.isPending.next(false);
|
|
1136
|
+
return this.handleError(err);
|
|
1156
1137
|
}));
|
|
1157
1138
|
}
|
|
1158
|
-
// UTILS
|
|
1159
1139
|
createObservable(options, request$, funcName) {
|
|
1160
1140
|
const polling = options.polling ? (options.polling > 0 ? true : false) : false;
|
|
1161
1141
|
const isPolling = polling &&
|
|
@@ -1168,36 +1148,35 @@ class HTTPManagerService extends RequestService {
|
|
|
1168
1148
|
if (!options.polling)
|
|
1169
1149
|
return;
|
|
1170
1150
|
const count = options.polling ? options.polling : 0;
|
|
1171
|
-
console.log('COUNT:', count);
|
|
1151
|
+
// console.log('COUNT:', count);
|
|
1172
1152
|
countdown(count)
|
|
1173
1153
|
.pipe(map((x) => {
|
|
1174
|
-
console.log('XX:', count, x);
|
|
1154
|
+
// console.log('XX:', count, x);
|
|
1175
1155
|
const pollingInSec = options.polling || 0;
|
|
1176
1156
|
const percentageCompleted = ((pollingInSec - x) / pollingInSec) * 100;
|
|
1177
1157
|
return Math.round(percentageCompleted);
|
|
1178
1158
|
}))
|
|
1179
1159
|
.subscribe((countDownValue) => {
|
|
1180
|
-
console.log(this.countdown.value, countDownValue);
|
|
1160
|
+
// console.log(this.countdown.value, countDownValue);
|
|
1181
1161
|
this.countdown.next(countDownValue);
|
|
1182
1162
|
});
|
|
1183
1163
|
}))
|
|
1184
1164
|
: request$.pipe(catchError((err) => {
|
|
1185
1165
|
if (err instanceof HttpErrorResponse) {
|
|
1186
1166
|
this.error.next(true);
|
|
1187
|
-
if (options.displayError)
|
|
1188
|
-
this.handleErrorWithSnackBar(err);
|
|
1189
1167
|
return this.handleError(err);
|
|
1190
1168
|
}
|
|
1191
1169
|
return throwError(() => err);
|
|
1192
|
-
})
|
|
1170
|
+
}));
|
|
1193
1171
|
return polling$.pipe(catchError((err, caught) => {
|
|
1194
1172
|
if (err instanceof HttpErrorResponse) {
|
|
1195
1173
|
this.error.next(true);
|
|
1196
|
-
|
|
1174
|
+
if (isPolling)
|
|
1175
|
+
this.stopPolling();
|
|
1197
1176
|
return this.handleError(err);
|
|
1198
1177
|
}
|
|
1199
1178
|
return throwError(() => err);
|
|
1200
|
-
}), options.retry
|
|
1179
|
+
}), options.retry?.times > 0
|
|
1201
1180
|
? delayedRetry((options?.retry.delay || 3) * 1000, (options?.retry.times || 0) - 1)
|
|
1202
1181
|
: (source) => source);
|
|
1203
1182
|
}
|
|
@@ -1207,24 +1186,25 @@ class HTTPManagerService extends RequestService {
|
|
|
1207
1186
|
}
|
|
1208
1187
|
prepareRequestData(options, data, funcName) {
|
|
1209
1188
|
if ((options.mapper && funcName === 'updateRecordRequest') || funcName === 'createRecordRequest') {
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
?
|
|
1213
|
-
|
|
1214
|
-
|
|
1189
|
+
if (options?.mapper) {
|
|
1190
|
+
data = options.mapper
|
|
1191
|
+
? Array.isArray(data)
|
|
1192
|
+
? map((item) => options.mapper(item))
|
|
1193
|
+
: options.mapper(data)
|
|
1194
|
+
: data;
|
|
1195
|
+
}
|
|
1215
1196
|
}
|
|
1216
1197
|
else {
|
|
1217
|
-
|
|
1218
|
-
|
|
1198
|
+
if (options?.adapter) {
|
|
1199
|
+
data = Array.isArray(data)
|
|
1219
1200
|
? map((item) => options.adapter(item))
|
|
1220
|
-
: options.adapter(data)
|
|
1221
|
-
|
|
1201
|
+
: options.adapter(data);
|
|
1202
|
+
}
|
|
1222
1203
|
}
|
|
1223
1204
|
return { options: options, data: data };
|
|
1224
1205
|
}
|
|
1225
1206
|
// MISC
|
|
1226
1207
|
handleError(error) {
|
|
1227
|
-
this.isPending.next(false);
|
|
1228
1208
|
return throwError(() => error);
|
|
1229
1209
|
}
|
|
1230
1210
|
handleErrorWithSnackBar(error) {
|
|
@@ -1241,7 +1221,7 @@ class HTTPManagerService extends RequestService {
|
|
|
1241
1221
|
this.isPending.next(false);
|
|
1242
1222
|
this.polling$.next();
|
|
1243
1223
|
}
|
|
1244
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HTTPManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1224
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HTTPManagerService, deps: [{ token: CONFIG_SETTINGS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1245
1225
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HTTPManagerService, providedIn: 'root' }); }
|
|
1246
1226
|
}
|
|
1247
1227
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HTTPManagerService, decorators: [{
|
|
@@ -1249,53 +1229,298 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1249
1229
|
args: [{
|
|
1250
1230
|
providedIn: 'root',
|
|
1251
1231
|
}]
|
|
1252
|
-
}], ctorParameters: function () { return [
|
|
1232
|
+
}], ctorParameters: function () { return [{ type: ConfigOptions, decorators: [{
|
|
1233
|
+
type: Optional
|
|
1234
|
+
}, {
|
|
1235
|
+
type: Inject,
|
|
1236
|
+
args: [CONFIG_SETTINGS_TOKEN]
|
|
1237
|
+
}] }]; } });
|
|
1253
1238
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1239
|
+
const storage = {
|
|
1240
|
+
localStores: [],
|
|
1241
|
+
sessionStores: [],
|
|
1242
|
+
settings: [],
|
|
1243
|
+
};
|
|
1244
|
+
class LocalStorageManagerService extends ComponentStore {
|
|
1245
|
+
startTimer() {
|
|
1246
|
+
const timer$ = interval(1000 * 3).pipe(withLatestFrom(this.data$), map(([_, state]) => state), tap((state) => {
|
|
1247
|
+
const expired = this.expired(state) ? this.expired(state) : [];
|
|
1248
|
+
if (expired.length > 0) {
|
|
1249
|
+
const ids = expired.map((item) => item.id);
|
|
1250
|
+
const updatedState = {
|
|
1251
|
+
...state,
|
|
1252
|
+
localStores: state.localStores.filter((item) => !ids.includes(item.id)),
|
|
1253
|
+
sessionStores: state.sessionStores.filter((item) => !ids.includes(item.id)),
|
|
1254
|
+
settings: state.settings.filter((item) => !ids.includes(item.id)),
|
|
1255
|
+
};
|
|
1256
|
+
this.persistState(updatedState);
|
|
1257
|
+
this.updateState(updatedState);
|
|
1258
|
+
}
|
|
1259
|
+
}));
|
|
1260
|
+
timer$.subscribe();
|
|
1258
1261
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1262
|
+
constructor(config) {
|
|
1263
|
+
super(storage);
|
|
1264
|
+
this.config = config;
|
|
1265
|
+
this.storageName = 'storage';
|
|
1266
|
+
this.storageSettingsName = 'global-storage';
|
|
1267
|
+
this.defaultOptions = SettingOptions.adapt();
|
|
1268
|
+
this.stateRetrieved = false;
|
|
1269
|
+
this.encrypted = false;
|
|
1270
|
+
this.app = inject(AppService);
|
|
1271
|
+
this.utils = inject(UtilsService);
|
|
1272
|
+
this.objectMergerService = inject(ObjectMergerService);
|
|
1273
|
+
this.encryption = inject(SymmetricalEncryptionService);
|
|
1274
|
+
this.encryptionTest = inject(EncryptionTestService);
|
|
1275
|
+
// SELECTORS
|
|
1276
|
+
this.data$ = this.select((state) => state);
|
|
1277
|
+
this.stores$ = this.select((state) => state.settings);
|
|
1278
|
+
this.storeExists$ = (store) => this.select(this.data$, (data) => data.settings.find(item => item.name === store) ? true : false);
|
|
1279
|
+
this.store$ = (store) => this.select(this.data$, (data) => {
|
|
1280
|
+
const foundStore = data.settings.find(item => item.name === store);
|
|
1281
|
+
if (foundStore) {
|
|
1282
|
+
const options = SettingOptions.adapt(foundStore.options);
|
|
1283
|
+
const found = foundStore.options?.storage === StorageType.GLOBAL
|
|
1284
|
+
? data.localStores.find(item => item.id === foundStore.id)
|
|
1285
|
+
: data.sessionStores.find(item => item.id === foundStore.id);
|
|
1286
|
+
if (!found) {
|
|
1287
|
+
this.deleteStore({ name: store });
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
if (!this.app?.appID) {
|
|
1291
|
+
console.warn('No App ID found - AppId not Provided');
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
const storageData = (options.encrypted) ? this.encryption.decrypt(found.data, this.app.appID) : found.data;
|
|
1295
|
+
return (this.isString(storageData)) ? JSON.parse(storageData) : storageData;
|
|
1296
|
+
}
|
|
1297
|
+
else {
|
|
1298
|
+
return null;
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
this.settings$ = this.select(state => (state) ? state.settings : storage.settings);
|
|
1302
|
+
this.setting$ = (store) => this.select(this.data$, (state) => {
|
|
1303
|
+
const foundSetting = state.settings.find(item => item.name === store);
|
|
1304
|
+
return (foundSetting) ? foundSetting : null;
|
|
1305
|
+
});
|
|
1306
|
+
this.persistence$ = this.data$
|
|
1307
|
+
.subscribe(data => {
|
|
1308
|
+
if (this.stateRetrieved)
|
|
1309
|
+
this.persistState(data);
|
|
1310
|
+
});
|
|
1311
|
+
this.updateState = this.updater((state, updatedState) => ({
|
|
1312
|
+
...updatedState,
|
|
1313
|
+
}));
|
|
1314
|
+
this.setStore = this.updater((state, store) => {
|
|
1315
|
+
const settings = StorageOption.adapt(store);
|
|
1316
|
+
settings.options = this.objectMergerService.mergeOptions(settings.options || this.defaultOptions, this.defaultOptions);
|
|
1317
|
+
const type = store.options.storage;
|
|
1318
|
+
const hasStore = this.hasGlobalStorage(type, store.id);
|
|
1319
|
+
store.name = this.validStoreName(store.name);
|
|
1320
|
+
if (!hasStore) {
|
|
1321
|
+
console.warn(`No such Store: ${store.name}`);
|
|
1322
|
+
return state;
|
|
1323
|
+
}
|
|
1324
|
+
else {
|
|
1325
|
+
const str = this.encryptionTest.isEncrypted(store.data) ? store.data : JSON.stringify(store.data);
|
|
1326
|
+
const dataStr = (this.isObjectOrArray(str)) ? (store.options.encrypted) ? this.encryption.encrypt(str, this.app.appID) : store.data : store.data;
|
|
1327
|
+
const localData = (dataStr && settings.options?.storage === StorageType.GLOBAL) ? [{ data: dataStr, id: settings.id }] : [];
|
|
1328
|
+
const sessionData = (dataStr && settings.options?.storage === StorageType.SESSION) ? [{ data: dataStr, id: settings.id }] : [];
|
|
1329
|
+
return {
|
|
1330
|
+
...state,
|
|
1331
|
+
localStores: [...state.localStores, ...localData],
|
|
1332
|
+
sessionStores: [...state.sessionStores, ...sessionData],
|
|
1333
|
+
settings: [...state.settings, ...[settings]],
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
});
|
|
1337
|
+
this.createStore = this.updater((state, store) => {
|
|
1338
|
+
const settings = StorageOption.adapt(store);
|
|
1339
|
+
settings.options = this.objectMergerService.mergeOptions(settings.options || this.defaultOptions, this.defaultOptions);
|
|
1340
|
+
const foundStore = state?.settings.some(item => item.name === store.name);
|
|
1341
|
+
const expires = (settings.options?.expiresIn) ? this.utils.expires(settings.options?.expiresIn) : 0;
|
|
1342
|
+
if (settings.options)
|
|
1343
|
+
settings.options.expires = expires;
|
|
1344
|
+
store.name = this.validStoreName(store.name);
|
|
1345
|
+
if (foundStore) {
|
|
1346
|
+
return state;
|
|
1347
|
+
}
|
|
1348
|
+
else {
|
|
1349
|
+
if (!this.isObjectOrArray(store.data)) {
|
|
1350
|
+
console.warn('Data must ba an Object or Array');
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
store.data = (this.isString(store.data)) ? JSON.parse(store.data) : store.data;
|
|
1354
|
+
const dataStr = (store.options.encrypted) ? this.encryption.encrypt(store.data, this.app.appID) : store.data;
|
|
1355
|
+
const localData = (settings.options?.storage === StorageType.GLOBAL) ? [{ data: dataStr, id: settings.id }] : [];
|
|
1356
|
+
const sessionData = (settings.options?.storage === StorageType.SESSION) ? [{ data: dataStr, id: settings.id }] : [];
|
|
1357
|
+
return {
|
|
1358
|
+
...state,
|
|
1359
|
+
localStores: [...state.localStores, ...localData],
|
|
1360
|
+
sessionStores: [...state.sessionStores, ...sessionData],
|
|
1361
|
+
settings: [...state.settings, ...[settings]],
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
this.updateStore = this.updater((state, store) => {
|
|
1366
|
+
store.name = this.validStoreName(store.name);
|
|
1367
|
+
const settings = state.settings.find(item => item.name === store.name);
|
|
1368
|
+
if (settings) {
|
|
1369
|
+
const type = settings.options?.storage;
|
|
1370
|
+
const hasStore = this.hasGlobalStorage(type, settings.id || '');
|
|
1371
|
+
if (!hasStore) {
|
|
1372
|
+
console.warn(`No such Store: ${store.name}`);
|
|
1373
|
+
}
|
|
1374
|
+
else {
|
|
1375
|
+
const dataStr = (settings.options?.encrypted) ? this.encryption.encrypt(store.data, this.app.appID) : store.data;
|
|
1376
|
+
const localData = (dataStr && settings.options?.storage === StorageType.GLOBAL) ? [{ data: dataStr, id: settings.id }] : [];
|
|
1377
|
+
const sessionData = (dataStr && settings.options?.storage === StorageType.SESSION) ? [{ data: dataStr, id: settings.id }] : [];
|
|
1378
|
+
state.localStores = state.localStores.filter(item => item.id !== settings.id);
|
|
1379
|
+
state.sessionStores = state.sessionStores.filter(item => item.id !== settings.id);
|
|
1380
|
+
return {
|
|
1381
|
+
...state,
|
|
1382
|
+
localStores: [...state.localStores, ...localData],
|
|
1383
|
+
sessionStores: [...state.sessionStores, ...sessionData],
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
return state;
|
|
1388
|
+
});
|
|
1389
|
+
this.deleteStore = this.updater((state, store) => {
|
|
1390
|
+
store.name = this.validStoreName(store.name);
|
|
1391
|
+
const id = state.settings.find(item => item.name === store.name)?.id;
|
|
1392
|
+
if (id) {
|
|
1393
|
+
const settings = state.settings.filter(item => item.id !== id);
|
|
1394
|
+
const localData = state.localStores.filter(item => item.id !== id);
|
|
1395
|
+
const sessionData = state.sessionStores.filter(item => item.id !== id);
|
|
1396
|
+
return {
|
|
1397
|
+
...state,
|
|
1398
|
+
localStores: [...localData],
|
|
1399
|
+
sessionStores: [...sessionData],
|
|
1400
|
+
settings: [...settings],
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
else {
|
|
1404
|
+
console.warn(`No such Store: ${store.name}`);
|
|
1405
|
+
return state;
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1408
|
+
this.isObjectOrArray = (obj) => {
|
|
1409
|
+
let parsed;
|
|
1410
|
+
try {
|
|
1411
|
+
parsed = JSON.parse(obj);
|
|
1412
|
+
}
|
|
1413
|
+
catch (e) {
|
|
1414
|
+
return false;
|
|
1415
|
+
}
|
|
1416
|
+
if (Array.isArray(parsed)) {
|
|
1417
|
+
const allStringsOrObjectsOrNumbers = parsed.every(item => typeof item === 'string' ||
|
|
1418
|
+
typeof item === 'object' && item !== null ||
|
|
1419
|
+
typeof item === 'number');
|
|
1420
|
+
return allStringsOrObjectsOrNumbers;
|
|
1421
|
+
}
|
|
1422
|
+
return typeof parsed === 'object' && parsed !== null;
|
|
1423
|
+
};
|
|
1424
|
+
this.storageName = config.LocalStorageOptions?.storageName || this.storageName;
|
|
1425
|
+
this.storageSettingsName = config.LocalStorageOptions?.storageSettingsName || this.storageSettingsName;
|
|
1426
|
+
this.defaultOptions = config.LocalStorageOptions?.options || this.defaultOptions;
|
|
1427
|
+
this.retrieveState();
|
|
1428
|
+
this.startTimer();
|
|
1261
1429
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1430
|
+
resetStore() {
|
|
1431
|
+
const newState = {
|
|
1432
|
+
localStores: [],
|
|
1433
|
+
sessionStores: [],
|
|
1434
|
+
settings: [],
|
|
1435
|
+
};
|
|
1436
|
+
this.updateState(newState);
|
|
1437
|
+
this.persistState(newState);
|
|
1268
1438
|
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1439
|
+
persistState(state) {
|
|
1440
|
+
if (!state)
|
|
1441
|
+
return;
|
|
1442
|
+
const strLocal = JSON.stringify(state.localStores);
|
|
1443
|
+
localStorage.setItem(this.storageName, strLocal);
|
|
1444
|
+
const strSession = JSON.stringify(state.sessionStores);
|
|
1445
|
+
sessionStorage.setItem(this.storageName, strSession);
|
|
1446
|
+
const settingsStr = this.encryption.encrypt(state.settings, this.app.appID);
|
|
1447
|
+
localStorage.setItem(this.storageSettingsName, settingsStr || '');
|
|
1271
1448
|
}
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
(
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
this.
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1449
|
+
expired(state) {
|
|
1450
|
+
if (!state)
|
|
1451
|
+
return [];
|
|
1452
|
+
return state.settings?.filter(item => (item.options?.expires || 0) > 0 && this.utils.hasExpired(item.options?.expires || 0));
|
|
1453
|
+
}
|
|
1454
|
+
retrieveState() {
|
|
1455
|
+
const str = localStorage.getItem(this.storageSettingsName);
|
|
1456
|
+
const localStr = localStorage.getItem(this.storageName);
|
|
1457
|
+
const sessionStr = sessionStorage.getItem(this.storageName);
|
|
1458
|
+
const localData = (localStr) ? JSON.parse(localStr) : null;
|
|
1459
|
+
const sessionData = (sessionStr) ? JSON.parse(sessionStr) : null;
|
|
1460
|
+
const decryptedStr = str ? this.encryption.decrypt(str, this.app.appID) : null;
|
|
1461
|
+
const settings = (decryptedStr && decryptedStr !== null) ? JSON.parse(decryptedStr) : [];
|
|
1462
|
+
settings.forEach(store => {
|
|
1463
|
+
const expired = (store.options?.expires || 0) > 0 && this.utils.hasExpired(store.options?.expires || 0);
|
|
1464
|
+
if (!expired) {
|
|
1465
|
+
const hasStorage = this.hasGlobalStorage(store.options?.storage, store.id || '');
|
|
1466
|
+
if (!hasStorage) {
|
|
1467
|
+
this.createStore({ id: store.id, name: store.name, data: [], options: SettingOptions.adapt(store.options) });
|
|
1468
|
+
}
|
|
1469
|
+
else {
|
|
1470
|
+
const storeData = (store.options?.storage === StorageType.GLOBAL) ? localData.find(item => item.id === store.id) : sessionData.find(item => item.id === store.id);
|
|
1471
|
+
this.setStore({ id: store.id || '', name: store.name, data: storeData?.data, options: SettingOptions.adapt(store.options) });
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
this.stateRetrieved = true;
|
|
1476
|
+
}
|
|
1477
|
+
isString(obj) {
|
|
1478
|
+
return (Object.prototype.toString.call(obj) === '[object String]');
|
|
1479
|
+
}
|
|
1480
|
+
fixAndParseJSON(jsonString) {
|
|
1481
|
+
const fixedString = jsonString
|
|
1482
|
+
.replace(/'/g, '"')
|
|
1483
|
+
.replace(/([{,]\s*)(\w+)\s*:/g, '$1"$2":')
|
|
1484
|
+
.replace(/,\s*(\}|\])/g, '$1');
|
|
1485
|
+
try {
|
|
1486
|
+
return JSON.parse(fixedString);
|
|
1487
|
+
}
|
|
1488
|
+
catch (error) {
|
|
1489
|
+
throw new Error('Failed to parse JSON: ' + error.message);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
validStoreName(str) {
|
|
1493
|
+
return str
|
|
1494
|
+
.toLowerCase() // Convert to lowercase
|
|
1495
|
+
.replace(/\s+/g, '_') // Replace spaces with underscores
|
|
1496
|
+
.replace(/[^ -~]/g, ''); // Remove non-ASCII characters
|
|
1497
|
+
}
|
|
1498
|
+
hasGlobalStorage(type = StorageType.GLOBAL, id) {
|
|
1499
|
+
const strData = [];
|
|
1500
|
+
if (type === StorageType.GLOBAL) {
|
|
1501
|
+
const str = localStorage.getItem(this.storageName);
|
|
1502
|
+
strData.push(...(str ? JSON.parse(str) : []));
|
|
1503
|
+
}
|
|
1504
|
+
else {
|
|
1505
|
+
const str = sessionStorage.getItem(this.storageName);
|
|
1506
|
+
strData.push(...(str ? JSON.parse(str) : []));
|
|
1507
|
+
}
|
|
1508
|
+
const found = strData.find(store => store.id === id);
|
|
1509
|
+
return (found) ? true : false;
|
|
1292
1510
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
const retryOptions = item?.retry ? RetryOptions.adapt(item.retry) : RetryOptions.adapt();
|
|
1296
|
-
return new ApiRequest(server, item?.path, (item?.headers) ? item.headers : {}, item?.adapter, item?.mapper, item?.polling ? Math.floor(item.polling) : 0, retryOptions, item?.stream, item?.displayError);
|
|
1511
|
+
ngOnDestroy() {
|
|
1512
|
+
this.persistence$.unsubscribe();
|
|
1297
1513
|
}
|
|
1514
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalStorageManagerService, deps: [{ token: CONFIG_SETTINGS_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1515
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalStorageManagerService, providedIn: 'root' }); }
|
|
1298
1516
|
}
|
|
1517
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalStorageManagerService, decorators: [{
|
|
1518
|
+
type: Injectable,
|
|
1519
|
+
args: [{ providedIn: 'root' }]
|
|
1520
|
+
}], ctorParameters: function () { return [{ type: ConfigOptions, decorators: [{
|
|
1521
|
+
type: Inject,
|
|
1522
|
+
args: [CONFIG_SETTINGS_TOKEN]
|
|
1523
|
+
}] }]; } });
|
|
1299
1524
|
|
|
1300
1525
|
class RequestOptions {
|
|
1301
1526
|
constructor(path = [], headers = {}) {
|
|
@@ -1313,7 +1538,7 @@ const defaultState = {
|
|
|
1313
1538
|
dataObject: null,
|
|
1314
1539
|
};
|
|
1315
1540
|
class HTTPManagerStateService extends ComponentStore {
|
|
1316
|
-
constructor(apiOptions, dataType, database) {
|
|
1541
|
+
constructor(apiOptions = ApiRequest.adapt(), dataType, database) {
|
|
1317
1542
|
super(defaultState);
|
|
1318
1543
|
this.apiOptions = apiOptions;
|
|
1319
1544
|
this.dataType = dataType;
|
|
@@ -1347,9 +1572,6 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
1347
1572
|
});
|
|
1348
1573
|
// --------------------------------------------------------------------------------------------------
|
|
1349
1574
|
// UPDATERS
|
|
1350
|
-
this.resetData$ = this.updater((state) => {
|
|
1351
|
-
return { ...state, data: [], dataObject: null };
|
|
1352
|
-
});
|
|
1353
1575
|
this.setData$ = this.updater((state, data) => {
|
|
1354
1576
|
if (!data)
|
|
1355
1577
|
return state;
|
|
@@ -1498,35 +1720,6 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
1498
1720
|
}
|
|
1499
1721
|
}));
|
|
1500
1722
|
})));
|
|
1501
|
-
// FETCH PAGINATION
|
|
1502
|
-
this.fetchPaginationCancel$ = new Subject();
|
|
1503
|
-
this.fetchPaginationRecords = (size = 10, options) => this.effect(() => {
|
|
1504
|
-
this.fetchPaginationCancel$.next();
|
|
1505
|
-
return of(RequestOptions.adapt(options)).pipe(switchMap(() => {
|
|
1506
|
-
this.resetData$();
|
|
1507
|
-
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
1508
|
-
const updatedPath = [...(options?.path ?? []), { size, page: 1 }];
|
|
1509
|
-
const firstRequestObservable = this.httpManagerService.getRequest(requestOptions, updatedPath).pipe(takeUntil(this.fetchPaginationCancel$), tap(() => this.httpManagerService.isPending.next(true)), tap((data) => {
|
|
1510
|
-
data = !data ? (this.dataType === DataType.ARRAY ? [] : {}) : data;
|
|
1511
|
-
this.setData$(data.results);
|
|
1512
|
-
}));
|
|
1513
|
-
return firstRequestObservable.pipe(takeUntil(this.fetchPaginationCancel$), expand((data) => {
|
|
1514
|
-
this.httpManagerService.isPending.next(true);
|
|
1515
|
-
const totalPages = data?.totalPages || 1;
|
|
1516
|
-
const currentPage = data?.page || 1;
|
|
1517
|
-
if (currentPage < totalPages) {
|
|
1518
|
-
const nextPage = currentPage + 1;
|
|
1519
|
-
const updatedPathWithNextPage = [...(options?.path ?? []), { size, page: nextPage }];
|
|
1520
|
-
const nextRequestObservable = this.httpManagerService.getRequest(requestOptions, updatedPathWithNextPage).pipe(takeUntil(this.fetchPaginationCancel$), tap(() => this.httpManagerService.isPending.next(true)), tap((nextData) => {
|
|
1521
|
-
nextData = !nextData ? (this.dataType === DataType.ARRAY ? [] : {}) : nextData;
|
|
1522
|
-
this.setData$(nextData.results);
|
|
1523
|
-
}));
|
|
1524
|
-
return nextRequestObservable;
|
|
1525
|
-
}
|
|
1526
|
-
return EMPTY;
|
|
1527
|
-
}), takeUntil(this.fetchPaginationCancel$), tap(() => this.httpManagerService.isPending.next(false)));
|
|
1528
|
-
}));
|
|
1529
|
-
});
|
|
1530
1723
|
this.setApiRequestOptions(apiOptions, dataType, database);
|
|
1531
1724
|
}
|
|
1532
1725
|
setApiRequestOptions(apiOptions, dataType, database) {
|
|
@@ -1535,7 +1728,7 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
1535
1728
|
this.hasDatabase = this.database?.table === "" ? false : true;
|
|
1536
1729
|
this.database = (this.hasDatabase) ? DatabaseStorage.adapt(database) : undefined;
|
|
1537
1730
|
}
|
|
1538
|
-
get
|
|
1731
|
+
get ApiRequestOptions() {
|
|
1539
1732
|
return this.apiOptions;
|
|
1540
1733
|
}
|
|
1541
1734
|
initStorage() {
|
|
@@ -1586,7 +1779,7 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
1586
1779
|
}
|
|
1587
1780
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HTTPManagerStateService, decorators: [{
|
|
1588
1781
|
type: Injectable
|
|
1589
|
-
}], ctorParameters: function () { return [{ type:
|
|
1782
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
1590
1783
|
type: Inject,
|
|
1591
1784
|
args: [API_OPTS]
|
|
1592
1785
|
}] }, { type: undefined, decorators: [{
|
|
@@ -1660,7 +1853,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1660
1853
|
|
|
1661
1854
|
class RequestErrorInterceptor {
|
|
1662
1855
|
constructor() {
|
|
1663
|
-
this.toastMessage = inject(ToastMessageService
|
|
1856
|
+
this.toastMessage = inject(ToastMessageService);
|
|
1664
1857
|
}
|
|
1665
1858
|
intercept(req, next) {
|
|
1666
1859
|
return next.handle(req).pipe(catchError$1((error) => {
|
|
@@ -1672,8 +1865,8 @@ class RequestErrorInterceptor {
|
|
|
1672
1865
|
duration: 5 * 1000, //5 seconds
|
|
1673
1866
|
});
|
|
1674
1867
|
if (error.status >= 400 && error.status < 500) {
|
|
1675
|
-
displayError.color = ToastColors.
|
|
1676
|
-
displayError.message = `${error.status}: ${error.statusText}`;
|
|
1868
|
+
displayError.color = ToastColors.WARN;
|
|
1869
|
+
displayError.message = error.error || `${error.status}: ${error.statusText}`;
|
|
1677
1870
|
console.error('Client Error:', {
|
|
1678
1871
|
status: error.status,
|
|
1679
1872
|
message: error.message,
|
|
@@ -1684,7 +1877,7 @@ class RequestErrorInterceptor {
|
|
|
1684
1877
|
}
|
|
1685
1878
|
else if (error.status >= 500) {
|
|
1686
1879
|
displayError.color = ToastColors.ERROR;
|
|
1687
|
-
displayError.message = `${error.status}: ${error.statusText}`;
|
|
1880
|
+
displayError.message = error.error || `${error.status}: ${error.statusText}`;
|
|
1688
1881
|
console.error('Server Error:', {
|
|
1689
1882
|
status: error.status,
|
|
1690
1883
|
message: error.message,
|
|
@@ -1703,6 +1896,1160 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1703
1896
|
type: Injectable
|
|
1704
1897
|
}] });
|
|
1705
1898
|
|
|
1899
|
+
const PROXY_CONFIG = new InjectionToken('PROXY_CONFIG');
|
|
1900
|
+
class ProxyDebuggerInterceptor {
|
|
1901
|
+
constructor(proxyConfig) {
|
|
1902
|
+
this.proxyConfig = proxyConfig;
|
|
1903
|
+
}
|
|
1904
|
+
intercept(req, next) {
|
|
1905
|
+
if (!this.proxyConfig) {
|
|
1906
|
+
return next.handle(req);
|
|
1907
|
+
}
|
|
1908
|
+
const headers = req.headers.keys().reduce((acc, key) => {
|
|
1909
|
+
acc[key] = req.headers.get(key) || '';
|
|
1910
|
+
return acc;
|
|
1911
|
+
}, {});
|
|
1912
|
+
for (const proxyPath in this.proxyConfig) {
|
|
1913
|
+
if (this.proxyConfig.hasOwnProperty(proxyPath)) {
|
|
1914
|
+
const proxyDetails = this.proxyConfig[proxyPath];
|
|
1915
|
+
const regex = new RegExp('^' + proxyPath.replace('/', '').replace('*', '(.*)'));
|
|
1916
|
+
if (regex.test(req.url)) {
|
|
1917
|
+
const target = proxyDetails.target;
|
|
1918
|
+
const endpoint = req.url.replace(regex, '$1');
|
|
1919
|
+
const actualPath = target + '/' + endpoint;
|
|
1920
|
+
console.log('Request Proxied:', {
|
|
1921
|
+
requestUrl: req.url,
|
|
1922
|
+
requestPayload: req.body,
|
|
1923
|
+
headers: headers,
|
|
1924
|
+
proxyPath: proxyPath,
|
|
1925
|
+
actualPath: actualPath,
|
|
1926
|
+
});
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
return next.handle(req);
|
|
1931
|
+
}
|
|
1932
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ProxyDebuggerInterceptor, deps: [{ token: PROXY_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1933
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ProxyDebuggerInterceptor }); }
|
|
1934
|
+
}
|
|
1935
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ProxyDebuggerInterceptor, decorators: [{
|
|
1936
|
+
type: Injectable
|
|
1937
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
1938
|
+
type: Optional
|
|
1939
|
+
}, {
|
|
1940
|
+
type: Inject,
|
|
1941
|
+
args: [PROXY_CONFIG]
|
|
1942
|
+
}] }]; } });
|
|
1943
|
+
|
|
1944
|
+
class DownloadFileComponent {
|
|
1945
|
+
constructor() {
|
|
1946
|
+
this.subscriptions = new Subscription();
|
|
1947
|
+
this.displayError = 3; // seconds
|
|
1948
|
+
this.diameter = 32;
|
|
1949
|
+
this.mode = 'determinate';
|
|
1950
|
+
this.isPending = false;
|
|
1951
|
+
this.active = false;
|
|
1952
|
+
this.disabled = false;
|
|
1953
|
+
this.error = new EventEmitter();
|
|
1954
|
+
this._progress = 0;
|
|
1955
|
+
this._hasError = false;
|
|
1956
|
+
this.errorTimerActive = false;
|
|
1957
|
+
}
|
|
1958
|
+
set progress(value) {
|
|
1959
|
+
this._progress = value ?? 0;
|
|
1960
|
+
}
|
|
1961
|
+
get progress() {
|
|
1962
|
+
return this._progress;
|
|
1963
|
+
}
|
|
1964
|
+
set hasError(value) {
|
|
1965
|
+
this._hasError = !!value;
|
|
1966
|
+
if (this._hasError && !this.errorTimerActive) {
|
|
1967
|
+
this.errorTimerActive = true;
|
|
1968
|
+
this.active = false;
|
|
1969
|
+
this.error.emit();
|
|
1970
|
+
this.subscriptions.add(timer(this.displayError * 1000)
|
|
1971
|
+
.subscribe((err) => {
|
|
1972
|
+
this._hasError = false;
|
|
1973
|
+
this.errorTimerActive = false;
|
|
1974
|
+
}));
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
get hasError() {
|
|
1978
|
+
return this._hasError;
|
|
1979
|
+
}
|
|
1980
|
+
ngOnInit() { }
|
|
1981
|
+
onAction() {
|
|
1982
|
+
this.isPending = false;
|
|
1983
|
+
if (this.event)
|
|
1984
|
+
this.event();
|
|
1985
|
+
}
|
|
1986
|
+
ngOnDestroy() {
|
|
1987
|
+
this.subscriptions.unsubscribe();
|
|
1988
|
+
}
|
|
1989
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DownloadFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1990
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DownloadFileComponent, selector: "app-download-file", inputs: { event: "event", displayError: "displayError", diameter: "diameter", mode: "mode", isPending: "isPending", active: "active", disabled: "disabled", progress: "progress", hasError: "hasError" }, outputs: { error: "error" }, ngImport: i0, template: "<ng-container *ngIf=\"!isPending; else DOWNLOADING\">\n <ng-container *ngIf=\"hasError; else NORMAL\">\n <div class=\"width center-txt\" style=\"margin-bottom: 4px;\">\n <mat-icon color=\"warn\" class=\"warn-icon\">warning</mat-icon>\n </div>\n </ng-container>\n <ng-template #NORMAL>\n <ng-container *ngIf=\"active; else ACTION\">\n\n <div class=\"container-obj\">\n <div class=\"centered-obj-div\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n </div>\n\n </ng-container>\n <ng-template #ACTION>\n <button data-tracking=\"export-btn\" mat-icon-button (click)=\"onAction()\" class=\"icon-button\" [disabled]=\"disabled\">\n <mat-icon class=\"custom-icon\">file_download</mat-icon>\n </button>\n </ng-template>\n </ng-template>\n</ng-container>\n\n<ng-template #DOWNLOADING>\n <div\n class=\"spinner-container\"\n *ngIf=\"(progress > 0 && progress < 100); else INDETERMINATE\"\n >\n <div class=\"spinner-background\">\n {{progress}}%\n </div>\n <mat-progress-spinner\n color=\"primary\"\n [mode]=\"mode\"\n [value]=\"progress\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n <ng-template #INDETERMINATE>\n <div class=\"container-obj\">\n <div class=\"centered-obj-div\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n </div>\n </ng-template>\n\n</ng-template>\n\n\n\n", styles: [":not(spinner-container).spinner-container{position:relative}:not(spinner-container).spinner-container .spinner-background{position:absolute;width:44px;height:44px;font-size:12px;line-height:32px;text-align:center;overflow:hidden;border-radius:50%;border:solid 5px whitesmoke}.center-txt{align-content:center;text-align:-webkit-center}.width{width:48px;height:48px}.icon-button{display:flex;align-items:center;justify-content:center;width:48px;height:48px;padding:0}.container-obj{display:flex;justify-content:center;align-items:center;width:48px;height:48px}.centered-obj-div{text-align:center}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1991
|
+
}
|
|
1992
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DownloadFileComponent, decorators: [{
|
|
1993
|
+
type: Component,
|
|
1994
|
+
args: [{ selector: 'app-download-file', encapsulation: ViewEncapsulation.None, template: "<ng-container *ngIf=\"!isPending; else DOWNLOADING\">\n <ng-container *ngIf=\"hasError; else NORMAL\">\n <div class=\"width center-txt\" style=\"margin-bottom: 4px;\">\n <mat-icon color=\"warn\" class=\"warn-icon\">warning</mat-icon>\n </div>\n </ng-container>\n <ng-template #NORMAL>\n <ng-container *ngIf=\"active; else ACTION\">\n\n <div class=\"container-obj\">\n <div class=\"centered-obj-div\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n </div>\n\n </ng-container>\n <ng-template #ACTION>\n <button data-tracking=\"export-btn\" mat-icon-button (click)=\"onAction()\" class=\"icon-button\" [disabled]=\"disabled\">\n <mat-icon class=\"custom-icon\">file_download</mat-icon>\n </button>\n </ng-template>\n </ng-template>\n</ng-container>\n\n<ng-template #DOWNLOADING>\n <div\n class=\"spinner-container\"\n *ngIf=\"(progress > 0 && progress < 100); else INDETERMINATE\"\n >\n <div class=\"spinner-background\">\n {{progress}}%\n </div>\n <mat-progress-spinner\n color=\"primary\"\n [mode]=\"mode\"\n [value]=\"progress\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n <ng-template #INDETERMINATE>\n <div class=\"container-obj\">\n <div class=\"centered-obj-div\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n </div>\n </ng-template>\n\n</ng-template>\n\n\n\n", styles: [":not(spinner-container).spinner-container{position:relative}:not(spinner-container).spinner-container .spinner-background{position:absolute;width:44px;height:44px;font-size:12px;line-height:32px;text-align:center;overflow:hidden;border-radius:50%;border:solid 5px whitesmoke}.center-txt{align-content:center;text-align:-webkit-center}.width{width:48px;height:48px}.icon-button{display:flex;align-items:center;justify-content:center;width:48px;height:48px;padding:0}.container-obj{display:flex;justify-content:center;align-items:center;width:48px;height:48px}.centered-obj-div{text-align:center}\n"] }]
|
|
1995
|
+
}], propDecorators: { event: [{
|
|
1996
|
+
type: Input
|
|
1997
|
+
}], displayError: [{
|
|
1998
|
+
type: Input
|
|
1999
|
+
}], diameter: [{
|
|
2000
|
+
type: Input
|
|
2001
|
+
}], mode: [{
|
|
2002
|
+
type: Input
|
|
2003
|
+
}], isPending: [{
|
|
2004
|
+
type: Input
|
|
2005
|
+
}], active: [{
|
|
2006
|
+
type: Input
|
|
2007
|
+
}], disabled: [{
|
|
2008
|
+
type: Input
|
|
2009
|
+
}], error: [{
|
|
2010
|
+
type: Output
|
|
2011
|
+
}], progress: [{
|
|
2012
|
+
type: Input
|
|
2013
|
+
}], hasError: [{
|
|
2014
|
+
type: Input
|
|
2015
|
+
}] } });
|
|
2016
|
+
|
|
2017
|
+
class DownloadLabels {
|
|
2018
|
+
constructor(error = '', action = '', icon = 'error') {
|
|
2019
|
+
this.error = error;
|
|
2020
|
+
this.action = action;
|
|
2021
|
+
this.icon = icon;
|
|
2022
|
+
}
|
|
2023
|
+
static adapt(item) {
|
|
2024
|
+
return new DownloadLabels(item?.error, item?.action, item?.icon);
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
class FileDownloaderComponent extends HTTPManagerService {
|
|
2029
|
+
set labels(value) {
|
|
2030
|
+
this._labels = (value) ? DownloadLabels.adapt(value) : DownloadLabels.adapt();
|
|
2031
|
+
}
|
|
2032
|
+
get labels() {
|
|
2033
|
+
return this._labels;
|
|
2034
|
+
}
|
|
2035
|
+
constructor() {
|
|
2036
|
+
super();
|
|
2037
|
+
this.delayError = 3;
|
|
2038
|
+
this.apiRequest = ApiRequest.adapt();
|
|
2039
|
+
this.displayErrorMessage = false;
|
|
2040
|
+
this._labels = DownloadLabels.adapt();
|
|
2041
|
+
this.active = false;
|
|
2042
|
+
this.subscription = new Subscription();
|
|
2043
|
+
this.completed = new EventEmitter();
|
|
2044
|
+
this.failed = new EventEmitter();
|
|
2045
|
+
this.disabled = false;
|
|
2046
|
+
}
|
|
2047
|
+
ngOnInit() {
|
|
2048
|
+
}
|
|
2049
|
+
onDownloadStreaming() {
|
|
2050
|
+
if (this.active)
|
|
2051
|
+
return;
|
|
2052
|
+
this.active = true;
|
|
2053
|
+
return this.downloadRequest(this.apiRequest)
|
|
2054
|
+
.pipe(distinctUntilChanged(), catchError((err) => {
|
|
2055
|
+
this.onError(err.message);
|
|
2056
|
+
this.active = false;
|
|
2057
|
+
this.failed.emit(err);
|
|
2058
|
+
return err;
|
|
2059
|
+
})).subscribe((res) => {
|
|
2060
|
+
if (res === 100) {
|
|
2061
|
+
this.active = false;
|
|
2062
|
+
this.completed.emit();
|
|
2063
|
+
}
|
|
2064
|
+
});
|
|
2065
|
+
}
|
|
2066
|
+
onError(message) {
|
|
2067
|
+
if (!message || !this.displayErrorMessage)
|
|
2068
|
+
return;
|
|
2069
|
+
const display = ToastDisplay.adapt({
|
|
2070
|
+
message,
|
|
2071
|
+
action: 'Ok',
|
|
2072
|
+
color: ToastColors.ERROR,
|
|
2073
|
+
icon: 'error',
|
|
2074
|
+
});
|
|
2075
|
+
this.active = false;
|
|
2076
|
+
this.toastMessage.toastMessage(display);
|
|
2077
|
+
}
|
|
2078
|
+
OnDestroy() {
|
|
2079
|
+
this.subscription.unsubscribe();
|
|
2080
|
+
}
|
|
2081
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FileDownloaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2082
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FileDownloaderComponent, selector: "app-file-downloader", inputs: { delayError: "delayError", apiRequest: "apiRequest", displayErrorMessage: "displayErrorMessage", labels: "labels", disabled: "disabled" }, outputs: { completed: "completed", failed: "failed" }, usesInheritance: true, ngImport: i0, template: "<app-download-file\n [disabled]=\"disabled\"\n [displayError]=\"3\"\n [event]=\"onDownloadStreaming.bind(this)\"\n [isPending]=\"(isPending$ | async) || false\"\n [progress]=\"(progress$ | async)\"\n [hasError]=\"(error$ | async)\"\n (error)=\"onError(labels.error)\"\n [active]=\"active\"\n></app-download-file>\n", styles: [".snackBarInfo{background-color:#f44336;color:#fff}.mat-simple-snackbar>span{font-weight:700}.mat-simple-snackbar-action .mat-button .mat-button-wrapper{color:#fff}.cdk-overlay-pane>.mat-snack-bar-container{width:100%}.mat-snack-bar-container{max-width:100%!important;width:100%}\n"], dependencies: [{ kind: "component", type: DownloadFileComponent, selector: "app-download-file", inputs: ["event", "displayError", "diameter", "mode", "isPending", "active", "disabled", "progress", "hasError"], outputs: ["error"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
2083
|
+
}
|
|
2084
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FileDownloaderComponent, decorators: [{
|
|
2085
|
+
type: Component,
|
|
2086
|
+
args: [{ selector: 'app-file-downloader', encapsulation: ViewEncapsulation.None, template: "<app-download-file\n [disabled]=\"disabled\"\n [displayError]=\"3\"\n [event]=\"onDownloadStreaming.bind(this)\"\n [isPending]=\"(isPending$ | async) || false\"\n [progress]=\"(progress$ | async)\"\n [hasError]=\"(error$ | async)\"\n (error)=\"onError(labels.error)\"\n [active]=\"active\"\n></app-download-file>\n", styles: [".snackBarInfo{background-color:#f44336;color:#fff}.mat-simple-snackbar>span{font-weight:700}.mat-simple-snackbar-action .mat-button .mat-button-wrapper{color:#fff}.cdk-overlay-pane>.mat-snack-bar-container{width:100%}.mat-snack-bar-container{max-width:100%!important;width:100%}\n"] }]
|
|
2087
|
+
}], ctorParameters: function () { return []; }, propDecorators: { delayError: [{
|
|
2088
|
+
type: Input
|
|
2089
|
+
}], apiRequest: [{
|
|
2090
|
+
type: Input
|
|
2091
|
+
}], displayErrorMessage: [{
|
|
2092
|
+
type: Input
|
|
2093
|
+
}], labels: [{
|
|
2094
|
+
type: Input
|
|
2095
|
+
}], completed: [{
|
|
2096
|
+
type: Output
|
|
2097
|
+
}], failed: [{
|
|
2098
|
+
type: Output
|
|
2099
|
+
}], disabled: [{
|
|
2100
|
+
type: Input
|
|
2101
|
+
}] } });
|
|
2102
|
+
|
|
2103
|
+
class SpinnerComponent {
|
|
2104
|
+
constructor() {
|
|
2105
|
+
this.value = 0;
|
|
2106
|
+
}
|
|
2107
|
+
ngOnInit() {
|
|
2108
|
+
}
|
|
2109
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2110
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SpinnerComponent, selector: "app-spinner", inputs: { color: "color", diameter: "diameter", display: "display", mode: "mode", strokeWidth: "strokeWidth", value: "value" }, ngImport: i0, template: "<div class=\"spinner-background\">{{display}}</div>\n<mat-progress-spinner\n [color]=\"color\"\n [diameter]=\"diameter\"\n [mode]=\"mode || 'indeterminate'\"\n [strokeWidth]=\"strokeWidth\"\n [value]=\"value\">\n</mat-progress-spinner>\n", styles: [".example-h2{margin:24px 0}:not(spinner-container).spinner-container{position:relative}:not(spinner-container).spinner-container .spinner-background{position:absolute;width:80px;height:80px;line-height:80px;text-align:center;overflow:hidden;border-color:#673ab71f;border-radius:50%;border-style:solid;border-width:10px}\n"], dependencies: [{ kind: "component", type: i3.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] }); }
|
|
2111
|
+
}
|
|
2112
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpinnerComponent, decorators: [{
|
|
2113
|
+
type: Component,
|
|
2114
|
+
args: [{ selector: 'app-spinner', template: "<div class=\"spinner-background\">{{display}}</div>\n<mat-progress-spinner\n [color]=\"color\"\n [diameter]=\"diameter\"\n [mode]=\"mode || 'indeterminate'\"\n [strokeWidth]=\"strokeWidth\"\n [value]=\"value\">\n</mat-progress-spinner>\n", styles: [".example-h2{margin:24px 0}:not(spinner-container).spinner-container{position:relative}:not(spinner-container).spinner-container .spinner-background{position:absolute;width:80px;height:80px;line-height:80px;text-align:center;overflow:hidden;border-color:#673ab71f;border-radius:50%;border-style:solid;border-width:10px}\n"] }]
|
|
2115
|
+
}], ctorParameters: function () { return []; }, propDecorators: { color: [{
|
|
2116
|
+
type: Input
|
|
2117
|
+
}], diameter: [{
|
|
2118
|
+
type: Input
|
|
2119
|
+
}], display: [{
|
|
2120
|
+
type: Input
|
|
2121
|
+
}], mode: [{
|
|
2122
|
+
type: Input
|
|
2123
|
+
}], strokeWidth: [{
|
|
2124
|
+
type: Input
|
|
2125
|
+
}], value: [{
|
|
2126
|
+
type: Input
|
|
2127
|
+
}] } });
|
|
2128
|
+
|
|
2129
|
+
class FileDownloaderModule {
|
|
2130
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FileDownloaderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2131
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: FileDownloaderModule, declarations: [SpinnerComponent,
|
|
2132
|
+
DownloadFileComponent,
|
|
2133
|
+
FileDownloaderComponent], imports: [CommonModule,
|
|
2134
|
+
MatIconModule,
|
|
2135
|
+
MatProgressSpinnerModule,
|
|
2136
|
+
MatButtonModule], exports: [FileDownloaderComponent] }); }
|
|
2137
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FileDownloaderModule, imports: [CommonModule,
|
|
2138
|
+
MatIconModule,
|
|
2139
|
+
MatProgressSpinnerModule,
|
|
2140
|
+
MatButtonModule] }); }
|
|
2141
|
+
}
|
|
2142
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FileDownloaderModule, decorators: [{
|
|
2143
|
+
type: NgModule,
|
|
2144
|
+
args: [{
|
|
2145
|
+
imports: [
|
|
2146
|
+
CommonModule,
|
|
2147
|
+
MatIconModule,
|
|
2148
|
+
MatProgressSpinnerModule,
|
|
2149
|
+
MatButtonModule,
|
|
2150
|
+
],
|
|
2151
|
+
declarations: [
|
|
2152
|
+
SpinnerComponent,
|
|
2153
|
+
DownloadFileComponent,
|
|
2154
|
+
FileDownloaderComponent,
|
|
2155
|
+
],
|
|
2156
|
+
exports: [
|
|
2157
|
+
FileDownloaderComponent
|
|
2158
|
+
]
|
|
2159
|
+
}]
|
|
2160
|
+
}] });
|
|
2161
|
+
|
|
2162
|
+
class LocalStorageDemoComponent {
|
|
2163
|
+
get type() {
|
|
2164
|
+
return (this.typeControl.value) ? +this.typeControl.value : 0;
|
|
2165
|
+
}
|
|
2166
|
+
get isValid() {
|
|
2167
|
+
return this.newStoreForm.valid;
|
|
2168
|
+
}
|
|
2169
|
+
get isValidData() {
|
|
2170
|
+
return this.storageForm.valid;
|
|
2171
|
+
}
|
|
2172
|
+
constructor(configOptions) {
|
|
2173
|
+
this.configOptions = configOptions;
|
|
2174
|
+
this.fb = inject(FormBuilder);
|
|
2175
|
+
this.utils = inject(UtilsService);
|
|
2176
|
+
this.type$ = new BehaviorSubject(StorageType.GLOBAL);
|
|
2177
|
+
this.typeControl = this.fb.control(StorageType.GLOBAL.toString());
|
|
2178
|
+
this.localStorageManagerService = inject(LocalStorageManagerService);
|
|
2179
|
+
this.settings$ = this.localStorageManagerService.settings$;
|
|
2180
|
+
this.setting$ = (store) => this.localStorageManagerService.setting$(store);
|
|
2181
|
+
this.storageForm = this.fb.group({
|
|
2182
|
+
store: this.fb.control(null),
|
|
2183
|
+
type: 'local',
|
|
2184
|
+
settingType: 'local',
|
|
2185
|
+
encrypted: false,
|
|
2186
|
+
data: this.fb.control('', Validators.required),
|
|
2187
|
+
});
|
|
2188
|
+
this.newStoreForm = this.fb.group({
|
|
2189
|
+
name: this.fb.control(null, Validators.required),
|
|
2190
|
+
storage: 'local',
|
|
2191
|
+
encrypted: false,
|
|
2192
|
+
data: this.fb.control('', Validators.required),
|
|
2193
|
+
expiresIn: this.fb.control('0')
|
|
2194
|
+
});
|
|
2195
|
+
this.storeData$ = this.storageForm.get('store')?.valueChanges
|
|
2196
|
+
.pipe(switchMap((data) => {
|
|
2197
|
+
return data
|
|
2198
|
+
? this.localStorageManagerService.store$(data.name)
|
|
2199
|
+
: of('');
|
|
2200
|
+
}), tap(data => {
|
|
2201
|
+
this.storageForm.get('data')?.patchValue(data, { emitEvent: false });
|
|
2202
|
+
}));
|
|
2203
|
+
this.expiresIn = (epoch) => this.utils.expiresIn(epoch);
|
|
2204
|
+
this.isValidJSON = (str) => {
|
|
2205
|
+
try {
|
|
2206
|
+
JSON.parse(str);
|
|
2207
|
+
return true;
|
|
2208
|
+
}
|
|
2209
|
+
catch (e) {
|
|
2210
|
+
return false;
|
|
2211
|
+
}
|
|
2212
|
+
};
|
|
2213
|
+
this.displayedColumns = ['name', 'id', 'encrypted', 'expires', "option"];
|
|
2214
|
+
this.filterData = (values) => {
|
|
2215
|
+
if (!values)
|
|
2216
|
+
return [];
|
|
2217
|
+
return values.filter((item) => item.options.storage === +this.type);
|
|
2218
|
+
};
|
|
2219
|
+
this.create = false;
|
|
2220
|
+
}
|
|
2221
|
+
ngOnInit() {
|
|
2222
|
+
this.storeProps = this.configOptions?.LocalStorageOptions;
|
|
2223
|
+
this.options = this.storeProps?.options;
|
|
2224
|
+
if (this.options?.storage) {
|
|
2225
|
+
this.typeControl.patchValue(this.options.storage.toString());
|
|
2226
|
+
this.typeControl.disable();
|
|
2227
|
+
}
|
|
2228
|
+
else {
|
|
2229
|
+
this.typeControl.enable();
|
|
2230
|
+
}
|
|
2231
|
+
if (this.options?.expiresIn) {
|
|
2232
|
+
this.newStoreForm.get('expiresIn')?.patchValue(this.options.expiresIn);
|
|
2233
|
+
this.newStoreForm.get('expiresIn')?.disable();
|
|
2234
|
+
}
|
|
2235
|
+
else {
|
|
2236
|
+
this.newStoreForm.get('expiresIn')?.enable();
|
|
2237
|
+
}
|
|
2238
|
+
if (this.options?.encrypted) {
|
|
2239
|
+
this.newStoreForm.get('encrypted')?.patchValue(this.options.encrypted);
|
|
2240
|
+
this.newStoreForm.get('encrypted')?.disable();
|
|
2241
|
+
}
|
|
2242
|
+
else {
|
|
2243
|
+
this.newStoreForm.get('encrypted')?.enable();
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
onCreateStore() {
|
|
2247
|
+
if (!this.isValid)
|
|
2248
|
+
return;
|
|
2249
|
+
const store = this.newStoreForm.value;
|
|
2250
|
+
if (!store.name || store.name === '')
|
|
2251
|
+
return;
|
|
2252
|
+
const options = { storage: this.type, encrypted: store.encrypted, expiresIn: store.expiresIn };
|
|
2253
|
+
this.localStorageManagerService.createStore({
|
|
2254
|
+
name: store.name,
|
|
2255
|
+
data: store.data,
|
|
2256
|
+
options: SettingOptions.adapt(options)
|
|
2257
|
+
});
|
|
2258
|
+
this.newStoreForm.reset();
|
|
2259
|
+
this.create = false;
|
|
2260
|
+
}
|
|
2261
|
+
onUpdateStore(store) {
|
|
2262
|
+
if (!this.storageForm.valid)
|
|
2263
|
+
return;
|
|
2264
|
+
const storeData = this.storageForm.value;
|
|
2265
|
+
const data = JSON.parse(storeData.data || '');
|
|
2266
|
+
const type = (storeData.type === 'local') ? StorageType.GLOBAL : StorageType.SESSION;
|
|
2267
|
+
const options = { storage: type, encrypted: storeData.encrypted };
|
|
2268
|
+
this.localStorageManagerService.updateStore({
|
|
2269
|
+
name: store.name,
|
|
2270
|
+
data
|
|
2271
|
+
});
|
|
2272
|
+
}
|
|
2273
|
+
onSelectedRow(store) {
|
|
2274
|
+
this.store = store;
|
|
2275
|
+
this.data$ = this.localStorageManagerService.store$(store.name).pipe(map(item => JSON.stringify(item)));
|
|
2276
|
+
this.create = false;
|
|
2277
|
+
}
|
|
2278
|
+
onCreate() {
|
|
2279
|
+
this.onCancel();
|
|
2280
|
+
this.create = true;
|
|
2281
|
+
}
|
|
2282
|
+
onDelete(store) {
|
|
2283
|
+
console.log('DELETED STORE:', store);
|
|
2284
|
+
this.localStorageManagerService.deleteStore({
|
|
2285
|
+
name: store.name,
|
|
2286
|
+
});
|
|
2287
|
+
this.onCancel();
|
|
2288
|
+
}
|
|
2289
|
+
onCancel() {
|
|
2290
|
+
this.data$ = EMPTY;
|
|
2291
|
+
this.store = null;
|
|
2292
|
+
this.create = false;
|
|
2293
|
+
}
|
|
2294
|
+
onUpdate(store, data) {
|
|
2295
|
+
this.localStorageManagerService.updateStore({
|
|
2296
|
+
name: store.name,
|
|
2297
|
+
data: JSON.parse(data)
|
|
2298
|
+
});
|
|
2299
|
+
this.onCancel();
|
|
2300
|
+
}
|
|
2301
|
+
onReset() {
|
|
2302
|
+
this.localStorageManagerService.resetStore();
|
|
2303
|
+
}
|
|
2304
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalStorageDemoComponent, deps: [{ token: CONFIG_SETTINGS_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2305
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: LocalStorageDemoComponent, selector: "app-local-storage-demo", ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <div style=\"display: flex; gap: 1rem\">\n <h2 style=\"padding-top: .5rem; display: flex;\">\n <div style=\"padding-top: .5rem;\">Local Storage Manager</div>\n <div>\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>info</mat-icon>\n </button>\n </div>\n </h2>\n <span style=\"flex:1\"></span>\n <div style=\"padding-top: .25rem;\">\n <mat-button-toggle-group name=\"storage\" [formControl]=\"typeControl\" (change)=\"onCancel()\">\n <mat-button-toggle value=\"0\">Local Storage</mat-button-toggle>\n <mat-button-toggle value=\"1\">Session Storage</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"margin-top: .25rem;\">\n <button mat-icon-button (click)=\"onCreate()\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </div>\n\n <ng-container *ngIf=\"storeProps?.storageName || storeProps?.storageSettingsName\">\n <div style=\"display: flex; gap: .5rem; flex-direction: column; border: gray solid thin; background-color: whitesmoke; padding: 1rem;\"\n >\n <div style=\"display: flex;\">\n <div *ngIf=\"storeProps?.storageSettingsName\" style=\"flex:1\">\n Database: <b>{{ storeProps?.storageSettingsName }}</b>\n </div>\n <div *ngIf=\"storeProps?.storageName\" style=\"flex:1\">\n Data: <b>{{ storeProps?.storageName }}</b>\n </div>\n </div>\n </div>\n </ng-container>\n\n <div style=\"margin-top: 2rem;\" [formGroup]=\"newStoreForm\" *ngIf=\"create; else LIST\">\n\n <h2>Create Store</h2>\n\n <div style=\"display: flex; gap: 1rem;\">\n <div style=\"flex:1\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Store Name</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"name\">\n </mat-form-field>\n </div>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In...</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"0\">None</mat-option>\n <mat-option value=\"30s\">30 Seconds</mat-option>\n <mat-option value=\"1mn\">1 Minute</mat-option>\n <mat-option value=\"1hr\">1 Hour</mat-option>\n <mat-option value=\"1d\">1 Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"margin-top: 1rem;\">\n <mat-slide-toggle formControlName=\"encrypted\">Encrypted</mat-slide-toggle>\n </div>\n </div>\n\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex: 1;\">\n <mat-label>Data (Must be an Object or Array of any)</mat-label>\n <textarea matInput placeholder=\"[]\" formControlName=\"data\" #json></textarea>\n </mat-form-field>\n </div>\n <mat-error *ngIf=\"!isValidJSON(json.value)\">Not Valid Data</mat-error>\n\n <div style=\"display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onCreateStore()\" [disabled]=\"!(isValid && isValidJSON(json.value))\">\n Save Store\n </button>\n </div>\n\n </div>\n\n <ng-template #LIST>\n\n <div style=\"margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n{{ settings$ | async | json }}\n <div *ngIf=\"filterData(settings$ | async) as data\">\n <ng-container *ngIf=\"data.length > 0; else NO_DATA\">\n <table mat-table [dataSource]=\"data\">\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> Store </th>\n <td mat-cell *matCellDef=\"let element\" style=\"font-weight: bold; text-transform: uppercase;\"> {{element.name}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"encrypted\">\n <th mat-header-cell *matHeaderCellDef style=\"text-align: center;\"> Encrypted </th>\n <td mat-cell *matCellDef=\"let element\" style=\"text-align: center;\">\n <ng-container *ngIf=\"element.options.encrypted; else NO\">YES</ng-container>\n <ng-template #NO><span style=\"color:gray\">NO</span></ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"expires\">\n <th mat-header-cell *matHeaderCellDef style=\"text-align: center;\"> Expires </th>\n <td mat-cell *matCellDef=\"let element\" style=\"text-align: center;\">\n <ng-container *ngIf=\"element.options.expires !== 0; else NO_DATA\">\n {{expiresIn(element.options.expires)}}\n </ng-container>\n <ng-template #NO_DATA>\n \u221E\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"option\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let element\" style=\"padding-right: 0;\">\n <div style=\"display: flex;justify-content: flex-end;\">\n <button mat-icon-button color=\"warn\" (click)=\"onDelete(element); $event.stopPropagation()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\" (click)=\"onSelectedRow(row)\"></tr>\n </table>\n </ng-container>\n\n <ng-template #NO_DATA>\n <h3 style=\"margin-top: 1rem;\">No Data</h3>\n </ng-template>\n\n <div *ngIf=\"(data$ | async) as data\" style=\"margin-top: 2rem;\">\n <div style=\"margin-bottom: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <h3>STORE: <span style=\"font-weight: bold;\">{{ store.name | uppercase }}</span></h3>\n <h3>SETTINGS: {{ setting$(store.name) | async | json }}</h3>\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex: 1;\">\n <mat-label>Data (Must be an Object or Array of any)</mat-label>\n <textarea matInput placeholder=\"[]\" #json [value]=\"data\"></textarea>\n </mat-form-field>\n </div>\n <mat-error *ngIf=\"!isValidJSON(json.value)\">Not Valid Data</mat-error>\n\n <div style=\"display: flex; gap: .5rem;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onCancel()\">Cancel</button>\n <button mat-stroked-button (click)=\"onUpdate(store, json.value)\" [disabled]=\"!(isValidJSON(json.value))\">Update</button>\n </div>\n </div>\n </div>\n\n </ng-template>\n\n <div style=\"margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <button mat-stroked-button (click)=\"onReset()\">Delete All Stores</button>\n </div>\n\n</div>\n\n\n<mat-menu #menu=\"matMenu\">\n <div style=\"padding: 1rem;\">\n <p>Please note that the LocalStorage (encryption) and management of data is dependant on initializing the APP_ID</p>\n <p>Must provide a value for <b>APP_ID</b> in AppModule->Providers</p>\n <mat-divider></mat-divider>\n <div style=\"font-size: smaller; margin-top: .5rem;\">\n <p>Example: UUID (self.crypto.randomUUID() to generate)</p>\n <div style=\"background-color: whitesmoke; padding: 1rem;\">\n {<br>\n provide: APP_ID,<br>\n useValue: \"056991ac-3537-43ab-b5b9-83edf6554eff\",<br>\n }\n </div>\n </div>\n </div>\n</mat-menu>\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.demo-row-is-clicked{font-weight:700}.mat-mdc-menu-panel.mat-mdc-menu-panel{max-width:280px!important}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "panelWidth", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i3$2.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "directive", type: i3$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i10.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10.MatButtonToggle, selector: "mat-button-toggle", inputs: ["disableRipple", "aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: i10$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
2306
|
+
}
|
|
2307
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalStorageDemoComponent, decorators: [{
|
|
2308
|
+
type: Component,
|
|
2309
|
+
args: [{ selector: 'app-local-storage-demo', encapsulation: ViewEncapsulation.None, template: "<div style=\"margin: 2rem;\">\n\n <div style=\"display: flex; gap: 1rem\">\n <h2 style=\"padding-top: .5rem; display: flex;\">\n <div style=\"padding-top: .5rem;\">Local Storage Manager</div>\n <div>\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>info</mat-icon>\n </button>\n </div>\n </h2>\n <span style=\"flex:1\"></span>\n <div style=\"padding-top: .25rem;\">\n <mat-button-toggle-group name=\"storage\" [formControl]=\"typeControl\" (change)=\"onCancel()\">\n <mat-button-toggle value=\"0\">Local Storage</mat-button-toggle>\n <mat-button-toggle value=\"1\">Session Storage</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"margin-top: .25rem;\">\n <button mat-icon-button (click)=\"onCreate()\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </div>\n\n <ng-container *ngIf=\"storeProps?.storageName || storeProps?.storageSettingsName\">\n <div style=\"display: flex; gap: .5rem; flex-direction: column; border: gray solid thin; background-color: whitesmoke; padding: 1rem;\"\n >\n <div style=\"display: flex;\">\n <div *ngIf=\"storeProps?.storageSettingsName\" style=\"flex:1\">\n Database: <b>{{ storeProps?.storageSettingsName }}</b>\n </div>\n <div *ngIf=\"storeProps?.storageName\" style=\"flex:1\">\n Data: <b>{{ storeProps?.storageName }}</b>\n </div>\n </div>\n </div>\n </ng-container>\n\n <div style=\"margin-top: 2rem;\" [formGroup]=\"newStoreForm\" *ngIf=\"create; else LIST\">\n\n <h2>Create Store</h2>\n\n <div style=\"display: flex; gap: 1rem;\">\n <div style=\"flex:1\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Store Name</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"name\">\n </mat-form-field>\n </div>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In...</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"0\">None</mat-option>\n <mat-option value=\"30s\">30 Seconds</mat-option>\n <mat-option value=\"1mn\">1 Minute</mat-option>\n <mat-option value=\"1hr\">1 Hour</mat-option>\n <mat-option value=\"1d\">1 Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"margin-top: 1rem;\">\n <mat-slide-toggle formControlName=\"encrypted\">Encrypted</mat-slide-toggle>\n </div>\n </div>\n\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex: 1;\">\n <mat-label>Data (Must be an Object or Array of any)</mat-label>\n <textarea matInput placeholder=\"[]\" formControlName=\"data\" #json></textarea>\n </mat-form-field>\n </div>\n <mat-error *ngIf=\"!isValidJSON(json.value)\">Not Valid Data</mat-error>\n\n <div style=\"display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onCreateStore()\" [disabled]=\"!(isValid && isValidJSON(json.value))\">\n Save Store\n </button>\n </div>\n\n </div>\n\n <ng-template #LIST>\n\n <div style=\"margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n{{ settings$ | async | json }}\n <div *ngIf=\"filterData(settings$ | async) as data\">\n <ng-container *ngIf=\"data.length > 0; else NO_DATA\">\n <table mat-table [dataSource]=\"data\">\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> Store </th>\n <td mat-cell *matCellDef=\"let element\" style=\"font-weight: bold; text-transform: uppercase;\"> {{element.name}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"encrypted\">\n <th mat-header-cell *matHeaderCellDef style=\"text-align: center;\"> Encrypted </th>\n <td mat-cell *matCellDef=\"let element\" style=\"text-align: center;\">\n <ng-container *ngIf=\"element.options.encrypted; else NO\">YES</ng-container>\n <ng-template #NO><span style=\"color:gray\">NO</span></ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"expires\">\n <th mat-header-cell *matHeaderCellDef style=\"text-align: center;\"> Expires </th>\n <td mat-cell *matCellDef=\"let element\" style=\"text-align: center;\">\n <ng-container *ngIf=\"element.options.expires !== 0; else NO_DATA\">\n {{expiresIn(element.options.expires)}}\n </ng-container>\n <ng-template #NO_DATA>\n \u221E\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"option\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let element\" style=\"padding-right: 0;\">\n <div style=\"display: flex;justify-content: flex-end;\">\n <button mat-icon-button color=\"warn\" (click)=\"onDelete(element); $event.stopPropagation()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\" (click)=\"onSelectedRow(row)\"></tr>\n </table>\n </ng-container>\n\n <ng-template #NO_DATA>\n <h3 style=\"margin-top: 1rem;\">No Data</h3>\n </ng-template>\n\n <div *ngIf=\"(data$ | async) as data\" style=\"margin-top: 2rem;\">\n <div style=\"margin-bottom: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <h3>STORE: <span style=\"font-weight: bold;\">{{ store.name | uppercase }}</span></h3>\n <h3>SETTINGS: {{ setting$(store.name) | async | json }}</h3>\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex: 1;\">\n <mat-label>Data (Must be an Object or Array of any)</mat-label>\n <textarea matInput placeholder=\"[]\" #json [value]=\"data\"></textarea>\n </mat-form-field>\n </div>\n <mat-error *ngIf=\"!isValidJSON(json.value)\">Not Valid Data</mat-error>\n\n <div style=\"display: flex; gap: .5rem;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onCancel()\">Cancel</button>\n <button mat-stroked-button (click)=\"onUpdate(store, json.value)\" [disabled]=\"!(isValidJSON(json.value))\">Update</button>\n </div>\n </div>\n </div>\n\n </ng-template>\n\n <div style=\"margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <button mat-stroked-button (click)=\"onReset()\">Delete All Stores</button>\n </div>\n\n</div>\n\n\n<mat-menu #menu=\"matMenu\">\n <div style=\"padding: 1rem;\">\n <p>Please note that the LocalStorage (encryption) and management of data is dependant on initializing the APP_ID</p>\n <p>Must provide a value for <b>APP_ID</b> in AppModule->Providers</p>\n <mat-divider></mat-divider>\n <div style=\"font-size: smaller; margin-top: .5rem;\">\n <p>Example: UUID (self.crypto.randomUUID() to generate)</p>\n <div style=\"background-color: whitesmoke; padding: 1rem;\">\n {<br>\n provide: APP_ID,<br>\n useValue: \"056991ac-3537-43ab-b5b9-83edf6554eff\",<br>\n }\n </div>\n </div>\n </div>\n</mat-menu>\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.demo-row-is-clicked{font-weight:700}.mat-mdc-menu-panel.mat-mdc-menu-panel{max-width:280px!important}\n"] }]
|
|
2310
|
+
}], ctorParameters: function () { return [{ type: ConfigOptions, decorators: [{
|
|
2311
|
+
type: Inject,
|
|
2312
|
+
args: [CONFIG_SETTINGS_TOKEN]
|
|
2313
|
+
}] }]; } });
|
|
2314
|
+
|
|
2315
|
+
class ClientInfo {
|
|
2316
|
+
constructor(domain = '', service = '', id = 0, name = '') {
|
|
2317
|
+
this.domain = domain;
|
|
2318
|
+
this.service = service;
|
|
2319
|
+
this.id = id;
|
|
2320
|
+
this.name = name;
|
|
2321
|
+
}
|
|
2322
|
+
static adapt(item) {
|
|
2323
|
+
return new ClientInfo(item?.domain, item?.service, item?.id, item?.name);
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
class ClientInfoMapper {
|
|
2328
|
+
constructor(id = 0, name = '') {
|
|
2329
|
+
this.id = id;
|
|
2330
|
+
this.name = name;
|
|
2331
|
+
}
|
|
2332
|
+
static adapt(item) {
|
|
2333
|
+
return new ClientInfoMapper(item?.id, item?.name);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
class AIPrompt {
|
|
2338
|
+
constructor(response = '') {
|
|
2339
|
+
this.response = response;
|
|
2340
|
+
}
|
|
2341
|
+
static adapt(item) {
|
|
2342
|
+
return new AIPrompt(item?.response);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
class RequestManagerDemoComponent {
|
|
2347
|
+
get retry() {
|
|
2348
|
+
return this.requestForm.get('retry')?.value;
|
|
2349
|
+
}
|
|
2350
|
+
get headers() {
|
|
2351
|
+
return this.requestForm.get('headers');
|
|
2352
|
+
}
|
|
2353
|
+
get isValid() {
|
|
2354
|
+
this.requestForm.markAllAsTouched();
|
|
2355
|
+
return this.requestForm.valid;
|
|
2356
|
+
}
|
|
2357
|
+
constructor() {
|
|
2358
|
+
this.displayedColumns = ['id', 'name', 'lastName', 'age'];
|
|
2359
|
+
this.fb = inject(FormBuilder);
|
|
2360
|
+
this.toastMessage = inject(ToastMessageService);
|
|
2361
|
+
this.httpManagerService = inject(HTTPManagerService);
|
|
2362
|
+
this.isPending$ = this.httpManagerService.isPending$;
|
|
2363
|
+
this.countdown$ = this.httpManagerService.countdown$;
|
|
2364
|
+
this.GET_error$ = new BehaviorSubject('');
|
|
2365
|
+
this.POST_error$ = new BehaviorSubject('');
|
|
2366
|
+
this.PUT_error$ = new BehaviorSubject('');
|
|
2367
|
+
this.DELETE_error$ = new BehaviorSubject('');
|
|
2368
|
+
this.STREAM_error$ = new BehaviorSubject('');
|
|
2369
|
+
this.STREAM_AI_error$ = new BehaviorSubject('');
|
|
2370
|
+
this.requestParams = {
|
|
2371
|
+
GET: ApiRequest.adapt(),
|
|
2372
|
+
POST: ApiRequest.adapt(),
|
|
2373
|
+
PUT: ApiRequest.adapt(),
|
|
2374
|
+
DELETE: ApiRequest.adapt(),
|
|
2375
|
+
STREAM: ApiRequest.adapt(),
|
|
2376
|
+
};
|
|
2377
|
+
this.questionControl = this.fb.control("", [Validators.required]);
|
|
2378
|
+
this.downloadRequest = ApiRequest.adapt({
|
|
2379
|
+
server: 'http://localhost:4200/assets',
|
|
2380
|
+
path: ['icons1.svg']
|
|
2381
|
+
});
|
|
2382
|
+
this.sampleClientData = {
|
|
2383
|
+
id: 0,
|
|
2384
|
+
name: "Old School Dates",
|
|
2385
|
+
domain: "osd.com",
|
|
2386
|
+
service: "osd",
|
|
2387
|
+
spiffe: "osd.com/osd",
|
|
2388
|
+
secret: "SMOPECXP-OS4P-USOG-X2II-3XMD1FQDR3IJX",
|
|
2389
|
+
created: 1693003138,
|
|
2390
|
+
modified: 1693003138,
|
|
2391
|
+
icon: "",
|
|
2392
|
+
imageFile: "",
|
|
2393
|
+
};
|
|
2394
|
+
this.requestForm = this.fb.group({
|
|
2395
|
+
path: this.fb.control(""),
|
|
2396
|
+
headers: this.fb.array([]),
|
|
2397
|
+
adapter: [null],
|
|
2398
|
+
retry: this.fb.group({
|
|
2399
|
+
times: [3],
|
|
2400
|
+
delay: [3],
|
|
2401
|
+
}),
|
|
2402
|
+
polling: [3],
|
|
2403
|
+
});
|
|
2404
|
+
this.sampleAdaptors = [
|
|
2405
|
+
{ label: "ClientInfo Basic", value: ClientInfo.adapt },
|
|
2406
|
+
{ label: "AI Prompt", value: AIPrompt.adapt },
|
|
2407
|
+
];
|
|
2408
|
+
this.sampleMappers = [
|
|
2409
|
+
{ label: "Mapper Basic", value: ClientInfoMapper.adapt },
|
|
2410
|
+
{ label: "AI Prompt", value: AIPrompt.adapt },
|
|
2411
|
+
];
|
|
2412
|
+
// server = `http://sample-endpoint/as/authorization.oauth2`
|
|
2413
|
+
this.arrayObjectsToObjects = (arr) => {
|
|
2414
|
+
return Array.isArray(arr) ? arr.reduce((obj, item) => Object.assign(obj, { [item.key]: item.value }), {}) : {};
|
|
2415
|
+
};
|
|
2416
|
+
}
|
|
2417
|
+
ngOnInit() {
|
|
2418
|
+
// const reqGet2 = ApiRequest.adapt({
|
|
2419
|
+
// server,
|
|
2420
|
+
// path: ['clients'],
|
|
2421
|
+
// headers: { authentication: "Bearer <KEY>" },
|
|
2422
|
+
// adapter: ClientInfo,
|
|
2423
|
+
// dataType: DataType.OBJECT,
|
|
2424
|
+
// // concurrent: false,
|
|
2425
|
+
// // polling: 3, //seconds
|
|
2426
|
+
// });
|
|
2427
|
+
// const req2 = [1024,1025,1026].map(item => {
|
|
2428
|
+
// return this.httpManagerService.getRequest<ClientInfo[]>(reqGet2, [item])
|
|
2429
|
+
// .pipe(
|
|
2430
|
+
// catchError(error => {
|
|
2431
|
+
// return throwError(() => new Error(error.error.message));
|
|
2432
|
+
// })
|
|
2433
|
+
// )
|
|
2434
|
+
// })
|
|
2435
|
+
// forkJoin(req2)
|
|
2436
|
+
// .subscribe(res => console.log(res))
|
|
2437
|
+
}
|
|
2438
|
+
addHeader() {
|
|
2439
|
+
const header = this.fb.group({
|
|
2440
|
+
key: ['', Validators.required],
|
|
2441
|
+
value: ['']
|
|
2442
|
+
});
|
|
2443
|
+
this.headers.push(header);
|
|
2444
|
+
}
|
|
2445
|
+
removeHeader(index) {
|
|
2446
|
+
this.headers.removeAt(index);
|
|
2447
|
+
}
|
|
2448
|
+
compileRequest() {
|
|
2449
|
+
const requestParams = this.requestForm.value;
|
|
2450
|
+
requestParams.headers = this.arrayObjectsToObjects(requestParams.headers || []);
|
|
2451
|
+
const pathReq = (requestParams.path === "") ? [] : (requestParams.path || "").split("/");
|
|
2452
|
+
if (!this.pollingState.checked)
|
|
2453
|
+
requestParams.polling = 0;
|
|
2454
|
+
if (!this.failedState.checked) {
|
|
2455
|
+
requestParams.retry = { times: 0, delay: 0 };
|
|
2456
|
+
}
|
|
2457
|
+
return ApiRequest.adapt({
|
|
2458
|
+
...requestParams,
|
|
2459
|
+
// ...{ path: pathReq, server: this.server },
|
|
2460
|
+
...{ path: pathReq },
|
|
2461
|
+
});
|
|
2462
|
+
}
|
|
2463
|
+
onGetRequest() {
|
|
2464
|
+
if (!this.isValid)
|
|
2465
|
+
return;
|
|
2466
|
+
const reqParams = this.compileRequest();
|
|
2467
|
+
this.requestParams.GET = reqParams;
|
|
2468
|
+
this.GET$ = EMPTY; //Cancels Previous
|
|
2469
|
+
this.GET_error$.next('');
|
|
2470
|
+
this.GET$ = this.httpManagerService.getRequest(reqParams)
|
|
2471
|
+
.pipe(
|
|
2472
|
+
// tap((data) => console.log("API GET response", data)),
|
|
2473
|
+
catchError(error => {
|
|
2474
|
+
return throwError(() => this.errorHandling(error, 'GET'));
|
|
2475
|
+
}));
|
|
2476
|
+
}
|
|
2477
|
+
onCreateRequest() {
|
|
2478
|
+
if (!this.isValid)
|
|
2479
|
+
return;
|
|
2480
|
+
const reqParams = this.compileRequest();
|
|
2481
|
+
this.requestParams.POST = reqParams;
|
|
2482
|
+
this.POST$ = EMPTY; //Cancels Previous
|
|
2483
|
+
this.POST_error$.next('');
|
|
2484
|
+
this.POST$ = this.httpManagerService.postRequest(this.sampleClientData, reqParams)
|
|
2485
|
+
.pipe(
|
|
2486
|
+
// tap((data) => console.log("API POST response", data)),
|
|
2487
|
+
catchError(error => {
|
|
2488
|
+
return throwError(() => this.errorHandling(error, 'POST'));
|
|
2489
|
+
}));
|
|
2490
|
+
}
|
|
2491
|
+
onUpdateRequest() {
|
|
2492
|
+
if (!this.isValid)
|
|
2493
|
+
return;
|
|
2494
|
+
const reqParams = this.compileRequest();
|
|
2495
|
+
this.sampleClientData.id = reqParams.path[reqParams.path.length - 1];
|
|
2496
|
+
this.requestParams.PUT = reqParams;
|
|
2497
|
+
this.PUT$ = EMPTY; //Cancels Previous
|
|
2498
|
+
this.PUT_error$.next('');
|
|
2499
|
+
this.PUT$ = this.httpManagerService.putRequest(this.sampleClientData, reqParams)
|
|
2500
|
+
.pipe(
|
|
2501
|
+
// tap((data) => console.log("API PUT response", data)),
|
|
2502
|
+
catchError(error => {
|
|
2503
|
+
return throwError(() => this.errorHandling(error, 'PUT'));
|
|
2504
|
+
}));
|
|
2505
|
+
}
|
|
2506
|
+
onDeleteRequest() {
|
|
2507
|
+
if (!this.isValid)
|
|
2508
|
+
return;
|
|
2509
|
+
const reqParams = this.compileRequest();
|
|
2510
|
+
this.requestParams.DELETE = reqParams;
|
|
2511
|
+
this.DELETE$ = EMPTY; //Cancels Previous
|
|
2512
|
+
this.DELETE_error$.next('');
|
|
2513
|
+
this.DELETE$ = this.httpManagerService.deleteRequest(reqParams)
|
|
2514
|
+
.pipe(
|
|
2515
|
+
// tap((data) => console.log("API DELETE response", data)),
|
|
2516
|
+
catchError(error => {
|
|
2517
|
+
return throwError(() => this.errorHandling(error, 'DELETE'));
|
|
2518
|
+
}));
|
|
2519
|
+
}
|
|
2520
|
+
onStreamPostRequest() {
|
|
2521
|
+
if (!this.isValid)
|
|
2522
|
+
return;
|
|
2523
|
+
const reqParams = this.compileRequest();
|
|
2524
|
+
reqParams.server = "http://localhost:11434/api";
|
|
2525
|
+
reqParams.path = ["generate"];
|
|
2526
|
+
reqParams.stream = true;
|
|
2527
|
+
const payload = {
|
|
2528
|
+
model: "mistral",
|
|
2529
|
+
prompt: this.questionControl.value,
|
|
2530
|
+
stream: reqParams.stream
|
|
2531
|
+
};
|
|
2532
|
+
this.requestParams.STREAM = reqParams;
|
|
2533
|
+
this.STREAM_AI$ = EMPTY;
|
|
2534
|
+
this.STREAM_AI_error$.next('');
|
|
2535
|
+
this.STREAM_AI$ = this.httpManagerService.postRequest(payload, reqParams)
|
|
2536
|
+
.pipe(map(items => items.map((word) => word.response).flat().join('')), tap(() => this.questionControl.reset()), catchError(error => {
|
|
2537
|
+
return throwError(() => this.errorHandling(error, 'STREAM'));
|
|
2538
|
+
}));
|
|
2539
|
+
}
|
|
2540
|
+
onStreamRequest() {
|
|
2541
|
+
if (!this.isValid)
|
|
2542
|
+
return;
|
|
2543
|
+
const reqParams = this.compileRequest();
|
|
2544
|
+
reqParams.server = "oidc";
|
|
2545
|
+
reqParams.stream = true;
|
|
2546
|
+
this.STREAM$ = this.httpManagerService.getRequest(reqParams)
|
|
2547
|
+
.pipe(
|
|
2548
|
+
// tap((data) => console.log("API STREAM response", data)),
|
|
2549
|
+
catchError(error => {
|
|
2550
|
+
return throwError(() => this.errorHandling(error, 'STREAM'));
|
|
2551
|
+
}));
|
|
2552
|
+
}
|
|
2553
|
+
onDownloadCompleted() {
|
|
2554
|
+
const message = "Download Completed";
|
|
2555
|
+
const display = ToastDisplay.adapt({
|
|
2556
|
+
message,
|
|
2557
|
+
action: 'Ok',
|
|
2558
|
+
color: ToastColors.SUCCESS,
|
|
2559
|
+
icon: 'sentiment_satisfied_alt',
|
|
2560
|
+
});
|
|
2561
|
+
this.toastMessage.toastMessage(display);
|
|
2562
|
+
}
|
|
2563
|
+
onDownloadFailed(err) {
|
|
2564
|
+
const message = "Download Failed";
|
|
2565
|
+
const display = ToastDisplay.adapt({
|
|
2566
|
+
message,
|
|
2567
|
+
action: 'Ok',
|
|
2568
|
+
color: ToastColors.ERROR,
|
|
2569
|
+
icon: 'warning',
|
|
2570
|
+
});
|
|
2571
|
+
this.toastMessage.toastMessage(display);
|
|
2572
|
+
}
|
|
2573
|
+
errorHandling(err, type) {
|
|
2574
|
+
if (type === 'GET')
|
|
2575
|
+
this.GET_error$.next(err.message);
|
|
2576
|
+
if (type === 'POST')
|
|
2577
|
+
this.POST_error$.next(err.message);
|
|
2578
|
+
if (type === 'PUT')
|
|
2579
|
+
this.PUT_error$.next(err.message);
|
|
2580
|
+
if (type === 'DELETE')
|
|
2581
|
+
this.DELETE_error$.next(err.message);
|
|
2582
|
+
if (type === 'STREAM')
|
|
2583
|
+
this.STREAM_error$.next(err.message);
|
|
2584
|
+
}
|
|
2585
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RequestManagerDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2586
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RequestManagerDemoComponent, selector: "app-request-manager-demo", viewQueries: [{ propertyName: "failedState", first: true, predicate: ["failedState"], descendants: true, static: true }, { propertyName: "pollingState", first: true, predicate: ["pollingState"], descendants: true, static: true }], ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2>\n HTTP Request Manager\n </h2>\n\n <div [formGroup]=\"requestForm\" style=\"margin-top: 2rem;\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Adapter (Model)</mat-label>\n <mat-select formControlName=\"adapter\">\n <mat-option>None</mat-option>\n <mat-option *ngFor=\"let adapter of sampleAdaptors\" [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Mapper (Model)</mat-label>\n <mat-select formControlName=\"adapter\">\n <mat-option>None</mat-option>\n <mat-option *ngFor=\"let mapper of sampleMappers\" [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>RestPath (/ delimited)</mat-label>\n <input matInput placeholder=\"clients/list\" formControlName=\"path\">\n </mat-form-field>\n </div>\n <div>\n <div formArrayName=\"headers\">\n <div *ngFor=\"let task of headers.controls; let i = index\" [formGroupName]=\"i\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"authentication\" formControlName=\"key\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Value</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"value\">\n </mat-form-field>\n <div style=\"margin-top: .5rem;\">\n <button mat-icon-button (click)=\"removeHeader(i)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n <button mat-stroked-button (click)=\"addHeader()\" class=\"btn\">Add Header</button>\n </div>\n <div style=\"margin-top: 2rem; display: flex; flex-direction:column; gap: 1rem;\">\n <div>\n <mat-slide-toggle #failedState>Retry on Failed</mat-slide-toggle>\n <div *ngIf=\"failedState.checked\" style=\"display: flex; gap: .5rem; margin-top: 1rem;\" formGroupName=\"retry\">\n <mat-form-field appearance=\"outline\">\n <mat-label>#of Times</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"times\" value=\"3\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Delay Until Next</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"delay\" value=\"3\">\n </mat-form-field>\n </div>\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n <div *ngIf=\"pollingState.checked\">\n <mat-form-field appearance=\"outline\" style=\"margin-top: 1rem\">\n <mat-label>#of Seconds</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"polling\" value=\"3\">\n </mat-form-field>\n </div>\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n <mat-progress-bar mode=\"indeterminate\"\n *ngIf=\"(isPending$ | async)\"\n ></mat-progress-bar>\n <mat-progress-bar mode=\"determinate\"\n *ngIf=\"pollingState.checked && !(isPending$ | async)\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n </div>\n\n <div style=\"margin-top: 1rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">GET Request</h2>\n <div>\n <button mat-raised-button (click)=\"onGetRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(GET_error$ | async) as get_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\" *ngIf=\"(GET$ | async) as dataRecord\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onCreateRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(POST_error$ | async) as post_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\" *ngIf=\"(POST$ | async) as dataRecord\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">PUT Request</h2>\n <div>\n <button mat-raised-button (click)=\"onUpdateRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(PUT_error$ | async) as put_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\" *ngIf=\"(PUT$ | async) as dataRecord\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">DELETE Request</h2>\n <div>\n <button mat-raised-button (click)=\"onDeleteRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(DELETE_error$ | async) as delete_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\" *ngIf=\"(DELETE$ | async) as dataRecord\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">Streaming GET Request</h2>\n <div>\n <button mat-raised-button (click)=\"onStreamRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(STREAM_error$ | async) as stream_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <div *ngIf=\"(STREAM$ | async) as data\" class=\"container\">\n <table mat-table [dataSource]=\"data\">\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> First Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.name}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef> Last Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.lastName}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"age\">\n <th mat-header-cell *matHeaderCellDef> Age </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.age}} </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">STREAMING POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" class=\"btn\">Ask Me</button>\n </div>\n </div>\n\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Ask me a Question</mat-label>\n <textarea matInput placeholder=\"Why is the sky blue?\" [formControl]=\"questionControl\"></textarea>\n </mat-form-field>\n </div>\n\n <div *ngIf=\"(STREAM_AI_error$ | async) as stream_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <div *ngIf=\"(STREAM_AI$ | async) as data\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap;\">{{data}}</p>\n </div>\n </div>\n\n </div>\n\n <div>\n <div style=\"display: flex;\">\n <h2 style=\"flex:1; margin-bottom: 0; padding-top: .5rem; display: flex;\">\n <div>\n Download File\n </div>\n <div style=\"flex:1; margin-left: 1rem;\">\n <mat-slide-toggle #disable>\n <span *ngIf=\"disable.checked; else DISABLE\">\n Enable\n </span>\n <ng-template #DISABLE>Disable</ng-template>\n </mat-slide-toggle>\n </div>\n </h2>\n <div>\n <app-file-downloader\n [disabled]=\"disable.checked\"\n [delayError]=\"3\"\n [apiRequest]=\"downloadRequest\"\n (completed)=\"onDownloadCompleted()\"\n (failed)=\"onDownloadFailed($event)\"\n ></app-file-downloader>\n </div>\n </div>\n </div>\n\n</div>\n", styles: [".btn{min-width:120px}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor;background-color:#f5f5f5}.container{height:400px;overflow:auto}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "panelWidth", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i9.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i10$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: FileDownloaderComponent, selector: "app-file-downloader", inputs: ["delayError", "apiRequest", "displayErrorMessage", "labels", "disabled"], outputs: ["completed", "failed"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
|
|
2587
|
+
}
|
|
2588
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RequestManagerDemoComponent, decorators: [{
|
|
2589
|
+
type: Component,
|
|
2590
|
+
args: [{ selector: 'app-request-manager-demo', template: "<div style=\"margin: 2rem;\">\n\n <h2>\n HTTP Request Manager\n </h2>\n\n <div [formGroup]=\"requestForm\" style=\"margin-top: 2rem;\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Adapter (Model)</mat-label>\n <mat-select formControlName=\"adapter\">\n <mat-option>None</mat-option>\n <mat-option *ngFor=\"let adapter of sampleAdaptors\" [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Mapper (Model)</mat-label>\n <mat-select formControlName=\"adapter\">\n <mat-option>None</mat-option>\n <mat-option *ngFor=\"let mapper of sampleMappers\" [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>RestPath (/ delimited)</mat-label>\n <input matInput placeholder=\"clients/list\" formControlName=\"path\">\n </mat-form-field>\n </div>\n <div>\n <div formArrayName=\"headers\">\n <div *ngFor=\"let task of headers.controls; let i = index\" [formGroupName]=\"i\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"authentication\" formControlName=\"key\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Value</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"value\">\n </mat-form-field>\n <div style=\"margin-top: .5rem;\">\n <button mat-icon-button (click)=\"removeHeader(i)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n <button mat-stroked-button (click)=\"addHeader()\" class=\"btn\">Add Header</button>\n </div>\n <div style=\"margin-top: 2rem; display: flex; flex-direction:column; gap: 1rem;\">\n <div>\n <mat-slide-toggle #failedState>Retry on Failed</mat-slide-toggle>\n <div *ngIf=\"failedState.checked\" style=\"display: flex; gap: .5rem; margin-top: 1rem;\" formGroupName=\"retry\">\n <mat-form-field appearance=\"outline\">\n <mat-label>#of Times</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"times\" value=\"3\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Delay Until Next</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"delay\" value=\"3\">\n </mat-form-field>\n </div>\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n <div *ngIf=\"pollingState.checked\">\n <mat-form-field appearance=\"outline\" style=\"margin-top: 1rem\">\n <mat-label>#of Seconds</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"polling\" value=\"3\">\n </mat-form-field>\n </div>\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n <mat-progress-bar mode=\"indeterminate\"\n *ngIf=\"(isPending$ | async)\"\n ></mat-progress-bar>\n <mat-progress-bar mode=\"determinate\"\n *ngIf=\"pollingState.checked && !(isPending$ | async)\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n </div>\n\n <div style=\"margin-top: 1rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">GET Request</h2>\n <div>\n <button mat-raised-button (click)=\"onGetRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(GET_error$ | async) as get_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\" *ngIf=\"(GET$ | async) as dataRecord\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onCreateRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(POST_error$ | async) as post_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\" *ngIf=\"(POST$ | async) as dataRecord\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">PUT Request</h2>\n <div>\n <button mat-raised-button (click)=\"onUpdateRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(PUT_error$ | async) as put_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\" *ngIf=\"(PUT$ | async) as dataRecord\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">DELETE Request</h2>\n <div>\n <button mat-raised-button (click)=\"onDeleteRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(DELETE_error$ | async) as delete_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\" *ngIf=\"(DELETE$ | async) as dataRecord\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">Streaming GET Request</h2>\n <div>\n <button mat-raised-button (click)=\"onStreamRequest()\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(STREAM_error$ | async) as stream_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <div *ngIf=\"(STREAM$ | async) as data\" class=\"container\">\n <table mat-table [dataSource]=\"data\">\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> First Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.name}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef> Last Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.lastName}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"age\">\n <th mat-header-cell *matHeaderCellDef> Age </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.age}} </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">STREAMING POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" class=\"btn\">Ask Me</button>\n </div>\n </div>\n\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Ask me a Question</mat-label>\n <textarea matInput placeholder=\"Why is the sky blue?\" [formControl]=\"questionControl\"></textarea>\n </mat-form-field>\n </div>\n\n <div *ngIf=\"(STREAM_AI_error$ | async) as stream_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <div *ngIf=\"(STREAM_AI$ | async) as data\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap;\">{{data}}</p>\n </div>\n </div>\n\n </div>\n\n <div>\n <div style=\"display: flex;\">\n <h2 style=\"flex:1; margin-bottom: 0; padding-top: .5rem; display: flex;\">\n <div>\n Download File\n </div>\n <div style=\"flex:1; margin-left: 1rem;\">\n <mat-slide-toggle #disable>\n <span *ngIf=\"disable.checked; else DISABLE\">\n Enable\n </span>\n <ng-template #DISABLE>Disable</ng-template>\n </mat-slide-toggle>\n </div>\n </h2>\n <div>\n <app-file-downloader\n [disabled]=\"disable.checked\"\n [delayError]=\"3\"\n [apiRequest]=\"downloadRequest\"\n (completed)=\"onDownloadCompleted()\"\n (failed)=\"onDownloadFailed($event)\"\n ></app-file-downloader>\n </div>\n </div>\n </div>\n\n</div>\n", styles: [".btn{min-width:120px}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor;background-color:#f5f5f5}.container{height:400px;overflow:auto}\n"] }]
|
|
2591
|
+
}], ctorParameters: function () { return []; }, propDecorators: { failedState: [{
|
|
2592
|
+
type: ViewChild,
|
|
2593
|
+
args: ["failedState", { static: true }]
|
|
2594
|
+
}], pollingState: [{
|
|
2595
|
+
type: ViewChild,
|
|
2596
|
+
args: ["pollingState", { static: true }]
|
|
2597
|
+
}] } });
|
|
2598
|
+
|
|
2599
|
+
class StateManagerDemoService extends HTTPManagerStateService {
|
|
2600
|
+
constructor() {
|
|
2601
|
+
super(ApiRequest.adapt({
|
|
2602
|
+
server: "",
|
|
2603
|
+
path: [],
|
|
2604
|
+
headers: {},
|
|
2605
|
+
adapter: ClientInfo.adapt,
|
|
2606
|
+
mapper: ClientInfoMapper.adapt,
|
|
2607
|
+
stream: false,
|
|
2608
|
+
}), DataType.ARRAY, DatabaseStorage.adapt());
|
|
2609
|
+
}
|
|
2610
|
+
setAPIOptions(apiOptions, dataType, database) {
|
|
2611
|
+
this.setApiRequestOptions(apiOptions, dataType, database);
|
|
2612
|
+
}
|
|
2613
|
+
getClients() {
|
|
2614
|
+
// const headers = {
|
|
2615
|
+
// auth: "sample-auth-token"
|
|
2616
|
+
// }
|
|
2617
|
+
// const sampleOptions = RequestOptions.adapt({ path: ["id", 12], headers, sample: true })
|
|
2618
|
+
this.fetchRecords();
|
|
2619
|
+
}
|
|
2620
|
+
createClient(data) {
|
|
2621
|
+
// const headers = {
|
|
2622
|
+
// auth: "sample-auth-token"
|
|
2623
|
+
// }
|
|
2624
|
+
// const sampleOptions = RequestOptions.adapt({ path: ["id", 12], headers, sample: true })
|
|
2625
|
+
this.createRecord(data);
|
|
2626
|
+
}
|
|
2627
|
+
updateClient(data) {
|
|
2628
|
+
// const headers = {
|
|
2629
|
+
// auth: "sample-auth-token"
|
|
2630
|
+
// }
|
|
2631
|
+
data.id = 1031;
|
|
2632
|
+
const sampleOptions = RequestOptions.adapt({ path: [data.id] });
|
|
2633
|
+
this.updateRecord(data, sampleOptions);
|
|
2634
|
+
}
|
|
2635
|
+
deleteClient(data) {
|
|
2636
|
+
// const headers = {
|
|
2637
|
+
// auth: "sample-auth-token"
|
|
2638
|
+
// }
|
|
2639
|
+
data.id = 1031;
|
|
2640
|
+
const sampleOptions = RequestOptions.adapt({ path: [data.id] });
|
|
2641
|
+
this.deleteRecord(sampleOptions);
|
|
2642
|
+
}
|
|
2643
|
+
streamRequest() {
|
|
2644
|
+
const headers = {
|
|
2645
|
+
auth: "sample-auth-token"
|
|
2646
|
+
};
|
|
2647
|
+
// const sampleOptions = RequestOptions.adapt({ path: [1], headers })
|
|
2648
|
+
this.fetchStream();
|
|
2649
|
+
}
|
|
2650
|
+
streamAIRequest(data) {
|
|
2651
|
+
const headers = {
|
|
2652
|
+
auth: "sample-auth-token"
|
|
2653
|
+
};
|
|
2654
|
+
const sampleOptions = RequestOptions.adapt({ path: [data.id] });
|
|
2655
|
+
this.createStream(data, sampleOptions);
|
|
2656
|
+
// this.fetchStream(sampleOptions)
|
|
2657
|
+
}
|
|
2658
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: StateManagerDemoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2659
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: StateManagerDemoService, providedIn: 'root' }); }
|
|
2660
|
+
}
|
|
2661
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: StateManagerDemoService, decorators: [{
|
|
2662
|
+
type: Injectable,
|
|
2663
|
+
args: [{
|
|
2664
|
+
providedIn: 'root'
|
|
2665
|
+
}]
|
|
2666
|
+
}], ctorParameters: function () { return []; } });
|
|
2667
|
+
|
|
2668
|
+
class RequestManagerStateDemoComponent {
|
|
2669
|
+
get dataObservable$() {
|
|
2670
|
+
switch (this.requestType) {
|
|
2671
|
+
case 'GET':
|
|
2672
|
+
return this.GET$;
|
|
2673
|
+
case 'PUT':
|
|
2674
|
+
return this.PUT$;
|
|
2675
|
+
case 'POST':
|
|
2676
|
+
return this.POST$;
|
|
2677
|
+
case 'DELETE':
|
|
2678
|
+
return this.DELETE$;
|
|
2679
|
+
case 'STREAM':
|
|
2680
|
+
return this.STREAM;
|
|
2681
|
+
case 'STREAM_AI':
|
|
2682
|
+
return this.STREAM_AI;
|
|
2683
|
+
default:
|
|
2684
|
+
return this.GET$;
|
|
2685
|
+
break;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
get hasChanged() {
|
|
2689
|
+
return this.requestForm.dirty;
|
|
2690
|
+
}
|
|
2691
|
+
get dataType() {
|
|
2692
|
+
return this.requestForm.get("datatype")?.value;
|
|
2693
|
+
}
|
|
2694
|
+
get database() {
|
|
2695
|
+
return this.requestForm.get("database")?.value;
|
|
2696
|
+
}
|
|
2697
|
+
get retry() {
|
|
2698
|
+
return this.requestForm.get("retry")?.value;
|
|
2699
|
+
}
|
|
2700
|
+
get headers() {
|
|
2701
|
+
return this.requestForm.get('headers');
|
|
2702
|
+
}
|
|
2703
|
+
get isValid() {
|
|
2704
|
+
this.requestForm.markAllAsTouched();
|
|
2705
|
+
return this.requestForm.valid;
|
|
2706
|
+
}
|
|
2707
|
+
constructor() {
|
|
2708
|
+
this.stateManagerDemoService = inject(StateManagerDemoService);
|
|
2709
|
+
this.displayedColumns = ['id', 'name', 'lastName', 'age'];
|
|
2710
|
+
this.fb = inject(FormBuilder);
|
|
2711
|
+
this.httpManagerService = inject(HTTPManagerService);
|
|
2712
|
+
this.isPending$ = this.stateManagerDemoService.isPending$;
|
|
2713
|
+
this.error$ = this.stateManagerDemoService.error$;
|
|
2714
|
+
this.countdown$ = this.httpManagerService.countdown$;
|
|
2715
|
+
this.GET_error$ = new BehaviorSubject('');
|
|
2716
|
+
this.POST_error$ = new BehaviorSubject('');
|
|
2717
|
+
this.PUT_error$ = new BehaviorSubject('');
|
|
2718
|
+
this.DELETE_error$ = new BehaviorSubject('');
|
|
2719
|
+
this.STREAM_error$ = new BehaviorSubject('');
|
|
2720
|
+
this.GET$ = new BehaviorSubject(null);
|
|
2721
|
+
this.POST$ = new BehaviorSubject(null);
|
|
2722
|
+
this.PUT$ = new BehaviorSubject(null);
|
|
2723
|
+
this.DELETE$ = new BehaviorSubject(null);
|
|
2724
|
+
this.STREAM = new BehaviorSubject(null);
|
|
2725
|
+
this.STREAM$ = this.STREAM.asObservable();
|
|
2726
|
+
this.STREAM_AI = new BehaviorSubject(null);
|
|
2727
|
+
this.STREAM_AI$ = this.STREAM_AI.asObservable()
|
|
2728
|
+
.pipe(map((items) => (items) ? items.map((item) => item.response) : []), map((items) => items.join('').trim()));
|
|
2729
|
+
this.questionControl = this.fb.control("", [Validators.required]);
|
|
2730
|
+
this.requestType = '';
|
|
2731
|
+
this.sampleClientData = {
|
|
2732
|
+
id: 0,
|
|
2733
|
+
name: "Old School Dates",
|
|
2734
|
+
domain: "osd.com",
|
|
2735
|
+
service: "osd",
|
|
2736
|
+
spiffe: "osd.com/osd",
|
|
2737
|
+
secret: "SMOPECXP-OS4P-USOG-X2II-3XMD1FQDR3IJX",
|
|
2738
|
+
created: 1693003138,
|
|
2739
|
+
modified: 1693003138,
|
|
2740
|
+
icon: "",
|
|
2741
|
+
imageFile: "",
|
|
2742
|
+
};
|
|
2743
|
+
this.selectedRecord = this.fb.control(null);
|
|
2744
|
+
this.requestForm = this.fb.group({
|
|
2745
|
+
datatype: this.fb.control('ARRAY'),
|
|
2746
|
+
path: this.fb.control(""),
|
|
2747
|
+
headers: this.fb.array([]),
|
|
2748
|
+
adapter: [null],
|
|
2749
|
+
mapper: [null],
|
|
2750
|
+
retry: this.fb.group({
|
|
2751
|
+
times: [3],
|
|
2752
|
+
delay: [3],
|
|
2753
|
+
}),
|
|
2754
|
+
polling: [3],
|
|
2755
|
+
database: this.fb.group({
|
|
2756
|
+
table: [''],
|
|
2757
|
+
expiresIn: ['1m'],
|
|
2758
|
+
})
|
|
2759
|
+
});
|
|
2760
|
+
this.sampleAdaptors = [
|
|
2761
|
+
{ label: "ClientInfo Basic", value: ClientInfo.adapt },
|
|
2762
|
+
{ label: "AI Prompt", value: AIPrompt.adapt },
|
|
2763
|
+
];
|
|
2764
|
+
this.sampleMappers = [
|
|
2765
|
+
{ label: "Mapper Basic", value: ClientInfoMapper.adapt },
|
|
2766
|
+
{ label: "AI Prompt", value: AIPrompt.adapt },
|
|
2767
|
+
];
|
|
2768
|
+
// server = `http://sample-endpoint/as/authorization.oauth2`
|
|
2769
|
+
this.arrayObjectsToObjects = (arr) => {
|
|
2770
|
+
return Array.isArray(arr) ? arr.reduce((obj, item) => Object.assign(obj, { [item.key]: item.value }), {}) : {};
|
|
2771
|
+
};
|
|
2772
|
+
}
|
|
2773
|
+
ngOnInit() {
|
|
2774
|
+
this.selectedRecord.valueChanges
|
|
2775
|
+
.subscribe((data) => {
|
|
2776
|
+
this.selectedRecord$ = (data) ? this.stateManagerDemoService.selectRecord$(data.id) : EMPTY;
|
|
2777
|
+
});
|
|
2778
|
+
this.stateManagerDemoService.data$
|
|
2779
|
+
.pipe(tap((data) => {
|
|
2780
|
+
switch (this.requestType) {
|
|
2781
|
+
case 'GET':
|
|
2782
|
+
this.GET$.next(data);
|
|
2783
|
+
break;
|
|
2784
|
+
case 'PUT':
|
|
2785
|
+
this.PUT$.next(data);
|
|
2786
|
+
break;
|
|
2787
|
+
case 'POST':
|
|
2788
|
+
this.POST$.next(data);
|
|
2789
|
+
break;
|
|
2790
|
+
case 'DELETE':
|
|
2791
|
+
this.DELETE$.next(data);
|
|
2792
|
+
break;
|
|
2793
|
+
case 'STREAM':
|
|
2794
|
+
this.STREAM.next(data);
|
|
2795
|
+
break;
|
|
2796
|
+
case 'STREAM_AI':
|
|
2797
|
+
this.STREAM_AI.next(data);
|
|
2798
|
+
break;
|
|
2799
|
+
default:
|
|
2800
|
+
break;
|
|
2801
|
+
}
|
|
2802
|
+
})).subscribe();
|
|
2803
|
+
}
|
|
2804
|
+
addHeader() {
|
|
2805
|
+
const header = this.fb.group({
|
|
2806
|
+
key: ['', Validators.required],
|
|
2807
|
+
value: ['']
|
|
2808
|
+
});
|
|
2809
|
+
this.headers.push(header);
|
|
2810
|
+
}
|
|
2811
|
+
removeHeader(index) {
|
|
2812
|
+
this.headers.removeAt(index);
|
|
2813
|
+
}
|
|
2814
|
+
compileRequest() {
|
|
2815
|
+
const requestParams = this.requestForm.value;
|
|
2816
|
+
requestParams.headers = this.arrayObjectsToObjects(requestParams.headers || []);
|
|
2817
|
+
const pathReq = (requestParams.path || "").split("/");
|
|
2818
|
+
if (!this.pollingState.checked)
|
|
2819
|
+
requestParams.polling = 0;
|
|
2820
|
+
if (!this.failedState.checked) {
|
|
2821
|
+
requestParams.retry = { times: 0, delay: 0 };
|
|
2822
|
+
}
|
|
2823
|
+
return ApiRequest.adapt({
|
|
2824
|
+
...requestParams,
|
|
2825
|
+
// ...{ path: pathReq, server: this.server },
|
|
2826
|
+
...{ path: pathReq },
|
|
2827
|
+
});
|
|
2828
|
+
}
|
|
2829
|
+
onSetStateOptions() {
|
|
2830
|
+
if (!this.isValid)
|
|
2831
|
+
return;
|
|
2832
|
+
const reqParams = this.compileRequest();
|
|
2833
|
+
const db = DatabaseStorage.adapt(this.database);
|
|
2834
|
+
const type = this.dataType === "ARRAY" ? DataType.ARRAY : DataType.OBJECT;
|
|
2835
|
+
this.stateManagerDemoService.setAPIOptions(reqParams, type, db);
|
|
2836
|
+
this.requestForm.markAsPristine();
|
|
2837
|
+
}
|
|
2838
|
+
onClearRecords() {
|
|
2839
|
+
this.stateManagerDemoService.clearRecords();
|
|
2840
|
+
}
|
|
2841
|
+
onRefreshRecords() {
|
|
2842
|
+
this.stateManagerDemoService.refreshData();
|
|
2843
|
+
}
|
|
2844
|
+
onGetRequest() {
|
|
2845
|
+
this.requestType = 'GET';
|
|
2846
|
+
this.stateManagerDemoService.getClients();
|
|
2847
|
+
}
|
|
2848
|
+
onCreateRequest() {
|
|
2849
|
+
this.requestType = 'POST';
|
|
2850
|
+
this.stateManagerDemoService.createClient(this.sampleClientData);
|
|
2851
|
+
}
|
|
2852
|
+
onUpdateRequest() {
|
|
2853
|
+
this.requestType = 'PUT';
|
|
2854
|
+
this.stateManagerDemoService.updateClient(this.sampleClientData);
|
|
2855
|
+
}
|
|
2856
|
+
onDeleteRequest() {
|
|
2857
|
+
this.requestType = 'DELETE';
|
|
2858
|
+
this.stateManagerDemoService.deleteClient(this.sampleClientData);
|
|
2859
|
+
}
|
|
2860
|
+
onStreamPostRequest() {
|
|
2861
|
+
if (!this.isValid)
|
|
2862
|
+
return;
|
|
2863
|
+
this.requestType = 'STREAM_AI';
|
|
2864
|
+
const reqParams = this.compileRequest();
|
|
2865
|
+
reqParams.server = "http://localhost:11434/api";
|
|
2866
|
+
reqParams.path = ["generate"];
|
|
2867
|
+
reqParams.stream = true;
|
|
2868
|
+
this.stateManagerDemoService.setAPIOptions(reqParams, DataType.ARRAY);
|
|
2869
|
+
const payload = {
|
|
2870
|
+
model: "mistral",
|
|
2871
|
+
prompt: this.questionControl.value,
|
|
2872
|
+
stream: reqParams.stream
|
|
2873
|
+
};
|
|
2874
|
+
this.stateManagerDemoService.streamAIRequest(payload);
|
|
2875
|
+
}
|
|
2876
|
+
onStreamRequest() {
|
|
2877
|
+
if (!this.isValid)
|
|
2878
|
+
return;
|
|
2879
|
+
this.requestType = 'STREAM';
|
|
2880
|
+
const reqParams = this.compileRequest();
|
|
2881
|
+
reqParams.server = "oidc";
|
|
2882
|
+
reqParams.stream = true;
|
|
2883
|
+
this.stateManagerDemoService.setAPIOptions(reqParams, DataType.ARRAY);
|
|
2884
|
+
this.stateManagerDemoService.streamRequest();
|
|
2885
|
+
}
|
|
2886
|
+
errorHandling(err, type) {
|
|
2887
|
+
if (type === 'GET')
|
|
2888
|
+
this.GET_error$.next(err.message);
|
|
2889
|
+
if (type === 'POST')
|
|
2890
|
+
this.POST_error$.next(err.message);
|
|
2891
|
+
if (type === 'PUT')
|
|
2892
|
+
this.PUT_error$.next(err.message);
|
|
2893
|
+
if (type === 'DELETE')
|
|
2894
|
+
this.DELETE_error$.next(err.message);
|
|
2895
|
+
if (type === 'STREAM')
|
|
2896
|
+
this.STREAM_error$.next(err.message);
|
|
2897
|
+
}
|
|
2898
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RequestManagerStateDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2899
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo", viewQueries: [{ propertyName: "failedState", first: true, predicate: ["failedState"], descendants: true, static: true }, { propertyName: "pollingState", first: true, predicate: ["pollingState"], descendants: true, static: true }], ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2>\n HTTP Request State Manager\n </h2>\n\n <div [formGroup]=\"requestForm\" style=\"margin-top: 2rem;\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>State Data Type</mat-label>\n <mat-select formControlName=\"datatype\">\n <mat-option value=\"ARRAY\">Array</mat-option>\n <mat-option value=\"OBJECT\">Object</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Adapter (Model)</mat-label>\n <mat-select formControlName=\"adapter\">\n <mat-option>None</mat-option>\n <mat-option *ngFor=\"let adapter of sampleAdaptors\" [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Mapper (Model)</mat-label>\n <mat-select formControlName=\"mapper\">\n <mat-option>None</mat-option>\n <mat-option *ngFor=\"let mapper of sampleMappers\" [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>RestPath (/ delimited)</mat-label>\n <input matInput placeholder=\"clients/list\" formControlName=\"path\">\n </mat-form-field>\n </div>\n <div>\n <div formArrayName=\"headers\">\n <div *ngFor=\"let task of headers.controls; let i = index\" [formGroupName]=\"i\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"authentication\" formControlName=\"key\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Value</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"value\">\n </mat-form-field>\n <div style=\"margin-top: .5rem;\">\n <button mat-icon-button (click)=\"removeHeader(i)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n <button mat-stroked-button (click)=\"addHeader()\">Add Header</button>\n </div>\n <div style=\"margin-top: 2rem; display: flex; flex-direction:column; gap: 1rem;\">\n <div>\n <mat-slide-toggle #failedState>Retry on Failed</mat-slide-toggle>\n <div *ngIf=\"failedState.checked\" style=\"display: flex; gap: .5rem; margin-top: 1rem;\" formGroupName=\"retry\">\n <mat-form-field appearance=\"outline\">\n <mat-label>#of Times</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"times\" value=\"3\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Delay Until Next</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"delay\" value=\"3\">\n </mat-form-field>\n </div>\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n <div *ngIf=\"pollingState.checked\">\n <mat-form-field appearance=\"outline\" style=\"margin-top: 1rem\">\n <mat-label>#of Seconds</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"polling\" value=\"3\">\n </mat-form-field>\n </div>\n </div>\n <div>\n <mat-slide-toggle #DBState>Database Storage</mat-slide-toggle>\n <div *ngIf=\"DBState.checked\" style=\"display: flex; gap: .5rem; margin-top: 1rem\" formGroupName=\"database\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Table Name</mat-label>\n <input matInput placeholder=\"table\" formControlName=\"table\" value=\"\">\n </mat-form-field>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"1m\">One Minute</mat-option>\n <mat-option value=\"1h\">One Hour</mat-option>\n <mat-option value=\"1d\">One Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n </div>\n <div style=\"margin-top: 1rem; display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onSetStateOptions()\" [disabled]=\"!hasChanged\">\n Set API Request Options\n </button>\n </div>\n <div>\n <mat-error *ngIf=\"(error$ | async) as error\">\n {{ error | json }}\n </mat-error>\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n <mat-progress-bar mode=\"indeterminate\" \n *ngIf=\"(isPending$ | async)\"\n ></mat-progress-bar>\n <div *ngIf=\"pollingState.checked\">\n <mat-progress-bar mode=\"determinate\" \n *ngIf=\"!(isPending$ | async) && (this.countdown$ | async) || -1 > 0\" \n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\" *ngIf=\"(GET$ | async) as data\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1;\">CURRENT STATE ({{ dataType }})</h2>\n </div>\n <div *ngIf=\"data.length > 1\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Records</mat-label>\n <mat-select [formControl]=\"selectedRecord\" [disabled]=\"data === null && data?.length === 0\">\n <mat-option [value]=\"\">None</mat-option>\n <mat-option *ngFor=\"let item of data\" [value]=\"item\">\n {{item.domain}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div *ngIf=\"(dataObservable$ | async) as dataRecord\">\n <div *ngIf=\"(selectedRecord$ | async) as record; else NO_RECORD\">\n {{ record | json }}\n </div>\n <ng-template #NO_RECORD>No Record Selected from State</ng-template>\n \n </div>\n <div style=\"margin-top: 1rem;\">\n <span *ngIf=\"data !== null && data?.length > 0; else NO_DATA\">\n State contains a Total of {{ data.length }} Records\n </span>\n <ng-template #NO_DATA>No Records</ng-template>\n <div style=\"display: flex; gap: .5rem; text-align: end; justify-content: flex-end;\">\n <button class=\"btn\" mat-stroked-button (click)=\"onClearRecords()\">Clear</button>\n <button class=\"btn\" mat-stroked-button (click)=\"onRefreshRecords()\">Refresh</button>\n </div>\n </div>\n </div>\n\n\n\n\n <div style=\"margin-top: 1rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">GET Request ({{ dataType }})</h2>\n <div>\n <button mat-raised-button (click)=\"onGetRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(GET_error$ | async) as get_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n <div>{{ (GET$ | async) | json }}</div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onCreateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(POST_error$ | async) as post_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n <div>{{ (POST$ | async) | json }}</div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">PUT Request</h2>\n <div>\n <button mat-raised-button (click)=\"onUpdateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(PUT_error$ | async) as put_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n <div>{{ (PUT$ | async) | json }}</div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">DELETE Request</h2>\n <div>\n <button mat-raised-button (click)=\"onDeleteRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(DELETE_error$ | async) as delete_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n <div>{{ (DELETE$ | async) | json }}</div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n \n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">Streaming GET Request</h2>\n <div>\n <button mat-raised-button (click)=\"onStreamRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(STREAM_error$ | async) as stream_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <div *ngIf=\"(STREAM$ | async) as data\" class=\"container\">\n <table mat-table [dataSource]=\"data\">\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> First Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.name}} </td>\n </ng-container>\n \n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef> Last Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.lastName}} </td>\n </ng-container>\n \n <ng-container matColumnDef=\"age\">\n <th mat-header-cell *matHeaderCellDef> Age </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.age}} </td>\n </ng-container>\n \n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">STREAMING POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Ask Me</button>\n </div>\n </div>\n\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Ask me a Question</mat-label>\n <textarea matInput placeholder=\"Why is the sky blue?\" [formControl]=\"questionControl\"></textarea>\n </mat-form-field>\n </div>\n\n <div *ngIf=\"(STREAM_error$ | async) as stream_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <div *ngIf=\"(STREAM_AI$ | async) as data\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap;\">{{data}}</p>\n </div>\n </div>\n\n </div>\n\n</div>", styles: [".btn{min-width:120px}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor;background-color:#f5f5f5}.container{height:400px;overflow:auto}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "panelWidth", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i9.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i10$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
|
|
2900
|
+
}
|
|
2901
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RequestManagerStateDemoComponent, decorators: [{
|
|
2902
|
+
type: Component,
|
|
2903
|
+
args: [{ selector: 'app-request-manager-state-demo', template: "<div style=\"margin: 2rem;\">\n\n <h2>\n HTTP Request State Manager\n </h2>\n\n <div [formGroup]=\"requestForm\" style=\"margin-top: 2rem;\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>State Data Type</mat-label>\n <mat-select formControlName=\"datatype\">\n <mat-option value=\"ARRAY\">Array</mat-option>\n <mat-option value=\"OBJECT\">Object</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Adapter (Model)</mat-label>\n <mat-select formControlName=\"adapter\">\n <mat-option>None</mat-option>\n <mat-option *ngFor=\"let adapter of sampleAdaptors\" [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Mapper (Model)</mat-label>\n <mat-select formControlName=\"mapper\">\n <mat-option>None</mat-option>\n <mat-option *ngFor=\"let mapper of sampleMappers\" [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>RestPath (/ delimited)</mat-label>\n <input matInput placeholder=\"clients/list\" formControlName=\"path\">\n </mat-form-field>\n </div>\n <div>\n <div formArrayName=\"headers\">\n <div *ngFor=\"let task of headers.controls; let i = index\" [formGroupName]=\"i\">\n <div style=\"display: flex; gap: .5rem\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Key</mat-label>\n <input matInput placeholder=\"authentication\" formControlName=\"key\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Value</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"value\">\n </mat-form-field>\n <div style=\"margin-top: .5rem;\">\n <button mat-icon-button (click)=\"removeHeader(i)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n <button mat-stroked-button (click)=\"addHeader()\">Add Header</button>\n </div>\n <div style=\"margin-top: 2rem; display: flex; flex-direction:column; gap: 1rem;\">\n <div>\n <mat-slide-toggle #failedState>Retry on Failed</mat-slide-toggle>\n <div *ngIf=\"failedState.checked\" style=\"display: flex; gap: .5rem; margin-top: 1rem;\" formGroupName=\"retry\">\n <mat-form-field appearance=\"outline\">\n <mat-label>#of Times</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"times\" value=\"3\">\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Delay Until Next</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"delay\" value=\"3\">\n </mat-form-field>\n </div>\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n <div *ngIf=\"pollingState.checked\">\n <mat-form-field appearance=\"outline\" style=\"margin-top: 1rem\">\n <mat-label>#of Seconds</mat-label>\n <input matInput placeholder=\"3\" formControlName=\"polling\" value=\"3\">\n </mat-form-field>\n </div>\n </div>\n <div>\n <mat-slide-toggle #DBState>Database Storage</mat-slide-toggle>\n <div *ngIf=\"DBState.checked\" style=\"display: flex; gap: .5rem; margin-top: 1rem\" formGroupName=\"database\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Table Name</mat-label>\n <input matInput placeholder=\"table\" formControlName=\"table\" value=\"\">\n </mat-form-field>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"1m\">One Minute</mat-option>\n <mat-option value=\"1h\">One Hour</mat-option>\n <mat-option value=\"1d\">One Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n </div>\n <div style=\"margin-top: 1rem; display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onSetStateOptions()\" [disabled]=\"!hasChanged\">\n Set API Request Options\n </button>\n </div>\n <div>\n <mat-error *ngIf=\"(error$ | async) as error\">\n {{ error | json }}\n </mat-error>\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n <mat-progress-bar mode=\"indeterminate\" \n *ngIf=\"(isPending$ | async)\"\n ></mat-progress-bar>\n <div *ngIf=\"pollingState.checked\">\n <mat-progress-bar mode=\"determinate\" \n *ngIf=\"!(isPending$ | async) && (this.countdown$ | async) || -1 > 0\" \n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\" *ngIf=\"(GET$ | async) as data\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1;\">CURRENT STATE ({{ dataType }})</h2>\n </div>\n <div *ngIf=\"data.length > 1\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Records</mat-label>\n <mat-select [formControl]=\"selectedRecord\" [disabled]=\"data === null && data?.length === 0\">\n <mat-option [value]=\"\">None</mat-option>\n <mat-option *ngFor=\"let item of data\" [value]=\"item\">\n {{item.domain}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div *ngIf=\"(dataObservable$ | async) as dataRecord\">\n <div *ngIf=\"(selectedRecord$ | async) as record; else NO_RECORD\">\n {{ record | json }}\n </div>\n <ng-template #NO_RECORD>No Record Selected from State</ng-template>\n \n </div>\n <div style=\"margin-top: 1rem;\">\n <span *ngIf=\"data !== null && data?.length > 0; else NO_DATA\">\n State contains a Total of {{ data.length }} Records\n </span>\n <ng-template #NO_DATA>No Records</ng-template>\n <div style=\"display: flex; gap: .5rem; text-align: end; justify-content: flex-end;\">\n <button class=\"btn\" mat-stroked-button (click)=\"onClearRecords()\">Clear</button>\n <button class=\"btn\" mat-stroked-button (click)=\"onRefreshRecords()\">Refresh</button>\n </div>\n </div>\n </div>\n\n\n\n\n <div style=\"margin-top: 1rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">GET Request ({{ dataType }})</h2>\n <div>\n <button mat-raised-button (click)=\"onGetRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(GET_error$ | async) as get_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n <div>{{ (GET$ | async) | json }}</div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onCreateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(POST_error$ | async) as post_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n <div>{{ (POST$ | async) | json }}</div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">PUT Request</h2>\n <div>\n <button mat-raised-button (click)=\"onUpdateRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(PUT_error$ | async) as put_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n <div>{{ (PUT$ | async) | json }}</div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">DELETE Request</h2>\n <div>\n <button mat-raised-button (click)=\"onDeleteRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(DELETE_error$ | async) as delete_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n <div>{{ (DELETE$ | async) | json }}</div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n \n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">Streaming GET Request</h2>\n <div>\n <button mat-raised-button (click)=\"onStreamRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Request</button>\n </div>\n </div>\n\n <div *ngIf=\"(STREAM_error$ | async) as stream_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <div *ngIf=\"(STREAM$ | async) as data\" class=\"container\">\n <table mat-table [dataSource]=\"data\">\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> First Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.name}} </td>\n </ng-container>\n \n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef> Last Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.lastName}} </td>\n </ng-container>\n \n <ng-container matColumnDef=\"age\">\n <th mat-header-cell *matHeaderCellDef> Age </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.age}} </td>\n </ng-container>\n \n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n </div>\n\n </div>\n\n <div style=\"margin-top: 2rem\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1\">STREAMING POST Request</h2>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" [disabled]=\"hasChanged\" class=\"btn\">Ask Me</button>\n </div>\n </div>\n\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex:1\">\n <mat-label>Ask me a Question</mat-label>\n <textarea matInput placeholder=\"Why is the sky blue?\" [formControl]=\"questionControl\"></textarea>\n </mat-form-field>\n </div>\n\n <div *ngIf=\"(STREAM_error$ | async) as stream_error\" style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <div *ngIf=\"(STREAM_AI$ | async) as data\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap;\">{{data}}</p>\n </div>\n </div>\n\n </div>\n\n</div>", styles: [".btn{min-width:120px}.mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor;background-color:#f5f5f5}.container{height:400px;overflow:auto}\n"] }]
|
|
2904
|
+
}], ctorParameters: function () { return []; }, propDecorators: { failedState: [{
|
|
2905
|
+
type: ViewChild,
|
|
2906
|
+
args: ["failedState", { static: true }]
|
|
2907
|
+
}], pollingState: [{
|
|
2908
|
+
type: ViewChild,
|
|
2909
|
+
args: ["pollingState", { static: true }]
|
|
2910
|
+
}] } });
|
|
2911
|
+
|
|
2912
|
+
class HttpRequestManagerModule {
|
|
2913
|
+
static forRoot(config = ConfigOptions.adapt()) {
|
|
2914
|
+
return {
|
|
2915
|
+
ngModule: HttpRequestManagerModule,
|
|
2916
|
+
providers: [
|
|
2917
|
+
{ provide: CONFIG_SETTINGS_TOKEN, useValue: ConfigOptions.adapt(config) },
|
|
2918
|
+
HTTPManagerService, LocalStorageManagerService //all services that need access to config
|
|
2919
|
+
],
|
|
2920
|
+
};
|
|
2921
|
+
}
|
|
2922
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HttpRequestManagerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2923
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: HttpRequestManagerModule, declarations: [HttpRequestServicesDemoComponent,
|
|
2924
|
+
RequestManagerStateDemoComponent,
|
|
2925
|
+
RequestManagerDemoComponent,
|
|
2926
|
+
LocalStorageDemoComponent
|
|
2927
|
+
// DatabaseDataDemoComponent,
|
|
2928
|
+
], imports: [CommonModule,
|
|
2929
|
+
ToastMessageModule,
|
|
2930
|
+
FormsModule,
|
|
2931
|
+
ReactiveFormsModule,
|
|
2932
|
+
MatButtonModule,
|
|
2933
|
+
MatSelectModule,
|
|
2934
|
+
MatChipsModule,
|
|
2935
|
+
MatMenuModule,
|
|
2936
|
+
MatIconModule,
|
|
2937
|
+
MatTableModule,
|
|
2938
|
+
MatToolbarModule,
|
|
2939
|
+
MatButtonToggleModule,
|
|
2940
|
+
MatAutocompleteModule,
|
|
2941
|
+
MatProgressBarModule,
|
|
2942
|
+
MatSlideToggleModule,
|
|
2943
|
+
MatDividerModule,
|
|
2944
|
+
MatFormFieldModule,
|
|
2945
|
+
MatInputModule,
|
|
2946
|
+
MatSlideToggleModule, i1.TranslateModule, MatSidenavModule,
|
|
2947
|
+
FileDownloaderModule], exports: [HttpRequestServicesDemoComponent] }); }
|
|
2948
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HttpRequestManagerModule, providers: [
|
|
2949
|
+
{ provide: HTTP_INTERCEPTORS, useClass: WithCredentialsInterceptor, multi: true },
|
|
2950
|
+
{ provide: HTTP_INTERCEPTORS, useClass: RequestHeadersInterceptor, multi: true },
|
|
2951
|
+
{ provide: HTTP_INTERCEPTORS, useClass: ProxyDebuggerInterceptor, multi: true },
|
|
2952
|
+
{ provide: CONFIG_SETTINGS_TOKEN, useValue: ConfigOptions.adapt() },
|
|
2953
|
+
HTTPManagerService, LocalStorageManagerService
|
|
2954
|
+
], imports: [CommonModule,
|
|
2955
|
+
ToastMessageModule,
|
|
2956
|
+
FormsModule,
|
|
2957
|
+
ReactiveFormsModule,
|
|
2958
|
+
MatButtonModule,
|
|
2959
|
+
MatSelectModule,
|
|
2960
|
+
MatChipsModule,
|
|
2961
|
+
MatMenuModule,
|
|
2962
|
+
MatIconModule,
|
|
2963
|
+
MatTableModule,
|
|
2964
|
+
MatToolbarModule,
|
|
2965
|
+
MatButtonToggleModule,
|
|
2966
|
+
MatAutocompleteModule,
|
|
2967
|
+
MatProgressBarModule,
|
|
2968
|
+
MatSlideToggleModule,
|
|
2969
|
+
MatDividerModule,
|
|
2970
|
+
MatFormFieldModule,
|
|
2971
|
+
MatInputModule,
|
|
2972
|
+
MatSlideToggleModule,
|
|
2973
|
+
TranslateModule.forRoot(),
|
|
2974
|
+
MatSidenavModule,
|
|
2975
|
+
FileDownloaderModule] }); }
|
|
2976
|
+
}
|
|
2977
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HttpRequestManagerModule, decorators: [{
|
|
2978
|
+
type: NgModule,
|
|
2979
|
+
args: [{
|
|
2980
|
+
imports: [
|
|
2981
|
+
CommonModule,
|
|
2982
|
+
ToastMessageModule,
|
|
2983
|
+
FormsModule,
|
|
2984
|
+
ReactiveFormsModule,
|
|
2985
|
+
MatButtonModule,
|
|
2986
|
+
MatSelectModule,
|
|
2987
|
+
MatChipsModule,
|
|
2988
|
+
MatMenuModule,
|
|
2989
|
+
MatIconModule,
|
|
2990
|
+
MatTableModule,
|
|
2991
|
+
MatToolbarModule,
|
|
2992
|
+
MatButtonToggleModule,
|
|
2993
|
+
MatAutocompleteModule,
|
|
2994
|
+
MatProgressBarModule,
|
|
2995
|
+
MatSlideToggleModule,
|
|
2996
|
+
MatDividerModule,
|
|
2997
|
+
MatFormFieldModule,
|
|
2998
|
+
MatInputModule,
|
|
2999
|
+
MatSlideToggleModule,
|
|
3000
|
+
TranslateModule.forRoot(),
|
|
3001
|
+
MatSidenavModule,
|
|
3002
|
+
FileDownloaderModule,
|
|
3003
|
+
],
|
|
3004
|
+
declarations: [
|
|
3005
|
+
HttpRequestServicesDemoComponent,
|
|
3006
|
+
RequestManagerStateDemoComponent,
|
|
3007
|
+
RequestManagerDemoComponent,
|
|
3008
|
+
LocalStorageDemoComponent
|
|
3009
|
+
// DatabaseDataDemoComponent,
|
|
3010
|
+
],
|
|
3011
|
+
exports: [
|
|
3012
|
+
HttpRequestServicesDemoComponent,
|
|
3013
|
+
],
|
|
3014
|
+
providers: [
|
|
3015
|
+
{ provide: HTTP_INTERCEPTORS, useClass: WithCredentialsInterceptor, multi: true },
|
|
3016
|
+
{ provide: HTTP_INTERCEPTORS, useClass: RequestHeadersInterceptor, multi: true },
|
|
3017
|
+
{ provide: HTTP_INTERCEPTORS, useClass: ProxyDebuggerInterceptor, multi: true },
|
|
3018
|
+
{ provide: CONFIG_SETTINGS_TOKEN, useValue: ConfigOptions.adapt() },
|
|
3019
|
+
HTTPManagerService, LocalStorageManagerService
|
|
3020
|
+
],
|
|
3021
|
+
}]
|
|
3022
|
+
}] });
|
|
3023
|
+
|
|
3024
|
+
class HttpRequestServicesDemoComponent {
|
|
3025
|
+
constructor(configOptions) {
|
|
3026
|
+
this.configOptions = configOptions;
|
|
3027
|
+
this.requestTypes = [
|
|
3028
|
+
{ name: "Http Service", value: 'http_service' },
|
|
3029
|
+
{ name: "Http State Service", value: 'http_state_service' },
|
|
3030
|
+
{ name: "Database Service", value: 'database_service', divider: true, disabled: true },
|
|
3031
|
+
{ name: "Local Storage Service", value: 'local_storage_service' },
|
|
3032
|
+
];
|
|
3033
|
+
this.selectedService = this.requestTypes[0].value;
|
|
3034
|
+
}
|
|
3035
|
+
ngOnInit() {
|
|
3036
|
+
if (this.configOptions)
|
|
3037
|
+
this.injectionOptions = this.configOptions;
|
|
3038
|
+
}
|
|
3039
|
+
onSelected(type) {
|
|
3040
|
+
this.selectedService = this.requestTypes[type].value;
|
|
3041
|
+
}
|
|
3042
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HttpRequestServicesDemoComponent, deps: [{ token: CONFIG_SETTINGS_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3043
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: HttpRequestServicesDemoComponent, selector: "app-http-request-services-demo", ngImport: i0, template: "<mat-toolbar style=\"display:flex\">\n <div>Global Data</div>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button [matMenuTriggerFor]=\"menu\">Services</button>\n <mat-menu #menu=\"matMenu\">\n <ng-container *ngFor=\"let type of requestTypes; index as i\">\n <div\n *ngIf=\"type?.divider\"\n style=\"margin-top: .5rem; margin-bottom: .5rem;\"\n >\n <mat-divider></mat-divider>\n </div>\n <button\n mat-menu-item\n (click)=\"onSelected(i)\"\n [disabled]=\"type.disabled\"\n >\n {{ type.name }}\n </button>\n </ng-container>\n\n </mat-menu>\n</mat-toolbar>\n\n<span [ngSwitch]=\"selectedService\">\n <p *ngSwitchCase=\"'http_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-demo></app-request-manager-demo>\n </p>\n <p *ngSwitchCase=\"'http_state_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-state-demo></app-request-manager-state-demo>\n </p>\n <p *ngSwitchCase=\"'database_service'\">\n <!-- <app-database-data-demo></app-database-data-demo> -->\n </p>\n <p *ngSwitchCase=\"'local_storage_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-demo></app-local-storage-demo>\n </p>\n <p *ngSwitchDefault>\n Other\n </p>\n</span>\n\n<ng-template #HTTP_OPTIONS>\n <ng-container *ngIf=\"injectionOptions?.httpRequestOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - HTTP Options</h3>\n {{ injectionOptions?.httpRequestOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #LOCAL_OPTIONS>\n <ng-container class=\"box\" *ngIf=\"injectionOptions?.LocalStorageOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - LocalStorage Options</h3>\n {{ injectionOptions?.LocalStorageOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n\n", styles: [".box{padding:1rem;background-color:#f5f5f5;border:thin gray solid;margin-top:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i3$2.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i3$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i3$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "component", type: i4$1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo" }, { kind: "component", type: RequestManagerDemoComponent, selector: "app-request-manager-demo" }, { kind: "component", type: LocalStorageDemoComponent, selector: "app-local-storage-demo" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
|
|
3044
|
+
}
|
|
3045
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HttpRequestServicesDemoComponent, decorators: [{
|
|
3046
|
+
type: Component,
|
|
3047
|
+
args: [{ selector: 'app-http-request-services-demo', template: "<mat-toolbar style=\"display:flex\">\n <div>Global Data</div>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button [matMenuTriggerFor]=\"menu\">Services</button>\n <mat-menu #menu=\"matMenu\">\n <ng-container *ngFor=\"let type of requestTypes; index as i\">\n <div\n *ngIf=\"type?.divider\"\n style=\"margin-top: .5rem; margin-bottom: .5rem;\"\n >\n <mat-divider></mat-divider>\n </div>\n <button\n mat-menu-item\n (click)=\"onSelected(i)\"\n [disabled]=\"type.disabled\"\n >\n {{ type.name }}\n </button>\n </ng-container>\n\n </mat-menu>\n</mat-toolbar>\n\n<span [ngSwitch]=\"selectedService\">\n <p *ngSwitchCase=\"'http_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-demo></app-request-manager-demo>\n </p>\n <p *ngSwitchCase=\"'http_state_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-state-demo></app-request-manager-state-demo>\n </p>\n <p *ngSwitchCase=\"'database_service'\">\n <!-- <app-database-data-demo></app-database-data-demo> -->\n </p>\n <p *ngSwitchCase=\"'local_storage_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-demo></app-local-storage-demo>\n </p>\n <p *ngSwitchDefault>\n Other\n </p>\n</span>\n\n<ng-template #HTTP_OPTIONS>\n <ng-container *ngIf=\"injectionOptions?.httpRequestOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - HTTP Options</h3>\n {{ injectionOptions?.httpRequestOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #LOCAL_OPTIONS>\n <ng-container class=\"box\" *ngIf=\"injectionOptions?.LocalStorageOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - LocalStorage Options</h3>\n {{ injectionOptions?.LocalStorageOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n\n", styles: [".box{padding:1rem;background-color:#f5f5f5;border:thin gray solid;margin-top:1rem}\n"] }]
|
|
3048
|
+
}], ctorParameters: function () { return [{ type: ConfigOptions, decorators: [{
|
|
3049
|
+
type: Inject,
|
|
3050
|
+
args: [CONFIG_SETTINGS_TOKEN]
|
|
3051
|
+
}] }]; } });
|
|
3052
|
+
|
|
1706
3053
|
/*
|
|
1707
3054
|
* Public API Surface of http-request-manager
|
|
1708
3055
|
*/
|
|
@@ -1711,5 +3058,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1711
3058
|
* Generated bundle index. Do not edit.
|
|
1712
3059
|
*/
|
|
1713
3060
|
|
|
1714
|
-
export { ApiRequest, AppService, AsymmetricalEncryptionService, DataType, DatabaseStorage, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerStateService, HeadersService, LocalStorageManagerService, PathQueryService, Random, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomSignature, RandomStr, RequestErrorInterceptor, RequestHeadersInterceptor, RequestOptions, RetryOptions, SettingOptions, StorageData, StorageOption,
|
|
3061
|
+
export { ApiRequest, AppService, AsymmetricalEncryptionService, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseStorage, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageManagerService, LocalStorageOptions, PathQueryService, Random, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomSignature, RandomStr, RequestErrorInterceptor, RequestHeadersInterceptor, RequestOptions, RetryOptions, SettingOptions, StorageData, StorageOption, StorageType, SymmetricalEncryptionService, UUID, UtilsService, WithCredentialsInterceptor, countdown, delayedRetry, requestPolling, requestStreaming };
|
|
1715
3062
|
//# sourceMappingURL=http-request-manager.mjs.map
|