@solcre-org/core-ui 2.12.11 → 2.12.12

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.
@@ -5229,6 +5229,317 @@ const isSameDate = (date1, date2) => {
5229
5229
  date1.getDate() === date2.getDate());
5230
5230
  };
5231
5231
 
5232
+ class DynamicFieldsHelper {
5233
+ formBuilder = new FormBuilder();
5234
+ config;
5235
+ mode;
5236
+ _editedData = signal(null);
5237
+ _fieldErrors = signal({});
5238
+ _originalData = signal(null);
5239
+ _form = signal(this.formBuilder.group({}));
5240
+ state;
5241
+ constructor(config, mode = ModalMode.CREATE) {
5242
+ this.config = config;
5243
+ this.mode = mode;
5244
+ this.state = {
5245
+ editedData: this._editedData.asReadonly(),
5246
+ fieldErrors: this._fieldErrors.asReadonly(),
5247
+ hasUnsavedChanges: computed(() => this.detectChanges()),
5248
+ isValid: computed(() => this.isFormValid())
5249
+ };
5250
+ this.initializeData();
5251
+ }
5252
+ initializeData() {
5253
+ const initialData = this.config.initialData;
5254
+ let newInstance;
5255
+ if (initialData && Object.keys(initialData).length > 0) {
5256
+ if (this.config.modelFactory) {
5257
+ newInstance = this.config.modelFactory(initialData);
5258
+ }
5259
+ else {
5260
+ newInstance = Object.create(Object.getPrototypeOf(initialData));
5261
+ Object.assign(newInstance, initialData);
5262
+ }
5263
+ }
5264
+ else if (this.mode === ModalMode.CREATE) {
5265
+ if (this.config.modelFactory) {
5266
+ newInstance = this.config.modelFactory({});
5267
+ }
5268
+ else {
5269
+ newInstance = {
5270
+ getId: () => 0,
5271
+ };
5272
+ }
5273
+ }
5274
+ else {
5275
+ this._editedData.set(null);
5276
+ return;
5277
+ }
5278
+ const formGroup = {};
5279
+ this.config.fields.forEach(field => {
5280
+ const fieldKey = field.key;
5281
+ const payloadKey = (field.keyToPayload ?? field.key);
5282
+ const modeConfig = field.modes?.[this.mode];
5283
+ const defaultValue = modeConfig?.defaultValue ?? field.defaultValue;
5284
+ if (this.mode === ModalMode.CREATE) {
5285
+ if (defaultValue !== undefined && newInstance[fieldKey] === undefined) {
5286
+ if (typeof defaultValue === 'function') {
5287
+ const computedValue = defaultValue(newInstance);
5288
+ newInstance[payloadKey] = computedValue;
5289
+ }
5290
+ else {
5291
+ newInstance[payloadKey] = defaultValue;
5292
+ }
5293
+ }
5294
+ }
5295
+ else if (this.mode === ModalMode.EDIT) {
5296
+ if (typeof defaultValue === 'function') {
5297
+ const computedValue = defaultValue(newInstance);
5298
+ newInstance[payloadKey] = computedValue;
5299
+ }
5300
+ }
5301
+ const validators = modeConfig?.validators ?? field.validators ?? [];
5302
+ formGroup[fieldKey] = [newInstance[fieldKey], validators];
5303
+ });
5304
+ this._form.set(this.formBuilder.group(formGroup));
5305
+ this.config.fields.forEach(field => {
5306
+ const fieldKey = field.key;
5307
+ const payloadKey = (field.keyToPayload ?? field.key);
5308
+ if ('dynamicValue' in field && typeof field.dynamicValue === 'function') {
5309
+ const dynamicVal = field.dynamicValue(newInstance);
5310
+ if (dynamicVal !== undefined) {
5311
+ newInstance[payloadKey] = dynamicVal;
5312
+ const control = this._form().get(fieldKey);
5313
+ if (control) {
5314
+ control.setValue(dynamicVal, { emitEvent: false });
5315
+ }
5316
+ }
5317
+ }
5318
+ });
5319
+ this._editedData.set(newInstance);
5320
+ if (this.mode !== ModalMode.VIEW) {
5321
+ const originalCopy = this.config.modelFactory
5322
+ ? this.config.modelFactory(newInstance)
5323
+ : Object.create(Object.getPrototypeOf(newInstance));
5324
+ Object.assign(originalCopy, newInstance);
5325
+ this._originalData.set(originalCopy);
5326
+ }
5327
+ setTimeout(() => {
5328
+ Object.values(this._form().controls).forEach(control => {
5329
+ control.markAsUntouched();
5330
+ });
5331
+ this._fieldErrors.set({});
5332
+ }, 0);
5333
+ if (this.config.onDataChange) {
5334
+ setTimeout(() => {
5335
+ this.config.onDataChange(newInstance);
5336
+ }, 1);
5337
+ }
5338
+ }
5339
+ getFieldValue(fieldKey) {
5340
+ const data = this._editedData();
5341
+ return data ? data[fieldKey] : null;
5342
+ }
5343
+ onFieldValueChange(fieldKey, value) {
5344
+ this.updateField(fieldKey, value);
5345
+ const control = this._form().get(fieldKey);
5346
+ if (control) {
5347
+ control.markAsTouched();
5348
+ this.validateField(fieldKey);
5349
+ if (this.config.onDataChange && this._editedData()) {
5350
+ this.config.onDataChange(this._editedData());
5351
+ }
5352
+ }
5353
+ }
5354
+ onFieldBlur(fieldKey) {
5355
+ const control = this._form().get(fieldKey);
5356
+ if (control) {
5357
+ control.markAsTouched();
5358
+ this.validateField(fieldKey);
5359
+ }
5360
+ }
5361
+ getFieldErrors(fieldKey) {
5362
+ return this._fieldErrors()[fieldKey] || [];
5363
+ }
5364
+ validateField(fieldKey) {
5365
+ const field = this.config.fields.find(f => f.key === fieldKey);
5366
+ const control = this._form().get(fieldKey);
5367
+ const errors = [];
5368
+ if (!field || !control)
5369
+ return;
5370
+ if (control.touched && control.errors) {
5371
+ const modeConfig = field.modes?.[this.mode];
5372
+ const errorMessages = modeConfig?.errorMessages ?? field.errorMessages ?? {};
5373
+ Object.keys(control.errors).forEach(errorKey => {
5374
+ const message = errorMessages[errorKey] || errorKey;
5375
+ errors.push(message);
5376
+ });
5377
+ }
5378
+ if (control.touched && this.config.customValidators && this._editedData()) {
5379
+ const customErrors = this.config.customValidators
5380
+ .flatMap(validator => validator(this._editedData()));
5381
+ errors.push(...customErrors);
5382
+ }
5383
+ this._fieldErrors.update(current => {
5384
+ const updated = { ...current };
5385
+ if (errors.length > 0) {
5386
+ updated[fieldKey] = errors;
5387
+ }
5388
+ else {
5389
+ delete updated[fieldKey];
5390
+ }
5391
+ return updated;
5392
+ });
5393
+ if (this.config.onValidationChange) {
5394
+ this.config.onValidationChange(this._fieldErrors());
5395
+ }
5396
+ }
5397
+ validateAllFields() {
5398
+ const allErrors = {};
5399
+ let isValid = true;
5400
+ this.config.fields.forEach(field => {
5401
+ const modeConfig = field.modes?.[this.mode];
5402
+ if (modeConfig?.visible === false)
5403
+ return;
5404
+ const control = this._form().get(field.key);
5405
+ if (control) {
5406
+ control.markAsTouched();
5407
+ if (control.errors) {
5408
+ isValid = false;
5409
+ const errorMessages = modeConfig?.errorMessages ?? field.errorMessages ?? {};
5410
+ const fieldErrors = Object.keys(control.errors).map(errorKey => errorMessages[errorKey] || errorKey);
5411
+ allErrors[field.key] = fieldErrors;
5412
+ }
5413
+ }
5414
+ });
5415
+ if (this.config.customValidators && this._editedData()) {
5416
+ const customErrors = this.config.customValidators
5417
+ .flatMap(validator => validator(this._editedData()));
5418
+ if (customErrors.length > 0) {
5419
+ isValid = false;
5420
+ allErrors['_custom'] = customErrors;
5421
+ }
5422
+ }
5423
+ this._fieldErrors.set(allErrors);
5424
+ if (this.config.onValidationChange) {
5425
+ this.config.onValidationChange(allErrors);
5426
+ }
5427
+ return isValid;
5428
+ }
5429
+ reset() {
5430
+ this._editedData.set(null);
5431
+ this._fieldErrors.set({});
5432
+ this._originalData.set(null);
5433
+ this._form.set(this.formBuilder.group({}));
5434
+ this.initializeData();
5435
+ }
5436
+ setData(data) {
5437
+ this.config.initialData = data;
5438
+ this.initializeData();
5439
+ }
5440
+ getPayloadData() {
5441
+ const data = this._editedData();
5442
+ if (!data)
5443
+ return null;
5444
+ let clonedData;
5445
+ if (this.config.modelFactory) {
5446
+ clonedData = this.config.modelFactory(data);
5447
+ }
5448
+ else {
5449
+ clonedData = Object.create(Object.getPrototypeOf(data));
5450
+ Object.assign(clonedData, data);
5451
+ }
5452
+ this.config.fields.forEach(field => {
5453
+ const fieldConfig = this.getFieldConfig(field);
5454
+ const shouldInclude = fieldConfig.includeInPayload !== false;
5455
+ if (!shouldInclude) {
5456
+ const targetKey = (fieldConfig.keyToPayload ?? field.key);
5457
+ delete clonedData[targetKey];
5458
+ }
5459
+ else if (field.keyToPayload && field.keyToPayload !== field.key) {
5460
+ delete clonedData[field.key];
5461
+ }
5462
+ });
5463
+ this.convertEmptyStringsToNull(clonedData);
5464
+ return clonedData;
5465
+ }
5466
+ updateField(fieldKey, value) {
5467
+ if (!this._editedData())
5468
+ return;
5469
+ const field = this.config.fields.find(f => f.key === fieldKey);
5470
+ if (!field)
5471
+ return;
5472
+ const payloadKey = (field.keyToPayload ?? field.key);
5473
+ this._editedData.update(data => {
5474
+ if (data) {
5475
+ data[payloadKey] = value;
5476
+ }
5477
+ return data;
5478
+ });
5479
+ const control = this._form().get(fieldKey);
5480
+ if (control) {
5481
+ control.setValue(value, { emitEvent: false });
5482
+ }
5483
+ }
5484
+ getFieldConfig(field) {
5485
+ const modeConfig = field.modes?.[this.mode];
5486
+ if (!modeConfig)
5487
+ return field;
5488
+ return {
5489
+ ...field,
5490
+ defaultValue: modeConfig.defaultValue ?? field.defaultValue,
5491
+ readonly: modeConfig.readonly ?? field.readonly,
5492
+ options: modeConfig.options ?? field.options,
5493
+ validators: modeConfig.validators ?? field.validators,
5494
+ errorMessages: modeConfig.errorMessages ?? field.errorMessages,
5495
+ multiple: modeConfig.multiple ?? field.multiple,
5496
+ visible: modeConfig.visible ?? field.visible,
5497
+ includeInPayload: modeConfig.includeInPayload ?? field.includeInPayload
5498
+ };
5499
+ }
5500
+ detectChanges() {
5501
+ const editedData = this._editedData();
5502
+ const originalData = this._originalData();
5503
+ if (!editedData || !originalData || this.mode === ModalMode.VIEW) {
5504
+ return false;
5505
+ }
5506
+ const relevantFields = this.config.fields.filter(field => {
5507
+ const modeConfig = field.modes?.[this.mode];
5508
+ return modeConfig?.visible !== false;
5509
+ });
5510
+ return relevantFields.some(field => {
5511
+ const fieldKey = field.key;
5512
+ const editedValue = editedData[fieldKey];
5513
+ const originalValue = originalData[fieldKey];
5514
+ if (Array.isArray(editedValue) && Array.isArray(originalValue)) {
5515
+ return JSON.stringify(editedValue) !== JSON.stringify(originalValue);
5516
+ }
5517
+ if (editedValue instanceof Date && originalValue instanceof Date) {
5518
+ return editedValue.getTime() !== originalValue.getTime();
5519
+ }
5520
+ return editedValue !== originalValue;
5521
+ });
5522
+ }
5523
+ isFormValid() {
5524
+ const fieldErrors = this._fieldErrors();
5525
+ return Object.keys(fieldErrors).length === 0;
5526
+ }
5527
+ convertEmptyStringsToNull(data) {
5528
+ Object.keys(data).forEach(key => {
5529
+ const value = data[key];
5530
+ if (typeof value === 'string' && value.trim() === '') {
5531
+ data[key] = null;
5532
+ }
5533
+ else if (Array.isArray(value)) {
5534
+ data[key] = value.map(item => typeof item === 'string' && item.trim() === '' ? null : item);
5535
+ }
5536
+ else if (value && typeof value === 'object' && value.constructor === Object) {
5537
+ this.convertEmptyStringsToNull(value);
5538
+ }
5539
+ });
5540
+ }
5541
+ }
5542
+
5232
5543
  class FileModel {
5233
5544
  id;
5234
5545
  filename;
@@ -11311,12 +11622,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
11311
11622
  // Este archivo es generado automáticamente por scripts/update-version.js
11312
11623
  // No edites manualmente este archivo
11313
11624
  const VERSION = {
11314
- full: '2.12.11',
11625
+ full: '2.12.12',
11315
11626
  major: 2,
11316
11627
  minor: 12,
11317
- patch: 11,
11318
- timestamp: '2025-09-05T14:00:47.757Z',
11319
- buildDate: '5/9/2025'
11628
+ patch: 12,
11629
+ timestamp: '2025-09-08T12:06:21.236Z',
11630
+ buildDate: '8/9/2025'
11320
11631
  };
11321
11632
 
11322
11633
  class MainNavComponent {
@@ -13233,5 +13544,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
13233
13544
  * Generated bundle index. Do not edit.
13234
13545
  */
13235
13546
 
13236
- export { ActiveFiltersComponent, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, CacheBustingInterceptor, CardComponent, CarouselComponent, CheckboxFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, DataListComponent, DataListItemComponent, DateFieldComponent, DateUtility, DatetimeFieldComponent, DialogActions, DocumentAction, DocumentDisplayMode, DropdownComponent, DropdownDirection, DropdownService, DynamicFieldDirective, FieldErrorsComponent, FieldType, FileFieldComponent, FileModel, FileTemplateModel, FileTemplateType, FileType, FileTypeModel, FileUploadService, FilterModalComponent, FilterService, FilterType, GenericButtonComponent, GenericDocumentationComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSidebarComponent, GenericStepsComponent, GenericTableComponent, GenericTabsComponent, GenericTimelineComponent, GlobalApiConfigService, HeaderComponent, HeaderConfigurationService, HeaderElementType, HeaderService, HttpLoaderFactory, ImageModalComponent, ImageModalService, ImagePreviewComponent, LayoutAuth, LayoutBreakpoint, LayoutComponent, LayoutService, LayoutStateService, LayoutType, LoaderComponent, LoaderService, MainNavComponent, MainNavService, ModalMode, ModelApiService, MultiEntryFieldComponent, MultiEntryOutputFormat, NumberFieldComponent, NumberFieldConfigType, NumberFieldType, NumberRange, PERMISSION_ACTIONS_PROVIDER, PERMISSION_PROVIDER, PERMISSION_RESOURCES_PROVIDER, PaginationService, PasswordFieldComponent, PermissionEnumsService, PermissionModel, PermissionService, PermissionWrapperService, PermissionsActions, PermissionsInterceptor, PermissionsResources, ProgressBarComponent, ProgressBarSize, RatingService, RatingSize, RatingType, ResetPasswordModel, RoleModel, SelectFieldComponent, ServerSelectFieldComponent, ServerSelectService, SidebarCustomModalComponent, SidebarCustomModalService, SidebarHeight, SidebarMobileModalService, SidebarMobileType, SidebarPosition, SidebarService, SidebarState, SidebarTemplateRegistryService, SidebarVisibility, SidebarWidth, SmartFieldComponent, SortDirection, SortMode, StepSize, StepStatus, StepType, StepsService, SwitchFieldComponent, TableAction, TableActionService, TableDataService, TableSortService, TextAreaFieldComponent, TextFieldComponent, TimeFieldComponent, TimeInterval, TimelineService, TimelineStatus, TimelineType, TranslationMergeService, UsersModel, VERSION, equalToValidator, isSameDate, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader };
13547
+ export { ActiveFiltersComponent, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, CacheBustingInterceptor, CardComponent, CarouselComponent, CheckboxFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, DataListComponent, DataListItemComponent, DateFieldComponent, DateUtility, DatetimeFieldComponent, DialogActions, DocumentAction, DocumentDisplayMode, DropdownComponent, DropdownDirection, DropdownService, DynamicFieldDirective, DynamicFieldsHelper, FieldErrorsComponent, FieldType, FileFieldComponent, FileModel, FileTemplateModel, FileTemplateType, FileType, FileTypeModel, FileUploadService, FilterModalComponent, FilterService, FilterType, GenericButtonComponent, GenericDocumentationComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSidebarComponent, GenericStepsComponent, GenericTableComponent, GenericTabsComponent, GenericTimelineComponent, GlobalApiConfigService, HeaderComponent, HeaderConfigurationService, HeaderElementType, HeaderService, HttpLoaderFactory, ImageModalComponent, ImageModalService, ImagePreviewComponent, LayoutAuth, LayoutBreakpoint, LayoutComponent, LayoutService, LayoutStateService, LayoutType, LoaderComponent, LoaderService, MainNavComponent, MainNavService, ModalMode, ModelApiService, MultiEntryFieldComponent, MultiEntryOutputFormat, NumberFieldComponent, NumberFieldConfigType, NumberFieldType, NumberRange, PERMISSION_ACTIONS_PROVIDER, PERMISSION_PROVIDER, PERMISSION_RESOURCES_PROVIDER, PaginationService, PasswordFieldComponent, PermissionEnumsService, PermissionModel, PermissionService, PermissionWrapperService, PermissionsActions, PermissionsInterceptor, PermissionsResources, ProgressBarComponent, ProgressBarSize, RatingService, RatingSize, RatingType, ResetPasswordModel, RoleModel, SelectFieldComponent, ServerSelectFieldComponent, ServerSelectService, SidebarCustomModalComponent, SidebarCustomModalService, SidebarHeight, SidebarMobileModalService, SidebarMobileType, SidebarPosition, SidebarService, SidebarState, SidebarTemplateRegistryService, SidebarVisibility, SidebarWidth, SmartFieldComponent, SortDirection, SortMode, StepSize, StepStatus, StepType, StepsService, SwitchFieldComponent, TableAction, TableActionService, TableDataService, TableSortService, TextAreaFieldComponent, TextFieldComponent, TimeFieldComponent, TimeInterval, TimelineService, TimelineStatus, TimelineType, TranslationMergeService, UsersModel, VERSION, equalToValidator, isSameDate, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader };
13237
13548
  //# sourceMappingURL=solcre-org-core-ui.mjs.map