http-request-manager 18.11.16 → 18.11.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, Injectable, APP_ID, Inject, InjectionToken, isDevMode, signal, effect, computed, Injector, Optional, EventEmitter, Input, Output, ViewEncapsulation, Component, NgModule, ViewChild } from '@angular/core';
3
3
  import { ComponentStore } from '@ngrx/component-store';
4
- import { map, catchError, filter, tap, finalize, takeWhile, retry, startWith, mergeMap, takeUntil, withLatestFrom, switchMap, delay, concatMap, take, scan, distinctUntilChanged } from 'rxjs/operators';
4
+ import { map, catchError, filter, tap, finalize, takeWhile, retry, startWith, mergeMap, takeUntil, concatMap, toArray, withLatestFrom, switchMap, delay, take, scan, distinctUntilChanged } from 'rxjs/operators';
5
5
  import { HttpClient, HttpHeaders, HttpEventType, HttpHeaderResponse, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
6
6
  import * as CryptoJS from 'crypto-js';
7
7
  import { from, BehaviorSubject, EMPTY, throwError, defer, interval, timer, Subject, of, merge, Subscription, take as take$1, catchError as catchError$1, map as map$1, tap as tap$1, switchMap as switchMap$1, startWith as startWith$1, distinctUntilChanged as distinctUntilChanged$1, combineLatest, filter as filter$1, takeUntil as takeUntil$1, ReplaySubject } from 'rxjs';
@@ -27,8 +27,10 @@ import * as i8 from '@angular/material/icon';
27
27
  import { MatIconModule } from '@angular/material/icon';
28
28
  import * as i13 from '@angular/material/input';
29
29
  import { MatInputModule } from '@angular/material/input';
30
- import * as i10 from '@angular/material/progress-bar';
30
+ import * as i8$1 from '@angular/material/progress-bar';
31
31
  import { MatProgressBarModule } from '@angular/material/progress-bar';
32
+ import * as i2 from '@angular/material/progress-spinner';
33
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
32
34
  import * as i5 from '@angular/material/select';
33
35
  import { MatSelectModule } from '@angular/material/select';
34
36
  import { MatSidenavModule } from '@angular/material/sidenav';
@@ -40,16 +42,17 @@ import * as i3$2 from '@angular/material/toolbar';
40
42
  import { MatToolbarModule } from '@angular/material/toolbar';
41
43
  import * as i9 from '@angular/material/table';
42
44
  import { MatTableModule } from '@angular/material/table';
43
- import * as i10$1 from '@angular/material/button-toggle';
45
+ import * as i10 from '@angular/material/button-toggle';
44
46
  import { MatButtonToggleModule } from '@angular/material/button-toggle';
45
47
  import * as i9$1 from '@angular/material/datepicker';
46
48
  import { MatDatepickerModule } from '@angular/material/datepicker';
47
49
  import * as i6 from '@angular/material/core';
48
50
  import { MatNativeDateModule } from '@angular/material/core';
51
+ import * as i16 from '@angular/material/card';
52
+ import { MatCardModule } from '@angular/material/card';
49
53
  import * as i1$2 from '@angular/material/tabs';
50
54
  import { MatTabsModule } from '@angular/material/tabs';
51
- import * as i2 from '@angular/material/progress-spinner';
52
- import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
55
+ import { ToastDisplay as ToastDisplay$1, ToastColors as ToastColors$1 } from 'toast-message';
53
56
  import { DataSource } from '@angular/cdk/collections';
54
57
 
55
58
  var StorageType;
@@ -2910,6 +2913,132 @@ function requestPolling(pollInterval, stopCondition$, isPending$) {
2910
2913
  };
2911
2914
  }
2912
2915
 
2916
+ class DatabaseStorage {
2917
+ constructor(table = '', expiresIn) {
2918
+ this.table = table;
2919
+ this.expiresIn = expiresIn;
2920
+ }
2921
+ static adapt(item) {
2922
+ if (!item?.table)
2923
+ return;
2924
+ return new DatabaseStorage(item?.table, item?.expiresIn);
2925
+ }
2926
+ }
2927
+
2928
+ class RetryOptions {
2929
+ constructor(times = 0, delay = 3) {
2930
+ this.times = times;
2931
+ this.delay = delay;
2932
+ }
2933
+ static adapt(item) {
2934
+ return new RetryOptions(item?.times, item?.delay);
2935
+ }
2936
+ }
2937
+
2938
+ class BatchOptions {
2939
+ constructor(mode = 'sequential', stopOnError = false, concurrency = 3, ignoreErrors = false, logErrors = true) {
2940
+ this.mode = mode;
2941
+ this.stopOnError = stopOnError;
2942
+ this.concurrency = concurrency;
2943
+ this.ignoreErrors = ignoreErrors;
2944
+ this.logErrors = logErrors;
2945
+ }
2946
+ static adapt(item) {
2947
+ return new BatchOptions(item?.mode ?? 'sequential', item?.stopOnError ?? false, item?.concurrency ?? 3, item?.ignoreErrors ?? false, item?.logErrors !== false);
2948
+ }
2949
+ }
2950
+
2951
+ class BatchResult {
2952
+ constructor(request, success, data, error, index = 0, timestamp = Date.now()) {
2953
+ this.request = request;
2954
+ this.success = success;
2955
+ this.data = data;
2956
+ this.error = error;
2957
+ this.index = index;
2958
+ this.timestamp = timestamp;
2959
+ }
2960
+ static adapt(item) {
2961
+ return new BatchResult(item?.request, item?.success ?? false, item?.data, item?.error, item?.index ?? 0, item?.timestamp ?? Date.now());
2962
+ }
2963
+ }
2964
+
2965
+ function isPendingState(state) {
2966
+ return state.isPending === true;
2967
+ }
2968
+ function isSuccessState(state) {
2969
+ return state.isPending === false && state.data !== undefined;
2970
+ }
2971
+ function isErrorState(state) {
2972
+ return state.isPending === false && state.error !== undefined;
2973
+ }
2974
+
2975
+ function calculateBatchProgress(states) {
2976
+ const total = states.length;
2977
+ const pending = states.filter(s => s.isPending).length;
2978
+ const completed = states.filter(s => !s.isPending && s.data !== undefined).length;
2979
+ const failed = states.filter(s => !s.isPending && s.error !== undefined).length;
2980
+ const percent = total > 0 ? Math.round(((completed + failed) / total) * 100) : 0;
2981
+ return { total, pending, completed, failed, percent };
2982
+ }
2983
+
2984
+ var DataType;
2985
+ (function (DataType) {
2986
+ DataType[DataType["ANY"] = 0] = "ANY";
2987
+ DataType[DataType["ARRAY"] = 1] = "ARRAY";
2988
+ DataType[DataType["OBJECT"] = 2] = "OBJECT";
2989
+ })(DataType || (DataType = {}));
2990
+
2991
+ class ConfigHTTPOptions {
2992
+ constructor(server = '', path, headers, polling, retry, stream, displayError) {
2993
+ this.server = server;
2994
+ this.path = path;
2995
+ this.headers = headers;
2996
+ this.polling = polling;
2997
+ this.retry = retry;
2998
+ this.stream = stream;
2999
+ this.displayError = displayError;
3000
+ }
3001
+ static adapt(item) {
3002
+ const server = Array.isArray(item?.server) ? item.server.join('/') : item?.server || '';
3003
+ const retryOptions = item?.retry ? RetryOptions.adapt(item.retry) : RetryOptions.adapt();
3004
+ 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);
3005
+ }
3006
+ }
3007
+
3008
+ class LocalStorageOptions {
3009
+ constructor(storageName, storageSettingsName, options) {
3010
+ this.storageName = storageName;
3011
+ this.storageSettingsName = storageSettingsName;
3012
+ this.options = options;
3013
+ }
3014
+ static adapt(item) {
3015
+ return new LocalStorageOptions((item?.storageName) ? item.storageName : 'storage', (item?.storageSettingsName) ? item.storageSettingsName : 'global-storage', (item?.options) ? SettingOptions.adapt(item.options) : SettingOptions.adapt());
3016
+ }
3017
+ }
3018
+
3019
+ class ConfigOptions {
3020
+ constructor(httpRequestOptions, LocalStorageOptions) {
3021
+ this.httpRequestOptions = httpRequestOptions;
3022
+ this.LocalStorageOptions = LocalStorageOptions;
3023
+ }
3024
+ static adapt(item) {
3025
+ return new ConfigOptions((item?.httpRequestOptions) ? ConfigHTTPOptions.adapt(item.httpRequestOptions) : undefined, (item?.LocalStorageOptions) ? LocalStorageOptions.adapt(item.LocalStorageOptions) : undefined);
3026
+ }
3027
+ }
3028
+
3029
+ class UserData {
3030
+ constructor(ldap = '', name = '', email = '', color = RandomPaletteColor()) {
3031
+ this.ldap = ldap;
3032
+ this.name = name;
3033
+ this.email = email;
3034
+ this.color = color;
3035
+ }
3036
+ static adapt(item) {
3037
+ const userName = `${item?.first_name} ${item?.last_name}`;
3038
+ return new UserData(item?.ldap, userName, item?.email, item?.color);
3039
+ }
3040
+ }
3041
+
2913
3042
  /**
2914
3043
  * Message Tracker Service - Guaranteed Message Delivery
2915
3044
  *
@@ -3329,86 +3458,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
3329
3458
  }]
3330
3459
  }], ctorParameters: () => [{ type: WebSocketManagerService }] });
3331
3460
 
3332
- class DatabaseStorage {
3333
- constructor(table = '', expiresIn) {
3334
- this.table = table;
3335
- this.expiresIn = expiresIn;
3336
- }
3337
- static adapt(item) {
3338
- if (!item?.table)
3339
- return;
3340
- return new DatabaseStorage(item?.table, item?.expiresIn);
3341
- }
3342
- }
3343
-
3344
- class RetryOptions {
3345
- constructor(times = 0, delay = 3) {
3346
- this.times = times;
3347
- this.delay = delay;
3348
- }
3349
- static adapt(item) {
3350
- return new RetryOptions(item?.times, item?.delay);
3351
- }
3352
- }
3353
-
3354
- var DataType;
3355
- (function (DataType) {
3356
- DataType[DataType["ANY"] = 0] = "ANY";
3357
- DataType[DataType["ARRAY"] = 1] = "ARRAY";
3358
- DataType[DataType["OBJECT"] = 2] = "OBJECT";
3359
- })(DataType || (DataType = {}));
3360
-
3361
- class ConfigHTTPOptions {
3362
- constructor(server = '', path, headers, polling, retry, stream, displayError) {
3363
- this.server = server;
3364
- this.path = path;
3365
- this.headers = headers;
3366
- this.polling = polling;
3367
- this.retry = retry;
3368
- this.stream = stream;
3369
- this.displayError = displayError;
3370
- }
3371
- static adapt(item) {
3372
- const server = Array.isArray(item?.server) ? item.server.join('/') : item?.server || '';
3373
- const retryOptions = item?.retry ? RetryOptions.adapt(item.retry) : RetryOptions.adapt();
3374
- 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);
3375
- }
3376
- }
3377
-
3378
- class LocalStorageOptions {
3379
- constructor(storageName, storageSettingsName, options) {
3380
- this.storageName = storageName;
3381
- this.storageSettingsName = storageSettingsName;
3382
- this.options = options;
3383
- }
3384
- static adapt(item) {
3385
- return new LocalStorageOptions((item?.storageName) ? item.storageName : 'storage', (item?.storageSettingsName) ? item.storageSettingsName : 'global-storage', (item?.options) ? SettingOptions.adapt(item.options) : SettingOptions.adapt());
3386
- }
3387
- }
3388
-
3389
- class ConfigOptions {
3390
- constructor(httpRequestOptions, LocalStorageOptions) {
3391
- this.httpRequestOptions = httpRequestOptions;
3392
- this.LocalStorageOptions = LocalStorageOptions;
3393
- }
3394
- static adapt(item) {
3395
- return new ConfigOptions((item?.httpRequestOptions) ? ConfigHTTPOptions.adapt(item.httpRequestOptions) : undefined, (item?.LocalStorageOptions) ? LocalStorageOptions.adapt(item.LocalStorageOptions) : undefined);
3396
- }
3397
- }
3398
-
3399
- class UserData {
3400
- constructor(ldap = '', name = '', email = '', color = RandomPaletteColor()) {
3401
- this.ldap = ldap;
3402
- this.name = name;
3403
- this.email = email;
3404
- this.color = color;
3405
- }
3406
- static adapt(item) {
3407
- const userName = `${item?.first_name} ${item?.last_name}`;
3408
- return new UserData(item?.ldap, userName, item?.email, item?.color);
3409
- }
3410
- }
3411
-
3412
3461
  class HTTPManagerService extends RequestService {
3413
3462
  constructor(configOptions) {
3414
3463
  super();
@@ -3725,6 +3774,140 @@ class HTTPManagerService extends RequestService {
3725
3774
  const updatedOptions = this.objectMergerService.mergeOptions(optionsReq);
3726
3775
  return updatedOptions;
3727
3776
  }
3777
+ // BATCH REQUESTS
3778
+ /**
3779
+ * Execute multiple HTTP requests with configurable execution strategy
3780
+ * @param requests Array of ApiRequest configurations
3781
+ * @param options Optional batch configuration (all properties optional)
3782
+ * @returns Observable emitting array of data in the order of requests provided
3783
+ */
3784
+ getBatchRequests(requests, options) {
3785
+ const batchOptions = BatchOptions.adapt(options);
3786
+ const mode = batchOptions.mode || 'sequential';
3787
+ if (mode === 'parallel') {
3788
+ return this.getParallelRequest(requests, batchOptions);
3789
+ }
3790
+ else {
3791
+ return this.getSequentialRequest(requests, batchOptions);
3792
+ }
3793
+ }
3794
+ /**
3795
+ * Execute requests sequentially (one at a time, in order)
3796
+ * @param requests Array of ApiRequest configurations
3797
+ * @param options Optional batch configuration
3798
+ * @returns Observable emitting array of data when all requests complete
3799
+ */
3800
+ getSequentialRequest(requests, options) {
3801
+ const batchOptions = BatchOptions.adapt(options);
3802
+ const results = new Array(requests.length);
3803
+ return from(requests).pipe(concatMap((req, index) => {
3804
+ return this.getRequest(req).pipe(tap(data => {
3805
+ results[index] = data;
3806
+ }), catchError(error => this.handleSequentialError(req, error, index, batchOptions)));
3807
+ }), toArray(), map(() => results));
3808
+ }
3809
+ /**
3810
+ * Execute requests in parallel with concurrency control
3811
+ * @param requests Array of ApiRequest configurations
3812
+ * @param options Optional batch configuration with concurrency limit
3813
+ * @returns Observable emitting array of data when all requests complete
3814
+ */
3815
+ getParallelRequest(requests, options) {
3816
+ const batchOptions = BatchOptions.adapt(options);
3817
+ const concurrency = batchOptions.concurrency || 3;
3818
+ const results = new Array(requests.length);
3819
+ return from(requests).pipe(mergeMap((req, index) => {
3820
+ return this.getRequest(req).pipe(tap(data => {
3821
+ results[index] = data;
3822
+ }), catchError(error => this.handleParallelError(req, error, index, batchOptions)));
3823
+ }, concurrency), toArray(), map(() => results));
3824
+ }
3825
+ /**
3826
+ * Execute multiple HTTP requests and emit individual state changes in real-time
3827
+ * @param requests Array of ApiRequest configurations
3828
+ * @param options Optional batch configuration (all properties optional)
3829
+ * @returns Observable stream of individual request states
3830
+ */
3831
+ getBatchRequestsStream(requests, options) {
3832
+ const batchOptions = BatchOptions.adapt(options);
3833
+ const mode = batchOptions.mode || 'sequential';
3834
+ if (mode === 'parallel') {
3835
+ return this.getParallelStream(requests, batchOptions);
3836
+ }
3837
+ else {
3838
+ return this.getSequentialStream(requests, batchOptions);
3839
+ }
3840
+ }
3841
+ /**
3842
+ * Execute requests sequentially and emit state changes
3843
+ */
3844
+ getSequentialStream(requests, options) {
3845
+ return from(requests).pipe(concatMap((req, index) => {
3846
+ const pending$ = of({
3847
+ index,
3848
+ request: req,
3849
+ isPending: true
3850
+ });
3851
+ const result$ = this.getRequest(req).pipe(map((data) => ({
3852
+ index,
3853
+ request: req,
3854
+ isPending: false,
3855
+ data
3856
+ })), catchError((error) => of({
3857
+ index,
3858
+ request: req,
3859
+ isPending: false,
3860
+ error
3861
+ })));
3862
+ return pending$.pipe(concatMap(() => result$));
3863
+ }));
3864
+ }
3865
+ /**
3866
+ * Execute requests in parallel and emit state changes
3867
+ */
3868
+ getParallelStream(requests, options) {
3869
+ const concurrency = options.concurrency || 3;
3870
+ return from(requests).pipe(mergeMap((req, index) => {
3871
+ const pending$ = of({
3872
+ index,
3873
+ request: req,
3874
+ isPending: true
3875
+ });
3876
+ const result$ = this.getRequest(req).pipe(map((data) => ({
3877
+ index,
3878
+ request: req,
3879
+ isPending: false,
3880
+ data
3881
+ })), catchError((error) => of({
3882
+ index,
3883
+ request: req,
3884
+ isPending: false,
3885
+ error
3886
+ })));
3887
+ return pending$.pipe(concatMap(() => result$));
3888
+ }, concurrency));
3889
+ }
3890
+ handleSequentialError(request, error, index, options) {
3891
+ if (options.logErrors !== false) {
3892
+ console.error(`Batch request ${index} failed:`, error);
3893
+ }
3894
+ if (options.stopOnError) {
3895
+ return throwError(() => error);
3896
+ }
3897
+ if (options.ignoreErrors) {
3898
+ return of(undefined);
3899
+ }
3900
+ return throwError(() => error);
3901
+ }
3902
+ handleParallelError(request, error, index, options) {
3903
+ if (options.logErrors !== false) {
3904
+ console.error(`Batch request ${index} failed:`, error);
3905
+ }
3906
+ if (options.ignoreErrors) {
3907
+ return of(undefined);
3908
+ }
3909
+ return of(undefined);
3910
+ }
3728
3911
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HTTPManagerService, deps: [{ token: CONFIG_SETTINGS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
3729
3912
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HTTPManagerService, providedIn: 'root' }); }
3730
3913
  }
