@fuentis/phoenix-ui 0.0.9-alpha.588 → 0.0.9-alpha.590
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/fesm2022/fuentis-phoenix-ui.mjs +122 -34
- package/fesm2022/fuentis-phoenix-ui.mjs.map +1 -1
- package/index.d.ts +10 -10
- package/package.json +1 -1
|
@@ -2900,7 +2900,11 @@ const DEFAULT_MORE_ACTIONS = {
|
|
|
2900
2900
|
label: '',
|
|
2901
2901
|
items: [
|
|
2902
2902
|
{ key: 'EXPORT_PDF', label: 'ACTION.EXPORT_PDF', icon: 'pi pi-file-pdf' },
|
|
2903
|
-
{
|
|
2903
|
+
{
|
|
2904
|
+
key: 'EXPORT_EXCEL',
|
|
2905
|
+
label: 'ACTION.EXPORT_EXCEL',
|
|
2906
|
+
icon: 'pi pi-file-excel',
|
|
2907
|
+
},
|
|
2904
2908
|
],
|
|
2905
2909
|
};
|
|
2906
2910
|
class TableComponent {
|
|
@@ -3154,7 +3158,9 @@ class TableComponent {
|
|
|
3154
3158
|
this.columnTypeMap = {};
|
|
3155
3159
|
for (const col of this.columns)
|
|
3156
3160
|
this.columnTypeMap[col.field] = col.columnType;
|
|
3157
|
-
const nextSelected = this.selectedColumnsInput?.length
|
|
3161
|
+
const nextSelected = this.selectedColumnsInput?.length
|
|
3162
|
+
? this.selectedColumnsInput
|
|
3163
|
+
: this.columns;
|
|
3158
3164
|
// microtask to avoid change detection timing issues
|
|
3159
3165
|
Promise.resolve().then(() => {
|
|
3160
3166
|
this.selectedColumns = [...nextSelected];
|
|
@@ -3255,29 +3261,31 @@ class TableComponent {
|
|
|
3255
3261
|
const s = cfg?.initialSort;
|
|
3256
3262
|
// NEW style
|
|
3257
3263
|
if (Array.isArray(s))
|
|
3258
|
-
return s.filter(x => !!x?.field);
|
|
3264
|
+
return s.filter((x) => !!x?.field);
|
|
3259
3265
|
if (s && typeof s === 'object' && s.field)
|
|
3260
3266
|
return [s];
|
|
3261
3267
|
// LEGACY fallback
|
|
3262
3268
|
if (cfg?.initialSortField) {
|
|
3263
|
-
return [
|
|
3269
|
+
return [
|
|
3270
|
+
{
|
|
3264
3271
|
field: cfg.initialSortField,
|
|
3265
3272
|
order: (cfg.initialSortOrder ?? 1),
|
|
3266
|
-
}
|
|
3273
|
+
},
|
|
3274
|
+
];
|
|
3267
3275
|
}
|
|
3268
3276
|
return [];
|
|
3269
3277
|
}
|
|
3270
3278
|
/**
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3279
|
+
* Applies initial sort once:
|
|
3280
|
+
* - Uses tableConfiguration.initialSortField if provided
|
|
3281
|
+
* - Otherwise uses the first available column field
|
|
3282
|
+
* - Always ASC (order = 1)
|
|
3283
|
+
*
|
|
3284
|
+
* Runs only when:
|
|
3285
|
+
* - we have data
|
|
3286
|
+
* - we have columns/selectedColumns
|
|
3287
|
+
* - it hasn't been applied yet for current dataset
|
|
3288
|
+
*/
|
|
3281
3289
|
applyInitialSortIfNeeded() {
|
|
3282
3290
|
if (this.initialSortApplied)
|
|
3283
3291
|
return;
|
|
@@ -3288,18 +3296,20 @@ class TableComponent {
|
|
|
3288
3296
|
this.initialSortApplied = true;
|
|
3289
3297
|
return;
|
|
3290
3298
|
}
|
|
3291
|
-
const cols = (this.selectedColumns?.length ? this.selectedColumns : this.columns) ??
|
|
3299
|
+
const cols = (this.selectedColumns?.length ? this.selectedColumns : this.columns) ??
|
|
3300
|
+
[];
|
|
3292
3301
|
if (!cols.length)
|
|
3293
3302
|
return;
|
|
3294
3303
|
// 1) normalize config
|
|
3295
3304
|
const cfgMeta = this.normalizeInitialSort(this.tableConfiguration);
|
|
3296
3305
|
// 2) if nothing configured -> fallback first column ASC
|
|
3297
3306
|
const fallbackField = cols[0]?.field;
|
|
3298
|
-
const wantedMeta = (cfgMeta.length ? cfgMeta : [{ field: fallbackField, order: 1 }])
|
|
3299
|
-
.filter(m => !!m?.field);
|
|
3307
|
+
const wantedMeta = (cfgMeta.length ? cfgMeta : [{ field: fallbackField, order: 1 }]).filter((m) => !!m?.field);
|
|
3300
3308
|
// 3) keep only fields that exist in columns
|
|
3301
|
-
const validMeta = wantedMeta.filter(m => cols.some((c) => c?.field === m.field));
|
|
3302
|
-
const finalMeta = validMeta.length
|
|
3309
|
+
const validMeta = wantedMeta.filter((m) => cols.some((c) => c?.field === m.field));
|
|
3310
|
+
const finalMeta = validMeta.length
|
|
3311
|
+
? validMeta
|
|
3312
|
+
: [{ field: fallbackField, order: 1 }];
|
|
3303
3313
|
if (!finalMeta[0]?.field) {
|
|
3304
3314
|
this.tableData = this.allData;
|
|
3305
3315
|
this.totalRecords = this.tableData.length;
|
|
@@ -3327,7 +3337,9 @@ class TableComponent {
|
|
|
3327
3337
|
onSearch(query) {
|
|
3328
3338
|
const trimmed = (query ?? '').trim().toLowerCase();
|
|
3329
3339
|
this.searchQuery = trimmed;
|
|
3330
|
-
const baseData = Object.keys(this.currentFilters).length > 0
|
|
3340
|
+
const baseData = Object.keys(this.currentFilters).length > 0
|
|
3341
|
+
? this.getFilteredData()
|
|
3342
|
+
: this.originalData;
|
|
3331
3343
|
const searchableFields = (this.columns ?? [])
|
|
3332
3344
|
.map((c) => (c?.field ?? '').trim())
|
|
3333
3345
|
.filter((f) => !!f);
|
|
@@ -3373,7 +3385,9 @@ class TableComponent {
|
|
|
3373
3385
|
return undefined;
|
|
3374
3386
|
if (!path.includes('.'))
|
|
3375
3387
|
return obj[path];
|
|
3376
|
-
return path
|
|
3388
|
+
return path
|
|
3389
|
+
.split('.')
|
|
3390
|
+
.reduce((acc, key) => (acc == null ? undefined : acc[key]), obj);
|
|
3377
3391
|
}
|
|
3378
3392
|
matchesQuery(value, query) {
|
|
3379
3393
|
if (value === null || value === undefined)
|
|
@@ -3400,18 +3414,31 @@ class TableComponent {
|
|
|
3400
3414
|
return this.originalData.filter((item) => {
|
|
3401
3415
|
return Object.keys(this.currentFilters).every((key) => {
|
|
3402
3416
|
const filterValue = this.currentFilters[key];
|
|
3403
|
-
if (!filterValue ||
|
|
3417
|
+
if (!filterValue ||
|
|
3418
|
+
(Array.isArray(filterValue) && filterValue.length === 0))
|
|
3404
3419
|
return true;
|
|
3405
3420
|
const itemValue = this.getNestedValue(item, key);
|
|
3421
|
+
// Ako je itemValue niz (kao u scopes)
|
|
3422
|
+
if (Array.isArray(itemValue)) {
|
|
3423
|
+
return filterValue.some((option) => {
|
|
3424
|
+
const optionKey = option?.key || option;
|
|
3425
|
+
return itemValue.some((val) => val?.name?.toString().toLowerCase() ===
|
|
3426
|
+
optionKey?.toString().toLowerCase());
|
|
3427
|
+
});
|
|
3428
|
+
}
|
|
3429
|
+
// Ako je filterValue niz
|
|
3406
3430
|
if (Array.isArray(filterValue)) {
|
|
3407
3431
|
return filterValue.some((option) => {
|
|
3408
3432
|
const optionKey = option?.key || option;
|
|
3409
|
-
return itemValue?.toString().toLowerCase() ===
|
|
3433
|
+
return (itemValue?.toString().toLowerCase() ===
|
|
3434
|
+
optionKey?.toString().toLowerCase());
|
|
3410
3435
|
});
|
|
3411
3436
|
}
|
|
3437
|
+
// Single filter
|
|
3412
3438
|
const singleFilterValue = filterValue?.key || filterValue;
|
|
3413
3439
|
return singleFilterValue
|
|
3414
|
-
? itemValue?.toString().toLowerCase() ===
|
|
3440
|
+
? itemValue?.toString().toLowerCase() ===
|
|
3441
|
+
singleFilterValue.toString().toLowerCase()
|
|
3415
3442
|
: true;
|
|
3416
3443
|
});
|
|
3417
3444
|
});
|
|
@@ -3478,7 +3505,10 @@ class TableComponent {
|
|
|
3478
3505
|
return '';
|
|
3479
3506
|
}
|
|
3480
3507
|
compareStringsNatural(a, b) {
|
|
3481
|
-
return a.localeCompare(b, undefined, {
|
|
3508
|
+
return a.localeCompare(b, undefined, {
|
|
3509
|
+
numeric: true,
|
|
3510
|
+
sensitivity: 'base',
|
|
3511
|
+
});
|
|
3482
3512
|
}
|
|
3483
3513
|
// ============================================================
|
|
3484
3514
|
// SELECTION / UI ACTIONS
|
|
@@ -3522,7 +3552,9 @@ class TableComponent {
|
|
|
3522
3552
|
* Used by checkbox template to disable selection on specific rows.
|
|
3523
3553
|
*/
|
|
3524
3554
|
isRowSelectable(event) {
|
|
3525
|
-
return typeof event.data?.canSelect === 'boolean'
|
|
3555
|
+
return typeof event.data?.canSelect === 'boolean'
|
|
3556
|
+
? event.data.canSelect
|
|
3557
|
+
: true;
|
|
3526
3558
|
}
|
|
3527
3559
|
/**
|
|
3528
3560
|
* Some tables allow click on first N columns to open details.
|
|
@@ -3545,7 +3577,9 @@ class TableComponent {
|
|
|
3545
3577
|
getNested(obj, path) {
|
|
3546
3578
|
if (!obj || !path)
|
|
3547
3579
|
return null;
|
|
3548
|
-
return path
|
|
3580
|
+
return path
|
|
3581
|
+
.split('.')
|
|
3582
|
+
.reduce((o, k) => (o != null ? o[k] : null), obj);
|
|
3549
3583
|
}
|
|
3550
3584
|
/**
|
|
3551
3585
|
* Applies column selection coming from table-caption (array of field names).
|
|
@@ -3734,6 +3768,55 @@ function noDangerousCharsValidator() {
|
|
|
3734
3768
|
};
|
|
3735
3769
|
}
|
|
3736
3770
|
|
|
3771
|
+
var CompareOperatorType;
|
|
3772
|
+
(function (CompareOperatorType) {
|
|
3773
|
+
CompareOperatorType["LESS_OR_EQUAL"] = "LESS_OR_EQUAL";
|
|
3774
|
+
CompareOperatorType["LESS"] = "LESS";
|
|
3775
|
+
CompareOperatorType["EQUAL"] = "EQUAL";
|
|
3776
|
+
CompareOperatorType["MORE_OR_EQUAL"] = "MORE_OR_EQUAL";
|
|
3777
|
+
CompareOperatorType["MORE"] = "MORE";
|
|
3778
|
+
})(CompareOperatorType || (CompareOperatorType = {}));
|
|
3779
|
+
function dateCompareValidator(fieldToCompare, comparison, errMessage) {
|
|
3780
|
+
return (control) => {
|
|
3781
|
+
if (!control.parent)
|
|
3782
|
+
return null; // ako form group ne postoji
|
|
3783
|
+
const compareControl = control.parent.get(fieldToCompare);
|
|
3784
|
+
if (!compareControl)
|
|
3785
|
+
return null; // polje za poređenje ne postoji
|
|
3786
|
+
const controlValue = control.value ? new Date(control.value) : null;
|
|
3787
|
+
const compareValue = compareControl.value
|
|
3788
|
+
? new Date(compareControl.value)
|
|
3789
|
+
: null;
|
|
3790
|
+
if (!controlValue || !compareValue)
|
|
3791
|
+
return null; // nema vrednosti, ne validira
|
|
3792
|
+
let valid = true;
|
|
3793
|
+
switch (comparison) {
|
|
3794
|
+
case CompareOperatorType.LESS:
|
|
3795
|
+
valid = controlValue < compareValue;
|
|
3796
|
+
break;
|
|
3797
|
+
case CompareOperatorType.LESS_OR_EQUAL:
|
|
3798
|
+
valid = controlValue <= compareValue;
|
|
3799
|
+
break;
|
|
3800
|
+
case CompareOperatorType.EQUAL:
|
|
3801
|
+
valid = controlValue.getTime() === compareValue.getTime();
|
|
3802
|
+
break;
|
|
3803
|
+
case CompareOperatorType.MORE_OR_EQUAL:
|
|
3804
|
+
valid = controlValue >= compareValue;
|
|
3805
|
+
break;
|
|
3806
|
+
case CompareOperatorType.MORE:
|
|
3807
|
+
valid = controlValue > compareValue;
|
|
3808
|
+
break;
|
|
3809
|
+
}
|
|
3810
|
+
if (!valid) {
|
|
3811
|
+
return {
|
|
3812
|
+
dateCompare: errMessage ||
|
|
3813
|
+
`Datum ne zadovoljava uslov ${comparison} u odnosu na ${fieldToCompare}`,
|
|
3814
|
+
};
|
|
3815
|
+
}
|
|
3816
|
+
return null; // validno
|
|
3817
|
+
};
|
|
3818
|
+
}
|
|
3819
|
+
|
|
3737
3820
|
class MetaFormService {
|
|
3738
3821
|
router = inject(Router);
|
|
3739
3822
|
formEvent = new Subject();
|
|
@@ -3808,8 +3891,7 @@ class MetaFormAbstract {
|
|
|
3808
3891
|
onFormCancel = new EventEmitter();
|
|
3809
3892
|
formActive$;
|
|
3810
3893
|
formSub$;
|
|
3811
|
-
constructor(fb, metaService, translateService, http
|
|
3812
|
-
) {
|
|
3894
|
+
constructor(fb, metaService, translateService, http) {
|
|
3813
3895
|
this.fb = fb;
|
|
3814
3896
|
this.metaService = metaService;
|
|
3815
3897
|
this.translateService = translateService;
|
|
@@ -3823,10 +3905,7 @@ class MetaFormAbstract {
|
|
|
3823
3905
|
}
|
|
3824
3906
|
createForm(controls) {
|
|
3825
3907
|
controls?.forEach((control) => {
|
|
3826
|
-
this.metaForm.addControl(control.configuration?.key, this.fb.control(getFieldType(control)
|
|
3827
|
-
///updateOn: blur only for controls with async validators. If added for all each tab/step toggle removes form value. Check why
|
|
3828
|
-
// control.asyncValidators && { updateOn: 'blur' },
|
|
3829
|
-
));
|
|
3908
|
+
this.metaForm.addControl(control.configuration?.key, this.fb.control(getFieldType(control)));
|
|
3830
3909
|
//add validators
|
|
3831
3910
|
this.addControlValidators(control);
|
|
3832
3911
|
//disable non editable fields
|
|
@@ -3864,6 +3943,11 @@ class MetaFormAbstract {
|
|
|
3864
3943
|
validators.push(timePeriod(this.translateService.currentLang, control.validators.tpMin));
|
|
3865
3944
|
control.validators.dueDate && validators.push(startDueDateValidator);
|
|
3866
3945
|
}
|
|
3946
|
+
if (control.validators?.compare) {
|
|
3947
|
+
const compareConfig = control.validators.compare;
|
|
3948
|
+
validators.push(dateCompareValidator(compareConfig.fieldToCompare, // napomena: ispravi typo 'feildToCompare'
|
|
3949
|
+
compareConfig.comparisonOperator, compareConfig.errMessage));
|
|
3950
|
+
}
|
|
3867
3951
|
if (control?.mandatory) {
|
|
3868
3952
|
validators.push(Validators.required);
|
|
3869
3953
|
}
|
|
@@ -4386,6 +4470,7 @@ var ErrorType;
|
|
|
4386
4470
|
ErrorType["MAX"] = "max";
|
|
4387
4471
|
ErrorType["MIN"] = "min";
|
|
4388
4472
|
ErrorType["DANGEROUS_CHARS"] = "dangerousChars";
|
|
4473
|
+
ErrorType["DATE_COMPARE"] = "dateCompare";
|
|
4389
4474
|
})(ErrorType || (ErrorType = {}));
|
|
4390
4475
|
|
|
4391
4476
|
class InlineFieldError {
|
|
@@ -4437,6 +4522,7 @@ class InlineFieldError {
|
|
|
4437
4522
|
// return 'ENTRY OK';
|
|
4438
4523
|
// }
|
|
4439
4524
|
if (control?.errors) {
|
|
4525
|
+
console.log('error type', Object.keys(control.errors)[0]);
|
|
4440
4526
|
switch (Object.keys(control.errors)[0]) {
|
|
4441
4527
|
case ErrorType.REQUIRED:
|
|
4442
4528
|
return this.translateService.instant('VALIDATION_MESSAGE.THIS_FIELD_IS_REQUIRED');
|
|
@@ -4469,6 +4555,8 @@ class InlineFieldError {
|
|
|
4469
4555
|
return this.translateService.instant('VALIDATION_MESSAGE.VALUE_SHOULD_MATCH_TIMEPATTERN_LIMIT_MIN');
|
|
4470
4556
|
case ErrorType.BOTH_DATES:
|
|
4471
4557
|
return this.translateService.instant('VALIDATION_MESSAGE.BOTH_START_END_DATE_REQUIRED');
|
|
4558
|
+
case ErrorType.DATE_COMPARE:
|
|
4559
|
+
return this.translateService.instant(control.errors['dateCompare']);
|
|
4472
4560
|
// add more cases for other validators as needed
|
|
4473
4561
|
case ErrorType.PATTERN:
|
|
4474
4562
|
const re = '^(https?://)?([\\da-z.-]+)\\.([a-z.]{2,6})[/\\w .-]*/?$';
|