http-request-manager 18.7.9 → 18.7.11

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.
@@ -11,41 +11,41 @@ import * as i1 from '@ngx-translate/core';
11
11
  import { TranslateModule } from '@ngx-translate/core';
12
12
  import * as i1$1 from '@angular/common';
13
13
  import { CommonModule } from '@angular/common';
14
- import * as i1$2 from '@angular/forms';
14
+ import * as i2$1 from '@angular/forms';
15
15
  import { FormBuilder, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
16
16
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
17
- import * as i2$1 from '@angular/material/button';
17
+ import * as i3 from '@angular/material/button';
18
18
  import { MatButtonModule } from '@angular/material/button';
19
19
  import * as i3$1 from '@angular/material/chips';
20
20
  import { MatChipsModule } from '@angular/material/chips';
21
- import * as i11 from '@angular/material/divider';
21
+ import * as i12 from '@angular/material/divider';
22
22
  import { MatDividerModule } from '@angular/material/divider';
23
- import * as i3 from '@angular/material/form-field';
23
+ import * as i4 from '@angular/material/form-field';
24
24
  import { MatFormFieldModule } from '@angular/material/form-field';
25
- import * as i6 from '@angular/material/icon';
25
+ import * as i8 from '@angular/material/icon';
26
26
  import { MatIconModule } from '@angular/material/icon';
27
- import * as i12 from '@angular/material/input';
27
+ import * as i13 from '@angular/material/input';
28
28
  import { MatInputModule } from '@angular/material/input';
29
- import * as i9$1 from '@angular/material/progress-bar';
29
+ import * as i10$1 from '@angular/material/progress-bar';
30
30
  import { MatProgressBarModule } from '@angular/material/progress-bar';
31
- import * as i4 from '@angular/material/select';
31
+ import * as i4$1 from '@angular/material/select';
32
32
  import { MatSelectModule } from '@angular/material/select';
33
33
  import { MatSidenavModule } from '@angular/material/sidenav';
34
- import * as i10$1 from '@angular/material/slide-toggle';
34
+ import * as i11 from '@angular/material/slide-toggle';
35
35
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
36
- import * as i6$1 from '@angular/material/menu';
36
+ import * as i7 from '@angular/material/menu';
37
37
  import { MatMenuModule } from '@angular/material/menu';
38
38
  import * as i3$2 from '@angular/material/toolbar';
39
39
  import { MatToolbarModule } from '@angular/material/toolbar';
40
- import * as i7 from '@angular/material/table';
40
+ import * as i9 from '@angular/material/table';
41
41
  import { MatTableModule } from '@angular/material/table';
42
42
  import * as i10 from '@angular/material/button-toggle';
43
43
  import { MatButtonToggleModule } from '@angular/material/button-toggle';
44
- import * as i9 from '@angular/material/datepicker';
44
+ import * as i9$1 from '@angular/material/datepicker';
45
45
  import { MatDatepickerModule } from '@angular/material/datepicker';
46
- import * as i5 from '@angular/material/core';
46
+ import * as i6 from '@angular/material/core';
47
47
  import { MatNativeDateModule } from '@angular/material/core';
48
- import * as i1$3 from '@angular/material/tabs';
48
+ import * as i1$2 from '@angular/material/tabs';
49
49
  import { MatTabsModule } from '@angular/material/tabs';
50
50
  import * as i2 from '@angular/material/progress-spinner';
51
51
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@@ -459,6 +459,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
459
459
  */
460
460
  const CONFIG_SETTINGS_TOKEN = new InjectionToken('http.config');
461
461
 
462
+ /**
463
+ * Enum representing valid streaming format types
464
+ *
465
+ * This enum defines all supported streaming formats for HTTP requests.
466
+ * Each enum value corresponds to a specific data format and parsing strategy.
467
+ */
468
+ var StreamType;
469
+ (function (StreamType) {
470
+ StreamType["JSON"] = "json";
471
+ StreamType["NDJSON"] = "ndjson";
472
+ StreamType["AI_STREAMING"] = "ai_streaming";
473
+ StreamType["EVENT_STREAM"] = "event_stream";
474
+ StreamType["AUTO"] = "auto";
475
+ })(StreamType || (StreamType = {}));
476
+
462
477
  class HeadersService {
463
478
  constructor() {
464
479
  this.headers = {};
@@ -529,6 +544,75 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
529
544
  }]
530
545
  }] });
531
546
 
547
+ /**
548
+ * Generate a random hex color code
549
+ * @returns A random hex color string (e.g., "#FF5733")
550
+ */
551
+ const RandomHexColor = () => {
552
+ // Generate a random number between 0 and 16777215 (0xFFFFFF)
553
+ const randomColor = Math.floor(Math.random() * 16777215);
554
+ // Convert to hexadecimal and pad with zeros to ensure 6 digits
555
+ const hexColor = randomColor.toString(16).padStart(6, '0');
556
+ // Return with # prefix
557
+ return `#${hexColor}`;
558
+ };
559
+ /**
560
+ * Generate a random hex color with constraints to ensure good visibility
561
+ * @param options Optional constraints for color generation
562
+ * @returns A random hex color string with good contrast
563
+ */
564
+ const RandomVisibleColor = (options) => {
565
+ const minBrightness = options?.minBrightness ?? 50;
566
+ const maxBrightness = options?.maxBrightness ?? 200;
567
+ // Generate RGB values within the specified brightness range
568
+ const r = Math.floor(Math.random() * (maxBrightness - minBrightness) + minBrightness);
569
+ const g = Math.floor(Math.random() * (maxBrightness - minBrightness) + minBrightness);
570
+ const b = Math.floor(Math.random() * (maxBrightness - minBrightness) + minBrightness);
571
+ // Convert to hex and pad with zeros
572
+ const toHex = (n) => n.toString(16).padStart(2, '0');
573
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
574
+ };
575
+ /**
576
+ * Generate a random color from a predefined palette
577
+ * @returns A hex color from a set of visually distinct colors
578
+ */
579
+ const RandomPaletteColor = () => {
580
+ const colorPalette = [
581
+ '#FF6B6B', // Coral
582
+ '#4ECDC4', // Turquoise
583
+ '#45B7D1', // Sky Blue
584
+ '#FFBE0B', // Amber
585
+ '#FB5607', // Orange
586
+ '#8338EC', // Violet
587
+ '#3A86FF', // Azure
588
+ '#38B000', // Green
589
+ '#9D4EDD', // Purple
590
+ '#FF006E', // Pink
591
+ '#0077B6', // Blue
592
+ '#2A9D8F' // Teal
593
+ ];
594
+ const randomIndex = Math.floor(Math.random() * colorPalette.length);
595
+ return colorPalette[randomIndex];
596
+ };
597
+ /**
598
+ * Generate a random HSL color
599
+ * @param options Optional constraints for HSL generation
600
+ * @returns A random HSL color string (e.g., "hsl(120, 100%, 50%)")
601
+ */
602
+ const RandomHSLColor = (options) => {
603
+ // Full range for hue (0-360)
604
+ const hue = Math.floor(Math.random() * 361);
605
+ // Default or custom saturation range
606
+ const satMin = options?.saturation?.[0] ?? 50;
607
+ const satMax = options?.saturation?.[1] ?? 100;
608
+ const saturation = Math.floor(Math.random() * (satMax - satMin + 1) + satMin);
609
+ // Default or custom lightness range
610
+ const lightMin = options?.lightness?.[0] ?? 40;
611
+ const lightMax = options?.lightness?.[1] ?? 80;
612
+ const lightness = Math.floor(Math.random() * (lightMax - lightMin + 1) + lightMin);
613
+ return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
614
+ };
615
+
532
616
  class AsymmetricalEncryptionService {
533
617
  constructor() { }
534
618
  generateKeyPair(modulusLength = 2048) {
@@ -711,21 +795,326 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
711
795
  }]
712
796
  }], ctorParameters: () => [] });
713
797
 