@@ -4239,6 +4422,140 @@ class HTTPManagerSignalsService extends RequestSignalsService {
4239
4422
  const updatedOptions = this.objectMergerService.mergeOptions(optionsReq);
4240
4423
  return updatedOptions;
4241
4424
  }
4425
+ // BATCH REQUESTS
4426
+ /**
4427
+ * Execute multiple HTTP requests with configurable execution strategy
4428
+ * @param requests Array of ApiRequest configurations
4429
+ * @param options Optional batch configuration (all properties optional)
4430
+ * @returns Observable emitting array of data in the order of requests provided
4431
+ */
4432
+ getBatchRequests(requests, options) {
4433
+ const batchOptions = BatchOptions.adapt(options);
4434
+ const mode = batchOptions.mode || 'sequential';
4435
+ if (mode === 'parallel') {
4436
+ return this.getParallelRequest(requests, batchOptions);
4437
+ }
4438
+ else {
4439
+ return this.getSequentialRequest(requests, batchOptions);
4440
+ }
4441
+ }
4442
+ /**
4443
+ * Execute requests sequentially (one at a time, in order)
4444
+ * @param requests Array of ApiRequest configurations
4445
+ * @param options Optional batch configuration
4446
+ * @returns Observable emitting array of data when all requests complete
4447
+ */
4448
+ getSequentialRequest(requests, options) {
4449
+ const batchOptions = BatchOptions.adapt(options);
4450
+ const results = new Array(requests.length);
4451
+ return from(requests).pipe(concatMap((req, index) => {
4452
+ return this.getRequest(req).pipe(tap(data => {
4453
+ results[index] = data;
4454
+ }), catchError(error => this.handleSequentialError(req, error, index, batchOptions)));
4455
+ }), toArray(), map(() => results));
4456
+ }
4457
+ /**
4458
+ * Execute requests in parallel with concurrency control
4459
+ * @param requests Array of ApiRequest configurations
4460
+ * @param options Optional batch configuration with concurrency limit
4461
+ * @returns Observable emitting array of data when all requests complete
4462
+ */
4463
+ getParallelRequest(requests, options) {
4464
+ const batchOptions = BatchOptions.adapt(options);
4465
+ const concurrency = batchOptions.concurrency || 3;
4466
+ const results = new Array(requests.length);
4467
+ return from(requests).pipe(mergeMap((req, index) => {
4468
+ return this.getRequest(req).pipe(tap(data => {
4469
+ results[index] = data;
4470
+ }), catchError(error => this.handleParallelError(req, error, index, batchOptions)));
4471
+ }, concurrency), toArray(), map(() => results));
4472
+ }
4473
+ /**
4474
+ * Execute multiple HTTP requests and emit individual state changes in real-time
4475
+ * @param requests Array of ApiRequest configurations
4476
+ * @param options Optional batch configuration (all properties optional)
4477
+ * @returns Observable stream of individual request states
4478
+ */
4479
+ getBatchRequestsStream(requests, options) {
4480
+ const batchOptions = BatchOptions.adapt(options);
4481
+ const mode = batchOptions.mode || 'sequential';
4482
+ if (mode === 'parallel') {
4483
+ return this.getParallelStream(requests, batchOptions);
4484
+ }
4485
+ else {
4486
+ return this.getSequentialStream(requests, batchOptions);
4487
+ }
4488
+ }
4489
+ /**
4490
+ * Execute requests sequentially and emit state changes
4491
+ */
4492
+ getSequentialStream(requests, options) {
4493
+ return from(requests).pipe(concatMap((req, index) => {
4494
+ const pending$ = of({
4495
+ index,
4496
+ request: req,
4497
+ isPending: true
4498
+ });
4499
+ const result$ = this.getRequest(req).pipe(map((data) => ({
4500
+ index,
4501
+ request: req,
4502
+ isPending: false,
4503
+ data
4504
+ })), catchError((error) => of({
4505
+ index,
4506
+ request: req,
4507
+ isPending: false,
4508
+ error
4509
+ })));
4510
+ return pending$.pipe(concatMap(() => result$));
4511
+ }));
4512
+ }
4513
+ /**
4514
+ * Execute requests in parallel and emit state changes
4515
+ */
4516
+ getParallelStream(requests, options) {
4517
+ const concurrency = options.concurrency || 3;
4518
+ return from(requests).pipe(mergeMap((req, index) => {
4519
+ const pending$ = of({
4520
+ index,
4521
+ request: req,
4522
+ isPending: true
4523
+ });
4524
+ const result$ = this.getRequest(req).pipe(map((data) => ({
4525
+ index,
4526
+ request: req,
4527
+ isPending: false,
4528
+ data
4529
+ })), catchError((error) => of({
4530
+ index,
4531
+ request: req,
4532
+ isPending: false,
4533
+ error
4534
+ })));
4535
+ return pending$.pipe(concatMap(() => result$));
4536
+ }, concurrency));
4537
+ }
4538
+ handleSequentialError(request, error, index, options) {
4539
+ if (options.logErrors !== false) {
4540
+ console.error(`Batch request ${index} failed:`, error);
4541
+ }
4542
+ if (options.stopOnError) {
4543
+ return throwError(() => error);
4544
+ }
4545
+ if (options.ignoreErrors) {
4546
+ return of(undefined);
4547
+ }
4548
+ return throwError(() => error);
4549
+ }
4550
+ handleParallelError(request, error, index, options) {
4551
+ if (options.logErrors !== false) {
4552
+ console.error(`Batch request ${index} failed:`, error);
4553
+ }
4554
+ if (options.ignoreErrors) {
4555
+ return of(undefined);
4556
+ }
4557
+ return of(undefined);
4558
+ }
4242
4559
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HTTPManagerSignalsService, deps: [{ token: CONFIG_SETTINGS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
4243
4560
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HTTPManagerSignalsService, providedIn: 'root' }); }
4244
4561
  }
