@flusys/ng-shared 1.1.0-beta → 1.1.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.
- package/README.md +295 -13
- package/fesm2022/flusys-ng-shared.mjs +1160 -795
- package/fesm2022/flusys-ng-shared.mjs.map +1 -1
- package/package.json +8 -8
- package/types/flusys-ng-shared.d.ts +820 -590
|
@@ -1,11 +1,11 @@
|
|
|
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';
|
|
8
|
+
import { CanActivateFn, Router, ActivatedRoute } from '@angular/router';
|
|
9
9
|
import * as i1$1 from 'primeng/autocomplete';
|
|
10
10
|
import * as i2$1 from 'primeng/avatar';
|
|
11
11
|
import * as i3$1 from 'primeng/button';
|
|
@@ -46,45 +46,190 @@ import * as i36 from 'primeng/tooltip';
|
|
|
46
46
|
import * as i37 from 'primeng/treetable';
|
|
47
47
|
import * as _flusys_ng_shared from '@flusys/ng-shared';
|
|
48
48
|
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
|
|
49
|
-
import { ApiLoaderService } from '@flusys/ng-core';
|
|
50
49
|
import { FormValueControl } from '@angular/forms/signals';
|
|
50
|
+
import { MessageService, ConfirmationService } from 'primeng/api';
|
|
51
|
+
import * as _flusys_ng_core from '@flusys/ng-core';
|
|
51
52
|
|
|
52
53
|
/**
|
|
53
|
-
*
|
|
54
|
+
* Centralized Permission Codes
|
|
54
55
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
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.
|
|
57
58
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* private readonly authStateProvider = inject(AUTH_STATE_PROVIDER);
|
|
62
|
-
*
|
|
63
|
-
* ngOnInit() {
|
|
64
|
-
* this.authStateProvider.initialize().subscribe({
|
|
65
|
-
* next: () => this.checkFormAccess(),
|
|
66
|
-
* error: () => this.checkFormAccess(),
|
|
67
|
-
* });
|
|
68
|
-
* }
|
|
69
|
-
*
|
|
70
|
-
* checkAccess() {
|
|
71
|
-
* if (this.authStateProvider.isAuthenticated()) {
|
|
72
|
-
* // User is logged in
|
|
73
|
-
* }
|
|
74
|
-
* }
|
|
75
|
-
* }
|
|
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)
|
|
76
62
|
*/
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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]];
|
|
88
233
|
|
|
89
234
|
/**
|
|
90
235
|
* Base entity interface - matches backend Identity entity
|
|
@@ -143,6 +288,61 @@ interface ILoggedUserInfo {
|
|
|
143
288
|
companyLogoId?: string;
|
|
144
289
|
branchLogoId?: string;
|
|
145
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
|
+
}
|
|
146
346
|
|
|
147
347
|
/**
|
|
148
348
|
* Request metadata added by backend ResponseMetaInterceptor
|
|
@@ -284,158 +484,6 @@ interface IFileData {
|
|
|
284
484
|
createdAt: Date;
|
|
285
485
|
}
|
|
286
486
|
|
|
287
|
-
/**
|
|
288
|
-
* Company basic info for dropdowns
|
|
289
|
-
*/
|
|
290
|
-
interface ICompanyBasicInfo {
|
|
291
|
-
id: string;
|
|
292
|
-
name: string;
|
|
293
|
-
slug?: string;
|
|
294
|
-
}
|
|
295
|
-
interface ICompanyApiProvider {
|
|
296
|
-
/**
|
|
297
|
-
* Get list of companies with pagination
|
|
298
|
-
*/
|
|
299
|
-
getCompanies(filter?: {
|
|
300
|
-
page?: number;
|
|
301
|
-
pageSize?: number;
|
|
302
|
-
search?: string;
|
|
303
|
-
[key: string]: any;
|
|
304
|
-
}): Observable<IListResponse<ICompanyBasicInfo>>;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Delete operation types
|
|
309
|
-
* - 'delete': Soft delete (sets deletedAt timestamp)
|
|
310
|
-
* - 'restore': Restore soft-deleted item (clears deletedAt)
|
|
311
|
-
* - 'permanent': Permanently delete from database
|
|
312
|
-
*/
|
|
313
|
-
type DeleteType = 'delete' | 'restore' | 'permanent';
|
|
314
|
-
/**
|
|
315
|
-
* Delete request payload - matches backend DeleteDto
|
|
316
|
-
*/
|
|
317
|
-
interface IDeleteData {
|
|
318
|
-
/** Single ID or array of IDs to delete */
|
|
319
|
-
id: string | string[];
|
|
320
|
-
/** Type of delete operation */
|
|
321
|
-
type: DeleteType;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
interface IDropDown {
|
|
325
|
-
label: string;
|
|
326
|
-
value: string;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
interface IPagination {
|
|
330
|
-
pageSize: number;
|
|
331
|
-
currentPage: number;
|
|
332
|
-
}
|
|
333
|
-
interface ISort {
|
|
334
|
-
[key: string]: 'ASC' | 'DESC';
|
|
335
|
-
}
|
|
336
|
-
interface IFilter {
|
|
337
|
-
[key: string]: any;
|
|
338
|
-
}
|
|
339
|
-
interface IFilterData {
|
|
340
|
-
filter?: IFilter;
|
|
341
|
-
pagination?: IPagination;
|
|
342
|
-
select?: string[];
|
|
343
|
-
sort?: ISort;
|
|
344
|
-
withDeleted?: boolean;
|
|
345
|
-
extraKey?: string[];
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/** Action node - checks a single permission */
|
|
349
|
-
interface IActionNode {
|
|
350
|
-
type: 'action';
|
|
351
|
-
actionId: string;
|
|
352
|
-
}
|
|
353
|
-
/** Group node - combines children with AND/OR logic */
|
|
354
|
-
interface IGroupNode {
|
|
355
|
-
type: 'group';
|
|
356
|
-
operator: 'AND' | 'OR';
|
|
357
|
-
children: ILogicNode[];
|
|
358
|
-
}
|
|
359
|
-
/** Permission logic tree (discriminated union of action/group) */
|
|
360
|
-
type ILogicNode = IActionNode | IGroupNode;
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* User Permission Provider Interface
|
|
364
|
-
*
|
|
365
|
-
* Abstracts user permission data access operations.
|
|
366
|
-
* Implemented by auth package, used by IAM for user permission queries.
|
|
367
|
-
*
|
|
368
|
-
* @example
|
|
369
|
-
* // In IAM component
|
|
370
|
-
* class UserActionSelectorComponent {
|
|
371
|
-
* private readonly userPermissionProvider = inject(USER_PERMISSION_PROVIDER);
|
|
372
|
-
*
|
|
373
|
-
* async loadUserBranches(userId: string) {
|
|
374
|
-
* const response = await this.userPermissionProvider
|
|
375
|
-
* .getUserBranchPermissions(userId, '')
|
|
376
|
-
* .toPromise();
|
|
377
|
-
* this.branches.set(response?.data ?? []);
|
|
378
|
-
* }
|
|
379
|
-
* }
|
|
380
|
-
*/
|
|
381
|
-
interface IUserPermissionProvider {
|
|
382
|
-
/**
|
|
383
|
-
* Get user's branch permissions
|
|
384
|
-
*/
|
|
385
|
-
getUserBranchPermissions(userId: string): Observable<ISingleResponse<any>>;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* User data for dropdowns and selectors
|
|
390
|
-
*/
|
|
391
|
-
interface IUserBasicInfo {
|
|
392
|
-
id: string;
|
|
393
|
-
name: string;
|
|
394
|
-
email: string;
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* User Provider Interface
|
|
398
|
-
*
|
|
399
|
-
* Abstracts user data access for IAM and other feature packages.
|
|
400
|
-
* Implemented by auth package, used by IAM for user selection in permission assignment.
|
|
401
|
-
*
|
|
402
|
-
* @example
|
|
403
|
-
* // In IAM component
|
|
404
|
-
* class UserActionSelectorComponent {
|
|
405
|
-
* private readonly userProvider = inject(USER_PROVIDER);
|
|
406
|
-
*
|
|
407
|
-
* loadUsers() {
|
|
408
|
-
* this.userProvider.getUsers({ page: 0, pageSize: 50 }).subscribe(users => {
|
|
409
|
-
* this.users.set(users.data);
|
|
410
|
-
* });
|
|
411
|
-
* }
|
|
412
|
-
* }
|
|
413
|
-
*/
|
|
414
|
-
interface IUserProvider {
|
|
415
|
-
/**
|
|
416
|
-
* Get list of users with pagination
|
|
417
|
-
* @param filter Optional filter (page, pageSize, search, etc.)
|
|
418
|
-
*/
|
|
419
|
-
getUsers(filter?: {
|
|
420
|
-
page?: number;
|
|
421
|
-
pageSize?: number;
|
|
422
|
-
search?: string;
|
|
423
|
-
companyId?: string;
|
|
424
|
-
branchId?: string;
|
|
425
|
-
[key: string]: any;
|
|
426
|
-
}): Observable<IListResponse<IUserBasicInfo>>;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
/** Filter params passed to loadUsers function */
|
|
430
|
-
interface IUserSelectFilter {
|
|
431
|
-
page: number;
|
|
432
|
-
pageSize: number;
|
|
433
|
-
search: string;
|
|
434
|
-
[key: string]: unknown;
|
|
435
|
-
}
|
|
436
|
-
/** Function type for loading users */
|
|
437
|
-
type LoadUsersFn = (filter: IUserSelectFilter) => Observable<IListResponse<IUserBasicInfo>>;
|
|
438
|
-
|
|
439
487
|
/**
|
|
440
488
|
* Basic file info for selectors and displays
|
|
441
489
|
*/
|
|
@@ -476,7 +524,6 @@ interface IFileSelectFilter {
|
|
|
476
524
|
search: string;
|
|
477
525
|
contentTypes?: string[];
|
|
478
526
|
folderId?: string;
|
|
479
|
-
[key: string]: unknown;
|
|
480
527
|
}
|
|
481
528
|
/**
|
|
482
529
|
* Function type for loading files
|
|
@@ -517,6 +564,79 @@ declare function getFileIconClass(contentType: string): string;
|
|
|
517
564
|
*/
|
|
518
565
|
declare function formatFileSize(sizeInKb: string | number): string;
|
|
519
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
|
+
}
|
|
520
640
|
/**
|
|
521
641
|
* User role info for profile display
|
|
522
642
|
*/
|
|
@@ -535,89 +655,39 @@ interface IProfileActionInfo {
|
|
|
535
655
|
description?: string | null;
|
|
536
656
|
}
|
|
537
657
|
/**
|
|
538
|
-
* Profile Permission Provider Interface
|
|
539
|
-
*
|
|
540
|
-
* Abstracts permission data access for profile page.
|
|
541
|
-
* Implemented by ng-iam, consumed by ng-auth profile page.
|
|
542
|
-
* Optional injection - if not provided, permissions section is hidden.
|
|
543
|
-
*
|
|
544
|
-
* @example
|
|
545
|
-
* // In profile component
|
|
546
|
-
* private readonly permissionProvider = inject(PROFILE_PERMISSION_PROVIDER, { optional: true });
|
|
547
|
-
*
|
|
548
|
-
* ngOnInit() {
|
|
549
|
-
* if (this.permissionProvider) {
|
|
550
|
-
* this.loadPermissions();
|
|
551
|
-
* }
|
|
552
|
-
* }
|
|
658
|
+
* Profile Permission Provider Interface - Abstracts permission data access for profile page.
|
|
553
659
|
*/
|
|
554
660
|
interface IProfilePermissionProvider {
|
|
555
|
-
/**
|
|
556
|
-
* Get user's assigned roles
|
|
557
|
-
* @param userId User ID
|
|
558
|
-
* @param branchId Optional branch ID for branch-scoped roles
|
|
559
|
-
*/
|
|
560
661
|
getUserRoles(userId: string, branchId?: string): Observable<ISingleResponse<IProfileRoleInfo[]>>;
|
|
561
|
-
/**
|
|
562
|
-
* Get user's direct actions
|
|
563
|
-
* @param userId User ID
|
|
564
|
-
* @param branchId Optional branch ID for branch-scoped actions
|
|
565
|
-
*/
|
|
566
662
|
getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
|
|
567
663
|
}
|
|
568
|
-
|
|
569
664
|
/**
|
|
570
665
|
* Uploaded file result with file manager ID
|
|
571
666
|
*/
|
|
572
667
|
interface IProfileUploadResult {
|
|
573
|
-
/** File manager ID (UUID) for storing in profilePictureId */
|
|
574
668
|
id: string;
|
|
575
|
-
/** Original file name */
|
|
576
669
|
name: string;
|
|
577
|
-
/** Storage key/path */
|
|
578
670
|
key: string;
|
|
579
|
-
/** File size in bytes */
|
|
580
671
|
size: number;
|
|
581
|
-
/** MIME type */
|
|
582
672
|
contentType: string;
|
|
583
673
|
}
|
|
584
674
|
/**
|
|
585
675
|
* Profile Upload Options
|
|
586
676
|
*/
|
|
587
677
|
interface IProfileUploadOptions {
|
|
588
|
-
/** Folder path for organizing uploads */
|
|
589
678
|
folderPath?: string;
|
|
590
|
-
/** Enable image compression */
|
|
591
679
|
compress?: boolean;
|
|
592
|
-
/** Max width for image compression */
|
|
593
680
|
maxWidth?: number;
|
|
594
|
-
/** Max height for image compression */
|
|
595
681
|
maxHeight?: number;
|
|
596
682
|
}
|
|
597
683
|
/**
|
|
598
|
-
* Profile Upload Provider Interface
|
|
599
|
-
*
|
|
600
|
-
* Provides file upload functionality for profile pictures.
|
|
601
|
-
* Implemented by ng-storage, consumed by ng-auth profile page.
|
|
602
|
-
*
|
|
603
|
-
* This interface enables ng-auth to use storage functionality
|
|
604
|
-
* without directly depending on ng-storage package.
|
|
684
|
+
* Profile Upload Provider Interface - Provides file upload functionality for profile pictures.
|
|
605
685
|
*/
|
|
606
686
|
interface IProfileUploadProvider {
|
|
607
|
-
/**
|
|
608
|
-
* Upload profile picture and register in file manager
|
|
609
|
-
* Returns file manager ID (UUID) for storing in user.profilePictureId
|
|
610
|
-
*
|
|
611
|
-
* @param file - File to upload
|
|
612
|
-
* @param options - Upload options (compression, folder, etc.)
|
|
613
|
-
* @returns Observable with upload result including file manager ID
|
|
614
|
-
*/
|
|
615
687
|
uploadProfilePicture(file: File, options?: IProfileUploadOptions): Observable<ISingleResponse<IProfileUploadResult>>;
|
|
616
688
|
}
|
|
617
|
-
|
|
618
689
|
/**
|
|
619
690
|
* Base user interface for list operations
|
|
620
|
-
* Extends this with app-specific user fields
|
|
621
691
|
*/
|
|
622
692
|
interface IUserListItem {
|
|
623
693
|
id: string;
|
|
@@ -625,140 +695,56 @@ interface IUserListItem {
|
|
|
625
695
|
email: string;
|
|
626
696
|
phone?: string;
|
|
627
697
|
isActive?: boolean;
|
|
628
|
-
[key: string]: unknown;
|
|
629
698
|
}
|
|
630
699
|
/**
|
|
631
700
|
* User list action definition
|
|
632
|
-
* @template T User type, defaults to IUserListItem
|
|
633
701
|
*/
|
|
634
702
|
interface IUserListAction<T = IUserListItem> {
|
|
635
|
-
/** Unique action identifier */
|
|
636
703
|
id: string;
|
|
637
|
-
/** Display label */
|
|
638
704
|
label: string;
|
|
639
|
-
/** PrimeNG icon class (e.g., 'pi pi-pencil') */
|
|
640
705
|
icon?: string;
|
|
641
|
-
/** Severity for styling (e.g., 'primary', 'danger', 'warning') */
|
|
642
706
|
severity?: 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'help' | 'contrast';
|
|
643
|
-
/** Permission code required (checked via hasPermission) */
|
|
644
707
|
permission?: string;
|
|
645
|
-
/** Tooltip text */
|
|
646
708
|
tooltip?: string;
|
|
647
|
-
/** Whether action is disabled */
|
|
648
709
|
disabled?: boolean | ((user: T) => boolean);
|
|
649
|
-
/** Whether action is visible */
|
|
650
710
|
visible?: boolean | ((user: T) => boolean);
|
|
651
711
|
}
|
|
652
712
|
/**
|
|
653
713
|
* Extra column definition for user list
|
|
654
714
|
*/
|
|
655
715
|
interface IUserListColumn {
|
|
656
|
-
/** Column field name */
|
|
657
716
|
field: string;
|
|
658
|
-
/** Column header label */
|
|
659
717
|
header: string;
|
|
660
|
-
/** Column width */
|
|
661
718
|
width?: string;
|
|
662
|
-
/** Whether column is sortable */
|
|
663
719
|
sortable?: boolean;
|
|
664
|
-
/** Whether column is filterable */
|
|
665
720
|
filterable?: boolean;
|
|
666
|
-
/** Custom template type for rendering */
|
|
667
721
|
templateType?: 'text' | 'badge' | 'date' | 'boolean' | 'custom';
|
|
668
722
|
}
|
|
669
|
-
/**
|
|
670
|
-
* User List Provider Interface
|
|
671
|
-
*
|
|
672
|
-
* Allows consuming applications to extend user list pages with:
|
|
673
|
-
* - Extra columns
|
|
674
|
-
* - Extra row actions
|
|
675
|
-
* - Extra toolbar actions
|
|
676
|
-
* - Custom data enrichment
|
|
677
|
-
*
|
|
678
|
-
* This follows the Provider Interface Pattern:
|
|
679
|
-
* - ng-shared defines the interface (this file)
|
|
680
|
-
* - Consuming apps (via ng-iam or app-specific) implement the interface
|
|
681
|
-
* - ng-auth user list optionally injects and uses the implementation
|
|
682
|
-
*
|
|
683
|
-
* @template T User type, defaults to IUserListItem
|
|
684
|
-
*
|
|
685
|
-
* @example
|
|
686
|
-
* // In app.config.ts
|
|
687
|
-
* providers: [
|
|
688
|
-
* { provide: USER_LIST_PROVIDER, useClass: MyUserListProvider },
|
|
689
|
-
* ]
|
|
690
|
-
*
|
|
691
|
-
* // Implementation
|
|
692
|
-
* @Injectable({ providedIn: 'root' })
|
|
693
|
-
* export class MyUserListProvider implements IUserListProvider {
|
|
694
|
-
* getExtraRowActions() {
|
|
695
|
-
* return [
|
|
696
|
-
* { id: 'assign-role', label: 'Assign Role', icon: 'pi pi-users' },
|
|
697
|
-
* ];
|
|
698
|
-
* }
|
|
699
|
-
* }
|
|
700
|
-
*/
|
|
701
|
-
interface IUserListProvider<T extends IUserListItem = IUserListItem> {
|
|
702
|
-
/**
|
|
703
|
-
* Get extra columns to display in user list
|
|
704
|
-
* @returns Array of extra column definitions
|
|
705
|
-
*/
|
|
706
|
-
getExtraColumns?(): IUserListColumn[];
|
|
707
|
-
/**
|
|
708
|
-
* Get extra row-level actions (per-user actions)
|
|
709
|
-
* Displayed in actions column for each row
|
|
710
|
-
* @returns Array of action definitions
|
|
711
|
-
*/
|
|
712
|
-
getExtraRowActions?(): IUserListAction<T>[];
|
|
713
|
-
/**
|
|
714
|
-
* Get extra toolbar actions
|
|
715
|
-
* Displayed in toolbar above the list
|
|
716
|
-
* @returns Array of action definitions
|
|
717
|
-
*/
|
|
718
|
-
getExtraToolbarActions?(): IUserListAction<T>[];
|
|
719
|
-
/**
|
|
720
|
-
* Handle row action click
|
|
721
|
-
* @param actionId Action identifier
|
|
722
|
-
* @param user User data from the row
|
|
723
|
-
*/
|
|
724
|
-
onRowAction?(actionId: string, user: T): void;
|
|
725
|
-
/**
|
|
726
|
-
* Handle toolbar action click
|
|
727
|
-
* @param actionId Action identifier
|
|
728
|
-
* @param selectedUsers Currently selected users (for bulk actions)
|
|
729
|
-
*/
|
|
730
|
-
onToolbarAction?(actionId: string, selectedUsers: T[]): void;
|
|
731
|
-
/**
|
|
732
|
-
* Enrich user list data with extra fields
|
|
733
|
-
* Called after data is loaded from API
|
|
734
|
-
* @param users List of users from API
|
|
735
|
-
* @returns Observable of enriched users
|
|
736
|
-
*/
|
|
737
|
-
enrichListData?(users: T[]): Observable<T[]>;
|
|
738
|
-
/**
|
|
739
|
-
* Get extra filters for user list
|
|
740
|
-
* @returns Array of filter definitions
|
|
741
|
-
*/
|
|
742
|
-
getExtraFilters?(): IUserListFilter[];
|
|
743
|
-
}
|
|
744
723
|
/**
|
|
745
724
|
* Extra filter definition for user list
|
|
746
725
|
*/
|
|
747
726
|
interface IUserListFilter {
|
|
748
|
-
/** Filter field name */
|
|
749
727
|
field: string;
|
|
750
|
-
/** Filter label */
|
|
751
728
|
label: string;
|
|
752
|
-
/** Filter type */
|
|
753
729
|
type: 'text' | 'dropdown' | 'multiselect' | 'date' | 'boolean';
|
|
754
|
-
/** Options for dropdown/multiselect */
|
|
755
730
|
options?: {
|
|
756
731
|
label: string;
|
|
757
732
|
value: string | number | boolean;
|
|
758
733
|
}[];
|
|
759
|
-
/** Placeholder text */
|
|
760
734
|
placeholder?: string;
|
|
761
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
|
+
}
|
|
762
748
|
|
|
763
749
|
declare enum ContactTypeEnum {
|
|
764
750
|
PHONE = 1,
|
|
@@ -780,15 +766,6 @@ declare class CookieService {
|
|
|
780
766
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<CookieService>;
|
|
781
767
|
}
|
|
782
768
|
|
|
783
|
-
/**
|
|
784
|
-
* Request DTO for fetching file URLs
|
|
785
|
-
*/
|
|
786
|
-
interface GetFilesRequestDto {
|
|
787
|
-
id: string;
|
|
788
|
-
}
|
|
789
|
-
/**
|
|
790
|
-
* Response DTO with file information including URL
|
|
791
|
-
*/
|
|
792
769
|
interface FilesResponseDto {
|
|
793
770
|
id: string;
|
|
794
771
|
name: string;
|
|
@@ -797,113 +774,47 @@ interface FilesResponseDto {
|
|
|
797
774
|
}
|
|
798
775
|
/**
|
|
799
776
|
* Service to fetch file URLs from the backend.
|
|
800
|
-
*
|
|
801
|
-
* - Handles presigned URLs for cloud storage (AWS S3, Azure)
|
|
802
|
-
* - Auto-refreshes expired URLs
|
|
803
|
-
* - Validates file access permissions
|
|
804
|
-
* - Works with all storage providers (Local, S3, Azure, SFTP)
|
|
777
|
+
* Handles presigned URLs for cloud storage, auto-refresh, and caching.
|
|
805
778
|
*/
|
|
806
779
|
declare class FileUrlService {
|
|
807
780
|
private readonly http;
|
|
808
781
|
private readonly appConfig;
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
/**
|
|
812
|
-
* Get file URL by ID from cache (reactive signal)
|
|
813
|
-
*/
|
|
782
|
+
private readonly _cache;
|
|
783
|
+
readonly cache: Signal<Map<string, FilesResponseDto>>;
|
|
784
|
+
/** Get file URL by ID from cache (synchronous) */
|
|
814
785
|
getFileUrl(fileId: string | null | undefined): string | null;
|
|
815
|
-
/**
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
fileUrlSignal(fileId: string | null | undefined): _angular_core.Signal<string | null>;
|
|
819
|
-
/**
|
|
820
|
-
* Fetch file URLs from backend and update cache.
|
|
821
|
-
* Skips IDs already in cache to prevent duplicate calls.
|
|
822
|
-
* Returns Observable of fetched files (including cached ones).
|
|
823
|
-
*/
|
|
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 */
|
|
824
789
|
fetchFileUrls(fileIds: string[], forceRefresh?: boolean): Observable<FilesResponseDto[]>;
|
|
825
|
-
/**
|
|
826
|
-
* Fetch a single file URL.
|
|
827
|
-
* Uses cache if available to prevent duplicate calls.
|
|
828
|
-
* Returns Observable of file info or null if not found.
|
|
829
|
-
*/
|
|
790
|
+
/** Fetch single file URL (delegates to fetchFileUrls) */
|
|
830
791
|
fetchSingleFileUrl(fileId: string, forceRefresh?: boolean): Observable<FilesResponseDto | null>;
|
|
831
|
-
/**
|
|
832
|
-
* Clear the URL cache.
|
|
833
|
-
* Useful on logout or when switching contexts.
|
|
834
|
-
*/
|
|
792
|
+
/** Clear entire cache */
|
|
835
793
|
clearCache(): void;
|
|
836
|
-
/**
|
|
837
|
-
* Remove specific file from cache.
|
|
838
|
-
*/
|
|
794
|
+
/** Remove specific file from cache */
|
|
839
795
|
removeFromCache(fileId: string): void;
|
|
796
|
+
private addToCache;
|
|
797
|
+
private getFromCache;
|
|
840
798
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUrlService, never>;
|
|
841
799
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<FileUrlService>;
|
|
842
800
|
}
|
|
843
801
|
|
|
844
802
|
/**
|
|
845
|
-
* Permission
|
|
846
|
-
*
|
|
847
|
-
* Centralized service for permission validation across all packages.
|
|
848
|
-
* Provides signal-based state management and reactive permission checking.
|
|
849
|
-
*
|
|
850
|
-
* Features:
|
|
851
|
-
* - Signal-based permission storage
|
|
852
|
-
* - Individual permission checks
|
|
853
|
-
* - Permission change detection
|
|
854
|
-
* - Reactive permission state updates
|
|
855
|
-
*
|
|
856
|
-
* Usage:
|
|
857
|
-
* ```typescript
|
|
858
|
-
* // In component
|
|
859
|
-
* readonly permissionValidator = inject(PermissionValidatorService);
|
|
860
|
-
*
|
|
861
|
-
* // Set permissions (typically from auth/IAM)
|
|
862
|
-
* this.permissionValidator.setPermissions(['user.view', 'user.create']);
|
|
863
|
-
*
|
|
864
|
-
* // Check individual permission
|
|
865
|
-
* if (this.permissionValidator.hasPermission('user.view')) {
|
|
866
|
-
* // Show UI element
|
|
867
|
-
* }
|
|
868
|
-
*
|
|
869
|
-
* // Access current permissions reactively
|
|
870
|
-
* const permissions = this.permissionValidator.permissions();
|
|
871
|
-
* ```
|
|
872
|
-
*
|
|
873
|
-
* @packageDocumentation
|
|
803
|
+
* Permission state management service.
|
|
804
|
+
* Provides signal-based storage and permission checking with wildcard support.
|
|
874
805
|
*/
|
|
875
806
|
declare class PermissionValidatorService {
|
|
876
|
-
/**
|
|
877
|
-
* Private writable signal for permissions
|
|
878
|
-
*/
|
|
879
807
|
private readonly _permissions;
|
|
880
|
-
/**
|
|
881
|
-
* Readonly permission signal for external consumers
|
|
882
|
-
*/
|
|
883
808
|
readonly permissions: _angular_core.Signal<string[]>;
|
|
884
|
-
/**
|
|
885
|
-
* Private writable signal for loaded state
|
|
886
|
-
*/
|
|
887
809
|
private readonly _isLoaded;
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
* @param permissions - Array of permission codes
|
|
891
|
-
*/
|
|
810
|
+
readonly isLoaded: _angular_core.Signal<boolean>;
|
|
811
|
+
/** Set permissions (replaces existing) */
|
|
892
812
|
setPermissions(permissions: string[]): void;
|
|
893
|
-
/**
|
|
894
|
-
* Clear all permissions
|
|
895
|
-
*/
|
|
813
|
+
/** Clear all permissions */
|
|
896
814
|
clearPermissions(): void;
|
|
897
|
-
/**
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
* @returns True if user has permission
|
|
901
|
-
*/
|
|
902
|
-
hasPermission(permissionCode: string): boolean;
|
|
903
|
-
/**
|
|
904
|
-
* Check if permissions are loaded
|
|
905
|
-
* @returns True if permissions have been loaded
|
|
906
|
-
*/
|
|
815
|
+
/** Check if user has permission (supports wildcards: '*', 'module.*') */
|
|
816
|
+
hasPermission(code: string): boolean;
|
|
817
|
+
/** @deprecated Use `isLoaded()` signal instead */
|
|
907
818
|
isPermissionsLoaded(): boolean;
|
|
908
819
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PermissionValidatorService, never>;
|
|
909
820
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<PermissionValidatorService>;
|
|
@@ -1015,9 +926,9 @@ declare class IsEmptyImageDirective {
|
|
|
1015
926
|
}
|
|
1016
927
|
|
|
1017
928
|
declare class PreventDefaultDirective {
|
|
1018
|
-
eventType: _angular_core.InputSignal<"click" | "keydown" | "keyup">;
|
|
1019
|
-
preventKey: _angular_core.InputSignal<string | undefined>;
|
|
1020
|
-
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>;
|
|
1021
932
|
onClick(event: MouseEvent): void;
|
|
1022
933
|
onKeydown(event: KeyboardEvent): void;
|
|
1023
934
|
onKeyup(event: KeyboardEvent): void;
|
|
@@ -1028,7 +939,7 @@ declare class PreventDefaultDirective {
|
|
|
1028
939
|
|
|
1029
940
|
declare class AngularModule {
|
|
1030
941
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularModule, never>;
|
|
1031
|
-
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]>;
|
|
1032
943
|
static ɵinj: _angular_core.ɵɵInjectorDeclaration<AngularModule>;
|
|
1033
944
|
}
|
|
1034
945
|
|
|
@@ -1038,6 +949,9 @@ declare class PrimeModule {
|
|
|
1038
949
|
static ɵinj: _angular_core.ɵɵInjectorDeclaration<PrimeModule>;
|
|
1039
950
|
}
|
|
1040
951
|
|
|
952
|
+
/** Service names that can be used for feature-specific base URLs */
|
|
953
|
+
type ServiceName = 'auth' | 'administration' | 'iam' | 'storage' | 'formBuilder' | 'email';
|
|
954
|
+
|
|
1041
955
|
/**
|
|
1042
956
|
* Service interface for CRUD operations.
|
|
1043
957
|
* Matches NestJS shared API controller endpoints:
|
|
@@ -1079,11 +993,20 @@ interface IApiService<DtoT, InterfaceT> {
|
|
|
1079
993
|
*
|
|
1080
994
|
* @example
|
|
1081
995
|
* ```typescript
|
|
1082
|
-
* // Define service
|
|
996
|
+
* // Define service with global apiBaseUrl
|
|
1083
997
|
* @Injectable({ providedIn: 'root' })
|
|
1084
998
|
* export class UserService extends ApiResourceService<UserDto, User> {
|
|
1085
|
-
* constructor(
|
|
1086
|
-
* super('users',
|
|
999
|
+
* constructor() {
|
|
1000
|
+
* super('auth/users', inject(HttpClient));
|
|
1001
|
+
* }
|
|
1002
|
+
* }
|
|
1003
|
+
*
|
|
1004
|
+
* // Define service with feature-specific baseUrl
|
|
1005
|
+
* @Injectable({ providedIn: 'root' })
|
|
1006
|
+
* export class FormService extends ApiResourceService<FormDto, Form> {
|
|
1007
|
+
* constructor() {
|
|
1008
|
+
* super('form', inject(HttpClient), 'formBuilder');
|
|
1009
|
+
* // URL: services.formBuilder.baseUrl + '/form'
|
|
1087
1010
|
* }
|
|
1088
1011
|
* }
|
|
1089
1012
|
*
|
|
@@ -1104,7 +1027,6 @@ interface IApiService<DtoT, InterfaceT> {
|
|
|
1104
1027
|
*/
|
|
1105
1028
|
declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiService<DtoT, InterfaceT> {
|
|
1106
1029
|
protected readonly baseUrl: string;
|
|
1107
|
-
protected readonly loaderService: ApiLoaderService;
|
|
1108
1030
|
protected readonly injector: Injector;
|
|
1109
1031
|
protected readonly http: HttpClient;
|
|
1110
1032
|
protected readonly moduleApiName: string;
|
|
@@ -1119,6 +1041,12 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
|
|
|
1119
1041
|
private _listResource;
|
|
1120
1042
|
/** Whether the list resource has been initialized */
|
|
1121
1043
|
private _resourceInitialized;
|
|
1044
|
+
/**
|
|
1045
|
+
* Signal to track resource initialization for computed signals.
|
|
1046
|
+
* This allows computed signals to re-evaluate when the resource is created.
|
|
1047
|
+
* Without this, computed signals would not detect when _listResource changes from null.
|
|
1048
|
+
*/
|
|
1049
|
+
private readonly _resourceInitSignal;
|
|
1122
1050
|
/** Get or create the list resource (lazy initialization) */
|
|
1123
1051
|
get listResource(): ResourceRef<IListResponse<InterfaceT> | undefined>;
|
|
1124
1052
|
/**
|
|
@@ -1127,17 +1055,37 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
|
|
|
1127
1055
|
* Uses runInInjectionContext to support lazy initialization outside constructor.
|
|
1128
1056
|
*/
|
|
1129
1057
|
initListResource(): void;
|
|
1130
|
-
/**
|
|
1058
|
+
/**
|
|
1059
|
+
* Whether data is currently loading.
|
|
1060
|
+
* Tracks _resourceInitSignal to re-evaluate when resource is created.
|
|
1061
|
+
*/
|
|
1131
1062
|
readonly isLoading: _angular_core.Signal<boolean>;
|
|
1132
|
-
/**
|
|
1063
|
+
/**
|
|
1064
|
+
* List data array.
|
|
1065
|
+
* Tracks _resourceInitSignal to re-evaluate when resource is created.
|
|
1066
|
+
*/
|
|
1133
1067
|
readonly data: _angular_core.Signal<InterfaceT[]>;
|
|
1134
|
-
/**
|
|
1068
|
+
/**
|
|
1069
|
+
* Total count of items.
|
|
1070
|
+
* Tracks _resourceInitSignal to re-evaluate when resource is created.
|
|
1071
|
+
*/
|
|
1135
1072
|
readonly total: _angular_core.Signal<number>;
|
|
1136
|
-
/**
|
|
1073
|
+
/**
|
|
1074
|
+
* Pagination metadata.
|
|
1075
|
+
* Tracks _resourceInitSignal to re-evaluate when resource is created.
|
|
1076
|
+
*/
|
|
1137
1077
|
readonly pageInfo: _angular_core.Signal<_flusys_ng_shared.IPaginationMeta | undefined>;
|
|
1138
|
-
/**
|
|
1078
|
+
/**
|
|
1079
|
+
* Whether there are more pages.
|
|
1080
|
+
* Tracks _resourceInitSignal to re-evaluate when resource is created.
|
|
1081
|
+
*/
|
|
1139
1082
|
readonly hasMore: _angular_core.Signal<boolean>;
|
|
1140
|
-
|
|
1083
|
+
/**
|
|
1084
|
+
* @param moduleApiName - The API resource path (e.g., 'form' for /form-builder/form)
|
|
1085
|
+
* @param http - HttpClient instance
|
|
1086
|
+
* @param serviceName - Optional service name for feature-specific base URL (e.g., 'formBuilder')
|
|
1087
|
+
*/
|
|
1088
|
+
constructor(moduleApiName: string, http: HttpClient, serviceName?: ServiceName);
|
|
1141
1089
|
protected getHttpOptions(endpoint: string, params?: HttpParams): {
|
|
1142
1090
|
params?: HttpParams | undefined;
|
|
1143
1091
|
headers: HttpHeaders;
|
|
@@ -1228,14 +1176,6 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
|
|
|
1228
1176
|
deleteAsync(deleteDto: IDeleteData): Promise<IMessageResponse>;
|
|
1229
1177
|
}
|
|
1230
1178
|
|
|
1231
|
-
declare class IconComponent {
|
|
1232
|
-
icon: _angular_core.InputSignal<string>;
|
|
1233
|
-
iconType: _angular_core.InputSignal<IconTypeEnum | undefined>;
|
|
1234
|
-
protected readonly IconTypeEnum: typeof IconTypeEnum;
|
|
1235
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
|
|
1236
|
-
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>;
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
1179
|
/**
|
|
1240
1180
|
* Base class for form controls that support ALL Angular form patterns:
|
|
1241
1181
|
*
|
|
@@ -1308,6 +1248,31 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
|
|
|
1308
1248
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormControl<any>, never>;
|
|
1309
1249
|
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>;
|
|
1310
1250
|
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Factory function to provide NG_VALUE_ACCESSOR for a component.
|
|
1253
|
+
* Use in component providers array.
|
|
1254
|
+
*
|
|
1255
|
+
* @example
|
|
1256
|
+
* ```typescript
|
|
1257
|
+
* @Component({
|
|
1258
|
+
* providers: [provideValueAccessor(LazySelectComponent)]
|
|
1259
|
+
* })
|
|
1260
|
+
* export class LazySelectComponent extends BaseFormControl<string | null> {}
|
|
1261
|
+
* ```
|
|
1262
|
+
*/
|
|
1263
|
+
declare function provideValueAccessor<T extends new (...args: unknown[]) => ControlValueAccessor>(component: T): {
|
|
1264
|
+
provide: _angular_core.InjectionToken<readonly ControlValueAccessor[]>;
|
|
1265
|
+
useExisting: _angular_core.Type<any>;
|
|
1266
|
+
multi: boolean;
|
|
1267
|
+
};
|
|
1268
|
+
|
|
1269
|
+
declare class IconComponent {
|
|
1270
|
+
icon: _angular_core.InputSignal<string>;
|
|
1271
|
+
iconType: _angular_core.InputSignal<IconTypeEnum | undefined>;
|
|
1272
|
+
protected readonly IconTypeEnum: typeof IconTypeEnum;
|
|
1273
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
|
|
1274
|
+
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>;
|
|
1275
|
+
}
|
|
1311
1276
|
|
|
1312
1277
|
/**
|
|
1313
1278
|
* Lazy-loading multi-select component with search, pagination, and select-all.
|
|
@@ -1318,31 +1283,28 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
|
|
|
1318
1283
|
* - Signal forms: `[formField]="formTree.field"`
|
|
1319
1284
|
*/
|
|
1320
1285
|
declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null> {
|
|
1286
|
+
private readonly destroyRef;
|
|
1287
|
+
private readonly onDocumentClickBound;
|
|
1288
|
+
readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
|
|
1321
1289
|
readonly placeHolder: _angular_core.InputSignal<string>;
|
|
1322
1290
|
readonly isEditMode: _angular_core.InputSignal<boolean>;
|
|
1323
1291
|
readonly isLoading: _angular_core.InputSignal<boolean>;
|
|
1324
1292
|
readonly total: _angular_core.InputSignal<number | undefined>;
|
|
1325
1293
|
readonly pagination: _angular_core.InputSignal<IPagination>;
|
|
1326
1294
|
readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
|
|
1327
|
-
/** Two-way bound value using model() for signal forms compatibility */
|
|
1328
1295
|
readonly value: _angular_core.ModelSignal<string[] | null>;
|
|
1329
1296
|
readonly onSearch: _angular_core.OutputEmitterRef<string>;
|
|
1330
1297
|
readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
|
|
1331
1298
|
readonly searchTerm: _angular_core.WritableSignal<string>;
|
|
1332
|
-
|
|
1299
|
+
readonly openOptions: _angular_core.WritableSignal<boolean>;
|
|
1333
1300
|
readonly selectedValueDisplay: _angular_core.Signal<string>;
|
|
1334
|
-
/** Computed: Whether all items are selected (replaces isSelectAll signal) */
|
|
1335
1301
|
readonly isSelectAll: _angular_core.Signal<boolean>;
|
|
1336
1302
|
constructor();
|
|
1337
|
-
private readonly onScrollBound;
|
|
1338
|
-
readonly multiScrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
|
|
1339
1303
|
onScroll(event: Event): void;
|
|
1340
|
-
readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
|
|
1341
|
-
openOptions: _angular_core.WritableSignal<boolean>;
|
|
1342
1304
|
onSelectClick(event: Event): void;
|
|
1343
1305
|
onOverlayClick(event: Event): void;
|
|
1344
|
-
handleDocumentClick
|
|
1345
|
-
isSelected(data: IDropDown): boolean
|
|
1306
|
+
private handleDocumentClick;
|
|
1307
|
+
isSelected(data: IDropDown): boolean;
|
|
1346
1308
|
key(option: IDropDown): string;
|
|
1347
1309
|
selectValue(event: CheckboxChangeEvent, option: IDropDown): void;
|
|
1348
1310
|
changeSelectAll(event: CheckboxChangeEvent): void;
|
|
@@ -1360,6 +1322,10 @@ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null>
|
|
|
1360
1322
|
* - Signal forms: `[formField]="formTree.field"`
|
|
1361
1323
|
*/
|
|
1362
1324
|
declare class LazySelectComponent extends BaseFormControl<string | null> {
|
|
1325
|
+
private readonly destroyRef;
|
|
1326
|
+
private readonly onScrollBound;
|
|
1327
|
+
private scrollTargetEl;
|
|
1328
|
+
readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
|
|
1363
1329
|
readonly placeHolder: _angular_core.InputSignal<string>;
|
|
1364
1330
|
readonly optionLabel: _angular_core.InputSignal<string>;
|
|
1365
1331
|
readonly optionValue: _angular_core.InputSignal<string>;
|
|
@@ -1368,16 +1334,12 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
|
|
|
1368
1334
|
readonly total: _angular_core.InputSignal<number | undefined>;
|
|
1369
1335
|
readonly pagination: _angular_core.InputSignal<IPagination>;
|
|
1370
1336
|
readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
|
|
1371
|
-
/** Two-way bound value using model() for signal forms compatibility */
|
|
1372
1337
|
readonly value: _angular_core.ModelSignal<string | null>;
|
|
1373
1338
|
readonly onSearch: _angular_core.OutputEmitterRef<string>;
|
|
1374
1339
|
readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
|
|
1375
1340
|
readonly searchTerm: _angular_core.WritableSignal<string>;
|
|
1341
|
+
readonly isPanelShow: _angular_core.WritableSignal<boolean>;
|
|
1376
1342
|
constructor();
|
|
1377
|
-
isPanelShow: _angular_core.WritableSignal<boolean>;
|
|
1378
|
-
scrollTargetEl: HTMLElement | null;
|
|
1379
|
-
private readonly onScrollBound;
|
|
1380
|
-
readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
|
|
1381
1343
|
onScroll(event: Event): void;
|
|
1382
1344
|
showPanel(): void;
|
|
1383
1345
|
onBlur(): void;
|
|
@@ -1385,6 +1347,45 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
|
|
|
1385
1347
|
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>;
|
|
1386
1348
|
}
|
|
1387
1349
|
|
|
1350
|
+
/**
|
|
1351
|
+
* Base class for user selection components.
|
|
1352
|
+
* Provides shared user loading, pagination, and search functionality.
|
|
1353
|
+
*
|
|
1354
|
+
* Subclasses must implement:
|
|
1355
|
+
* - `setupValueEffect()` to track value changes and emit selection events
|
|
1356
|
+
*/
|
|
1357
|
+
declare abstract class BaseUserSelectComponent {
|
|
1358
|
+
protected readonly destroyRef: DestroyRef;
|
|
1359
|
+
protected readonly injector: Injector;
|
|
1360
|
+
protected readonly userProvider: IUserProvider;
|
|
1361
|
+
protected abortController: AbortController | null;
|
|
1362
|
+
readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
|
|
1363
|
+
readonly placeHolder: _angular_core.InputSignal<string>;
|
|
1364
|
+
readonly isEditMode: _angular_core.InputSignal<boolean>;
|
|
1365
|
+
readonly filterActive: _angular_core.InputSignal<boolean>;
|
|
1366
|
+
readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
|
|
1367
|
+
readonly pageSize: _angular_core.InputSignal<number>;
|
|
1368
|
+
readonly onError: _angular_core.OutputEmitterRef<Error>;
|
|
1369
|
+
readonly isLoading: _angular_core.WritableSignal<boolean>;
|
|
1370
|
+
readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
|
|
1371
|
+
readonly total: _angular_core.WritableSignal<number | undefined>;
|
|
1372
|
+
readonly pagination: _angular_core.WritableSignal<IPagination>;
|
|
1373
|
+
readonly searchTerm: _angular_core.WritableSignal<string>;
|
|
1374
|
+
readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
|
|
1375
|
+
constructor();
|
|
1376
|
+
/** Setup effect to track value changes and emit selection events */
|
|
1377
|
+
protected abstract setupValueEffect(): void;
|
|
1378
|
+
handleSearch(search: string): void;
|
|
1379
|
+
handlePagination(pagination: IPagination): void;
|
|
1380
|
+
/** Reload users (useful when filters change externally) */
|
|
1381
|
+
reload(): void;
|
|
1382
|
+
protected fetchUsers(append?: boolean): Promise<void>;
|
|
1383
|
+
/** Load users from USER_PROVIDER with active filter */
|
|
1384
|
+
private loadUsersFromProvider;
|
|
1385
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseUserSelectComponent, never>;
|
|
1386
|
+
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>;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1388
1389
|
/**
|
|
1389
1390
|
* User Select Component - Single user selection with lazy loading.
|
|
1390
1391
|
*
|
|
@@ -1412,35 +1413,12 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
|
|
|
1412
1413
|
* />
|
|
1413
1414
|
* ```
|
|
1414
1415
|
*/
|
|
1415
|
-
declare class UserSelectComponent {
|
|
1416
|
-
private readonly destroyRef;
|
|
1417
|
-
private readonly userProvider;
|
|
1418
|
-
private abortController;
|
|
1419
|
-
readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
|
|
1420
|
-
readonly placeHolder: _angular_core.InputSignal<string>;
|
|
1421
|
-
readonly isEditMode: _angular_core.InputSignal<boolean>;
|
|
1422
|
-
readonly filterActive: _angular_core.InputSignal<boolean>;
|
|
1423
|
-
readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
|
|
1424
|
-
readonly pageSize: _angular_core.InputSignal<number>;
|
|
1416
|
+
declare class UserSelectComponent extends BaseUserSelectComponent {
|
|
1425
1417
|
readonly value: _angular_core.ModelSignal<string | null>;
|
|
1426
1418
|
readonly userSelected: _angular_core.OutputEmitterRef<IUserBasicInfo | null>;
|
|
1427
|
-
|
|
1428
|
-
readonly isLoading: _angular_core.WritableSignal<boolean>;
|
|
1429
|
-
readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
|
|
1430
|
-
readonly total: _angular_core.WritableSignal<number | undefined>;
|
|
1431
|
-
readonly pagination: _angular_core.WritableSignal<IPagination>;
|
|
1432
|
-
readonly searchTerm: _angular_core.WritableSignal<string>;
|
|
1433
|
-
readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
|
|
1434
|
-
constructor();
|
|
1435
|
-
handleSearch(search: string): void;
|
|
1436
|
-
handlePagination(pagination: IPagination): void;
|
|
1437
|
-
private fetchUsers;
|
|
1438
|
-
/** Load users from USER_PROVIDER with active filter */
|
|
1439
|
-
private loadUsersFromProvider;
|
|
1440
|
-
/** Reload users (useful when filters change externally) */
|
|
1441
|
-
reload(): void;
|
|
1419
|
+
protected setupValueEffect(): void;
|
|
1442
1420
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserSelectComponent, never>;
|
|
1443
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserSelectComponent, "lib-user-select", never, { "
|
|
1421
|
+
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>;
|
|
1444
1422
|
}
|
|
1445
1423
|
|
|
1446
1424
|
/**
|
|
@@ -1471,76 +1449,18 @@ declare class UserSelectComponent {
|
|
|
1471
1449
|
* />
|
|
1472
1450
|
* ```
|
|
1473
1451
|
*/
|
|
1474
|
-
declare class UserMultiSelectComponent {
|
|
1475
|
-
private readonly destroyRef;
|
|
1476
|
-
private readonly userProvider;
|
|
1477
|
-
private abortController;
|
|
1478
|
-
readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
|
|
1479
|
-
readonly placeHolder: _angular_core.InputSignal<string>;
|
|
1480
|
-
readonly isEditMode: _angular_core.InputSignal<boolean>;
|
|
1481
|
-
readonly filterActive: _angular_core.InputSignal<boolean>;
|
|
1482
|
-
readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
|
|
1483
|
-
readonly pageSize: _angular_core.InputSignal<number>;
|
|
1452
|
+
declare class UserMultiSelectComponent extends BaseUserSelectComponent {
|
|
1484
1453
|
readonly value: _angular_core.ModelSignal<string[] | null>;
|
|
1485
1454
|
readonly usersSelected: _angular_core.OutputEmitterRef<IUserBasicInfo[]>;
|
|
1486
|
-
|
|
1487
|
-
readonly isLoading: _angular_core.WritableSignal<boolean>;
|
|
1488
|
-
readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
|
|
1489
|
-
readonly total: _angular_core.WritableSignal<number | undefined>;
|
|
1490
|
-
readonly pagination: _angular_core.WritableSignal<IPagination>;
|
|
1491
|
-
readonly searchTerm: _angular_core.WritableSignal<string>;
|
|
1492
|
-
readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
|
|
1493
|
-
constructor();
|
|
1494
|
-
handleSearch(search: string): void;
|
|
1495
|
-
handlePagination(pagination: IPagination): void;
|
|
1496
|
-
private fetchUsers;
|
|
1497
|
-
/** Load users from USER_PROVIDER with active filter */
|
|
1498
|
-
private loadUsersFromProvider;
|
|
1499
|
-
/** Reload users (useful when filters change externally) */
|
|
1500
|
-
reload(): void;
|
|
1455
|
+
protected setupValueEffect(): void;
|
|
1501
1456
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserMultiSelectComponent, never>;
|
|
1502
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserMultiSelectComponent, "lib-user-multi-select", never, { "
|
|
1457
|
+
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>;
|
|
1503
1458
|
}
|
|
1504
1459
|
|
|
1505
1460
|
/**
|
|
1506
1461
|
* File Uploader Component - Drag & drop file upload with type filtering.
|
|
1507
1462
|
*
|
|
1508
1463
|
* Pass your own `uploadFile` function - works with any storage API.
|
|
1509
|
-
*
|
|
1510
|
-
* Features:
|
|
1511
|
-
* - Drag & drop support
|
|
1512
|
-
* - File type filtering (images, documents, etc.)
|
|
1513
|
-
* - Upload progress indication
|
|
1514
|
-
* - Multiple file support (optional)
|
|
1515
|
-
* - Image compression options
|
|
1516
|
-
*
|
|
1517
|
-
* @example
|
|
1518
|
-
* ```typescript
|
|
1519
|
-
* // In component
|
|
1520
|
-
* readonly uploadService = inject(UploadService);
|
|
1521
|
-
*
|
|
1522
|
-
* readonly uploadFile: UploadFileFn = (file, options) =>
|
|
1523
|
-
* this.uploadService.uploadSingleFile(file, options);
|
|
1524
|
-
* ```
|
|
1525
|
-
*
|
|
1526
|
-
* ```html
|
|
1527
|
-
* <!-- Single image upload -->
|
|
1528
|
-
* <lib-file-uploader
|
|
1529
|
-
* [uploadFile]="uploadFile"
|
|
1530
|
-
* [acceptTypes]="['image/*']"
|
|
1531
|
-
* [multiple]="false"
|
|
1532
|
-
* (fileUploaded)="onFileUploaded($event)"
|
|
1533
|
-
* />
|
|
1534
|
-
*
|
|
1535
|
-
* <!-- Multiple document upload -->
|
|
1536
|
-
* <lib-file-uploader
|
|
1537
|
-
* [uploadFile]="uploadFile"
|
|
1538
|
-
* [acceptTypes]="FILE_TYPE_FILTERS.DOCUMENTS"
|
|
1539
|
-
* [multiple]="true"
|
|
1540
|
-
* [maxFiles]="5"
|
|
1541
|
-
* (filesUploaded)="onFilesUploaded($event)"
|
|
1542
|
-
* />
|
|
1543
|
-
* ```
|
|
1544
1464
|
*/
|
|
1545
1465
|
declare class FileUploaderComponent {
|
|
1546
1466
|
private readonly messageService;
|
|
@@ -1739,63 +1659,340 @@ declare const PROFILE_UPLOAD_PROVIDER: InjectionToken<IProfileUploadProvider>;
|
|
|
1739
1659
|
declare const USER_LIST_PROVIDER: InjectionToken<IUserListProvider<IUserListItem>>;
|
|
1740
1660
|
|
|
1741
1661
|
/**
|
|
1742
|
-
* Permission Guard
|
|
1743
|
-
*
|
|
1744
|
-
* Route-level guard for permission-based access control.
|
|
1745
|
-
* Validates permissions before allowing navigation.
|
|
1746
|
-
*
|
|
1747
|
-
* Features:
|
|
1748
|
-
* - Single permission check
|
|
1749
|
-
* - Complex ILogicNode logic trees
|
|
1750
|
-
* - Configurable redirect URL
|
|
1751
|
-
* - Debug logging for denied access
|
|
1662
|
+
* Permission Guard - Single permission or ILogicNode check.
|
|
1752
1663
|
*
|
|
1753
1664
|
* @example
|
|
1754
1665
|
* ```typescript
|
|
1755
|
-
* // Simple permission check
|
|
1756
1666
|
* { path: 'users', canActivate: [permissionGuard('user.view')] }
|
|
1757
|
-
*
|
|
1758
|
-
* // Complex logic
|
|
1759
|
-
* { path: 'admin', canActivate: [permissionGuard({
|
|
1760
|
-
* id: 'root',
|
|
1761
|
-
* type: 'group',
|
|
1762
|
-
* operator: 'AND',
|
|
1763
|
-
* children: [
|
|
1764
|
-
* { id: '1', type: 'action', actionId: 'admin.view' },
|
|
1765
|
-
* { id: '2', type: 'action', actionId: 'admin.manage' }
|
|
1766
|
-
* ]
|
|
1767
|
-
* })] }
|
|
1768
|
-
*
|
|
1769
|
-
* // With custom redirect
|
|
1770
|
-
* { path: 'users', canActivate: [permissionGuard('user.view', '/access-denied')] }
|
|
1667
|
+
* { path: 'admin', canActivate: [permissionGuard(logicNode, '/access-denied')] }
|
|
1771
1668
|
* ```
|
|
1772
1669
|
*/
|
|
1773
1670
|
declare function permissionGuard(permission: string | ILogicNode, redirectTo?: string): CanActivateFn;
|
|
1774
1671
|
/**
|
|
1775
|
-
* Any Permission Guard (OR logic)
|
|
1776
|
-
*
|
|
1777
|
-
* Allows access if user has ANY of the specified permissions.
|
|
1672
|
+
* Any Permission Guard (OR logic) - Access if user has ANY permission.
|
|
1778
1673
|
*
|
|
1779
1674
|
* @example
|
|
1780
1675
|
* ```typescript
|
|
1781
|
-
* // Allow if user has view OR create permission
|
|
1782
1676
|
* { path: 'users', canActivate: [anyPermissionGuard(['user.view', 'user.create'])] }
|
|
1783
1677
|
* ```
|
|
1784
1678
|
*/
|
|
1785
1679
|
declare function anyPermissionGuard(permissions: string[], redirectTo?: string): CanActivateFn;
|
|
1786
1680
|
/**
|
|
1787
|
-
* All Permissions Guard (AND logic)
|
|
1788
|
-
*
|
|
1789
|
-
* Allows access only if user has ALL of the specified permissions.
|
|
1681
|
+
* All Permissions Guard (AND logic) - Access only if user has ALL permissions.
|
|
1790
1682
|
*
|
|
1791
1683
|
* @example
|
|
1792
1684
|
* ```typescript
|
|
1793
|
-
* // Allow only if user has BOTH view AND create permissions
|
|
1794
1685
|
* { path: 'admin', canActivate: [allPermissionsGuard(['admin.view', 'admin.manage'])] }
|
|
1795
1686
|
* ```
|
|
1796
1687
|
*/
|
|
1797
1688
|
declare function allPermissionsGuard(permissions: string[], redirectTo?: string): CanActivateFn;
|
|
1798
1689
|
|
|
1690
|
+
/**
|
|
1691
|
+
* Base class for form page components that handle create/edit operations.
|
|
1692
|
+
* Provides common functionality for loading existing items, form submission,
|
|
1693
|
+
* navigation, and toast notifications.
|
|
1694
|
+
*
|
|
1695
|
+
* ## Features
|
|
1696
|
+
* - Automatic route parameter handling (loads item when ID is present)
|
|
1697
|
+
* - Edit mode detection based on existing item
|
|
1698
|
+
* - Unified submit handler for create/update operations
|
|
1699
|
+
* - Cancel navigation
|
|
1700
|
+
* - Toast messages for success/validation errors
|
|
1701
|
+
*
|
|
1702
|
+
* ## Usage
|
|
1703
|
+
*
|
|
1704
|
+
* ```typescript
|
|
1705
|
+
* interface IProductFormModel {
|
|
1706
|
+
* name: string;
|
|
1707
|
+
* price: number;
|
|
1708
|
+
* }
|
|
1709
|
+
*
|
|
1710
|
+
* @Component({
|
|
1711
|
+
* selector: 'app-product-form',
|
|
1712
|
+
* standalone: true,
|
|
1713
|
+
* changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1714
|
+
* template: `...`
|
|
1715
|
+
* })
|
|
1716
|
+
* export class ProductFormComponent extends BaseFormPage<IProduct, IProductFormModel> {
|
|
1717
|
+
* private readonly productService = inject(ProductApiService);
|
|
1718
|
+
*
|
|
1719
|
+
* // Form model signal (private writable, public readonly)
|
|
1720
|
+
* private readonly _formModel = signal<IProductFormModel>({ name: '', price: 0 });
|
|
1721
|
+
* readonly formModel = this._formModel.asReadonly();
|
|
1722
|
+
*
|
|
1723
|
+
* // Required abstract implementations
|
|
1724
|
+
* getFormModel(): Signal<IProductFormModel> {
|
|
1725
|
+
* return this.formModel;
|
|
1726
|
+
* }
|
|
1727
|
+
*
|
|
1728
|
+
* getResourceRoute(): string {
|
|
1729
|
+
* return '/products';
|
|
1730
|
+
* }
|
|
1731
|
+
*
|
|
1732
|
+
* getResourceName(): string {
|
|
1733
|
+
* return 'Product';
|
|
1734
|
+
* }
|
|
1735
|
+
*
|
|
1736
|
+
* isFormValid(): boolean {
|
|
1737
|
+
* const model = this.formModel();
|
|
1738
|
+
* return model.name.trim().length > 0 && model.price > 0;
|
|
1739
|
+
* }
|
|
1740
|
+
*
|
|
1741
|
+
* loadItem(id: string): void {
|
|
1742
|
+
* this.isLoading.set(true);
|
|
1743
|
+
* this.productService.findById(id)
|
|
1744
|
+
* .pipe(takeUntilDestroyed(this.destroyRef))
|
|
1745
|
+
* .subscribe({
|
|
1746
|
+
* next: (response) => {
|
|
1747
|
+
* if (response.success && response.data) {
|
|
1748
|
+
* this.existingItem.set(response.data);
|
|
1749
|
+
* this._formModel.set({
|
|
1750
|
+
* name: response.data.name,
|
|
1751
|
+
* price: response.data.price,
|
|
1752
|
+
* });
|
|
1753
|
+
* }
|
|
1754
|
+
* this.isLoading.set(false);
|
|
1755
|
+
* },
|
|
1756
|
+
* error: () => {
|
|
1757
|
+
* this.router.navigate([this.getResourceRoute()]);
|
|
1758
|
+
* this.isLoading.set(false);
|
|
1759
|
+
* },
|
|
1760
|
+
* });
|
|
1761
|
+
* }
|
|
1762
|
+
*
|
|
1763
|
+
* createItem(model: IProductFormModel): Observable<ISingleResponse<IProduct>> {
|
|
1764
|
+
* return this.productService.insert(model);
|
|
1765
|
+
* }
|
|
1766
|
+
*
|
|
1767
|
+
* updateItem(model: IProductFormModel): Observable<ISingleResponse<IProduct>> {
|
|
1768
|
+
* return this.productService.update({ id: this.existingItem()!.id, ...model });
|
|
1769
|
+
* }
|
|
1770
|
+
* }
|
|
1771
|
+
* ```
|
|
1772
|
+
*
|
|
1773
|
+
* @template T The entity/interface type being edited
|
|
1774
|
+
* @template TFormModel The form model interface
|
|
1775
|
+
*/
|
|
1776
|
+
declare abstract class BaseFormPage<T, TFormModel> {
|
|
1777
|
+
protected readonly router: Router;
|
|
1778
|
+
protected readonly route: ActivatedRoute;
|
|
1779
|
+
protected readonly messageService: MessageService;
|
|
1780
|
+
protected readonly destroyRef: DestroyRef;
|
|
1781
|
+
protected readonly routeParams: Signal<i3.ParamMap | undefined>;
|
|
1782
|
+
protected initialized: boolean;
|
|
1783
|
+
/** Loading state for async operations */
|
|
1784
|
+
readonly isLoading: _angular_core.WritableSignal<boolean>;
|
|
1785
|
+
/** The existing item when in edit mode, null when creating */
|
|
1786
|
+
readonly existingItem: _angular_core.WritableSignal<T | null>;
|
|
1787
|
+
/** Whether the form is in edit mode (has existing item) */
|
|
1788
|
+
readonly isEditMode: Signal<boolean>;
|
|
1789
|
+
/**
|
|
1790
|
+
* Get the form model signal.
|
|
1791
|
+
* Returns a readonly Signal - implementations should expose their
|
|
1792
|
+
* WritableSignal as readonly through this method.
|
|
1793
|
+
*/
|
|
1794
|
+
abstract getFormModel(): Signal<TFormModel>;
|
|
1795
|
+
/**
|
|
1796
|
+
* Get the base route for the resource (used for navigation after save/cancel).
|
|
1797
|
+
* @example '/products' or '/administration/users'
|
|
1798
|
+
*/
|
|
1799
|
+
abstract getResourceRoute(): string;
|
|
1800
|
+
/**
|
|
1801
|
+
* Get the display name of the resource for toast messages.
|
|
1802
|
+
* @example 'Product' or 'User'
|
|
1803
|
+
*/
|
|
1804
|
+
abstract getResourceName(): string;
|
|
1805
|
+
/**
|
|
1806
|
+
* Validate the current form model.
|
|
1807
|
+
* Return true if the form is valid and can be submitted.
|
|
1808
|
+
*/
|
|
1809
|
+
abstract isFormValid(): boolean;
|
|
1810
|
+
/**
|
|
1811
|
+
* Load an existing item by ID.
|
|
1812
|
+
* Should set existingItem and populate formModel on success.
|
|
1813
|
+
* Should handle loading state and navigation on error.
|
|
1814
|
+
*/
|
|
1815
|
+
abstract loadItem(id: string): void;
|
|
1816
|
+
/**
|
|
1817
|
+
* Create a new item with the given form model.
|
|
1818
|
+
* Return an Observable that emits the API response.
|
|
1819
|
+
*/
|
|
1820
|
+
abstract createItem(model: TFormModel): Observable<unknown>;
|
|
1821
|
+
/**
|
|
1822
|
+
* Update an existing item with the given form model.
|
|
1823
|
+
* Return an Observable that emits the API response.
|
|
1824
|
+
*/
|
|
1825
|
+
abstract updateItem(model: TFormModel): Observable<unknown>;
|
|
1826
|
+
constructor();
|
|
1827
|
+
/**
|
|
1828
|
+
* Handle form submission.
|
|
1829
|
+
* Validates the form, then calls createItem or updateItem based on mode.
|
|
1830
|
+
* Shows appropriate toast messages and navigates back on success.
|
|
1831
|
+
*/
|
|
1832
|
+
onSubmit(): void;
|
|
1833
|
+
/**
|
|
1834
|
+
* Handle cancel action.
|
|
1835
|
+
* Navigates back to the resource list.
|
|
1836
|
+
*/
|
|
1837
|
+
onCancel(): void;
|
|
1838
|
+
/**
|
|
1839
|
+
* Show validation error toast.
|
|
1840
|
+
* Override to customize the validation error message.
|
|
1841
|
+
*/
|
|
1842
|
+
protected showValidationError(): void;
|
|
1843
|
+
/**
|
|
1844
|
+
* Show success toast.
|
|
1845
|
+
* @param detail The success message to display
|
|
1846
|
+
*/
|
|
1847
|
+
protected showSuccess(detail: string): void;
|
|
1848
|
+
/**
|
|
1849
|
+
* Show error toast.
|
|
1850
|
+
* @param detail The error message to display
|
|
1851
|
+
*/
|
|
1852
|
+
protected showError(detail: string): void;
|
|
1853
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormPage<any, any>, never>;
|
|
1854
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormPage<any, any>, never, never, {}, {}, never, never, true, never>;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
/**
|
|
1858
|
+
* Base List Page
|
|
1859
|
+
* Abstract directive providing common signals, computed values, and utilities
|
|
1860
|
+
* for list page components across all feature packages.
|
|
1861
|
+
*
|
|
1862
|
+
* Features:
|
|
1863
|
+
* - Pagination state management (pageSize, currentPage, total)
|
|
1864
|
+
* - Loading state
|
|
1865
|
+
* - CRUD navigation helpers
|
|
1866
|
+
* - Message display utilities
|
|
1867
|
+
* - Delete confirmation with API integration
|
|
1868
|
+
* - Company feature flag support
|
|
1869
|
+
*
|
|
1870
|
+
* Usage:
|
|
1871
|
+
* ```typescript
|
|
1872
|
+
* @Component({ ... })
|
|
1873
|
+
* export class UserListComponent extends BaseListPage<IUser> {
|
|
1874
|
+
* getResourceRoute(): string { return '/users'; }
|
|
1875
|
+
* getDeleteConfirmMessage(user: IUser): string { return `Delete "${user.name}"?`; }
|
|
1876
|
+
* async loadData(): Promise<void> { ... }
|
|
1877
|
+
* }
|
|
1878
|
+
* ```
|
|
1879
|
+
*/
|
|
1880
|
+
declare abstract class BaseListPage<T> {
|
|
1881
|
+
protected readonly router: Router;
|
|
1882
|
+
protected readonly messageService: MessageService;
|
|
1883
|
+
protected readonly appConfig: _flusys_ng_core.IAppConfig;
|
|
1884
|
+
protected readonly confirmationService: ConfirmationService;
|
|
1885
|
+
protected readonly destroyRef: DestroyRef;
|
|
1886
|
+
/** Items list */
|
|
1887
|
+
readonly items: _angular_core.WritableSignal<T[]>;
|
|
1888
|
+
/** Loading state */
|
|
1889
|
+
readonly isLoading: _angular_core.WritableSignal<boolean>;
|
|
1890
|
+
/** Total records for pagination */
|
|
1891
|
+
readonly total: _angular_core.WritableSignal<number>;
|
|
1892
|
+
/** Page size */
|
|
1893
|
+
readonly pageSize: _angular_core.WritableSignal<number>;
|
|
1894
|
+
/** First record index (for p-table lazy load) */
|
|
1895
|
+
readonly first: _angular_core.WritableSignal<number>;
|
|
1896
|
+
/** Current page (0-based for API, derived from first/pageSize) */
|
|
1897
|
+
readonly currentPage: _angular_core.Signal<number>;
|
|
1898
|
+
/** Show company info if company feature enabled */
|
|
1899
|
+
readonly showCompanyInfo: _angular_core.Signal<boolean>;
|
|
1900
|
+
/**
|
|
1901
|
+
* Abstract method to load data - must be implemented by subclass
|
|
1902
|
+
*/
|
|
1903
|
+
abstract loadData(): Promise<void>;
|
|
1904
|
+
/**
|
|
1905
|
+
* Get the base route for this resource
|
|
1906
|
+
* Used for navigation to create/edit pages
|
|
1907
|
+
* @example '/administration/users' or '/storage/folders'
|
|
1908
|
+
*/
|
|
1909
|
+
abstract getResourceRoute(): string;
|
|
1910
|
+
/**
|
|
1911
|
+
* Get the confirmation message for deleting an item
|
|
1912
|
+
* @param item The item to delete
|
|
1913
|
+
* @returns Confirmation message string
|
|
1914
|
+
*/
|
|
1915
|
+
abstract getDeleteConfirmMessage(item: T): string;
|
|
1916
|
+
/**
|
|
1917
|
+
* Navigate to create page
|
|
1918
|
+
*/
|
|
1919
|
+
onCreate(): void;
|
|
1920
|
+
/**
|
|
1921
|
+
* Navigate to edit page
|
|
1922
|
+
* @param id The ID of the item to edit
|
|
1923
|
+
*/
|
|
1924
|
+
onEdit(id: string): void;
|
|
1925
|
+
/**
|
|
1926
|
+
* Handle page change from p-table lazy load
|
|
1927
|
+
*/
|
|
1928
|
+
onPageChange(event: {
|
|
1929
|
+
first?: number | null;
|
|
1930
|
+
rows?: number | null;
|
|
1931
|
+
}): void;
|
|
1932
|
+
/**
|
|
1933
|
+
* Get pagination params for API call
|
|
1934
|
+
* Returns 0-based page for backend API
|
|
1935
|
+
*/
|
|
1936
|
+
protected getPaginationParams(): {
|
|
1937
|
+
currentPage: number;
|
|
1938
|
+
pageSize: number;
|
|
1939
|
+
};
|
|
1940
|
+
/**
|
|
1941
|
+
* Show success toast message
|
|
1942
|
+
*/
|
|
1943
|
+
protected showSuccess(detail: string, summary?: string): void;
|
|
1944
|
+
/**
|
|
1945
|
+
* Show error toast message
|
|
1946
|
+
*/
|
|
1947
|
+
protected showError(detail: string, summary?: string): void;
|
|
1948
|
+
/**
|
|
1949
|
+
* Show info toast message
|
|
1950
|
+
*/
|
|
1951
|
+
protected showInfo(detail: string, summary?: string): void;
|
|
1952
|
+
/**
|
|
1953
|
+
* Show warning toast message
|
|
1954
|
+
*/
|
|
1955
|
+
protected showWarn(detail: string, summary?: string): void;
|
|
1956
|
+
/**
|
|
1957
|
+
* Delete an item with confirmation dialog
|
|
1958
|
+
* @param item The item to delete
|
|
1959
|
+
* @param idGetter Function to extract ID from item
|
|
1960
|
+
* @param deleteApiCall Function that returns Observable for delete API call
|
|
1961
|
+
* @param options Optional configuration
|
|
1962
|
+
*/
|
|
1963
|
+
onDelete(item: T, idGetter: (item: T) => string, deleteApiCall: (id: string) => Observable<unknown>, options?: {
|
|
1964
|
+
header?: string;
|
|
1965
|
+
successMessage?: string;
|
|
1966
|
+
errorMessage?: string;
|
|
1967
|
+
}): void;
|
|
1968
|
+
/**
|
|
1969
|
+
* Delete an item with confirmation dialog using async/await
|
|
1970
|
+
* @param item The item to delete
|
|
1971
|
+
* @param idGetter Function to extract ID from item
|
|
1972
|
+
* @param deleteApiCall Async function for delete API call
|
|
1973
|
+
* @param options Optional configuration
|
|
1974
|
+
*/
|
|
1975
|
+
onDeleteAsync(item: T, idGetter: (item: T) => string, deleteApiCall: (id: string) => Promise<unknown>, options?: {
|
|
1976
|
+
header?: string;
|
|
1977
|
+
successMessage?: string;
|
|
1978
|
+
errorMessage?: string;
|
|
1979
|
+
}): Promise<void>;
|
|
1980
|
+
/**
|
|
1981
|
+
* Navigate to a route
|
|
1982
|
+
*/
|
|
1983
|
+
protected navigateTo(path: string[]): void;
|
|
1984
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseListPage<any>, never>;
|
|
1985
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseListPage<any>, never, never, {}, {}, never, never, true, never>;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
/**
|
|
1989
|
+
* Check if user has a specific permission using wildcard matching.
|
|
1990
|
+
* Supports:
|
|
1991
|
+
* - Exact match: 'user.create' matches 'user.create'
|
|
1992
|
+
* - Full wildcard: '*' matches everything
|
|
1993
|
+
* - Module wildcard: 'user.*' matches 'user.create', 'user.read', etc.
|
|
1994
|
+
*/
|
|
1995
|
+
declare function hasPermission(requiredPermission: string, userPermissions: string[]): boolean;
|
|
1799
1996
|
/** Evaluate permission logic (string or ILogicNode) against user permissions */
|
|
1800
1997
|
declare function evaluatePermission(logic: string | ILogicNode | null | undefined, permissions: string[]): boolean;
|
|
1801
1998
|
/** Recursively evaluate an ILogicNode tree */
|
|
@@ -1805,5 +2002,38 @@ declare function hasAnyPermission(permissionCodes: string[], permissions: string
|
|
|
1805
2002
|
/** Check if user has ALL of the specified permissions (AND logic) */
|
|
1806
2003
|
declare function hasAllPermissions(permissionCodes: string[], permissions: string[]): boolean;
|
|
1807
2004
|
|
|
1808
|
-
|
|
1809
|
-
|
|
2005
|
+
/**
|
|
2006
|
+
* Configuration for scroll pagination behavior
|
|
2007
|
+
*/
|
|
2008
|
+
interface ScrollPaginationConfig {
|
|
2009
|
+
/** Distance from bottom to trigger pagination (default: 50px) */
|
|
2010
|
+
threshold?: number;
|
|
2011
|
+
/** Current pagination state */
|
|
2012
|
+
pagination: IPagination;
|
|
2013
|
+
/** Total items available */
|
|
2014
|
+
total: number | undefined;
|
|
2015
|
+
/** Whether currently loading */
|
|
2016
|
+
isLoading: boolean;
|
|
2017
|
+
}
|
|
2018
|
+
/**
|
|
2019
|
+
* Check if scroll has reached near bottom and calculate next page if available.
|
|
2020
|
+
* Returns next pagination if should load more, null otherwise.
|
|
2021
|
+
*
|
|
2022
|
+
* @example
|
|
2023
|
+
* ```typescript
|
|
2024
|
+
* onScroll(event: Event): void {
|
|
2025
|
+
* const nextPagination = checkScrollPagination(event, {
|
|
2026
|
+
* pagination: this.pagination(),
|
|
2027
|
+
* total: this.total(),
|
|
2028
|
+
* isLoading: this.isLoading(),
|
|
2029
|
+
* });
|
|
2030
|
+
* if (nextPagination) {
|
|
2031
|
+
* this.onPagination.emit(nextPagination);
|
|
2032
|
+
* }
|
|
2033
|
+
* }
|
|
2034
|
+
* ```
|
|
2035
|
+
*/
|
|
2036
|
+
declare function checkScrollPagination(event: Event, config: ScrollPaginationConfig): IPagination | null;
|
|
2037
|
+
|
|
2038
|
+
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 };
|
|
2039
|
+
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, ServiceName, UploadFileFn };
|