714
- function requestStreaming() {
715
- return input$ => input$.pipe(filter((event) => event.type === HttpEventType.DownloadProgress || event.type === HttpEventType.Response), map((event) => {
798
+ /**
799
+ * COMPREHENSIVE REQUEST STREAMING OPERATOR - FULLY ABSTRACTED
800
+ *
801
+ * Single function that handles ALL streaming formats without hardcoded assumptions:
802
+ * - JSON format (Individual JSON objects)
803
+ * - NDJSON format (Newline delimited JSON)
804
+ * - AI streaming format (Real-time AI responses)
805
+ * - Server-Sent Events format
806
+ * - Auto-detection mode
807
+ *
808
+ * Usage:
809
+ * this.http.get(url, options).pipe(requestStreaming()).subscribe(data => {...})
810
+ * this.http.get(url, options).pipe(requestStreaming({ streamType: StreamType.NDJSON })).subscribe(data => {...})
811
+ */
812
+ function requestStreaming(config) {
813
+ let buffer = '';
814
+ let contentType = '';
815
+ let streamConfig = config || { streamType: StreamType.AI_STREAMING };
816
+ return input$ => input$.pipe(
817
+ // Filter only streaming-related events
818
+ filter((event) => event.type === HttpEventType.DownloadProgress ||
819
+ event.type === HttpEventType.Response ||
820
+ event.type === HttpEventType.ResponseHeader),
821
+ // Process each streaming event
822
+ map((event) => {
823
+ // Capture content type from response headers
824
+ if (event.type === HttpEventType.ResponseHeader) {
825
+ contentType = event.headers?.get('content-type') || '';
826
+ return null;
827
+ }
828
+ // Handle download progress (streaming chunks)
716
829
  if (event.type === HttpEventType.DownloadProgress) {
717
- return event.partialText || '';
830
+ if (event.partialText) {
831
+ buffer += event.partialText;
832
+ return parseStreamData(buffer, contentType, streamConfig);
833
+ }
718
834
  }
835
+ // Handle final response
719
836
  else if (event.type === HttpEventType.Response) {
720
- return event.body;
837
+ if (event.body) {
838
+ buffer += event.body;
839
+ return parseStreamData(buffer, contentType, streamConfig);
840
+ }
841
+ }
842
+ return null;
843
+ }),
844
+ // Filter out null results
845
+ filter(result => result !== null));
846
+ }
847
+ /**
848
+ * Main streaming data parser - handles ALL formats based on streamType
849
+ */
850
+ function parseStreamData(buffer, contentType, config) {
851
+ const results = [];
852
+ if (!buffer.trim()) {
853
+ return results;
854
+ }
855
+ // Determine parsing format based on streamType and content type
856
+ const format = config.streamType === StreamType.AI_STREAMING ? detectFormat(buffer, contentType) : config.streamType;
857
+ switch (format) {
858
+ case StreamType.NDJSON:
859
+ return parseNdjson(buffer, config);
860
+ case StreamType.JSON:
861
+ return parseJsonObjects(buffer, config);
862
+ case StreamType.AI_STREAMING:
863
+ return parseAiStreaming(buffer, config);
864
+ case StreamType.EVENT_STREAM:
865
+ return parseEventStream(buffer, config);
866
+ default:
867
+ return autoParse(buffer, contentType, config);
868
+ }
869
+ }
870
+ /**
871
+ * Parse NDJSON format (JSON objects per line)
872
+ */
873
+ function parseNdjson(buffer, config) {
874
+ const results = [];
875
+ const lines = buffer.split('\n').filter(line => line.trim());
876
+ lines.forEach(line => {
877
+ const trimmedLine = line.trim();
878
+ if (trimmedLine && trimmedLine.startsWith('{') && trimmedLine.endsWith('}')) {
879
+ try {
880
+ const parsed = JSON.parse(trimmedLine);
881
+ if (config.addMetadata !== false) {
882
+ results.push({
883
+ ...parsed,
884
+ _streamType: 'ndjson_record',
885
+ _format: StreamType.NDJSON,
886
+ _timestamp: new Date().toISOString()
887
+ });
888
+ }
889
+ else {
890
+ results.push(parsed);
891
+ }
892
+ }
893
+ catch (e) {
894
+ console.warn('Failed to parse NDJSON line:', trimmedLine.substring(0, 100));
895
+ }
896
+ }
897
+ });
898
+ return results;
899
+ }
900
+ /**
901
+ * Parse individual JSON objects
902
+ */
903
+ function parseJsonObjects(buffer, config) {
904
+ const results = [];
905
+ const jsonObjects = extractJsonObjects(buffer);
906
+ jsonObjects.forEach(jsonStr => {
907
+ try {
908
+ const parsed = JSON.parse(jsonStr);
909
+ if (config.addMetadata !== false) {
910
+ results.push({
911
+ ...parsed,
912
+ _streamType: 'json_object',
913
+ _format: StreamType.JSON,
914
+ _timestamp: new Date().toISOString()
915
+ });
916
+ }
917
+ else {
918
+ results.push(parsed);
919
+ }
721
920
  }
722
- }), map((data) => {
723
- if (typeof data === 'string') {
724
- const matches = data.match(/{[^}]+}/g) || [];
725
- return (matches.length > 0) ? matches.map(match => JSON.parse(match)) : data;
921
+ catch (e) {
922
+ console.warn('Failed to parse JSON object:', jsonStr.substring(0, 100));
726
923
  }
727
- return data;
728
- }));
924
+ });
925
+ return results;
926
+ }
927
+ /**
928
+ * Parse AI streaming format
929
+ */
930
+ function parseAiStreaming(buffer, config) {
931
+ const results = [];
932
+ const jsonObjects = extractJsonObjects(buffer);
933
+ jsonObjects.forEach(jsonStr => {
934
+ try {
935
+ const parsed = JSON.parse(jsonStr);
936
+ // Validate AI streaming format
937
+ if (parsed.type && ['ai_thinking', 'ai_response', 'ai_suggestion', 'ai_status'].includes(parsed.type)) {
938
+ if (config.addMetadata !== false) {
939
+ results.push({
940
+ ...parsed,
941
+ _streamType: 'ai_chunk',
942
+ _format: StreamType.AI_STREAMING,
943
+ _timestamp: new Date().toISOString()
944
+ });
945
+ }
946
+ else {
947
+ results.push(parsed);
948
+ }
949
+ }
950
+ }
951
+ catch (e) {
952
+ console.warn('Failed to parse AI streaming chunk:', jsonStr.substring(0, 100));
953
+ }
954
+ });
955
+ return results;
956
+ }
957
+ /**
958
+ * Parse Server-Sent Events format
959
+ */
960
+ function parseEventStream(buffer, config) {
961
+ const results = [];
962
+ const events = buffer.split('\n\n').filter(event => event.trim());
963
+ events.forEach(event => {
964
+ const lines = event.split('\n');
965
+ let eventData = '';
966
+ lines.forEach(line => {
967
+ if (line.startsWith('data: ')) {
968
+ eventData += line.substring(6);
969
+ }
970
+ });
971
+ if (eventData) {
972
+ try {
973
+ const parsed = JSON.parse(eventData);
974
+ if (config.addMetadata !== false) {
975
+ results.push({
976
+ ...parsed,
977
+ _streamType: 'event_stream',
978
+ _format: StreamType.EVENT_STREAM,
979
+ _timestamp: new Date().toISOString()
980
+ });
981
+ }
982
+ else {
983
+ results.push(parsed);
984
+ }
985
+ }
986
+ catch (e) {
987
+ results.push({
988
+ content: eventData,
989
+ _streamType: 'event_stream',
990
+ _format: StreamType.EVENT_STREAM,
991
+ _timestamp: new Date().toISOString()
992
+ });
993
+ }
994
+ }
995
+ });
996
+ return results;
997
+ }
998
+ /**
999
+ * Auto-detect and parse unknown formats
1000
+ */
1001
+ function autoParse(buffer, contentType, config) {
1002
+ // Check content type hints
1003
+ if (contentType.includes('application/x-ndjson') || isNdjsonFormat(buffer)) {
1004
+ return parseNdjson(buffer, config);
1005
+ }
1006
+ if (contentType.includes('application/json') || buffer.includes('{')) {
1007
+ // Check if it looks like AI streaming
1008
+ if (buffer.includes('"type":') && buffer.includes('"ai_')) {
1009
+ return parseAiStreaming(buffer, config);
1010
+ }
1011
+ return parseJsonObjects(buffer, config);
1012
+ }
1013
+ if (contentType.includes('text/event-stream')) {
1014
+ return parseEventStream(buffer, config);
1015
+ }
1016
+ // Fallback: try to parse as JSON, otherwise treat as text
1017
+ const jsonObjects = extractJsonObjects(buffer);
1018
+ if (jsonObjects.length > 0) {
1019
+ return parseJsonObjects(buffer, config);
1020
+ }
1021
+ else {
1022
+ // Return as text chunks
1023
+ return buffer.split('\n').filter(line => line.trim()).map(line => ({
1024
+ content: line.trim(),
1025
+ _streamType: 'text',
1026
+ _format: 'plain',
1027
+ _timestamp: new Date().toISOString()
1028
+ }));
1029
+ }
1030
+ }
1031
+ /**
1032
+ * Detect streaming format from content
1033
+ */
1034
+ function detectFormat(buffer, contentType) {
1035
+ if (contentType.includes('application/x-ndjson') || isNdjsonFormat(buffer)) {
1036
+ return StreamType.NDJSON;
1037
+ }
1038
+ if (contentType.includes('text/event-stream')) {
1039
+ return StreamType.EVENT_STREAM;
1040
+ }
1041
+ if (contentType.includes('application/json') || buffer.includes('{')) {
1042
+ // Check if it looks like AI streaming
1043
+ if (buffer.includes('"type":') && buffer.includes('"ai_')) {
1044
+ return StreamType.AI_STREAMING;
1045
+ }
1046
+ return StreamType.JSON;
1047
+ }
1048
+ return StreamType.JSON; // Default
1049
+ }
1050
+ /**
1051
+ * Check if buffer is NDJSON format
1052
+ */
1053
+ function isNdjsonFormat(buffer) {
1054
+ const lines = buffer.split('\n').filter(line => line.trim());
1055
+ const jsonLines = lines.filter(line => line.trim().startsWith('{') && line.trim().endsWith('}'));
1056
+ return jsonLines.length > 1 || (lines.length > 1 && jsonLines.length > 0);
1057
+ }
1058
+ /**
1059
+ * Extract individual JSON objects from text
1060
+ */
1061
+ function extractJsonObjects(text) {
1062
+ const objects = [];
1063
+ let braceCount = 0;
1064
+ let currentObject = '';
1065
+ let inString = false;
1066
+ let escaped = false;
1067
+ for (let i = 0; i < text.length; i++) {
1068
+ const char = text[i];
1069
+ if (escaped) {
1070
+ currentObject += char;
1071
+ escaped = false;
1072
+ continue;
1073
+ }
1074
+ if (char === '\\') {
1075
+ escaped = true;
1076
+ currentObject += char;
1077
+ continue;
1078
+ }
1079
+ if (char === '"' && !escaped) {
1080
+ inString = !inString;
1081
+ }
1082
+ if (!inString) {
1083
+ if (char === '{')
1084
+ braceCount++;
1085
+ else if (char === '}')
1086
+ braceCount--;
1087
+ }
1088
+ currentObject += char;
1089
+ if (braceCount === 0 && currentObject.trim()) {
1090
+ objects.push(currentObject.trim());
1091
+ currentObject = '';
1092
+ }
1093
+ }
1094
+ return objects;
1095
+ }
1096
+ /**
1097
+ * Convenience functions for common use cases
1098
+ */
1099
+ // Stream with JSON format
1100
+ function streamJSON() {
1101
+ return requestStreaming({ streamType: StreamType.JSON });
1102
+ }
1103
+ // Stream with NDJSON format
1104
+ function streamNDJSON() {
1105
+ return requestStreaming({ streamType: StreamType.NDJSON });
1106
+ }
1107
+ // Stream AI responses
1108
+ function streamAI() {
1109
+ return requestStreaming({ streamType: StreamType.AI_STREAMING });
1110
+ }
1111
+ // Stream Server-Sent Events
1112
+ function streamEvents() {
1113
+ return requestStreaming({ streamType: StreamType.EVENT_STREAM });
1114
+ }
1115
+ // Auto-detect streaming format
1116
+ function streamAuto() {
1117
+ return requestStreaming({ streamType: StreamType.AUTO });
729
1118
  }
730
1119
 
731
1120
  class ChannelInfo {
@@ -1128,7 +1517,7 @@ class RequestService extends WebsocketService {
1128
1517
  const headers = this.buildCombinedHeaders(options);
1129
1518
  this.isPending.next(true);
1130
1519
  return (options.stream)
1131
- ? this.http.get(urlPath, headers).pipe(requestStreaming(), this.handleFinalize())
1520
+ ? this.http.get(urlPath, headers).pipe(requestStreaming({ streamType: options.streamType || StreamType.AI_STREAMING }), this.handleFinalize())
1132
1521
  : this.http.get(urlPath, headers).pipe(this.request(options));
1133
1522
  }
1134
1523
  createRecordRequest(options, data) {
@@ -1136,7 +1525,7 @@ class RequestService extends WebsocketService {
1136
1525
  const headers = this.buildCombinedHeaders(options);
1137
1526
  this.isPending.next(true);
1138
1527
  return (options.stream)
1139
- ? this.http.post(urlPath, data, headers).pipe(requestStreaming(), this.handleFinalize())
1528
+ ? this.http.post(urlPath, data, headers).pipe(requestStreaming({ streamType: options.streamType || StreamType.AI_STREAMING }), this.handleFinalize())
1140
1529
  : this.http.post(urlPath, data, headers).pipe(this.request(options));
1141
1530
  }
1142
1531
  updateRecordRequest(options, data) {
@@ -1958,7 +2347,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1958
2347
  }] }] });
1959
2348
 