@@ -7087,10 +7404,10 @@ class FileDownloaderComponent extends HTTPManagerService {
7087
7404
  onError(message) {
7088
7405
  if (!message || !this.displayErrorMessage)
7089
7406
  return;
7090
- const display = ToastDisplay.adapt({
7407
+ const display = ToastDisplay$1.adapt({
7091
7408
  message,
7092
7409
  action: 'Ok',
7093
- color: ToastColors.ERROR,
7410
+ color: ToastColors$1.ERROR,
7094
7411
  icon: 'error',
7095
7412
  });
7096
7413
  this.active = false;
@@ -7743,7 +8060,7 @@ class RequestManagerBasicDemoComponent {
7743
8060
  this.AIType = type;
7744
8061
  }
7745
8062
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerBasicDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7746
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerBasicDemoComponent, selector: "app-request-manager-basic-demo", providers: [HTTPManagerService], 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 Basic Request Manager Setup\n </h2>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked && !(isPending$ | async)) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\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 @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n @if ((GET$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n @if ((POST$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <h3>Include Record ID in the RestPath</h3>\n\n @if ((PUT$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 <h3>Include Record ID in the RestPath</h3>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n @if ((DELETE$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\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 @if ((STREAM$ | async); as data) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </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\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Records: {{ data.length }}\n </div>\n </div>\n }\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; padding-top: .5rem;\">AI -@if (AIType === 1) {\n <span>STREAMING</span>\n } POST Request</h2>\n <div style=\"display: flex; gap: 1rem;\">\n <button mat-raised-button [matMenuTriggerFor]=\"menu\" style=\"min-width: 120px;\">\n <mat-icon>lan</mat-icon>\n @if (AIType === 0) {\n <span>Server</span>\n } @else {\n Local\n }\n </button>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"onSelectAIType(0)\">Server</button>\n <button mat-menu-item (click)=\"onSelectAIType(1)\">Local</button>\n </mat-menu>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" class=\"btn\">Ask Me</button>\n </div>\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 @if ((STREAM_AI_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n @if (AIType === 1) {\n <div style=\"color: red;\">\n You must have Ollama active and the 'phi3:latest' model to use this feature.\n </div>\n } @else {\n <span style=\"color: gray;\">\n Define the RestPath to the API endpoint that will handle the AI request.\n Use: 'ai/chat' for server\n </span>\n }\n\n <div>\n @if ((STREAM_AI$ | async); as data) {\n <div style=\"margin-top: 1rem; font-size: 1.2rem; border-radius: 1rem; border: black 1px solid; padding: 2rem;\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap; line-height: 1.6rem;\">{{data}}</p>\n </div>\n }\n </div>\n\n</div>\n\n<div style=\"margin-top: 1.5rem; margin-bottom: 1rem; line-height: 1.5rem;\">\n <mat-divider></mat-divider>\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 @if (disable.checked) {\n <span>\n Enable\n </span>\n } @else {\n Disable\n }\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}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i10.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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", "saveFileAs", "labels", "disabled"], outputs: ["completed", "failed"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
8063
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerBasicDemoComponent, selector: "app-request-manager-basic-demo", providers: [HTTPManagerService], 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 Basic Request Manager Setup\n </h2>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked && !(isPending$ | async)) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\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 @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n @if ((GET$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n @if ((POST$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <h3>Include Record ID in the RestPath</h3>\n\n @if ((PUT$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 <h3>Include Record ID in the RestPath</h3>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n @if ((DELETE$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\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 @if ((STREAM$ | async); as data) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </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\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Records: {{ data.length }}\n </div>\n </div>\n }\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; padding-top: .5rem;\">AI -@if (AIType === 1) {\n <span>STREAMING</span>\n } POST Request</h2>\n <div style=\"display: flex; gap: 1rem;\">\n <button mat-raised-button [matMenuTriggerFor]=\"menu\" style=\"min-width: 120px;\">\n <mat-icon>lan</mat-icon>\n @if (AIType === 0) {\n <span>Server</span>\n } @else {\n Local\n }\n </button>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"onSelectAIType(0)\">Server</button>\n <button mat-menu-item (click)=\"onSelectAIType(1)\">Local</button>\n </mat-menu>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" class=\"btn\">Ask Me</button>\n </div>\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 @if ((STREAM_AI_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n @if (AIType === 1) {\n <div style=\"color: red;\">\n You must have Ollama active and the 'phi3:latest' model to use this feature.\n </div>\n } @else {\n <span style=\"color: gray;\">\n Define the RestPath to the API endpoint that will handle the AI request.\n Use: 'ai/chat' for server\n </span>\n }\n\n <div>\n @if ((STREAM_AI$ | async); as data) {\n <div style=\"margin-top: 1rem; font-size: 1.2rem; border-radius: 1rem; border: black 1px solid; padding: 2rem;\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap; line-height: 1.6rem;\">{{data}}</p>\n </div>\n }\n </div>\n\n</div>\n\n<div style=\"margin-top: 1.5rem; margin-bottom: 1rem; line-height: 1.5rem;\">\n <mat-divider></mat-divider>\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 @if (disable.checked) {\n <span>\n Enable\n </span>\n } @else {\n Disable\n }\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}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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", "saveFileAs", "labels", "disabled"], outputs: ["completed", "failed"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
7747
8064
  }
7748
8065
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerBasicDemoComponent, decorators: [{
7749
8066
  type: Component,
@@ -8143,7 +8460,7 @@ class RequestManagerStateDemoComponent {
8143
8460
  this.prompts = [];
8144
8461
  }
8145
8462
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerStateDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8146
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo", inputs: { server: "server", adapter: "adapter", mapper: "mapper" }, providers: [StateManagerDemoService, HTTPManagerService], 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\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\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\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\n\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 @for (task of headers.controls; track task; let i = $index) {\n <div [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 }\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 @if (failedState.checked) {\n <div 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 }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\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 }\n </div>\n <div>\n <mat-slide-toggle #DBState>Database Storage</mat-slide-toggle>\n @if (DBState.checked) {\n <div 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 }\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 @if ((error$ | async); as error) {\n <mat-error>\n {{ error }}\n </mat-error>\n }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked) {\n <div>\n @if (!(isPending$ | async) && (this.countdown$ | async) || -1 > 0) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\n </div>\n }\n\n </div>\n\n @if ((GET$ | async); as data) {\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1;\">CURRENT STATE ({{ dataType }})</h2>\n </div>\n @if (data.length > 1) {\n <div>\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 @for (item of data; track item) {\n <mat-option [value]=\"item\">\n {{item.name || (item.first_name) | titlecase}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n @if ((dataObservable$ | async); as dataRecord) {\n <div>\n @if ((selectedRecord$ | async); as record) {\n <div>\n {{ record | json }}\n </div>\n } @else {\n No Record Selected from State\n }\n </div>\n }\n <div style=\"margin-top: 1rem;\">\n @if (data !== null && data?.length > 0) {\n <span>\n State contains a Total of {{ data.length }} Records\n </span>\n } @else {\n No Records\n }\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 </div>\n </div>\n </div>\n }\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 @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n @if ((GET$ | async); as getData) {\n <div>{{ getData | json }}</div>\n }\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 @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n @if ((POST$ | async); as postData) {\n <div>{{ postData | json }}</div>\n }\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 @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n @if ((PUT$ | async); as putData) {\n <div>{{ putData | json }}</div>\n }\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 @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n @if ((DELETE$ | async); as deleteData) {\n <div>{{ deleteData | json }}</div>\n }\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 style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\n <button mat-raised-button (click)=\"onStreamRequest()\" class=\"btn\" [disabled]=\"hasChanged\">Request</button>\n </div>\n </div>\n\n @if ((STREAM_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n @if ((STREAM$ | async); as data) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </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\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Data received\n </div>\n </div>\n }\n </div>\n\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}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i10.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
8463
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo", inputs: { server: "server", adapter: "adapter", mapper: "mapper" }, providers: [StateManagerDemoService, HTTPManagerService], 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\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\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\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\n\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 @for (task of headers.controls; track task; let i = $index) {\n <div [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 }\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 @if (failedState.checked) {\n <div 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 }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\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 }\n </div>\n <div>\n <mat-slide-toggle #DBState>Database Storage</mat-slide-toggle>\n @if (DBState.checked) {\n <div 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 }\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 @if ((error$ | async); as error) {\n <mat-error>\n {{ error }}\n </mat-error>\n }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked) {\n <div>\n @if (!(isPending$ | async) && (this.countdown$ | async) || -1 > 0) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\n </div>\n }\n\n </div>\n\n @if ((GET$ | async); as data) {\n <div style=\"margin-top: 2rem\">\n <div style=\"display: flex;\">\n <h2 style=\"flex:1;\">CURRENT STATE ({{ dataType }})</h2>\n </div>\n @if (data.length > 1) {\n <div>\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 @for (item of data; track item) {\n <mat-option [value]=\"item\">\n {{item.name || (item.first_name) | titlecase}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n @if ((dataObservable$ | async); as dataRecord) {\n <div>\n @if ((selectedRecord$ | async); as record) {\n <div>\n {{ record | json }}\n </div>\n } @else {\n No Record Selected from State\n }\n </div>\n }\n <div style=\"margin-top: 1rem;\">\n @if (data !== null && data?.length > 0) {\n <span>\n State contains a Total of {{ data.length }} Records\n </span>\n } @else {\n No Records\n }\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 </div>\n </div>\n </div>\n }\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 @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n @if ((GET$ | async); as getData) {\n <div>{{ getData | json }}</div>\n }\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 @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n @if ((POST$ | async); as postData) {\n <div>{{ postData | json }}</div>\n }\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 @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n @if ((PUT$ | async); as putData) {\n <div>{{ putData | json }}</div>\n }\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 @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n @if ((DELETE$ | async); as deleteData) {\n <div>{{ deleteData | json }}</div>\n }\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 style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\n <button mat-raised-button (click)=\"onStreamRequest()\" class=\"btn\" [disabled]=\"hasChanged\">Request</button>\n </div>\n </div>\n\n @if ((STREAM_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n <div style=\"margin-top: 1rem;\">\n @if ((STREAM$ | async); as data) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </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\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Data received\n </div>\n </div>\n }\n </div>\n\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}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
8147
8464
  }
8148
8465
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerStateDemoComponent, decorators: [{
8149
8466
  type: Component,
@@ -8184,6 +8501,16 @@ class RequestManagerDemoComponent {
8184
8501
  isObject(value) {
8185
8502
  return value !== null && typeof value === 'object' && !Array.isArray(value);
8186
8503
  }
8504
+ // Computed properties for filtered states (removes undefined)
8505
+ get filteredParallelStates() {
8506
+ return this.parallelBatchStates.filter(s => s !== undefined);
8507
+ }
8508
+ get filteredSequentialStates() {
8509
+ return this.sequentialBatchStates.filter(s => s !== undefined);
8510
+ }
8511
+ get filteredStreamStates() {
8512
+ return this.streamBatchStates.filter(s => s !== undefined);
8513
+ }
8187
8514
  get retry() {
8188
8515
  return this.requestForm.get('retry')?.value;
8189
8516
  }
@@ -8209,6 +8536,15 @@ class RequestManagerDemoComponent {
8209
8536
  this.DELETE_error$ = new BehaviorSubject('');
8210
8537
  this.STREAM_error$ = new BehaviorSubject('');
8211
8538
  this.STREAM_AI_error$ = new BehaviorSubject('');
8539
+ this.isParallelLoading = false;
8540
+ this.isSequentialLoading = false;
8541
+ // Parallel batch states for individual request tracking
8542
+ this.parallelBatchStates = [];
8543
+ // Sequential batch states for individual request tracking
8544
+ this.sequentialBatchStates = [];
8545
+ // Stream batch request properties
8546
+ this.streamBatchStates = [];
8547
+ this.isStreamLoading = false;
8212
8548
  this.requestParams = {
8213
8549
  GET: ApiRequest.adapt(),
8214
8550
  POST: ApiRequest.adapt(),
@@ -8481,12 +8817,151 @@ class RequestManagerDemoComponent {
8481
8817
  onSelectAIType(type) {
8482
8818
  this.AIType = type;
8483
8819
  }
8820
+ // ═══════════════════════════════════════════════════════════════════════════
8821
+ // BATCH REQUEST DEMO METHODS
8822
+ // ═══════════════════════════════════════════════════════════════════════════
8823
+ /**
8824
+ * Execute parallel batch request - fetch 5 users from JSONPlaceholder with individual states
8825
+ */
8826
+ onExecuteParallelBatch() {
8827
+ this.isParallelLoading = true;
8828
+ this.parallelError = undefined;
8829
+ this.parallelExecutionTime = undefined;
8830
+ this.parallelResults = undefined;
8831
+ const requests = this.createBatchRequests('https://jsonplaceholder.typicode.com', ['users'], [1, 2, 3, 4, 5]);
8832
+ const startTime = performance.now();
8833
+ this.httpManagerService.getParallelRequest(requests, BatchOptions.adapt({
8834
+ concurrency: 3,
8835
+ ignoreErrors: true,
8836
+ logErrors: true
8837
+ })).pipe(tap(results => {
8838
+ this.parallelResults = results;
8839
+ this.parallelExecutionTime = performance.now() - startTime;
8840
+ this.isParallelLoading = false;
8841
+ }), catchError(error => {
8842
+ this.parallelError = error.message || 'Parallel batch failed';
8843
+ this.isParallelLoading = false;
8844
+ return throwError(() => error);
8845
+ })).subscribe();
8846
+ }
8847
+ /**
8848
+ * Execute sequential batch request - fetch 5 todos from JSONPlaceholder with individual states
8849
+ */
8850
+ onExecuteSequentialBatch() {
8851
+ this.isSequentialLoading = true;
8852
+ this.sequentialError = undefined;
8853
+ this.sequentialExecutionTime = undefined;
8854
+ this.sequentialResults = undefined;
8855
+ const requests = this.createBatchRequests('https://jsonplaceholder.typicode.com', ['todos'], [1, 2, 3, 4, 5]);
8856
+ const startTime = performance.now();
8857
+ this.httpManagerService.getSequentialRequest(requests, BatchOptions.adapt({
8858
+ stopOnError: false,
8859
+ ignoreErrors: true,
8860
+ logErrors: true
8861
+ })).pipe(tap(results => {
8862
+ this.sequentialResults = results;
8863
+ this.sequentialExecutionTime = performance.now() - startTime;
8864
+ this.isSequentialLoading = false;
8865
+ }), catchError(error => {
8866
+ this.sequentialError = error.message || 'Sequential batch failed';
8867
+ this.isSequentialLoading = false;
8868
+ return throwError(() => error);
8869
+ })).subscribe();
8870
+ }
8871
+ /**
8872
+ * Execute stream batch request - fetch 5 posts with real-time state updates
8873
+ */
8874
+ onExecuteStreamBatch() {
8875
+ this.isStreamLoading = true;
8876
+ this.streamError = undefined;
8877
+ this.streamExecutionTime = undefined;
8878
+ this.streamBatchStates = [];
8879
+ this.streamProgress = undefined;
8880
+ const requests = this.createBatchRequests('https://jsonplaceholder.typicode.com', ['posts'], [1, 2, 3, 4, 5]);
8881
+ const startTime = performance.now();
8882
+ this.httpManagerService.getBatchRequestsStream(requests, {
8883
+ mode: 'parallel',
8884
+ concurrency: 3,
8885
+ stopOnError: false,
8886
+ ignoreErrors: true,
8887
+ logErrors: true
8888
+ }).pipe(tap(state => {
8889
+ this.streamBatchStates[state.index] = state;
8890
+ this.streamProgress = calculateBatchProgress(this.streamBatchStates.filter(s => s !== undefined));
8891
+ if (!state.isPending) {
8892
+ this.streamExecutionTime = performance.now() - startTime;
8893
+ }
8894
+ this.isStreamLoading = this.streamBatchStates.some(s => s && s.isPending);
8895
+ }), catchError(error => {
8896
+ this.streamError = error.message || 'Stream batch failed';
8897
+ this.isStreamLoading = false;
8898
+ return throwError(() => error);
8899
+ })).subscribe();
8900
+ }
8901
+ /**
8902
+ * Type guard for pending state
8903
+ */
8904
+ isPendingState(state) {
8905
+ return state.isPending === true;
8906
+ }
8907
+ /**
8908
+ * Type guard for success state
8909
+ */
8910
+ isSuccessState(state) {
8911
+ return state.isPending === false && state.data !== undefined;
8912
+ }
8913
+ /**
8914
+ * Type guard for error state
8915
+ */
8916
+ isErrorState(state) {
8917
+ return state.isPending === false && state.error !== undefined;
8918
+ }
8919
+ /**
8920
+ * Helper to create batch requests from IDs
8921
+ */
8922
+ createBatchRequests(baseUrl, basePath, ids) {
8923
+ return ids.map(id => ApiRequest.adapt({
8924
+ server: baseUrl,
8925
+ path: [...basePath, id]
8926
+ }));
8927
+ }
8928
+ /**
8929
+ * Check if result is successful (not undefined)
8930
+ */
8931
+ isSuccess(result) {
8932
+ return result !== undefined && result !== null;
8933
+ }
8934
+ /**
8935
+ * Format execution time for display
8936
+ */
8937
+ formatTime(ms) {
8938
+ if (ms < 1000) {
8939
+ return `${Math.round(ms)}ms`;
8940
+ }
8941
+ return `${(ms / 1000).toFixed(2)}s`;
8942
+ }
8943
+ /**
8944
+ * Get success count from results array
8945
+ */
8946
+ getSuccessCount(results) {
8947
+ if (!results)
8948
+ return 0;
8949
+ return results.filter(r => r !== undefined).length;
8950
+ }
8951
+ /**
8952
+ * Get failure count from results array
8953
+ */
8954
+ getFailureCount(results) {
8955
+ if (!results)
8956
+ return 0;
8957
+ return results.filter(r => r === undefined).length;
8958
+ }
8484
8959
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8485
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerDemoComponent, selector: "app-request-manager-demo", inputs: { server: "server", adapter: "adapter", mapper: "mapper" }, providers: [HTTPManagerService], 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\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\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\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\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 @for (task of headers.controls; track task; let i = $index) {\n <div [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 }\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 @if (failedState.checked) {\n <div 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 }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\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 }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked && !(isPending$ | async)) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\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 @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n @if ((GET$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n @if ((POST$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <h3>Include Record ID in the RestPath</h3>\n\n @if ((PUT$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 <h3>Include Record ID in the RestPath</h3>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n @if ((DELETE$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\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 @if ((STREAM$ | async); as data) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8\">\n \n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\"> \n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </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 \n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Records: {{ data.length }}\n </div>\n </div>\n }\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; padding-top: .5rem;\">AI -@if (AIType === 1) {\n <span>STREAMING</span>\n } POST Request</h2>\n <div style=\"display: flex; gap: 1rem;\">\n <button mat-raised-button [matMenuTriggerFor]=\"menu\" style=\"min-width: 120px;\">\n <mat-icon>lan</mat-icon>\n @if (AIType === 0) {\n <span>Server</span>\n } @else {\n Local\n }\n </button>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"onSelectAIType(0)\">Server</button>\n <button mat-menu-item (click)=\"onSelectAIType(1)\">Local</button>\n </mat-menu>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" class=\"btn\">Ask Me</button>\n </div>\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 @if ((STREAM_AI_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n @if (AIType === 1) {\n <div style=\"color: red;\">\n You must have Ollama active and the 'phi3:latest' model to use this feature.\n </div>\n } @else {\n <span style=\"color: gray;\">\n Define the RestPath to the API endpoint that will handle the AI request.\n Use: 'ai/chat' for server\n </span>\n }\n\n <div>\n @if ((STREAM_AI$ | async); as data) {\n <div style=\"margin-top: 1rem; font-size: 1.2rem; border-radius: 1rem; border: black 1px solid; padding: 2rem;\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap; line-height: 1.6rem;\">{{data}}</p>\n </div>\n }\n </div>\n\n</div>\n\n<div style=\"margin-top: 1.5rem; margin-bottom: 1rem; line-height: 1.5rem;\">\n <mat-divider></mat-divider>\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 @if (disable.checked) {\n <span>\n Enable\n </span>\n } @else {\n Disable\n }\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}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i10.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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", "saveFileAs", "labels", "disabled"], outputs: ["completed", "failed"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
8960
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerDemoComponent, selector: "app-request-manager-demo", inputs: { server: "server", adapter: "adapter", mapper: "mapper" }, providers: [HTTPManagerService], 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\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\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\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\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 @for (task of headers.controls; track task; let i = $index) {\n <div [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 }\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 @if (failedState.checked) {\n <div 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 }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\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 }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked && !(isPending$ | async)) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\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 @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n @if ((GET$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n @if ((POST$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <h3>Include Record ID in the RestPath</h3>\n\n @if ((PUT$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 <h3>Include Record ID in the RestPath</h3>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n @if ((DELETE$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\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 @if ((STREAM$ | async); as data) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </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\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Records: {{ data.length }}\n </div>\n </div>\n }\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 <!-- Parallel Requests Section -->\n <div>\n <div style=\"display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;\">\n <h2 style=\"flex: 1; margin: 0;\">Parallel Requests</h2>\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"onExecuteParallelBatch()\"\n [disabled]=\"isParallelLoading\"\n style=\"min-width: 200px;\">\n <mat-icon>sync</mat-icon>\n <span style=\"margin-left: 8px;\">\n {{ isParallelLoading ? 'Loading...' : 'Fetch 5 Users' }}\n </span>\n </button>\n </div>\n\n <!-- Loading Indicator -->\n @if (isParallelLoading) {\n <div style=\"margin: 1rem 0;\">\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n <p style=\"margin-top: 0.5rem; color: #666;\">\n Executing parallel requests (concurrency: 3)...\n </p>\n </div>\n }\n\n <!-- Results -->\n @if (parallelResults) {\n <div style=\"margin: 1rem 0;\">\n <mat-card appearance=\"outlined\">\n <mat-card-content>\n <div style=\"display: grid; gap: 0.5rem;\">\n @for (result of parallelResults; track $index; let i = $index) {\n <div\n style=\"padding: 0.75rem; border-radius: 4px; border: 1px solid;\n {{ result ? 'background: #e3f2fd; border-color: #2196f3;' :\n 'background: #ffebee; border-color: #f44336;' }}\">\n @if (result) {\n <div style=\"display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;\">\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #2196f3; font-size: 18px;\">check_circle</mat-icon>\n <strong>User #{{ result.id }}:</strong>\n <span>{{ result.name }}</span>\n </div>\n <span style=\"color: #2196f3; font-weight: bold;\">Complete</span>\n </div>\n } @else {\n <div style=\"display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;\">\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #f44336; font-size: 18px;\">error</mat-icon>\n <strong>Request {{ i + 1 }}:</strong>\n <span>Failed</span>\n </div>\n <span style=\"color: #f44336; font-weight: bold;\">Error</span>\n </div>\n }\n </div>\n }\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n }\n\n <!-- Execution Metrics -->\n @if (parallelExecutionTime !== undefined) {\n <div style=\"background: #f5f5f5; padding: 1rem; border-radius: 4px; margin: 1rem 0;\">\n <div style=\"display: flex; gap: 2rem;\">\n <div>\n <strong>\u23F1Execution Time:</strong>\n <span style=\"margin-left: 0.5rem; color: #4caf50;\">\n {{ formatTime(parallelExecutionTime) }}\n </span>\n </div>\n <div>\n <strong>Mode:</strong>\n <span style=\"margin-left: 0.5rem;\">Parallel</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Error Display -->\n @if (parallelError) {\n <div style=\"margin-top: 1rem;\">\n <mat-error>{{ parallelError }}</mat-error>\n </div>\n }\n </div>\n\n <!-- Sequential Requests Section -->\n <div>\n <div style=\"display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;\">\n <h2 style=\"flex: 1; margin: 0;\">Sequential Requests</h2>\n <button\n mat-raised-button\n color=\"accent\"\n (click)=\"onExecuteSequentialBatch()\"\n [disabled]=\"isSequentialLoading\"\n style=\"min-width: 200px;\">\n <mat-icon>timeline</mat-icon>\n <span style=\"margin-left: 8px;\">\n {{ isSequentialLoading ? 'Loading...' : 'Fetch 5 Todos' }}\n </span>\n </button>\n </div>\n\n <!-- Loading Indicator -->\n @if (isSequentialLoading) {\n <div style=\"margin: 1rem 0;\">\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n <p style=\"margin-top: 0.5rem; color: #666;\">\n Executing sequential requests (one at a time)...\n </p>\n </div>\n }\n\n <!-- Results -->\n @if (sequentialResults) {\n <div style=\"margin: 1rem 0;\">\n <mat-card appearance=\"outlined\">\n <mat-card-content>\n <div style=\"display: grid; gap: 0.5rem;\">\n @for (result of sequentialResults; track $index; let i = $index) {\n <div\n style=\"padding: 0.75rem; border-radius: 4px; border: 1px solid;\n {{ result ? 'background: #e3f2fd; border-color: #2196f3;' :\n 'background: #ffebee; border-color: #f44336;' }}\">\n @if (result) {\n <div style=\"display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;\">\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #2196f3; font-size: 18px;\">check_circle</mat-icon>\n <strong>Todo #{{ result.id }}:</strong>\n <span style=\"flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\">\n {{ result.title }}\n </span>\n </div>\n </div>\n } @else {\n <div style=\"display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;\">\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #f44336; font-size: 18px;\">error</mat-icon>\n <strong>Request {{ i + 1 }}:</strong>\n <span>Failed</span>\n </div>\n <span style=\"color: #f44336; font-weight: bold;\">Error</span>\n </div>\n }\n </div>\n }\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n }\n\n <!-- Execution Metrics -->\n @if (sequentialExecutionTime !== undefined) {\n <div style=\"background: #f5f5f5; padding: 1rem; border-radius: 4px; margin: 1rem 0;\">\n <div style=\"display: flex; gap: 2rem;\">\n <div>\n <strong>Execution Time:</strong>\n <span style=\"margin-left: 0.5rem; color: #4caf50;\">\n {{ formatTime(sequentialExecutionTime) }}\n </span>\n </div>\n <div>\n <strong>Mode:</strong>\n <span style=\"margin-left: 0.5rem;\">Sequential</span>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Stream Mode Section -->\n <div>\n <div style=\"display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;\">\n <h2 style=\"flex: 1; margin: 0;\">Stream Mode (Real-time States)</h2>\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"onExecuteStreamBatch()\"\n [disabled]=\"isStreamLoading\"\n style=\"min-width: 200px;\">\n <mat-icon>auto_awesome</mat-icon>\n <span style=\"margin-left: 8px;\">\n {{ isStreamLoading ? 'Loading...' : 'Fetch 5 Posts' }}\n </span>\n </button>\n </div>\n\n <!-- Loading Indicator -->\n @if (isStreamLoading) {\n <div style=\"margin: 1rem 0;\">\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n <p style=\"margin-top: 0.5rem; color: #666;\">\n Executing parallel requests with real-time state updates...\n </p>\n </div>\n }\n\n <!-- Progress Bar -->\n @if (streamProgress) {\n <div style=\"background: #f5f5f5; padding: 1rem; border-radius: 4px; margin: 1rem 0;\">\n <div style=\"display: flex; gap: 2rem; margin-bottom: 0.5rem;\">\n <div>\n <strong>Execution Time:</strong>\n <span style=\"margin-left: 0.5rem; color: #4caf50;\">\n {{ formatTime(streamExecutionTime || 0) }}\n </span>\n </div>\n <div>\n <strong>Progress:</strong>\n <span style=\"margin-left: 0.5rem;\">\n {{ streamProgress.completed }} / {{ streamProgress.total }} completed\n </span>\n </div>\n <div>\n <strong>Pending:</strong>\n <span style=\"margin-left: 0.5rem;\">\n {{ streamProgress.pending }}\n </span>\n </div>\n <div>\n <strong>Failed:</strong>\n <span style=\"margin-left: 0.5rem;\">\n {{ streamProgress.failed }}\n </span>\n </div>\n </div>\n <mat-progress-bar\n mode=\"determinate\"\n [value]=\"streamProgress.percent\"\n color=\"accent\">\n </mat-progress-bar>\n <p style=\"margin-top: 0.5rem; text-align: right; color: #666;\">\n {{ streamProgress.percent }}%\n </p>\n </div>\n }\n\n <!-- Error Display -->\n @if (streamError) {\n <div style=\"margin-top: 1rem;\">\n <mat-error>{{ streamError }}</mat-error>\n </div>\n }\n\n <!-- Individual Request States -->\n @if (streamBatchStates.length > 0) {\n <div style=\"margin-top: 1rem;\">\n <mat-card appearance=\"outlined\">\n <mat-card-content>\n <div style=\"display: grid; gap: 0.5rem;\">\n @for (state of filteredStreamStates; track state.index; let i = $index) {\n <div\n style=\"padding: 0.75rem; border-radius: 4px; border: 1px solid;\n {{ isPendingState(state) ? 'background: #fff3e0; border-color: #ff9800;' :\n isSuccessState(state) ? 'background: #e3f2fd; border-color: #2196f3;' :\n 'background: #ffebee; border-color: #f44336;' }}\">\n @if (isPendingState(state)) {\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-spinner diameter=\"16\" style=\"margin-right: 0.5rem;\"></mat-spinner>\n <strong>Request {{ state.index + 1 }}:</strong>\n <span>Loading...</span>\n </div>\n } @else if (isSuccessState(state)) {\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #2196f3; font-size: 18px;\">check_circle</mat-icon>\n <strong>Post #{{ state.data.id }}:</strong>\n <span style=\"flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\">\n {{ state.data.title }}\n </span>\n </div>\n } @else {\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #f44336; font-size: 18px;\">error</mat-icon>\n <strong>Request {{ state.index + 1 }}:</strong>\n <span>Failed</span>\n <mat-chip style=\"margin-left: auto; font-size: 0.8em; background: #f44336; color: white;\">\n Error\n </mat-chip>\n </div>\n }\n </div>\n }\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n }\n </div>\n\n <!-- Comparison Info -->\n <div style=\"padding: 1rem; background: whitesmoke; border-radius: 4px; border: 1px solid #ccc;\">\n <h4 style=\"margin-top: 0;\">Key Differences</h4>\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;\">\n <div>\n <strong>Parallel:</strong>\n <ul style=\"margin: 0.5rem 0 0 1rem; padding: 0;\">\n <li>Faster execution (concurrent)</li>\n <li>Multiple requests simultaneously</li>\n <li>Results may complete out of order</li>\n <li>Best for: Independent requests</li>\n </ul>\n </div>\n <div>\n <strong>Sequential:</strong>\n <ul style=\"margin: 0.5rem 0 0 1rem; padding: 0;\">\n <li>Slower execution (one-by-one)</li>\n <li>Requests execute in order</li>\n <li>Results always in request order</li>\n <li>Best for: Dependent requests</li>\n </ul>\n </div>\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}.box{padding:10px;border:1px solid #ccc}.batch-demo-section{margin:2rem 0;padding:1.5rem;border:1px solid #e0e0e0;border-radius:8px;background:#fafafa}.batch-result-item{padding:.75rem;border-radius:4px;margin-bottom:.5rem;display:flex;align-items:center;gap:.5rem}.batch-result-item.success{background:#e8f5e9;border-left:3px solid #4caf50}.batch-result-item.error{background:#ffebee;border-left:3px solid #f44336}.execution-metrics{display:flex;gap:2rem;padding:1rem;background:#f5f5f5;border-radius:4px;margin:1rem 0}.execution-metrics>div{display:flex;align-items:center;gap:.5rem}.comparison-box{padding:1rem;background:#fff3e0;border-radius:4px;margin-top:2rem}.comparison-box h4{margin-top:0;margin-bottom:1rem}.comparison-box .comparison-grid{display:grid;grid-template-columns:1fr 1fr;gap:1rem}@media(max-width:768px){.comparison-box .comparison-grid{grid-template-columns:1fr}}.loading-indicator{margin:1rem 0}.result-card{margin-top:1rem}.result-card mat-card-content{padding:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i3$1.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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: i16.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i16.MatCardContent, selector: "mat-card-content" }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
8486
8961
  }
8487
8962
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerDemoComponent, decorators: [{
8488
8963
  type: Component,
8489
- args: [{ selector: 'app-request-manager-demo', providers: [HTTPManagerService], standalone: false, 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\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\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\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\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 @for (task of headers.controls; track task; let i = $index) {\n <div [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 }\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 @if (failedState.checked) {\n <div 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 }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\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 }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked && !(isPending$ | async)) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\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 @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n @if ((GET$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n @if ((POST$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <h3>Include Record ID in the RestPath</h3>\n\n @if ((PUT$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 <h3>Include Record ID in the RestPath</h3>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n @if ((DELETE$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\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 @if ((STREAM$ | async); as data) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8\">\n \n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\"> \n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </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 \n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Records: {{ data.length }}\n </div>\n </div>\n }\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; padding-top: .5rem;\">AI -@if (AIType === 1) {\n <span>STREAMING</span>\n } POST Request</h2>\n <div style=\"display: flex; gap: 1rem;\">\n <button mat-raised-button [matMenuTriggerFor]=\"menu\" style=\"min-width: 120px;\">\n <mat-icon>lan</mat-icon>\n @if (AIType === 0) {\n <span>Server</span>\n } @else {\n Local\n }\n </button>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"onSelectAIType(0)\">Server</button>\n <button mat-menu-item (click)=\"onSelectAIType(1)\">Local</button>\n </mat-menu>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" class=\"btn\">Ask Me</button>\n </div>\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 @if ((STREAM_AI_error$ | async); as stream_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ stream_error }}</mat-error>\n </div>\n }\n\n @if (AIType === 1) {\n <div style=\"color: red;\">\n You must have Ollama active and the 'phi3:latest' model to use this feature.\n </div>\n } @else {\n <span style=\"color: gray;\">\n Define the RestPath to the API endpoint that will handle the AI request.\n Use: 'ai/chat' for server\n </span>\n }\n\n <div>\n @if ((STREAM_AI$ | async); as data) {\n <div style=\"margin-top: 1rem; font-size: 1.2rem; border-radius: 1rem; border: black 1px solid; padding: 2rem;\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap; line-height: 1.6rem;\">{{data}}</p>\n </div>\n }\n </div>\n\n</div>\n\n<div style=\"margin-top: 1.5rem; margin-bottom: 1rem; line-height: 1.5rem;\">\n <mat-divider></mat-divider>\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 @if (disable.checked) {\n <span>\n Enable\n </span>\n } @else {\n Disable\n }\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}.box{padding:10px;border:1px solid #ccc}\n"] }]
8964
+ args: [{ selector: 'app-request-manager-demo', providers: [HTTPManagerService], standalone: false, 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\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\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\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\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 @for (task of headers.controls; track task; let i = $index) {\n <div [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 }\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 @if (failedState.checked) {\n <div 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 }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\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 }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if ((isPending$ | async)) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked && !(isPending$ | async)) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"(this.countdown$ | async)\"\n ></mat-progress-bar>\n }\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 @if ((GET_error$ | async); as get_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ get_error }}</mat-error>\n </div>\n }\n\n @if ((GET$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(GET$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((POST_error$ | async); as post_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ post_error }}</mat-error>\n </div>\n }\n\n @if ((POST$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(POST$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 @if ((PUT_error$ | async); as put_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ put_error }}</mat-error>\n </div>\n }\n\n <h3>Include Record ID in the RestPath</h3>\n\n @if ((PUT$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(PUT$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 <h3>Include Record ID in the RestPath</h3>\n\n @if ((DELETE_error$ | async); as delete_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ delete_error }}</mat-error>\n </div>\n }\n\n @if ((DELETE$ | async); as dataRecord) {\n <div style=\"margin-top: 1rem;\">\n <!-- <div [innerHTML]=\"(DELETE$ | async) | jsonv\"></div> -->\n {{ dataRecord | json }}\n </div>\n }\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 style=\"display: flex; gap: 1rem; align-items: center;\">\n <div style=\"display: flex; gap: 1rem; align-items: center;\">\n {{ streamType }}\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>data_usage</mat-icon>\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let item of streamTypes\" (click)=\"onStreamType(item.id)\">{{ item.value }}</button>\n </mat-menu>\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 @if ((STREAM$ | async); as data) {\n <div class=\"container\">\n <table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8\">\n\n <!-- Dynamic columns -->\n <ng-container *ngFor=\"let column of displayedColumns\" [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (isObject(element[column]); as objValue) {\n <pre style=\"margin: 0; font-size: 0.8em; white-space: pre-wrap;\">{{ objValue | json }}</pre>\n } @else {\n {{ element[column] }}\n }\n </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\n <!-- Debug info -->\n <div style=\"margin-top: 1rem; font-size: 0.8em; color: #666;\">\n Columns: {{ displayedColumns.join(', ') }} | Records: {{ data.length }}\n </div>\n </div>\n }\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 <!-- Parallel Requests Section -->\n <div>\n <div style=\"display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;\">\n <h2 style=\"flex: 1; margin: 0;\">Parallel Requests</h2>\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"onExecuteParallelBatch()\"\n [disabled]=\"isParallelLoading\"\n style=\"min-width: 200px;\">\n <mat-icon>sync</mat-icon>\n <span style=\"margin-left: 8px;\">\n {{ isParallelLoading ? 'Loading...' : 'Fetch 5 Users' }}\n </span>\n </button>\n </div>\n\n <!-- Loading Indicator -->\n @if (isParallelLoading) {\n <div style=\"margin: 1rem 0;\">\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n <p style=\"margin-top: 0.5rem; color: #666;\">\n Executing parallel requests (concurrency: 3)...\n </p>\n </div>\n }\n\n <!-- Results -->\n @if (parallelResults) {\n <div style=\"margin: 1rem 0;\">\n <mat-card appearance=\"outlined\">\n <mat-card-content>\n <div style=\"display: grid; gap: 0.5rem;\">\n @for (result of parallelResults; track $index; let i = $index) {\n <div\n style=\"padding: 0.75rem; border-radius: 4px; border: 1px solid;\n {{ result ? 'background: #e3f2fd; border-color: #2196f3;' :\n 'background: #ffebee; border-color: #f44336;' }}\">\n @if (result) {\n <div style=\"display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;\">\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #2196f3; font-size: 18px;\">check_circle</mat-icon>\n <strong>User #{{ result.id }}:</strong>\n <span>{{ result.name }}</span>\n </div>\n <span style=\"color: #2196f3; font-weight: bold;\">Complete</span>\n </div>\n } @else {\n <div style=\"display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;\">\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #f44336; font-size: 18px;\">error</mat-icon>\n <strong>Request {{ i + 1 }}:</strong>\n <span>Failed</span>\n </div>\n <span style=\"color: #f44336; font-weight: bold;\">Error</span>\n </div>\n }\n </div>\n }\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n }\n\n <!-- Execution Metrics -->\n @if (parallelExecutionTime !== undefined) {\n <div style=\"background: #f5f5f5; padding: 1rem; border-radius: 4px; margin: 1rem 0;\">\n <div style=\"display: flex; gap: 2rem;\">\n <div>\n <strong>\u23F1Execution Time:</strong>\n <span style=\"margin-left: 0.5rem; color: #4caf50;\">\n {{ formatTime(parallelExecutionTime) }}\n </span>\n </div>\n <div>\n <strong>Mode:</strong>\n <span style=\"margin-left: 0.5rem;\">Parallel</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Error Display -->\n @if (parallelError) {\n <div style=\"margin-top: 1rem;\">\n <mat-error>{{ parallelError }}</mat-error>\n </div>\n }\n </div>\n\n <!-- Sequential Requests Section -->\n <div>\n <div style=\"display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;\">\n <h2 style=\"flex: 1; margin: 0;\">Sequential Requests</h2>\n <button\n mat-raised-button\n color=\"accent\"\n (click)=\"onExecuteSequentialBatch()\"\n [disabled]=\"isSequentialLoading\"\n style=\"min-width: 200px;\">\n <mat-icon>timeline</mat-icon>\n <span style=\"margin-left: 8px;\">\n {{ isSequentialLoading ? 'Loading...' : 'Fetch 5 Todos' }}\n </span>\n </button>\n </div>\n\n <!-- Loading Indicator -->\n @if (isSequentialLoading) {\n <div style=\"margin: 1rem 0;\">\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n <p style=\"margin-top: 0.5rem; color: #666;\">\n Executing sequential requests (one at a time)...\n </p>\n </div>\n }\n\n <!-- Results -->\n @if (sequentialResults) {\n <div style=\"margin: 1rem 0;\">\n <mat-card appearance=\"outlined\">\n <mat-card-content>\n <div style=\"display: grid; gap: 0.5rem;\">\n @for (result of sequentialResults; track $index; let i = $index) {\n <div\n style=\"padding: 0.75rem; border-radius: 4px; border: 1px solid;\n {{ result ? 'background: #e3f2fd; border-color: #2196f3;' :\n 'background: #ffebee; border-color: #f44336;' }}\">\n @if (result) {\n <div style=\"display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;\">\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #2196f3; font-size: 18px;\">check_circle</mat-icon>\n <strong>Todo #{{ result.id }}:</strong>\n <span style=\"flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\">\n {{ result.title }}\n </span>\n </div>\n </div>\n } @else {\n <div style=\"display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;\">\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #f44336; font-size: 18px;\">error</mat-icon>\n <strong>Request {{ i + 1 }}:</strong>\n <span>Failed</span>\n </div>\n <span style=\"color: #f44336; font-weight: bold;\">Error</span>\n </div>\n }\n </div>\n }\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n }\n\n <!-- Execution Metrics -->\n @if (sequentialExecutionTime !== undefined) {\n <div style=\"background: #f5f5f5; padding: 1rem; border-radius: 4px; margin: 1rem 0;\">\n <div style=\"display: flex; gap: 2rem;\">\n <div>\n <strong>Execution Time:</strong>\n <span style=\"margin-left: 0.5rem; color: #4caf50;\">\n {{ formatTime(sequentialExecutionTime) }}\n </span>\n </div>\n <div>\n <strong>Mode:</strong>\n <span style=\"margin-left: 0.5rem;\">Sequential</span>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Stream Mode Section -->\n <div>\n <div style=\"display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;\">\n <h2 style=\"flex: 1; margin: 0;\">Stream Mode (Real-time States)</h2>\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"onExecuteStreamBatch()\"\n [disabled]=\"isStreamLoading\"\n style=\"min-width: 200px;\">\n <mat-icon>auto_awesome</mat-icon>\n <span style=\"margin-left: 8px;\">\n {{ isStreamLoading ? 'Loading...' : 'Fetch 5 Posts' }}\n </span>\n </button>\n </div>\n\n <!-- Loading Indicator -->\n @if (isStreamLoading) {\n <div style=\"margin: 1rem 0;\">\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n <p style=\"margin-top: 0.5rem; color: #666;\">\n Executing parallel requests with real-time state updates...\n </p>\n </div>\n }\n\n <!-- Progress Bar -->\n @if (streamProgress) {\n <div style=\"background: #f5f5f5; padding: 1rem; border-radius: 4px; margin: 1rem 0;\">\n <div style=\"display: flex; gap: 2rem; margin-bottom: 0.5rem;\">\n <div>\n <strong>Execution Time:</strong>\n <span style=\"margin-left: 0.5rem; color: #4caf50;\">\n {{ formatTime(streamExecutionTime || 0) }}\n </span>\n </div>\n <div>\n <strong>Progress:</strong>\n <span style=\"margin-left: 0.5rem;\">\n {{ streamProgress.completed }} / {{ streamProgress.total }} completed\n </span>\n </div>\n <div>\n <strong>Pending:</strong>\n <span style=\"margin-left: 0.5rem;\">\n {{ streamProgress.pending }}\n </span>\n </div>\n <div>\n <strong>Failed:</strong>\n <span style=\"margin-left: 0.5rem;\">\n {{ streamProgress.failed }}\n </span>\n </div>\n </div>\n <mat-progress-bar\n mode=\"determinate\"\n [value]=\"streamProgress.percent\"\n color=\"accent\">\n </mat-progress-bar>\n <p style=\"margin-top: 0.5rem; text-align: right; color: #666;\">\n {{ streamProgress.percent }}%\n </p>\n </div>\n }\n\n <!-- Error Display -->\n @if (streamError) {\n <div style=\"margin-top: 1rem;\">\n <mat-error>{{ streamError }}</mat-error>\n </div>\n }\n\n <!-- Individual Request States -->\n @if (streamBatchStates.length > 0) {\n <div style=\"margin-top: 1rem;\">\n <mat-card appearance=\"outlined\">\n <mat-card-content>\n <div style=\"display: grid; gap: 0.5rem;\">\n @for (state of filteredStreamStates; track state.index; let i = $index) {\n <div\n style=\"padding: 0.75rem; border-radius: 4px; border: 1px solid;\n {{ isPendingState(state) ? 'background: #fff3e0; border-color: #ff9800;' :\n isSuccessState(state) ? 'background: #e3f2fd; border-color: #2196f3;' :\n 'background: #ffebee; border-color: #f44336;' }}\">\n @if (isPendingState(state)) {\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-spinner diameter=\"16\" style=\"margin-right: 0.5rem;\"></mat-spinner>\n <strong>Request {{ state.index + 1 }}:</strong>\n <span>Loading...</span>\n </div>\n } @else if (isSuccessState(state)) {\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #2196f3; font-size: 18px;\">check_circle</mat-icon>\n <strong>Post #{{ state.data.id }}:</strong>\n <span style=\"flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\">\n {{ state.data.title }}\n </span>\n </div>\n } @else {\n <div style=\"display: flex; align-items: center; gap: 0.5rem;\">\n <mat-icon style=\"color: #f44336; font-size: 18px;\">error</mat-icon>\n <strong>Request {{ state.index + 1 }}:</strong>\n <span>Failed</span>\n <mat-chip style=\"margin-left: auto; font-size: 0.8em; background: #f44336; color: white;\">\n Error\n </mat-chip>\n </div>\n }\n </div>\n }\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n }\n </div>\n\n <!-- Comparison Info -->\n <div style=\"padding: 1rem; background: whitesmoke; border-radius: 4px; border: 1px solid #ccc;\">\n <h4 style=\"margin-top: 0;\">Key Differences</h4>\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;\">\n <div>\n <strong>Parallel:</strong>\n <ul style=\"margin: 0.5rem 0 0 1rem; padding: 0;\">\n <li>Faster execution (concurrent)</li>\n <li>Multiple requests simultaneously</li>\n <li>Results may complete out of order</li>\n <li>Best for: Independent requests</li>\n </ul>\n </div>\n <div>\n <strong>Sequential:</strong>\n <ul style=\"margin: 0.5rem 0 0 1rem; padding: 0;\">\n <li>Slower execution (one-by-one)</li>\n <li>Requests execute in order</li>\n <li>Results always in request order</li>\n <li>Best for: Dependent requests</li>\n </ul>\n </div>\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}.box{padding:10px;border:1px solid #ccc}.batch-demo-section{margin:2rem 0;padding:1.5rem;border:1px solid #e0e0e0;border-radius:8px;background:#fafafa}.batch-result-item{padding:.75rem;border-radius:4px;margin-bottom:.5rem;display:flex;align-items:center;gap:.5rem}.batch-result-item.success{background:#e8f5e9;border-left:3px solid #4caf50}.batch-result-item.error{background:#ffebee;border-left:3px solid #f44336}.execution-metrics{display:flex;gap:2rem;padding:1rem;background:#f5f5f5;border-radius:4px;margin:1rem 0}.execution-metrics>div{display:flex;align-items:center;gap:.5rem}.comparison-box{padding:1rem;background:#fff3e0;border-radius:4px;margin-top:2rem}.comparison-box h4{margin-top:0;margin-bottom:1rem}.comparison-box .comparison-grid{display:grid;grid-template-columns:1fr 1fr;gap:1rem}@media(max-width:768px){.comparison-box .comparison-grid{grid-template-columns:1fr}}.loading-indicator{margin:1rem 0}.result-card{margin-top:1rem}.result-card mat-card-content{padding:1rem}\n"] }]
8490
8965
  }], ctorParameters: () => [], propDecorators: { server: [{
8491
8966
  type: Input
8492
8967
  }], adapter: [{
@@ -8642,7 +9117,7 @@ class LocalStorageDemoComponent {
8642
9117
  this.localStorageManagerService.resetStore();
8643
9118
  }
8644
9119
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageDemoComponent, deps: [{ token: CONFIG_SETTINGS_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
8645
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", 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 &#123;<br>\n provide: APP_ID,<br>\n useValue: \"056991ac-3537-43ab-b5b9-83edf6554eff\",<br>\n &#125;\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$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i10$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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 }); }
9120
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", 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 &#123;<br>\n provide: APP_ID,<br>\n useValue: \"056991ac-3537-43ab-b5b9-83edf6554eff\",<br>\n &#125;\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$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.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", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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 }); }
8646
9121
  }
8647
9122
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageDemoComponent, decorators: [{
8648
9123
  type: Component,
@@ -9617,7 +10092,7 @@ class RequestManagerWsDemoComponent {
9617
10092
  this.stateService.updateConnection(this.server, this.wsServer, this.jwtToken, this.user, this.path);
9618
10093
  }
9619
10094
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerWsDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9620
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerWsDemoComponent, selector: "app-request-manager-ws-demo", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user", path: "path" }, ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2 style=\"display: flex;\">\n <span style=\"flex:1\">HTTP Request State Manager - Websockets</span>\n @if ((connectionStatus$ | async); as connected) {\n <span>\n WS -\n <span style=\"color: green;\">Connected</span>\n </span>\n } @else {\n <span style=\"color: red;\">Disconnected {{ attempts$ | async }} - {{ nextRetry$ |async }}</span>\n }\n </h2>\n\n <div>\n\n @if ((user$ | async); as userInfo) {\n <div>\n <mat-toolbar>\n <div style=\"display: flex; flex:1\">\n <div style=\"flex:1\">{{ userInfo.name }}</div>\n <div>({{ userInfo.ldap }})</div>\n </div>\n </mat-toolbar>\n </div>\n }\n\n @if ((isPending$ | async)) {\n <div>\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n </div>\n }\n\n <mat-tab-group animationDuration=\"0ms\" [selectedIndex]=\"1\">\n\n <mat-tab label=\"WS - Data Control\">\n <!-- DATA CONTROL -->\n <app-ws-data-control\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [path]=\"path\"\n ></app-ws-data-control>\n\n </mat-tab>\n\n <mat-tab label=\"WS - Messaging\">\n <!-- MESSAGING -->\n <app-ws-messaging\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [path]=\"path\"\n ></app-ws-messaging>\n\n </mat-tab>\n\n <mat-tab label=\"WS - Notifications\">\n <!-- WS - Notifications -->\n <app-ws-notifications\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n ></app-ws-notifications>\n </mat-tab>\n\n <mat-tab label=\"WS - Chats\" [disabled]=\"true\">\n <!-- WS - Chats -->\n <app-ws-chats></app-ws-chats>\n </mat-tab>\n\n <mat-tab label=\"WS - AI Messaging\" [disabled]=\"true\">\n <!-- WS - AI Messaging -->\n <app-ws-ai-messaging></app-ws-ai-messaging>\n </mat-tab>\n\n </mat-tab-group>\n</div>\n\n</div>\n\n", styles: [""], dependencies: [{ kind: "component", type: i1$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i1$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i10.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i3$2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: WsDataControlComponent, selector: "app-ws-data-control", inputs: ["server", "wsServer", "jwtToken", "user", "path"] }, { kind: "component", type: WsMessagingComponent, selector: "app-ws-messaging", inputs: ["server", "wsServer", "jwtToken", "user", "path"] }, { kind: "component", type: WsNotificationsComponent, selector: "app-ws-notifications", inputs: ["server", "wsServer", "jwtToken", "user"] }, { kind: "component", type: WsAiMessagingComponent, selector: "app-ws-ai-messaging" }, { kind: "component", type: WsChatsComponent, selector: "app-ws-chats" }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
10095
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerWsDemoComponent, selector: "app-request-manager-ws-demo", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user", path: "path" }, ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2 style=\"display: flex;\">\n <span style=\"flex:1\">HTTP Request State Manager - Websockets</span>\n @if ((connectionStatus$ | async); as connected) {\n <span>\n WS -\n <span style=\"color: green;\">Connected</span>\n </span>\n } @else {\n <span style=\"color: red;\">Disconnected {{ attempts$ | async }} - {{ nextRetry$ |async }}</span>\n }\n </h2>\n\n <div>\n\n @if ((user$ | async); as userInfo) {\n <div>\n <mat-toolbar>\n <div style=\"display: flex; flex:1\">\n <div style=\"flex:1\">{{ userInfo.name }}</div>\n <div>({{ userInfo.ldap }})</div>\n </div>\n </mat-toolbar>\n </div>\n }\n\n @if ((isPending$ | async)) {\n <div>\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n </div>\n }\n\n <mat-tab-group animationDuration=\"0ms\" [selectedIndex]=\"1\">\n\n <mat-tab label=\"WS - Data Control\">\n <!-- DATA CONTROL -->\n <app-ws-data-control\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [path]=\"path\"\n ></app-ws-data-control>\n\n </mat-tab>\n\n <mat-tab label=\"WS - Messaging\">\n <!-- MESSAGING -->\n <app-ws-messaging\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [path]=\"path\"\n ></app-ws-messaging>\n\n </mat-tab>\n\n <mat-tab label=\"WS - Notifications\">\n <!-- WS - Notifications -->\n <app-ws-notifications\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n ></app-ws-notifications>\n </mat-tab>\n\n <mat-tab label=\"WS - Chats\" [disabled]=\"true\">\n <!-- WS - Chats -->\n <app-ws-chats></app-ws-chats>\n </mat-tab>\n\n <mat-tab label=\"WS - AI Messaging\" [disabled]=\"true\">\n <!-- WS - AI Messaging -->\n <app-ws-ai-messaging></app-ws-ai-messaging>\n </mat-tab>\n\n </mat-tab-group>\n</div>\n\n</div>\n\n", styles: [""], dependencies: [{ kind: "component", type: i1$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i1$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i3$2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: WsDataControlComponent, selector: "app-ws-data-control", inputs: ["server", "wsServer", "jwtToken", "user", "path"] }, { kind: "component", type: WsMessagingComponent, selector: "app-ws-messaging", inputs: ["server", "wsServer", "jwtToken", "user", "path"] }, { kind: "component", type: WsNotificationsComponent, selector: "app-ws-notifications", inputs: ["server", "wsServer", "jwtToken", "user"] }, { kind: "component", type: WsAiMessagingComponent, selector: "app-ws-ai-messaging" }, { kind: "component", type: WsChatsComponent, selector: "app-ws-chats" }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
9621
10096
  }
9622
10097
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerWsDemoComponent, decorators: [{
9623
10098
  type: Component,
@@ -10051,7 +10526,7 @@ class LocalStorageSignalsDemoComponent {
10051
10526
  this.localStorageManagerService.resetStore();
10052
10527
  }
10053
10528
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageSignalsDemoComponent, deps: [{ token: CONFIG_SETTINGS_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
10054
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: LocalStorageSignalsDemoComponent, selector: "app-local-storage-signals-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;\">\n <span>Local Storage Manager</span>\n <span style=\"margin-left: .5rem;\">\n <mat-icon color=\"accent\">fiber_new</mat-icon>\n </span>\n </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() | json }}\n <div *ngIf=\"filterData(settings()) 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=\"storeSelected() as selectedStore\" 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;\">{{ selectedStore.name | uppercase }}</span></h3>\n <h3>SETTINGS: {{ localStorageManagerService.setting(selectedStore.name) ? (localStorageManagerService.setting(selectedStore.name)() | 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]=\"selectedStoreData()\"></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(selectedStore, 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 &#123;<br>\n provide: APP_ID,<br>\n useValue: \"056991ac-3537-43ab-b5b9-83edf6554eff\",<br>\n &#125;\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$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i10$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }], encapsulation: i0.ViewEncapsulation.None }); }
10529
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: LocalStorageSignalsDemoComponent, selector: "app-local-storage-signals-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;\">\n <span>Local Storage Manager</span>\n <span style=\"margin-left: .5rem;\">\n <mat-icon color=\"accent\">fiber_new</mat-icon>\n </span>\n </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() | json }}\n <div *ngIf=\"filterData(settings()) 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=\"storeSelected() as selectedStore\" 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;\">{{ selectedStore.name | uppercase }}</span></h3>\n <h3>SETTINGS: {{ localStorageManagerService.setting(selectedStore.name) ? (localStorageManagerService.setting(selectedStore.name)() | 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]=\"selectedStoreData()\"></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(selectedStore, 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 &#123;<br>\n provide: APP_ID,<br>\n useValue: \"056991ac-3537-43ab-b5b9-83edf6554eff\",<br>\n &#125;\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$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.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", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }], encapsulation: i0.ViewEncapsulation.None }); }
10055
10530
  }
10056
10531
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageSignalsDemoComponent, decorators: [{
10057
10532
  type: Component,
@@ -10397,7 +10872,7 @@ class RequestSignalsManagerDemoComponent {
10397
10872
  this.AIType = type;
10398
10873
  }
10399
10874
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestSignalsManagerDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10400
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestSignalsManagerDemoComponent, selector: "app-request-signals-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 <span>HTTP Request Signals Manager</span>\n <span style=\"margin-left: .5rem;\">\n <mat-icon color=\"accent\">fiber_new</mat-icon>\n </span>\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\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\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\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\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 @for (task of headers.controls; track task; let i = $index) {\n <div [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 }\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 @if (failedState.checked) {\n <div 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 }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\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 }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if (isPending()) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked && !isPending()) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"countdown()\"\n ></mat-progress-bar>\n }\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 @if (GET_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ GET_error }}</mat-error>\n </div>\n }\n\n @if (GET_result) {\n <div style=\"margin-top: 1rem;\">\n {{ GET_result | json }}\n </div>\n }\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 @if (POST_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ POST_error }}</mat-error>\n </div>\n }\n\n @if (POST_result) {\n <div style=\"margin-top: 1rem;\">\n {{ POST_result | json }}\n </div>\n }\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 @if (PUT_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ PUT_error }}</mat-error>\n </div>\n }\n\n <h3>Include Record ID in the RestPath</h3>\n\n @if (PUT_result) {\n <div style=\"margin-top: 1rem;\">\n {{ PUT_result | json }}\n </div>\n }\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 <h3>Include Record ID in the RestPath</h3>\n\n @if (DELETE_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ DELETE_error }}</mat-error>\n </div>\n }\n\n @if (DELETE_result) {\n <div style=\"margin-top: 1rem;\">\n {{ DELETE_result | json }}\n </div>\n }\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 @if (STREAM_result; as data) {\n <div 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 <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 <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 <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 <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n }\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; padding-top: .5rem;\">AI -@if (AIType === 1) {\n <span>STREAMING</span>\n } POST Request</h2>\n <div style=\"display: flex; gap: 1rem;\">\n <button mat-raised-button [matMenuTriggerFor]=\"menu\" style=\"min-width: 120px;\">\n <mat-icon>lan</mat-icon>\n @if (AIType === 0) {\n <span>Server</span>\n } @else {\n Local\n }\n </button>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"onSelectAIType(0)\">Server</button>\n <button mat-menu-item (click)=\"onSelectAIType(1)\">Local</button>\n </mat-menu>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" class=\"btn\">Ask Me</button>\n </div>\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 @if (STREAM_AI_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ STREAM_AI_error }}</mat-error>\n </div>\n }\n\n @if (AIType === 1) {\n <div style=\"color: red;\">\n You must have Ollama active and the 'phi3:latest' model to use this feature.\n </div>\n } @else {\n <span style=\"color: gray;\">\n Define the RestPath to the API endpoint that will handle the AI request.\n Use: 'ai/chat' for server\n </span>\n }\n\n <div>\n @if (STREAM_AI_result) {\n <div style=\"margin-top: 1rem; font-size: 1.2rem; border-radius: 1rem; border: black 1px solid; padding: 2rem;\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap; line-height: 1.6rem;\">{{STREAM_AI_result}}</p>\n </div>\n }\n </div>\n\n</div>\n\n<div style=\"margin-top: 1.5rem; margin-bottom: 1rem; line-height: 1.5rem;\">\n <mat-divider></mat-divider>\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 @if (disable.checked) {\n <span>\n Enable\n </span>\n } @else {\n Disable\n }\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}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i2$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i10.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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", "saveFileAs", "labels", "disabled"], outputs: ["completed", "failed"] }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
10875
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestSignalsManagerDemoComponent, selector: "app-request-signals-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 <span>HTTP Request Signals Manager</span>\n <span style=\"margin-left: .5rem;\">\n <mat-icon color=\"accent\">fiber_new</mat-icon>\n </span>\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\" #adapterSelect>\n <mat-option>None</mat-option>\n @for (adapter of sampleAdaptors; track adapter) {\n <mat-option [value]=\"adapter.value\">\n {{adapter.label}}\n </mat-option>\n }\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\" #mapperSelect>\n <mat-option>None</mat-option>\n @for (mapper of sampleMappers; track mapper) {\n <mat-option [value]=\"mapper.value\">\n {{mapper.label}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (adapterSelect.value || mapperSelect.value) {\n <div style=\"display: flex; margin-bottom: 2rem;\">\n <div style=\"flex:1\" class=\"box\">\n <h3>Adapter (Incoming)</h3>\n @if (adapterSelect.value) {\n <div>\n {{ props(adapterSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n <div style=\"flex:1\" class=\"box\">\n <h3>Mapper (Outgoing)</h3>\n @if (mapperSelect.value) {\n <div>\n {{ props(mapperSelect.value) | json }}\n </div>\n } @else {\n No Transformation\n }\n </div>\n </div>\n }\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 @for (task of headers.controls; track task; let i = $index) {\n <div [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 }\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 @if (failedState.checked) {\n <div 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 }\n </div>\n <div>\n <mat-slide-toggle #pollingState>Polling</mat-slide-toggle>\n @if (pollingState.checked) {\n <div>\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 }\n </div>\n </div>\n </div>\n\n <div style=\"margin-bottom: 1rem; margin-top: 2rem;\">\n @if (isPending()) {\n <mat-progress-bar mode=\"indeterminate\"\n ></mat-progress-bar>\n }\n @if (pollingState.checked && !isPending()) {\n <mat-progress-bar mode=\"determinate\"\n [value]=\"countdown()\"\n ></mat-progress-bar>\n }\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 @if (GET_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ GET_error }}</mat-error>\n </div>\n }\n\n @if (GET_result) {\n <div style=\"margin-top: 1rem;\">\n {{ GET_result | json }}\n </div>\n }\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 @if (POST_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ POST_error }}</mat-error>\n </div>\n }\n\n @if (POST_result) {\n <div style=\"margin-top: 1rem;\">\n {{ POST_result | json }}\n </div>\n }\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 @if (PUT_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ PUT_error }}</mat-error>\n </div>\n }\n\n <h3>Include Record ID in the RestPath</h3>\n\n @if (PUT_result) {\n <div style=\"margin-top: 1rem;\">\n {{ PUT_result | json }}\n </div>\n }\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 <h3>Include Record ID in the RestPath</h3>\n\n @if (DELETE_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ DELETE_error }}</mat-error>\n </div>\n }\n\n @if (DELETE_result) {\n <div style=\"margin-top: 1rem;\">\n {{ DELETE_result | json }}\n </div>\n }\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 @if (STREAM_result; as data) {\n <div 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 <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 <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 <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 <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n }\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; padding-top: .5rem;\">AI -@if (AIType === 1) {\n <span>STREAMING</span>\n } POST Request</h2>\n <div style=\"display: flex; gap: 1rem;\">\n <button mat-raised-button [matMenuTriggerFor]=\"menu\" style=\"min-width: 120px;\">\n <mat-icon>lan</mat-icon>\n @if (AIType === 0) {\n <span>Server</span>\n } @else {\n Local\n }\n </button>\n <mat-menu #menu=\"matMenu\">\n <button mat-menu-item (click)=\"onSelectAIType(0)\">Server</button>\n <button mat-menu-item (click)=\"onSelectAIType(1)\">Local</button>\n </mat-menu>\n <div>\n <button mat-raised-button (click)=\"onStreamPostRequest()\" class=\"btn\">Ask Me</button>\n </div>\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 @if (STREAM_AI_error) {\n <div style=\"margin-top: .5rem;\">\n <mat-error>{{ STREAM_AI_error }}</mat-error>\n </div>\n }\n\n @if (AIType === 1) {\n <div style=\"color: red;\">\n You must have Ollama active and the 'phi3:latest' model to use this feature.\n </div>\n } @else {\n <span style=\"color: gray;\">\n Define the RestPath to the API endpoint that will handle the AI request.\n Use: 'ai/chat' for server\n </span>\n }\n\n <div>\n @if (STREAM_AI_result) {\n <div style=\"margin-top: 1rem; font-size: 1.2rem; border-radius: 1rem; border: black 1px solid; padding: 2rem;\">\n <p style=\"margin-bottom: .5rem; white-space:pre-wrap; line-height: 1.6rem;\">{{STREAM_AI_result}}</p>\n </div>\n }\n </div>\n\n</div>\n\n<div style=\"margin-top: 1.5rem; margin-bottom: 1rem; line-height: 1.5rem;\">\n <mat-divider></mat-divider>\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 @if (disable.checked) {\n <span>\n Enable\n </span>\n } @else {\n Disable\n }\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}.box{padding:10px;border:1px solid #ccc}\n"], dependencies: [{ kind: "directive", type: i2$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", 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: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.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", "saveFileAs", "labels", "disabled"], outputs: ["completed", "failed"] }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
10401
10876
  }
10402
10877
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestSignalsManagerDemoComponent, decorators: [{
10403
10878
  type: Component,
@@ -10451,6 +10926,7 @@ class HttpRequestManagerModule {
10451
10926
  MatButtonToggleModule,
10452
10927
  MatAutocompleteModule,
10453
10928
  MatProgressBarModule,
10929
+ MatProgressSpinnerModule,
10454
10930
  MatSlideToggleModule,
10455
10931
  MatDividerModule,
10456
10932
  MatFormFieldModule,
@@ -10459,6 +10935,7 @@ class HttpRequestManagerModule {
10459
10935
  MatSlideToggleModule, i1.TranslateModule, MatSidenavModule,
10460
10936
  MatDatepickerModule,
10461
10937
  MatNativeDateModule,
10938
+ MatCardModule,
10462
10939
  FileDownloaderModule], exports: [HttpRequestServicesDemoComponent] }); }
10463
10940
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HttpRequestManagerModule, providers: [
10464
10941
  { provide: HTTP_INTERCEPTORS, useClass: WithCredentialsInterceptor, multi: true },
@@ -10483,6 +10960,7 @@ class HttpRequestManagerModule {
10483
10960
  MatButtonToggleModule,
10484
10961
  MatAutocompleteModule,
10485
10962
  MatProgressBarModule,
10963
+ MatProgressSpinnerModule,
10486
10964
  MatSlideToggleModule,
10487
10965
  MatDividerModule,
10488
10966
  MatFormFieldModule,
@@ -10493,6 +10971,7 @@ class HttpRequestManagerModule {
10493
10971
  MatSidenavModule,
10494
10972
  MatDatepickerModule,
10495
10973
  MatNativeDateModule,
10974
+ MatCardModule,
10496
10975
  FileDownloaderModule] }); }
10497
10976
  }
10498
10977
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HttpRequestManagerModule, decorators: [{
@@ -10513,6 +10992,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10513
10992
  MatButtonToggleModule,
10514
10993
  MatAutocompleteModule,
10515
10994
  MatProgressBarModule,
10995
+ MatProgressSpinnerModule,
10516
10996
  MatSlideToggleModule,
10517
10997
  MatDividerModule,
10518
10998
  MatFormFieldModule,
@@ -10523,6 +11003,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10523
11003
  MatSidenavModule,
10524
11004
  MatDatepickerModule,
10525
11005
  MatNativeDateModule,
11006
+ MatCardModule,
10526
11007
  FileDownloaderModule,
10527
11008
  // MessengerChatModule,
10528
11009
  // StoreStateManagerModule
@@ -10696,5 +11177,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
10696
11177
  * Generated bundle index. Do not edit.
10697
11178
  */
10698
11179
 
10699
- export { ApiRequest, AppService, AsymmetricalEncryptionService, CONFIG_SETTINGS_TOKEN, ChannelType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsDemoComponent, LocalStorageSignalsManagerService, LoggerService, NotificationMessage, PathQueryService, PublicMessage, Random, RandomHSLColor, RandomHexColor, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomPaletteColor, RandomSignature, RandomStr, RandomVisibleColor, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, StateMessage, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, StoreStateManagerSignalsService, StoreStateSignalsDemoComponent, StreamType, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UserData, UtilsService, WSOptions, WebSocketMessageService, WithCredentialsInterceptor, countdown, createChannelName, delayedRetry, requestPolling, requestStreaming, streamAI, streamAuto, streamEvents, streamJSON, streamNDJSON };
11180
+ export { ApiRequest, AppService, AsymmetricalEncryptionService, BatchOptions, BatchResult, CONFIG_SETTINGS_TOKEN, ChannelType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsDemoComponent, LocalStorageSignalsManagerService, LoggerService, NotificationMessage, PathQueryService, PublicMessage, Random, RandomHSLColor, RandomHexColor, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomPaletteColor, RandomSignature, RandomStr, RandomVisibleColor, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, StateMessage, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, StoreStateManagerSignalsService, StoreStateSignalsDemoComponent, StreamType, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UserData, UtilsService, WSOptions, WebSocketMessageService, WithCredentialsInterceptor, calculateBatchProgress, countdown, createChannelName, delayedRetry, isErrorState, isPendingState, isSuccessState, requestPolling, requestStreaming, streamAI, streamAuto, streamEvents, streamJSON, streamNDJSON };
10700
11181
  //# sourceMappingURL=http-request-manager.mjs.map