@codex-ts/core-lib 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/core-lib/fesm2022/core-lib.mjs +2349 -0
  2. package/dist/core-lib/fesm2022/core-lib.mjs.map +1 -0
  3. package/dist/core-lib/index.d.ts +29 -0
  4. package/dist/core-lib/lib/components/base-form.component.d.ts +62 -0
  5. package/dist/core-lib/lib/components/base-list-page.component.d.ts +132 -0
  6. package/dist/core-lib/lib/components/base-page.component.d.ts +25 -0
  7. package/dist/core-lib/lib/components/base-tabbed-form.component.d.ts +54 -0
  8. package/dist/core-lib/lib/components/formly/core-formly.module.d.ts +7 -0
  9. package/dist/core-lib/lib/components/formly/form-field.wrapper.d.ts +21 -0
  10. package/dist/core-lib/lib/components/formly/formly.constants.d.ts +13 -0
  11. package/dist/core-lib/lib/components/formly/types/checkbox.type.d.ts +12 -0
  12. package/dist/core-lib/lib/components/formly/types/date.type.d.ts +20 -0
  13. package/dist/core-lib/lib/components/formly/types/multiselect.type.d.ts +26 -0
  14. package/dist/core-lib/lib/components/formly/types/numeric-input.type.d.ts +17 -0
  15. package/dist/core-lib/lib/components/formly/types/radio.type.d.ts +13 -0
  16. package/dist/core-lib/lib/components/formly/types/select.type.d.ts +25 -0
  17. package/dist/core-lib/lib/components/formly/types/text-input.type.d.ts +12 -0
  18. package/dist/core-lib/lib/components/formly/types/textarea.type.d.ts +14 -0
  19. package/dist/core-lib/lib/constants/app.constants.d.ts +13 -0
  20. package/dist/core-lib/lib/constants/app.messages.d.ts +36 -0
  21. package/dist/core-lib/lib/enums/component-context.enum.d.ts +6 -0
  22. package/dist/core-lib/lib/enums/tabbed-form-type.enum.d.ts +4 -0
  23. package/dist/core-lib/lib/models/pagination/filter-criteria.interface.d.ts +9 -0
  24. package/dist/core-lib/lib/models/pagination/page-request.interface.d.ts +10 -0
  25. package/dist/core-lib/lib/models/pagination/page.interface.d.ts +9 -0
  26. package/dist/core-lib/lib/models/pagination/sort-criteria.interface.d.ts +4 -0
  27. package/dist/core-lib/lib/pipes/indian-date.pipe.d.ts +12 -0
  28. package/dist/core-lib/lib/services/base-crud.service.d.ts +36 -0
  29. package/dist/core-lib/lib/services/entity-registry.service.d.ts +26 -0
  30. package/dist/core-lib/lib/services/entity.service.d.ts +9 -0
  31. package/dist/core-lib/lib/services/enum-registry.service.d.ts +41 -0
  32. package/dist/core-lib/lib/services/formly-config.service.d.ts +11 -0
  33. package/dist/core-lib/lib/services/http-utility.service.d.ts +130 -0
  34. package/dist/core-lib/lib/services/notification.service.d.ts +13 -0
  35. package/dist/core-lib/lib/services/reference-data-provider.service.d.ts +8 -0
  36. package/dist/core-lib/lib/services/utils.service.d.ts +72 -0
  37. package/ng-package.json +7 -0
  38. package/package.json +63 -0
  39. package/src/index.ts +44 -0
  40. package/src/lib/components/base-form.component.ts +328 -0
  41. package/src/lib/components/base-list-page.component.ts +327 -0
  42. package/src/lib/components/base-page.component.ts +33 -0
  43. package/src/lib/components/base-tabbed-form.component.ts +345 -0
  44. package/src/lib/components/formly/core-formly.module.ts +34 -0
  45. package/src/lib/components/formly/field.interface.ts +15 -0
  46. package/src/lib/components/formly/form-field.wrapper.ts +94 -0
  47. package/src/lib/components/formly/formly.constants.ts +14 -0
  48. package/src/lib/components/formly/primeng-formly.module.ts +77 -0
  49. package/src/lib/components/formly/types/checkbox.type.ts +43 -0
  50. package/src/lib/components/formly/types/date.type.ts +88 -0
  51. package/src/lib/components/formly/types/multiselect.type.ts +61 -0
  52. package/src/lib/components/formly/types/numeric-input.type.ts +45 -0
  53. package/src/lib/components/formly/types/radio.type.ts +47 -0
  54. package/src/lib/components/formly/types/select.type.ts +54 -0
  55. package/src/lib/components/formly/types/text-input.type.ts +33 -0
  56. package/src/lib/components/formly/types/textarea.type.ts +37 -0
  57. package/src/lib/constants/app.constants.ts +15 -0
  58. package/src/lib/constants/app.messages.ts +36 -0
  59. package/src/lib/enums/component-context.enum.ts +6 -0
  60. package/src/lib/enums/tabbed-form-type.enum.ts +4 -0
  61. package/src/lib/models/pagination/filter-criteria.interface.ts +19 -0
  62. package/src/lib/models/pagination/page-request.interface.ts +13 -0
  63. package/src/lib/models/pagination/page.interface.ts +9 -0
  64. package/src/lib/models/pagination/sort-criteria.interface.ts +4 -0
  65. package/src/lib/pipes/indian-date.pipe.ts +46 -0
  66. package/src/lib/services/base-crud.service.ts +81 -0
  67. package/src/lib/services/entity-registry.service.ts +51 -0
  68. package/src/lib/services/entity.service.ts +10 -0
  69. package/src/lib/services/enum-registry.service.ts +66 -0
  70. package/src/lib/services/formly-config.service.ts +50 -0
  71. package/src/lib/services/http-utility.service.example.ts +253 -0
  72. package/src/lib/services/http-utility.service.md +175 -0
  73. package/src/lib/services/http-utility.service.ts +389 -0
  74. package/src/lib/services/notification.service.ts +35 -0
  75. package/src/lib/services/reference-data-provider.service.ts +28 -0
  76. package/src/lib/services/utils.service.ts +154 -0