1960
2349
  class ApiRequest {
1961
- constructor(server = '', path, headers, adapter, mapper, polling, retry, stream, displayError, saveAs, fileContentHeader, ws) {
2350
+ constructor(server = '', path, headers, adapter, mapper, polling, retry, stream, streamType, displayError, saveAs, fileContentHeader, ws) {
1962
2351
  this.server = server;
1963
2352
  this.path = path;
1964
2353
  this.headers = headers;
@@ -1967,6 +2356,7 @@ class ApiRequest {
1967
2356
  this.polling = polling;
1968
2357
  this.retry = retry;
1969
2358
  this.stream = stream;
2359
+ this.streamType = streamType;
1970
2360
  this.displayError = displayError;
1971
2361
  this.saveAs = saveAs;
1972
2362
  this.fileContentHeader = fileContentHeader;
@@ -1974,7 +2364,7 @@ class ApiRequest {
1974
2364
  }
1975
2365
  static adapt(item) {
1976
2366
  const server = Array.isArray(item?.server) ? item.server.join('/') : item?.server || '';
1977
- return new ApiRequest(server, (item?.path) ? item.path : [], (item?.headers) ? item.headers : {}, item?.adapter, item?.mapper, item?.polling ? Math.floor(item.polling) : 0, item?.retry ? RetryOptions.adapt(item.retry) : RetryOptions.adapt(), (item?.stream) ? item.stream : false, (item?.displayError) ? item.displayError : false, item?.saveAs, item?.fileContentHeader, item?.ws);
2367
+ return new ApiRequest(server, (item?.path) ? item.path : [], (item?.headers) ? item.headers : {}, item?.adapter, item?.mapper, item?.polling ? Math.floor(item.polling) : 0, item?.retry ? RetryOptions.adapt(item.retry) : RetryOptions.adapt(), (item?.stream) ? item.stream : false, item?.streamType || StreamType.AI_STREAMING, (item?.displayError) ? item.displayError : false, item?.saveAs, item?.fileContentHeader, item?.ws);
1978
2368
  }
1979
2369
  }
1980
2370
 
@@ -3111,13 +3501,6 @@ class HTTPManagerStateService extends ComponentStore {
3111
3501
  }
3112
3502
  switch (message.type) {
3113
3503
  case 'channelsList':
3114
- console.log('💬 Channels:', message.channels);
3115
- // this.channelList = message.channels
3116
- // if (this.channelList.includes(wsOptions.id)) {
3117
- // this.httpManagerService.subscribeToChannel(wsOptions.id)
3118
- // } else {
3119
- // this.httpManagerService.createChannel(wsOptions.id)
3120
- // }
3121
3504
  this.channels.next(message.channels);
3122
3505
  break;
3123
3506
  case 'subscribed':
@@ -4247,7 +4630,7 @@ class DownloadFileComponent {
4247
4630
  this.subscriptions.unsubscribe();
4248
4631
  }
4249
4632
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DownloadFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4250
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: DownloadFileComponent, selector: "app-download-file", inputs: { event: "event", displayError: "displayError", diameter: "diameter", mode: "mode", isPending: "isPending", active: "active", disabled: "disabled", progress: "progress", hasError: "hasError" }, outputs: { error: "error" }, ngImport: i0, template: "@if (!isPending) {\n @if (hasError) {\n <div class=\"width center-txt\" style=\"margin-bottom: 4px;\">\n <mat-icon color=\"warn\" class=\"warn-icon\">warning</mat-icon>\n </div>\n } @else {\n @if (active) {\n <div class=\"container-obj\">\n <div class=\"centered-obj-div\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n </div>\n } @else {\n <button data-tracking=\"export-btn\" mat-icon-button (click)=\"onAction()\" class=\"icon-button\" [disabled]=\"disabled\">\n <mat-icon class=\"custom-icon\">file_download</mat-icon>\n </button>\n }\n }\n} @else {\n @if ((progress > 0 && progress < 100)) {\n <div\n class=\"spinner-container\"\n >\n <div class=\"spinner-background\">\n {{progress}}%\n </div>\n <mat-progress-spinner\n color=\"primary\"\n [mode]=\"mode\"\n [value]=\"progress\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n } @else {\n <div class=\"container-obj\">\n <div class=\"centered-obj-div\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n </div>\n }\n}\n\n\n\n\n", styles: [":not(spinner-container).spinner-container{position:relative}:not(spinner-container).spinner-container .spinner-background{position:absolute;width:44px;height:44px;font-size:12px;line-height:32px;text-align:center;overflow:hidden;border-radius:50%;border:solid 5px whitesmoke}.center-txt{align-content:center;text-align:-webkit-center}.width{width:48px;height:48px}.icon-button{display:flex;align-items:center;justify-content:center;width:48px;height:48px;padding:0}.container-obj{display:flex;justify-content:center;align-items:center;width:48px;height:48px}.centered-obj-div{text-align:center}\n"], dependencies: [{ kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }], encapsulation: i0.ViewEncapsulation.None }); }
4633
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: DownloadFileComponent, selector: "app-download-file", inputs: { event: "event", displayError: "displayError", diameter: "diameter", mode: "mode", isPending: "isPending", active: "active", disabled: "disabled", progress: "progress", hasError: "hasError" }, outputs: { error: "error" }, ngImport: i0, template: "@if (!isPending) {\n @if (hasError) {\n <div class=\"width center-txt\" style=\"margin-bottom: 4px;\">\n <mat-icon color=\"warn\" class=\"warn-icon\">warning</mat-icon>\n </div>\n } @else {\n @if (active) {\n <div class=\"container-obj\">\n <div class=\"centered-obj-div\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n </div>\n } @else {\n <button data-tracking=\"export-btn\" mat-icon-button (click)=\"onAction()\" class=\"icon-button\" [disabled]=\"disabled\">\n <mat-icon class=\"custom-icon\">file_download</mat-icon>\n </button>\n }\n }\n} @else {\n @if ((progress > 0 && progress < 100)) {\n <div\n class=\"spinner-container\"\n >\n <div class=\"spinner-background\">\n {{progress}}%\n </div>\n <mat-progress-spinner\n color=\"primary\"\n [mode]=\"mode\"\n [value]=\"progress\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n } @else {\n <div class=\"container-obj\">\n <div class=\"centered-obj-div\">\n <mat-progress-spinner\n color=\"primary\"\n mode=\"indeterminate\"\n [diameter]=\"44\"\n ></mat-progress-spinner>\n </div>\n </div>\n }\n}\n\n\n\n\n", styles: [":not(spinner-container).spinner-container{position:relative}:not(spinner-container).spinner-container .spinner-background{position:absolute;width:44px;height:44px;font-size:12px;line-height:32px;text-align:center;overflow:hidden;border-radius:50%;border:solid 5px whitesmoke}.center-txt{align-content:center;text-align:-webkit-center}.width{width:48px;height:48px}.icon-button{display:flex;align-items:center;justify-content:center;width:48px;height:48px;padding:0}.container-obj{display:flex;justify-content:center;align-items:center;width:48px;height:48px}.centered-obj-div{text-align:center}\n"], dependencies: [{ kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }], encapsulation: i0.ViewEncapsulation.None }); }
4251
4634
  }
4252
4635
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DownloadFileComponent, decorators: [{
4253
4636
  type: Component,
@@ -4576,7 +4959,7 @@ class LocalStorageSignalsDemoComponent {
4576
4959
  this.localStorageManagerService.resetStore();
4577
4960
  }
4578
4961
  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 }); }
4579
- 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: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i4.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: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6$1.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: i6$1.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: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.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: i10$1.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: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }], encapsulation: i0.ViewEncapsulation.None }); }
4962
+ 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: i4$1.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 }); }
4580
4963
  }
4581
4964
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageSignalsDemoComponent, decorators: [{
4582
4965
  type: Component,
@@ -4913,6 +5296,7 @@ class NotificationServiceDemo {
4913
5296
  ldap: user?.ldap,
4914
5297
  name: user?.name,
4915
5298
  email: user?.email,
5299
+ color: user?.color,
4916
5300
  },
4917
5301
  ...content
4918
5302
  };
@@ -4931,14 +5315,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
4931
5315
  }] });
4932
5316
 
