@solcre-org/core-ui 2.15.30 → 2.15.32

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.
@@ -4984,9 +4984,11 @@ class MultiEntryFieldComponent {
4984
4984
  valueChange = output();
4985
4985
  onBlurEvent = output();
4986
4986
  onEnterEvent = output();
4987
+ hasErrors = output();
4987
4988
  ModalMode = ModalMode;
4988
4989
  entries = signal([]);
4989
4990
  fieldValues = signal([]);
4991
+ entryErrors = signal(new Map());
4990
4992
  isSyncingFromInput = signal(false);
4991
4993
  lastInputSignature = null;
4992
4994
  lastEmittedSignature = null;
@@ -5087,6 +5089,11 @@ class MultiEntryFieldComponent {
5087
5089
  if (matchesLastEmitted) {
5088
5090
  this.lastEmittedSignature = signature;
5089
5091
  }
5092
+ newEntries.forEach((entry, index) => {
5093
+ if (entry.value !== null && entry.value !== undefined && entry.value !== '') {
5094
+ this.validateEntry(entry.value, index);
5095
+ }
5096
+ });
5090
5097
  }
5091
5098
  finally {
5092
5099
  this.isSyncingFromInput.set(false);
@@ -5116,6 +5123,18 @@ class MultiEntryFieldComponent {
5116
5123
  const newValues = currentValues.filter((_, i) => i !== index);
5117
5124
  this.entries.set(newEntries);
5118
5125
  this.fieldValues.set(newValues);
5126
+ const currentErrors = new Map(this.entryErrors());
5127
+ const newErrors = new Map();
5128
+ currentErrors.forEach((errors, idx) => {
5129
+ if (idx < index) {
5130
+ newErrors.set(idx, errors);
5131
+ }
5132
+ else if (idx > index) {
5133
+ newErrors.set(idx - 1, errors);
5134
+ }
5135
+ });
5136
+ this.entryErrors.set(newErrors);
5137
+ this.hasErrors.emit(newErrors.size > 0);
5119
5138
  }
5120
5139
  }
5121
5140
  onFieldValueChange(value, index) {
@@ -5125,6 +5144,43 @@ class MultiEntryFieldComponent {
5125
5144
  const currentEntries = [...this.entries()];
5126
5145
  currentEntries[index].value = value;
5127
5146
  this.entries.set(currentEntries);
5147
+ this.validateEntry(value, index);
5148
+ }
5149
+ validateEntry(value, index) {
5150
+ const validators = this.getCurrentValidators();
5151
+ const errors = [];
5152
+ for (const validator of validators) {
5153
+ const control = { value };
5154
+ const validationResult = validator(control);
5155
+ if (validationResult) {
5156
+ const errorKeys = Object.keys(validationResult);
5157
+ const baseField = this.field();
5158
+ for (const errorKey of errorKeys) {
5159
+ const errorMessage = baseField.errorMessages?.[errorKey];
5160
+ if (errorMessage) {
5161
+ errors.push(errorMessage);
5162
+ }
5163
+ else {
5164
+ errors.push(`Validation error: ${errorKey}`);
5165
+ }
5166
+ }
5167
+ }
5168
+ }
5169
+ const currentErrors = new Map(this.entryErrors());
5170
+ if (errors.length > 0) {
5171
+ currentErrors.set(index, errors);
5172
+ }
5173
+ else {
5174
+ currentErrors.delete(index);
5175
+ }
5176
+ this.entryErrors.set(currentErrors);
5177
+ this.hasErrors.emit(currentErrors.size > 0);
5178
+ }
5179
+ getEntryErrors(index) {
5180
+ return this.entryErrors().get(index) || [];
5181
+ }
5182
+ hasAnyErrors() {
5183
+ return this.entryErrors().size > 0;
5128
5184
  }
5129
5185
  onFieldBlur(fieldKey) {
5130
5186
  this.onBlurEvent.emit(fieldKey);
@@ -5217,7 +5273,7 @@ class MultiEntryFieldComponent {
5217
5273
  }
5218
5274
  }
5219
5275
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: MultiEntryFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5220
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: MultiEntryFieldComponent, isStandalone: true, selector: "core-multi-entry-field", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, rowData: { classPropertyName: "rowData", publicName: "rowData", isSignal: true, isRequired: false, transformFunction: null }, formValue: { classPropertyName: "formValue", publicName: "formValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", onBlurEvent: "onBlurEvent", onEnterEvent: "onEnterEvent" }, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<div class=\"c-entry-group\">\n @for (entry of entries(); track entry.id; let index = $index) {\n <div class=\"c-entry-item\">\n <!-- Campo din\u00E1mico para cada entrada -->\n <div\n coreDynamicField\n [field]=\"createFieldConfigForEntry(index)\"\n [value]=\"entry.value\"\n [mode]=\"mode()\"\n [errors]=\"errors()\"\n [rowData]=\"rowData()\"\n [formValue]=\"formValue()\"\n (valueChange)=\"onFieldValueChange($event, index)\"\n (onBlurEvent)=\"onFieldBlur($event)\"\n (onEnterEvent)=\"onFieldEnter($event)\">\n </div>\n\n <!-- Botones de acci\u00F3n (agregar/eliminar) -->\n @if (shouldShowActions(index)) {\n <div class=\"c-entry-actions\">\n @if (shouldShowAddButton(index)) {\n <button \n type=\"button\"\n class=\"c-entry-action c-entry-action--add\"\n (click)=\"addEntry()\"\n [disabled]=\"isDisabled()\"\n [title]=\"addLabel() | translate\"\n [attr.aria-label]=\"addLabel() | translate\">\n <span class=\"icon-counter-up\"></span>\n {{ addLabel() | translate }}\n </button>\n }\n \n @if (shouldShowRemoveButton(index)) {\n <button \n type=\"button\"\n class=\"c-entry-action c-entry-action--remove\"\n (click)=\"removeEntry(index)\"\n [disabled]=\"isDisabled()\"\n [title]=\"removeLabel() | translate\"\n [attr.aria-label]=\"removeLabel() | translate\">\n <span class=\"icon-counter-down\"></span>\n {{ removeLabel() | translate }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- Errores del campo principal -->\n @if (errors().length > 0) {\n <core-field-errors [errors]=\"errors()\"></core-field-errors>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: FieldErrorsComponent, selector: "core-field-errors", inputs: ["errors"] }] });
5276
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: MultiEntryFieldComponent, isStandalone: true, selector: "core-multi-entry-field", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, rowData: { classPropertyName: "rowData", publicName: "rowData", isSignal: true, isRequired: false, transformFunction: null }, formValue: { classPropertyName: "formValue", publicName: "formValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", onBlurEvent: "onBlurEvent", onEnterEvent: "onEnterEvent", hasErrors: "hasErrors" }, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<div class=\"c-entry-group\">\n @for (entry of entries(); track entry.id; let index = $index) {\n <div class=\"c-entry-item\">\n <!-- Campo din\u00E1mico para cada entrada -->\n <div\n coreDynamicField\n [field]=\"createFieldConfigForEntry(index)\"\n [value]=\"entry.value\"\n [mode]=\"mode()\"\n [errors]=\"getEntryErrors(index)\"\n [rowData]=\"rowData()\"\n [formValue]=\"formValue()\"\n (valueChange)=\"onFieldValueChange($event, index)\"\n (onBlurEvent)=\"onFieldBlur($event)\"\n (onEnterEvent)=\"onFieldEnter($event)\">\n </div>\n\n <!-- Botones de acci\u00F3n (agregar/eliminar) -->\n @if (shouldShowActions(index)) {\n <div class=\"c-entry-actions\">\n @if (shouldShowAddButton(index)) {\n <button \n type=\"button\"\n class=\"c-entry-action c-entry-action--add\"\n (click)=\"addEntry()\"\n [disabled]=\"isDisabled()\"\n [title]=\"addLabel() | translate\"\n [attr.aria-label]=\"addLabel() | translate\">\n <span class=\"icon-counter-up\"></span>\n {{ addLabel() | translate }}\n </button>\n }\n \n @if (shouldShowRemoveButton(index)) {\n <button \n type=\"button\"\n class=\"c-entry-action c-entry-action--remove\"\n (click)=\"removeEntry(index)\"\n [disabled]=\"isDisabled()\"\n [title]=\"removeLabel() | translate\"\n [attr.aria-label]=\"removeLabel() | translate\">\n <span class=\"icon-counter-down\"></span>\n {{ removeLabel() | translate }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- Errores del campo principal (solo si hay errores globales) -->\n @if (errors().length > 0) {\n <core-field-errors [errors]=\"errors()\"></core-field-errors>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: FieldErrorsComponent, selector: "core-field-errors", inputs: ["errors"] }] });
5221
5277
  }
5222
5278
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: MultiEntryFieldComponent, decorators: [{
5223
5279
  type: Component,
@@ -5228,7 +5284,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
5228
5284
  TranslateModule,
5229
5285
  DynamicFieldDirective,
5230
5286
  FieldErrorsComponent
5231
- ], hostDirectives: [CoreHostDirective], template: "<div class=\"c-entry-group\">\n @for (entry of entries(); track entry.id; let index = $index) {\n <div class=\"c-entry-item\">\n <!-- Campo din\u00E1mico para cada entrada -->\n <div\n coreDynamicField\n [field]=\"createFieldConfigForEntry(index)\"\n [value]=\"entry.value\"\n [mode]=\"mode()\"\n [errors]=\"errors()\"\n [rowData]=\"rowData()\"\n [formValue]=\"formValue()\"\n (valueChange)=\"onFieldValueChange($event, index)\"\n (onBlurEvent)=\"onFieldBlur($event)\"\n (onEnterEvent)=\"onFieldEnter($event)\">\n </div>\n\n <!-- Botones de acci\u00F3n (agregar/eliminar) -->\n @if (shouldShowActions(index)) {\n <div class=\"c-entry-actions\">\n @if (shouldShowAddButton(index)) {\n <button \n type=\"button\"\n class=\"c-entry-action c-entry-action--add\"\n (click)=\"addEntry()\"\n [disabled]=\"isDisabled()\"\n [title]=\"addLabel() | translate\"\n [attr.aria-label]=\"addLabel() | translate\">\n <span class=\"icon-counter-up\"></span>\n {{ addLabel() | translate }}\n </button>\n }\n \n @if (shouldShowRemoveButton(index)) {\n <button \n type=\"button\"\n class=\"c-entry-action c-entry-action--remove\"\n (click)=\"removeEntry(index)\"\n [disabled]=\"isDisabled()\"\n [title]=\"removeLabel() | translate\"\n [attr.aria-label]=\"removeLabel() | translate\">\n <span class=\"icon-counter-down\"></span>\n {{ removeLabel() | translate }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- Errores del campo principal -->\n @if (errors().length > 0) {\n <core-field-errors [errors]=\"errors()\"></core-field-errors>\n }\n</div>\n" }]
5287
+ ], hostDirectives: [CoreHostDirective], template: "<div class=\"c-entry-group\">\n @for (entry of entries(); track entry.id; let index = $index) {\n <div class=\"c-entry-item\">\n <!-- Campo din\u00E1mico para cada entrada -->\n <div\n coreDynamicField\n [field]=\"createFieldConfigForEntry(index)\"\n [value]=\"entry.value\"\n [mode]=\"mode()\"\n [errors]=\"getEntryErrors(index)\"\n [rowData]=\"rowData()\"\n [formValue]=\"formValue()\"\n (valueChange)=\"onFieldValueChange($event, index)\"\n (onBlurEvent)=\"onFieldBlur($event)\"\n (onEnterEvent)=\"onFieldEnter($event)\">\n </div>\n\n <!-- Botones de acci\u00F3n (agregar/eliminar) -->\n @if (shouldShowActions(index)) {\n <div class=\"c-entry-actions\">\n @if (shouldShowAddButton(index)) {\n <button \n type=\"button\"\n class=\"c-entry-action c-entry-action--add\"\n (click)=\"addEntry()\"\n [disabled]=\"isDisabled()\"\n [title]=\"addLabel() | translate\"\n [attr.aria-label]=\"addLabel() | translate\">\n <span class=\"icon-counter-up\"></span>\n {{ addLabel() | translate }}\n </button>\n }\n \n @if (shouldShowRemoveButton(index)) {\n <button \n type=\"button\"\n class=\"c-entry-action c-entry-action--remove\"\n (click)=\"removeEntry(index)\"\n [disabled]=\"isDisabled()\"\n [title]=\"removeLabel() | translate\"\n [attr.aria-label]=\"removeLabel() | translate\">\n <span class=\"icon-counter-down\"></span>\n {{ removeLabel() | translate }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- Errores del campo principal (solo si hay errores globales) -->\n @if (errors().length > 0) {\n <core-field-errors [errors]=\"errors()\"></core-field-errors>\n }\n</div>\n" }]
5232
5288
  }], ctorParameters: () => [] });