@@ -0,0 +1,36 @@
1
+ export const AppMessages = {
2
+ COMMON: {
3
+ ERROR: {
4
+ GENERAL: 'An error occurred',
5
+ INVALID_INPUT: 'Invalid input provided',
6
+ REQUIRED_FIELD: 'This field is required'
7
+ },
8
+ SUCCESS: {
9
+ SAVE: 'saved successfully',
10
+ UPDATE: 'updated successfully',
11
+ DELETE: 'deleted successfully'
12
+ }
13
+ },
14
+ FORM: {
15
+ ERROR: {
16
+ INIT: 'Failed to initialize form',
17
+ SAVE: 'Failed to save',
18
+ LOAD: 'Failed to load',
19
+ VALIDATION: 'Please fill in all required fields correctly'
20
+ },
21
+ SUCCESS: {
22
+ SAVE: 'saved successfully'
23
+ }
24
+ },
25
+ LIST: {
26
+ ERROR: {
27
+ LOAD: 'Failed to load',
28
+ DELETE: 'Failed to delete',
29
+ NAVIGATION: 'Navigation failed',
30
+ INVALID_ID: 'Cannot perform action without ID'
31
+ },
32
+ SUCCESS: {
33
+ DELETE: 'deleted successfully'
34
+ }
35
+ }
36
+ } as const;
@@ -0,0 +1,6 @@
1
+ export enum ComponentContext {
2
+ STANDALONE = 'STANDALONE',
3
+ TABBED = 'TABBED',
4
+ MODAL = 'MODAL',
5
+ EMBEDDED = 'EMBEDDED'
6
+ }
@@ -0,0 +1,4 @@
1
+ export enum TabbedFormType {
2
+ STANDARD = 'STANDARD',
3
+ LIST = 'LIST'
4
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Matches backend FilterCriteria and FilterOperator
3
+ */
4
+ export type FilterOperator =
5
+ | 'EQUALS'
6
+ | 'NOT_EQUALS'
7
+ | 'CONTAINS'
8
+ | 'STARTS_WITH'
9
+ | 'ENDS_WITH'
10
+ | 'LESS_THAN'
11
+ | 'LESS_THAN_EQUALS'
12
+ | 'GREATER_THAN'
13
+ | 'GREATER_THAN_EQUALS';
14
+
15
+ export interface FilterCriteria {
16
+ field: string;
17
+ value: string; // Backend expects all values as strings
18
+ operator: FilterOperator;
19
+ }
@@ -0,0 +1,13 @@
1
+ import { FilterCriteria } from './filter-criteria.interface';
2
+ import { SortCriteria } from './sort-criteria.interface';
3
+
4
+ export interface PageRequest {
5
+ page?: number;
6
+ size?: number;
7
+ sorts?: SortCriteria[];
8
+ filters?: FilterCriteria[];
9
+ }
10
+
11
+ // Re-export for convenience
12
+ export type { FilterCriteria } from './filter-criteria.interface';
13
+ export type { SortCriteria } from './sort-criteria.interface';
@@ -0,0 +1,9 @@
1
+ export interface Page<T> {
2
+ content: T[];
3
+ page:{
4
+ totalElements: number;
5
+ totalPages: number;
6
+ size: number;
7
+ number: number;
8
+ }
9
+ }
@@ -0,0 +1,4 @@
1
+ export interface SortCriteria {
2
+ field: string;
3
+ direction: 'asc' | 'desc';
4
+ }
@@ -0,0 +1,46 @@
1
+ import { Pipe, PipeTransform } from '@angular/core';
2
+ import { DatePipe } from '@angular/common';
3
+
4
+ type DateFormat = 'default' | 'short' | 'medium';
5
+
6
+ @Pipe({
7
+ name: 'indianDate',
8
+ standalone: true
9
+ })
10
+ export class IndianDatePipe implements PipeTransform {
11
+ constructor(private datePipe: DatePipe) {}
12
+
13
+ transform(value: string | null, format: DateFormat = 'default'): string | null {
14
+ if (!value) return null;
15
+
16
+ // First validate dd-MM-yyyy format
17
+ const dateRegex = /^(0[1-9]|[12][0-9]|3[01])-(0[1-9]|1[0-2])-\d{4}$/;
18
+ if (!dateRegex.test(value)) {
19
+ throw new Error(`Invalid date format: ${value}. Expected format: dd-MM-yyyy`);
20
+ }
21
+
22
+ // Validate real date
23
+ const [day, month, year] = value.split('-').map(Number);
24
+ const date = new Date(year, month - 1, day);
25
+ if (
26
+ date.getFullYear() !== year ||
27
+ date.getMonth() !== month - 1 ||
28
+ date.getDate() !== day
29
+ ) {
30
+ throw new Error(`Invalid date: ${value}`);
31
+ }
32
+
33
+ // Apply requested format
34
+ switch (format) {
35
+ case 'short':
36
+ // Pad with leading zeros for consistent format
37
+ const paddedDay = day.toString().padStart(2, '0');
38
+ const paddedMonth = month.toString().padStart(2, '0');
39
+ return `${paddedDay}-${paddedMonth}-${year}`; // 10-03-2025
40
+ case 'medium':
41
+ return this.datePipe.transform(date, 'dd MMM yyyy'); // 10 Jan 2019
42
+ default:
43
+ return value; // original dd-MM-yyyy
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,81 @@
1
+ import { HttpParams, HttpErrorResponse } from '@angular/common/http';
2
+ import { Observable, throwError } from 'rxjs';
3
+ import { HttpUtilityService } from './http-utility.service';
4
+ import { UtilsService } from './utils.service';
5
+ import { MessageService } from 'primeng/api';
6
+ import { Page } from '../models/pagination/page.interface';
7
+ import { PageRequest } from '../models/pagination/page-request.interface';
8
+ import { EntityService } from './entity.service';
9
+
10
+ export abstract class BaseCrudService<T extends { uuid: string }> implements EntityService<T> {
11
+ // Use the loading state from HttpUtilityService
12
+ get loading$() {
13
+ return this.httpUtility.loading$;
14
+ }
15
+
16
+ protected apiUrl: string;
17
+
18
+ /**
19
+ * Creates an instance of BaseCrudService.
20
+ * @param httpUtility - Service for making HTTP requests
21
+ * @param utilsService - Utility service for common operations
22
+ * @param resourcePath - API resource path (e.g., 'customers', 'products')
23
+ * @param backendBaseUrl - Base URL for the backend API
24
+ * @param messageService - Optional service for showing messages
25
+ */
26
+ protected constructor(
27
+ protected httpUtility: HttpUtilityService,
28
+ protected utilsService: UtilsService,
29
+ protected resourcePath: string,
30
+ protected backendBaseUrl: string,
31
+ protected messageService: MessageService | undefined
32
+ ) {
33
+ this.apiUrl = this.joinUrls(backendBaseUrl, resourcePath);
34
+ }
35
+
36
+ /**
37
+ * Joins URL parts ensuring no double slashes
38
+ */
39
+ private joinUrls(...parts: string[]): string {
40
+ return parts.map(part => part.replace(/^\/+|\/+$/g, '')).join('/');
41
+ }
42
+
43
+ getAll(pageRequest?: PageRequest): Observable<Page<T>> {
44
+ if (pageRequest) {
45
+ return this.httpUtility.post<Page<T>>(`${this.apiUrl}/page`, pageRequest);
46
+ } else {
47
+ return this.httpUtility.get<Page<T>>(this.apiUrl);
48
+ }
49
+ }
50
+
51
+ getById(uuid: string): Observable<T> {
52
+ if (!this.utilsService.isValidUUID(uuid)) {
53
+ this.utilsService.showError('Invalid UUID format', this.messageService);
54
+ return throwError(() => new Error('Invalid UUID format'));
55
+ }
56
+
57
+ return this.httpUtility.get<T>(`${this.apiUrl}/${uuid}`);
58
+ }
59
+
60
+ create(entity: Omit<T, 'uuid'>): Observable<T> {
61
+ return this.httpUtility.post<T>(this.apiUrl, entity);
62
+ }
63
+
64
+ update(uuid: string, entity: Omit<T, 'uuid'>): Observable<T> {
65
+ if (!this.utilsService.isValidUUID(uuid)) {
66
+ this.utilsService.showError('Invalid UUID format', this.messageService);
67
+ return throwError(() => new Error('Invalid UUID format'));
68
+ }
69
+
70
+ return this.httpUtility.put<T>(`${this.apiUrl}/${uuid}`, entity);
71
+ }
72
+
73
+ delete(uuid: string): Observable<void> {
74
+ if (!this.utilsService.isValidUUID(uuid)) {
75
+ this.utilsService.showError('Invalid UUID format', this.messageService);
76
+ return throwError(() => new Error('Invalid UUID format'));
77
+ }
78
+
79
+ return this.httpUtility.delete<void>(`${this.apiUrl}/${uuid}`);
80
+ }
81
+ }
@@ -0,0 +1,51 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Observable, map } from 'rxjs';
3
+ import { HttpUtilityService } from './http-utility.service';
4
+ import { ReferenceDataProviderService } from './reference-data-provider.service';
5
+
6
+ export interface ReferenceDto {
7
+ key: string;
8
+ displayLabel: string;
9
+ data?: any;
10
+ }
11
+
12
+ @Injectable({
13
+ providedIn: 'root'
14
+ })
15
+ export class EntityRegistryService {
16
+ constructor(
17
+ private httpUtility: HttpUtilityService,
18
+ private dataProvider: ReferenceDataProviderService
19
+ ) {}
20
+
21
+ /**
22
+ * Gets reference options for an entity, suitable for select/dropdown components
23
+ * @param entityName The name of the entity (e.g., 'customers', 'departments')
24
+ * @returns Observable of options array with label/value pairs
25
+ */
26
+ getEntityOptions(entityName: string): Observable<{ label: string; value: string; data?: any; }[]> {
27
+ console.log('getEntityOptions', entityName);
28
+ const url = this.dataProvider.getReferenceEndpoint(entityName);
29
+
30
+ if (!url) {
31
+ console.warn(`No endpoint configured for entity: ${entityName}`);
32
+ return new Observable(subscriber => {
33
+ subscriber.next([]);
34
+ subscriber.complete();
35
+ });
36
+ }
37
+
38
+ return this.httpUtility.get<ReferenceDto[]>(url, {
39
+ retries: 1,
40
+ timeoutMs: 10000,
41
+ }).pipe(
42
+ map((items) =>
43
+ items?.map((item) => ({
44
+ label: item.displayLabel,
45
+ value: item.key,
46
+ data: item.data,
47
+ })) || []
48
+ )
49
+ );
50
+ }
51
+ }
@@ -0,0 +1,10 @@
1
+ import { Observable } from 'rxjs';
2
+
3
+ /**
4
+ * Interface for basic CRUD operations that all entity services must implement
5
+ */
6
+ export interface EntityService<T> {
7
+ create(data: Omit<T, 'uuid'>): Observable<T>;
8
+ update(uuid: string, data: Omit<T, 'uuid'>): Observable<T>;
9
+ getById(uuid: string): Observable<T>;
10
+ }
@@ -0,0 +1,66 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { UtilsService } from './utils.service';
3
+
4
+ @Injectable({
5
+ providedIn: 'root'
6
+ })
7
+ export class EnumRegistryService {
8
+ private enumMap = new Map<string, any>();
9
+
10
+ constructor(private utilsService: UtilsService) {}
11
+
12
+ /**
13
+ * Initialize global enums
14
+ */
15
+ static registerGlobalEnums(enums: Record<string, any>) {
16
+ return {
17
+ provide: EnumRegistryService,
18
+ useFactory: (utilsService: UtilsService) => {
19
+ const service = new EnumRegistryService(utilsService);
20
+ Object.entries(enums).forEach(([name, enumType]) => {
21
+ service.register(name, enumType);
22
+ });
23
+ return service;
24
+ },
25
+ deps: [UtilsService]
26
+ };
27
+ }
28
+
29
+ /**
30
+ * Register an enum type with the service
31
+ * @param name Name to register the enum under
32
+ * @param enumType The enum type to register
33
+ */
34
+ register(name: string, enumType: any) {
35
+ this.enumMap.set(name, enumType);
36
+ }
37
+
38
+ /**
39
+ * Get formly-compatible options array for a registered enum
40
+ * @param name Name of the registered enum
41
+ * @returns Array of {label, value} pairs suitable for formly select fields
42
+ */
43
+ getEnumValues(name: string) {
44
+ const enumType = this.enumMap.get(name);
45
+ if (!enumType) {
46
+ console.warn(`Enum type "${name}" not found in registry`);
47
+ return [];
48
+ }
49
+ return this.utilsService.getEnumValues(enumType);
50
+ }
51
+
52
+ /**
53
+ * Check if an enum type is registered
54
+ * @param name Name of the enum to check
55
+ */
56
+ hasEnum(name: string): boolean {
57
+ return this.enumMap.has(name);
58
+ }
59
+
60
+ /**
61
+ * Clear all registered enums
62
+ */
63
+ clear() {
64
+ this.enumMap.clear();
65
+ }
66
+ }
@@ -0,0 +1,50 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { FormlyFieldConfig } from '@ngx-formly/core';
3
+ import { PageMode } from '../constants/app.constants';
4
+ import { EnumRegistryService } from './enum-registry.service';
5
+
6
+ @Injectable({
7
+ providedIn: 'root'
8
+ })
9
+ export class FormlyConfigService {
10
+ constructor(private enumRegistry: EnumRegistryService) {}
11
+
12
+ getFormConfig(
13
+ fields: FormlyFieldConfig[],
14
+ mode: PageMode,
15
+ dynamicOptions?: Record<string, any>
16
+ ): FormlyFieldConfig[] {
17
+ const commonConfig = {
18
+ props: {
19
+ disabled: mode === 'view'
20
+ }
21
+ };
22
+
23
+ return fields.map((field: FormlyFieldConfig) => {
24
+ // Apply dynamic options from child component
25
+ if (dynamicOptions && field.key && typeof field.key === 'string') {
26
+ const fieldOptions = dynamicOptions[field.key];
27
+ if (fieldOptions) {
28
+ field.props = {
29
+ ...field.props,
30
+ ...fieldOptions
31
+ };
32
+ }
33
+ }
34
+
35
+ // Handle field groups recursively
36
+ if (field.fieldGroup) {
37
+ field.fieldGroup = this.getFormConfig(field.fieldGroup, mode, dynamicOptions);
38
+ }
39
+
40
+ return {
41
+ ...field,
42
+ ...commonConfig,
43
+ props: {
44
+ ...field.props,
45
+ ...commonConfig.props
46
+ }
47
+ };
48
+ });
49
+ }
50
+ }
@@ -0,0 +1,253 @@
1
+ import { Component, OnInit } from '@angular/core';
2
+ import { HttpHeaders } from '@angular/common/http';
3
+ import { HttpUtilityService } from './http-utility.service';
4
+
5
+ /**
6
+ * Example component showing how to use the HttpUtilityService
7
+ * This is just a demonstration and not an actual component to use.
8
+ */
9
+ @Component({
10
+ selector: 'app-http-utility-example',
11
+ template: `
12
+ <div>
13
+ <h2>HTTP Utility Service Example</h2>
14
+ <div *ngIf="loading">Loading...</div>
15
+ <div *ngIf="user">
16
+ <p>User ID: {{ user.id }}</p>
17
+ <p>Name: {{ user.name }}</p>
18
+ <p>Email: {{ user.email }}</p>
19
+ </div>
20
+ <div *ngIf="errorMessage" class="error">{{ errorMessage }}</div>
21
+ <button (click)="loadUser()">Load User</button>
22
+ <button (click)="createUser()">Create User</button>
23
+ <button (click)="updateUser()">Update User</button>
24
+ <button (click)="deleteUser()">Delete User</button>
25
+ <button (click)="uploadUserPhoto()">Upload Photo</button>
26
+ <button (click)="loadMultipleResources()">Load Multiple Resources</button>
27
+ <button (click)="downloadReport()">Download Report</button>
28
+ </div>
29
+ `
30
+ })
31
+ export class HttpUtilityExampleComponent implements OnInit {
32
+ loading = false;
33
+ user: any;
34
+ errorMessage = '';
35
+
36
+ // Make sure to inject the service in the constructor
37
+ constructor(private httpUtility: HttpUtilityService) {
38
+ // Subscribe to the loading state observable
39
+ this.httpUtility.loading$.subscribe(isLoading => {
40
+ this.loading = isLoading;
41
+ });
42
+ }
43
+
44
+ ngOnInit(): void {
45
+ // Initial data loading
46
+ this.loadUser();
47
+ }
48
+
49
+ /**
50
+ * Example of a GET request with parameters
51
+ */
52
+ loadUser(): void {
53
+ // Clear previous error messages
54
+ this.errorMessage = '';
55
+
56
+ // Creating parameters with the utility method
57
+ const params = this.httpUtility.createParams({
58
+ id: '12345',
59
+ includeDetails: true
60
+ });
61
+
62
+ // Example API call with options
63
+ this.httpUtility.get<any>('/api/users/current', {
64
+ params,
65
+ retries: 3,
66
+ timeoutMs: 10000
67
+ }).subscribe({
68
+ next: (data) => {
69
+ console.log('User data loaded:', data);
70
+ this.user = data;
71
+ },
72
+ error: (error) => {
73
+ console.error('Error loading user:', error);
74
+ this.errorMessage = error.message;
75
+ }
76
+ });
77
+ }
78
+
79
+ /**
80
+ * Example of a POST request with custom headers
81
+ */
82
+ createUser(): void {
83
+ this.errorMessage = '';
84
+
85
+ // Example user data
86
+ const newUser = {
87
+ name: 'John Doe',
88
+ email: 'john.doe@example.com',
89
+ role: 'user'
90
+ };
91
+
92
+ // Custom headers
93
+ const headers = new HttpHeaders({
94
+ 'X-Custom-Header': 'some-value'
95
+ });
96
+
97
+ this.httpUtility.post<any>('/api/users', newUser, {
98
+ headers,
99
+ withCredentials: true
100
+ }).subscribe({
101
+ next: (response) => {
102
+ console.log('User created:', response);
103
+ this.user = response;
104
+ },
105
+ error: (error) => {
106
+ console.error('Error creating user:', error);
107
+ this.errorMessage = error.message;
108
+ }
109
+ });
110
+ }
111
+
112
+ /**
113
+ * Example of a PUT request
114
+ */
115
+ updateUser(): void {
116
+ if (!this.user) {
117
+ this.errorMessage = 'No user loaded to update';
118
+ return;
119
+ }
120
+
121
+ const updatedUser = {
122
+ ...this.user,
123
+ name: 'Updated Name'
124
+ };
125
+
126
+ this.httpUtility.put<any>(`/api/users/${this.user.id}`, updatedUser)
127
+ .subscribe({
128
+ next: (response) => {
129
+ console.log('User updated:', response);
130
+ this.user = response;
131
+ },
132
+ error: (error) => {
133
+ console.error('Error updating user:', error);
134
+ this.errorMessage = error.message;
135
+ }
136
+ });
137
+ }
138
+
139
+ /**
140
+ * Example of a DELETE request
141
+ */
142
+ deleteUser(): void {
143
+ if (!this.user) {
144
+ this.errorMessage = 'No user loaded to delete';
145
+ return;
146
+ }
147
+
148
+ this.httpUtility.delete<void>(`/api/users/${this.user.id}`)
149
+ .subscribe({
150
+ next: () => {
151
+ console.log('User deleted successfully');
152
+ this.user = null;
153
+ },
154
+ error: (error) => {
155
+ console.error('Error deleting user:', error);
156
+ this.errorMessage = error.message;
157
+ }
158
+ });
159
+ }
160
+
161
+ /**
162
+ * Example of file upload with progress tracking
163
+ */
164
+ uploadUserPhoto(): void {
165
+ // In a real application, you would get this from a file input
166
+ // This is just for demonstration purposes
167
+ const file = new File(['dummy content'], 'profile-photo.jpg', { type: 'image/jpeg' });
168
+
169
+ // Additional form data
170
+ const additionalData = {
171
+ userId: this.user?.id || 'unknown',
172
+ description: 'Profile photo'
173
+ };
174
+
175
+ // Define the expected response type
176
+ interface PhotoUploadResponse {
177
+ photoUrl: string;
178
+ timestamp: string;
179
+ fileSize: number;
180
+ }
181
+
182
+ this.httpUtility.uploadFile<PhotoUploadResponse>('/api/users/photo', file, additionalData, {
183
+ onProgress: (percentage) => {
184
+ console.log(`Upload progress: ${percentage}%`);
185
+ // Update UI with progress
186
+ }
187
+ }).subscribe({
188
+ next: (response) => {
189
+ console.log('Photo uploaded:', response);
190
+ // Update user with new photo URL
191
+ this.user = {
192
+ ...this.user,
193
+ photoUrl: response.photoUrl
194
+ };
195
+ },
196
+ error: (error) => {
197
+ console.error('Error uploading photo:', error);
198
+ this.errorMessage = error.message;
199
+ }
200
+ });
201
+ }
202
+
203
+ /**
204
+ * Example of batch requests
205
+ */
206
+ loadMultipleResources(): void {
207
+ // Create multiple requests
208
+ const userRequest = this.httpUtility.get<any>('/api/users/current');
209
+ const postsRequest = this.httpUtility.get<any[]>('/api/posts');
210
+ const notificationsRequest = this.httpUtility.get<any[]>('/api/notifications');
211
+
212
+ // Execute all requests in parallel
213
+ this.httpUtility.batchRequests([
214
+ userRequest,
215
+ postsRequest,
216
+ notificationsRequest
217
+ ]).subscribe({
218
+ next: ([user, posts, notifications]) => {
219
+ console.log('All data loaded:', { user, posts, notifications });
220
+ this.user = user;
221
+ // Handle other data
222
+ },
223
+ error: (error) => {
224
+ console.error('Error loading batch data:', error);
225
+ this.errorMessage = error.message;
226
+ }
227
+ });
228
+ }
229
+
230
+ /**
231
+ * Example of file download
232
+ */
233
+ downloadReport(): void {
234
+ this.httpUtility.downloadFile('/api/reports/user-activity', 'user-activity.pdf')
235
+ .subscribe({
236
+ next: (blob) => {
237
+ // Create a download link and trigger it
238
+ const url = window.URL.createObjectURL(blob);
239
+ const a = document.createElement('a');
240
+ a.href = url;
241
+ a.download = 'user-activity.pdf';
242
+ document.body.appendChild(a);
243
+ a.click();
244
+ window.URL.revokeObjectURL(url);
245
+ a.remove();
246
+ },
247
+ error: (error) => {
248
+ console.error('Error downloading file:', error);
249
+ this.errorMessage = error.message;
250
+ }
251
+ });
252
+ }
253
+ }