4933
5317
  class UserData {
4934
- constructor(ldap = '', name = '', email = '') {
5318
+ constructor(ldap = '', name = '', email = '', color = RandomPaletteColor()) {
4935
5319
  this.ldap = ldap;
4936
5320
  this.name = name;
4937
5321
  this.email = email;
5322
+ this.color = color;
4938
5323
  }
4939
5324
  static adapt(item) {
4940
5325
  const userName = `${item?.first_name} ${item?.last_name}`;
4941
- return new UserData(item?.ldap, userName, item?.email);
5326
+ return new UserData(item?.ldap, userName, item?.email, item?.color);
4942
5327
  }
4943
5328
  }
4944
5329
 
@@ -5069,7 +5454,7 @@ class WsDataControlComponent {
5069
5454
  this.stateDataRequestService.deleteData(lastRec);
5070
5455
  }
5071
5456
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WsDataControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5072
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WsDataControlComponent, selector: "app-ws-data-control", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user", path: "path", wsChannel: "wsChannel" }, ngImport: i0, template: "@if ((data$ | async); as data) {\n <div style=\"margin: 1rem;\">\n @if ((users$ |async); as users) {\n <div>\n @if (users.length > 0) {\n <h3 style=\"margin: 0;\">Connected Users</h3>\n } @else {\n <h3 style=\"margin: 0;\">No Users</h3>\n }\n <mat-chip-set>\n @for (user of users; track user.sessionId) {\n <mat-chip\n [class.user-chip--primary]=\"isUser(user, (user$ | async))\"\n [style.color]=\"isUser(user, (user$ | async)) ? '#fff' : null\"\n [disableRipple]=\"true\"\n >\n {{ user.name }}\n </mat-chip>\n }\n </mat-chip-set>\n </div>\n }\n <div style=\"margin-top: 1rem; margin-bottom: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div class=\"box\" style=\"margin-bottom: 1rem;\" *ngIf=\"(userAction$ | async) as userAction\">\n {{ userAction?.content?.user?.name }} has {{ userAction?.content?.method }}\n </div>\n\n <h3 style=\"margin: 0;\">Data Actions</h3>\n <div style=\"display: flex; gap: 1rem; margin-bottom: 1rem;\">\n <button mat-stroked-button (click)=\"onGetData()\">Get Data</button>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button color=\"accent\" (click)=\"onUpdateData(data)\">Update Data</button>\n <button mat-stroked-button color=\"warn\" (click)=\"onRemoveData(data)\">Remove Data</button>\n <button mat-stroked-button color=\"primary\" (click)=\"onAddData()\">Add Data</button>\n </div>\n @if (data.length > 0) {\n <div>\n <table mat-table [dataSource]=\"data\" style=\"border: 1px solid grey;\">\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=\"spiffe\">\n <th mat-header-cell *matHeaderCellDef> Spiffe </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.spiffe}} </td>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.first_name}} {{element.last_name}}</td>\n </ng-container>\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef> Email </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.email}} </td>\n </ng-container>\n <tr mat-header-row *matHeaderRowDef=\"['id', 'spiffe', 'name', 'email']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['id', 'spiffe', 'name', 'email'];\"></tr>\n </table>\n <div style=\"border: 1px solid grey; padding: .5rem; border-top: none;\">\n <h3 style=\"margin: 0;\">Total Records {{ data.length }}</h3>\n </div>\n </div>\n } @else {\n <div style=\"margin-top: 1rem; font-style: italic;\">\n No Data Available\n </div>\n }\n </div>\n}\n\n", styles: [".user-chip--primary{background-color:var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5))!important;color:#fff!important;--mdc-evolution-chip-container-color: var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5));--mdc-evolution-chip-label-text-color: #fff}.user-chip--primary :is(.mdc-evolution-chip__text-label,.mdc-evolution-chip__action,.mdc-evolution-chip__cell,.mat-mdc-chip-action-label){color:#fff!important}.user-chip--primary,.user-chip--primary *{color:#fff!important}:host ::ng-deep .user-chip--primary{background-color:var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5))!important;color:#fff!important;--mdc-evolution-chip-container-color: var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5));--mdc-evolution-chip-label-text-color: #fff}:host ::ng-deep .user-chip--primary .mdc-evolution-chip__text-label,:host ::ng-deep .user-chip--primary .mdc-evolution-chip__action,:host ::ng-deep .user-chip--primary .mdc-evolution-chip__cell,:host ::ng-deep .user-chip--primary .mat-mdc-chip-action-label,:host ::ng-deep .user-chip--primary *{color:#fff!important}.box{padding:.5rem;border:1px solid rgb(174,174,13);background-color:#ececaf}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { 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: i3$1.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
5457
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WsDataControlComponent, selector: "app-ws-data-control", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user", path: "path", wsChannel: "wsChannel" }, ngImport: i0, template: "@if ((data$ | async); as data) {\n <div style=\"margin: 1rem;\">\n @if ((users$ |async); as users) {\n <div>\n @if (users.length > 0) {\n <h3 style=\"margin: 0;\">Connected Users</h3>\n } @else {\n <h3 style=\"margin: 0;\">No Users</h3>\n }\n <mat-chip-set>\n @for (user of users; track user.sessionId) {\n <mat-chip\n [class.user-chip--primary]=\"isUser(user, (user$ | async))\"\n [style.color]=\"isUser(user, (user$ | async)) ? '#fff' : null\"\n [disableRipple]=\"true\"\n >\n {{ user.name }}\n </mat-chip>\n }\n </mat-chip-set>\n </div>\n }\n <div style=\"margin-top: 1rem; margin-bottom: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div class=\"box\" style=\"margin-bottom: 1rem;\" *ngIf=\"(userAction$ | async) as userAction\">\n {{ userAction?.content?.user?.name }} has {{ userAction?.content?.method }}\n </div>\n\n <h3 style=\"margin: 0;\">Data Actions</h3>\n <div style=\"display: flex; gap: 1rem; margin-bottom: 1rem;\">\n <button mat-stroked-button (click)=\"onGetData()\">Get Data</button>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button color=\"accent\" (click)=\"onUpdateData(data)\">Update Data</button>\n <button mat-stroked-button color=\"warn\" (click)=\"onRemoveData(data)\">Remove Data</button>\n <button mat-stroked-button color=\"primary\" (click)=\"onAddData()\">Add Data</button>\n </div>\n @if (data.length > 0) {\n <div>\n <table mat-table [dataSource]=\"data\" style=\"border: 1px solid grey;\">\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=\"spiffe\">\n <th mat-header-cell *matHeaderCellDef> Spiffe </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.spiffe}} </td>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.first_name}} {{element.last_name}}</td>\n </ng-container>\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef> Email </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.email}} </td>\n </ng-container>\n <tr mat-header-row *matHeaderRowDef=\"['id', 'spiffe', 'name', 'email']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['id', 'spiffe', 'name', 'email'];\"></tr>\n </table>\n <div style=\"border: 1px solid grey; padding: .5rem; border-top: none;\">\n <h3 style=\"margin: 0;\">Total Records {{ data.length }}</h3>\n </div>\n </div>\n } @else {\n <div style=\"margin-top: 1rem; font-style: italic;\">\n No Data Available\n </div>\n }\n </div>\n}\n\n", styles: [".user-chip--primary{background-color:var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5))!important;color:#fff!important;--mdc-evolution-chip-container-color: var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5));--mdc-evolution-chip-label-text-color: #fff}.user-chip--primary :is(.mdc-evolution-chip__text-label,.mdc-evolution-chip__action,.mdc-evolution-chip__cell,.mat-mdc-chip-action-label){color:#fff!important}.user-chip--primary,.user-chip--primary *{color:#fff!important}:host ::ng-deep .user-chip--primary{background-color:var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5))!important;color:#fff!important;--mdc-evolution-chip-container-color: var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5));--mdc-evolution-chip-label-text-color: #fff}:host ::ng-deep .user-chip--primary .mdc-evolution-chip__text-label,:host ::ng-deep .user-chip--primary .mdc-evolution-chip__action,:host ::ng-deep .user-chip--primary .mdc-evolution-chip__cell,:host ::ng-deep .user-chip--primary .mat-mdc-chip-action-label,:host ::ng-deep .user-chip--primary *{color:#fff!important}.box{padding:.5rem;border:1px solid rgb(174,174,13);background-color:#ececaf}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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$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: i3$1.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { 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: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
5073
5458
  }
5074
5459
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WsDataControlComponent, decorators: [{
5075
5460
  type: Component,
@@ -5242,7 +5627,7 @@ class WsMessagingComponent {
5242
5627
  this.content.reset();
5243
5628
  }
5244
5629
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WsMessagingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5245
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WsMessagingComponent, selector: "app-ws-messaging", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user" }, ngImport: i0, template: "\n @if ((data$ | async); as data) {\n @if ((user$ | async); as user) {\n <div style=\"display: flex; gap: 1rem; flex-direction: column; margin-top: 1rem;\">\n\n <!-- Channel Creation Section -->\n <div style=\"padding: 1rem; background: #e3f2fd; border-radius: 4px;\">\n <strong>Create New Channel</strong>\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field appearance=\"outline\" style=\"width: 100%;\">\n <mat-label>Channel Name</mat-label>\n <input matInput [formControl]=\"newChannelName\" placeholder=\"Enter channel name\"\n (keydown.enter)=\"onCreateChannel()\">\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; margin-top: -0.5rem;\">\n <button mat-raised-button color=\"primary\" (click)=\"onCreateChannel()\"\n [disabled]=\"newChannelName.invalid\">\n Create Channel\n </button>\n </div>\n </div>\n </div>\n\n <!-- Messaging Section - only show when subscribed to channels -->\n @if ((subscribedChannels$ | async); as subscribedChannels) {\n @if (subscribedChannels.length > 0) {\n <div style=\"padding: 1rem; background: #fff3e0; border-radius: 4px;\" [formGroup]=\"messages\">\n <strong>Send Message</strong>\n\n <!-- Channel Selection with Checkboxes -->\n <div style=\"margin-top: 0.5rem;\">\n <mat-form-field appearance=\"outline\" style=\"width: 100%;\">\n <mat-label>Select Channels</mat-label>\n <mat-select formControlName=\"selectedChannels\" multiple>\n <mat-select-trigger>\n @if (selectedChannels.value?.length === 1) {\n {{ selectedChannels.value[0] }}\n } @else if (selectedChannels.value?.length > 1) {\n {{ selectedChannels.value[0] }} (+{{ selectedChannels.value.length - 1 }} {{ selectedChannels.value.length === 2 ? 'other' : 'others' }})\n }\n </mat-select-trigger>\n @for (channel of subscribedChannels; track channel) {\n <mat-option [value]=\"channel\">{{ channel }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n <!-- Message Input -->\n <div style=\"display: flex; flex-direction: column;\">\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\">\n <mat-label>Message</mat-label>\n <textarea\n matInput placeholder=\"Type your message...\"\n formControlName=\"content\"\n (keydown.enter)=\"onSendMessage(user); $event.preventDefault()\"\n ></textarea>\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; margin-top: -0.5rem;\">\n <button mat-raised-button color=\"primary\" (click)=\"onSendMessage(user)\"\n [disabled]=\"messages.invalid\">\n Send\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n </div>\n }\n }\n\n <!-- Channel List with Subscription Controls using Chips -->\n @if ((channels$ | async); as channels) {\n @if ((subscribedChannels$ | async); as subscribedChannels) {\n <div style=\"padding: 1rem; background: #f5f5f5; border-radius: 4px; margin-top: 1rem;\">\n <strong>Subscribe to Channel(s)</strong>\n <div style=\"margin-top: 0.5rem;\">\n @if (channels.length === 0) {\n <div style=\"color: #666; font-style: italic;\">No channels available. Create one above.</div>\n } @else {\n <mat-chip-listbox aria-label=\"Channel selection\" [multiple]=\"true\">\n @for (channel of channels; track channel) {\n <mat-chip-option\n [selected]=\"isSubscribed(channel, subscribedChannels)\"\n (click)=\"onChipClick(channel, subscribedChannels)\">\n {{ channel }}\n </mat-chip-option>\n }\n </mat-chip-listbox>\n }\n </div>\n </div>\n }\n }\n", styles: ["button[mat-raised-button],button[mat-stroked-button]{min-width:120px}mat-chip-option{min-width:120px;justify-content:center;border-radius:4px!important;padding:.25rem!important}\n"], dependencies: [{ kind: "directive", type: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "component", type: i4.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: "directive", type: i4.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i3$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i3$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
5630
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WsMessagingComponent, selector: "app-ws-messaging", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user" }, ngImport: i0, template: "\n @if ((data$ | async); as data) {\n @if ((user$ | async); as user) {\n <div style=\"display: flex; gap: 1rem; flex-direction: column; margin-top: 1rem;\">\n\n <!-- Channel Creation Section -->\n <div style=\"padding: 1rem; background: #e3f2fd; border-radius: 4px;\">\n <strong>Create New Channel</strong>\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field appearance=\"outline\" style=\"width: 100%;\">\n <mat-label>Channel Name</mat-label>\n <input matInput [formControl]=\"newChannelName\" placeholder=\"Enter channel name\"\n (keydown.enter)=\"onCreateChannel()\">\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; margin-top: -0.5rem;\">\n <button mat-raised-button color=\"primary\" (click)=\"onCreateChannel()\"\n [disabled]=\"newChannelName.invalid\">\n Create Channel\n </button>\n </div>\n </div>\n </div>\n\n <!-- Messaging Section - only show when subscribed to channels -->\n @if ((subscribedChannels$ | async); as subscribedChannels) {\n @if (subscribedChannels.length > 0) {\n <div style=\"padding: 1rem; background: #fff3e0; border-radius: 4px;\" [formGroup]=\"messages\">\n <strong>Send Message</strong>\n\n <!-- Channel Selection with Checkboxes -->\n <div style=\"margin-top: 0.5rem;\">\n <mat-form-field appearance=\"outline\" style=\"width: 100%;\">\n <mat-label>Select Channels</mat-label>\n <mat-select formControlName=\"selectedChannels\" multiple>\n <mat-select-trigger>\n @if (selectedChannels.value?.length === 1) {\n {{ selectedChannels.value[0] }}\n } @else if (selectedChannels.value?.length > 1) {\n {{ selectedChannels.value[0] }} (+{{ selectedChannels.value.length - 1 }} {{ selectedChannels.value.length === 2 ? 'other' : 'others' }})\n }\n </mat-select-trigger>\n @for (channel of subscribedChannels; track channel) {\n <mat-option [value]=\"channel\">{{ channel }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n <!-- Message Input -->\n <div style=\"display: flex; flex-direction: column;\">\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\">\n <mat-label>Message</mat-label>\n <textarea\n matInput placeholder=\"Type your message...\"\n formControlName=\"content\"\n (keydown.enter)=\"onSendMessage(user); $event.preventDefault()\"\n ></textarea>\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; margin-top: -0.5rem;\">\n <button mat-raised-button color=\"primary\" (click)=\"onSendMessage(user)\"\n [disabled]=\"messages.invalid\">\n Send\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n </div>\n }\n }\n\n <!-- Channel List with Subscription Controls using Chips -->\n @if ((channels$ | async); as channels) {\n @if ((subscribedChannels$ | async); as subscribedChannels) {\n <div style=\"padding: 1rem; background: #f5f5f5; border-radius: 4px; margin-top: 1rem;\">\n <strong>Subscribe to Channel(s)</strong>\n <div style=\"margin-top: 0.5rem;\">\n @if (channels.length === 0) {\n <div style=\"color: #666; font-style: italic;\">No channels available. Create one above.</div>\n } @else {\n <mat-chip-listbox aria-label=\"Channel selection\" [multiple]=\"true\">\n @for (channel of channels; track channel) {\n <mat-chip-option\n [selected]=\"isSubscribed(channel, subscribedChannels)\"\n (click)=\"onChipClick(channel, subscribedChannels)\">\n {{ channel }}\n </mat-chip-option>\n }\n </mat-chip-listbox>\n }\n </div>\n </div>\n }\n }\n", styles: ["button[mat-raised-button],button[mat-stroked-button]{min-width:120px}mat-chip-option{min-width:120px;justify-content:center;border-radius:4px!important;padding:.25rem!important}\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: "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: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "component", type: i4$1.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: "directive", type: i4$1.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i3$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i3$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { 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" }] }); }
5246
5631
  }
5247
5632
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WsMessagingComponent, decorators: [{
5248
5633
  type: Component,
@@ -5436,11 +5821,11 @@ class WsNotificationsComponent {
5436
5821
  return new Date().toISOString().split('T')[0];
5437
5822
  }
5438
5823
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WsNotificationsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5439
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WsNotificationsComponent, selector: "app-ws-notifications", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user" }, ngImport: i0, template: "<div style=\"display: flex; gap: 1rem; flex-direction: column; margin-top: 1rem;\">\n\n <!-- Channel Creation Section -->\n <div style=\"padding: 1rem; background: #e8f5e9; border-radius: 4px;\">\n <strong>Create Notification Channel</strong>\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field appearance=\"outline\" style=\"width: 100%;\">\n <mat-label>Channel Name</mat-label>\n <input\n matInput\n [formControl]=\"newChannelName\"\n placeholder=\"Enter notification channel name\"\n (keydown.enter)=\"onCreateChannel()\"\n >\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; gap: 0.5rem;\">\n <button mat-raised-button color=\"accent\" (click)=\"onDefinePreviousChannels()\">\n Define Previous Channels\n </button>\n <button mat-raised-button color=\"primary\" (click)=\"onCreateChannel()\"\n [disabled]=\"newChannelName.invalid\">\n Create Channel\n </button>\n </div>\n </div>\n </div>\n\n <!-- Channel Connection Section - Only shown when NOT connected -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (!isChannelConnected(subscribedChannels)) {\n <div style=\"padding: 1rem; background: #e3f2fd; border-radius: 4px;\">\n <strong>Connect to Channel</strong>\n <div style=\"display: flex; gap: 1rem; margin-top: 0.5rem; flex-wrap: wrap; align-items: flex-start;\">\n <!-- Channel Selection (from today's DB data) -->\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\">\n <mat-label>Select Channel</mat-label>\n <mat-select [formControl]=\"selectedConnectionChannel\" placeholder=\"Select a notification channel\">\n @for (channel of (todaysNotificationChannels$ | async) || []; track channel) {\n <mat-option [value]=\"channel\">{{ channel }}</mat-option>\n }\n @empty {\n <mat-option disabled>No channels with data for today</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <!-- Date Filter -->\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\" [formGroup]=\"dateFilter\">\n <mat-label>Start Date</mat-label>\n <input matInput [matDatepicker]=\"startPicker\" formControlName=\"startDate\">\n <mat-datepicker-toggle matIconSuffix [for]=\"startPicker\"></mat-datepicker-toggle>\n <mat-datepicker #startPicker></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\" [formGroup]=\"dateFilter\">\n <mat-label>End Date</mat-label>\n <input matInput [matDatepicker]=\"endPicker\" formControlName=\"endDate\">\n <mat-datepicker-toggle matIconSuffix [for]=\"endPicker\"></mat-datepicker-toggle>\n <mat-datepicker #endPicker></mat-datepicker>\n </mat-form-field>\n </div>\n\n <div style=\"display: flex; gap: 0.5rem;\">\n <span style=\"flex:1\"></span>\n <button\n mat-raised-button color=\"primary\"\n (click)=\"onConnectToChannel()\"\n [disabled]=\"!selectedConnectionChannel.value\"\n >\n Connect\n </button>\n </div>\n </div>\n }\n }\n\n <!-- Send Notification Section -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (subscribedChannels.length > 0) {\n <div\n style=\"padding: 1rem; background: #fff8e1; border-radius: 4px;\"\n [formGroup]=\"notificationForm\"\n >\n <strong>Send Notification</strong>\n\n <!-- Notification Content -->\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\">\n <mat-label>Notification Message</mat-label>\n <textarea\n matInput placeholder=\"Type your notification...\"\n formControlName=\"content\"\n rows=\"2\"\n (keydown.enter)=\"onSendNotification(); $event.preventDefault()\"\n ></textarea>\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; margin-top: -0.5rem;\">\n <button\n mat-raised-button color=\"accent\"\n (click)=\"onSendNotification()\"\n [disabled]=\"notificationForm.invalid\"\n >\n Send Notification\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n <!-- Notifications Table - Only shown when connected -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (isChannelConnected(subscribedChannels)) {\n @if ((notificationMessages$ | async); as notifications) {\n <div>\n <div style=\"display: flex; justify-content: space-between; align-items: center;\">\n <strong>Notifications ({{ notifications.length }})</strong>\n </div>\n\n @if (notifications.length > 0) {\n <div style=\"margin-top: 0.5rem; height: 400px; overflow: auto; border: 1px solid #888; border-radius: 4px;\">\n <table mat-table [dataSource]=\"notifications\" style=\"width: 100%;\">\n\n <!-- Date Column -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef style=\"width: 180px;\">Date</th>\n <td mat-cell *matCellDef=\"let notification\">\n {{ formatTimestamp(notification.created) | date }}\n </td>\n </ng-container>\n\n <!-- User Column -->\n <ng-container matColumnDef=\"user\">\n <th mat-header-cell *matHeaderCellDef style=\"width: 150px;\">User</th>\n <td mat-cell *matCellDef=\"let notification\">\n <strong>{{ notification.user_name }}</strong>\n </td>\n </ng-container>\n\n <!-- Message Column -->\n <ng-container matColumnDef=\"message\">\n <th mat-header-cell *matHeaderCellDef>Message</th>\n <td mat-cell *matCellDef=\"let notification\">\n {{ notification.content?.message || notification.content }}\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n } @else {\n <div style=\"text-align: center; color: #666; padding: 2rem;\">\n <mat-icon style=\"font-size: 48px; height: 48px; width: 48px; opacity: 0.5;\">notifications_none</mat-icon>\n <p>No notifications yet. Waiting for notifications on this channel...</p>\n </div>\n }\n </div>\n\n <!-- Disconnect Button - Below the table -->\n <div style=\"display: flex; justify-content: right; padding: 1rem;\">\n <button mat-raised-button color=\"warn\" (click)=\"onDisconnectFromChannel()\">\n Disconnect from Channel\n </button>\n </div>\n }\n }\n }\n\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i4.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: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i9.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i9.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }] }); }
5824
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WsNotificationsComponent, selector: "app-ws-notifications", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user" }, ngImport: i0, template: "<div style=\"display: flex; gap: 1rem; flex-direction: column; margin-top: 1rem;\">\n\n <!-- Channel Creation Section -->\n <div style=\"padding: 1rem; background: #e8f5e9; border-radius: 4px;\">\n <strong>Create Notification Channel</strong>\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field appearance=\"outline\" style=\"width: 100%;\">\n <mat-label>Channel Name</mat-label>\n <input\n matInput\n [formControl]=\"newChannelName\"\n placeholder=\"Enter notification channel name\"\n (keydown.enter)=\"onCreateChannel()\"\n >\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; gap: 0.5rem;\">\n <button mat-raised-button color=\"accent\" (click)=\"onDefinePreviousChannels()\">\n Define Previous Channels\n </button>\n <button mat-raised-button color=\"primary\" (click)=\"onCreateChannel()\"\n [disabled]=\"newChannelName.invalid\">\n Create Channel\n </button>\n </div>\n </div>\n </div>\n\n <!-- Channel Connection Section - Only shown when NOT connected -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (!isChannelConnected(subscribedChannels)) {\n <div style=\"padding: 1rem; background: #e3f2fd; border-radius: 4px;\">\n <strong>Connect to Channel</strong>\n <div style=\"display: flex; gap: 1rem; margin-top: 0.5rem; flex-wrap: wrap; align-items: flex-start;\">\n <!-- Channel Selection (from today's DB data) -->\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\">\n <mat-label>Select Channel</mat-label>\n <mat-select [formControl]=\"selectedConnectionChannel\" placeholder=\"Select a notification channel\">\n @for (channel of (todaysNotificationChannels$ | async) || []; track channel) {\n <mat-option [value]=\"channel\">{{ channel }}</mat-option>\n }\n @empty {\n <mat-option disabled>No channels with data for today</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <!-- Date Filter -->\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\" [formGroup]=\"dateFilter\">\n <mat-label>Start Date</mat-label>\n <input matInput [matDatepicker]=\"startPicker\" formControlName=\"startDate\">\n <mat-datepicker-toggle matIconSuffix [for]=\"startPicker\"></mat-datepicker-toggle>\n <mat-datepicker #startPicker></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\" [formGroup]=\"dateFilter\">\n <mat-label>End Date</mat-label>\n <input matInput [matDatepicker]=\"endPicker\" formControlName=\"endDate\">\n <mat-datepicker-toggle matIconSuffix [for]=\"endPicker\"></mat-datepicker-toggle>\n <mat-datepicker #endPicker></mat-datepicker>\n </mat-form-field>\n </div>\n\n <div style=\"display: flex; gap: 0.5rem;\">\n <span style=\"flex:1\"></span>\n <button\n mat-raised-button color=\"primary\"\n (click)=\"onConnectToChannel()\"\n [disabled]=\"!selectedConnectionChannel.value\"\n >\n Connect\n </button>\n </div>\n </div>\n }\n }\n\n <!-- Send Notification Section -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (subscribedChannels.length > 0) {\n <div\n style=\"padding: 1rem; background: #fff8e1; border-radius: 4px;\"\n [formGroup]=\"notificationForm\"\n >\n <strong>Send Notification</strong>\n\n <!-- Notification Content -->\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\">\n <mat-label>Notification Message</mat-label>\n <textarea\n matInput placeholder=\"Type your notification...\"\n formControlName=\"content\"\n rows=\"2\"\n (keydown.enter)=\"onSendNotification(); $event.preventDefault()\"\n ></textarea>\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; margin-top: -0.5rem;\">\n <button\n mat-raised-button color=\"accent\"\n (click)=\"onSendNotification()\"\n [disabled]=\"notificationForm.invalid\"\n >\n Send Notification\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n <!-- Notifications Table - Only shown when connected -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (isChannelConnected(subscribedChannels)) {\n @if ((notificationMessages$ | async); as notifications) {\n <div>\n <div style=\"display: flex; justify-content: space-between; align-items: center;\">\n <strong>Notifications ({{ notifications.length }})</strong>\n </div>\n\n @if (notifications.length > 0) {\n <div style=\"margin-top: 0.5rem; height: 400px; overflow: auto; border: 1px solid #888; border-radius: 4px;\">\n <table mat-table [dataSource]=\"notifications\" style=\"width: 100%;\">\n\n <!-- Date Column -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef style=\"width: 180px;\">Date</th>\n <td mat-cell *matCellDef=\"let notification\">\n {{ formatTimestamp(notification.created) | date }}\n </td>\n </ng-container>\n\n <!-- User Column -->\n <ng-container matColumnDef=\"user\">\n <th mat-header-cell *matHeaderCellDef style=\"width: 150px;\">User</th>\n <td mat-cell *matCellDef=\"let notification\">\n <strong>{{ notification.user_name }}</strong>\n </td>\n </ng-container>\n\n <!-- Message Column -->\n <ng-container matColumnDef=\"message\">\n <th mat-header-cell *matHeaderCellDef>Message</th>\n <td mat-cell *matCellDef=\"let notification\">\n <div class=\"pill\" [style.background-color]=\"notification.content.sessionId.color || '#000000'\">\n {{ notification.content?.message || notification.content }}\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n } @else {\n <div style=\"text-align: center; color: #666; padding: 2rem;\">\n <mat-icon style=\"font-size: 48px; height: 48px; width: 48px; opacity: 0.5;\">notifications_none</mat-icon>\n <p>No notifications yet. Waiting for notifications on this channel...</p>\n </div>\n }\n </div>\n\n <!-- Disconnect Button - Below the table -->\n <div style=\"display: flex; justify-content: right; padding: 1rem;\">\n <button mat-raised-button color=\"warn\" (click)=\"onDisconnectFromChannel()\">\n Disconnect from Channel\n </button>\n </div>\n }\n }\n }\n\n</div>\n", styles: [".colored-message{font-weight:500;padding:4px 8px;border-radius:4px;display:inline-block;max-width:100%;word-wrap:break-word}.colored-message.black-text{color:#000!important}.colored-message.white-text{color:#fff!important;text-shadow:0 0 2px rgba(0,0,0,.5)}td.mat-mdc-cell{padding:8px 12px}.pill{border-radius:1rem;padding:.5rem 1rem;color:#fff}\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: "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: 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.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i4$1.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: 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: 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: i9$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i9$1.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }] }); }
5440
5825
  }
5441
5826
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WsNotificationsComponent, decorators: [{
5442
5827
  type: Component,
5443
- args: [{ selector: 'app-ws-notifications', standalone: false, template: "<div style=\"display: flex; gap: 1rem; flex-direction: column; margin-top: 1rem;\">\n\n <!-- Channel Creation Section -->\n <div style=\"padding: 1rem; background: #e8f5e9; border-radius: 4px;\">\n <strong>Create Notification Channel</strong>\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field appearance=\"outline\" style=\"width: 100%;\">\n <mat-label>Channel Name</mat-label>\n <input\n matInput\n [formControl]=\"newChannelName\"\n placeholder=\"Enter notification channel name\"\n (keydown.enter)=\"onCreateChannel()\"\n >\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; gap: 0.5rem;\">\n <button mat-raised-button color=\"accent\" (click)=\"onDefinePreviousChannels()\">\n Define Previous Channels\n </button>\n <button mat-raised-button color=\"primary\" (click)=\"onCreateChannel()\"\n [disabled]=\"newChannelName.invalid\">\n Create Channel\n </button>\n </div>\n </div>\n </div>\n\n <!-- Channel Connection Section - Only shown when NOT connected -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (!isChannelConnected(subscribedChannels)) {\n <div style=\"padding: 1rem; background: #e3f2fd; border-radius: 4px;\">\n <strong>Connect to Channel</strong>\n <div style=\"display: flex; gap: 1rem; margin-top: 0.5rem; flex-wrap: wrap; align-items: flex-start;\">\n <!-- Channel Selection (from today's DB data) -->\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\">\n <mat-label>Select Channel</mat-label>\n <mat-select [formControl]=\"selectedConnectionChannel\" placeholder=\"Select a notification channel\">\n @for (channel of (todaysNotificationChannels$ | async) || []; track channel) {\n <mat-option [value]=\"channel\">{{ channel }}</mat-option>\n }\n @empty {\n <mat-option disabled>No channels with data for today</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <!-- Date Filter -->\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\" [formGroup]=\"dateFilter\">\n <mat-label>Start Date</mat-label>\n <input matInput [matDatepicker]=\"startPicker\" formControlName=\"startDate\">\n <mat-datepicker-toggle matIconSuffix [for]=\"startPicker\"></mat-datepicker-toggle>\n <mat-datepicker #startPicker></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\" [formGroup]=\"dateFilter\">\n <mat-label>End Date</mat-label>\n <input matInput [matDatepicker]=\"endPicker\" formControlName=\"endDate\">\n <mat-datepicker-toggle matIconSuffix [for]=\"endPicker\"></mat-datepicker-toggle>\n <mat-datepicker #endPicker></mat-datepicker>\n </mat-form-field>\n </div>\n\n <div style=\"display: flex; gap: 0.5rem;\">\n <span style=\"flex:1\"></span>\n <button\n mat-raised-button color=\"primary\"\n (click)=\"onConnectToChannel()\"\n [disabled]=\"!selectedConnectionChannel.value\"\n >\n Connect\n </button>\n </div>\n </div>\n }\n }\n\n <!-- Send Notification Section -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (subscribedChannels.length > 0) {\n <div\n style=\"padding: 1rem; background: #fff8e1; border-radius: 4px;\"\n [formGroup]=\"notificationForm\"\n >\n <strong>Send Notification</strong>\n\n <!-- Notification Content -->\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\">\n <mat-label>Notification Message</mat-label>\n <textarea\n matInput placeholder=\"Type your notification...\"\n formControlName=\"content\"\n rows=\"2\"\n (keydown.enter)=\"onSendNotification(); $event.preventDefault()\"\n ></textarea>\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; margin-top: -0.5rem;\">\n <button\n mat-raised-button color=\"accent\"\n (click)=\"onSendNotification()\"\n [disabled]=\"notificationForm.invalid\"\n >\n Send Notification\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n <!-- Notifications Table - Only shown when connected -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (isChannelConnected(subscribedChannels)) {\n @if ((notificationMessages$ | async); as notifications) {\n <div>\n <div style=\"display: flex; justify-content: space-between; align-items: center;\">\n <strong>Notifications ({{ notifications.length }})</strong>\n </div>\n\n @if (notifications.length > 0) {\n <div style=\"margin-top: 0.5rem; height: 400px; overflow: auto; border: 1px solid #888; border-radius: 4px;\">\n <table mat-table [dataSource]=\"notifications\" style=\"width: 100%;\">\n\n <!-- Date Column -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef style=\"width: 180px;\">Date</th>\n <td mat-cell *matCellDef=\"let notification\">\n {{ formatTimestamp(notification.created) | date }}\n </td>\n </ng-container>\n\n <!-- User Column -->\n <ng-container matColumnDef=\"user\">\n <th mat-header-cell *matHeaderCellDef style=\"width: 150px;\">User</th>\n <td mat-cell *matCellDef=\"let notification\">\n <strong>{{ notification.user_name }}</strong>\n </td>\n </ng-container>\n\n <!-- Message Column -->\n <ng-container matColumnDef=\"message\">\n <th mat-header-cell *matHeaderCellDef>Message</th>\n <td mat-cell *matCellDef=\"let notification\">\n {{ notification.content?.message || notification.content }}\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n } @else {\n <div style=\"text-align: center; color: #666; padding: 2rem;\">\n <mat-icon style=\"font-size: 48px; height: 48px; width: 48px; opacity: 0.5;\">notifications_none</mat-icon>\n <p>No notifications yet. Waiting for notifications on this channel...</p>\n </div>\n }\n </div>\n\n <!-- Disconnect Button - Below the table -->\n <div style=\"display: flex; justify-content: right; padding: 1rem;\">\n <button mat-raised-button color=\"warn\" (click)=\"onDisconnectFromChannel()\">\n Disconnect from Channel\n </button>\n </div>\n }\n }\n }\n\n</div>\n" }]
5828
+ args: [{ selector: 'app-ws-notifications', standalone: false, template: "<div style=\"display: flex; gap: 1rem; flex-direction: column; margin-top: 1rem;\">\n\n <!-- Channel Creation Section -->\n <div style=\"padding: 1rem; background: #e8f5e9; border-radius: 4px;\">\n <strong>Create Notification Channel</strong>\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field appearance=\"outline\" style=\"width: 100%;\">\n <mat-label>Channel Name</mat-label>\n <input\n matInput\n [formControl]=\"newChannelName\"\n placeholder=\"Enter notification channel name\"\n (keydown.enter)=\"onCreateChannel()\"\n >\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; gap: 0.5rem;\">\n <button mat-raised-button color=\"accent\" (click)=\"onDefinePreviousChannels()\">\n Define Previous Channels\n </button>\n <button mat-raised-button color=\"primary\" (click)=\"onCreateChannel()\"\n [disabled]=\"newChannelName.invalid\">\n Create Channel\n </button>\n </div>\n </div>\n </div>\n\n <!-- Channel Connection Section - Only shown when NOT connected -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (!isChannelConnected(subscribedChannels)) {\n <div style=\"padding: 1rem; background: #e3f2fd; border-radius: 4px;\">\n <strong>Connect to Channel</strong>\n <div style=\"display: flex; gap: 1rem; margin-top: 0.5rem; flex-wrap: wrap; align-items: flex-start;\">\n <!-- Channel Selection (from today's DB data) -->\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\">\n <mat-label>Select Channel</mat-label>\n <mat-select [formControl]=\"selectedConnectionChannel\" placeholder=\"Select a notification channel\">\n @for (channel of (todaysNotificationChannels$ | async) || []; track channel) {\n <mat-option [value]=\"channel\">{{ channel }}</mat-option>\n }\n @empty {\n <mat-option disabled>No channels with data for today</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <!-- Date Filter -->\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\" [formGroup]=\"dateFilter\">\n <mat-label>Start Date</mat-label>\n <input matInput [matDatepicker]=\"startPicker\" formControlName=\"startDate\">\n <mat-datepicker-toggle matIconSuffix [for]=\"startPicker\"></mat-datepicker-toggle>\n <mat-datepicker #startPicker></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" style=\"flex: 1; min-width: 200px;\" [formGroup]=\"dateFilter\">\n <mat-label>End Date</mat-label>\n <input matInput [matDatepicker]=\"endPicker\" formControlName=\"endDate\">\n <mat-datepicker-toggle matIconSuffix [for]=\"endPicker\"></mat-datepicker-toggle>\n <mat-datepicker #endPicker></mat-datepicker>\n </mat-form-field>\n </div>\n\n <div style=\"display: flex; gap: 0.5rem;\">\n <span style=\"flex:1\"></span>\n <button\n mat-raised-button color=\"primary\"\n (click)=\"onConnectToChannel()\"\n [disabled]=\"!selectedConnectionChannel.value\"\n >\n Connect\n </button>\n </div>\n </div>\n }\n }\n\n <!-- Send Notification Section -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (subscribedChannels.length > 0) {\n <div\n style=\"padding: 1rem; background: #fff8e1; border-radius: 4px;\"\n [formGroup]=\"notificationForm\"\n >\n <strong>Send Notification</strong>\n\n <!-- Notification Content -->\n <div style=\"display: flex; flex-direction: column; margin-top: 0.5rem;\">\n <mat-form-field style=\"width: 100%;\" appearance=\"outline\">\n <mat-label>Notification Message</mat-label>\n <textarea\n matInput placeholder=\"Type your notification...\"\n formControlName=\"content\"\n rows=\"2\"\n (keydown.enter)=\"onSendNotification(); $event.preventDefault()\"\n ></textarea>\n </mat-form-field>\n <div style=\"display: flex; justify-content: flex-end; margin-top: -0.5rem;\">\n <button\n mat-raised-button color=\"accent\"\n (click)=\"onSendNotification()\"\n [disabled]=\"notificationForm.invalid\"\n >\n Send Notification\n </button>\n </div>\n </div>\n </div>\n }\n }\n\n <!-- Notifications Table - Only shown when connected -->\n @if ((subscribedNotificationChannels$ | async); as subscribedChannels) {\n @if (isChannelConnected(subscribedChannels)) {\n @if ((notificationMessages$ | async); as notifications) {\n <div>\n <div style=\"display: flex; justify-content: space-between; align-items: center;\">\n <strong>Notifications ({{ notifications.length }})</strong>\n </div>\n\n @if (notifications.length > 0) {\n <div style=\"margin-top: 0.5rem; height: 400px; overflow: auto; border: 1px solid #888; border-radius: 4px;\">\n <table mat-table [dataSource]=\"notifications\" style=\"width: 100%;\">\n\n <!-- Date Column -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef style=\"width: 180px;\">Date</th>\n <td mat-cell *matCellDef=\"let notification\">\n {{ formatTimestamp(notification.created) | date }}\n </td>\n </ng-container>\n\n <!-- User Column -->\n <ng-container matColumnDef=\"user\">\n <th mat-header-cell *matHeaderCellDef style=\"width: 150px;\">User</th>\n <td mat-cell *matCellDef=\"let notification\">\n <strong>{{ notification.user_name }}</strong>\n </td>\n </ng-container>\n\n <!-- Message Column -->\n <ng-container matColumnDef=\"message\">\n <th mat-header-cell *matHeaderCellDef>Message</th>\n <td mat-cell *matCellDef=\"let notification\">\n <div class=\"pill\" [style.background-color]=\"notification.content.sessionId.color || '#000000'\">\n {{ notification.content?.message || notification.content }}\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n } @else {\n <div style=\"text-align: center; color: #666; padding: 2rem;\">\n <mat-icon style=\"font-size: 48px; height: 48px; width: 48px; opacity: 0.5;\">notifications_none</mat-icon>\n <p>No notifications yet. Waiting for notifications on this channel...</p>\n </div>\n }\n </div>\n\n <!-- Disconnect Button - Below the table -->\n <div style=\"display: flex; justify-content: right; padding: 1rem;\">\n <button mat-raised-button color=\"warn\" (click)=\"onDisconnectFromChannel()\">\n Disconnect from Channel\n </button>\n </div>\n }\n }\n }\n\n</div>\n", styles: [".colored-message{font-weight:500;padding:4px 8px;border-radius:4px;display:inline-block;max-width:100%;word-wrap:break-word}.colored-message.black-text{color:#000!important}.colored-message.white-text{color:#fff!important;text-shadow:0 0 2px rgba(0,0,0,.5)}td.mat-mdc-cell{padding:8px 12px}.pill{border-radius:1rem;padding:.5rem 1rem;color:#fff}\n"] }]
5444
5829
  }], propDecorators: { server: [{
5445
5830
  type: Input
5446
5831
  }], wsServer: [{
@@ -5483,74 +5868,17 @@ class RequestManagerWsDemoComponent {
5483
5868
  this.path = ['ai', 'tests'];
5484
5869
  this.wsChannel = '';
5485
5870
  this.user$ = this.stateService.user$;
5486
- // users$ = this.stateService.userList$
5487
5871
  this.attempts$ = this.stateService.wsRetryAttempts$;
5488
5872
  this.nextRetry$ = this.stateService.wsNextRetry$;
5489
5873
  this.connectionStatus$ = this.stateService.connectionStatus$;
5490
5874
  this.data$ = this.stateService.data$;
5491
5875
  this.isPending$ = this.stateService.isPending$;
5492
5876
  }
5493
- // messages = this.fb.group<any>({
5494
- // toUser: this.fb.control<string|null>(null, Validators.required),
5495
- // content: this.fb.control<string|null>(null, Validators.required),
5496
- // })
5497
- // get toUser() {
5498
- // return this.messages.get('toUser') as FormControl
5499
- // }
5500
- // get content() {
5501
- // return this.messages.get('content') as FormControl
5502
- // }
5503
- // get isValid() {
5504
- // return this.toUser.valid
5505
- // }
5506
- // fromMe = (user: string, fromUser: string) => {
5507
- // return user === fromUser
5508
- // }
5509
- // communicationMessages$ = this.stateRequestServiceDemo.communicationMessages$
5510
- // latestCommunicationMessages$ = this.stateRequestServiceDemo.latestCommunicationMessages$
5511
- // chat$: Observable<{ user: any, messages: any[]}|any> = combineLatest([this.user$, this.communicationMessages$])
5512
- // .pipe(
5513
- // map(([user, messages]: any) => ({ user, messages })),
5514
- // map(obj => {
5515
- // if(!obj.user) return EMPTY
5516
- // // const mainUser = UserName.adapt({
5517
- // // id: obj.user.username,
5518
- // // first: obj.user?.name?.first,
5519
- // // last: obj.user?.name?.last,
5520
- // // })
5521
- // const mainUser = ''
5522
- // const messages = obj.messages.map((item: any) => {
5523
- // if(item.toUser === 'allChannels') {
5524
- // // item.toUser = UserName.adapt({
5525
- // // id: '',
5526
- // // first: 'All Users',
5527
- // // last: '',
5528
- // // })
5529
- // }
5530
- // // return Message.adapt({
5531
- // // fromUser: {
5532
- // // id: item.fromUser.username,
5533
- // // first: item.fromUser?.name?.first,
5534
- // // last: item.fromUser?.name?.last,
5535
- // // },
5536
- // // toUser: {
5537
- // // id: item.toUser.username,
5538
- // // first: item.toUser?.name?.first,
5539
- // // last: item.toUser?.name?.last,
5540
- // // },
5541
- // // content: item.content,
5542
- // // date: item.issued,
5543
- // // })
5544
- // })
5545
- // return { user: mainUser, messages }
5546
- // })
5547
- // );
5548
5877
  ngOnInit() {
5549
- // Initialize WS connection and retry driver
5550
5878
  this.stateService.updateConnection(this.server, this.wsServer, this.jwtToken, this.user);
5551
5879
  }
5552
5880
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerWsDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5553
- 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", wsChannel: "wsChannel" }, 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 [wsChannel]=\"wsChannel\"\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 ></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$3.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i1$3.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: i9$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", "wsChannel"] }, { kind: "component", type: WsMessagingComponent, selector: "app-ws-messaging", inputs: ["server", "wsServer", "jwtToken", "user"] }, { 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" }] }); }
5881
+ 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", wsChannel: "wsChannel" }, 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 [wsChannel]=\"wsChannel\"\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 ></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$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", "wsChannel"] }, { kind: "component", type: WsMessagingComponent, selector: "app-ws-messaging", inputs: ["server", "wsServer", "jwtToken", "user"] }, { 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" }] }); }
5554
5882
  }
5555
5883
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerWsDemoComponent, decorators: [{
5556
5884
  type: Component,
@@ -5905,7 +6233,7 @@ class RequestSignalsManagerDemoComponent {
5905
6233
  this.AIType = type;
5906
6234
  }
5907
6235
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestSignalsManagerDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5908
- 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: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i4.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: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6$1.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: i6$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6$1.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: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i9$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i10$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["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: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: FileDownloaderComponent, selector: "app-file-downloader", inputs: ["delayError", "apiRequest", "displayErrorMessage", "saveFileAs", "labels", "disabled"], outputs: ["completed", "failed"] }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
6236
+ 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: i4$1.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$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" }] }); }
5909
6237
  }
5910
6238
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestSignalsManagerDemoComponent, decorators: [{
5911
6239
  type: Component,
@@ -5980,7 +6308,7 @@ class StoreStateManagerDemoComponent {
5980
6308
  this.settingsStateService.getEnum_1().subscribe(data => console.log('DUMP:', data));
5981
6309
  }
5982
6310
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StoreStateManagerDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5983
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: StoreStateManagerDemoComponent, selector: "app-store-state-manager-demo", providers: [SettingsStateService], ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2>\n <span>Store State Manager</span>\n <span style=\"margin-left: .5rem;\">\n <mat-icon color=\"accent\">fiber_new</mat-icon>\n </span>\n </h2>\n\n {{ dataState$ | async | json}}\n\n <div style=\"display: flex; gap:.5rem; margin-top: 1rem; margin-bottom: 1rem;\">\n <button mat-stroked-button (click)=\"onUpdateEnum_1()\">Update Start</button>\n <button mat-stroked-button (click)=\"onUpdateEnum_2()\">Update End</button>\n <button mat-stroked-button (click)=\"onGetEnum_1()\">Dump</button>\n </div>\n\n <div>\n <h3 style=\"margin: 0;\">Enum 1</h3>\n {{ dataEnum$ | async | json}}\n </div>\n\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
6311
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: StoreStateManagerDemoComponent, selector: "app-store-state-manager-demo", providers: [SettingsStateService], ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2>\n <span>Store State Manager</span>\n <span style=\"margin-left: .5rem;\">\n <mat-icon color=\"accent\">fiber_new</mat-icon>\n </span>\n </h2>\n\n {{ dataState$ | async | json}}\n\n <div style=\"display: flex; gap:.5rem; margin-top: 1rem; margin-bottom: 1rem;\">\n <button mat-stroked-button (click)=\"onUpdateEnum_1()\">Update Start</button>\n <button mat-stroked-button (click)=\"onUpdateEnum_2()\">Update End</button>\n <button mat-stroked-button (click)=\"onGetEnum_1()\">Dump</button>\n </div>\n\n <div>\n <h3 style=\"margin: 0;\">Enum 1</h3>\n {{ dataEnum$ | async | json}}\n </div>\n\n</div>\n", styles: [""], dependencies: [{ 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: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
5984
6312
  }
5985
6313
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StoreStateManagerDemoComponent, decorators: [{
5986
6314
  type: Component,
@@ -6266,6 +6594,14 @@ class RequestManagerStateDemoComponent {
6266
6594
  this.stateManagerDemoService = inject(StateManagerDemoService);
6267
6595
  this.displayedColumns = ['id', 'name', 'lastName', 'age'];
6268
6596
  this.fb = inject(FormBuilder);
6597
+ this.streamTypes = [
6598
+ { id: 'JSON', value: 'json' },
6599
+ { id: 'NDJSON', value: 'ndjson' },
6600
+ { id: 'AI Streaming', value: 'ai_streaming' },
6601
+ { id: 'Event Stream', value: 'event_stream' },
6602
+ { id: 'Auto', value: 'auto' },
6603
+ ];
6604
+ this.streamType = 'Auto';
6269
6605
  this.httpManagerService = inject(HTTPManagerService);
6270
6606
  this.isPending$ = this.stateManagerDemoService.isPending$;
6271
6607
  this.error$ = this.stateManagerDemoService.error$;
@@ -6372,6 +6708,9 @@ class RequestManagerStateDemoComponent {
6372
6708
  }
6373
6709
  })).subscribe();
6374
6710
  }
6711
+ onStreamType(type) {
6712
+ this.streamType = type;
6713
+ }
6375
6714
  addHeader() {
6376
6715
  const header = this.fb.group({
6377
6716
  key: ['', Validators.required],
@@ -6432,6 +6771,7 @@ class RequestManagerStateDemoComponent {
6432
6771
  return;
6433
6772
  const reqParams = this.compileRequest();
6434
6773
  reqParams.apiOptions.stream = true;
6774
+ reqParams.apiOptions.streamType = this.streamType;
6435
6775
  this.requestType = 'STREAM';
6436
6776
  this.stateManagerDemoService.streamRequest();
6437
6777
  }
@@ -6457,11 +6797,11 @@ class RequestManagerStateDemoComponent {
6457
6797
  this.prompts = [];
6458
6798
  }
6459
6799
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerStateDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6460
- 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>\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\">\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>\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$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i4.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: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i9$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i10$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["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: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
6800
+ 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\">\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>\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: i4$1.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$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" }] }); }
6461
6801
  }
6462
6802
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerStateDemoComponent, decorators: [{
6463
6803
  type: Component,
6464
- args: [{ selector: 'app-request-manager-state-demo', providers: [StateManagerDemoService, HTTPManagerService], standalone: false, 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>\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\">\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>\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"] }]
6804
+ args: [{ selector: 'app-request-manager-state-demo', providers: [StateManagerDemoService, HTTPManagerService], standalone: false, 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\">\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>\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"] }]
6465
6805
  }], ctorParameters: () => [], propDecorators: { server: [{
6466
6806
  type: Input
6467
6807
  }], adapter: [{
@@ -6508,6 +6848,14 @@ class RequestManagerDemoComponent {
6508
6848
  DELETE: ApiRequest.adapt(),
6509
6849
  STREAM: ApiRequest.adapt(),
6510
6850
  };
6851
+ this.streamTypes = [
6852
+ { id: 'JSON', value: 'json' },
6853
+ { id: 'NDJSON', value: 'ndjson' },
6854
+ { id: 'AI Streaming', value: 'ai_streaming' },
6855
+ { id: 'Event Stream', value: 'event_stream' },
6856
+ { id: 'Auto', value: 'auto' },
6857
+ ];
6858
+ this.streamType = 'Auto';
6511
6859
  this.questionControl = this.fb.control("", [Validators.required]);
6512
6860
  this.downloadRequest = ApiRequest.adapt({
6513
6861
  server: 'assets/images',
@@ -6584,6 +6932,9 @@ class RequestManagerDemoComponent {
6584
6932
  // forkJoin(req2)
6585
6933
  // .subscribe(res => console.log(res))
6586
6934
  }
6935
+ onStreamType(type) {
6936
+ this.streamType = type;
6937
+ }
6587
6938
  addHeader() {
6588
6939
  const header = this.fb.group({
6589
6940
  key: ['', Validators.required],
@@ -6697,6 +7048,7 @@ class RequestManagerDemoComponent {
6697
7048
  apiOptions.server = "api";
6698
7049
  apiPath = ["generate"];
6699
7050
  apiOptions.stream = true;
7051
+ apiOptions.streamType = this.streamType;
6700
7052
  payload = {
6701
7053
  model: "phi3:latest",
6702
7054
  prompt: this.questionControl.value,
@@ -6714,6 +7066,7 @@ class RequestManagerDemoComponent {
6714
7066
  return;
6715
7067
  const reqParams = this.compileRequest();
6716
7068
  reqParams.apiOptions.stream = true;
7069
+ reqParams.apiOptions.streamType = StreamType.NDJSON;
6717
7070
  this.requestParams.GET = reqParams.apiOptions;
6718
7071
  this.STREAM$ = this.httpManagerService.getRequest(reqParams.apiOptions, reqParams.path)
6719
7072
  .pipe(
@@ -6758,11 +7111,11 @@ class RequestManagerDemoComponent {
6758
7111
  this.AIType = type;
6759
7112
  }
6760
7113
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6761
- 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>\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\">\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$ | 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$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i4.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: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6$1.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: i6$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6$1.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: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i9$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i10$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["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: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: FileDownloaderComponent, selector: "app-file-downloader", inputs: ["delayError", "apiRequest", "displayErrorMessage", "saveFileAs", "labels", "disabled"], outputs: ["completed", "failed"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
7114
+ 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\">\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$ | 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: i4$1.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$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" }] }); }
6762
7115
  }
6763
7116
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerDemoComponent, decorators: [{
6764
7117
  type: Component,
6765
- 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>\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\">\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$ | 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"] }]
7118
+ 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\">\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$ | 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"] }]
6766
7119
  }], ctorParameters: () => [], propDecorators: { server: [{
6767
7120
  type: Input
6768
7121
  }], adapter: [{
@@ -6918,7 +7271,7 @@ class LocalStorageDemoComponent {
6918
7271
  this.localStorageManagerService.resetStore();
6919
7272
  }
6920
7273
  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 }); }
6921
- 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: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i4.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: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6$1.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: i6$1.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: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.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: i10$1.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: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i12.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }], encapsulation: i0.ViewEncapsulation.None }); }
7274
+ 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: i4$1.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 }); }
6922
7275
  }
6923
7276
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LocalStorageDemoComponent, decorators: [{
6924
7277
  type: Component,
@@ -7049,7 +7402,7 @@ class DatabaseDataDemoComponent {
7049
7402
  .pipe(tap((data) => console.log('deleteTableRecord:', data)));
7050
7403
  }
7051
7404
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DatabaseDataDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7052
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DatabaseDataDemoComponent, selector: "app-database-data-demo", ngImport: i0, template: "<div style=\"padding: 2rem;\">\n\n <h2>\n Database Manager Service Demo\n </h2>\n\n <div style=\"margin-bottom: 1rem; display: flex; gap: 1rem;\">\n <button mat-stroked-button\n color=\"primary\"\n (click)=\"clearAllData()\"\n >\n Clear Data\n </button>\n <button mat-stroked-button\n color=\"primary\"\n (click)=\"updateData()\"\n >\n Update Data\n </button>\n <div style=\"flex:1\"></div>\n <button\n mat-stroked-button\n color=\"warn\"\n [disabled]=\"!dataToDisplay.length\"\n (click)=\"removeData()\"\n >\n Remove Data\n </button>\n <button mat-stroked-button\n color=\"primary\"\n (click)=\"addData()\"\n >\n Add Data\n </button>\n </div>\n\n <div class=\"table-container\">\n <table mat-table [dataSource]=\"dataSource\">\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=\"last_name\">\n <th mat-header-cell *matHeaderCellDef>Last Name</th>\n <td mat-cell *matCellDef=\"let element\">{{element.last_name}}</td>\n </ng-container>\n\n <ng-container matColumnDef=\"age\">\n <th mat-header-cell *matHeaderCellDef>Age</th>\n <td mat-cell *matCellDef=\"let element\">{{element.age}}</td>\n </ng-container>\n\n <ng-container matColumnDef=\"amount\">\n <th mat-header-cell *matHeaderCellDef>Amount</th>\n <td mat-cell *matCellDef=\"let element\">{{element.amount | currency}}</td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "pipe", type: i1$1.CurrencyPipe, name: "currency" }] }); }
7405
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DatabaseDataDemoComponent, selector: "app-database-data-demo", ngImport: i0, template: "<div style=\"padding: 2rem;\">\n\n <h2>\n Database Manager Service Demo\n </h2>\n\n <div style=\"margin-bottom: 1rem; display: flex; gap: 1rem;\">\n <button mat-stroked-button\n color=\"primary\"\n (click)=\"clearAllData()\"\n >\n Clear Data\n </button>\n <button mat-stroked-button\n color=\"primary\"\n (click)=\"updateData()\"\n >\n Update Data\n </button>\n <div style=\"flex:1\"></div>\n <button\n mat-stroked-button\n color=\"warn\"\n [disabled]=\"!dataToDisplay.length\"\n (click)=\"removeData()\"\n >\n Remove Data\n </button>\n <button mat-stroked-button\n color=\"primary\"\n (click)=\"addData()\"\n >\n Add Data\n </button>\n </div>\n\n <div class=\"table-container\">\n <table mat-table [dataSource]=\"dataSource\">\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=\"last_name\">\n <th mat-header-cell *matHeaderCellDef>Last Name</th>\n <td mat-cell *matCellDef=\"let element\">{{element.last_name}}</td>\n </ng-container>\n\n <ng-container matColumnDef=\"age\">\n <th mat-header-cell *matHeaderCellDef>Age</th>\n <td mat-cell *matCellDef=\"let element\">{{element.age}}</td>\n </ng-container>\n\n <ng-container matColumnDef=\"amount\">\n <th mat-header-cell *matHeaderCellDef>Amount</th>\n <td mat-cell *matCellDef=\"let element\">{{element.amount | currency}}</td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n\n</div>\n", styles: [""], dependencies: [{ 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: 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: "pipe", type: i1$1.CurrencyPipe, name: "currency" }] }); }
7053
7406
  }
