@flusys/ng-shared 1.0.0-beta → 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.
@@ -1,86 +1,235 @@
1
- import * as _angular_core from '@angular/core';
2
- import { Signal, Injector, ResourceRef, model, ElementRef, InjectionToken } from '@angular/core';
3
1
  import { Observable } from 'rxjs';
2
+ import * as _angular_core from '@angular/core';
3
+ import { Signal, Injector, ResourceRef, model, ElementRef, DestroyRef, InjectionToken } from '@angular/core';
4
4
  import * as i1 from '@angular/common';
5
5
  import * as i2 from '@angular/forms';
6
6
  import { ControlValueAccessor } from '@angular/forms';
7
7
  import * as i3 from '@angular/router';
8
- import { CanActivateFn } from '@angular/router';
9
- import * as i1$1 from 'primeng/inputtext';
10
- import * as i2$1 from 'primeng/tag';
11
- import * as i3$1 from 'primeng/selectbutton';
12
- import * as i4 from 'primeng/password';
13
- import * as i5 from 'primeng/button';
14
- import * as i6 from 'primeng/tooltip';
15
- import * as i7 from 'primeng/checkbox';
8
+ import { CanActivateFn, Router, ActivatedRoute } from '@angular/router';
9
+ import * as i1$1 from 'primeng/autocomplete';
10
+ import * as i2$1 from 'primeng/avatar';
11
+ import * as i3$1 from 'primeng/button';
12
+ import * as i4 from 'primeng/card';
13
+ import * as i5 from 'primeng/checkbox';
16
14
  import { CheckboxChangeEvent } from 'primeng/checkbox';
17
- import * as i8 from 'primeng/steps';
18
- import * as i9 from 'primeng/ripple';
19
- import * as i10 from 'primeng/panel';
20
- import * as i11 from 'primeng/paginator';
21
- import * as i12 from 'primeng/table';
22
- import * as i13 from 'primeng/inputnumber';
23
- import * as i14 from 'primeng/textarea';
24
- import * as i15 from 'primeng/progressbar';
25
- import * as i16 from 'primeng/fileupload';
26
- import * as i17 from 'primeng/card';
27
- import * as i18 from 'primeng/select';
28
- import * as i19 from 'primeng/inputicon';
29
- import * as i20 from 'primeng/iconfield';
15
+ import * as i6 from 'primeng/confirmdialog';
16
+ import * as i7 from 'primeng/datepicker';
17
+ import * as i8 from 'primeng/dialog';
18
+ import * as i9 from 'primeng/divider';
19
+ import * as i10 from 'primeng/fileupload';
20
+ import * as i11 from 'primeng/iconfield';
21
+ import * as i12 from 'primeng/image';
22
+ import * as i13 from 'primeng/inputicon';
23
+ import * as i14 from 'primeng/inputnumber';
24
+ import * as i15 from 'primeng/inputtext';
25
+ import * as i16 from 'primeng/listbox';
26
+ import * as i17 from 'primeng/multiselect';
27
+ import * as i18 from 'primeng/paginator';
28
+ import * as i19 from 'primeng/panel';
29
+ import * as i20 from 'primeng/password';
30
30
  import * as i21 from 'primeng/popover';
31
- import * as i22 from 'primeng/listbox';
31
+ import * as i22 from 'primeng/progressbar';
32
32
  import * as i23 from 'primeng/radiobutton';
33
- import * as i24 from 'primeng/toggleswitch';
34
- import * as i25 from 'primeng/image';
35
- import * as i26 from 'primeng/datepicker';
36
- import * as i27 from 'primeng/splitbutton';
37
- import * as i28 from 'primeng/divider';
38
- import * as i29 from 'primeng/multiselect';
39
- import * as i30 from 'primeng/autocomplete';
33
+ import * as i24 from 'primeng/ripple';
34
+ import * as i25 from 'primeng/selectbutton';
35
+ import * as i26 from 'primeng/select';
36
+ import * as i27 from 'primeng/skeleton';
37
+ import * as i28 from 'primeng/splitbutton';
38
+ import * as i29 from 'primeng/steps';
39
+ import * as i30 from 'primeng/table';
40
40
  import * as i31 from 'primeng/tabs';
41
- import * as i32 from 'primeng/dialog';
42
- import * as i33 from 'primeng/treetable';
41
+ import * as i32 from 'primeng/tag';
42
+ import * as i33 from 'primeng/textarea';
43
+ import * as i34 from 'primeng/toast';
44
+ import * as i35 from 'primeng/toggleswitch';
45
+ import * as i36 from 'primeng/tooltip';
46
+ import * as i37 from 'primeng/treetable';
43
47
  import * as _flusys_ng_shared from '@flusys/ng-shared';
44
48
  import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
45
- import { ApiLoaderService } from '@flusys/ng-core';
46
49
  import { FormValueControl } from '@angular/forms/signals';
50
+ import { MessageService, ConfirmationService } from 'primeng/api';
51
+ import * as _flusys_ng_core from '@flusys/ng-core';
47
52
 
48
53
  /**
49
- * Auth State Provider Interface
54
+ * Centralized Permission Codes
50
55
  *
51
- * Abstracts auth state access for feature packages (form-builder, etc.)
52
- * that need to check authentication status without depending on ng-auth directly.
56
+ * Single source of truth for all permission codes used across the application.
57
+ * Use these constants instead of hardcoded strings to prevent typos and enable easy refactoring.
53
58
  *
54
- * @example
55
- * // In form-builder component
56
- * class PublicFormPageComponent {
57
- * private readonly authStateProvider = inject(AUTH_STATE_PROVIDER);
58
- *
59
- * ngOnInit() {
60
- * this.authStateProvider.initialize().subscribe({
61
- * next: () => this.checkFormAccess(),
62
- * error: () => this.checkFormAccess(),
63
- * });
64
- * }
65
- *
66
- * checkAccess() {
67
- * if (this.authStateProvider.isAuthenticated()) {
68
- * // User is logged in
69
- * }
70
- * }
71
- * }
59
+ * Naming Convention: <entity>.<action>
60
+ * - entity: The resource being accessed (e.g., user, role, company)
61
+ * - action: The operation being performed (create, read, update, delete, assign)
72
62
  */
