@solcre-org/core-ui 2.15.27 → 2.15.29

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.
@@ -18,8 +18,8 @@ import { DomSanitizer } from '@angular/platform-browser';
18
18
  import * as i1$1 from '@angular/common/http';
19
19
  import { HttpClient, HttpHeaders } from '@angular/common/http';
20
20
  import dayjs from 'dayjs';
21
- import utc from 'dayjs/plugin/utc';
22
- import timezone from 'dayjs/plugin/timezone';
21
+ import * as utc from 'dayjs/plugin/utc';
22
+ import * as timezone from 'dayjs/plugin/timezone';
23
23
  import * as i1 from '@angular/cdk/overlay';
24
24
  import { OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
25
25
  import { TemplatePortal } from '@angular/cdk/portal';
@@ -2860,7 +2860,6 @@ const DEFAULT_COUNTRIES = [
2860
2860
  { "code": CountryCode.PL, "phone": "+48", "name": "Poland", "flag": "165-poland.svg" },
2861
2861
  { "code": CountryCode.CV, "phone": "+238", "name": "Cape Verde", "flag": "166-cape verde.svg" },
2862
2862
  { "code": CountryCode.TD, "phone": "+235", "name": "Chad", "flag": "167-chad.svg" },
2863
- { "code": CountryCode.BT, "phone": "+975", "name": "Bhutan", "flag": "168-bhutan.svg" },
2864
2863
  { "code": CountryCode.IO, "phone": "+246", "name": "British Indian Ocean Territory", "flag": "169-british indian ocean territory.svg" },
2865
2864
  { "code": CountryCode.KY, "phone": "+1", "name": "Cayman Islands", "flag": "170-cayman islands.svg" },
2866
2865
  { "code": CountryCode.CF, "phone": "+236", "name": "Central African Republic", "flag": "171-central african republic.svg" },
@@ -5492,6 +5491,7 @@ class DataListComponent {
5492
5491
  const value = this.getItemValue(item);
5493
5492
  return {
5494
5493
  $implicit: value,
5494
+ value: value,
5495
5495
  item: item,
5496
5496
  data: data
5497
5497
  };
@@ -5608,6 +5608,18 @@ var PermissionsResources;
5608
5608
  PermissionsResources["MY_COMPANY_TELEWORK"] = "my_company_remote_work";
5609
5609
  PermissionsResources["FILE_TEMPLATES"] = "file_templates";
5610
5610
  PermissionsResources["CONFIGURATION"] = "configuration";
5611
+ PermissionsResources["COMPANIES_CHANGE_STATUS"] = "companies_change_status";
5612
+ PermissionsResources["EMPLOYEES_BULK_UPLOAD"] = "employees_bulk_upload";
5613
+ PermissionsResources["EMPLOYEES_EXPORT"] = "employees_export";
5614
+ PermissionsResources["RESERVATIONS_EXPORT"] = "reservations_export";
5615
+ PermissionsResources["SERVICES_EXPORT"] = "services_export";
5616
+ PermissionsResources["ACCESS_CARD_ASSIGN"] = "access_card_assign";
5617
+ PermissionsResources["ACCESS_CARD_REJECT_REQUEST"] = "access_card_reject_request";
5618
+ PermissionsResources["ACCESS_CARD_MARK_DELIVERED"] = "access_card_mark_delivered";
5619
+ PermissionsResources["ACCESS_CARD_REQUEST_REASSIGNMENT"] = "access_card_request_reassignment";
5620
+ PermissionsResources["ACCESS_CARD_MARK_RETURNED"] = "access_card_mark_returned";
5621
+ PermissionsResources["SERVICE_BUDGET_APPROVE"] = "service_budget_approve";
5622
+ PermissionsResources["SERVICE_BUDGET_REJECT"] = "service_budget_reject";
5611
5623
  })(PermissionsResources || (PermissionsResources = {}));
5612
5624
 
5613
5625
  class PermissionWrapperService {
@@ -5984,7 +5996,7 @@ class StepsService {
5984
5996
  return this._steps().findIndex(step => step.id === activeId);
5985
5997
  });
5986
5998
  initializeSteps(steps, activeStepId, instanceId) {
5987
- this._steps.set([...steps]);
5999
+ this._steps.set(steps.map(s => ({ ...s })));
5988
6000
  this._stepsInstanceId.set(instanceId || 'default');
5989
6001
  if (activeStepId) {
5990
6002
  this._activeStepId.set(activeStepId);
@@ -5999,11 +6011,11 @@ class StepsService {
5999
6011
  if (!step) {
6000
6012
  return null;
6001
6013
  }
6014
+ const previousStepId = this._activeStepId();
6015
+ this._activeStepId.set(stepId);
6002
6016
  if (step.disabled) {
6003
6017
  return null;
6004
6018
  }
6005
- const previousStepId = this._activeStepId();
6006
- this._activeStepId.set(stepId);
6007
6019
  return {
6008
6020
  step,
6009
6021
  index: this._steps().findIndex(s => s.id === stepId),
@@ -6635,7 +6647,8 @@ class GenericModalComponent {
6635
6647
  label: field.label,
6636
6648
  value: data[field.key],
6637
6649
  formattedValue: this.getFormattedValue(field, data[field.key]),
6638
- visible: true
6650
+ visible: true,
6651
+ customTemplate: field.customViewTemplate
6639
6652
  }));
6640
6653
  });
6641
6654
  visibleTabs = computed(() => {
@@ -6935,44 +6948,42 @@ class GenericModalComponent {
6935
6948
  formGroup[fieldKey] = [initialValue, validators];
6936
6949
  });
6937
6950
  this.form.set(this.formBuilder.group(formGroup));
6938
- setTimeout(() => {
6939
- this.allFields().forEach(field => {
6940
- const fieldKey = field.key;
6941
- const payloadKey = (field.keyToPayload ?? field.key);
6942
- const modeConfig = field.modes?.[this.mode()];
6943
- const dynamicValueFn = (modeConfig?.dynamicValue ?? field.dynamicValue);
6944
- if (typeof dynamicValueFn === 'function') {
6945
- const dynamicVal = dynamicValueFn(newInstance);
6946
- if (dynamicVal !== undefined && dynamicVal !== null) {
6947
- newInstance[payloadKey] = dynamicVal;
6948
- const control = this.form().get(fieldKey);
6949
- if (control) {
6950
- control.setValue(dynamicVal, { emitEvent: true });
6951
- }
6951
+ this.allFields().forEach(field => {
6952
+ const fieldKey = field.key;
6953
+ const payloadKey = (field.keyToPayload ?? field.key);
6954
+ const modeConfig = field.modes?.[this.mode()];
6955
+ const dynamicValueFn = (modeConfig?.dynamicValue ?? field.dynamicValue);
6956
+ if (typeof dynamicValueFn === 'function') {
6957
+ const dynamicVal = dynamicValueFn(newInstance);
6958
+ if (dynamicVal !== undefined && dynamicVal !== null) {
6959
+ newInstance[payloadKey] = dynamicVal;
6960
+ const control = this.form().get(fieldKey);
6961
+ if (control) {
6962
+ control.setValue(dynamicVal, { emitEvent: true });
6952
6963
  }
6953
6964
  }
6954
- });
6955
- this.allFields().forEach(field => {
6956
- const fieldKey = field.key;
6957
- const control = this.form().get(fieldKey);
6958
- if (control && control.value !== undefined && control.value !== null) {
6959
- const payloadKey = (field.keyToPayload ?? field.key);
6960
- newInstance[payloadKey] = control.value;
6961
- }
6962
- });
6963
- Object.values(this.form().controls).forEach(control => {
6964
- control.markAsUntouched();
6965
- });
6966
- this.fieldErrors.set({});
6967
- this.internalErrors.set([]);
6968
- this.editedData.set(newInstance);
6969
- if (this.mode() !== ModalMode.VIEW) {
6970
- const originalCopy = Object.create(Object.getPrototypeOf(newInstance));
6971
- Object.assign(originalCopy, newInstance);
6972
- this.originalData.set(originalCopy);
6973
6965
  }
6974
- this.modalData.emit(newInstance);
6975
- }, 50);
6966
+ });
6967
+ this.allFields().forEach(field => {
6968
+ const fieldKey = field.key;
6969
+ const control = this.form().get(fieldKey);
6970
+ if (control && control.value !== undefined && control.value !== null) {
6971
+ const payloadKey = (field.keyToPayload ?? field.key);
6972
+ newInstance[payloadKey] = control.value;
6973
+ }
6974
+ });
6975
+ Object.values(this.form().controls).forEach(control => {
6976
+ control.markAsUntouched();
6977
+ });
6978
+ this.fieldErrors.set({});
6979
+ this.internalErrors.set([]);
6980
+ this.editedData.set(newInstance);
6981
+ if (this.mode() !== ModalMode.VIEW) {
6982
+ const originalCopy = Object.create(Object.getPrototypeOf(newInstance));
6983
+ Object.assign(originalCopy, newInstance);
6984
+ this.originalData.set(originalCopy);
6985
+ }
6986
+ this.modalData.emit(newInstance);
6976
6987
  }
6977
6988
  initializeActiveTabAndStep() {
6978
6989
  if (this.hasTabs()) {
@@ -7101,15 +7112,18 @@ class GenericModalComponent {
7101
7112
  const { _isSeparatedDocumentField, ...separatedKeys } = value;
7102
7113
  this.editedData.update(data => {
7103
7114
  if (data) {
7115
+ const newData = Object.create(Object.getPrototypeOf(data));
7116
+ Object.assign(newData, data);
7104
7117
  Object.keys(separatedKeys).forEach(key => {
7105
7118
  const value = separatedKeys[key];
7106
7119
  if (value !== null && value !== undefined) {
7107
- data[key] = value;
7120
+ newData[key] = value;
7108
7121
  }
7109
7122
  else {
7110
- delete data[key];
7123
+ delete newData[key];
7111
7124
  }
7112
7125
  });
7126
+ return newData;
7113
7127
  }
7114
7128
  return data;
7115
7129
  });
@@ -7126,22 +7140,15 @@ class GenericModalComponent {
7126
7140
  return;
7127
7141
  }
7128
7142
  const payloadKey = (field.keyToPayload ?? field.key);
7129
- if (field.type === FieldType.FILE) {
7130
- this.editedData.update(data => {
7131
- if (data) {
7132
- data[payloadKey] = value;
7133
- }
7134
- return data;
7135
- });
7136
- }
7137
- else {
7138
- this.editedData.update(data => {
7139
- if (data) {
7140
- data[payloadKey] = value;
7141
- }
7142
- return data;
7143
- });
7144
- }
7143
+ this.editedData.update(data => {
7144
+ if (data) {
7145
+ const newData = Object.create(Object.getPrototypeOf(data));
7146
+ Object.assign(newData, data);
7147
+ newData[payloadKey] = value;
7148
+ return newData;
7149
+ }
7150
+ return data;
7151
+ });
7145
7152
  const control = this.form().get(fieldKey);
7146
7153
  if (control) {
7147
7154
  control.setValue(value, { emitEvent: false });
@@ -7407,7 +7414,8 @@ class GenericModalComponent {
7407
7414
  errorMessages: modeConfig.errorMessages ?? field.errorMessages,
7408
7415
  multiple: modeConfig.multiple ?? field.multiple,
7409
7416
  visible: this.evaluateVisibility(modeConfig.visible ?? field.visible),
7410
- includeInPayload: modeConfig.includeInPayload ?? field.includeInPayload
7417
+ includeInPayload: modeConfig.includeInPayload ?? field.includeInPayload,
7418
+ customViewTemplate: modeConfig.customViewTemplate ?? field.customViewTemplate
7411
7419
  };
7412
7420
  }
7413
7421
  evaluateVisibility(visible) {
@@ -7578,7 +7586,7 @@ class GenericModalComponent {
7578
7586
  });
7579
7587
  }
7580
7588
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7581
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: GenericModalComponent, isStandalone: true, selector: "core-generic-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null }, tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, isMultiple: { classPropertyName: "isMultiple", publicName: "isMultiple", isSignal: true, isRequired: false, transformFunction: null }, customTemplate: { classPropertyName: "customTemplate", publicName: "customTemplate", isSignal: true, isRequired: false, transformFunction: null }, customViewTemplate: { classPropertyName: "customViewTemplate", publicName: "customViewTemplate", isSignal: true, isRequired: false, transformFunction: null }, finalStepTemplate: { classPropertyName: "finalStepTemplate", publicName: "finalStepTemplate", isSignal: true, isRequired: false, transformFunction: null }, buttonConfig: { classPropertyName: "buttonConfig", publicName: "buttonConfig", isSignal: true, isRequired: false, transformFunction: null }, modelFactory: { classPropertyName: "modelFactory", publicName: "modelFactory", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, validators: { classPropertyName: "validators", publicName: "validators", isSignal: true, isRequired: false, transformFunction: null }, customHasChanges: { classPropertyName: "customHasChanges", publicName: "customHasChanges", isSignal: true, isRequired: false, transformFunction: null }, stepValidationEnabled: { classPropertyName: "stepValidationEnabled", publicName: "stepValidationEnabled", isSignal: true, isRequired: false, transformFunction: null }, allowFreeNavigation: { classPropertyName: "allowFreeNavigation", publicName: "allowFreeNavigation", isSignal: true, isRequired: false, transformFunction: null }, autoMarkCompleted: { classPropertyName: "autoMarkCompleted", publicName: "autoMarkCompleted", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { save: "save", close: "close", modalData: "modalData" }, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<div class=\"c-modal\" [class.is-visible]=\"isOpen()\" [class.is-closing]=\"isClosing()\">\n <div class=\"c-modal__overlay\" (click)=\"onClose()\"></div>\n <div class=\"c-modal__holder\">\n <div class=\"c-modal__header\">\n <p class=\"c-modal__title\">\n {{ title() | translate }}\n </p>\n <core-generic-button\n [config]=\"closeButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n </div>\n <div class=\"c-modal__body\">\n @if (editedData() || customTemplate()) {\n @if (hasTabs()) {\n <nav core-generic-tabs\n [config]=\"genericTabsConfig()\"\n [activeTabId]=\"activeTabId()\"\n [hasTabErrors]=\"hasTabErrorsFunction\"\n (tabChange)=\"onGenericTabChange($event)\">\n </nav>\n } @else if (hasSteps()) {\n <core-generic-steps\n [config]=\"stepsConfig()\">\n </core-generic-steps>\n }\n\n @if (customTemplate()) {\n <div class=\"c-entry-group\">\n <ng-container\n [ngTemplateOutlet]=\"customTemplate()\"\n [ngTemplateOutletContext]=\"{\n $implicit: editedData(),\n mode: mode(),\n updateField: onFieldValueChange.bind(this),\n save: onSave.bind(this),\n close: onClose.bind(this),\n activeTabId: activeTabId(),\n onTabChange: onTabChange.bind(this),\n getFieldErrors: getFieldErrors.bind(this),\n validateAllFields: validateAllFields.bind(this),\n hasErrors: hasErrors(),\n setCustomHasChanges: setCustomHasChanges.bind(this)\n }\"\n ></ng-container>\n </div> <!-- .c-entry-group -->\n } @else if (editedData()) {\n @if (mode() === ModalMode.VIEW) {\n <core-data-list\n [items]=\"dataListItems()\"\n [customTemplate]=\"customViewTemplate()\"\n [emptyMessage]=\"'modal.noData'\"\n ></core-data-list>\n } @else {\n @if (hasSteps() && currentStep()?.customTemplate) {\n <!-- Renderizar template personalizado del step -->\n <div class=\"c-entry-group\">\n <ng-container\n [ngTemplateOutlet]=\"currentStep()!.customTemplate!\"\n [ngTemplateOutletContext]=\"{\n $implicit: editedData(),\n mode: mode(),\n updateField: onFieldValueChange.bind(this),\n save: onSave.bind(this),\n close: onClose.bind(this),\n getFieldErrors: getFieldErrors.bind(this)\n }\"\n ></ng-container>\n </div>\n } @else {\n <!-- Renderizar campos normales -->\n <div class=\"c-entry-group\">\n @for (field of currentFields(); track field.key) {\n @if (getFieldConfig(field).visible) {\n <div\n coreDynamicField\n [field]=\"getFieldConfig(field)\"\n [value]=\"editedData()![field.key]\"\n [mode]=\"mode()\"\n [errors]=\"getFieldErrors(field.key)\"\n [rowData]=\"editedData()\"\n [formValue]=\"editedData()\"\n (valueChange)=\"onFieldValueChange(field.key, $event)\"\n (onBlurEvent)=\"validateAllFields()\"\n (selectionChange)=\"onSelectionChange($event)\"\n ></div>\n }\n }\n </div> <!-- .c-entry-group -->\n }\n }\n }\n } @else {\n <p>{{ 'modal.noData' | translate }}</p>\n }\n </div>\n <div class=\"c-modal__bottom\">\n @if (buttonConfig().length > 0) {\n @for (button of buttonConfig(); track $index) {\n <core-generic-button\n [config]=\"getCustomButtonConfig(button)\"\n [data]=\"data()\"\n (buttonClick)=\"onCustomButtonClick(button)\">\n </core-generic-button>\n }\n } @else {\n @if (hasSteps()) {\n <!-- Botones para navegaci\u00F3n de steps -->\n <core-generic-button\n [config]=\"defaultCancelButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n @if (currentStepIndex() > 0) {\n <core-generic-button\n [config]=\"prevStepButtonConfig()\"\n (buttonClick)=\"goToPreviousStep()\">\n </core-generic-button>\n }\n <core-generic-button\n [config]=\"nextStepButtonConfig()\"\n (buttonClick)=\"goToNextStep()\">\n </core-generic-button>\n } @else {\n <!-- Botones normales para modales sin steps -->\n <core-generic-button\n [config]=\"defaultCancelButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n @if (mode() !== ModalMode.VIEW && showSaveButton()) {\n <core-generic-button\n [config]=\"defaultSaveButtonConfig()\"\n (buttonClick)=\"onSave()\">\n </core-generic-button>\n }\n }\n }\n </div>\n </div>\n</div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "directive", type: DynamicFieldDirective, selector: "[coreDynamicField]", inputs: ["field", "value", "mode", "errors", "rowData", "formValue"], outputs: ["valueChange", "onBlurEvent", "onEnterEvent", "selectionChange"] }, { kind: "component", type: GenericTabsComponent, selector: "nav[core-generic-tabs]", inputs: ["config", "activeTabId", "hasTabErrors"], outputs: ["tabClick", "tabChange"] }, { kind: "component", type: GenericStepsComponent, selector: "core-generic-steps", inputs: ["config", "useService", "instanceId"], outputs: ["stepClick", "stepChange", "serviceStepChange"] }, { kind: "component", type: GenericButtonComponent, selector: "core-generic-button", inputs: ["config", "data"], outputs: ["buttonClick"] }, { kind: "component", type: DataListComponent, selector: "core-data-list", inputs: ["items", "fields", "data", "customTemplate", "showEmptyMessage", "emptyMessage", "cssClasses"] }] });
7589
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: GenericModalComponent, isStandalone: true, selector: "core-generic-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null }, tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, isMultiple: { classPropertyName: "isMultiple", publicName: "isMultiple", isSignal: true, isRequired: false, transformFunction: null }, customTemplate: { classPropertyName: "customTemplate", publicName: "customTemplate", isSignal: true, isRequired: false, transformFunction: null }, customViewTemplate: { classPropertyName: "customViewTemplate", publicName: "customViewTemplate", isSignal: true, isRequired: false, transformFunction: null }, finalStepTemplate: { classPropertyName: "finalStepTemplate", publicName: "finalStepTemplate", isSignal: true, isRequired: false, transformFunction: null }, buttonConfig: { classPropertyName: "buttonConfig", publicName: "buttonConfig", isSignal: true, isRequired: false, transformFunction: null }, modelFactory: { classPropertyName: "modelFactory", publicName: "modelFactory", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, validators: { classPropertyName: "validators", publicName: "validators", isSignal: true, isRequired: false, transformFunction: null }, customHasChanges: { classPropertyName: "customHasChanges", publicName: "customHasChanges", isSignal: true, isRequired: false, transformFunction: null }, stepValidationEnabled: { classPropertyName: "stepValidationEnabled", publicName: "stepValidationEnabled", isSignal: true, isRequired: false, transformFunction: null }, allowFreeNavigation: { classPropertyName: "allowFreeNavigation", publicName: "allowFreeNavigation", isSignal: true, isRequired: false, transformFunction: null }, autoMarkCompleted: { classPropertyName: "autoMarkCompleted", publicName: "autoMarkCompleted", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { save: "save", close: "close", modalData: "modalData" }, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<div class=\"c-modal\" [class.is-visible]=\"isOpen()\" [class.is-closing]=\"isClosing()\">\n <div class=\"c-modal__overlay\" (click)=\"onClose()\"></div>\n <div class=\"c-modal__holder\">\n <div class=\"c-modal__header\">\n <p class=\"c-modal__title\">\n {{ title() | translate }}\n </p>\n <core-generic-button\n [config]=\"closeButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n </div>\n <div class=\"c-modal__body\">\n @if (editedData() || customTemplate()) {\n @if (hasTabs()) {\n <nav core-generic-tabs\n [config]=\"genericTabsConfig()\"\n [activeTabId]=\"activeTabId()\"\n [hasTabErrors]=\"hasTabErrorsFunction\"\n (tabChange)=\"onGenericTabChange($event)\">\n </nav>\n } @else if (hasSteps()) {\n <core-generic-steps\n [config]=\"stepsConfig()\">\n </core-generic-steps>\n }\n\n @if (customTemplate()) {\n <div class=\"c-entry-group\">\n <ng-container\n [ngTemplateOutlet]=\"customTemplate()\"\n [ngTemplateOutletContext]=\"{\n $implicit: editedData(),\n mode: mode(),\n updateField: onFieldValueChange.bind(this),\n save: onSave.bind(this),\n close: onClose.bind(this),\n activeTabId: activeTabId(),\n onTabChange: onTabChange.bind(this),\n getFieldErrors: getFieldErrors.bind(this),\n validateAllFields: validateAllFields.bind(this),\n hasErrors: hasErrors(),\n setCustomHasChanges: setCustomHasChanges.bind(this)\n }\"\n ></ng-container>\n </div> <!-- .c-entry-group -->\n } @else if (editedData()) {\n @if (mode() === ModalMode.VIEW) {\n <core-data-list\n [items]=\"dataListItems()\"\n [data]=\"editedData()\"\n [customTemplate]=\"customViewTemplate()\"\n [emptyMessage]=\"'modal.noData'\"\n ></core-data-list>\n } @else {\n @if (hasSteps() && currentStep()?.customTemplate) {\n <!-- Renderizar template personalizado del step -->\n <div class=\"c-entry-group\">\n <ng-container\n [ngTemplateOutlet]=\"currentStep()!.customTemplate!\"\n [ngTemplateOutletContext]=\"{\n $implicit: editedData(),\n mode: mode(),\n updateField: onFieldValueChange.bind(this),\n save: onSave.bind(this),\n close: onClose.bind(this),\n getFieldErrors: getFieldErrors.bind(this)\n }\"\n ></ng-container>\n </div>\n } @else {\n <!-- Renderizar campos normales -->\n <div class=\"c-entry-group\">\n @for (field of currentFields(); track field.key) {\n @if (getFieldConfig(field).visible) {\n <div\n coreDynamicField\n [field]=\"getFieldConfig(field)\"\n [value]=\"editedData()![field.key]\"\n [mode]=\"mode()\"\n [errors]=\"getFieldErrors(field.key)\"\n [rowData]=\"editedData()\"\n [formValue]=\"editedData()\"\n (valueChange)=\"onFieldValueChange(field.key, $event)\"\n (onBlurEvent)=\"validateAllFields()\"\n (selectionChange)=\"onSelectionChange($event)\"\n ></div>\n }\n }\n </div> <!-- .c-entry-group -->\n }\n }\n }\n } @else {\n <p>{{ 'modal.noData' | translate }}</p>\n }\n </div>\n <div class=\"c-modal__bottom\">\n @if (buttonConfig().length > 0) {\n @for (button of buttonConfig(); track $index) {\n <core-generic-button\n [config]=\"getCustomButtonConfig(button)\"\n [data]=\"data()\"\n (buttonClick)=\"onCustomButtonClick(button)\">\n </core-generic-button>\n }\n } @else {\n @if (hasSteps()) {\n <!-- Botones para navegaci\u00F3n de steps -->\n <core-generic-button\n [config]=\"defaultCancelButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n @if (currentStepIndex() > 0) {\n <core-generic-button\n [config]=\"prevStepButtonConfig()\"\n (buttonClick)=\"goToPreviousStep()\">\n </core-generic-button>\n }\n <core-generic-button\n [config]=\"nextStepButtonConfig()\"\n (buttonClick)=\"goToNextStep()\">\n </core-generic-button>\n } @else {\n <!-- Botones normales para modales sin steps -->\n <core-generic-button\n [config]=\"defaultCancelButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n @if (mode() !== ModalMode.VIEW && showSaveButton()) {\n <core-generic-button\n [config]=\"defaultSaveButtonConfig()\"\n (buttonClick)=\"onSave()\">\n </core-generic-button>\n }\n }\n }\n </div>\n </div>\n</div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "directive", type: DynamicFieldDirective, selector: "[coreDynamicField]", inputs: ["field", "value", "mode", "errors", "rowData", "formValue"], outputs: ["valueChange", "onBlurEvent", "onEnterEvent", "selectionChange"] }, { kind: "component", type: GenericTabsComponent, selector: "nav[core-generic-tabs]", inputs: ["config", "activeTabId", "hasTabErrors"], outputs: ["tabClick", "tabChange"] }, { kind: "component", type: GenericStepsComponent, selector: "core-generic-steps", inputs: ["config", "useService", "instanceId"], outputs: ["stepClick", "stepChange", "serviceStepChange"] }, { kind: "component", type: GenericButtonComponent, selector: "core-generic-button", inputs: ["config", "data"], outputs: ["buttonClick"] }, { kind: "component", type: DataListComponent, selector: "core-data-list", inputs: ["items", "fields", "data", "customTemplate", "showEmptyMessage", "emptyMessage", "cssClasses"] }] });
7582
7590
  }
7583
7591
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericModalComponent, decorators: [{
7584
7592
  type: Component,
@@ -7592,7 +7600,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
7592
7600
  GenericStepsComponent,
7593
7601
  GenericButtonComponent,
7594
7602
  DataListComponent,
7595
- ], hostDirectives: [CoreHostDirective], template: "<div class=\"c-modal\" [class.is-visible]=\"isOpen()\" [class.is-closing]=\"isClosing()\">\n <div class=\"c-modal__overlay\" (click)=\"onClose()\"></div>\n <div class=\"c-modal__holder\">\n <div class=\"c-modal__header\">\n <p class=\"c-modal__title\">\n {{ title() | translate }}\n </p>\n <core-generic-button\n [config]=\"closeButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n </div>\n <div class=\"c-modal__body\">\n @if (editedData() || customTemplate()) {\n @if (hasTabs()) {\n <nav core-generic-tabs\n [config]=\"genericTabsConfig()\"\n [activeTabId]=\"activeTabId()\"\n [hasTabErrors]=\"hasTabErrorsFunction\"\n (tabChange)=\"onGenericTabChange($event)\">\n </nav>\n } @else if (hasSteps()) {\n <core-generic-steps\n [config]=\"stepsConfig()\">\n </core-generic-steps>\n }\n\n @if (customTemplate()) {\n <div class=\"c-entry-group\">\n <ng-container\n [ngTemplateOutlet]=\"customTemplate()\"\n [ngTemplateOutletContext]=\"{\n $implicit: editedData(),\n mode: mode(),\n updateField: onFieldValueChange.bind(this),\n save: onSave.bind(this),\n close: onClose.bind(this),\n activeTabId: activeTabId(),\n onTabChange: onTabChange.bind(this),\n getFieldErrors: getFieldErrors.bind(this),\n validateAllFields: validateAllFields.bind(this),\n hasErrors: hasErrors(),\n setCustomHasChanges: setCustomHasChanges.bind(this)\n }\"\n ></ng-container>\n </div> <!-- .c-entry-group -->\n } @else if (editedData()) {\n @if (mode() === ModalMode.VIEW) {\n <core-data-list\n [items]=\"dataListItems()\"\n [customTemplate]=\"customViewTemplate()\"\n [emptyMessage]=\"'modal.noData'\"\n ></core-data-list>\n } @else {\n @if (hasSteps() && currentStep()?.customTemplate) {\n <!-- Renderizar template personalizado del step -->\n <div class=\"c-entry-group\">\n <ng-container\n [ngTemplateOutlet]=\"currentStep()!.customTemplate!\"\n [ngTemplateOutletContext]=\"{\n $implicit: editedData(),\n mode: mode(),\n updateField: onFieldValueChange.bind(this),\n save: onSave.bind(this),\n close: onClose.bind(this),\n getFieldErrors: getFieldErrors.bind(this)\n }\"\n ></ng-container>\n </div>\n } @else {\n <!-- Renderizar campos normales -->\n <div class=\"c-entry-group\">\n @for (field of currentFields(); track field.key) {\n @if (getFieldConfig(field).visible) {\n <div\n coreDynamicField\n [field]=\"getFieldConfig(field)\"\n [value]=\"editedData()![field.key]\"\n [mode]=\"mode()\"\n [errors]=\"getFieldErrors(field.key)\"\n [rowData]=\"editedData()\"\n [formValue]=\"editedData()\"\n (valueChange)=\"onFieldValueChange(field.key, $event)\"\n (onBlurEvent)=\"validateAllFields()\"\n (selectionChange)=\"onSelectionChange($event)\"\n ></div>\n }\n }\n </div> <!-- .c-entry-group -->\n }\n }\n }\n } @else {\n <p>{{ 'modal.noData' | translate }}</p>\n }\n </div>\n <div class=\"c-modal__bottom\">\n @if (buttonConfig().length > 0) {\n @for (button of buttonConfig(); track $index) {\n <core-generic-button\n [config]=\"getCustomButtonConfig(button)\"\n [data]=\"data()\"\n (buttonClick)=\"onCustomButtonClick(button)\">\n </core-generic-button>\n }\n } @else {\n @if (hasSteps()) {\n <!-- Botones para navegaci\u00F3n de steps -->\n <core-generic-button\n [config]=\"defaultCancelButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n @if (currentStepIndex() > 0) {\n <core-generic-button\n [config]=\"prevStepButtonConfig()\"\n (buttonClick)=\"goToPreviousStep()\">\n </core-generic-button>\n }\n <core-generic-button\n [config]=\"nextStepButtonConfig()\"\n (buttonClick)=\"goToNextStep()\">\n </core-generic-button>\n } @else {\n <!-- Botones normales para modales sin steps -->\n <core-generic-button\n [config]=\"defaultCancelButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n @if (mode() !== ModalMode.VIEW && showSaveButton()) {\n <core-generic-button\n [config]=\"defaultSaveButtonConfig()\"\n (buttonClick)=\"onSave()\">\n </core-generic-button>\n }\n }\n }\n </div>\n </div>\n</div>" }]
7603
+ ], hostDirectives: [CoreHostDirective], template: "<div class=\"c-modal\" [class.is-visible]=\"isOpen()\" [class.is-closing]=\"isClosing()\">\n <div class=\"c-modal__overlay\" (click)=\"onClose()\"></div>\n <div class=\"c-modal__holder\">\n <div class=\"c-modal__header\">\n <p class=\"c-modal__title\">\n {{ title() | translate }}\n </p>\n <core-generic-button\n [config]=\"closeButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n </div>\n <div class=\"c-modal__body\">\n @if (editedData() || customTemplate()) {\n @if (hasTabs()) {\n <nav core-generic-tabs\n [config]=\"genericTabsConfig()\"\n [activeTabId]=\"activeTabId()\"\n [hasTabErrors]=\"hasTabErrorsFunction\"\n (tabChange)=\"onGenericTabChange($event)\">\n </nav>\n } @else if (hasSteps()) {\n <core-generic-steps\n [config]=\"stepsConfig()\">\n </core-generic-steps>\n }\n\n @if (customTemplate()) {\n <div class=\"c-entry-group\">\n <ng-container\n [ngTemplateOutlet]=\"customTemplate()\"\n [ngTemplateOutletContext]=\"{\n $implicit: editedData(),\n mode: mode(),\n updateField: onFieldValueChange.bind(this),\n save: onSave.bind(this),\n close: onClose.bind(this),\n activeTabId: activeTabId(),\n onTabChange: onTabChange.bind(this),\n getFieldErrors: getFieldErrors.bind(this),\n validateAllFields: validateAllFields.bind(this),\n hasErrors: hasErrors(),\n setCustomHasChanges: setCustomHasChanges.bind(this)\n }\"\n ></ng-container>\n </div> <!-- .c-entry-group -->\n } @else if (editedData()) {\n @if (mode() === ModalMode.VIEW) {\n <core-data-list\n [items]=\"dataListItems()\"\n [data]=\"editedData()\"\n [customTemplate]=\"customViewTemplate()\"\n [emptyMessage]=\"'modal.noData'\"\n ></core-data-list>\n } @else {\n @if (hasSteps() && currentStep()?.customTemplate) {\n <!-- Renderizar template personalizado del step -->\n <div class=\"c-entry-group\">\n <ng-container\n [ngTemplateOutlet]=\"currentStep()!.customTemplate!\"\n [ngTemplateOutletContext]=\"{\n $implicit: editedData(),\n mode: mode(),\n updateField: onFieldValueChange.bind(this),\n save: onSave.bind(this),\n close: onClose.bind(this),\n getFieldErrors: getFieldErrors.bind(this)\n }\"\n ></ng-container>\n </div>\n } @else {\n <!-- Renderizar campos normales -->\n <div class=\"c-entry-group\">\n @for (field of currentFields(); track field.key) {\n @if (getFieldConfig(field).visible) {\n <div\n coreDynamicField\n [field]=\"getFieldConfig(field)\"\n [value]=\"editedData()![field.key]\"\n [mode]=\"mode()\"\n [errors]=\"getFieldErrors(field.key)\"\n [rowData]=\"editedData()\"\n [formValue]=\"editedData()\"\n (valueChange)=\"onFieldValueChange(field.key, $event)\"\n (onBlurEvent)=\"validateAllFields()\"\n (selectionChange)=\"onSelectionChange($event)\"\n ></div>\n }\n }\n </div> <!-- .c-entry-group -->\n }\n }\n }\n } @else {\n <p>{{ 'modal.noData' | translate }}</p>\n }\n </div>\n <div class=\"c-modal__bottom\">\n @if (buttonConfig().length > 0) {\n @for (button of buttonConfig(); track $index) {\n <core-generic-button\n [config]=\"getCustomButtonConfig(button)\"\n [data]=\"data()\"\n (buttonClick)=\"onCustomButtonClick(button)\">\n </core-generic-button>\n }\n } @else {\n @if (hasSteps()) {\n <!-- Botones para navegaci\u00F3n de steps -->\n <core-generic-button\n [config]=\"defaultCancelButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n @if (currentStepIndex() > 0) {\n <core-generic-button\n [config]=\"prevStepButtonConfig()\"\n (buttonClick)=\"goToPreviousStep()\">\n </core-generic-button>\n }\n <core-generic-button\n [config]=\"nextStepButtonConfig()\"\n (buttonClick)=\"goToNextStep()\">\n </core-generic-button>\n } @else {\n <!-- Botones normales para modales sin steps -->\n <core-generic-button\n [config]=\"defaultCancelButtonConfig()\"\n (buttonClick)=\"onClose()\">\n </core-generic-button>\n @if (mode() !== ModalMode.VIEW && showSaveButton()) {\n <core-generic-button\n [config]=\"defaultSaveButtonConfig()\"\n (buttonClick)=\"onSave()\">\n </core-generic-button>\n }\n }\n }\n </div>\n </div>\n</div>" }]
7596
7604
  }], ctorParameters: () => [] });