7054
7407
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DatabaseDataDemoComponent, decorators: [{
7055
7408
  type: Component,
@@ -7098,7 +7451,7 @@ class HttpRequestServicesDemoComponent {
7098
7451
  this.selectedService = this.requestTypes[type].value;
7099
7452
  }
7100
7453
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HttpRequestServicesDemoComponent, deps: [{ token: CONFIG_SETTINGS_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
7101
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: HttpRequestServicesDemoComponent, selector: "app-http-request-services-demo", inputs: { wsServer: "wsServer", jwtToken: "jwtToken", server: "server", user: "user", path: "path", wsChannel: "wsChannel", adapter: "adapter", mapper: "mapper" }, ngImport: i0, template: "<mat-toolbar style=\"display:flex\">\n <div>Http Request Manager Services</div>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button [matMenuTriggerFor]=\"menu\">Services</button>\n <mat-menu #menu=\"matMenu\">\n @for (type of requestTypes; track type; let i = $index) {\n @if (type?.divider) {\n <div\n style=\"margin-top: .5rem; margin-bottom: .5rem;\"\n >\n <mat-divider></mat-divider>\n </div>\n }\n <button\n mat-menu-item\n (click)=\"onSelected(i)\"\n [disabled]=\"type.disabled\"\n >\n {{ type.name }}\n </button>\n }\n\n </mat-menu>\n</mat-toolbar>\n\n<span>\n @switch (selectedService) {\n @case ('http_service') {\n <p>\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-demo\n [server]=\"server\"\n [adapter]=\"adapter\"\n [mapper]=\"mapper\"\n ></app-request-manager-demo>\n </p>\n }\n <!-- <p *ngSwitchCase=\"'http_signals_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-signals-manager-demo></app-request-signals-manager-demo>\n </p> -->\n @case ('http_state_service') {\n <p>\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-state-demo\n [server]=\"server\"\n [adapter]=\"adapter\"\n [mapper]=\"mapper\"\n ></app-request-manager-state-demo>\n </p>\n }\n @case ('http_state_service_ws') {\n <p>\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-ws-demo\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [wsChannel]=\"wsChannel\"\n [path]=\"path\"\n ></app-request-manager-ws-demo>\n </p>\n }\n @case ('database_service') {\n <p>\n <app-database-data-demo></app-database-data-demo>\n </p>\n }\n @case ('local_storage_service') {\n <p>\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-demo></app-local-storage-demo>\n </p>\n }\n <!-- <p *ngSwitchCase=\"'local_storage_signals_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-signals-demo></app-local-storage-signals-demo>\n</p> -->\n@case ('store_state_manager') {\n <p>\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-store-state-manager-demo></app-store-state-manager-demo>\n </p>\n}\n@default {\n <p>\n Other\n </p>\n}\n}\n</span>\n\n<ng-template #HTTP_OPTIONS>\n @if (injectionOptions?.httpRequestOptions) {\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - HTTP Options</h3>\n {{ injectionOptions?.httpRequestOptions| json }}\n </div>\n }\n</ng-template>\n\n<ng-template #LOCAL_OPTIONS>\n @if (injectionOptions?.LocalStorageOptions) {\n <ng-container class=\"box\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - LocalStorage Options</h3>\n {{ injectionOptions?.LocalStorageOptions| json }}\n </div>\n </ng-container>\n }\n</ng-template>\n\n\n", styles: [".box{padding:1rem;background-color:#f5f5f5;border:thin gray solid;margin-top:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6$1.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: i6$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6$1.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: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: i3$2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo", inputs: ["server", "adapter", "mapper"] }, { kind: "component", type: RequestManagerDemoComponent, selector: "app-request-manager-demo", inputs: ["server", "adapter", "mapper"] }, { kind: "component", type: LocalStorageDemoComponent, selector: "app-local-storage-demo" }, { kind: "component", type: RequestManagerWsDemoComponent, selector: "app-request-manager-ws-demo", inputs: ["server", "wsServer", "jwtToken", "user", "path", "wsChannel"] }, { kind: "component", type: StoreStateManagerDemoComponent, selector: "app-store-state-manager-demo" }, { kind: "component", type: DatabaseDataDemoComponent, selector: "app-database-data-demo" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
7454
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: HttpRequestServicesDemoComponent, selector: "app-http-request-services-demo", inputs: { wsServer: "wsServer", jwtToken: "jwtToken", server: "server", user: "user", path: "path", wsChannel: "wsChannel", adapter: "adapter", mapper: "mapper" }, ngImport: i0, template: "<mat-toolbar style=\"display:flex\">\n <div>Http Request Manager Services</div>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button [matMenuTriggerFor]=\"menu\">Services</button>\n <mat-menu #menu=\"matMenu\">\n @for (type of requestTypes; track type; let i = $index) {\n @if (type?.divider) {\n <div\n style=\"margin-top: .5rem; margin-bottom: .5rem;\"\n >\n <mat-divider></mat-divider>\n </div>\n }\n <button\n mat-menu-item\n (click)=\"onSelected(i)\"\n [disabled]=\"type.disabled\"\n >\n {{ type.name }}\n </button>\n }\n\n </mat-menu>\n</mat-toolbar>\n\n<span>\n @switch (selectedService) {\n @case ('http_service') {\n <p>\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-demo\n [server]=\"server\"\n [adapter]=\"adapter\"\n [mapper]=\"mapper\"\n ></app-request-manager-demo>\n </p>\n }\n <!-- <p *ngSwitchCase=\"'http_signals_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-signals-manager-demo></app-request-signals-manager-demo>\n </p> -->\n @case ('http_state_service') {\n <p>\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-state-demo\n [server]=\"server\"\n [adapter]=\"adapter\"\n [mapper]=\"mapper\"\n ></app-request-manager-state-demo>\n </p>\n }\n @case ('http_state_service_ws') {\n <p>\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-ws-demo\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [wsChannel]=\"wsChannel\"\n [path]=\"path\"\n ></app-request-manager-ws-demo>\n </p>\n }\n @case ('database_service') {\n <p>\n <app-database-data-demo></app-database-data-demo>\n </p>\n }\n @case ('local_storage_service') {\n <p>\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-demo></app-local-storage-demo>\n </p>\n }\n <!-- <p *ngSwitchCase=\"'local_storage_signals_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-signals-demo></app-local-storage-signals-demo>\n</p> -->\n@case ('store_state_manager') {\n <p>\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-store-state-manager-demo></app-store-state-manager-demo>\n </p>\n}\n@default {\n <p>\n Other\n </p>\n}\n}\n</span>\n\n<ng-template #HTTP_OPTIONS>\n @if (injectionOptions?.httpRequestOptions) {\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - HTTP Options</h3>\n {{ injectionOptions?.httpRequestOptions| json }}\n </div>\n }\n</ng-template>\n\n<ng-template #LOCAL_OPTIONS>\n @if (injectionOptions?.LocalStorageOptions) {\n <ng-container class=\"box\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - LocalStorage Options</h3>\n {{ injectionOptions?.LocalStorageOptions| json }}\n </div>\n </ng-container>\n }\n</ng-template>\n\n\n", styles: [".box{padding:1rem;background-color:#f5f5f5;border:thin gray solid;margin-top:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: 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: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: i3$2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo", inputs: ["server", "adapter", "mapper"] }, { kind: "component", type: RequestManagerDemoComponent, selector: "app-request-manager-demo", inputs: ["server", "adapter", "mapper"] }, { kind: "component", type: LocalStorageDemoComponent, selector: "app-local-storage-demo" }, { kind: "component", type: RequestManagerWsDemoComponent, selector: "app-request-manager-ws-demo", inputs: ["server", "wsServer", "jwtToken", "user", "path", "wsChannel"] }, { kind: "component", type: StoreStateManagerDemoComponent, selector: "app-store-state-manager-demo" }, { kind: "component", type: DatabaseDataDemoComponent, selector: "app-database-data-demo" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
7102
7455
  }
7103
7456
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HttpRequestServicesDemoComponent, decorators: [{
7104
7457
  type: Component,
@@ -7132,5 +7485,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
7132
7485
  * Generated bundle index. Do not edit.
7133
7486
  */
7134
7487
 
7135
- export { ApiRequest, AppService, AsymmetricalEncryptionService, CONFIG_SETTINGS_TOKEN, ChannelInfo, ChannelType, CommunicationType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsManagerService, PathQueryService, Random, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomSignature, RandomStr, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UtilsService, WSOptions, WSUser, WebsocketService, WithCredentialsInterceptor, countdown, createChannelName, delayedRetry, requestPolling, requestStreaming };
7488
+ export { ApiRequest, AppService, AsymmetricalEncryptionService, CONFIG_SETTINGS_TOKEN, ChannelInfo, ChannelType, CommunicationType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsManagerService, PathQueryService, Random, RandomHSLColor, RandomHexColor, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomPaletteColor, RandomSignature, RandomStr, RandomVisibleColor, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, StreamType, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UtilsService, WSOptions, WSUser, WebsocketService, WithCredentialsInterceptor, countdown, createChannelName, delayedRetry, requestPolling, requestStreaming, streamAI, streamAuto, streamEvents, streamJSON, streamNDJSON };
7136
7489
  //# sourceMappingURL=http-request-manager.mjs.map