73
- interface IAuthStateProvider {
74
- /**
75
- * Signal indicating if user is currently authenticated
76
- */
77
- isAuthenticated: Signal<boolean>;
78
- /**
79
- * Initialize auth state (restore session from cookies/storage)
80
- * Call this before checking isAuthenticated for users returning after login
81
- */
82
- initialize(): Observable<void>;
83
- }
63
+ declare const USER_PERMISSIONS: {
64
+ readonly CREATE: "user.create";
65
+ readonly READ: "user.read";
66
+ readonly UPDATE: "user.update";
67
+ readonly DELETE: "user.delete";
68
+ };
69
+ declare const COMPANY_PERMISSIONS: {
70
+ readonly CREATE: "company.create";
71
+ readonly READ: "company.read";
72
+ readonly UPDATE: "company.update";
73
+ readonly DELETE: "company.delete";
74
+ };
75
+ declare const BRANCH_PERMISSIONS: {
76
+ readonly CREATE: "branch.create";
77
+ readonly READ: "branch.read";
78
+ readonly UPDATE: "branch.update";
79
+ readonly DELETE: "branch.delete";
80
+ };
81
+ declare const ACTION_PERMISSIONS: {
82
+ readonly CREATE: "action.create";
83
+ readonly READ: "action.read";
84
+ readonly UPDATE: "action.update";
85
+ readonly DELETE: "action.delete";
86
+ };
87
+ declare const ROLE_PERMISSIONS: {
88
+ readonly CREATE: "role.create";
89
+ readonly READ: "role.read";
90
+ readonly UPDATE: "role.update";
91
+ readonly DELETE: "role.delete";
92
+ };
93
+ declare const ROLE_ACTION_PERMISSIONS: {
94
+ readonly READ: "role-action.read";
95
+ readonly ASSIGN: "role-action.assign";
96
+ };
97
+ declare const USER_ROLE_PERMISSIONS: {
98
+ readonly READ: "user-role.read";
99
+ readonly ASSIGN: "user-role.assign";
100
+ };
101
+ declare const USER_ACTION_PERMISSIONS: {
102
+ readonly READ: "user-action.read";
103
+ readonly ASSIGN: "user-action.assign";
104
+ };
105
+ declare const COMPANY_ACTION_PERMISSIONS: {
106
+ readonly READ: "company-action.read";
107
+ readonly ASSIGN: "company-action.assign";
108
+ };
109
+ declare const FILE_PERMISSIONS: {
110
+ readonly CREATE: "file.create";
111
+ readonly READ: "file.read";
112
+ readonly UPDATE: "file.update";
113
+ readonly DELETE: "file.delete";
114
+ };
115
+ declare const FOLDER_PERMISSIONS: {
116
+ readonly CREATE: "folder.create";
117
+ readonly READ: "folder.read";
118
+ readonly UPDATE: "folder.update";
119
+ readonly DELETE: "folder.delete";
120
+ };
121
+ declare const STORAGE_CONFIG_PERMISSIONS: {
122
+ readonly CREATE: "storage-config.create";
123
+ readonly READ: "storage-config.read";
124
+ readonly UPDATE: "storage-config.update";
125
+ readonly DELETE: "storage-config.delete";
126
+ };
127
+ declare const EMAIL_CONFIG_PERMISSIONS: {
128
+ readonly CREATE: "email-config.create";
129
+ readonly READ: "email-config.read";
130
+ readonly UPDATE: "email-config.update";
131
+ readonly DELETE: "email-config.delete";
132
+ };
133
+ declare const EMAIL_TEMPLATE_PERMISSIONS: {
134
+ readonly CREATE: "email-template.create";
135
+ readonly READ: "email-template.read";
136
+ readonly UPDATE: "email-template.update";
137
+ readonly DELETE: "email-template.delete";
138
+ };
139
+ declare const FORM_PERMISSIONS: {
140
+ readonly CREATE: "form.create";
141
+ readonly READ: "form.read";
142
+ readonly UPDATE: "form.update";
143
+ readonly DELETE: "form.delete";
144
+ };
145
+ /**
146
+ * All permission codes grouped by module
147
+ */
148
+ declare const PERMISSIONS: {
149
+ readonly USER: {
150
+ readonly CREATE: "user.create";
151
+ readonly READ: "user.read";
152
+ readonly UPDATE: "user.update";
153
+ readonly DELETE: "user.delete";
154
+ };
155
+ readonly COMPANY: {
156
+ readonly CREATE: "company.create";
157
+ readonly READ: "company.read";
158
+ readonly UPDATE: "company.update";
159
+ readonly DELETE: "company.delete";
160
+ };
161
+ readonly BRANCH: {
162
+ readonly CREATE: "branch.create";
163
+ readonly READ: "branch.read";
164
+ readonly UPDATE: "branch.update";
165
+ readonly DELETE: "branch.delete";
166
+ };
167
+ readonly ACTION: {
168
+ readonly CREATE: "action.create";
169
+ readonly READ: "action.read";
170
+ readonly UPDATE: "action.update";
171
+ readonly DELETE: "action.delete";
172
+ };
173
+ readonly ROLE: {
174
+ readonly CREATE: "role.create";
175
+ readonly READ: "role.read";
176
+ readonly UPDATE: "role.update";
177
+ readonly DELETE: "role.delete";
178
+ };
179
+ readonly ROLE_ACTION: {
180
+ readonly READ: "role-action.read";
181
+ readonly ASSIGN: "role-action.assign";
182
+ };
183
+ readonly USER_ROLE: {
184
+ readonly READ: "user-role.read";
185
+ readonly ASSIGN: "user-role.assign";
186
+ };
187
+ readonly USER_ACTION: {
188
+ readonly READ: "user-action.read";
189
+ readonly ASSIGN: "user-action.assign";
190
+ };
191
+ readonly COMPANY_ACTION: {
192
+ readonly READ: "company-action.read";
193
+ readonly ASSIGN: "company-action.assign";
194
+ };
195
+ readonly FILE: {
196
+ readonly CREATE: "file.create";
197
+ readonly READ: "file.read";
198
+ readonly UPDATE: "file.update";
199
+ readonly DELETE: "file.delete";
200
+ };
201
+ readonly FOLDER: {
202
+ readonly CREATE: "folder.create";
203
+ readonly READ: "folder.read";
204
+ readonly UPDATE: "folder.update";
205
+ readonly DELETE: "folder.delete";
206
+ };
207
+ readonly STORAGE_CONFIG: {
208
+ readonly CREATE: "storage-config.create";
209
+ readonly READ: "storage-config.read";
210
+ readonly UPDATE: "storage-config.update";
211
+ readonly DELETE: "storage-config.delete";
212
+ };
213
+ readonly EMAIL_CONFIG: {
214
+ readonly CREATE: "email-config.create";
215
+ readonly READ: "email-config.read";
216
+ readonly UPDATE: "email-config.update";
217
+ readonly DELETE: "email-config.delete";
218
+ };
219
+ readonly EMAIL_TEMPLATE: {
220
+ readonly CREATE: "email-template.create";
221
+ readonly READ: "email-template.read";
222
+ readonly UPDATE: "email-template.update";
223
+ readonly DELETE: "email-template.delete";
224
+ };
225
+ readonly FORM: {
226
+ readonly CREATE: "form.create";
227
+ readonly READ: "form.read";
228
+ readonly UPDATE: "form.update";
229
+ readonly DELETE: "form.delete";
230
+ };
231
+ };
232
+ type PermissionCode = (typeof PERMISSIONS)[keyof typeof PERMISSIONS][keyof (typeof PERMISSIONS)[keyof typeof PERMISSIONS]];
84
233
 
85
234
  /**
86
235
  * Base entity interface - matches backend Identity entity
@@ -139,6 +288,61 @@ interface ILoggedUserInfo {
139
288
  companyLogoId?: string;
140
289
  branchLogoId?: string;
141
290
  }
291
+ /**
292
+ * Simple dropdown item for select components
293
+ */
294
+ interface IDropDown {
295
+ label: string;
296
+ value: string;
297
+ }
298
+ /**
299
+ * Delete operation types
300
+ * - 'delete': Soft delete (sets deletedAt timestamp)
301
+ * - 'restore': Restore soft-deleted item (clears deletedAt)
302
+ * - 'permanent': Permanently delete from database
303
+ */
304
+ type DeleteType = 'delete' | 'restore' | 'permanent';
305
+ /**
306
+ * Delete request payload - matches backend DeleteDto
307
+ */
308
+ interface IDeleteData {
309
+ /** Single ID or array of IDs to delete */
310
+ id: string | string[];
311
+ /** Type of delete operation */
312
+ type: DeleteType;
313
+ }
314
+ /** Action node - checks a single permission */
315
+ interface IActionNode {
316
+ type: 'action';
317
+ actionId: string;
318
+ }
319
+ /** Group node - combines children with AND/OR logic */
320
+ interface IGroupNode {
321
+ type: 'group';
322
+ operator: 'AND' | 'OR';
323
+ children: ILogicNode[];
324
+ }
325
+ /** Permission logic tree (discriminated union of action/group) */
326
+ type ILogicNode = IActionNode | IGroupNode;
327
+
328
+ interface IPagination {
329
+ pageSize: number;
330
+ currentPage: number;
331
+ }
332
+ interface ISort {
333
+ [key: string]: 'ASC' | 'DESC';
334
+ }
335
+ interface IFilter {
336
+ [key: string]: string | number | boolean | null | undefined | string[] | number[];
337
+ }
338
+ interface IFilterData {
339
+ filter?: IFilter;
340
+ pagination?: IPagination;
341
+ select?: string[];
342
+ sort?: ISort;
343
+ withDeleted?: boolean;
344
+ extraKey?: string[];
345
+ }
142
346
 
143
347
  /**
144
348
  * Request metadata added by backend ResponseMetaInterceptor
@@ -280,158 +484,6 @@ interface IFileData {
280
484
  createdAt: Date;
281
485
  }
282
486
 
283
- /**
284
- * Company basic info for dropdowns
285
- */
286
- interface ICompanyBasicInfo {
287
- id: string;
288
- name: string;
289
- slug?: string;
290
- }
291
- interface ICompanyApiProvider {
292
- /**
293
- * Get list of companies with pagination
294
- */
295
- getCompanies(filter?: {
296
- page?: number;
297
- pageSize?: number;
298
- search?: string;
299
- [key: string]: any;
300
- }): Observable<IListResponse<ICompanyBasicInfo>>;
301
- }
302
-
303
- /**
304
- * Delete operation types
305
- * - 'delete': Soft delete (sets deletedAt timestamp)
306
- * - 'restore': Restore soft-deleted item (clears deletedAt)
307
- * - 'permanent': Permanently delete from database
308
- */
309
- type DeleteType = 'delete' | 'restore' | 'permanent';
310
- /**
311
- * Delete request payload - matches backend DeleteDto
312
- */
313
- interface IDeleteData {
314
- /** Single ID or array of IDs to delete */
315
- id: string | string[];
316
- /** Type of delete operation */
317
- type: DeleteType;
318
- }
319
-
320
- interface IDropDown {
321
- label: string;
322
- value: string;
323
- }
324
-
325
- interface IPagination {
326
- pageSize: number;
327
- currentPage: number;
328
- }
329
- interface ISort {
330
- [key: string]: 'ASC' | 'DESC';
331
- }
332
- interface IFilter {
333
- [key: string]: any;
334
- }
335
- interface IFilterData {
336
- filter?: IFilter;
337
- pagination?: IPagination;
338
- select?: string[];
339
- sort?: ISort;
340
- withDeleted?: boolean;
341
- extraKey?: string[];
342
- }
343
-
344
- /** Action node - checks a single permission */
345
- interface IActionNode {
346
- type: 'action';
347
- actionId: string;
348
- }
349
- /** Group node - combines children with AND/OR logic */
350
- interface IGroupNode {
351
- type: 'group';
352
- operator: 'AND' | 'OR';
353
- children: ILogicNode[];
354
- }
355
- /** Permission logic tree (discriminated union of action/group) */
356
- type ILogicNode = IActionNode | IGroupNode;
357
-
358
- /**
359
- * User Permission Provider Interface
360
- *
361
- * Abstracts user permission data access operations.
362
- * Implemented by auth package, used by IAM for user permission queries.
363
- *
364
- * @example
365
- * // In IAM component
366
- * class UserActionSelectorComponent {
367
- * private readonly userPermissionProvider = inject(USER_PERMISSION_PROVIDER);
368
- *
369
- * async loadUserBranches(userId: string) {
370
- * const response = await this.userPermissionProvider
371
- * .getUserBranchPermissions(userId, '')
372
- * .toPromise();
373
- * this.branches.set(response?.data ?? []);
374
- * }
375
- * }
376
- */
377
- interface IUserPermissionProvider {
378
- /**
379
- * Get user's branch permissions
380
- */
381
- getUserBranchPermissions(userId: string): Observable<ISingleResponse<any>>;
382
- }
383
-
384
- /**
385
- * User data for dropdowns and selectors
386
- */
387
- interface IUserBasicInfo {
388
- id: string;
389
- name: string;
390
- email: string;
391
- }
392
- /**
393
- * User Provider Interface
394
- *
395
- * Abstracts user data access for IAM and other feature packages.
396
- * Implemented by auth package, used by IAM for user selection in permission assignment.
397
- *
398
- * @example
399
- * // In IAM component
400
- * class UserActionSelectorComponent {
401
- * private readonly userProvider = inject(USER_PROVIDER);
402
- *
403
- * loadUsers() {
404
- * this.userProvider.getUsers({ page: 0, pageSize: 50 }).subscribe(users => {
405
- * this.users.set(users.data);
406
- * });
407
- * }
408
- * }
409
- */
410
- interface IUserProvider {
411
- /**
412
- * Get list of users with pagination
413
- * @param filter Optional filter (page, pageSize, search, etc.)
414
- */
415
- getUsers(filter?: {
416
- page?: number;
417
- pageSize?: number;
418
- search?: string;
419
- companyId?: string;
420
- branchId?: string;
421
- [key: string]: any;
422
- }): Observable<IListResponse<IUserBasicInfo>>;
423
- }
424
-
425
- /** Filter params passed to loadUsers function */
426
- interface IUserSelectFilter {
427
- page: number;
428
- pageSize: number;
429
- search: string;
430
- [key: string]: unknown;
431
- }
432
- /** Function type for loading users */
433
- type LoadUsersFn = (filter: IUserSelectFilter) => Observable<IListResponse<IUserBasicInfo>>;
434
-
435
487
  /**
436
488
  * Basic file info for selectors and displays
437
489
  */