5233
5289
 
5234
5290
  class SmartFieldComponent {
@@ -5276,7 +5332,7 @@ class SmartFieldComponent {
5276
5332
  (selectionChange)="selectionChange.emit($event)">
5277
5333
  </div>
5278
5334
  }
5279
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "directive", type: DynamicFieldDirective, selector: "[coreDynamicField]", inputs: ["field", "value", "mode", "errors", "rowData", "formValue"], outputs: ["valueChange", "onBlurEvent", "onEnterEvent", "selectionChange"] }, { kind: "component", type: MultiEntryFieldComponent, selector: "core-multi-entry-field", inputs: ["field", "value", "mode", "errors", "rowData", "formValue"], outputs: ["valueChange", "onBlurEvent", "onEnterEvent"] }] });
5335
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "directive", type: DynamicFieldDirective, selector: "[coreDynamicField]", inputs: ["field", "value", "mode", "errors", "rowData", "formValue"], outputs: ["valueChange", "onBlurEvent", "onEnterEvent", "selectionChange"] }, { kind: "component", type: MultiEntryFieldComponent, selector: "core-multi-entry-field", inputs: ["field", "value", "mode", "errors", "rowData", "formValue"], outputs: ["valueChange", "onBlurEvent", "onEnterEvent", "hasErrors"] }] });
5280
5336
  }