7597
7605
 
7598
7606
  class PaginationService {
@@ -7887,29 +7895,62 @@ class FileTemplateType {
7887
7895
  }
7888
7896
  }
7889
7897
 
7890
- // Safely extend dayjs with plugins (check if extend exists for Jest compatibility)
7891
- if (dayjs.extend) {
7892
- dayjs.extend(utc);
7893
- dayjs.extend(timezone);
7894
- }
7898
+ const utcPlugin = utc.default || utc;
7899
+ const tzPlugin = timezone.default || timezone;
7900
+ dayjs.extend(utcPlugin);
7901
+ dayjs.extend(tzPlugin);
7895
7902
  class DateUtility {
7903
+ static hasTz() {
7904
+ return typeof dayjs.tz === 'function';
7905
+ }
7906
+ static pad2(n) { return String(n).padStart(2, '0'); }
7907
+ static formatByPattern(d, pattern) {
7908
+ const dd = this.pad2(d.getUTCDate());
7909
+ const mm = this.pad2(d.getUTCMonth() + 1);
7910
+ const yyyy = d.getUTCFullYear();
7911
+ const HH = this.pad2(d.getUTCHours());
7912
+ const MM = this.pad2(d.getUTCMinutes());
7913
+ switch (pattern) {
7914
+ case 'DD/MM/YYYY HH:mm':
7915
+ return `${dd}/${mm}/${yyyy} ${HH}:${MM}`;
7916
+ case 'YYYY-MM-DD HH:mm':
7917
+ return `${yyyy}-${mm}-${dd} ${HH}:${MM}`;
7918
+ case 'YYYY-MM-DD':
7919
+ return `${yyyy}-${mm}-${dd}`;
7920
+ default:
7921
+ return d.toLocaleString();
7922
+ }
7923
+ }
7896
7924
  static fromUTCtoUruguay(date, outputFormat = 'DD/MM/YYYY HH:mm') {
7897
7925
  try {
7898
7926
  if (!date) {
7899
7927
  return '';
7900
7928
  }
7901
- let dayJsObj;
7902
- if (typeof date === 'string') {
7903
- dayJsObj = dayjs.utc(date);
7904
- }
7905
- else {
7906
- dayJsObj = dayjs.utc(date);
7929
+ const inputDate = new Date(date);
7930
+ if (isNaN(inputDate.getTime())) {
7931
+ console.error('Fecha inválida:', date);
7932
+ return '';
7907
7933
  }
7908
- return dayJsObj.tz('America/Montevideo').format(outputFormat);
7934
+ const offsetMs = 3 * 60 * 60 * 1000;
7935
+ const uyDate = new Date(inputDate.getTime() - offsetMs);
7936
+ return DateUtility.formatByPattern(uyDate, outputFormat);
7909
7937
  }
7910
7938
  catch (e) {
7911
7939
  console.error('Error al convertir fecha de UTC a Uruguay:', e);
7912
- return '';
7940
+ try {
7941
+ const d = typeof date === 'string' ? new Date(date) : date;
7942
+ if (!d || isNaN(d.getTime()))
7943
+ return '';
7944
+ const dd = String(d.getUTCDate()).padStart(2, '0');
7945
+ const mm = String(d.getUTCMonth() + 1).padStart(2, '0');
7946
+ const yyyy = d.getUTCFullYear();
7947
+ const hh = String(d.getUTCHours()).padStart(2, '0');
7948
+ const min = String(d.getUTCMinutes()).padStart(2, '0');
7949
+ return `${dd}/${mm}/${yyyy} ${hh}:${min}`;
7950
+ }
7951
+ catch {
7952
+ return '';
7953
+ }
7913
7954
  }
7914
7955
  }
7915
7956
  static fromUTCtoUruguayWithInputFormat(date, inputFormat, outputFormat = 'DD/MM/YYYY HH:mm') {
@@ -7917,27 +7958,39 @@ class DateUtility {
7917
7958
  if (!date) {
7918
7959
  return '';
7919
7960
  }
7920
- let dayJsObj;
7961
+ let inputDate = null;
7921
7962
  if (typeof date === 'string') {
7922
- if (inputFormat) {
7923
- dayJsObj = dayjs(date, inputFormat).utc();
7924
- if (!dayJsObj.isValid()) {
7963
+ if (inputFormat === 'DD-MM-YYYY HH:mm') {
7964
+ const [dpart, tpart] = date.split(' ');
7965
+ if (!dpart || !tpart) {
7966
+ console.error('Error al parsear fecha con formato personalizado:', date, inputFormat);
7967
+ return '';
7968
+ }
7969
+ const [d, m, y] = dpart.split('-').map(Number);
7970
+ const [hh, mm] = tpart.split(':').map(Number);
7971
+ if (!y || !m || !d) {
7925
7972
  console.error('Error al parsear fecha con formato personalizado:', date, inputFormat);
7926
7973
  return '';
7927
7974
  }
7975
+ // Interpret as UTC time then shift to Uruguay
7976
+ inputDate = new Date(Date.UTC(y, m - 1, d, hh, mm, 0));
7928
7977
  }
7929
7978
  else {
7930
- dayJsObj = dayjs.utc(date);
7979
+ // Fallback: ISO-like strings
7980
+ const tmp = new Date(date);
7981
+ if (isNaN(tmp.getTime())) {
7982
+ console.error('Fecha inválida:', date);
7983
+ return '';
7984
+ }
7985
+ inputDate = tmp;
7931
7986
  }
7932
7987
  }
7933
7988
  else {
7934
- dayJsObj = dayjs.utc(date);
7935
- }
7936
- if (!dayJsObj.isValid()) {
7937
- console.error('Fecha inválida:', date);
7938
- return '';
7989
+ inputDate = new Date(date.getTime());
7939
7990
  }
7940
- return dayJsObj.tz('America/Montevideo').format(outputFormat);
7991
+ const offsetMs = 3 * 60 * 60 * 1000;
7992
+ const uyDate = new Date(inputDate.getTime() - offsetMs);
7993
+ return DateUtility.formatByPattern(uyDate, outputFormat);
7941
7994
  }
7942
7995
  catch (e) {
7943
7996
  console.error('Error al convertir fecha de UTC a Uruguay con formato de entrada:', e);
@@ -7949,23 +8002,33 @@ class DateUtility {
7949
8002
  if (!date) {
7950
8003
  return null;
7951
8004
  }
7952
- let dayJsObj;
7953
- if (typeof date === 'string') {
7954
- dayJsObj = dayjs.utc(date);
7955
- }
7956
- else {
7957
- dayJsObj = dayjs.utc(date);
8005
+ const inputDate = new Date(date);
8006
+ if (isNaN(inputDate.getTime())) {
8007
+ console.error('Fecha inválida:', date);
8008
+ return null;
7958
8009
  }
7959
- return dayJsObj.tz('America/Montevideo').toDate();
8010
+ const offsetMs = 3 * 60 * 60 * 1000;
8011
+ return new Date(inputDate.getTime() - offsetMs);
7960
8012
  }
7961
8013
  catch (e) {
7962
8014
  console.error('Error al convertir fecha de UTC a Uruguay:', e);
7963
- return null;
8015
+ try {
8016
+ const d = typeof date === 'string' ? new Date(date) : date;
8017
+ if (!d || isNaN(d.getTime()))
8018
+ return null;
8019
+ return d;
8020
+ }
8021
+ catch {
8022
+ return null;
8023
+ }
7964
8024
  }
7965
8025
  }
7966
8026
  static getCurrentUruguayTime(outputFormat = 'DD/MM/YYYY HH:mm') {
7967
8027
  try {
7968
- return dayjs().tz('America/Montevideo').format(outputFormat);
8028
+ const now = new Date();
8029
+ const offsetMs = 3 * 60 * 60 * 1000; // UTC-3
8030
+ const uy = new Date(now.getTime() - offsetMs);
8031
+ return DateUtility.formatByPattern(uy, outputFormat);
7969
8032
  }
7970
8033
  catch (e) {
7971
8034
  console.error('Error al obtener fecha actual de Uruguay:', e);
@@ -7977,14 +8040,29 @@ class DateUtility {
7977
8040
  if (!date) {
7978
8041
  return '';
7979
8042
  }
7980
- let dayJsObj;
8043
+ let inputDate = null;
7981
8044
  if (typeof date === 'string') {
7982
- dayJsObj = dayjs.tz(date, 'America/Montevideo');
8045
+ const parts = date.split('T');
8046
+ if (parts.length >= 2) {
8047
+ const [y, m, d] = parts[0].split('-').map(Number);
8048
+ const [hh, mm, ss] = parts[1].split(':').map(Number);
8049
+ inputDate = new Date(Date.UTC(y, m - 1, d, hh ?? 0, mm ?? 0, ss ?? 0));
8050
+ }
8051
+ else {
8052
+ const tmp = new Date(date);
8053
+ if (isNaN(tmp.getTime())) {
8054
+ console.error('Fecha inválida:', date);
8055
+ return '';
8056
+ }
8057
+ inputDate = tmp;
8058
+ }
7983
8059
  }
7984
8060
  else {
7985
- dayJsObj = dayjs.tz(date, 'America/Montevideo');
8061
+ inputDate = new Date(date.getTime());
7986
8062
  }
7987
- return dayJsObj.utc().format(outputFormat);
8063
+ const offsetMs = 3 * 60 * 60 * 1000;
8064
+ const utcDate = new Date(inputDate.getTime() + offsetMs);
8065
+ return DateUtility.formatByPattern(utcDate, outputFormat);
7988
8066
  }
7989
8067
  catch (e) {
7990
8068
  console.error('Error al convertir fecha de Uruguay a UTC:', e);
@@ -7996,15 +8074,21 @@ class DateUtility {
7996
8074
  if (!date1 || !date2) {
7997
8075
  return false;
7998
8076
  }
7999
- const uruguayDate1 = this.fromUTCtoUruguayDate(date1);
8000
- const uruguayDate2 = this.fromUTCtoUruguayDate(date2);
8001
- if (!uruguayDate1 || !uruguayDate2) {
8077
+ const d1 = new Date(date1);
8078
+ const d2 = new Date(date2);
8079
+ if (isNaN(d1.getTime()) || isNaN(d2.getTime())) {
8080
+ console.error('Fechas inválidas para comparación en Uruguay:', date1, date2);
8002
8081
  return false;
8003
8082
  }
8004
- return dayjs.tz(uruguayDate1, 'America/Montevideo').isSame(dayjs.tz(uruguayDate2, 'America/Montevideo'), 'day');
8083
+ const offsetMs = 3 * 60 * 60 * 1000;
8084
+ const d1Uy = new Date(d1.getTime() - offsetMs);
8085
+ const d2Uy = new Date(d2.getTime() - offsetMs);
8086
+ return (d1Uy.getUTCFullYear() === d2Uy.getUTCFullYear() &&
8087
+ d1Uy.getUTCMonth() === d2Uy.getUTCMonth() &&
8088
+ d1Uy.getUTCDate() === d2Uy.getUTCDate());
8005
8089
  }
8006
- catch (e) {
8007
- console.error('Error al comparar fechas en Uruguay:', e);
8090
+ catch (err) {
8091
+ console.error('Error al comparar fechas en Uruguay:', err);
8008
8092
  return false;
8009
8093
  }
8010
8094
  }
@@ -16007,12 +16091,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
16007
16091
  // Este archivo es generado automáticamente por scripts/update-version.js
16008
16092
  // No edites manualmente este archivo
16009
16093
  const VERSION = {
16010
- full: '2.15.27',
16094
+ full: '2.15.29',
16011
16095
  major: 2,
16012
16096
  minor: 15,
16013
- patch: 27,
16014
- timestamp: '2025-10-28T15:03:19.976Z',
16015
- buildDate: '28/10/2025'
16097
+ patch: 29,
16098
+ timestamp: '2025-11-06T15:29:21.774Z',
16099
+ buildDate: '6/11/2025'
16016
16100
  };
16017
16101
 
16018
16102
  class MainNavComponent {
@@ -16927,7 +17011,6 @@ class CustomClassService {
16927
17011
  this.rendererFactory = rendererFactory;
16928
17012
  this.dataStore = dataStore;
16929
17013
  this.renderer = this.rendererFactory.createRenderer(null, null);
16930
- // Initialize the store
16931
17014
  this.dataStore.hydrate(this.STORE_KEY, []);
16932
17015
  }
16933
17016
  ngOnDestroy() {
@@ -17024,9 +17107,7 @@ class CustomClassService {
17024
17107
  }
17025
17108
  const classes = Array.isArray(classNames) ? classNames : [classNames];
17026
17109
  elements.forEach(element => {
17027
- // Clear all existing classes
17028
17110
  element.className = '';
17029
- // Add new classes
17030
17111
  classes.forEach(className => {
17031
17112
  if (className && className.trim()) {
17032
17113
  this.renderer.addClass(element, className.trim());
@@ -17038,7 +17119,6 @@ class CustomClassService {
17038
17119
  }
17039
17120
  resolveElements(target, parent) {
17040
17121
  let searchContext = document;
17041
- // Resolve parent context if provided
17042
17122
  if (parent) {
17043
17123
  if (parent instanceof ElementRef) {
17044
17124
  searchContext = parent.nativeElement;
@@ -17056,41 +17136,32 @@ class CustomClassService {
17056
17136
  }
17057
17137
  }
17058
17138
  }
17059
- // ElementRef from ViewChild
17060
17139
  if (target instanceof ElementRef) {
17061
17140
  const element = target.nativeElement;
17062
- // If parent is specified, check if element is within parent
17063
17141
  if (parent && searchContext !== document) {
17064
17142
  return searchContext.contains(element) ? [element] : [];
17065
17143
  }
17066
17144
  return [element];
17067
17145
  }
17068
- // Direct HTMLElement
17069
17146
  if (target instanceof HTMLElement) {
17070
- // If parent is specified, check if element is within parent
17071
17147
  if (parent && searchContext !== document) {
17072
17148
  return searchContext.contains(target) ? [target] : [];
17073
17149
  }
17074
17150
  return [target];
17075
17151
  }
17076
- // NodeList or HTMLCollection
17077
17152
  if (target instanceof NodeList || target instanceof HTMLCollection) {
17078
17153
  const elements = Array.from(target);
17079
- // Filter by parent if specified
17080
17154
  if (parent && searchContext !== document) {
17081
17155
  return elements.filter(el => searchContext.contains(el));
17082
17156
  }
17083
17157
  return elements;
17084
17158
  }
17085
- // CSS Selector string
17086
17159
  if (typeof target === 'string') {
17087
17160
  const elements = searchContext.querySelectorAll(target);
17088
17161
  return Array.from(elements);
17089
17162
  }
17090
- // If it has a nativeElement property (custom wrapper)
17091
17163
  if (target && target.nativeElement instanceof HTMLElement) {
17092
17164
  const element = target.nativeElement;
17093
- // If parent is specified, check if element is within parent
17094
17165
  if (parent && searchContext !== document) {
17095
17166
  return searchContext.contains(element) ? [element] : [];
17096
17167
  }
@@ -18380,10 +18451,17 @@ class FilePreviewService {
18380
18451
  truncateFilename(filename, maxLength = 30) {
18381
18452
  if (filename.length <= maxLength)
18382
18453
  return filename;
18383
- const extension = filename.split('.').pop() || '';
18384
- const nameWithoutExtension = filename.substring(0, filename.lastIndexOf('.')) || filename;
18385
- const truncatedName = nameWithoutExtension.substring(0, maxLength - extension.length - 4) + '...';
18386
- return extension ? `${truncatedName}.${extension}` : truncatedName;
18454
+ const lastDotIndex = filename.lastIndexOf('.');
18455
+ const hasExtension = lastDotIndex > 0;
18456
+ if (hasExtension) {
18457
+ const extension = filename.substring(lastDotIndex + 1);
18458
+ const nameWithoutExtension = filename.substring(0, lastDotIndex);
18459
+ const truncatedName = nameWithoutExtension.substring(0, maxLength - extension.length - 4) + '...';
18460
+ return `${truncatedName}.${extension}`;
18461
+ }
18462
+ else {
18463
+ return filename.substring(0, maxLength - 3) + '...';
18464
+ }
18387
18465
  }
18388
18466
  isImage(contentType) {
18389
18467
  const result = getFilePreviewType(contentType) === FilePreviewType.IMAGE;
@@ -18394,13 +18472,6 @@ class FilePreviewService {
18394
18472
  return null;
18395
18473
  return null;
18396
18474
  }
18397
- /**
18398
- * Genera una vista previa real de la imagen desde S3
18399
- * @param file FilePreviewItem con los datos del archivo
18400
- * @param maxWidth Ancho máximo de la vista previa (default: 300px)
18401
- * @param maxHeight Alto máximo de la vista previa (default: 200px)
18402
- * @returns Observable<string> con la imagen en formato base64 o null si hay error
18403
- */
18404
18475
  generateImagePreview(file, maxWidth = 300, maxHeight = 200) {
18405
18476
  if (!this.isImage(file.contentType) || !file.s3Key) {
18406
18477
  return of(null);
@@ -18819,14 +18890,9 @@ class GenericChatComponent {
18819
18890
  if (!file) {
18820
18891
  return null;
18821
18892
  }
18822
- // Para archivos de imagen, intentar obtener URL en este orden de prioridad:
18823
- // 1. thumbnailUrl (URL optimizada para preview)
18824
- // 2. url (URL principal del archivo)
18825
- // 3. src (URL alternativa)
18826
18893
  if (this.isImageFilePreview(file)) {
18827
18894
  return file.thumbnailUrl || file.url || file.src || null;
18828
18895
  }
18829
- // Para archivos no imagen, usar URL principal
18830
18896
  return file.url || file.src || null;
18831
18897
  }
18832
18898
  getAttachmentPlaceholderUrl(file) {