@flusys/ng-shared 1.0.0-rc → 1.0.1
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 +28 -3
- package/fesm2022/flusys-ng-shared.mjs +377 -572
- package/fesm2022/flusys-ng-shared.mjs.map +1 -1
- package/package.json +9 -9
- package/types/flusys-ng-shared.d.ts +270 -528
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, PLATFORM_ID, Injectable, DOCUMENT, REQUEST, signal, computed, ElementRef, input, effect, Directive, TemplateRef, ViewContainerRef, output, NgModule, Injector, runInInjectionContext, resource, model, untracked, forwardRef, ChangeDetectionStrategy, Component, DestroyRef, viewChild, afterNextRender, InjectionToken, isDevMode } from '@angular/core';
|
|
3
|
-
import * as
|
|
3
|
+
import * as i3 from '@angular/common';
|
|
4
4
|
import { isPlatformServer, CommonModule, NgOptimizedImage, NgComponentOutlet, DatePipe } from '@angular/common';
|
|
5
5
|
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
|
6
|
-
import { APP_CONFIG, getServiceUrl
|
|
6
|
+
import { APP_CONFIG, getServiceUrl } from '@flusys/ng-core';
|
|
7
7
|
import { of, firstValueFrom, map as map$1 } from 'rxjs';
|
|
8
8
|
import { map, tap, catchError } from 'rxjs/operators';
|
|
9
|
-
import * as i1$
|
|
9
|
+
import * as i1$1 from '@angular/forms';
|
|
10
10
|
import { NgControl, FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
11
11
|
import { RouterOutlet, RouterLink, RouterLinkActive, Router, ActivatedRoute } from '@angular/router';
|
|
12
12
|
import { AutoCompleteModule } from 'primeng/autocomplete';
|
|
13
13
|
import { AvatarModule } from 'primeng/avatar';
|
|
14
|
-
import * as i1$
|
|
14
|
+
import * as i1$2 from 'primeng/button';
|
|
15
15
|
import { ButtonModule } from 'primeng/button';
|
|
16
16
|
import { CardModule } from 'primeng/card';
|
|
17
|
-
import * as i1
|
|
17
|
+
import * as i1 from 'primeng/checkbox';
|
|
18
18
|
import { CheckboxModule } from 'primeng/checkbox';
|
|
19
19
|
import { ConfirmDialogModule } from 'primeng/confirmdialog';
|
|
20
20
|
import { DatePickerModule } from 'primeng/datepicker';
|
|
@@ -38,7 +38,7 @@ import * as i2$1 from 'primeng/progressbar';
|
|
|
38
38
|
import { ProgressBarModule } from 'primeng/progressbar';
|
|
39
39
|
import { RadioButtonModule } from 'primeng/radiobutton';
|
|
40
40
|
import { RippleModule } from 'primeng/ripple';
|
|
41
|
-
import * as i3 from 'primeng/select';
|
|
41
|
+
import * as i3$1 from 'primeng/select';
|
|
42
42
|
import { SelectModule } from 'primeng/select';
|
|
43
43
|
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
44
44
|
import { SkeletonModule } from 'primeng/skeleton';
|
|
@@ -266,10 +266,10 @@ class PlatformService {
|
|
|
266
266
|
get isServer() {
|
|
267
267
|
return isPlatformServer(this.platformId);
|
|
268
268
|
}
|
|
269
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
270
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.
|
|
269
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PlatformService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
270
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PlatformService, providedIn: 'root' });
|
|
271
271
|
}
|
|
272
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
272
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PlatformService, decorators: [{
|
|
273
273
|
type: Injectable,
|
|
274
274
|
args: [{ providedIn: 'root' }]
|
|
275
275
|
}] });
|
|
@@ -281,10 +281,10 @@ class CookieService {
|
|
|
281
281
|
get() {
|
|
282
282
|
return !this.platformService.isServer ? this.doc.cookie : this.request?.headers.get('cookie') ?? "";
|
|
283
283
|
}
|
|
284
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
285
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.
|
|
284
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CookieService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
285
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CookieService, providedIn: 'root' });
|
|
286
286
|
}
|
|
287
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
287
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CookieService, decorators: [{
|
|
288
288
|
type: Injectable,
|
|
289
289
|
args: [{
|
|
290
290
|
providedIn: 'root',
|
|
@@ -293,193 +293,171 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
293
293
|
|
|
294
294
|
/**
|
|
295
295
|
* Service to fetch file URLs from the backend.
|
|
296
|
-
*
|
|
297
|
-
* - Handles presigned URLs for cloud storage (AWS S3, Azure)
|
|
298
|
-
* - Auto-refreshes expired URLs
|
|
299
|
-
* - Validates file access permissions
|
|
300
|
-
* - Works with all storage providers (Local, S3, Azure, SFTP)
|
|
296
|
+
* Handles presigned URLs for cloud storage, auto-refresh, and caching.
|
|
301
297
|
*/
|
|
302
298
|
class FileUrlService {
|
|
303
299
|
http = inject(HttpClient);
|
|
304
300
|
appConfig = inject(APP_CONFIG);
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Get file URL by ID from cache (reactive signal)
|
|
309
|
-
*/
|
|
301
|
+
_cache = signal(new Map(), ...(ngDevMode ? [{ debugName: "_cache" }] : []));
|
|
302
|
+
cache = this._cache.asReadonly();
|
|
303
|
+
/** Get file URL by ID from cache (synchronous) */
|
|
310
304
|
getFileUrl(fileId) {
|
|
311
305
|
if (!fileId)
|
|
312
306
|
return null;
|
|
313
|
-
return this.
|
|
307
|
+
return this._cache().get(fileId)?.url ?? null;
|
|
314
308
|
}
|
|
315
|
-
/**
|
|
316
|
-
* Get file URL signal (computed from cache)
|
|
317
|
-
*/
|
|
309
|
+
/** Get file URL as computed signal */
|
|
318
310
|
fileUrlSignal(fileId) {
|
|
319
311
|
return computed(() => this.getFileUrl(fileId));
|
|
320
312
|
}
|
|
321
|
-
/**
|
|
322
|
-
* Fetch file URLs from backend and update cache.
|
|
323
|
-
* Skips IDs already in cache to prevent duplicate calls.
|
|
324
|
-
* Returns Observable of fetched files (including cached ones).
|
|
325
|
-
*/
|
|
313
|
+
/** Fetch file URLs from backend and update cache */
|
|
326
314
|
fetchFileUrls(fileIds, forceRefresh = false) {
|
|
327
315
|
if (!fileIds.length)
|
|
328
316
|
return of([]);
|
|
329
|
-
const cache = this.
|
|
330
|
-
// Filter out IDs already in cache (unless force refresh)
|
|
317
|
+
const cache = this._cache();
|
|
331
318
|
const missingIds = forceRefresh
|
|
332
319
|
? fileIds
|
|
333
320
|
: fileIds.filter((id) => !cache.has(id));
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const cachedFiles = fileIds
|
|
337
|
-
.map((id) => cache.get(id))
|
|
338
|
-
.filter((f) => !!f);
|
|
339
|
-
return of(cachedFiles);
|
|
321
|
+
if (!missingIds.length) {
|
|
322
|
+
return of(this.getFromCache(fileIds));
|
|
340
323
|
}
|
|
341
324
|
const requestDto = missingIds.map((id) => ({ id }));
|
|
342
325
|
return this.http
|
|
343
326
|
.post(`${getServiceUrl(this.appConfig, 'storage')}/file-manager/get-files`, requestDto)
|
|
344
|
-
.pipe(map((response) => response.data ?? []), tap((files) =>
|
|
345
|
-
// Update cache with new files
|
|
346
|
-
const newCache = new Map(this.urlCache());
|
|
347
|
-
files.forEach((file) => newCache.set(file.id, file));
|
|
348
|
-
this.urlCache.set(newCache);
|
|
349
|
-
}), map(() => {
|
|
350
|
-
// Return all requested files (cached + newly fetched)
|
|
351
|
-
const allCache = this.urlCache();
|
|
352
|
-
return fileIds
|
|
353
|
-
.map((id) => allCache.get(id))
|
|
354
|
-
.filter((f) => !!f);
|
|
355
|
-
}), catchError(() => of([])));
|
|
327
|
+
.pipe(map((response) => response.data ?? []), tap((files) => this.addToCache(files)), map(() => this.getFromCache(fileIds)), catchError(() => of([])));
|
|
356
328
|
}
|
|
357
|
-
/**
|
|
358
|
-
* Fetch a single file URL.
|
|
359
|
-
* Uses cache if available to prevent duplicate calls.
|
|
360
|
-
* Returns Observable of file info or null if not found.
|
|
361
|
-
*/
|
|
329
|
+
/** Fetch single file URL (delegates to fetchFileUrls) */
|
|
362
330
|
fetchSingleFileUrl(fileId, forceRefresh = false) {
|
|
363
|
-
// Return from cache immediately if available
|
|
364
|
-
if (!forceRefresh) {
|
|
365
|
-
const cached = this.urlCache().get(fileId);
|
|
366
|
-
if (cached) {
|
|
367
|
-
return of(cached);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
331
|
return this.fetchFileUrls([fileId], forceRefresh).pipe(map((files) => files[0] ?? null));
|
|
371
332
|
}
|
|
372
|
-
/**
|
|
373
|
-
* Clear the URL cache.
|
|
374
|
-
* Useful on logout or when switching contexts.
|
|
375
|
-
*/
|
|
333
|
+
/** Clear entire cache */
|
|
376
334
|
clearCache() {
|
|
377
|
-
this.
|
|
335
|
+
this._cache.set(new Map());
|
|
378
336
|
}
|
|
379
|
-
/**
|
|
380
|
-
* Remove specific file from cache.
|
|
381
|
-
*/
|
|
337
|
+
/** Remove specific file from cache */
|
|
382
338
|
removeFromCache(fileId) {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
339
|
+
this._cache.update((cache) => {
|
|
340
|
+
const next = new Map(cache);
|
|
341
|
+
next.delete(fileId);
|
|
342
|
+
return next;
|
|
343
|
+
});
|
|
386
344
|
}
|
|
387
|
-
|
|
388
|
-
|
|
345
|
+
addToCache(files) {
|
|
346
|
+
this._cache.update((cache) => {
|
|
347
|
+
const next = new Map(cache);
|
|
348
|
+
for (const file of files) {
|
|
349
|
+
next.set(file.id, file);
|
|
350
|
+
}
|
|
351
|
+
return next;
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
getFromCache(fileIds) {
|
|
355
|
+
const cache = this._cache();
|
|
356
|
+
return fileIds
|
|
357
|
+
.map((id) => cache.get(id))
|
|
358
|
+
.filter((f) => f !== undefined);
|
|
359
|
+
}
|
|
360
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileUrlService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
361
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileUrlService, providedIn: 'root' });
|
|
389
362
|
}
|
|
390
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
363
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileUrlService, decorators: [{
|
|
391
364
|
type: Injectable,
|
|
392
365
|
args: [{ providedIn: 'root' }]
|
|
393
366
|
}] });
|
|
394
367
|
|
|
395
368
|
/**
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
369
|
+
* Check if user has a specific permission using wildcard matching.
|
|
370
|
+
* Supports:
|
|
371
|
+
* - Exact match: 'user.create' matches 'user.create'
|
|
372
|
+
* - Full wildcard: '*' matches everything
|
|
373
|
+
* - Module wildcard: 'user.*' matches 'user.create', 'user.read', etc.
|
|
374
|
+
*/
|
|
375
|
+
function hasPermission(requiredPermission, userPermissions) {
|
|
376
|
+
// Exact match
|
|
377
|
+
if (userPermissions.includes(requiredPermission))
|
|
378
|
+
return true;
|
|
379
|
+
// Wildcard matching
|
|
380
|
+
for (const permission of userPermissions) {
|
|
381
|
+
// Full wildcard - grants all permissions
|
|
382
|
+
if (permission === '*')
|
|
383
|
+
return true;
|
|
384
|
+
// Module wildcard (e.g., 'user.*' matches 'user.create')
|
|
385
|
+
if (permission.endsWith('.*') &&
|
|
386
|
+
requiredPermission.startsWith(permission.slice(0, -1))) {
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
/** Evaluate permission logic (string or ILogicNode) against user permissions */
|
|
393
|
+
function evaluatePermission(logic, permissions) {
|
|
394
|
+
if (!logic)
|
|
395
|
+
return false;
|
|
396
|
+
if (typeof logic === 'string')
|
|
397
|
+
return hasPermission(logic, permissions);
|
|
398
|
+
return evaluateLogicNode(logic, permissions);
|
|
399
|
+
}
|
|
400
|
+
/** Recursively evaluate an ILogicNode tree */
|
|
401
|
+
function evaluateLogicNode(node, permissions) {
|
|
402
|
+
switch (node.type) {
|
|
403
|
+
case 'action':
|
|
404
|
+
return node.actionId ? hasPermission(node.actionId, permissions) : false;
|
|
405
|
+
case 'group':
|
|
406
|
+
if (!node.children || node.children.length === 0)
|
|
407
|
+
return false;
|
|
408
|
+
return node.operator === 'AND'
|
|
409
|
+
? node.children.every((child) => evaluateLogicNode(child, permissions))
|
|
410
|
+
: node.children.some((child) => evaluateLogicNode(child, permissions));
|
|
411
|
+
default:
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/** Check if user has ANY of the specified permissions (OR logic) */
|
|
416
|
+
function hasAnyPermission(permissionCodes, permissions) {
|
|
417
|
+
if (!permissionCodes?.length)
|
|
418
|
+
return false;
|
|
419
|
+
return permissionCodes.some((code) => hasPermission(code, permissions));
|
|
420
|
+
}
|
|
421
|
+
/** Check if user has ALL of the specified permissions (AND logic) */
|
|
422
|
+
function hasAllPermissions(permissionCodes, permissions) {
|
|
423
|
+
if (!permissionCodes?.length)
|
|
424
|
+
return false;
|
|
425
|
+
return permissionCodes.every((code) => hasPermission(code, permissions));
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Permission state management service.
|
|
430
|
+
* Provides signal-based storage and permission checking with wildcard support.
|
|
428
431
|
*/
|
|
429
432
|
class PermissionValidatorService {
|
|
430
|
-
// ==================== SIGNALS ====================
|
|
431
|
-
/**
|
|
432
|
-
* Private writable signal for permissions
|
|
433
|
-
*/
|
|
434
433
|
_permissions = signal([], ...(ngDevMode ? [{ debugName: "_permissions" }] : []));
|
|
435
|
-
/**
|
|
436
|
-
* Readonly permission signal for external consumers
|
|
437
|
-
*/
|
|
438
434
|
permissions = this._permissions.asReadonly();
|
|
439
|
-
/**
|
|
440
|
-
* Private writable signal for loaded state
|
|
441
|
-
*/
|
|
442
435
|
_isLoaded = signal(false, ...(ngDevMode ? [{ debugName: "_isLoaded" }] : []));
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
* @param permissions - Array of permission codes
|
|
446
|
-
*/
|
|
436
|
+
isLoaded = this._isLoaded.asReadonly();
|
|
437
|
+
/** Set permissions (replaces existing) */
|
|
447
438
|
setPermissions(permissions) {
|
|
448
439
|
this._permissions.set(permissions);
|
|
449
440
|
this._isLoaded.set(true);
|
|
450
441
|
}
|
|
451
|
-
/**
|
|
452
|
-
* Clear all permissions
|
|
453
|
-
*/
|
|
442
|
+
/** Clear all permissions */
|
|
454
443
|
clearPermissions() {
|
|
455
444
|
this._permissions.set([]);
|
|
456
445
|
this._isLoaded.set(false);
|
|
457
446
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
* @param permissionCode - Required permission code
|
|
462
|
-
* @returns True if user has permission
|
|
463
|
-
*/
|
|
464
|
-
hasPermission(permissionCode) {
|
|
465
|
-
return this.permissions().includes(permissionCode);
|
|
447
|
+
/** Check if user has permission (supports wildcards: '*', 'module.*') */
|
|
448
|
+
hasPermission(code) {
|
|
449
|
+
return hasPermission(code, this._permissions());
|
|
466
450
|
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Check if permissions are loaded
|
|
470
|
-
* @returns True if permissions have been loaded
|
|
471
|
-
*/
|
|
451
|
+
/** @deprecated Use `isLoaded()` signal instead */
|
|
472
452
|
isPermissionsLoaded() {
|
|
473
453
|
return this._isLoaded();
|
|
474
454
|
}
|
|
475
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
476
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.
|
|
455
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PermissionValidatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
456
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PermissionValidatorService, providedIn: 'root' });
|
|
477
457
|
}
|
|
478
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
458
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PermissionValidatorService, decorators: [{
|
|
479
459
|
type: Injectable,
|
|
480
|
-
args: [{
|
|
481
|
-
providedIn: 'root',
|
|
482
|
-
}]
|
|
460
|
+
args: [{ providedIn: 'root' }]
|
|
483
461
|
}] });
|
|
484
462
|
|
|
485
463
|
class EditModeElementChangerDirective {
|
|
@@ -535,77 +513,16 @@ class EditModeElementChangerDirective {
|
|
|
535
513
|
}
|
|
536
514
|
}
|
|
537
515
|
}
|
|
538
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
539
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.
|
|
516
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: EditModeElementChangerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
517
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.5", type: EditModeElementChangerDirective, isStandalone: true, selector: "[appEditModeElementChanger]", inputs: { isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
|
|
540
518
|
}
|
|
541
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
519
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: EditModeElementChangerDirective, decorators: [{
|
|
542
520
|
type: Directive,
|
|
543
521
|
args: [{
|
|
544
522
|
selector: '[appEditModeElementChanger]',
|
|
545
|
-
standalone: true,
|
|
546
523
|
}]
|
|
547
524
|
}], ctorParameters: () => [], propDecorators: { isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: true }] }] } });
|
|
548
525
|
|
|
549
|
-
/**
|
|
550
|
-
* Check if user has a specific permission using wildcard matching.
|
|
551
|
-
* Supports:
|
|
552
|
-
* - Exact match: 'user.create' matches 'user.create'
|
|
553
|
-
* - Full wildcard: '*' matches everything
|
|
554
|
-
* - Module wildcard: 'user.*' matches 'user.create', 'user.read', etc.
|
|
555
|
-
*/
|
|
556
|
-
function hasPermission(requiredPermission, userPermissions) {
|
|
557
|
-
// Exact match
|
|
558
|
-
if (userPermissions.includes(requiredPermission))
|
|
559
|
-
return true;
|
|
560
|
-
// Wildcard matching
|
|
561
|
-
for (const permission of userPermissions) {
|
|
562
|
-
// Full wildcard - grants all permissions
|
|
563
|
-
if (permission === '*')
|
|
564
|
-
return true;
|
|
565
|
-
// Module wildcard (e.g., 'user.*' matches 'user.create')
|
|
566
|
-
if (permission.endsWith('.*') &&
|
|
567
|
-
requiredPermission.startsWith(permission.slice(0, -1))) {
|
|
568
|
-
return true;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
return false;
|
|
572
|
-
}
|
|
573
|
-
/** Evaluate permission logic (string or ILogicNode) against user permissions */
|
|
574
|
-
function evaluatePermission(logic, permissions) {
|
|
575
|
-
if (!logic)
|
|
576
|
-
return false;
|
|
577
|
-
if (typeof logic === 'string')
|
|
578
|
-
return hasPermission(logic, permissions);
|
|
579
|
-
return evaluateLogicNode(logic, permissions);
|
|
580
|
-
}
|
|
581
|
-
/** Recursively evaluate an ILogicNode tree */
|
|
582
|
-
function evaluateLogicNode(node, permissions) {
|
|
583
|
-
switch (node.type) {
|
|
584
|
-
case 'action':
|
|
585
|
-
return node.actionId ? hasPermission(node.actionId, permissions) : false;
|
|
586
|
-
case 'group':
|
|
587
|
-
if (!node.children || node.children.length === 0)
|
|
588
|
-
return false;
|
|
589
|
-
return node.operator === 'AND'
|
|
590
|
-
? node.children.every((child) => evaluateLogicNode(child, permissions))
|
|
591
|
-
: node.children.some((child) => evaluateLogicNode(child, permissions));
|
|
592
|
-
default:
|
|
593
|
-
return false;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
/** Check if user has ANY of the specified permissions (OR logic) */
|
|
597
|
-
function hasAnyPermission(permissionCodes, permissions) {
|
|
598
|
-
if (!permissionCodes?.length)
|
|
599
|
-
return false;
|
|
600
|
-
return permissionCodes.some((code) => hasPermission(code, permissions));
|
|
601
|
-
}
|
|
602
|
-
/** Check if user has ALL of the specified permissions (AND logic) */
|
|
603
|
-
function hasAllPermissions(permissionCodes, permissions) {
|
|
604
|
-
if (!permissionCodes?.length)
|
|
605
|
-
return false;
|
|
606
|
-
return permissionCodes.every((code) => hasPermission(code, permissions));
|
|
607
|
-
}
|
|
608
|
-
|
|
609
526
|
/**
|
|
610
527
|
* HasPermission Directive
|
|
611
528
|
*
|
|
@@ -719,14 +636,13 @@ class HasPermissionDirective {
|
|
|
719
636
|
this.viewCreated = false;
|
|
720
637
|
}
|
|
721
638
|
}
|
|
722
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
723
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.
|
|
639
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: HasPermissionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
640
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.5", type: HasPermissionDirective, isStandalone: true, selector: "[hasPermission]", inputs: { hasPermission: { classPropertyName: "hasPermission", publicName: "hasPermission", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
724
641
|
}
|
|
725
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
642
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: HasPermissionDirective, decorators: [{
|
|
726
643
|
type: Directive,
|
|
727
644
|
args: [{
|
|
728
645
|
selector: '[hasPermission]',
|
|
729
|
-
standalone: true,
|
|
730
646
|
}]
|
|
731
647
|
}], ctorParameters: () => [], propDecorators: { hasPermission: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasPermission", required: false }] }] } });
|
|
732
648
|
|
|
@@ -744,10 +660,10 @@ class IsEmptyImageDirective {
|
|
|
744
660
|
onError() {
|
|
745
661
|
this.hasError.set(true);
|
|
746
662
|
}
|
|
747
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
748
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.
|
|
663
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: IsEmptyImageDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
664
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.5", type: IsEmptyImageDirective, isStandalone: true, selector: "img", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "error": "onError()" }, properties: { "src": "imageSrc()" } }, ngImport: i0 });
|
|
749
665
|
}
|
|
750
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
666
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: IsEmptyImageDirective, decorators: [{
|
|
751
667
|
type: Directive,
|
|
752
668
|
args: [{
|
|
753
669
|
selector: 'img',
|
|
@@ -755,7 +671,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
755
671
|
'[src]': 'imageSrc()',
|
|
756
672
|
'(error)': 'onError()',
|
|
757
673
|
},
|
|
758
|
-
standalone: true,
|
|
759
674
|
}]
|
|
760
675
|
}], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }] } });
|
|
761
676
|
|
|
@@ -786,14 +701,13 @@ class PreventDefaultDirective {
|
|
|
786
701
|
event.preventDefault();
|
|
787
702
|
this.action.emit(event);
|
|
788
703
|
}
|
|
789
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
790
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.
|
|
704
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PreventDefaultDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
705
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.5", type: PreventDefaultDirective, isStandalone: true, selector: "[appPreventDefault]", inputs: { eventType: { classPropertyName: "eventType", publicName: "eventType", isSignal: true, isRequired: false, transformFunction: null }, preventKey: { classPropertyName: "preventKey", publicName: "preventKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { listeners: { "click": "onClick($event)", "keydown": "onKeydown($event)", "keyup": "onKeyup($event)" } }, ngImport: i0 });
|
|
791
706
|
}
|
|
792
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
707
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PreventDefaultDirective, decorators: [{
|
|
793
708
|
type: Directive,
|
|
794
709
|
args: [{
|
|
795
710
|
selector: '[appPreventDefault]',
|
|
796
|
-
standalone: true,
|
|
797
711
|
host: {
|
|
798
712
|
'(click)': 'onClick($event)',
|
|
799
713
|
'(keydown)': 'onKeydown($event)',
|
|
@@ -803,8 +717,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
803
717
|
}], propDecorators: { eventType: [{ type: i0.Input, args: [{ isSignal: true, alias: "eventType", required: false }] }], preventKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventKey", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
804
718
|
|
|
805
719
|
class AngularModule {
|
|
806
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
807
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.
|
|
720
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AngularModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
721
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.5", ngImport: i0, type: AngularModule, imports: [CommonModule,
|
|
808
722
|
FormsModule,
|
|
809
723
|
ReactiveFormsModule,
|
|
810
724
|
RouterOutlet,
|
|
@@ -823,13 +737,13 @@ class AngularModule {
|
|
|
823
737
|
NgOptimizedImage,
|
|
824
738
|
NgComponentOutlet,
|
|
825
739
|
PreventDefaultDirective] });
|
|
826
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.
|
|
740
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AngularModule, providers: [DatePipe], imports: [CommonModule,
|
|
827
741
|
FormsModule,
|
|
828
742
|
ReactiveFormsModule, CommonModule,
|
|
829
743
|
FormsModule,
|
|
830
744
|
ReactiveFormsModule] });
|
|
831
745
|
}
|
|
832
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
746
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AngularModule, decorators: [{
|
|
833
747
|
type: NgModule,
|
|
834
748
|
args: [{
|
|
835
749
|
imports: [
|
|
@@ -861,8 +775,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
861
775
|
}] });
|
|
862
776
|
|
|
863
777
|
class PrimeModule {
|
|
864
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
865
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.
|
|
778
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PrimeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
779
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.5", ngImport: i0, type: PrimeModule, exports: [AutoCompleteModule,
|
|
866
780
|
AvatarModule,
|
|
867
781
|
ButtonModule,
|
|
868
782
|
CardModule,
|
|
@@ -899,7 +813,7 @@ class PrimeModule {
|
|
|
899
813
|
ToggleSwitchModule,
|
|
900
814
|
TooltipModule,
|
|
901
815
|
TreeTableModule] });
|
|
902
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.
|
|
816
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PrimeModule, imports: [AutoCompleteModule,
|
|
903
817
|
AvatarModule,
|
|
904
818
|
ButtonModule,
|
|
905
819
|
CardModule,
|
|
@@ -937,7 +851,7 @@ class PrimeModule {
|
|
|
937
851
|
TooltipModule,
|
|
938
852
|
TreeTableModule] });
|
|
939
853
|
}
|
|
940
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
854
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: PrimeModule, decorators: [{
|
|
941
855
|
type: NgModule,
|
|
942
856
|
args: [{
|
|
943
857
|
exports: [
|
|
@@ -1003,11 +917,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1003
917
|
*
|
|
1004
918
|
* @example
|
|
1005
919
|
* ```typescript
|
|
1006
|
-
* // Define service
|
|
920
|
+
* // Define service with global apiBaseUrl
|
|
1007
921
|
* @Injectable({ providedIn: 'root' })
|
|
1008
922
|
* export class UserService extends ApiResourceService<UserDto, User> {
|
|
1009
|
-
* constructor(
|
|
1010
|
-
* super('users',
|
|
923
|
+
* constructor() {
|
|
924
|
+
* super('auth/users', inject(HttpClient));
|
|
925
|
+
* }
|
|
926
|
+
* }
|
|
927
|
+
*
|
|
928
|
+
* // Define service with feature-specific baseUrl
|
|
929
|
+
* @Injectable({ providedIn: 'root' })
|
|
930
|
+
* export class FormService extends ApiResourceService<FormDto, Form> {
|
|
931
|
+
* constructor() {
|
|
932
|
+
* super('form', inject(HttpClient), 'formBuilder');
|
|
933
|
+
* // URL: services.formBuilder.baseUrl + '/form'
|
|
1011
934
|
* }
|
|
1012
935
|
* }
|
|
1013
936
|
*
|
|
@@ -1028,7 +951,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1028
951
|
*/
|
|
1029
952
|
class ApiResourceService {
|
|
1030
953
|
baseUrl;
|
|
1031
|
-
loaderService = inject(ApiLoaderService);
|
|
1032
954
|
injector = inject(Injector);
|
|
1033
955
|
http;
|
|
1034
956
|
moduleApiName;
|
|
@@ -1132,9 +1054,17 @@ class ApiResourceService {
|
|
|
1132
1054
|
return false;
|
|
1133
1055
|
return meta.hasMore ?? (meta.page + 1) * meta.pageSize < meta.total;
|
|
1134
1056
|
}, ...(ngDevMode ? [{ debugName: "hasMore" }] : []));
|
|
1135
|
-
|
|
1057
|
+
/**
|
|
1058
|
+
* @param moduleApiName - The API resource path (e.g., 'form' for /form-builder/form)
|
|
1059
|
+
* @param http - HttpClient instance
|
|
1060
|
+
* @param serviceName - Optional service name for feature-specific base URL (e.g., 'formBuilder')
|
|
1061
|
+
*/
|
|
1062
|
+
constructor(moduleApiName, http, serviceName) {
|
|
1136
1063
|
this.moduleApiName = moduleApiName;
|
|
1137
|
-
|
|
1064
|
+
const config = inject(APP_CONFIG);
|
|
1065
|
+
// Use service-specific URL if provided, otherwise fallback to global apiBaseUrl
|
|
1066
|
+
const serviceBaseUrl = serviceName ? getServiceUrl(config, serviceName) : config.apiBaseUrl;
|
|
1067
|
+
this.baseUrl = `${serviceBaseUrl}/${moduleApiName}`;
|
|
1138
1068
|
this.http = http;
|
|
1139
1069
|
// Resource is now lazy-initialized, not created in constructor
|
|
1140
1070
|
}
|
|
@@ -1398,10 +1328,10 @@ class BaseFormControl {
|
|
|
1398
1328
|
this.onTouched();
|
|
1399
1329
|
}
|
|
1400
1330
|
}
|
|
1401
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1402
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.
|
|
1331
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseFormControl, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1332
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.5", type: BaseFormControl, isStandalone: true, inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", touched: "touchedChange" }, ngImport: i0 });
|
|
1403
1333
|
}
|
|
1404
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1334
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseFormControl, decorators: [{
|
|
1405
1335
|
type: Directive
|
|
1406
1336
|
}], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }] } });
|
|
1407
1337
|
/**
|
|
@@ -1428,30 +1358,29 @@ class IconComponent {
|
|
|
1428
1358
|
icon = input.required(...(ngDevMode ? [{ debugName: "icon" }] : []));
|
|
1429
1359
|
iconType = input(IconTypeEnum.PRIMENG_ICON, ...(ngDevMode ? [{ debugName: "iconType" }] : []));
|
|
1430
1360
|
IconTypeEnum = IconTypeEnum; // Needed for template reference
|
|
1431
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1432
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
1361
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1362
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: IconComponent, isStandalone: true, selector: "lib-icon", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, iconType: { classPropertyName: "iconType", publicName: "iconType", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1433
1363
|
@if (icon()) {
|
|
1434
1364
|
@if (iconType() === IconTypeEnum.PRIMENG_ICON) {
|
|
1435
|
-
<i [
|
|
1365
|
+
<i [class]="icon()"></i>
|
|
1436
1366
|
} @else if (iconType() === IconTypeEnum.IMAGE_FILE_LINK) {
|
|
1437
1367
|
<img [alt]="icon()" [src]="icon()" />
|
|
1438
1368
|
} @else {
|
|
1439
1369
|
<i class="pi pi-question"></i>
|
|
1440
1370
|
}
|
|
1441
1371
|
}
|
|
1442
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type:
|
|
1372
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: IsEmptyImageDirective, selector: "img", inputs: ["src"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1443
1373
|
}
|
|
1444
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1374
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: IconComponent, decorators: [{
|
|
1445
1375
|
type: Component,
|
|
1446
1376
|
args: [{
|
|
1447
1377
|
selector: 'lib-icon',
|
|
1448
|
-
standalone: true,
|
|
1449
1378
|
imports: [AngularModule],
|
|
1450
1379
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1451
1380
|
template: `
|
|
1452
1381
|
@if (icon()) {
|
|
1453
1382
|
@if (iconType() === IconTypeEnum.PRIMENG_ICON) {
|
|
1454
|
-
<i [
|
|
1383
|
+
<i [class]="icon()"></i>
|
|
1455
1384
|
} @else if (iconType() === IconTypeEnum.IMAGE_FILE_LINK) {
|
|
1456
1385
|
<img [alt]="icon()" [src]="icon()" />
|
|
1457
1386
|
} @else {
|
|
@@ -1462,6 +1391,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1462
1391
|
}]
|
|
1463
1392
|
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], iconType: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconType", required: false }] }] } });
|
|
1464
1393
|
|
|
1394
|
+
/**
|
|
1395
|
+
* Check if scroll has reached near bottom and calculate next page if available.
|
|
1396
|
+
* Returns next pagination if should load more, null otherwise.
|
|
1397
|
+
*
|
|
1398
|
+
* @example
|
|
1399
|
+
* ```typescript
|
|
1400
|
+
* onScroll(event: Event): void {
|
|
1401
|
+
* const nextPagination = checkScrollPagination(event, {
|
|
1402
|
+
* pagination: this.pagination(),
|
|
1403
|
+
* total: this.total(),
|
|
1404
|
+
* isLoading: this.isLoading(),
|
|
1405
|
+
* });
|
|
1406
|
+
* if (nextPagination) {
|
|
1407
|
+
* this.onPagination.emit(nextPagination);
|
|
1408
|
+
* }
|
|
1409
|
+
* }
|
|
1410
|
+
* ```
|
|
1411
|
+
*/
|
|
1412
|
+
function checkScrollPagination(event, config) {
|
|
1413
|
+
const el = event.target;
|
|
1414
|
+
if (!(el instanceof HTMLElement))
|
|
1415
|
+
return null;
|
|
1416
|
+
const threshold = config.threshold ?? 50;
|
|
1417
|
+
const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - threshold;
|
|
1418
|
+
if (!nearBottom || config.isLoading)
|
|
1419
|
+
return null;
|
|
1420
|
+
const { pagination, total } = config;
|
|
1421
|
+
const nextPage = pagination.currentPage + 1;
|
|
1422
|
+
const hasMore = nextPage * pagination.pageSize < (total ?? 0);
|
|
1423
|
+
if (!hasMore)
|
|
1424
|
+
return null;
|
|
1425
|
+
return { ...pagination, currentPage: nextPage };
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1465
1428
|
/**
|
|
1466
1429
|
* Lazy-loading multi-select component with search, pagination, and select-all.
|
|
1467
1430
|
*
|
|
@@ -1543,17 +1506,13 @@ class LazyMultiSelectComponent extends BaseFormControl {
|
|
|
1543
1506
|
});
|
|
1544
1507
|
}
|
|
1545
1508
|
onScroll(event) {
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
const hasMore = nextPage * pag.pageSize < (this.total() ?? 0);
|
|
1554
|
-
if (hasMore) {
|
|
1555
|
-
this.onPagination.emit({ ...pag, currentPage: nextPage });
|
|
1556
|
-
}
|
|
1509
|
+
const nextPagination = checkScrollPagination(event, {
|
|
1510
|
+
pagination: this.pagination(),
|
|
1511
|
+
total: this.total(),
|
|
1512
|
+
isLoading: this.isLoading(),
|
|
1513
|
+
});
|
|
1514
|
+
if (nextPagination) {
|
|
1515
|
+
this.onPagination.emit(nextPagination);
|
|
1557
1516
|
}
|
|
1558
1517
|
}
|
|
1559
1518
|
onSelectClick(event) {
|
|
@@ -1602,12 +1561,12 @@ class LazyMultiSelectComponent extends BaseFormControl {
|
|
|
1602
1561
|
event.stopPropagation();
|
|
1603
1562
|
this.value.set([]);
|
|
1604
1563
|
}
|
|
1605
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1606
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
1564
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LazyMultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1565
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: LazyMultiSelectComponent, isStandalone: true, selector: "lib-lazy-multi-select", inputs: { placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: true, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: true, transformFunction: null }, selectDataList: { classPropertyName: "selectDataList", publicName: "selectDataList", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onSearch: "onSearch", onPagination: "onPagination" }, providers: [provideValueAccessor(LazyMultiSelectComponent)], viewQueries: [{ propertyName: "pSelectRef", first: true, predicate: ["pSelect"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"p-select w-full\" #pSelect (click)=\"onSelectClick($event)\" [class.p-disabled]=\"disabled()\">\n @if (selectedValueDisplay()) {\n <span class=\"p-select-label\">{{ selectedValueDisplay() }}</span>\n } @else {\n <span class=\"p-select-label p-placeholder\">{{ placeHolder() }}</span>\n }\n\n <span class=\"p-select-clear-icon\" (click)=\"clear($event)\">\n <i class=\"pi pi-times\"></i>\n </span>\n\n <div class=\"p-select-dropdown\">\n <span class=\"p-select-dropdown-icon flex items-center\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n class=\"p-multiselect-dropdown-icon p-icon\" aria-hidden=\"true\">\n <path d=\"M7.01744 10.398C6.91269 10.3985 6.8089 10.378 6.71215 10.3379C6.61541 10.2977 6.52766 10.2386 6.45405 10.1641L1.13907 4.84913C1.03306 4.69404 0.985221 4.5065 1.00399 4.31958C1.02276 4.13266 1.10693 3.95838 1.24166 3.82747C1.37639 3.69655 1.55301 3.61742 1.74039 3.60402C1.92777 3.59062 2.11386 3.64382 2.26584 3.75424L7.01744 8.47394L11.769 3.75424C11.9189 3.65709 12.097 3.61306 12.2748 3.62921C12.4527 3.64535 12.6199 3.72073 12.7498 3.84328C12.8797 3.96582 12.9647 4.12842 12.9912 4.30502C13.0177 4.48162 12.9841 4.662 12.8958 4.81724L7.58083 10.1322C7.50996 10.2125 7.42344 10.2775 7.32656 10.3232C7.22968 10.3689 7.12449 10.3944 7.01744 10.398Z\" fill=\"currentColor\" />\n </svg>\n </span>\n </div>\n\n @if (openOptions()) {\n <div class=\"p-select-overlay\" (click)=\"onOverlayClick($event)\">\n <div class=\"p-select-header flex flex-row gap-2 items-center\">\n <p-checkbox\n binary=\"true\"\n [ngModel]=\"isSelectAll()\"\n [disabled]=\"disabled()\"\n (onChange)=\"changeSelectAll($event)\"\n />\n <input\n type=\"text\"\n pInputText\n class=\"w-full\"\n placeholder=\"Search...\"\n [ngModel]=\"searchTerm()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"searchTerm.set($event)\"\n />\n </div>\n <div class=\"p-select-list-container\" (scroll)=\"onScroll($event)\">\n <ul class=\"p-select-list\">\n @for (data of selectDataList(); track key(data)) {\n <li class=\"p-select-option flex flex-row gap-2 items-center\"\n [ngClass]=\"{ 'p-select-option-selected': isSelected(data) }\">\n <p-checkbox\n binary=\"true\"\n [ngModel]=\"isSelected(data)\"\n [disabled]=\"disabled()\"\n (onChange)=\"selectValue($event, data)\"\n />\n <span>{{ data.label }}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n</div>", styles: [".p-select-overlay{position:absolute;top:100%;left:0;right:0;z-index:var(--p-overlay-select-zindex, 1004);margin-top:var(--p-select-overlay-offset, 2px);background:var(--p-select-overlay-background, var(--p-surface-0));border:1px solid var(--p-select-overlay-border-color, var(--p-surface-200));border-radius:var(--p-select-overlay-border-radius, var(--p-border-radius));box-shadow:var(--p-select-overlay-shadow, var(--p-overlay-shadow))}.p-select-header{padding:.75rem;border-bottom:1px solid var(--p-surface-200);background:var(--p-surface-50)}:host-context(.p-dark) .p-select-header,.dark .p-select-header{border-color:var(--p-surface-700);background:var(--p-surface-800)}.p-select-list-container{max-height:10rem;overflow-y:auto}@media(min-width:640px){.p-select-list-container{max-height:12.5rem}}.p-select-list{margin:0;padding:.25rem 0;list-style:none}.p-select-option{padding:.5rem .75rem;cursor:pointer;transition:background-color .2s ease}.p-select-option:hover{background:var(--p-select-option-focus-background, var(--p-surface-100));color:var(--p-select-option-focus-color, var(--p-text-color))}:host-context(.p-dark) .p-select-option:hover,.dark .p-select-option:hover{background:var(--p-surface-700)}.p-select-option.p-select-option-selected{background:var(--p-select-option-selected-background, var(--p-primary-50));color:var(--p-select-option-selected-color, var(--p-primary-color))}:host-context(.p-dark) .p-select-option.p-select-option-selected,.dark .p-select-option.p-select-option-selected{background:var(--p-primary-900)}.p-select-option.p-select-option-selected:hover{background:var(--p-select-option-selected-focus-background, var(--p-primary-100));color:var(--p-select-option-selected-focus-color, var(--p-primary-color))}:host-context(.p-dark) .p-select-option.p-select-option-selected:hover,.dark .p-select-option.p-select-option-selected:hover{background:var(--p-primary-800)}.p-select-clear-icon{display:flex;align-items:center;padding:0 .5rem;color:var(--p-text-color-secondary);cursor:pointer;transition:color .2s ease}.p-select-clear-icon:hover{color:var(--p-text-color)}\n"], dependencies: [{ kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1607
1566
|
}
|
|
1608
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1567
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LazyMultiSelectComponent, decorators: [{
|
|
1609
1568
|
type: Component,
|
|
1610
|
-
args: [{ selector: 'lib-lazy-multi-select',
|
|
1569
|
+
args: [{ selector: 'lib-lazy-multi-select', imports: [PrimeModule, AngularModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [provideValueAccessor(LazyMultiSelectComponent)], template: "<div class=\"p-select w-full\" #pSelect (click)=\"onSelectClick($event)\" [class.p-disabled]=\"disabled()\">\n @if (selectedValueDisplay()) {\n <span class=\"p-select-label\">{{ selectedValueDisplay() }}</span>\n } @else {\n <span class=\"p-select-label p-placeholder\">{{ placeHolder() }}</span>\n }\n\n <span class=\"p-select-clear-icon\" (click)=\"clear($event)\">\n <i class=\"pi pi-times\"></i>\n </span>\n\n <div class=\"p-select-dropdown\">\n <span class=\"p-select-dropdown-icon flex items-center\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n class=\"p-multiselect-dropdown-icon p-icon\" aria-hidden=\"true\">\n <path d=\"M7.01744 10.398C6.91269 10.3985 6.8089 10.378 6.71215 10.3379C6.61541 10.2977 6.52766 10.2386 6.45405 10.1641L1.13907 4.84913C1.03306 4.69404 0.985221 4.5065 1.00399 4.31958C1.02276 4.13266 1.10693 3.95838 1.24166 3.82747C1.37639 3.69655 1.55301 3.61742 1.74039 3.60402C1.92777 3.59062 2.11386 3.64382 2.26584 3.75424L7.01744 8.47394L11.769 3.75424C11.9189 3.65709 12.097 3.61306 12.2748 3.62921C12.4527 3.64535 12.6199 3.72073 12.7498 3.84328C12.8797 3.96582 12.9647 4.12842 12.9912 4.30502C13.0177 4.48162 12.9841 4.662 12.8958 4.81724L7.58083 10.1322C7.50996 10.2125 7.42344 10.2775 7.32656 10.3232C7.22968 10.3689 7.12449 10.3944 7.01744 10.398Z\" fill=\"currentColor\" />\n </svg>\n </span>\n </div>\n\n @if (openOptions()) {\n <div class=\"p-select-overlay\" (click)=\"onOverlayClick($event)\">\n <div class=\"p-select-header flex flex-row gap-2 items-center\">\n <p-checkbox\n binary=\"true\"\n [ngModel]=\"isSelectAll()\"\n [disabled]=\"disabled()\"\n (onChange)=\"changeSelectAll($event)\"\n />\n <input\n type=\"text\"\n pInputText\n class=\"w-full\"\n placeholder=\"Search...\"\n [ngModel]=\"searchTerm()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"searchTerm.set($event)\"\n />\n </div>\n <div class=\"p-select-list-container\" (scroll)=\"onScroll($event)\">\n <ul class=\"p-select-list\">\n @for (data of selectDataList(); track key(data)) {\n <li class=\"p-select-option flex flex-row gap-2 items-center\"\n [ngClass]=\"{ 'p-select-option-selected': isSelected(data) }\">\n <p-checkbox\n binary=\"true\"\n [ngModel]=\"isSelected(data)\"\n [disabled]=\"disabled()\"\n (onChange)=\"selectValue($event, data)\"\n />\n <span>{{ data.label }}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n</div>", styles: [".p-select-overlay{position:absolute;top:100%;left:0;right:0;z-index:var(--p-overlay-select-zindex, 1004);margin-top:var(--p-select-overlay-offset, 2px);background:var(--p-select-overlay-background, var(--p-surface-0));border:1px solid var(--p-select-overlay-border-color, var(--p-surface-200));border-radius:var(--p-select-overlay-border-radius, var(--p-border-radius));box-shadow:var(--p-select-overlay-shadow, var(--p-overlay-shadow))}.p-select-header{padding:.75rem;border-bottom:1px solid var(--p-surface-200);background:var(--p-surface-50)}:host-context(.p-dark) .p-select-header,.dark .p-select-header{border-color:var(--p-surface-700);background:var(--p-surface-800)}.p-select-list-container{max-height:10rem;overflow-y:auto}@media(min-width:640px){.p-select-list-container{max-height:12.5rem}}.p-select-list{margin:0;padding:.25rem 0;list-style:none}.p-select-option{padding:.5rem .75rem;cursor:pointer;transition:background-color .2s ease}.p-select-option:hover{background:var(--p-select-option-focus-background, var(--p-surface-100));color:var(--p-select-option-focus-color, var(--p-text-color))}:host-context(.p-dark) .p-select-option:hover,.dark .p-select-option:hover{background:var(--p-surface-700)}.p-select-option.p-select-option-selected{background:var(--p-select-option-selected-background, var(--p-primary-50));color:var(--p-select-option-selected-color, var(--p-primary-color))}:host-context(.p-dark) .p-select-option.p-select-option-selected,.dark .p-select-option.p-select-option-selected{background:var(--p-primary-900)}.p-select-option.p-select-option-selected:hover{background:var(--p-select-option-selected-focus-background, var(--p-primary-100));color:var(--p-select-option-selected-focus-color, var(--p-primary-color))}:host-context(.p-dark) .p-select-option.p-select-option-selected:hover,.dark .p-select-option.p-select-option-selected:hover{background:var(--p-primary-800)}.p-select-clear-icon{display:flex;align-items:center;padding:0 .5rem;color:var(--p-text-color-secondary);cursor:pointer;transition:color .2s ease}.p-select-clear-icon:hover{color:var(--p-text-color)}\n"] }]
|
|
1611
1570
|
}], ctorParameters: () => [], propDecorators: { pSelectRef: [{ type: i0.ViewChild, args: ['pSelect', { isSignal: true }] }], placeHolder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeHolder", required: false }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: true }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: true }] }], selectDataList: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectDataList", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], onSearch: [{ type: i0.Output, args: ["onSearch"] }], onPagination: [{ type: i0.Output, args: ["onPagination"] }] } });
|
|
1612
1571
|
|
|
1613
1572
|
/**
|
|
@@ -1673,17 +1632,13 @@ class LazySelectComponent extends BaseFormControl {
|
|
|
1673
1632
|
});
|
|
1674
1633
|
}
|
|
1675
1634
|
onScroll(event) {
|
|
1676
|
-
const
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
const hasMore = nextPage * pag.pageSize < (this.total() ?? 0);
|
|
1684
|
-
if (hasMore) {
|
|
1685
|
-
this.onPagination.emit({ ...pag, currentPage: nextPage });
|
|
1686
|
-
}
|
|
1635
|
+
const nextPagination = checkScrollPagination(event, {
|
|
1636
|
+
pagination: this.pagination(),
|
|
1637
|
+
total: this.total(),
|
|
1638
|
+
isLoading: this.isLoading(),
|
|
1639
|
+
});
|
|
1640
|
+
if (nextPagination) {
|
|
1641
|
+
this.onPagination.emit(nextPagination);
|
|
1687
1642
|
}
|
|
1688
1643
|
}
|
|
1689
1644
|
showPanel() {
|
|
@@ -1709,12 +1664,12 @@ class LazySelectComponent extends BaseFormControl {
|
|
|
1709
1664
|
onBlur() {
|
|
1710
1665
|
this.markAsTouched();
|
|
1711
1666
|
}
|
|
1712
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1713
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.
|
|
1667
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LazySelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1668
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.5", type: LazySelectComponent, isStandalone: true, selector: "lib-lazy-select", inputs: { placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: true, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: true, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: true, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: true, transformFunction: null }, selectDataList: { classPropertyName: "selectDataList", publicName: "selectDataList", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onSearch: "onSearch", onPagination: "onPagination" }, providers: [provideValueAccessor(LazySelectComponent)], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div #scrollContainer class=\"lib-scroll-container\">\n <p-select\n class=\"w-full\"\n [options]=\"selectDataList()\"\n [optionLabel]=\"optionLabel()\"\n [optionValue]=\"optionValue()\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [placeholder]=\"placeHolder()\"\n [disabled]=\"disabled()\"\n [(ngModel)]=\"value\"\n appEditModeElementChanger\n [isEditMode]=\"isEditMode()\"\n (click)=\"showPanel()\"\n (onBlur)=\"onBlur()\"\n >\n <ng-template #filter let-filter>\n <input\n pInputText\n class=\"w-full\"\n [ngModel]=\"searchTerm()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"searchTerm.set($event)\"\n />\n </ng-template>\n <ng-template #selectedItem let-selectedOption>\n {{ selectedOption[optionLabel()] }}\n </ng-template>\n <ng-template #item let-item>\n {{ item[optionLabel()] }}\n </ng-template>\n </p-select>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i3$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: EditModeElementChangerDirective, selector: "[appEditModeElementChanger]", inputs: ["isEditMode"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1714
1669
|
}
|
|
1715
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1670
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LazySelectComponent, decorators: [{
|
|
1716
1671
|
type: Component,
|
|
1717
|
-
args: [{ selector: 'lib-lazy-select',
|
|
1672
|
+
args: [{ selector: 'lib-lazy-select', imports: [AngularModule, PrimeModule, EditModeElementChangerDirective], changeDetection: ChangeDetectionStrategy.OnPush, providers: [provideValueAccessor(LazySelectComponent)], template: "<div #scrollContainer class=\"lib-scroll-container\">\n <p-select\n class=\"w-full\"\n [options]=\"selectDataList()\"\n [optionLabel]=\"optionLabel()\"\n [optionValue]=\"optionValue()\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [placeholder]=\"placeHolder()\"\n [disabled]=\"disabled()\"\n [(ngModel)]=\"value\"\n appEditModeElementChanger\n [isEditMode]=\"isEditMode()\"\n (click)=\"showPanel()\"\n (onBlur)=\"onBlur()\"\n >\n <ng-template #filter let-filter>\n <input\n pInputText\n class=\"w-full\"\n [ngModel]=\"searchTerm()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"searchTerm.set($event)\"\n />\n </ng-template>\n <ng-template #selectedItem let-selectedOption>\n {{ selectedOption[optionLabel()] }}\n </ng-template>\n <ng-template #item let-item>\n {{ item[optionLabel()] }}\n </ng-template>\n </p-select>\n</div>\n" }]
|
|
1718
1673
|
}], ctorParameters: () => [], propDecorators: { scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }], placeHolder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeHolder", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: true }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: true }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: true }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: true }] }], selectDataList: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectDataList", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], onSearch: [{ type: i0.Output, args: ["onSearch"] }], onPagination: [{ type: i0.Output, args: ["onPagination"] }] } });
|
|
1719
1674
|
|
|
1720
1675
|
/**
|
|
@@ -1813,56 +1768,33 @@ const PROFILE_UPLOAD_PROVIDER = new InjectionToken('PROFILE_UPLOAD_PROVIDER');
|
|
|
1813
1768
|
*/
|
|
1814
1769
|
const USER_LIST_PROVIDER = new InjectionToken('USER_LIST_PROVIDER');
|
|
1815
1770
|
|
|
1816
|
-
const DEFAULT_PAGE_SIZE$
|
|
1771
|
+
const DEFAULT_PAGE_SIZE$1 = 20;
|
|
1817
1772
|
/**
|
|
1818
|
-
*
|
|
1819
|
-
*
|
|
1820
|
-
* Uses USER_PROVIDER internally by default, or accepts custom `loadUsers` function.
|
|
1773
|
+
* Base class for user selection components.
|
|
1774
|
+
* Provides shared user loading, pagination, and search functionality.
|
|
1821
1775
|
*
|
|
1822
|
-
*
|
|
1823
|
-
* -
|
|
1824
|
-
* - Infinite scroll pagination
|
|
1825
|
-
* - Filter active users by default (configurable)
|
|
1826
|
-
* - Supports additional filters via `additionalFilters` input
|
|
1827
|
-
*
|
|
1828
|
-
* @example
|
|
1829
|
-
* ```html
|
|
1830
|
-
* <!-- Simple usage - uses USER_PROVIDER internally -->
|
|
1831
|
-
* <lib-user-select
|
|
1832
|
-
* [(value)]="selectedUserId"
|
|
1833
|
-
* [isEditMode]="true"
|
|
1834
|
-
* />
|
|
1835
|
-
*
|
|
1836
|
-
* <!-- With custom loadUsers function -->
|
|
1837
|
-
* <lib-user-select
|
|
1838
|
-
* [(value)]="selectedUserId"
|
|
1839
|
-
* [isEditMode]="true"
|
|
1840
|
-
* [loadUsers]="customLoadUsers"
|
|
1841
|
-
* />
|
|
1842
|
-
* ```
|
|
1776
|
+
* Subclasses must implement:
|
|
1777
|
+
* - `setupValueEffect()` to track value changes and emit selection events
|
|
1843
1778
|
*/
|
|
1844
|
-
class
|
|
1779
|
+
class BaseUserSelectComponent {
|
|
1845
1780
|
destroyRef = inject(DestroyRef);
|
|
1781
|
+
injector = inject(Injector);
|
|
1846
1782
|
userProvider = inject(USER_PROVIDER);
|
|
1847
1783
|
abortController = null;
|
|
1848
|
-
// Optional: custom function to load users (uses USER_PROVIDER if not provided)
|
|
1849
|
-
loadUsers = input(...(ngDevMode ? [undefined, { debugName: "loadUsers" }] : []));
|
|
1850
1784
|
// Inputs
|
|
1785
|
+
loadUsers = input(...(ngDevMode ? [undefined, { debugName: "loadUsers" }] : []));
|
|
1851
1786
|
placeHolder = input('Select User', ...(ngDevMode ? [{ debugName: "placeHolder" }] : []));
|
|
1852
1787
|
isEditMode = input.required(...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
|
|
1853
1788
|
filterActive = input(true, ...(ngDevMode ? [{ debugName: "filterActive" }] : []));
|
|
1854
1789
|
additionalFilters = input({}, ...(ngDevMode ? [{ debugName: "additionalFilters" }] : []));
|
|
1855
|
-
pageSize = input(DEFAULT_PAGE_SIZE$
|
|
1856
|
-
// Two-way bound value
|
|
1857
|
-
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
1790
|
+
pageSize = input(DEFAULT_PAGE_SIZE$1, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
|
|
1858
1791
|
// Outputs
|
|
1859
|
-
userSelected = output();
|
|
1860
1792
|
onError = output();
|
|
1861
1793
|
// Internal state
|
|
1862
1794
|
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1863
1795
|
users = signal([], ...(ngDevMode ? [{ debugName: "users" }] : []));
|
|
1864
1796
|
total = signal(undefined, ...(ngDevMode ? [{ debugName: "total" }] : []));
|
|
1865
|
-
pagination = signal({ pageSize: DEFAULT_PAGE_SIZE$
|
|
1797
|
+
pagination = signal({ pageSize: DEFAULT_PAGE_SIZE$1, currentPage: 0 }, ...(ngDevMode ? [{ debugName: "pagination" }] : []));
|
|
1866
1798
|
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
1867
1799
|
// Computed dropdown data
|
|
1868
1800
|
dropdownUsers = computed(() => this.users().map((user) => ({
|
|
@@ -1885,20 +1817,8 @@ class UserSelectComponent {
|
|
|
1885
1817
|
afterNextRender(() => {
|
|
1886
1818
|
this.fetchUsers();
|
|
1887
1819
|
});
|
|
1888
|
-
//
|
|
1889
|
-
|
|
1890
|
-
const selectedId = this.value();
|
|
1891
|
-
const users = this.users();
|
|
1892
|
-
untracked(() => {
|
|
1893
|
-
if (selectedId) {
|
|
1894
|
-
const user = users.find((u) => u.id === selectedId);
|
|
1895
|
-
this.userSelected.emit(user ?? null);
|
|
1896
|
-
}
|
|
1897
|
-
else {
|
|
1898
|
-
this.userSelected.emit(null);
|
|
1899
|
-
}
|
|
1900
|
-
});
|
|
1901
|
-
});
|
|
1820
|
+
// Setup value change tracking (implemented by subclass)
|
|
1821
|
+
this.setupValueEffect();
|
|
1902
1822
|
}
|
|
1903
1823
|
handleSearch(search) {
|
|
1904
1824
|
this.searchTerm.set(search);
|
|
@@ -1910,6 +1830,12 @@ class UserSelectComponent {
|
|
|
1910
1830
|
this.pagination.set(pagination);
|
|
1911
1831
|
this.fetchUsers(true);
|
|
1912
1832
|
}
|
|
1833
|
+
/** Reload users (useful when filters change externally) */
|
|
1834
|
+
reload() {
|
|
1835
|
+
this.pagination.update((p) => ({ ...p, currentPage: 0 }));
|
|
1836
|
+
this.users.set([]);
|
|
1837
|
+
this.fetchUsers();
|
|
1838
|
+
}
|
|
1913
1839
|
async fetchUsers(append = false) {
|
|
1914
1840
|
if (this.isLoading())
|
|
1915
1841
|
return;
|
|
@@ -1967,14 +1893,63 @@ class UserSelectComponent {
|
|
|
1967
1893
|
})),
|
|
1968
1894
|
})));
|
|
1969
1895
|
}
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1896
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseUserSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1897
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.5", type: BaseUserSelectComponent, isStandalone: true, inputs: { loadUsers: { classPropertyName: "loadUsers", publicName: "loadUsers", isSignal: true, isRequired: false, transformFunction: null }, placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, filterActive: { classPropertyName: "filterActive", publicName: "filterActive", isSignal: true, isRequired: false, transformFunction: null }, additionalFilters: { classPropertyName: "additionalFilters", publicName: "additionalFilters", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onError: "onError" }, ngImport: i0 });
|
|
1898
|
+
}
|
|
1899
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseUserSelectComponent, decorators: [{
|
|
1900
|
+
type: Directive
|
|
1901
|
+
}], ctorParameters: () => [], propDecorators: { loadUsers: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadUsers", required: false }] }], placeHolder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeHolder", required: false }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: true }] }], filterActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterActive", required: false }] }], additionalFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "additionalFilters", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], onError: [{ type: i0.Output, args: ["onError"] }] } });
|
|
1902
|
+
|
|
1903
|
+
/**
|
|
1904
|
+
* User Select Component - Single user selection with lazy loading.
|
|
1905
|
+
*
|
|
1906
|
+
* Uses USER_PROVIDER internally by default, or accepts custom `loadUsers` function.
|
|
1907
|
+
*
|
|
1908
|
+
* Features:
|
|
1909
|
+
* - Search with debouncing (handled by lazy-select)
|
|
1910
|
+
* - Infinite scroll pagination
|
|
1911
|
+
* - Filter active users by default (configurable)
|
|
1912
|
+
* - Supports additional filters via `additionalFilters` input
|
|
1913
|
+
*
|
|
1914
|
+
* @example
|
|
1915
|
+
* ```html
|
|
1916
|
+
* <!-- Simple usage - uses USER_PROVIDER internally -->
|
|
1917
|
+
* <lib-user-select
|
|
1918
|
+
* [(value)]="selectedUserId"
|
|
1919
|
+
* [isEditMode]="true"
|
|
1920
|
+
* />
|
|
1921
|
+
*
|
|
1922
|
+
* <!-- With custom loadUsers function -->
|
|
1923
|
+
* <lib-user-select
|
|
1924
|
+
* [(value)]="selectedUserId"
|
|
1925
|
+
* [isEditMode]="true"
|
|
1926
|
+
* [loadUsers]="customLoadUsers"
|
|
1927
|
+
* />
|
|
1928
|
+
* ```
|
|
1929
|
+
*/
|
|
1930
|
+
class UserSelectComponent extends BaseUserSelectComponent {
|
|
1931
|
+
// Two-way bound value
|
|
1932
|
+
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
1933
|
+
// Outputs
|
|
1934
|
+
userSelected = output();
|
|
1935
|
+
setupValueEffect() {
|
|
1936
|
+
// Emit selected user when value changes
|
|
1937
|
+
effect(() => {
|
|
1938
|
+
const selectedId = this.value();
|
|
1939
|
+
const users = this.users();
|
|
1940
|
+
untracked(() => {
|
|
1941
|
+
if (selectedId) {
|
|
1942
|
+
const user = users.find((u) => u.id === selectedId);
|
|
1943
|
+
this.userSelected.emit(user ?? null);
|
|
1944
|
+
}
|
|
1945
|
+
else {
|
|
1946
|
+
this.userSelected.emit(null);
|
|
1947
|
+
}
|
|
1948
|
+
});
|
|
1949
|
+
});
|
|
1975
1950
|
}
|
|
1976
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
1977
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.
|
|
1951
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UserSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1952
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.5", type: UserSelectComponent, isStandalone: true, selector: "lib-user-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", userSelected: "userSelected" }, usesInheritance: true, ngImport: i0, template: `
|
|
1978
1953
|
<lib-lazy-select
|
|
1979
1954
|
[(value)]="value"
|
|
1980
1955
|
[placeHolder]="placeHolder()"
|
|
@@ -1990,11 +1965,10 @@ class UserSelectComponent {
|
|
|
1990
1965
|
/>
|
|
1991
1966
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: LazySelectComponent, selector: "lib-lazy-select", inputs: ["placeHolder", "optionLabel", "optionValue", "isEditMode", "isLoading", "total", "pagination", "selectDataList", "value"], outputs: ["valueChange", "onSearch", "onPagination"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1992
1967
|
}
|
|
1993
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
1968
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UserSelectComponent, decorators: [{
|
|
1994
1969
|
type: Component,
|
|
1995
1970
|
args: [{
|
|
1996
1971
|
selector: 'lib-user-select',
|
|
1997
|
-
standalone: true,
|
|
1998
1972
|
imports: [AngularModule, PrimeModule, LazySelectComponent],
|
|
1999
1973
|
template: `
|
|
2000
1974
|
<lib-lazy-select
|
|
@@ -2013,9 +1987,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2013
1987
|
`,
|
|
2014
1988
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2015
1989
|
}]
|
|
2016
|
-
}],
|
|
1990
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], userSelected: [{ type: i0.Output, args: ["userSelected"] }] } });
|
|
2017
1991
|
|
|
2018
|
-
const DEFAULT_PAGE_SIZE$1 = 20;
|
|
2019
1992
|
/**
|
|
2020
1993
|
* User Multi-Select Component - Multiple user selection with lazy loading.
|
|
2021
1994
|
*
|
|
@@ -2044,50 +2017,12 @@ const DEFAULT_PAGE_SIZE$1 = 20;
|
|
|
2044
2017
|
* />
|
|
2045
2018
|
* ```
|
|
2046
2019
|
*/
|
|
2047
|
-
class UserMultiSelectComponent {
|
|
2048
|
-
destroyRef = inject(DestroyRef);
|
|
2049
|
-
userProvider = inject(USER_PROVIDER);
|
|
2050
|
-
abortController = null;
|
|
2051
|
-
// Optional: custom function to load users (uses USER_PROVIDER if not provided)
|
|
2052
|
-
loadUsers = input(...(ngDevMode ? [undefined, { debugName: "loadUsers" }] : []));
|
|
2053
|
-
// Inputs
|
|
2054
|
-
placeHolder = input('Select Users', ...(ngDevMode ? [{ debugName: "placeHolder" }] : []));
|
|
2055
|
-
isEditMode = input.required(...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
|
|
2056
|
-
filterActive = input(true, ...(ngDevMode ? [{ debugName: "filterActive" }] : []));
|
|
2057
|
-
additionalFilters = input({}, ...(ngDevMode ? [{ debugName: "additionalFilters" }] : []));
|
|
2058
|
-
pageSize = input(DEFAULT_PAGE_SIZE$1, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
|
|
2020
|
+
class UserMultiSelectComponent extends BaseUserSelectComponent {
|
|
2059
2021
|
// Two-way bound value
|
|
2060
2022
|
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
2061
2023
|
// Outputs
|
|
2062
2024
|
usersSelected = output();
|
|
2063
|
-
|
|
2064
|
-
// Internal state
|
|
2065
|
-
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
2066
|
-
users = signal([], ...(ngDevMode ? [{ debugName: "users" }] : []));
|
|
2067
|
-
total = signal(undefined, ...(ngDevMode ? [{ debugName: "total" }] : []));
|
|
2068
|
-
pagination = signal({ pageSize: DEFAULT_PAGE_SIZE$1, currentPage: 0 }, ...(ngDevMode ? [{ debugName: "pagination" }] : []));
|
|
2069
|
-
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
2070
|
-
// Computed dropdown data
|
|
2071
|
-
dropdownUsers = computed(() => this.users().map((user) => ({
|
|
2072
|
-
label: user.name || user.email,
|
|
2073
|
-
value: user.id,
|
|
2074
|
-
})), ...(ngDevMode ? [{ debugName: "dropdownUsers" }] : []));
|
|
2075
|
-
constructor() {
|
|
2076
|
-
// Cleanup on destroy
|
|
2077
|
-
this.destroyRef.onDestroy(() => {
|
|
2078
|
-
this.abortController?.abort();
|
|
2079
|
-
});
|
|
2080
|
-
// Update page size from input
|
|
2081
|
-
effect(() => {
|
|
2082
|
-
const size = this.pageSize();
|
|
2083
|
-
untracked(() => {
|
|
2084
|
-
this.pagination.update((p) => ({ ...p, pageSize: size }));
|
|
2085
|
-
});
|
|
2086
|
-
});
|
|
2087
|
-
// Load initial users after render
|
|
2088
|
-
afterNextRender(() => {
|
|
2089
|
-
this.fetchUsers();
|
|
2090
|
-
});
|
|
2025
|
+
setupValueEffect() {
|
|
2091
2026
|
// Emit selected users when value changes
|
|
2092
2027
|
effect(() => {
|
|
2093
2028
|
const selectedIds = this.value() ?? [];
|
|
@@ -2098,81 +2033,8 @@ class UserMultiSelectComponent {
|
|
|
2098
2033
|
});
|
|
2099
2034
|
});
|
|
2100
2035
|
}
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
this.pagination.update((p) => ({ ...p, currentPage: 0 }));
|
|
2104
|
-
this.users.set([]);
|
|
2105
|
-
this.fetchUsers();
|
|
2106
|
-
}
|
|
2107
|
-
handlePagination(pagination) {
|
|
2108
|
-
this.pagination.set(pagination);
|
|
2109
|
-
this.fetchUsers(true);
|
|
2110
|
-
}
|
|
2111
|
-
async fetchUsers(append = false) {
|
|
2112
|
-
if (this.isLoading())
|
|
2113
|
-
return;
|
|
2114
|
-
// Cancel previous request
|
|
2115
|
-
this.abortController?.abort();
|
|
2116
|
-
this.abortController = new AbortController();
|
|
2117
|
-
this.isLoading.set(true);
|
|
2118
|
-
try {
|
|
2119
|
-
const pag = this.pagination();
|
|
2120
|
-
const filter = {
|
|
2121
|
-
page: pag.currentPage,
|
|
2122
|
-
pageSize: pag.pageSize,
|
|
2123
|
-
search: this.searchTerm(),
|
|
2124
|
-
...this.additionalFilters(),
|
|
2125
|
-
};
|
|
2126
|
-
// Use custom loadUsers if provided, otherwise use USER_PROVIDER
|
|
2127
|
-
const customLoadUsers = this.loadUsers();
|
|
2128
|
-
const response = await firstValueFrom(customLoadUsers
|
|
2129
|
-
? customLoadUsers(filter)
|
|
2130
|
-
: this.loadUsersFromProvider(filter));
|
|
2131
|
-
if (response.success && response.data) {
|
|
2132
|
-
if (append) {
|
|
2133
|
-
this.users.update((current) => [...current, ...response.data]);
|
|
2134
|
-
}
|
|
2135
|
-
else {
|
|
2136
|
-
this.users.set(response.data);
|
|
2137
|
-
}
|
|
2138
|
-
this.total.set(response.meta?.total);
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
catch (error) {
|
|
2142
|
-
if (error.name !== 'AbortError') {
|
|
2143
|
-
this.onError.emit(error);
|
|
2144
|
-
}
|
|
2145
|
-
}
|
|
2146
|
-
finally {
|
|
2147
|
-
this.isLoading.set(false);
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2150
|
-
/** Load users from USER_PROVIDER with active filter */
|
|
2151
|
-
loadUsersFromProvider(filter) {
|
|
2152
|
-
return this.userProvider
|
|
2153
|
-
.getUsers({
|
|
2154
|
-
page: filter.page,
|
|
2155
|
-
pageSize: filter.pageSize,
|
|
2156
|
-
search: filter.search,
|
|
2157
|
-
isActive: this.filterActive() ? true : undefined,
|
|
2158
|
-
})
|
|
2159
|
-
.pipe(map$1((res) => ({
|
|
2160
|
-
...res,
|
|
2161
|
-
data: res.data?.map((u) => ({
|
|
2162
|
-
id: u.id,
|
|
2163
|
-
name: u.name,
|
|
2164
|
-
email: u.email,
|
|
2165
|
-
})),
|
|
2166
|
-
})));
|
|
2167
|
-
}
|
|
2168
|
-
/** Reload users (useful when filters change externally) */
|
|
2169
|
-
reload() {
|
|
2170
|
-
this.pagination.update((p) => ({ ...p, currentPage: 0 }));
|
|
2171
|
-
this.users.set([]);
|
|
2172
|
-
this.fetchUsers();
|
|
2173
|
-
}
|
|
2174
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: UserMultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2175
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.3", type: UserMultiSelectComponent, isStandalone: true, selector: "lib-user-multi-select", inputs: { loadUsers: { classPropertyName: "loadUsers", publicName: "loadUsers", isSignal: true, isRequired: false, transformFunction: null }, placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, filterActive: { classPropertyName: "filterActive", publicName: "filterActive", isSignal: true, isRequired: false, transformFunction: null }, additionalFilters: { classPropertyName: "additionalFilters", publicName: "additionalFilters", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", usersSelected: "usersSelected", onError: "onError" }, ngImport: i0, template: `
|
|
2036
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UserMultiSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2037
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.5", type: UserMultiSelectComponent, isStandalone: true, selector: "lib-user-multi-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", usersSelected: "usersSelected" }, usesInheritance: true, ngImport: i0, template: `
|
|
2176
2038
|
<lib-lazy-multi-select
|
|
2177
2039
|
[(value)]="value"
|
|
2178
2040
|
[placeHolder]="placeHolder()"
|
|
@@ -2186,11 +2048,10 @@ class UserMultiSelectComponent {
|
|
|
2186
2048
|
/>
|
|
2187
2049
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: LazyMultiSelectComponent, selector: "lib-lazy-multi-select", inputs: ["placeHolder", "isEditMode", "isLoading", "total", "pagination", "selectDataList", "value"], outputs: ["valueChange", "onSearch", "onPagination"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2188
2050
|
}
|
|
2189
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
2051
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UserMultiSelectComponent, decorators: [{
|
|
2190
2052
|
type: Component,
|
|
2191
2053
|
args: [{
|
|
2192
2054
|
selector: 'lib-user-multi-select',
|
|
2193
|
-
standalone: true,
|
|
2194
2055
|
imports: [AngularModule, PrimeModule, LazyMultiSelectComponent],
|
|
2195
2056
|
template: `
|
|
2196
2057
|
<lib-lazy-multi-select
|
|
@@ -2207,7 +2068,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2207
2068
|
`,
|
|
2208
2069
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2209
2070
|
}]
|
|
2210
|
-
}],
|
|
2071
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], usersSelected: [{ type: i0.Output, args: ["usersSelected"] }] } });
|
|
2211
2072
|
|
|
2212
2073
|
/**
|
|
2213
2074
|
* File Uploader Component - Drag & drop file upload with type filtering.
|
|
@@ -2377,8 +2238,8 @@ class FileUploaderComponent {
|
|
|
2377
2238
|
const mb = kb / 1024;
|
|
2378
2239
|
return `${mb.toFixed(1)} MB`;
|
|
2379
2240
|
}
|
|
2380
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
2381
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
2241
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2242
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: FileUploaderComponent, isStandalone: true, selector: "lib-file-uploader", inputs: { uploadFile: { classPropertyName: "uploadFile", publicName: "uploadFile", isSignal: true, isRequired: true, transformFunction: null }, acceptTypes: { classPropertyName: "acceptTypes", publicName: "acceptTypes", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, maxSizeMb: { classPropertyName: "maxSizeMb", publicName: "maxSizeMb", isSignal: true, isRequired: false, transformFunction: null }, uploadOptions: { classPropertyName: "uploadOptions", publicName: "uploadOptions", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showPreview: { classPropertyName: "showPreview", publicName: "showPreview", isSignal: true, isRequired: false, transformFunction: null }, autoUpload: { classPropertyName: "autoUpload", publicName: "autoUpload", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileUploaded: "fileUploaded", filesUploaded: "filesUploaded", onError: "onError", fileSelected: "fileSelected" }, ngImport: i0, template: `
|
|
2382
2243
|
<div
|
|
2383
2244
|
class="w-full"
|
|
2384
2245
|
[class.opacity-60]="disabled()"
|
|
@@ -2454,11 +2315,11 @@ class FileUploaderComponent {
|
|
|
2454
2315
|
</div>
|
|
2455
2316
|
}
|
|
2456
2317
|
</div>
|
|
2457
|
-
`, isInline: true, styles: [".upload-zone{border-color:var(--p-surface-300);background:var(--p-surface-50)}.upload-zone:hover:not(.cursor-not-allowed){border-color:var(--p-primary-color);background:var(--p-surface-100)}.upload-zone.drag-over{border-color:var(--p-primary-color);background:var(--p-primary-50)}:host-context(.p-dark) .upload-zone,.dark .upload-zone{border-color:var(--p-surface-600);background:var(--p-surface-800)}:host-context(.p-dark) .upload-zone:hover:not(.cursor-not-allowed),.dark .upload-zone:hover:not(.cursor-not-allowed){border-color:var(--p-primary-color);background:var(--p-surface-700)}:host-context(.p-dark) .upload-zone.drag-over,.dark .upload-zone.drag-over{border-color:var(--p-primary-color);background:var(--p-primary-900)}.file-preview-item{border:1px solid var(--p-surface-200);background:var(--p-surface-0)}:host-context(.p-dark) .file-preview-item,.dark .file-preview-item{border-color:var(--p-surface-600);background:var(--p-surface-800)}\n"], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i1$
|
|
2318
|
+
`, isInline: true, styles: [".upload-zone{border-color:var(--p-surface-300);background:var(--p-surface-50)}.upload-zone:hover:not(.cursor-not-allowed){border-color:var(--p-primary-color);background:var(--p-surface-100)}.upload-zone.drag-over{border-color:var(--p-primary-color);background:var(--p-primary-50)}:host-context(.p-dark) .upload-zone,.dark .upload-zone{border-color:var(--p-surface-600);background:var(--p-surface-800)}:host-context(.p-dark) .upload-zone:hover:not(.cursor-not-allowed),.dark .upload-zone:hover:not(.cursor-not-allowed){border-color:var(--p-primary-color);background:var(--p-surface-700)}:host-context(.p-dark) .upload-zone.drag-over,.dark .upload-zone.drag-over{border-color:var(--p-primary-color);background:var(--p-primary-900)}.file-preview-item{border:1px solid var(--p-surface-200);background:var(--p-surface-0)}:host-context(.p-dark) .file-preview-item,.dark .file-preview-item{border-color:var(--p-surface-600);background:var(--p-surface-800)}\n"], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2$1.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2458
2319
|
}
|
|
2459
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
2320
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileUploaderComponent, decorators: [{
|
|
2460
2321
|
type: Component,
|
|
2461
|
-
args: [{ selector: 'lib-file-uploader',
|
|
2322
|
+
args: [{ selector: 'lib-file-uploader', imports: [AngularModule, PrimeModule], template: `
|
|
2462
2323
|
<div
|
|
2463
2324
|
class="w-full"
|
|
2464
2325
|
[class.opacity-60]="disabled()"
|
|
@@ -2649,16 +2510,14 @@ class FileSelectorDialogComponent {
|
|
|
2649
2510
|
}, 500);
|
|
2650
2511
|
}
|
|
2651
2512
|
onScroll(event) {
|
|
2652
|
-
const
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
this.fetchFiles(true);
|
|
2661
|
-
}
|
|
2513
|
+
const nextPagination = checkScrollPagination(event, {
|
|
2514
|
+
pagination: this.pagination(),
|
|
2515
|
+
total: this.total(),
|
|
2516
|
+
isLoading: this.isLoading(),
|
|
2517
|
+
});
|
|
2518
|
+
if (nextPagination) {
|
|
2519
|
+
this.pagination.set(nextPagination);
|
|
2520
|
+
this.fetchFiles(true);
|
|
2662
2521
|
}
|
|
2663
2522
|
}
|
|
2664
2523
|
toggleSelection(file) {
|
|
@@ -2760,8 +2619,8 @@ class FileSelectorDialogComponent {
|
|
|
2760
2619
|
this.isLoading.set(false);
|
|
2761
2620
|
}
|
|
2762
2621
|
}
|
|
2763
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
2764
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
2622
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileSelectorDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2623
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: FileSelectorDialogComponent, isStandalone: true, selector: "lib-file-selector-dialog", inputs: { loadFiles: { classPropertyName: "loadFiles", publicName: "loadFiles", isSignal: true, isRequired: true, transformFunction: null }, header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, acceptTypes: { classPropertyName: "acceptTypes", publicName: "acceptTypes", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxSelection: { classPropertyName: "maxSelection", publicName: "maxSelection", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", fileSelected: "fileSelected", filesSelected: "filesSelected", closed: "closed", onError: "onError" }, ngImport: i0, template: `
|
|
2765
2624
|
<p-dialog
|
|
2766
2625
|
[header]="header()"
|
|
2767
2626
|
[(visible)]="visible"
|
|
@@ -2868,11 +2727,11 @@ class FileSelectorDialogComponent {
|
|
|
2868
2727
|
</div>
|
|
2869
2728
|
</ng-template>
|
|
2870
2729
|
</p-dialog>
|
|
2871
|
-
`, isInline: true, styles: [".file-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.75rem;max-height:300px;overflow-y:auto;padding:.5rem}@media(min-width:480px){.file-grid{grid-template-columns:repeat(3,1fr);max-height:350px}}@media(min-width:640px){.file-grid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:1rem;max-height:400px}}.file-card{border:2px solid var(--p-surface-300);border-radius:var(--p-border-radius);cursor:pointer;transition:all .2s ease;overflow:hidden;background:var(--p-surface-0)}:host-context(.p-dark) .file-card,.dark .file-card{border-color:var(--p-surface-600);background:var(--p-surface-800)}.file-card:hover:not(.disabled){border-color:var(--p-primary-color);transform:translateY(-2px);box-shadow:var(--p-overlay-shadow)}.file-card.selected{border-color:var(--p-primary-color);background:var(--p-primary-50)}:host-context(.p-dark) .file-card.selected,.dark .file-card.selected{background:var(--p-primary-900)}.file-card.disabled{opacity:.5;cursor:not-allowed}.file-preview{position:relative;height:80px;display:flex;align-items:center;justify-content:center;background:var(--p-surface-100)}@media(min-width:640px){.file-preview{height:100px}}:host-context(.p-dark) .file-preview,.dark .file-preview{background:var(--p-surface-700)}.selected-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(var(--p-primary-500-rgb, 59, 130, 246),.3)}.selected-overlay i{color:var(--p-primary-color);background:var(--p-surface-0);border-radius:50%;padding:.5rem}:host-context(.p-dark) .selected-overlay i,.dark .selected-overlay i{background:var(--p-surface-900)}\n"], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$
|
|
2730
|
+
`, isInline: true, styles: [".file-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.75rem;max-height:300px;overflow-y:auto;padding:.5rem}@media(min-width:480px){.file-grid{grid-template-columns:repeat(3,1fr);max-height:350px}}@media(min-width:640px){.file-grid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:1rem;max-height:400px}}.file-card{border:2px solid var(--p-surface-300);border-radius:var(--p-border-radius);cursor:pointer;transition:all .2s ease;overflow:hidden;background:var(--p-surface-0)}:host-context(.p-dark) .file-card,.dark .file-card{border-color:var(--p-surface-600);background:var(--p-surface-800)}.file-card:hover:not(.disabled){border-color:var(--p-primary-color);transform:translateY(-2px);box-shadow:var(--p-overlay-shadow)}.file-card.selected{border-color:var(--p-primary-color);background:var(--p-primary-50)}:host-context(.p-dark) .file-card.selected,.dark .file-card.selected{background:var(--p-primary-900)}.file-card.disabled{opacity:.5;cursor:not-allowed}.file-preview{position:relative;height:80px;display:flex;align-items:center;justify-content:center;background:var(--p-surface-100)}@media(min-width:640px){.file-preview{height:100px}}:host-context(.p-dark) .file-preview,.dark .file-preview{background:var(--p-surface-700)}.selected-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(var(--p-primary-500-rgb, 59, 130, 246),.3)}.selected-overlay i{color:var(--p-primary-color);background:var(--p-surface-0);border-radius:50%;padding:.5rem}:host-context(.p-dark) .selected-overlay i,.dark .selected-overlay i{background:var(--p-surface-900)}\n"], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: IsEmptyImageDirective, selector: "img", inputs: ["src"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i1$2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i4.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2872
2731
|
}
|
|
2873
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
2732
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileSelectorDialogComponent, decorators: [{
|
|
2874
2733
|
type: Component,
|
|
2875
|
-
args: [{ selector: 'lib-file-selector-dialog',
|
|
2734
|
+
args: [{ selector: 'lib-file-selector-dialog', imports: [AngularModule, PrimeModule], template: `
|
|
2876
2735
|
<p-dialog
|
|
2877
2736
|
[header]="header()"
|
|
2878
2737
|
[(visible)]="visible"
|
|
@@ -2982,129 +2841,75 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
2982
2841
|
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".file-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.75rem;max-height:300px;overflow-y:auto;padding:.5rem}@media(min-width:480px){.file-grid{grid-template-columns:repeat(3,1fr);max-height:350px}}@media(min-width:640px){.file-grid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:1rem;max-height:400px}}.file-card{border:2px solid var(--p-surface-300);border-radius:var(--p-border-radius);cursor:pointer;transition:all .2s ease;overflow:hidden;background:var(--p-surface-0)}:host-context(.p-dark) .file-card,.dark .file-card{border-color:var(--p-surface-600);background:var(--p-surface-800)}.file-card:hover:not(.disabled){border-color:var(--p-primary-color);transform:translateY(-2px);box-shadow:var(--p-overlay-shadow)}.file-card.selected{border-color:var(--p-primary-color);background:var(--p-primary-50)}:host-context(.p-dark) .file-card.selected,.dark .file-card.selected{background:var(--p-primary-900)}.file-card.disabled{opacity:.5;cursor:not-allowed}.file-preview{position:relative;height:80px;display:flex;align-items:center;justify-content:center;background:var(--p-surface-100)}@media(min-width:640px){.file-preview{height:100px}}:host-context(.p-dark) .file-preview,.dark .file-preview{background:var(--p-surface-700)}.selected-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(var(--p-primary-500-rgb, 59, 130, 246),.3)}.selected-overlay i{color:var(--p-primary-color);background:var(--p-surface-0);border-radius:50%;padding:.5rem}:host-context(.p-dark) .selected-overlay i,.dark .selected-overlay i{background:var(--p-surface-900)}\n"] }]
|
|
2983
2842
|
}], ctorParameters: () => [], propDecorators: { loadFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadFiles", required: true }] }], header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], acceptTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "acceptTypes", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelection", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }, { type: i0.Output, args: ["visibleChange"] }], fileSelected: [{ type: i0.Output, args: ["fileSelected"] }], filesSelected: [{ type: i0.Output, args: ["filesSelected"] }], closed: [{ type: i0.Output, args: ["closed"] }], onError: [{ type: i0.Output, args: ["onError"] }] } });
|
|
2984
2843
|
|
|
2985
|
-
|
|
2986
|
-
const devLog = (message) => {
|
|
2987
|
-
if (isDevMode())
|
|
2988
|
-
console.log(message);
|
|
2989
|
-
};
|
|
2990
|
-
/**
|
|
2991
|
-
* Permission Guard
|
|
2992
|
-
*
|
|
2993
|
-
* Route-level guard for permission-based access control.
|
|
2994
|
-
* Validates permissions before allowing navigation.
|
|
2995
|
-
*
|
|
2996
|
-
* Features:
|
|
2997
|
-
* - Single permission check
|
|
2998
|
-
* - Complex ILogicNode logic trees
|
|
2999
|
-
* - Configurable redirect URL
|
|
3000
|
-
* - Debug logging for denied access
|
|
3001
|
-
*
|
|
3002
|
-
* @example
|
|
3003
|
-
* ```typescript
|
|
3004
|
-
* // Simple permission check
|
|
3005
|
-
* { path: 'users', canActivate: [permissionGuard('user.view')] }
|
|
3006
|
-
*
|
|
3007
|
-
* // Complex logic
|
|
3008
|
-
* { path: 'admin', canActivate: [permissionGuard({
|
|
3009
|
-
* id: 'root',
|
|
3010
|
-
* type: 'group',
|
|
3011
|
-
* operator: 'AND',
|
|
3012
|
-
* children: [
|
|
3013
|
-
* { id: '1', type: 'action', actionId: 'admin.view' },
|
|
3014
|
-
* { id: '2', type: 'action', actionId: 'admin.manage' }
|
|
3015
|
-
* ]
|
|
3016
|
-
* })] }
|
|
3017
|
-
*
|
|
3018
|
-
* // With custom redirect
|
|
3019
|
-
* { path: 'users', canActivate: [permissionGuard('user.view', '/access-denied')] }
|
|
3020
|
-
* ```
|
|
3021
|
-
*/
|
|
3022
|
-
function permissionGuard(permission, redirectTo = '/') {
|
|
2844
|
+
function createGuard(guardName, redirectTo, evaluate, getDenialMessage) {
|
|
3023
2845
|
return () => {
|
|
3024
2846
|
const permissionValidator = inject(PermissionValidatorService);
|
|
3025
2847
|
const router = inject(Router);
|
|
3026
|
-
// Check if permissions are loaded
|
|
3027
2848
|
if (!permissionValidator.isPermissionsLoaded()) {
|
|
3028
|
-
|
|
2849
|
+
if (isDevMode()) {
|
|
2850
|
+
console.log(`[${guardName}] Permissions not loaded, denying access`);
|
|
2851
|
+
}
|
|
3029
2852
|
return router.createUrlTree([redirectTo]);
|
|
3030
2853
|
}
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
devLog(`[permissionGuard] Access denied - missing permission: ${permissionCode}`);
|
|
2854
|
+
if (!evaluate(permissionValidator.permissions())) {
|
|
2855
|
+
if (isDevMode()) {
|
|
2856
|
+
console.log(`[${guardName}] ${getDenialMessage()}`);
|
|
2857
|
+
}
|
|
3036
2858
|
return router.createUrlTree([redirectTo]);
|
|
3037
2859
|
}
|
|
3038
2860
|
return true;
|
|
3039
2861
|
};
|
|
3040
2862
|
}
|
|
3041
2863
|
/**
|
|
3042
|
-
*
|
|
2864
|
+
* Permission Guard - Single permission or ILogicNode check.
|
|
3043
2865
|
*
|
|
3044
|
-
*
|
|
2866
|
+
* @example
|
|
2867
|
+
* ```typescript
|
|
2868
|
+
* { path: 'users', canActivate: [permissionGuard('user.view')] }
|
|
2869
|
+
* { path: 'admin', canActivate: [permissionGuard(logicNode, '/access-denied')] }
|
|
2870
|
+
* ```
|
|
2871
|
+
*/
|
|
2872
|
+
function permissionGuard(permission, redirectTo = '/') {
|
|
2873
|
+
const code = typeof permission === 'string' ? permission : 'complex-logic';
|
|
2874
|
+
return createGuard('permissionGuard', redirectTo, (perms) => evaluatePermission(permission, perms), () => `Access denied - missing: ${code}`);
|
|
2875
|
+
}
|
|
2876
|
+
/**
|
|
2877
|
+
* Any Permission Guard (OR logic) - Access if user has ANY permission.
|
|
3045
2878
|
*
|
|
3046
2879
|
* @example
|
|
3047
2880
|
* ```typescript
|
|
3048
|
-
* // Allow if user has view OR create permission
|
|
3049
2881
|
* { path: 'users', canActivate: [anyPermissionGuard(['user.view', 'user.create'])] }
|
|
3050
2882
|
* ```
|
|
3051
2883
|
*/
|
|
3052
2884
|
function anyPermissionGuard(permissions, redirectTo = '/') {
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
if (!permissionValidator.isPermissionsLoaded()) {
|
|
3063
|
-
devLog('[anyPermissionGuard] Permissions not loaded, denying access to route');
|
|
3064
|
-
return router.createUrlTree([redirectTo]);
|
|
3065
|
-
}
|
|
3066
|
-
const userPermissions = permissionValidator.permissions();
|
|
3067
|
-
const hasPermission = hasAnyPermission(permissions, userPermissions);
|
|
3068
|
-
if (!hasPermission) {
|
|
3069
|
-
devLog(`[anyPermissionGuard] Access denied - missing any of: ${permissions.join(', ')}`);
|
|
3070
|
-
return router.createUrlTree([redirectTo]);
|
|
3071
|
-
}
|
|
3072
|
-
return true;
|
|
3073
|
-
};
|
|
2885
|
+
if (!permissions?.length) {
|
|
2886
|
+
return () => {
|
|
2887
|
+
if (isDevMode()) {
|
|
2888
|
+
console.log('[anyPermissionGuard] Empty permissions array, denying');
|
|
2889
|
+
}
|
|
2890
|
+
return inject(Router).createUrlTree([redirectTo]);
|
|
2891
|
+
};
|
|
2892
|
+
}
|
|
2893
|
+
return createGuard('anyPermissionGuard', redirectTo, (perms) => hasAnyPermission(permissions, perms), () => `Access denied - missing any of: ${permissions.join(', ')}`);
|
|
3074
2894
|
}
|
|
3075
2895
|
/**
|
|
3076
|
-
* All Permissions Guard (AND logic)
|
|
3077
|
-
*
|
|
3078
|
-
* Allows access only if user has ALL of the specified permissions.
|
|
2896
|
+
* All Permissions Guard (AND logic) - Access only if user has ALL permissions.
|
|
3079
2897
|
*
|
|
3080
2898
|
* @example
|
|
3081
2899
|
* ```typescript
|
|
3082
|
-
* // Allow only if user has BOTH view AND create permissions
|
|
3083
2900
|
* { path: 'admin', canActivate: [allPermissionsGuard(['admin.view', 'admin.manage'])] }
|
|
3084
2901
|
* ```
|
|
3085
2902
|
*/
|
|
3086
2903
|
function allPermissionsGuard(permissions, redirectTo = '/') {
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
if (!permissionValidator.isPermissionsLoaded()) {
|
|
3097
|
-
devLog('[allPermissionsGuard] Permissions not loaded, denying access to route');
|
|
3098
|
-
return router.createUrlTree([redirectTo]);
|
|
3099
|
-
}
|
|
3100
|
-
const userPermissions = permissionValidator.permissions();
|
|
3101
|
-
const hasPermission = hasAllPermissions(permissions, userPermissions);
|
|
3102
|
-
if (!hasPermission) {
|
|
3103
|
-
devLog(`[allPermissionsGuard] Access denied - missing all of: ${permissions.join(', ')}`);
|
|
3104
|
-
return router.createUrlTree([redirectTo]);
|
|
3105
|
-
}
|
|
3106
|
-
return true;
|
|
3107
|
-
};
|
|
2904
|
+
if (!permissions?.length) {
|
|
2905
|
+
return () => {
|
|
2906
|
+
if (isDevMode()) {
|
|
2907
|
+
console.log('[allPermissionsGuard] Empty permissions array, denying');
|
|
2908
|
+
}
|
|
2909
|
+
return inject(Router).createUrlTree([redirectTo]);
|
|
2910
|
+
};
|
|
2911
|
+
}
|
|
2912
|
+
return createGuard('allPermissionsGuard', redirectTo, (perms) => hasAllPermissions(permissions, perms), () => `Access denied - missing all of: ${permissions.join(', ')}`);
|
|
3108
2913
|
}
|
|
3109
2914
|
|
|
3110
2915
|
/**
|
|
@@ -3287,10 +3092,10 @@ class BaseFormPage {
|
|
|
3287
3092
|
detail,
|
|
3288
3093
|
});
|
|
3289
3094
|
}
|
|
3290
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
3291
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.
|
|
3095
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseFormPage, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3096
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.5", type: BaseFormPage, isStandalone: true, ngImport: i0 });
|
|
3292
3097
|
}
|
|
3293
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
3098
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseFormPage, decorators: [{
|
|
3294
3099
|
type: Directive
|
|
3295
3100
|
}], ctorParameters: () => [] });
|
|
3296
3101
|
|
|
@@ -3451,10 +3256,10 @@ class BaseListPage {
|
|
|
3451
3256
|
navigateTo(path) {
|
|
3452
3257
|
this.router.navigate(path);
|
|
3453
3258
|
}
|
|
3454
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
3455
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.
|
|
3259
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseListPage, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3260
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.5", type: BaseListPage, isStandalone: true, ngImport: i0 });
|
|
3456
3261
|
}
|
|
3457
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
3262
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseListPage, decorators: [{
|
|
3458
3263
|
type: Directive
|
|
3459
3264
|
}] });
|
|
3460
3265
|
|
|
@@ -3464,5 +3269,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
3464
3269
|
* Generated bundle index. Do not edit.
|
|
3465
3270
|
*/
|
|
3466
3271
|
|
|
3467
|
-
export { ACTION_PERMISSIONS, AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, BRANCH_PERMISSIONS, BaseFormControl, BaseFormPage, BaseListPage, 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, evaluateLogicNode, evaluatePermission, formatFileSize, getAcceptString, getFileIconClass, hasAllPermissions, hasAnyPermission, hasPermission, isFileTypeAllowed, permissionGuard, provideValueAccessor };
|
|
3272
|
+
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 };
|
|
3468
3273
|
//# sourceMappingURL=flusys-ng-shared.mjs.map
|