5281
5337
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SmartFieldComponent, decorators: [{
5282
5338
  type: Component,
@@ -5545,7 +5601,7 @@ class PermissionService {
5545
5601
  getUser() {
5546
5602
  return this.userSubject.value;
5547
5603
  }
5548
- hasPermission(resource, action) {
5604
+ hasPermission(resource, action, custom_action) {
5549
5605
  const user = this.userSubject.value;
5550
5606
  if (!user || !user.roles) {
5551
5607
  return false;
@@ -5553,13 +5609,48 @@ class PermissionService {
5553
5609
  if (user.roles.some(role => !role.permissions)) {
5554
5610
  return true;
5555
5611
  }
5556
- const hasPermission = user.roles.some(role => role.permissions?.some(perm => {
5557
- const matches = perm.resource === resource && perm.action === action && perm.is_active;
5558
- if (matches) {
5559
- }
5560
- return matches;
5561
- }));
5562
- return hasPermission;
5612
+ if (custom_action) {
5613
+ console.log('🔍 Checking custom_action permission:', {
5614
+ custom_action,
5615
+ action,
5616
+ userRoles: user.roles?.map(role => ({
5617
+ name: role.name,
5618
+ permissions: role.permissions?.map(p => ({
5619
+ custom_action: p.custom_action,
5620
+ action: p.action,
5621
+ is_active: p.is_active
5622
+ }))
5623
+ }))
5624
+ });
5625
+ const hasPermission = user.roles.some(role => role.permissions?.some(perm => {
5626
+ // Normalizar null a undefined para comparación
5627
+ const permCustomAction = perm.custom_action ?? undefined;
5628
+ const matches = permCustomAction === custom_action && perm.action === action && perm.is_active;
5629
+ if (perm.custom_action || perm.action === action) {
5630
+ console.log('🔎 Comparing permission:', {
5631
+ perm_custom_action: permCustomAction,
5632
+ expected_custom_action: custom_action,
5633
+ perm_action: perm.action,
5634
+ expected_action: action,
5635
+ is_active: perm.is_active,
5636
+ matches
5637
+ });
5638
+ }
5639
+ return matches;
5640
+ }));
5641
+ console.log('🎯 Final result:', hasPermission);
5642
+ return hasPermission;
5643
+ }
5644
+ if (resource) {
5645
+ const hasPermission = user.roles.some(role => role.permissions?.some(perm => {
5646
+ const matches = perm.resource === resource && perm.action === action && perm.is_active;
5647
+ if (matches) {
5648
+ }
5649
+ return matches;
5650
+ }));
5651
+ return hasPermission;
5652
+ }
5653
+ return false;
5563
5654
  }
5564
5655
  hasAnyPermission(resources, action) {
5565
5656
  return resources.some(resource => this.hasPermission(resource, action));
@@ -5608,18 +5699,6 @@ var PermissionsResources;
5608
5699
  PermissionsResources["MY_COMPANY_TELEWORK"] = "my_company_remote_work";
5609
5700
  PermissionsResources["FILE_TEMPLATES"] = "file_templates";
5610
5701
  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";
5623
5702
  })(PermissionsResources || (PermissionsResources = {}));
5624
5703
 
5625
5704
  class PermissionWrapperService {
@@ -5749,8 +5828,9 @@ class PermissionWrapperService {
5749
5828
  }
5750
5829
  });
5751
5830
  }
5752
- hasPermission(resource, action) {
5753
- return this.activeProvider.hasPermission(resource, action);
5831
+ hasPermission(resource, action, custom_action) {
5832
+ const result = this.activeProvider.hasPermission(resource, action, custom_action);
5833
+ return result;
5754
5834
  }
5755
5835
  setUser(user) {
5756
5836
  this.activeProvider.setUser(user);
@@ -5813,7 +5893,9 @@ class GenericButtonComponent {
5813
5893
  if (this.config().loading)
5814
5894
  return true;
5815
5895
  if (this.config().requiredPermission) {
5816
- return !this.permissionService.hasPermission(this.config().requiredPermission.resource, this.config().requiredPermission.action);
5896
+ const perm = this.config().requiredPermission;
5897
+ const hasPermission = this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
5898
+ return !hasPermission;
5817
5899
  }
5818
5900
  return false;
5819
5901
  });
@@ -7704,13 +7786,15 @@ class PermissionModel {
7704
7786
  resource;
7705
7787
  action;
7706
7788
  is_active;
7707
- constructor(id, name, description, resource, action, is_active) {
7789
+ custom_action;
7790
+ constructor(id, name, description, resource, action, is_active, custom_action) {
7708
7791
  this.id = id;
7709
7792
  this.name = name;
7710
7793
  this.description = description;
7711
7794
  this.resource = resource;
7712
7795
  this.action = action;
7713
7796
  this.is_active = is_active;
7797
+ this.custom_action = custom_action;
7714
7798
  }
7715
7799
  fromJSON(json) {
7716
7800
  if (json) {
@@ -7720,6 +7804,7 @@ class PermissionModel {
7720
7804
  this.resource = json.resource;
7721
7805
  this.action = json.action;
7722
7806
  this.is_active = json.is_active;
7807
+ this.custom_action = json.custom_action;
7723
7808
  }
7724
7809
  return this;
7725
7810
  }
@@ -7737,6 +7822,7 @@ class PermissionModel {
7737
7822
  "resource": this.resource,
7738
7823
  "action": this.action,
7739
7824
  "is_active": this.is_active,
7825
+ "custom_action": this.custom_action,
7740
7826
  };
7741
7827
  }
7742
7828
  getId() {
@@ -12591,7 +12677,7 @@ class GenericTableComponent {
12591
12677
  const createAction = this.actions().find(a => a.action === TableAction.CREATE);
12592
12678
  if (createAction && createAction.mobileConfig?.showInsideModal !== false && !this.getMobileShowInHeader(createAction) && !this.getMobileShowOutsideFixedActions(createAction)) {
12593
12679
  if (!createAction.requiredPermission ||
12594
- this.permissionService.hasPermission(createAction.requiredPermission.resource, createAction.requiredPermission.action)) {
12680
+ this.permissionService.hasPermission(createAction.requiredPermission.resource, createAction.requiredPermission.action, createAction.requiredPermission.custom_action)) {
12595
12681
  modalActions.push({
12596
12682
  icon: createAction.icon || this.getDefaultIconForAction(TableAction.CREATE),
12597
12683
  label: this.getActionLabel(TableAction.CREATE),
@@ -13323,7 +13409,7 @@ class GenericTableComponent {
13323
13409
  }
13324
13410
  shouldShowFixedAction(action) {
13325
13411
  if (action.requiredPermission) {
13326
- const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action);
13412
+ const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
13327
13413
  if (!hasPermission)
13328
13414
  return false;
13329
13415
  }
@@ -13332,7 +13418,7 @@ class GenericTableComponent {
13332
13418
  return action.shouldShow(selectedRow);
13333
13419
  }
13334
13420
  if (action.customAction?.requiredPermission) {
13335
- const hasPermission = this.permissionService.hasPermission(action.customAction.requiredPermission.resource, action.customAction.requiredPermission.action);
13421
+ const hasPermission = this.permissionService.hasPermission(action.customAction.requiredPermission.resource, action.customAction.requiredPermission.action, action.customAction.requiredPermission.custom_action);
13336
13422
  if (!hasPermission)
13337
13423
  return false;
13338
13424
  }
@@ -13343,7 +13429,7 @@ class GenericTableComponent {
13343
13429
  }
13344
13430
  }
13345
13431
  if (action.globalAction?.requiredPermission) {
13346
- const hasPermission = this.permissionService.hasPermission(action.globalAction.requiredPermission.resource, action.globalAction.requiredPermission.action);
13432
+ const hasPermission = this.permissionService.hasPermission(action.globalAction.requiredPermission.resource, action.globalAction.requiredPermission.action, action.globalAction.requiredPermission.custom_action);
13347
13433
  if (!hasPermission)
13348
13434
  return false;
13349
13435
  }
@@ -13582,7 +13668,7 @@ class GenericTableComponent {
13582
13668
  hasPermission(action) {
13583
13669
  if (!action.requiredPermission)
13584
13670
  return true;
13585
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action);
13671
+ return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
13586
13672
  }
13587
13673
  showFiltersPopup() {
13588
13674
  this.isFilterModalOpen.set(true);
@@ -15864,7 +15950,7 @@ class HeaderComponent {
15864
15950
  hasPermission(action) {
15865
15951
  if (!action.requiredPermission)
15866
15952
  return true;
15867
- const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action);
15953
+ const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
15868
15954
  if (!hasPermission)
15869
15955
  return false;
15870
15956
  const isMobile = this.mobileResolutionService.isMobile();
@@ -15894,7 +15980,7 @@ class HeaderComponent {
15894
15980
  hasCustomActionPermission(action) {
15895
15981
  if (!action.requiredPermission)
15896
15982
  return true;
15897
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action);
15983
+ return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
15898
15984
  }
15899
15985
  isCustomActionVisible(action) {
15900
15986
  if (action.visible === false)
@@ -15939,7 +16025,7 @@ class HeaderComponent {
15939
16025
  return false;
15940
16026
  if (!action.requiredPermission)
15941
16027
  return true;
15942
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action);
16028
+ return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
15943
16029
  }
15944
16030
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
15945
16031
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: HeaderComponent, isStandalone: true, selector: "core-header", outputs: { filterRequested: "filterRequested", createRequested: "createRequested", globalActionTriggered: "globalActionTriggered" }, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "@if (headerService.getIsVisible()()) {\n @if(!headerService.getHeaderOutside()()) {\n <div class=\"c-header\">\n <div class=\"c-header__row\">\n\n <div class=\"c-header__group\">\n\n <h2 class=\"c-header__heading u-heading\">{{ getHeaderTitle() }}</h2>\n\n </div>\n\n <div class=\"c-header__group u-flex\">\n\n @for (element of headerService.getOrderedElements(); track element.type + '-' + (element.actionId || $index)) {\n @if (headerService.isElementVisible(element.type, element)) {\n \n @switch (element.type) {\n @case (HeaderElementType.GLOBAL_ACTIONS) {\n @for (globalAction of headerService.getGlobalActions()(); track globalAction.label || $index) {\n @if (hasPermission(globalAction)) {\n @if (globalAction.isSwitch && globalAction.switchOptions) {\n <core-generic-switch\n [options]=\"globalAction.switchOptions\"\n [selectedValue]=\"globalAction.switchSelectedValue\"\n [ariaLabel]=\"globalAction.switchAriaLabel || globalAction.label || 'Switch options'\"\n (valueChange)=\"onGlobalSwitchChange($event, globalAction)\">\n </core-generic-switch>\n } @else {\n <core-generic-button \n [config]=\"getGlobalActionButtonConfig(globalAction)\"\n (buttonClick)=\"onGlobalButtonClick($event, globalAction)\">\n </core-generic-button>\n }\n }\n }\n }\n \n @case (HeaderElementType.CUSTOM_ACTIONS) {\n @for (customAction of headerService.getCustomActions()(); track customAction.id) {\n @if (isCustomActionVisible(customAction)) {\n <core-generic-button \n [config]=\"getCustomActionButtonConfig(customAction)\"\n (buttonClick)=\"onCustomButtonClick($event, customAction)\">\n </core-generic-button>\n }\n }\n }\n \n @case (HeaderElementType.FILTER) {\n <core-generic-button \n [config]=\"getFilterButtonConfig()\"\n (buttonClick)=\"onFilterButtonClick()\">\n </core-generic-button>\n }\n \n @case (HeaderElementType.CREATE) {\n <core-generic-button \n [config]=\"getCreateButtonConfig()\"\n (buttonClick)=\"onCreateButtonClick()\">\n </core-generic-button>\n }\n\n @case (HeaderElementType.INDIVIDUAL_ACTION) {\n @if (getIndividualAction(element); as action) {\n @if (hasIndividualActionPermission(action)) {\n @if (isIndividualActionSwitch(action)) {\n <core-generic-switch\n [options]=\"action.switchOptions\"\n [selectedValue]=\"action.switchSelectedValue\"\n [ariaLabel]=\"action.switchAriaLabel || action.label || 'Switch options'\"\n (valueChange)=\"onGlobalSwitchChange($event, action)\">\n </core-generic-switch>\n } @else if (element.actionType === 'global') {\n <core-generic-button \n [config]=\"getGlobalActionButtonConfig(action)\"\n (buttonClick)=\"onGlobalButtonClick($event, action)\">\n </core-generic-button>\n } @else if (element.actionType === 'custom') {\n <core-generic-button \n [config]=\"getCustomActionButtonConfig(action)\"\n (buttonClick)=\"onCustomButtonClick($event, action)\">\n </core-generic-button>\n }\n }\n }\n }\n }\n \n }\n }\n\n </div>\n\n </div>\n\n <p class=\"c-header__text u-text\" *ngIf=\"getHeaderText()\">\n {{ getHeaderText() }}\n </p>\n\n @if (\n headerService.isElementVisible(HeaderElementType.CUSTOM_TEMPLATE) && \n headerService.getCustomTemplate()()\n ) {\n <ng-container [ngTemplateOutlet]=\"headerService.getCustomTemplate()()\"></ng-container>\n }\n </div>\n } @else {\n @if(\n headerService.isElementVisible(HeaderElementType.CUSTOM_TEMPLATE) && \n headerService.getCustomTemplate()()\n ) {\n <ng-container [ngTemplateOutlet]=\"headerService.getCustomTemplate()()\"></ng-container>\n }\n }\n}", styles: [":root{--header-bg: #ffffff;--header-text: #333;--header-shadow: rgba(0, 0, 0, .1);--logout-btn-color: #e74c3c;--logout-btn-hover: #c0392b;--theme-btn-color: #666;--theme-btn-hover: #007bff}.dark-mode{--header-bg: #1a1a1a;--header-text: #e0e0e0;--header-shadow: rgba(255, 255, 255, .1);--logout-btn-color: #ff6b6b;--logout-btn-hover: #ff8787;--theme-btn-color: #bbb;--theme-btn-hover: #4da8ff}.header{background-color:var(--header-bg);box-shadow:0 2px 4px var(--header-shadow);padding:15px 20px;display:flex;justify-content:space-between;align-items:center}.header .user-info{font-weight:500;color:var(--header-text)}.header .header-actions{display:flex;align-items:center;gap:15px}.header .theme-toggle-btn{background:none;border:none;color:var(--theme-btn-color);font-size:16px;cursor:pointer;display:flex;align-items:center}.header .theme-toggle-btn:hover{color:var(--theme-btn-hover)}.header .logout-btn{background:none;border:none;color:var(--logout-btn-color);font-size:16px;cursor:pointer;display:flex;align-items:center}.header .logout-btn i{margin-right:5px}.header .logout-btn:hover{color:var(--logout-btn-hover)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: GenericButtonComponent, selector: "core-generic-button", inputs: ["config", "data"], outputs: ["buttonClick"] }, { kind: "component", type: GenericSwitchComponent, selector: "core-generic-switch", inputs: ["options", "selectedValue", "ariaLabel"], outputs: ["valueChange"] }] });
@@ -16015,8 +16101,25 @@ var PermissionsActions;
16015
16101
  PermissionsActions["WRITE"] = "W";
16016
16102
  PermissionsActions["READ"] = "R";
16017
16103
  PermissionsActions["DELETE"] = "D";
16104
+ PermissionsActions["CUSTOM"] = "C";
16018
16105
  })(PermissionsActions || (PermissionsActions = {}));
16019
16106
 
16107
+ var PermissionsCustomActions;
16108
+ (function (PermissionsCustomActions) {
16109
+ PermissionsCustomActions["COMPANIES_CHANGE_STATUS"] = "companies_change_status";
16110
+ PermissionsCustomActions["EMPLOYEES_BULK_UPLOAD"] = "employees_bulk_upload";
16111
+ PermissionsCustomActions["EMPLOYEES_EXPORT"] = "employees_export";
16112
+ PermissionsCustomActions["RESERVATIONS_EXPORT"] = "reservations_export";
16113
+ PermissionsCustomActions["SERVICES_EXPORT"] = "services_export";
16114
+ PermissionsCustomActions["ACCESS_CARD_ASSIGN"] = "access_card_assign";
16115
+ PermissionsCustomActions["ACCESS_CARD_REJECT_REQUEST"] = "access_card_reject_request";
16116
+ PermissionsCustomActions["ACCESS_CARD_MARK_DELIVERED"] = "access_card_mark_delivered";
16117
+ PermissionsCustomActions["ACCESS_CARD_REQUEST_REASSIGNMENT"] = "access_card_request_reassignment";
16118
+ PermissionsCustomActions["ACCESS_CARD_MARK_RETURNED"] = "access_card_mark_returned";
16119
+ PermissionsCustomActions["SERVICE_BUDGET_APPROVE"] = "service_budget_approve";
16120
+ PermissionsCustomActions["SERVICE_BUDGET_REJECT"] = "service_budget_reject";
16121
+ })(PermissionsCustomActions || (PermissionsCustomActions = {}));
16122
+
16020
16123
  var SidebarState;
16021
16124
  (function (SidebarState) {
16022
16125
  SidebarState["EXPANDED"] = "expanded";
@@ -16094,12 +16197,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
16094
16197
  // Este archivo es generado automáticamente por scripts/update-version.js
16095
16198
  // No edites manualmente este archivo
16096
16199
  const VERSION = {
16097
- full: '2.15.30',
16200
+ full: '2.15.32',
16098
16201
  major: 2,
16099
16202
  minor: 15,
16100
- patch: 30,
16101
- timestamp: '2025-11-06T15:47:00.778Z',
16102
- buildDate: '6/11/2025'
16203
+ patch: 32,
16204
+ timestamp: '2025-11-10T15:59:54.714Z',
16205
+ buildDate: '10/11/2025'
16103
16206
  };
16104
16207
 
16105
16208
  class MainNavComponent {
@@ -16198,7 +16301,7 @@ class MainNavComponent {
16198
16301
  return true;
16199
16302
  }
16200
16303
  try {
16201
- return this.permissionService.hasPermission(item.requiredPermission.resource, item.requiredPermission.action);
16304
+ return this.permissionService.hasPermission(item.requiredPermission.resource, item.requiredPermission.action, item.requiredPermission.custom_action);
16202
16305
  }
16203
16306
  catch (error) {
16204
16307
  return !this.isProduction();
@@ -19827,5 +19930,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
19827
19930
  * Generated bundle index. Do not edit.
19828
19931
  */
19829
19932
 
19830
- export { ALL_COUNTRY_CODES, ActiveFiltersComponent, AgeValidationHelper, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, COMMON_COUNTRIES, CacheBustingInterceptor, CardComponent, CarouselComponent, ChatMessagePosition, ChatMessageType, CheckboxFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreManualRefreshComponent, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, CountryCode, CustomClassService, DEFAULT_COUNTRIES, DataListComponent, DataListItemComponent, DataStoreService, DateFieldComponent, DateUtility, DatetimeFieldComponent, DialogActions, DocumentAction, DocumentDisplayMode, DocumentFieldComponent, DocumentFieldValidators, DocumentPayloadMode, DropdownComponent, DropdownDirection, DropdownService, DynamicFieldDirective, DynamicFieldsHelper, FieldErrorsComponent, FieldType, FileFieldComponent, FileModel, FilePreviewActionType, FileTemplateModel, FileTemplateType, FileType, FileTypeModel, FileUploadService, FilterModalComponent, FilterService, FilterType, FixedActionPosition, FixedActionsMobileModalComponent, FixedActionsMobileModalService, GalleryAnimationType, GalleryLayoutType, GalleryModalComponent, GalleryModalGlobalService, GenericButtonComponent, GenericChatComponent, GenericChatService, GenericDocumentationComponent, GenericFixedActionsComponent, GenericGalleryComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSidebarComponent, GenericSkeletonComponent, GenericStepsComponent, GenericSwitchComponent, GenericTableComponent, GenericTabsComponent, GenericTimelineComponent, GlobalApiConfigService, HeaderComponent, HeaderConfigurationService, HeaderElementType, HeaderService, HttpLoaderFactory, ImageModalComponent, ImageModalService, ImagePreviewComponent, LATIN_AMERICA_COUNTRIES, LayoutAuth, LayoutBreakpoint, LayoutComponent, LayoutService, LayoutStateService, LayoutType, LoaderComponent, LoaderService, MainNavComponent, MainNavService, ManualRefreshService, MobileHeaderComponent, MobileResolutionService, 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, PhoneFieldComponent, ProgressBarComponent, ProgressBarSize, RatingService, RatingSize, RatingType, ResetPasswordModel, RoleModel, SOUTH_AMERICA_COUNTRIES, SelectFieldComponent, ServerSelectFieldComponent, ServerSelectService, SidebarCustomModalComponent, SidebarCustomModalService, SidebarHeight, SidebarMobileModalService, SidebarMobileType, SidebarPosition, SidebarService, SidebarState, SidebarTemplateRegistryService, SidebarVisibility, SidebarWidth, SkeletonAnimation, SkeletonService, SkeletonSize, SkeletonType, SmartFieldComponent, SortDirection, SortMode, StepSize, StepStatus, StepType, StepsService, SwitchFieldComponent, TableAction, TableActionService, TableDataService, TableFixedActionsService, TableSortService, TextAreaFieldComponent, TextFieldComponent, TimeFieldComponent, TimeInterval, TimelineService, TimelineStatus, TimelineType, TranslationMergeService, UruguayanDocumentValidationHelper, UsersModel, VERSION, ageValidator, calculateAge, equalToValidator, generateRandomUruguayanDocument, getCountryCodeStrings, getLatestBirthDateForAge, getRandomCi, getUruguayanDocumentValidationDigit, getValidationDigit, isSameDate, isValidCountryCode, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader, random, transform, transformUruguayanDocument, uruguayanDocumentValidator, validate, validateAge, validateCi, validateUruguayanDocument, validationDigit };
19933
+ export { ALL_COUNTRY_CODES, ActiveFiltersComponent, AgeValidationHelper, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, COMMON_COUNTRIES, CacheBustingInterceptor, CardComponent, CarouselComponent, ChatMessagePosition, ChatMessageType, CheckboxFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreManualRefreshComponent, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, CountryCode, CustomClassService, DEFAULT_COUNTRIES, DataListComponent, DataListItemComponent, DataStoreService, DateFieldComponent, DateUtility, DatetimeFieldComponent, DialogActions, DocumentAction, DocumentDisplayMode, DocumentFieldComponent, DocumentFieldValidators, DocumentPayloadMode, DropdownComponent, DropdownDirection, DropdownService, DynamicFieldDirective, DynamicFieldsHelper, FieldErrorsComponent, FieldType, FileFieldComponent, FileModel, FilePreviewActionType, FileTemplateModel, FileTemplateType, FileType, FileTypeModel, FileUploadService, FilterModalComponent, FilterService, FilterType, FixedActionPosition, FixedActionsMobileModalComponent, FixedActionsMobileModalService, GalleryAnimationType, GalleryLayoutType, GalleryModalComponent, GalleryModalGlobalService, GenericButtonComponent, GenericChatComponent, GenericChatService, GenericDocumentationComponent, GenericFixedActionsComponent, GenericGalleryComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSidebarComponent, GenericSkeletonComponent, GenericStepsComponent, GenericSwitchComponent, GenericTableComponent, GenericTabsComponent, GenericTimelineComponent, GlobalApiConfigService, HeaderComponent, HeaderConfigurationService, HeaderElementType, HeaderService, HttpLoaderFactory, ImageModalComponent, ImageModalService, ImagePreviewComponent, LATIN_AMERICA_COUNTRIES, LayoutAuth, LayoutBreakpoint, LayoutComponent, LayoutService, LayoutStateService, LayoutType, LoaderComponent, LoaderService, MainNavComponent, MainNavService, ManualRefreshService, MobileHeaderComponent, MobileResolutionService, ModalMode, ModelApiService, MultiEntryFieldComponent, MultiEntryOutputFormat, NumberFieldComponent, NumberFieldConfigType, NumberFieldType, NumberRange, PERMISSION_ACTIONS_PROVIDER, PERMISSION_PROVIDER, PERMISSION_RESOURCES_PROVIDER, PaginationService, PasswordFieldComponent, PermissionEnumsService, PermissionModel, PermissionService, PermissionWrapperService, PermissionsActions, PermissionsCustomActions, PermissionsInterceptor, PermissionsResources, PhoneFieldComponent, ProgressBarComponent, ProgressBarSize, RatingService, RatingSize, RatingType, ResetPasswordModel, RoleModel, SOUTH_AMERICA_COUNTRIES, SelectFieldComponent, ServerSelectFieldComponent, ServerSelectService, SidebarCustomModalComponent, SidebarCustomModalService, SidebarHeight, SidebarMobileModalService, SidebarMobileType, SidebarPosition, SidebarService, SidebarState, SidebarTemplateRegistryService, SidebarVisibility, SidebarWidth, SkeletonAnimation, SkeletonService, SkeletonSize, SkeletonType, SmartFieldComponent, SortDirection, SortMode, StepSize, StepStatus, StepType, StepsService, SwitchFieldComponent, TableAction, TableActionService, TableDataService, TableFixedActionsService, TableSortService, TextAreaFieldComponent, TextFieldComponent, TimeFieldComponent, TimeInterval, TimelineService, TimelineStatus, TimelineType, TranslationMergeService, UruguayanDocumentValidationHelper, UsersModel, VERSION, ageValidator, calculateAge, equalToValidator, generateRandomUruguayanDocument, getCountryCodeStrings, getLatestBirthDateForAge, getRandomCi, getUruguayanDocumentValidationDigit, getValidationDigit, isSameDate, isValidCountryCode, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader, random, transform, transformUruguayanDocument, uruguayanDocumentValidator, validate, validateAge, validateCi, validateUruguayanDocument, validationDigit };
19831
19934
  //# sourceMappingURL=solcre-org-core-ui.mjs.map