@@ -457,6 +509,7 @@ interface IFileUploadOptions {
457
509
  * Uploaded file response
458
510
  */
459
511
  interface IUploadedFile {
512
+ id?: string;
460
513
  name: string;
461
514
  key: string;
462
515
  size: number;
@@ -471,7 +524,6 @@ interface IFileSelectFilter {
471
524
  search: string;
472
525
  contentTypes?: string[];
473
526
  folderId?: string;
474
- [key: string]: unknown;
475
527
  }
476
528
  /**
477
529
  * Function type for loading files
@@ -512,6 +564,188 @@ declare function getFileIconClass(contentType: string): string;
512
564
  */
513
565
  declare function formatFileSize(sizeInKb: string | number): string;
514
566
 
567
+ /**
568
+ * Auth State Provider Interface
569
+ *
570
+ * Abstracts auth state access for feature packages (form-builder, etc.)
571
+ * that need to check authentication status without depending on ng-auth directly.
572
+ */
573
+ interface IAuthStateProvider {
574
+ /** Signal indicating if user is currently authenticated */
575
+ isAuthenticated: Signal<boolean>;
576
+ /** Initialize auth state (restore session from cookies/storage) */
577
+ initialize(): Observable<void>;
578
+ }
579
+ /**
580
+ * User data for dropdowns and selectors
581
+ */
582
+ interface IUserBasicInfo {
583
+ id: string;
584
+ name: string;
585
+ email: string;
586
+ }
587
+ /**
588
+ * User Provider Interface - Abstracts user data access for IAM and other feature packages.
589
+ */
590
+ interface IUserProvider {
591
+ getUsers(filter?: {
592
+ page?: number;
593
+ pageSize?: number;
594
+ search?: string;
595
+ companyId?: string;
596
+ branchId?: string;
597
+ isActive?: boolean;
598
+ }): Observable<IListResponse<IUserBasicInfo>>;
599
+ }
600
+ /** Filter params passed to loadUsers function */
601
+ interface IUserSelectFilter {
602
+ page: number;
603
+ pageSize: number;
604
+ search: string;
605
+ }
606
+ /** Function type for loading users */
607
+ type LoadUsersFn = (filter: IUserSelectFilter) => Observable<IListResponse<IUserBasicInfo>>;
608
+ /**
609
+ * User branch permission data
610
+ */
611
+ interface IUserBranchPermission {
612
+ branchId: string;
613
+ branchName: string;
614
+ companyId: string;
615
+ }
616
+ /**
617
+ * User Permission Provider Interface - Abstracts user permission data access operations.
618
+ */
619
+ interface IUserPermissionProvider {
620
+ getUserBranchPermissions(userId: string): Observable<ISingleResponse<IUserBranchPermission[]>>;
621
+ }
622
+ /**
623
+ * Company basic info for dropdowns
624
+ */
625
+ interface ICompanyBasicInfo {
626
+ id: string;
627
+ name: string;
628
+ slug?: string;
629
+ }
630
+ /**
631
+ * Company API Provider Interface
632
+ */
633
+ interface ICompanyApiProvider {
634
+ getCompanies(filter?: {
635
+ page?: number;
636
+ pageSize?: number;
637
+ search?: string;
638
+ }): Observable<IListResponse<ICompanyBasicInfo>>;
639
+ }
640
+ /**
641
+ * User role info for profile display
642
+ */
643
+ interface IProfileRoleInfo {
644
+ id: string;
645
+ name: string;
646
+ description?: string | null;
647
+ }
648
+ /**
649
+ * User action info for profile display
650
+ */
651
+ interface IProfileActionInfo {
652
+ id: string;
653
+ name: string;
654
+ code: string;
655
+ description?: string | null;
656
+ }
657
+ /**
658
+ * Profile Permission Provider Interface - Abstracts permission data access for profile page.
659
+ */
660
+ interface IProfilePermissionProvider {
661
+ getUserRoles(userId: string, branchId?: string): Observable<ISingleResponse<IProfileRoleInfo[]>>;
662
+ getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
663
+ }
664
+ /**
665
+ * Uploaded file result with file manager ID
666
+ */
667
+ interface IProfileUploadResult {
668
+ id: string;
669
+ name: string;
670
+ key: string;
671
+ size: number;
672
+ contentType: string;
673
+ }
674
+ /**
675
+ * Profile Upload Options
676
+ */
677
+ interface IProfileUploadOptions {
678
+ folderPath?: string;
679
+ compress?: boolean;
680
+ maxWidth?: number;
681
+ maxHeight?: number;
682
+ }
683
+ /**
684
+ * Profile Upload Provider Interface - Provides file upload functionality for profile pictures.
685
+ */
686
+ interface IProfileUploadProvider {
687
+ uploadProfilePicture(file: File, options?: IProfileUploadOptions): Observable<ISingleResponse<IProfileUploadResult>>;
688
+ }
689
+ /**
690
+ * Base user interface for list operations
691
+ */
692
+ interface IUserListItem {
693
+ id: string;
694
+ name: string;
695
+ email: string;
696
+ phone?: string;
697
+ isActive?: boolean;
698
+ }
699
+ /**
700
+ * User list action definition
701
+ */
702
+ interface IUserListAction<T = IUserListItem> {
703
+ id: string;
704
+ label: string;
705
+ icon?: string;
706
+ severity?: 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'help' | 'contrast';
707
+ permission?: string;
708
+ tooltip?: string;
709
+ disabled?: boolean | ((user: T) => boolean);
710
+ visible?: boolean | ((user: T) => boolean);
711
+ }
712
+ /**
713
+ * Extra column definition for user list
714
+ */
715
+ interface IUserListColumn {
716
+ field: string;
717
+ header: string;
718
+ width?: string;
719
+ sortable?: boolean;
720
+ filterable?: boolean;
721
+ templateType?: 'text' | 'badge' | 'date' | 'boolean' | 'custom';
722
+ }
723
+ /**
724
+ * Extra filter definition for user list
725
+ */
726
+ interface IUserListFilter {
727
+ field: string;
728
+ label: string;
729
+ type: 'text' | 'dropdown' | 'multiselect' | 'date' | 'boolean';
730
+ options?: {
731
+ label: string;
732
+ value: string | number | boolean;
733
+ }[];
734
+ placeholder?: string;
735
+ }
736
+ /**
737
+ * User List Provider Interface - Allows apps to extend user list pages.
738
+ */
739
+ interface IUserListProvider<T extends IUserListItem = IUserListItem> {
740
+ getExtraColumns?(): IUserListColumn[];
741
+ getExtraRowActions?(): IUserListAction<T>[];
742
+ getExtraToolbarActions?(): IUserListAction<T>[];
743
+ onRowAction?(actionId: string, user: T): void;
744
+ onToolbarAction?(actionId: string, selectedUsers: T[]): void;
745
+ enrichListData?(users: T[]): Observable<T[]>;
746
+ getExtraFilters?(): IUserListFilter[];
747
+ }
748
+
515
749
  declare enum ContactTypeEnum {
516
750
  PHONE = 1,
517
751
  EMAIL = 2
@@ -532,15 +766,6 @@ declare class CookieService {
532
766
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<CookieService>;
533
767
  }
534
768
 
535
- /**
536
- * Request DTO for fetching file URLs
537
- */
538
- interface GetFilesRequestDto {
539
- id: string;
540
- }
541
- /**
542
- * Response DTO with file information including URL
543
- */
544
769
  interface FilesResponseDto {
545
770
  id: string;
546
771
  name: string;
@@ -549,111 +774,47 @@ interface FilesResponseDto {
549
774
  }
550
775
  /**
551
776
  * Service to fetch file URLs from the backend.
552
- * Uses POST /file-manager/get-files endpoint which:
553
- * - Handles presigned URLs for cloud storage (AWS S3, Azure)
554
- * - Auto-refreshes expired URLs
555
- * - Validates file access permissions
556
- * - Works with all storage providers (Local, S3, Azure, SFTP)
777
+ * Handles presigned URLs for cloud storage, auto-refresh, and caching.
557
778
  */
558
779
  declare class FileUrlService {
559
780
  private readonly http;
560
781
  private readonly appConfig;
561
- /** Cache of file URLs by file ID */
562
- private readonly urlCache;
563
- /**
564
- * Get file URL by ID from cache (reactive signal)
565
- */
782
+ private readonly _cache;
783
+ readonly cache: Signal<Map<string, FilesResponseDto>>;
784
+ /** Get file URL by ID from cache (synchronous) */
566
785
  getFileUrl(fileId: string | null | undefined): string | null;
567
- /**
568
- * Get file URL signal (computed from cache)
569
- */
570
- fileUrlSignal(fileId: string | null | undefined): _angular_core.Signal<string | null>;
571
- /**
572
- * Fetch file URLs from backend and update cache.
573
- * Returns Observable of fetched files.
574
- */
575
- fetchFileUrls(fileIds: string[]): Observable<FilesResponseDto[]>;
576
- /**
577
- * Fetch a single file URL.
578
- * Returns Observable of file info or null if not found.
579
- */
580
- fetchSingleFileUrl(fileId: string): Observable<FilesResponseDto | null>;
581
- /**
582
- * Clear the URL cache.
583
- * Useful on logout or when switching contexts.
584
- */
786
+ /** Get file URL as computed signal */
787
+ fileUrlSignal(fileId: string | null | undefined): Signal<string | null>;
788
+ /** Fetch file URLs from backend and update cache */
789
+ fetchFileUrls(fileIds: string[], forceRefresh?: boolean): Observable<FilesResponseDto[]>;
790
+ /** Fetch single file URL (delegates to fetchFileUrls) */
791
+ fetchSingleFileUrl(fileId: string, forceRefresh?: boolean): Observable<FilesResponseDto | null>;
792
+ /** Clear entire cache */
585
793
  clearCache(): void;
586
- /**
587
- * Remove specific file from cache.
588
- */
794
+ /** Remove specific file from cache */
589
795
  removeFromCache(fileId: string): void;
796
+ private addToCache;
797
+ private getFromCache;
590
798
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUrlService, never>;
591
799
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<FileUrlService>;
592
800
  }
593
801
 
594
802
  /**
595
- * Permission Validator Service
596
- *
597
- * Centralized service for permission validation across all packages.
598
- * Provides signal-based state management and reactive permission checking.
599
- *
600
- * Features:
601
- * - Signal-based permission storage
602
- * - Individual permission checks
603
- * - Permission change detection
604
- * - Reactive permission state updates
605
- *
606
- * Usage:
607
- * ```typescript
608
- * // In component
609
- * readonly permissionValidator = inject(PermissionValidatorService);
610
- *
611
- * // Set permissions (typically from auth/IAM)
612
- * this.permissionValidator.setPermissions(['user.view', 'user.create']);
613
- *
614
- * // Check individual permission
615
- * if (this.permissionValidator.hasPermission('user.view')) {
616
- * // Show UI element
617
- * }
618
- *
619
- * // Access current permissions reactively
620
- * const permissions = this.permissionValidator.permissions();
621
- * ```
622
- *
623
- * @packageDocumentation
803
+ * Permission state management service.
804
+ * Provides signal-based storage and permission checking with wildcard support.
624
805
  */
625
806
  declare class PermissionValidatorService {
626
- /**
627
- * Private writable signal for permissions
628
- */
629
807
  private readonly _permissions;
630
- /**
631
- * Readonly permission signal for external consumers
632
- */
633
808
  readonly permissions: _angular_core.Signal<string[]>;
634
- /**
635
- * Private writable signal for loaded state
636
- */
637
809
  private readonly _isLoaded;
638
- /**
639
- * Set permissions (replaces existing permissions)
640
- * @param permissions - Array of permission codes
641
- */
810
+ readonly isLoaded: _angular_core.Signal<boolean>;
811
+ /** Set permissions (replaces existing) */
642
812
  setPermissions(permissions: string[]): void;
643
- /**
644
- * Clear all permissions
645
- */
813
+ /** Clear all permissions */
646
814
  clearPermissions(): void;
647
- /**
648
- * Check if user has a specific permission
649
- * @param permissionCode - Required permission code
650
- * @returns True if user has permission
651
- */
652
- hasPermission(permissionCode: string): boolean;
653
- /**
654
- * Check if permissions are loaded
655
- * @returns True if permissions have been loaded
656
- */
815
+ /** Check if user has permission (supports wildcards: '*', 'module.*') */
816
+ hasPermission(code: string): boolean;
817
+ /** @deprecated Use `isLoaded()` signal instead */
657
818
  isPermissionsLoaded(): boolean;
658
819
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PermissionValidatorService, never>;
659
820
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<PermissionValidatorService>;
@@ -765,9 +926,9 @@ declare class IsEmptyImageDirective {
765
926
  }
766
927
 
767
928
  declare class PreventDefaultDirective {
768
- eventType: _angular_core.InputSignal<"click" | "keydown" | "keyup">;
769
- preventKey: _angular_core.InputSignal<string | undefined>;
770
- action: _angular_core.OutputEmitterRef<Event>;
929
+ readonly eventType: _angular_core.InputSignal<"click" | "keydown" | "keyup">;
930
+ readonly preventKey: _angular_core.InputSignal<string | undefined>;
931
+ readonly action: _angular_core.OutputEmitterRef<Event>;
771
932
  onClick(event: MouseEvent): void;
772
933
  onKeydown(event: KeyboardEvent): void;
773
934
  onKeyup(event: KeyboardEvent): void;
@@ -778,13 +939,13 @@ declare class PreventDefaultDirective {
778
939
 
779
940
  declare class AngularModule {
780
941
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularModule, never>;
781
- static ɵmod: _angular_core.ɵɵNgModuleDeclaration<AngularModule, never, [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective], [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective]>;
942
+ static ɵmod: _angular_core.ɵɵNgModuleDeclaration<AngularModule, never, [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof i3.RouterLinkActive, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective], [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof i3.RouterLinkActive, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective]>;
782
943
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<AngularModule>;
783
944
  }
784
945
 
785
946
  declare class PrimeModule {
786
947
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PrimeModule, never>;
787
- static ɵmod: _angular_core.ɵɵNgModuleDeclaration<PrimeModule, never, never, [typeof i1$1.InputTextModule, typeof i2$1.TagModule, typeof i3$1.SelectButtonModule, typeof i4.PasswordModule, typeof i5.ButtonModule, typeof i6.TooltipModule, typeof i7.CheckboxModule, typeof i8.StepsModule, typeof i9.RippleModule, typeof i10.PanelModule, typeof i11.PaginatorModule, typeof i12.TableModule, typeof i13.InputNumberModule, typeof i14.TextareaModule, typeof i15.ProgressBarModule, typeof i16.FileUploadModule, typeof i17.CardModule, typeof i18.SelectModule, typeof i19.InputIconModule, typeof i20.IconFieldModule, typeof i21.PopoverModule, typeof i22.ListboxModule, typeof i23.RadioButtonModule, typeof i24.ToggleSwitchModule, typeof i25.ImageModule, typeof i26.DatePickerModule, typeof i27.SplitButtonModule, typeof i28.DividerModule, typeof i29.MultiSelectModule, typeof i30.AutoCompleteModule, typeof i31.TabsModule, typeof i32.DialogModule, typeof i33.TreeTableModule]>;
948
+ static ɵmod: _angular_core.ɵɵNgModuleDeclaration<PrimeModule, never, never, [typeof i1$1.AutoCompleteModule, typeof i2$1.AvatarModule, typeof i3$1.ButtonModule, typeof i4.CardModule, typeof i5.CheckboxModule, typeof i6.ConfirmDialogModule, typeof i7.DatePickerModule, typeof i8.DialogModule, typeof i9.DividerModule, typeof i10.FileUploadModule, typeof i11.IconFieldModule, typeof i12.ImageModule, typeof i13.InputIconModule, typeof i14.InputNumberModule, typeof i15.InputTextModule, typeof i16.ListboxModule, typeof i17.MultiSelectModule, typeof i18.PaginatorModule, typeof i19.PanelModule, typeof i20.PasswordModule, typeof i21.PopoverModule, typeof i22.ProgressBarModule, typeof i23.RadioButtonModule, typeof i24.RippleModule, typeof i25.SelectButtonModule, typeof i26.SelectModule, typeof i27.SkeletonModule, typeof i28.SplitButtonModule, typeof i29.StepsModule, typeof i30.TableModule, typeof i31.TabsModule, typeof i32.TagModule, typeof i33.TextareaModule, typeof i34.ToastModule, typeof i35.ToggleSwitchModule, typeof i36.TooltipModule, typeof i37.TreeTableModule]>;
788
949
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<PrimeModule>;
789
950
  }
790
951
 
@@ -854,7 +1015,6 @@ interface IApiService<DtoT, InterfaceT> {
854
1015
  */
855
1016
  declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiService<DtoT, InterfaceT> {
856
1017
  protected readonly baseUrl: string;
857
- protected readonly loaderService: ApiLoaderService;
858
1018
  protected readonly injector: Injector;
859
1019
  protected readonly http: HttpClient;
860
1020
  protected readonly moduleApiName: string;
@@ -869,6 +1029,12 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
869
1029
  private _listResource;
870
1030
  /** Whether the list resource has been initialized */
871
1031
  private _resourceInitialized;
1032
+ /**
1033
+ * Signal to track resource initialization for computed signals.
1034
+ * This allows computed signals to re-evaluate when the resource is created.
1035
+ * Without this, computed signals would not detect when _listResource changes from null.
1036
+ */
1037
+ private readonly _resourceInitSignal;
872
1038
  /** Get or create the list resource (lazy initialization) */
873
1039
  get listResource(): ResourceRef<IListResponse<InterfaceT> | undefined>;
874
1040
  /**
@@ -877,15 +1043,30 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
877
1043
  * Uses runInInjectionContext to support lazy initialization outside constructor.
878
1044
  */
879
1045
  initListResource(): void;
880
- /** Whether data is currently loading */
1046
+ /**
1047
+ * Whether data is currently loading.
1048
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1049
+ */
881
1050
  readonly isLoading: _angular_core.Signal<boolean>;
882
- /** List data array */
1051
+ /**
1052
+ * List data array.
1053
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1054
+ */
883
1055
  readonly data: _angular_core.Signal<InterfaceT[]>;
884
- /** Total count of items */
1056
+ /**
1057
+ * Total count of items.
1058
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1059
+ */
885
1060
  readonly total: _angular_core.Signal<number>;
886
- /** Pagination metadata */
1061
+ /**
1062
+ * Pagination metadata.
1063
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1064
+ */
887
1065
  readonly pageInfo: _angular_core.Signal<_flusys_ng_shared.IPaginationMeta | undefined>;
888
- /** Whether there are more pages */
1066
+ /**
1067
+ * Whether there are more pages.
1068
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1069
+ */
889
1070
  readonly hasMore: _angular_core.Signal<boolean>;
890
1071
  constructor(moduleApiName: string, http: HttpClient);
891
1072
  protected getHttpOptions(endpoint: string, params?: HttpParams): {
@@ -969,21 +1150,13 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
969
1150
  */
970
1151
  updateAsync(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
971
1152
  /**
972
- * Update multiple items (async)
973
- */
974
- updateManyAsync(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
975
- /**
976
- * Delete items (async)
977
- */
978
- deleteAsync(deleteDto: IDeleteData): Promise<IMessageResponse>;
979
- }
980
-
981
- declare class IconComponent {
982
- icon: _angular_core.InputSignal<string>;
983
- iconType: _angular_core.InputSignal<IconTypeEnum | undefined>;
984
- protected readonly IconTypeEnum: typeof IconTypeEnum;
985
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
986
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<IconComponent, "lib-icon", never, { "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "iconType": { "alias": "iconType"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1153
+ * Update multiple items (async)
1154
+ */
1155
+ updateManyAsync(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
1156
+ /**
1157
+ * Delete items (async)
1158
+ */
1159
+ deleteAsync(deleteDto: IDeleteData): Promise<IMessageResponse>;
987
1160
  }
988
1161
 
989
1162
  /**
@@ -1058,6 +1231,31 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
1058
1231
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormControl<any>, never>;
1059
1232
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormControl<any>, never, never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; }, { "disabled": "disabledChange"; "touched": "touchedChange"; }, never, never, true, never>;
1060
1233
  }
1234
+ /**
1235
+ * Factory function to provide NG_VALUE_ACCESSOR for a component.
1236
+ * Use in component providers array.
1237
+ *
1238
+ * @example
1239
+ * ```typescript
1240
+ * @Component({
1241
+ * providers: [provideValueAccessor(LazySelectComponent)]
1242
+ * })
1243
+ * export class LazySelectComponent extends BaseFormControl<string | null> {}
1244
+ * ```
1245
+ */
1246
+ declare function provideValueAccessor<T extends new (...args: unknown[]) => ControlValueAccessor>(component: T): {
1247
+ provide: _angular_core.InjectionToken<readonly ControlValueAccessor[]>;
1248
+ useExisting: _angular_core.Type<any>;
1249
+ multi: boolean;
1250
+ };
1251
+
1252
+ declare class IconComponent {
1253
+ icon: _angular_core.InputSignal<string>;
1254
+ iconType: _angular_core.InputSignal<IconTypeEnum | undefined>;
1255
+ protected readonly IconTypeEnum: typeof IconTypeEnum;
1256
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
1257
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<IconComponent, "lib-icon", never, { "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "iconType": { "alias": "iconType"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1258
+ }
1061
1259
 
1062
1260
  /**
1063
1261
  * Lazy-loading multi-select component with search, pagination, and select-all.
@@ -1068,31 +1266,28 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
1068
1266
  * - Signal forms: `[formField]="formTree.field"`
1069
1267
  */
1070
1268
  declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null> {
1269
+ private readonly destroyRef;
1270
+ private readonly onDocumentClickBound;
1271
+ readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1071
1272
  readonly placeHolder: _angular_core.InputSignal<string>;
1072
1273
  readonly isEditMode: _angular_core.InputSignal<boolean>;
1073
1274
  readonly isLoading: _angular_core.InputSignal<boolean>;
1074
1275
  readonly total: _angular_core.InputSignal<number | undefined>;
1075
1276
  readonly pagination: _angular_core.InputSignal<IPagination>;
1076
1277
  readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
1077
- /** Two-way bound value using model() for signal forms compatibility */
1078
1278
  readonly value: _angular_core.ModelSignal<string[] | null>;
1079
1279
  readonly onSearch: _angular_core.OutputEmitterRef<string>;
1080
1280
  readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
1081
1281
  readonly searchTerm: _angular_core.WritableSignal<string>;
1082
- /** Computed: Display text for selected values (replaces getSelectedValue method) */
1282
+ readonly openOptions: _angular_core.WritableSignal<boolean>;
1083
1283
  readonly selectedValueDisplay: _angular_core.Signal<string>;
1084
- /** Computed: Whether all items are selected (replaces isSelectAll signal) */
1085
1284
  readonly isSelectAll: _angular_core.Signal<boolean>;
1086
1285
  constructor();
1087
- private readonly onScrollBound;
1088
- readonly multiScrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1089
1286
  onScroll(event: Event): void;
1090
- readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1091
- openOptions: _angular_core.WritableSignal<boolean>;
1092
1287
  onSelectClick(event: Event): void;
1093
1288
  onOverlayClick(event: Event): void;
1094
- handleDocumentClick(event: MouseEvent): void;
1095
- isSelected(data: IDropDown): boolean | undefined;
1289
+ private handleDocumentClick;
1290
+ isSelected(data: IDropDown): boolean;
1096
1291
  key(option: IDropDown): string;
1097
1292
  selectValue(event: CheckboxChangeEvent, option: IDropDown): void;
1098
1293
  changeSelectAll(event: CheckboxChangeEvent): void;
@@ -1110,6 +1305,10 @@ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null>
1110
1305
  * - Signal forms: `[formField]="formTree.field"`
1111
1306
  */
1112
1307
  declare class LazySelectComponent extends BaseFormControl<string | null> {
1308
+ private readonly destroyRef;
1309
+ private readonly onScrollBound;
1310
+ private scrollTargetEl;
1311
+ readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1113
1312
  readonly placeHolder: _angular_core.InputSignal<string>;
1114
1313
  readonly optionLabel: _angular_core.InputSignal<string>;
1115
1314
  readonly optionValue: _angular_core.InputSignal<string>;
@@ -1118,16 +1317,12 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1118
1317
  readonly total: _angular_core.InputSignal<number | undefined>;
1119
1318
  readonly pagination: _angular_core.InputSignal<IPagination>;
1120
1319
  readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
1121
- /** Two-way bound value using model() for signal forms compatibility */
1122
1320
  readonly value: _angular_core.ModelSignal<string | null>;
1123
1321
  readonly onSearch: _angular_core.OutputEmitterRef<string>;
1124
1322
  readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
1125
1323
  readonly searchTerm: _angular_core.WritableSignal<string>;
1324
+ readonly isPanelShow: _angular_core.WritableSignal<boolean>;
1126
1325
  constructor();
1127
- isPanelShow: _angular_core.WritableSignal<boolean>;
1128
- scrollTargetEl: HTMLElement | null;
1129
- private readonly onScrollBound;
1130
- readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1131
1326
  onScroll(event: Event): void;
1132
1327
  showPanel(): void;
1133
1328
  onBlur(): void;
@@ -1135,6 +1330,45 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1135
1330
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazySelectComponent, "lib-lazy-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "optionLabel": { "alias": "optionLabel"; "required": true; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "required": true; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1136
1331
  }
1137
1332
 
1333
+ /**
1334
+ * Base class for user selection components.
1335
+ * Provides shared user loading, pagination, and search functionality.
1336
+ *
1337
+ * Subclasses must implement:
1338
+ * - `setupValueEffect()` to track value changes and emit selection events
1339
+ */
1340
+ declare abstract class BaseUserSelectComponent {
1341
+ protected readonly destroyRef: DestroyRef;
1342
+ protected readonly injector: Injector;
1343
+ protected readonly userProvider: IUserProvider;
1344
+ protected abortController: AbortController | null;
1345
+ readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1346
+ readonly placeHolder: _angular_core.InputSignal<string>;
1347
+ readonly isEditMode: _angular_core.InputSignal<boolean>;
1348
+ readonly filterActive: _angular_core.InputSignal<boolean>;
1349
+ readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
1350
+ readonly pageSize: _angular_core.InputSignal<number>;
1351
+ readonly onError: _angular_core.OutputEmitterRef<Error>;
1352
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1353
+ readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
1354
+ readonly total: _angular_core.WritableSignal<number | undefined>;
1355
+ readonly pagination: _angular_core.WritableSignal<IPagination>;
1356
+ readonly searchTerm: _angular_core.WritableSignal<string>;
1357
+ readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1358
+ constructor();
1359
+ /** Setup effect to track value changes and emit selection events */
1360
+ protected abstract setupValueEffect(): void;
1361
+ handleSearch(search: string): void;
1362
+ handlePagination(pagination: IPagination): void;
1363
+ /** Reload users (useful when filters change externally) */
1364
+ reload(): void;
1365
+ protected fetchUsers(append?: boolean): Promise<void>;
1366
+ /** Load users from USER_PROVIDER with active filter */
1367
+ private loadUsersFromProvider;
1368
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseUserSelectComponent, never>;
1369
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseUserSelectComponent, never, never, { "loadUsers": { "alias": "loadUsers"; "required": false; "isSignal": true; }; "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "filterActive": { "alias": "filterActive"; "required": false; "isSignal": true; }; "additionalFilters": { "alias": "additionalFilters"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; }, { "onError": "onError"; }, never, never, true, never>;
1370
+ }
1371
+
1138
1372
  /**
1139
1373
  * User Select Component - Single user selection with lazy loading.
1140
1374
  *
@@ -1162,35 +1396,12 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1162
1396
  * />
1163
1397
  * ```
1164
1398
  */
1165
- declare class UserSelectComponent {
1166
- private readonly destroyRef;
1167
- private readonly userProvider;
1168
- private abortController;
1169
- readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1170
- readonly placeHolder: _angular_core.InputSignal<string>;
1171
- readonly isEditMode: _angular_core.InputSignal<boolean>;
1172
- readonly filterActive: _angular_core.InputSignal<boolean>;
1173
- readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
1174
- readonly pageSize: _angular_core.InputSignal<number>;
1399
+ declare class UserSelectComponent extends BaseUserSelectComponent {
1175
1400
  readonly value: _angular_core.ModelSignal<string | null>;
1176
1401
  readonly userSelected: _angular_core.OutputEmitterRef<IUserBasicInfo | null>;
1177
- readonly onError: _angular_core.OutputEmitterRef<Error>;
1178
- readonly isLoading: _angular_core.WritableSignal<boolean>;
1179
- readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
1180
- readonly total: _angular_core.WritableSignal<number | undefined>;
1181
- readonly pagination: _angular_core.WritableSignal<IPagination>;
1182
- readonly searchTerm: _angular_core.WritableSignal<string>;
1183
- readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1184
- constructor();
1185
- handleSearch(search: string): void;
1186
- handlePagination(pagination: IPagination): void;
1187
- private fetchUsers;
1188
- /** Load users from USER_PROVIDER with active filter */
1189
- private loadUsersFromProvider;
1190
- /** Reload users (useful when filters change externally) */
1191
- reload(): void;
1402
+ protected setupValueEffect(): void;
1192
1403
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserSelectComponent, never>;
1193
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserSelectComponent, "lib-user-select", never, { "loadUsers": { "alias": "loadUsers"; "required": false; "isSignal": true; }; "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "filterActive": { "alias": "filterActive"; "required": false; "isSignal": true; }; "additionalFilters": { "alias": "additionalFilters"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "userSelected": "userSelected"; "onError": "onError"; }, never, never, true, never>;
1404
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserSelectComponent, "lib-user-select", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "userSelected": "userSelected"; }, never, never, true, never>;
1194
1405
  }
1195
1406
 
1196
1407
  /**
@@ -1221,76 +1432,18 @@ declare class UserSelectComponent {
1221
1432
  * />
1222
1433
  * ```
1223
1434
  */
1224
- declare class UserMultiSelectComponent {
1225
- private readonly destroyRef;
1226
- private readonly userProvider;
1227
- private abortController;
1228
- readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1229
- readonly placeHolder: _angular_core.InputSignal<string>;
1230
- readonly isEditMode: _angular_core.InputSignal<boolean>;
1231
- readonly filterActive: _angular_core.InputSignal<boolean>;
1232
- readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
1233
- readonly pageSize: _angular_core.InputSignal<number>;
1435
+ declare class UserMultiSelectComponent extends BaseUserSelectComponent {
1234
1436
  readonly value: _angular_core.ModelSignal<string[] | null>;
1235
1437
  readonly usersSelected: _angular_core.OutputEmitterRef<IUserBasicInfo[]>;
1236
- readonly onError: _angular_core.OutputEmitterRef<Error>;
1237
- readonly isLoading: _angular_core.WritableSignal<boolean>;
1238
- readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
1239
- readonly total: _angular_core.WritableSignal<number | undefined>;
1240
- readonly pagination: _angular_core.WritableSignal<IPagination>;
1241
- readonly searchTerm: _angular_core.WritableSignal<string>;
1242
- readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1243
- constructor();
1244
- handleSearch(search: string): void;
1245
- handlePagination(pagination: IPagination): void;
1246
- private fetchUsers;
1247
- /** Load users from USER_PROVIDER with active filter */
1248
- private loadUsersFromProvider;
1249
- /** Reload users (useful when filters change externally) */
1250
- reload(): void;
1438
+ protected setupValueEffect(): void;
1251
1439
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserMultiSelectComponent, never>;
1252
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserMultiSelectComponent, "lib-user-multi-select", never, { "loadUsers": { "alias": "loadUsers"; "required": false; "isSignal": true; }; "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "filterActive": { "alias": "filterActive"; "required": false; "isSignal": true; }; "additionalFilters": { "alias": "additionalFilters"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "usersSelected": "usersSelected"; "onError": "onError"; }, never, never, true, never>;
1440
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserMultiSelectComponent, "lib-user-multi-select", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "usersSelected": "usersSelected"; }, never, never, true, never>;
1253
1441
  }
1254
1442
 
1255
1443
  /**
1256
1444
  * File Uploader Component - Drag & drop file upload with type filtering.
1257
1445
  *
1258
1446
  * Pass your own `uploadFile` function - works with any storage API.
1259
- *
1260
- * Features:
1261
- * - Drag & drop support
1262
- * - File type filtering (images, documents, etc.)
1263
- * - Upload progress indication
1264
- * - Multiple file support (optional)
1265
- * - Image compression options
1266
- *
1267
- * @example
1268
- * ```typescript
1269
- * // In component
1270
- * readonly uploadService = inject(UploadService);
1271
- *
1272
- * readonly uploadFile: UploadFileFn = (file, options) =>
1273
- * this.uploadService.uploadSingleFile(file, options);
1274
- * ```
1275
- *
1276
- * ```html
1277
- * <!-- Single image upload -->
1278
- * <lib-file-uploader
1279
- * [uploadFile]="uploadFile"
1280
- * [acceptTypes]="['image/*']"
1281
- * [multiple]="false"
1282
- * (fileUploaded)="onFileUploaded($event)"
1283
- * />
1284
- *
1285
- * <!-- Multiple document upload -->
1286
- * <lib-file-uploader
1287
- * [uploadFile]="uploadFile"
1288
- * [acceptTypes]="FILE_TYPE_FILTERS.DOCUMENTS"
1289
- * [multiple]="true"
1290
- * [maxFiles]="5"
1291
- * (filesUploaded)="onFilesUploaded($event)"
1292
- * />
1293
- * ```
1294
1447
  */
1295
1448
  declare class FileUploaderComponent {
1296
1449
  private readonly messageService;
@@ -1457,65 +1610,372 @@ declare const USER_PERMISSION_PROVIDER: InjectionToken<IUserPermissionProvider>;
1457
1610
  * Provides auth state access for feature packages (form-builder, etc.)
1458
1611
  */
1459
1612
  declare const AUTH_STATE_PROVIDER: InjectionToken<IAuthStateProvider>;
1460
-
1461
1613
  /**
1462
- * Permission Guard
1614
+ * Profile Permission Provider Token
1463
1615
  *
1464
- * Route-level guard for permission-based access control.
1465
- * Validates permissions before allowing navigation.
1616
+ * Provides user permission data for profile display.
1617
+ * Optional - if not configured, profile permissions section is hidden.
1618
+ * Use with `inject(PROFILE_PERMISSION_PROVIDER, { optional: true })`.
1619
+ */
1620
+ declare const PROFILE_PERMISSION_PROVIDER: InjectionToken<IProfilePermissionProvider>;
1621
+ /**
1622
+ * Profile Upload Provider Token
1466
1623
  *
1467
- * Features:
1468
- * - Single permission check
1469
- * - Complex ILogicNode logic trees
1470
- * - Configurable redirect URL
1471
- * - Debug logging for denied access
1624
+ * Provides file upload functionality for profile pictures.
1625
+ * Optional - if not configured or storage not enabled, upload section is hidden.
1626
+ * Use with `inject(PROFILE_UPLOAD_PROVIDER, { optional: true })`.
1627
+ */
1628
+ declare const PROFILE_UPLOAD_PROVIDER: InjectionToken<IProfileUploadProvider>;
1629
+ /**
1630
+ * User List Provider Token
1631
+ *
1632
+ * Provides extra actions, columns, and data enrichment for user list.
1633
+ * Optional - if not configured, default user list behavior is used.
1634
+ * Use with `inject(USER_LIST_PROVIDER, { optional: true })`.
1635
+ *
1636
+ * @example
1637
+ * // In app.config.ts
1638
+ * providers: [
1639
+ * { provide: USER_LIST_PROVIDER, useClass: MyUserListProvider },
1640
+ * ]
1641
+ */
1642
+ declare const USER_LIST_PROVIDER: InjectionToken<IUserListProvider<IUserListItem>>;
1643
+
1644
+ /**
1645
+ * Permission Guard - Single permission or ILogicNode check.
1472
1646
  *
1473
1647
  * @example
1474
1648
  * ```typescript
1475
- * // Simple permission check
1476
1649
  * { path: 'users', canActivate: [permissionGuard('user.view')] }
1477
- *
1478
- * // Complex logic
1479
- * { path: 'admin', canActivate: [permissionGuard({
1480
- * id: 'root',
1481
- * type: 'group',
1482
- * operator: 'AND',
1483
- * children: [
1484
- * { id: '1', type: 'action', actionId: 'admin.view' },
1485
- * { id: '2', type: 'action', actionId: 'admin.manage' }
1486
- * ]
1487
- * })] }
1488
- *
1489
- * // With custom redirect
1490
- * { path: 'users', canActivate: [permissionGuard('user.view', '/access-denied')] }
1650
+ * { path: 'admin', canActivate: [permissionGuard(logicNode, '/access-denied')] }
1491
1651
  * ```
1492
1652
  */
1493
1653
  declare function permissionGuard(permission: string | ILogicNode, redirectTo?: string): CanActivateFn;
1494
1654
  /**
1495
- * Any Permission Guard (OR logic)
1496
- *
1497
- * Allows access if user has ANY of the specified permissions.
1655
+ * Any Permission Guard (OR logic) - Access if user has ANY permission.
1498
1656
  *
1499
1657
  * @example
1500
1658
  * ```typescript
1501
- * // Allow if user has view OR create permission
1502
1659
  * { path: 'users', canActivate: [anyPermissionGuard(['user.view', 'user.create'])] }
1503
1660
  * ```
1504
1661
  */
1505
1662
  declare function anyPermissionGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1506
1663
  /**
1507
- * All Permissions Guard (AND logic)
1508
- *
1509
- * Allows access only if user has ALL of the specified permissions.
1664
+ * All Permissions Guard (AND logic) - Access only if user has ALL permissions.
1510
1665
  *
1511
1666
  * @example
1512
1667
  * ```typescript
1513
- * // Allow only if user has BOTH view AND create permissions
1514
1668
  * { path: 'admin', canActivate: [allPermissionsGuard(['admin.view', 'admin.manage'])] }
1515
1669
  * ```
1516
1670
  */
1517
1671
  declare function allPermissionsGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1518
1672
 
1673
+ /**
1674
+ * Base class for form page components that handle create/edit operations.
1675
+ * Provides common functionality for loading existing items, form submission,
1676
+ * navigation, and toast notifications.
1677
+ *
1678
+ * ## Features
1679
+ * - Automatic route parameter handling (loads item when ID is present)
1680
+ * - Edit mode detection based on existing item
1681
+ * - Unified submit handler for create/update operations
1682
+ * - Cancel navigation
1683
+ * - Toast messages for success/validation errors
1684
+ *
1685
+ * ## Usage
1686
+ *
1687
+ * ```typescript
1688
+ * interface IProductFormModel {
1689
+ * name: string;
1690
+ * price: number;
1691
+ * }
1692
+ *
1693
+ * @Component({
1694
+ * selector: 'app-product-form',
1695
+ * standalone: true,
1696
+ * changeDetection: ChangeDetectionStrategy.OnPush,
1697
+ * template: `...`
1698
+ * })
1699
+ * export class ProductFormComponent extends BaseFormPage<IProduct, IProductFormModel> {
1700
+ * private readonly productService = inject(ProductApiService);
1701
+ *
1702
+ * // Form model signal (private writable, public readonly)
1703
+ * private readonly _formModel = signal<IProductFormModel>({ name: '', price: 0 });
1704
+ * readonly formModel = this._formModel.asReadonly();
1705
+ *
1706
+ * // Required abstract implementations
1707
+ * getFormModel(): Signal<IProductFormModel> {
1708
+ * return this.formModel;
1709
+ * }
1710
+ *
1711
+ * getResourceRoute(): string {
1712
+ * return '/products';
1713
+ * }
1714
+ *
1715
+ * getResourceName(): string {
1716
+ * return 'Product';
1717
+ * }
1718
+ *
1719
+ * isFormValid(): boolean {
1720
+ * const model = this.formModel();
1721
+ * return model.name.trim().length > 0 && model.price > 0;
1722
+ * }
1723
+ *
1724
+ * loadItem(id: string): void {
1725
+ * this.isLoading.set(true);
1726
+ * this.productService.findById(id)
1727
+ * .pipe(takeUntilDestroyed(this.destroyRef))
1728
+ * .subscribe({
1729
+ * next: (response) => {
1730
+ * if (response.success && response.data) {
1731
+ * this.existingItem.set(response.data);
1732
+ * this._formModel.set({
1733
+ * name: response.data.name,
1734
+ * price: response.data.price,
1735
+ * });
1736
+ * }
1737
+ * this.isLoading.set(false);
1738
+ * },
1739
+ * error: () => {
1740
+ * this.router.navigate([this.getResourceRoute()]);
1741
+ * this.isLoading.set(false);
1742
+ * },
1743
+ * });
1744
+ * }
1745
+ *
1746
+ * createItem(model: IProductFormModel): Observable<ISingleResponse<IProduct>> {
1747
+ * return this.productService.insert(model);
1748
+ * }
1749
+ *
1750
+ * updateItem(model: IProductFormModel): Observable<ISingleResponse<IProduct>> {
1751
+ * return this.productService.update({ id: this.existingItem()!.id, ...model });
1752
+ * }
1753
+ * }
1754
+ * ```
1755
+ *
1756
+ * @template T The entity/interface type being edited
1757
+ * @template TFormModel The form model interface
1758
+ */
1759
+ declare abstract class BaseFormPage<T, TFormModel> {
1760
+ protected readonly router: Router;
1761
+ protected readonly route: ActivatedRoute;
1762
+ protected readonly messageService: MessageService;
1763
+ protected readonly destroyRef: DestroyRef;
1764
+ protected readonly routeParams: Signal<i3.ParamMap | undefined>;
1765
+ protected initialized: boolean;
1766
+ /** Loading state for async operations */
1767
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1768
+ /** The existing item when in edit mode, null when creating */
1769
+ readonly existingItem: _angular_core.WritableSignal<T | null>;
1770
+ /** Whether the form is in edit mode (has existing item) */
1771
+ readonly isEditMode: Signal<boolean>;
1772
+ /**
1773
+ * Get the form model signal.
1774
+ * Returns a readonly Signal - implementations should expose their
1775
+ * WritableSignal as readonly through this method.
1776
+ */
1777
+ abstract getFormModel(): Signal<TFormModel>;
1778
+ /**
1779
+ * Get the base route for the resource (used for navigation after save/cancel).
1780
+ * @example '/products' or '/administration/users'
1781
+ */
1782
+ abstract getResourceRoute(): string;
1783
+ /**
1784
+ * Get the display name of the resource for toast messages.
1785
+ * @example 'Product' or 'User'
1786
+ */
1787
+ abstract getResourceName(): string;
1788
+ /**
1789
+ * Validate the current form model.
1790
+ * Return true if the form is valid and can be submitted.
1791
+ */
1792
+ abstract isFormValid(): boolean;
1793
+ /**
1794
+ * Load an existing item by ID.
1795
+ * Should set existingItem and populate formModel on success.
1796
+ * Should handle loading state and navigation on error.
1797
+ */
1798
+ abstract loadItem(id: string): void;
1799
+ /**
1800
+ * Create a new item with the given form model.
1801
+ * Return an Observable that emits the API response.
1802
+ */
1803
+ abstract createItem(model: TFormModel): Observable<unknown>;
1804
+ /**
1805
+ * Update an existing item with the given form model.
1806
+ * Return an Observable that emits the API response.
1807
+ */
1808
+ abstract updateItem(model: TFormModel): Observable<unknown>;
1809
+ constructor();
1810
+ /**
1811
+ * Handle form submission.
1812
+ * Validates the form, then calls createItem or updateItem based on mode.
1813
+ * Shows appropriate toast messages and navigates back on success.
1814
+ */
1815
+ onSubmit(): void;
1816
+ /**
1817
+ * Handle cancel action.
1818
+ * Navigates back to the resource list.
1819
+ */
1820
+ onCancel(): void;
1821
+ /**
1822
+ * Show validation error toast.
1823
+ * Override to customize the validation error message.
1824
+ */
1825
+ protected showValidationError(): void;
1826
+ /**
1827
+ * Show success toast.
1828
+ * @param detail The success message to display
1829
+ */
1830
+ protected showSuccess(detail: string): void;
1831
+ /**
1832
+ * Show error toast.
1833
+ * @param detail The error message to display
1834
+ */
1835
+ protected showError(detail: string): void;
1836
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormPage<any, any>, never>;
1837
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormPage<any, any>, never, never, {}, {}, never, never, true, never>;
1838
+ }
1839
+
1840
+ /**
1841
+ * Base List Page
1842
+ * Abstract directive providing common signals, computed values, and utilities
1843
+ * for list page components across all feature packages.
1844
+ *
1845
+ * Features:
1846
+ * - Pagination state management (pageSize, currentPage, total)
1847
+ * - Loading state
1848
+ * - CRUD navigation helpers
1849
+ * - Message display utilities
1850
+ * - Delete confirmation with API integration
1851
+ * - Company feature flag support
1852
+ *
1853
+ * Usage:
1854
+ * ```typescript
1855
+ * @Component({ ... })
1856
+ * export class UserListComponent extends BaseListPage<IUser> {
1857
+ * getResourceRoute(): string { return '/users'; }
1858
+ * getDeleteConfirmMessage(user: IUser): string { return `Delete "${user.name}"?`; }
1859
+ * async loadData(): Promise<void> { ... }
1860
+ * }
1861
+ * ```
1862
+ */
1863
+ declare abstract class BaseListPage<T> {
1864
+ protected readonly router: Router;
1865
+ protected readonly messageService: MessageService;
1866
+ protected readonly appConfig: _flusys_ng_core.IAppConfig;
1867
+ protected readonly confirmationService: ConfirmationService;
1868
+ protected readonly destroyRef: DestroyRef;
1869
+ /** Items list */
1870
+ readonly items: _angular_core.WritableSignal<T[]>;
1871
+ /** Loading state */
1872
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1873
+ /** Total records for pagination */
1874
+ readonly total: _angular_core.WritableSignal<number>;
1875
+ /** Page size */
1876
+ readonly pageSize: _angular_core.WritableSignal<number>;
1877
+ /** First record index (for p-table lazy load) */
1878
+ readonly first: _angular_core.WritableSignal<number>;
1879
+ /** Current page (0-based for API, derived from first/pageSize) */
1880
+ readonly currentPage: _angular_core.Signal<number>;
1881
+ /** Show company info if company feature enabled */
1882
+ readonly showCompanyInfo: _angular_core.Signal<boolean>;
1883
+ /**
1884
+ * Abstract method to load data - must be implemented by subclass
1885
+ */
1886
+ abstract loadData(): Promise<void>;
1887
+ /**
1888
+ * Get the base route for this resource
1889
+ * Used for navigation to create/edit pages
1890
+ * @example '/administration/users' or '/storage/folders'
1891
+ */
1892
+ abstract getResourceRoute(): string;
1893
+ /**
1894
+ * Get the confirmation message for deleting an item
1895
+ * @param item The item to delete
1896
+ * @returns Confirmation message string
1897
+ */
1898
+ abstract getDeleteConfirmMessage(item: T): string;
1899
+ /**
1900
+ * Navigate to create page
1901
+ */
1902
+ onCreate(): void;
1903
+ /**
1904
+ * Navigate to edit page
1905
+ * @param id The ID of the item to edit
1906
+ */
1907
+ onEdit(id: string): void;
1908
+ /**
1909
+ * Handle page change from p-table lazy load
1910
+ */
1911
+ onPageChange(event: {
1912
+ first?: number | null;
1913
+ rows?: number | null;
1914
+ }): void;
1915
+ /**
1916
+ * Get pagination params for API call
1917
+ * Returns 0-based page for backend API
1918
+ */
1919
+ protected getPaginationParams(): {
1920
+ currentPage: number;
1921
+ pageSize: number;
1922
+ };
1923
+ /**
1924
+ * Show success toast message
1925
+ */
1926
+ protected showSuccess(detail: string, summary?: string): void;
1927
+ /**
1928
+ * Show error toast message
1929
+ */
1930
+ protected showError(detail: string, summary?: string): void;
1931
+ /**
1932
+ * Show info toast message
1933
+ */
1934
+ protected showInfo(detail: string, summary?: string): void;
1935
+ /**
1936
+ * Show warning toast message
1937
+ */
1938
+ protected showWarn(detail: string, summary?: string): void;
1939
+ /**
1940
+ * Delete an item with confirmation dialog
1941
+ * @param item The item to delete
1942
+ * @param idGetter Function to extract ID from item
1943
+ * @param deleteApiCall Function that returns Observable for delete API call
1944
+ * @param options Optional configuration
1945
+ */
1946
+ onDelete(item: T, idGetter: (item: T) => string, deleteApiCall: (id: string) => Observable<unknown>, options?: {
1947
+ header?: string;
1948
+ successMessage?: string;
1949
+ errorMessage?: string;
1950
+ }): void;
1951
+ /**
1952
+ * Delete an item with confirmation dialog using async/await
1953
+ * @param item The item to delete
1954
+ * @param idGetter Function to extract ID from item
1955
+ * @param deleteApiCall Async function for delete API call
1956
+ * @param options Optional configuration
1957
+ */
1958
+ onDeleteAsync(item: T, idGetter: (item: T) => string, deleteApiCall: (id: string) => Promise<unknown>, options?: {
1959
+ header?: string;
1960
+ successMessage?: string;
1961
+ errorMessage?: string;
1962
+ }): Promise<void>;
1963
+ /**
1964
+ * Navigate to a route
1965
+ */
1966
+ protected navigateTo(path: string[]): void;
1967
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseListPage<any>, never>;
1968
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseListPage<any>, never, never, {}, {}, never, never, true, never>;
1969
+ }
1970
+
1971
+ /**
1972
+ * Check if user has a specific permission using wildcard matching.
1973
+ * Supports:
1974
+ * - Exact match: 'user.create' matches 'user.create'
1975
+ * - Full wildcard: '*' matches everything
1976
+ * - Module wildcard: 'user.*' matches 'user.create', 'user.read', etc.
1977
+ */
1978
+ declare function hasPermission(requiredPermission: string, userPermissions: string[]): boolean;
1519
1979
  /** Evaluate permission logic (string or ILogicNode) against user permissions */
1520
1980
  declare function evaluatePermission(logic: string | ILogicNode | null | undefined, permissions: string[]): boolean;
1521
1981
  /** Recursively evaluate an ILogicNode tree */
@@ -1525,5 +1985,38 @@ declare function hasAnyPermission(permissionCodes: string[], permissions: string
1525
1985
  /** Check if user has ALL of the specified permissions (AND logic) */
1526
1986
  declare function hasAllPermissions(permissionCodes: string[], permissions: string[]): boolean;
1527
1987
 
1528
- export { AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, COMPANY_API_PROVIDER, ContactTypeEnum, CookieService, EditModeElementChangerDirective, FILE_TYPE_FILTERS, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, IsEmptyImageDirective, LazyMultiSelectComponent, LazySelectComponent, PermissionValidatorService, PlatformService, PreventDefaultDirective, PrimeModule, USER_PERMISSION_PROVIDER, USER_PROVIDER, UserMultiSelectComponent, UserSelectComponent, allPermissionsGuard, anyPermissionGuard, evaluateLogicNode, evaluatePermission, formatFileSize, getAcceptString, getFileIconClass, hasAllPermissions, hasAnyPermission, isFileTypeAllowed, permissionGuard };
1529
- export type { ApiResponse, DeleteType, FilesResponseDto, GetFileUrlsFn, GetFilesRequestDto, IActionNode, IActivatable, IApiService, IAuthStateProvider, IBaseEntity, IBulkMeta, IBulkResponse, ICompanyApiProvider, ICompanyBasicInfo, IDeleteData, IDropDown, IErrorResponse, IFileBasicInfo, IFileData, IFileSelectFilter, IFileUploadOptions, IFilter, IFilterData, IGroupNode, IListResponse, ILoggedUserInfo, ILogicNode, ILoginResponse, ILoginUserData, IMessageResponse, IMetadata, IOrderable, IPagination, IPaginationMeta, IRefreshTokenResponse, IRequestMeta, ISingleResponse, ISoftDeletable, ISort, ITimestampable, IUploadedFile, IUserBasicInfo, IUserBranchPayload, IUserCompanyPayload, IUserPermissionProvider, IUserProvider, IUserSelectFilter, IValidationError, LoadFilesFn, LoadUsersFn, UploadFileFn };
1988
+ /**
1989
+ * Configuration for scroll pagination behavior
1990
+ */
1991
+ interface ScrollPaginationConfig {
1992
+ /** Distance from bottom to trigger pagination (default: 50px) */
1993
+ threshold?: number;
1994
+ /** Current pagination state */
1995
+ pagination: IPagination;
1996
+ /** Total items available */
1997
+ total: number | undefined;
1998
+ /** Whether currently loading */
1999
+ isLoading: boolean;
2000
+ }
2001
+ /**
2002
+ * Check if scroll has reached near bottom and calculate next page if available.
2003
+ * Returns next pagination if should load more, null otherwise.
2004
+ *
2005
+ * @example
2006
+ * ```typescript
2007
+ * onScroll(event: Event): void {
2008
+ * const nextPagination = checkScrollPagination(event, {
2009
+ * pagination: this.pagination(),
2010
+ * total: this.total(),
2011
+ * isLoading: this.isLoading(),
2012
+ * });
2013
+ * if (nextPagination) {
2014
+ * this.onPagination.emit(nextPagination);
2015
+ * }
2016
+ * }
2017
+ * ```
2018
+ */
2019
+ declare function checkScrollPagination(event: Event, config: ScrollPaginationConfig): IPagination | null;
2020
+
2021
+ export { ACTION_PERMISSIONS, AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, BRANCH_PERMISSIONS, BaseFormControl, BaseFormPage, BaseListPage, BaseUserSelectComponent, COMPANY_ACTION_PERMISSIONS, COMPANY_API_PROVIDER, COMPANY_PERMISSIONS, ContactTypeEnum, CookieService, EMAIL_CONFIG_PERMISSIONS, EMAIL_TEMPLATE_PERMISSIONS, EditModeElementChangerDirective, FILE_PERMISSIONS, FILE_TYPE_FILTERS, FOLDER_PERMISSIONS, FORM_PERMISSIONS, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, IsEmptyImageDirective, LazyMultiSelectComponent, LazySelectComponent, PERMISSIONS, PROFILE_PERMISSION_PROVIDER, PROFILE_UPLOAD_PROVIDER, PermissionValidatorService, PlatformService, PreventDefaultDirective, PrimeModule, ROLE_ACTION_PERMISSIONS, ROLE_PERMISSIONS, STORAGE_CONFIG_PERMISSIONS, USER_ACTION_PERMISSIONS, USER_LIST_PROVIDER, USER_PERMISSIONS, USER_PERMISSION_PROVIDER, USER_PROVIDER, USER_ROLE_PERMISSIONS, UserMultiSelectComponent, UserSelectComponent, allPermissionsGuard, anyPermissionGuard, checkScrollPagination, evaluateLogicNode, evaluatePermission, formatFileSize, getAcceptString, getFileIconClass, hasAllPermissions, hasAnyPermission, hasPermission, isFileTypeAllowed, permissionGuard, provideValueAccessor };
2022
+ export type { ApiResponse, DeleteType, FilesResponseDto, GetFileUrlsFn, IActionNode, IActivatable, IApiService, IAuthStateProvider, IBaseEntity, IBulkMeta, IBulkResponse, ICompanyApiProvider, ICompanyBasicInfo, IDeleteData, IDropDown, IErrorResponse, IFileBasicInfo, IFileData, IFileSelectFilter, IFileUploadOptions, IFilter, IFilterData, IGroupNode, IListResponse, ILoggedUserInfo, ILogicNode, ILoginResponse, ILoginUserData, IMessageResponse, IMetadata, IOrderable, IPagination, IPaginationMeta, IProfileActionInfo, IProfilePermissionProvider, IProfileRoleInfo, IProfileUploadOptions, IProfileUploadProvider, IProfileUploadResult, IRefreshTokenResponse, IRequestMeta, ISingleResponse, ISoftDeletable, ISort, ITimestampable, IUploadedFile, IUserBasicInfo, IUserBranchPayload, IUserBranchPermission, IUserCompanyPayload, IUserListAction, IUserListColumn, IUserListFilter, IUserListItem, IUserListProvider, IUserPermissionProvider, IUserProvider, IUserSelectFilter, IValidationError, LoadFilesFn, LoadUsersFn, PermissionCode, ScrollPaginationConfig, UploadFileFn };