@solcre-org/core-ui 2.16.0 → 2.16.3

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.
@@ -2721,6 +2721,47 @@ function getCountryCodeStrings() {
2721
2721
  return ALL_COUNTRY_CODES.map(code => code.toString());
2722
2722
  }
2723
2723
 
2724
+ var DayState;
2725
+ (function (DayState) {
2726
+ DayState["DEFAULT"] = "default";
2727
+ DayState["ACTIVE"] = "active";
2728
+ DayState["CURRENT"] = "current";
2729
+ DayState["DISABLED"] = "disabled";
2730
+ DayState["SELECTED"] = "selected";
2731
+ })(DayState || (DayState = {}));
2732
+
2733
+ var DayType;
2734
+ (function (DayType) {
2735
+ DayType["PREVIOUS_MONTH"] = "previous";
2736
+ DayType["CURRENT_MONTH"] = "current";
2737
+ DayType["NEXT_MONTH"] = "next";
2738
+ })(DayType || (DayType = {}));
2739
+
2740
+ var CalendarEventType;
2741
+ (function (CalendarEventType) {
2742
+ CalendarEventType["BLOCKED"] = "blocked";
2743
+ CalendarEventType["UNAVAILABLE"] = "unavailable";
2744
+ CalendarEventType["EVENT"] = "event";
2745
+ CalendarEventType["PENDING"] = "pending";
2746
+ CalendarEventType["USER_EVENT"] = "user-event";
2747
+ CalendarEventType["CONFIRMED"] = "confirmed";
2748
+ CalendarEventType["CANCELLED"] = "cancelled";
2749
+ CalendarEventType["COMPLETED"] = "completed";
2750
+ CalendarEventType["REJECTED"] = "rejected";
2751
+ CalendarEventType["EXPIRED"] = "expired";
2752
+ })(CalendarEventType || (CalendarEventType = {}));
2753
+
2754
+ var WeekDay;
2755
+ (function (WeekDay) {
2756
+ WeekDay[WeekDay["MONDAY"] = 0] = "MONDAY";
2757
+ WeekDay[WeekDay["TUESDAY"] = 1] = "TUESDAY";
2758
+ WeekDay[WeekDay["WEDNESDAY"] = 2] = "WEDNESDAY";
2759
+ WeekDay[WeekDay["THURSDAY"] = 3] = "THURSDAY";
2760
+ WeekDay[WeekDay["FRIDAY"] = 4] = "FRIDAY";
2761
+ WeekDay[WeekDay["SATURDAY"] = 5] = "SATURDAY";
2762
+ WeekDay[WeekDay["SUNDAY"] = 6] = "SUNDAY";
2763
+ })(WeekDay || (WeekDay = {}));
2764
+
2724
2765
  const DEFAULT_COUNTRIES = [
2725
2766
  { "code": CountryCode.PY, "phone": "+595", "name": "Paraguay", "flag": "001-paraguay.svg" },
2726
2767
  { "code": CountryCode.SN, "phone": "+221", "name": "Senegal", "flag": "002-senegal.svg" },
@@ -5924,11 +5965,30 @@ class GenericButtonComponent {
5924
5965
  return true;
5925
5966
  if (this.config().requiredPermission) {
5926
5967
  const perm = this.config().requiredPermission;
5927
- const hasPermission = this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
5968
+ const hasPermission = this.checkRequiredPermission(perm);
5928
5969
  return !hasPermission;
5929
5970
  }
5930
5971
  return false;
5931
5972
  });
5973
+ checkRequiredPermission(perm) {
5974
+ if (perm.custom_action && perm.action) {
5975
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
5976
+ }
5977
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
5978
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
5979
+ if (resources.length === 0 && actions.length === 0) {
5980
+ return true;
5981
+ }
5982
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
5983
+ for (const resource of resourcesToCheck) {
5984
+ for (const action of actions) {
5985
+ if (this.permissionService.hasPermission(resource, action)) {
5986
+ return true;
5987
+ }
5988
+ }
5989
+ }
5990
+ return false;
5991
+ }
5932
5992
  buttonClasses = computed(() => {
5933
5993
  const config = this.config();
5934
5994
  const classes = [];
@@ -10228,7 +10288,26 @@ class DropdownComponent {
10228
10288
  hasPermission(action) {
10229
10289
  if (!action.requiredPermission)
10230
10290
  return true;
10231
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action);
10291
+ return this.checkRequiredPermission(action.requiredPermission);
10292
+ }
10293
+ checkRequiredPermission(perm) {
10294
+ if (perm.custom_action && perm.action) {
10295
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
10296
+ }
10297
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
10298
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
10299
+ if (resources.length === 0 && actions.length === 0) {
10300
+ return true;
10301
+ }
10302
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
10303
+ for (const resource of resourcesToCheck) {
10304
+ for (const actionItem of actions) {
10305
+ if (this.permissionService.hasPermission(resource, actionItem)) {
10306
+ return true;
10307
+ }
10308
+ }
10309
+ }
10310
+ return false;
10232
10311
  }
10233
10312
  shouldShowAction(actionConfig) {
10234
10313
  const currentRow = this.row();
@@ -12451,7 +12530,7 @@ class FixedActionsMobileModalComponent {
12451
12530
  });
12452
12531
  shouldShowAction(action) {
12453
12532
  if (action.requiredPermission) {
12454
- const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
12533
+ const hasPermission = this.checkRequiredPermission(action.requiredPermission);
12455
12534
  if (!hasPermission)
12456
12535
  return false;
12457
12536
  }
@@ -12460,7 +12539,7 @@ class FixedActionsMobileModalComponent {
12460
12539
  return action.shouldShow(data.data);
12461
12540
  }
12462
12541
  if (action.customAction?.requiredPermission) {
12463
- const hasPermission = this.permissionService.hasPermission(action.customAction.requiredPermission.resource, action.customAction.requiredPermission.action, action.customAction.requiredPermission.custom_action);
12542
+ const hasPermission = this.checkRequiredPermission(action.customAction.requiredPermission);
12464
12543
  if (!hasPermission)
12465
12544
  return false;
12466
12545
  }
@@ -12468,7 +12547,7 @@ class FixedActionsMobileModalComponent {
12468
12547
  return action.customAction.shouldShow(data.data);
12469
12548
  }
12470
12549
  if (action.globalAction?.requiredPermission) {
12471
- const hasPermission = this.permissionService.hasPermission(action.globalAction.requiredPermission.resource, action.globalAction.requiredPermission.action, action.globalAction.requiredPermission.custom_action);
12550
+ const hasPermission = this.checkRequiredPermission(action.globalAction.requiredPermission);
12472
12551
  if (!hasPermission)
12473
12552
  return false;
12474
12553
  }
@@ -12516,6 +12595,25 @@ class FixedActionsMobileModalComponent {
12516
12595
  this.onClose();
12517
12596
  }
12518
12597
  }
12598
+ checkRequiredPermission(perm) {
12599
+ if (perm.custom_action && perm.action) {
12600
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
12601
+ }
12602
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
12603
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
12604
+ if (resources.length === 0 && actions.length === 0) {
12605
+ return true;
12606
+ }
12607
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
12608
+ for (const resource of resourcesToCheck) {
12609
+ for (const action of actions) {
12610
+ if (this.permissionService.hasPermission(resource, action)) {
12611
+ return true;
12612
+ }
12613
+ }
12614
+ }
12615
+ return false;
12616
+ }
12519
12617
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: FixedActionsMobileModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12520
12618
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: FixedActionsMobileModalComponent, isStandalone: true, selector: "core-fixed-actions-mobile-modal", ngImport: i0, template: "@if (isVisible()) {\n <div class=\"c-services-chat c-modal is-visible\">\n <div class=\"c-modal__overlay\" (click)=\"onOverlayClick($event)\"></div>\n <div class=\"c-modal__holder\">\n <div class=\"c-modal__header\">\n @if (modalData()?.title || modalData()?.subtitle) {\n <p class=\"c-modal__title\">\n {{ modalData()?.title }}\n @if (modalData()?.subtitle) {\n <br>\n <small>{{ modalData()?.subtitle }}</small>\n }\n </p>\n }\n <button \n type=\"button\" \n class=\"c-icon-btn c-modal__close\" \n aria-label=\"Cerrar\" \n title=\"Cerrar\"\n (click)=\"onClose()\">\n <span class=\"icon-cross-thin\"></span>\n </button>\n </div>\n <div class=\"c-modal__body\">\n <nav class=\"c-mobile-nav\">\n <ul>\n @for (action of visibleActions(); track $index) {\n <li class=\"c-mobile-nav__item\">\n <a \n class=\"c-mobile-nav__link\" \n [class.is-disabled]=\"isActionDisabled(action)\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n href=\"javascript:void(0)\"\n (click)=\"onActionClick(action)\">\n @if (getActionIcon(action)) {\n <span [ngClass]=\"getActionIcon(action) | coreIconCompat\"></span>\n }\n {{ getActionLabel(action) | translate }}\n </a>\n </li>\n }\n </ul>\n </nav>\n </div>\n </div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "pipe", type: IconCompatPipe, name: "coreIconCompat" }] });
12521
12619
  }
@@ -12793,8 +12891,7 @@ class GenericTableComponent {
12793
12891
  const modalActions = [];
12794
12892
  const createAction = this.actions().find(a => a.action === TableAction.CREATE);
12795
12893
  if (createAction && createAction.mobileConfig?.showInsideModal !== false && !this.getMobileShowInHeader(createAction) && !this.getMobileShowOutsideFixedActions(createAction)) {
12796
- if (!createAction.requiredPermission ||
12797
- this.permissionService.hasPermission(createAction.requiredPermission.resource, createAction.requiredPermission.action, createAction.requiredPermission.custom_action)) {
12894
+ if (!createAction.requiredPermission || this.checkRequiredPermission(createAction.requiredPermission)) {
12798
12895
  modalActions.push({
12799
12896
  icon: createAction.icon || this.getDefaultIconForAction(TableAction.CREATE),
12800
12897
  label: this.getActionLabel(TableAction.CREATE),
@@ -13602,7 +13699,7 @@ class GenericTableComponent {
13602
13699
  }
13603
13700
  shouldShowFixedAction(action) {
13604
13701
  if (action.requiredPermission) {
13605
- const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
13702
+ const hasPermission = this.checkRequiredPermission(action.requiredPermission);
13606
13703
  if (!hasPermission)
13607
13704
  return false;
13608
13705
  }
@@ -13611,7 +13708,7 @@ class GenericTableComponent {
13611
13708
  return action.shouldShow(selectedRow);
13612
13709
  }
13613
13710
  if (action.customAction?.requiredPermission) {
13614
- const hasPermission = this.permissionService.hasPermission(action.customAction.requiredPermission.resource, action.customAction.requiredPermission.action, action.customAction.requiredPermission.custom_action);
13711
+ const hasPermission = this.checkRequiredPermission(action.customAction.requiredPermission);
13615
13712
  if (!hasPermission)
13616
13713
  return false;
13617
13714
  }
@@ -13622,7 +13719,7 @@ class GenericTableComponent {
13622
13719
  }
13623
13720
  }
13624
13721
  if (action.globalAction?.requiredPermission) {
13625
- const hasPermission = this.permissionService.hasPermission(action.globalAction.requiredPermission.resource, action.globalAction.requiredPermission.action, action.globalAction.requiredPermission.custom_action);
13722
+ const hasPermission = this.checkRequiredPermission(action.globalAction.requiredPermission);
13626
13723
  if (!hasPermission)
13627
13724
  return false;
13628
13725
  }
@@ -13861,7 +13958,26 @@ class GenericTableComponent {
13861
13958
  hasPermission(action) {
13862
13959
  if (!action.requiredPermission)
13863
13960
  return true;
13864
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
13961
+ return this.checkRequiredPermission(action.requiredPermission);
13962
+ }
13963
+ checkRequiredPermission(perm) {
13964
+ if (perm.custom_action && perm.action) {
13965
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
13966
+ }
13967
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
13968
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
13969
+ if (resources.length === 0 && actions.length === 0) {
13970
+ return true;
13971
+ }
13972
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
13973
+ for (const resource of resourcesToCheck) {
13974
+ for (const action of actions) {
13975
+ if (this.permissionService.hasPermission(resource, action)) {
13976
+ return true;
13977
+ }
13978
+ }
13979
+ }
13980
+ return false;
13865
13981
  }
13866
13982
  showFiltersPopup() {
13867
13983
  this.isFilterModalOpen.set(true);
@@ -16163,7 +16279,7 @@ class HeaderComponent {
16163
16279
  hasPermission(action) {
16164
16280
  if (!action.requiredPermission)
16165
16281
  return true;
16166
- const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
16282
+ const hasPermission = this.checkRequiredPermission(action.requiredPermission);
16167
16283
  if (!hasPermission)
16168
16284
  return false;
16169
16285
  const isMobile = this.mobileResolutionService.isMobile();
@@ -16193,7 +16309,7 @@ class HeaderComponent {
16193
16309
  hasCustomActionPermission(action) {
16194
16310
  if (!action.requiredPermission)
16195
16311
  return true;
16196
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
16312
+ return this.checkRequiredPermission(action.requiredPermission);
16197
16313
  }
16198
16314
  isCustomActionVisible(action) {
16199
16315
  if (action.visible === false)
@@ -16238,7 +16354,26 @@ class HeaderComponent {
16238
16354
  return false;
16239
16355
  if (!action.requiredPermission)
16240
16356
  return true;
16241
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
16357
+ return this.checkRequiredPermission(action.requiredPermission);
16358
+ }
16359
+ checkRequiredPermission(perm) {
16360
+ if (perm.custom_action && perm.action) {
16361
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
16362
+ }
16363
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
16364
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
16365
+ if (resources.length === 0 && actions.length === 0) {
16366
+ return true;
16367
+ }
16368
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
16369
+ for (const resource of resourcesToCheck) {
16370
+ for (const action of actions) {
16371
+ if (this.permissionService.hasPermission(resource, action)) {
16372
+ return true;
16373
+ }
16374
+ }
16375
+ }
16376
+ return false;
16242
16377
  }
16243
16378
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16244
16379
  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"] }] });
@@ -16410,12 +16545,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
16410
16545
  // Este archivo es generado automáticamente por scripts/update-version.js
16411
16546
  // No edites manualmente este archivo
16412
16547
  const VERSION = {
16413
- full: '2.16.0',
16548
+ full: '2.16.3',
16414
16549
  major: 2,
16415
16550
  minor: 16,
16416
- patch: 0,
16417
- timestamp: '2025-12-04T12:05:49.777Z',
16418
- buildDate: '4/12/2025'
16551
+ patch: 3,
16552
+ timestamp: '2025-12-05T15:12:25.862Z',
16553
+ buildDate: '5/12/2025'
16419
16554
  };
16420
16555
 
16421
16556
  class MainNavComponent {
@@ -16557,7 +16692,27 @@ class MainNavComponent {
16557
16692
  return true;
16558
16693
  }
16559
16694
  try {
16560
- return this.permissionService.hasPermission(item.requiredPermission.resource, item.requiredPermission.action, item.requiredPermission.custom_action);
16695
+ const perm = item.requiredPermission;
16696
+ const matchMode = perm.match || 'any';
16697
+ const resources = perm.resources?.length
16698
+ ? perm.resources
16699
+ : [perm.resource];
16700
+ const actions = perm.actions?.length
16701
+ ? perm.actions
16702
+ : (perm.action ? [perm.action] : []);
16703
+ if (actions.length === 0) {
16704
+ return true;
16705
+ }
16706
+ const permissionChecks = [];
16707
+ for (const resource of resources) {
16708
+ for (const action of actions) {
16709
+ permissionChecks.push(this.permissionService.hasPermission(resource, action, perm.custom_action));
16710
+ }
16711
+ }
16712
+ if (matchMode === 'all') {
16713
+ return permissionChecks.every(result => result);
16714
+ }
16715
+ return permissionChecks.some(result => result);
16561
16716
  }
16562
16717
  catch (error) {
16563
16718
  return !this.isProduction();
@@ -17637,7 +17792,7 @@ class GenericFixedActionsComponent {
17637
17792
  })
17638
17793
  .filter(action => {
17639
17794
  if (action.requiredPermission) {
17640
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
17795
+ return this.checkRequiredPermission(action.requiredPermission);
17641
17796
  }
17642
17797
  return true;
17643
17798
  })
@@ -17659,7 +17814,7 @@ class GenericFixedActionsComponent {
17659
17814
  })
17660
17815
  .filter(action => {
17661
17816
  if (action.requiredPermission) {
17662
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
17817
+ return this.checkRequiredPermission(action.requiredPermission);
17663
17818
  }
17664
17819
  return true;
17665
17820
  })
@@ -17693,7 +17848,7 @@ class GenericFixedActionsComponent {
17693
17848
  if (external && external.length > 0) {
17694
17849
  external.forEach(action => {
17695
17850
  if (action.requiredPermission) {
17696
- if (this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action)) {
17851
+ if (this.checkRequiredPermission(action.requiredPermission)) {
17697
17852
  actions.push(action);
17698
17853
  }
17699
17854
  }
@@ -17709,7 +17864,7 @@ class GenericFixedActionsComponent {
17709
17864
  : this.tableFixedActionsService.getActiveTableActions();
17710
17865
  tableActions.forEach(action => {
17711
17866
  if (action.requiredPermission) {
17712
- if (this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action)) {
17867
+ if (this.checkRequiredPermission(action.requiredPermission)) {
17713
17868
  actions.push(action);
17714
17869
  }
17715
17870
  }
@@ -17782,6 +17937,25 @@ class GenericFixedActionsComponent {
17782
17937
  actions: fixedActions
17783
17938
  });
17784
17939
  }
17940
+ checkRequiredPermission(perm) {
17941
+ if (perm.custom_action && perm.action) {
17942
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
17943
+ }
17944
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
17945
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
17946
+ if (resources.length === 0 && actions.length === 0) {
17947
+ return true;
17948
+ }
17949
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
17950
+ for (const resource of resourcesToCheck) {
17951
+ for (const action of actions) {
17952
+ if (this.permissionService.hasPermission(resource, action)) {
17953
+ return true;
17954
+ }
17955
+ }
17956
+ }
17957
+ return false;
17958
+ }
17785
17959
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericFixedActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17786
17960
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: GenericFixedActionsComponent, isStandalone: true, selector: "core-generic-fixed-actions", inputs: { externalActions: { classPropertyName: "externalActions", publicName: "externalActions", isSignal: true, isRequired: false, transformFunction: null }, tableId: { classPropertyName: "tableId", publicName: "tableId", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "c-fixed-actions c-fixed-actions--right" }, ngImport: i0, template: `
17787
17961
  @if (shouldShow() && visibleActions().length > 0) {
@@ -19948,25 +20122,136 @@ class AdAuthService {
19948
20122
  msalInstance = null;
19949
20123
  msalModule = null;
19950
20124
  initializationPromise = null;
20125
+ codeVerifier = null;
19951
20126
  authState = signal({
19952
20127
  isAuthenticated: false,
19953
20128
  user: null,
19954
20129
  isLoading: false,
19955
20130
  error: null
19956
20131
  });
20132
+ _authorizationCode = signal(null);
20133
+ authorizationCode = computed(() => this._authorizationCode());
19957
20134
  isAuthenticated = computed(() => this.authState().isAuthenticated);
19958
20135
  currentUser = computed(() => this.authState().user);
19959
20136
  isLoading = computed(() => this.authState().isLoading);
19960
20137
  error = computed(() => this.authState().error);
19961
20138
  constructor() {
19962
- // Only initialize if config is provided
19963
20139
  if (this.config) {
19964
- this.initializationPromise = this.initializeMsal();
20140
+ if (this.config.authorizationCodeOnly) {
20141
+ this.checkForAuthorizationCode();
20142
+ }
20143
+ else {
20144
+ this.initializationPromise = this.initializeMsal();
20145
+ }
19965
20146
  }
19966
20147
  }
19967
- /**
19968
- * Dynamically loads MSAL library only when needed
19969
- */
20148
+ checkForAuthorizationCode() {
20149
+ const urlParams = new URLSearchParams(window.location.search);
20150
+ const code = urlParams.get('code');
20151
+ const state = urlParams.get('state');
20152
+ const error = urlParams.get('error');
20153
+ const errorDescription = urlParams.get('error_description');
20154
+ if (error) {
20155
+ this.updateAuthState({
20156
+ error: { code: error, message: errorDescription },
20157
+ isLoading: false
20158
+ });
20159
+ this.cleanUrlParams();
20160
+ return;
20161
+ }
20162
+ if (code) {
20163
+ const storedCodeVerifier = sessionStorage.getItem('ad_auth_code_verifier');
20164
+ const storedState = sessionStorage.getItem('ad_auth_state');
20165
+ if (storedState && state !== storedState) {
20166
+ this.updateAuthState({
20167
+ error: { code: 'state_mismatch', message: 'State parameter mismatch' },
20168
+ isLoading: false
20169
+ });
20170
+ this.cleanUrlParams();
20171
+ return;
20172
+ }
20173
+ this._authorizationCode.set({
20174
+ code,
20175
+ state: state || undefined,
20176
+ codeVerifier: storedCodeVerifier || undefined
20177
+ });
20178
+ sessionStorage.removeItem('ad_auth_code_verifier');
20179
+ sessionStorage.removeItem('ad_auth_state');
20180
+ this.cleanUrlParams();
20181
+ }
20182
+ }
20183
+ cleanUrlParams() {
20184
+ const url = new URL(window.location.href);
20185
+ url.searchParams.delete('code');
20186
+ url.searchParams.delete('state');
20187
+ url.searchParams.delete('error');
20188
+ url.searchParams.delete('error_description');
20189
+ url.searchParams.delete('session_state');
20190
+ window.history.replaceState({}, document.title, url.pathname + url.hash);
20191
+ }
20192
+ async generatePKCE() {
20193
+ const array = new Uint8Array(32);
20194
+ crypto.getRandomValues(array);
20195
+ const codeVerifier = this.base64UrlEncode(array);
20196
+ const encoder = new TextEncoder();
20197
+ const data = encoder.encode(codeVerifier);
20198
+ const digest = await crypto.subtle.digest('SHA-256', data);
20199
+ const codeChallenge = this.base64UrlEncode(new Uint8Array(digest));
20200
+ return { codeVerifier, codeChallenge };
20201
+ }
20202
+ base64UrlEncode(buffer) {
20203
+ let binary = '';
20204
+ for (let i = 0; i < buffer.byteLength; i++) {
20205
+ binary += String.fromCharCode(buffer[i]);
20206
+ }
20207
+ return btoa(binary)
20208
+ .replace(/\+/g, '-')
20209
+ .replace(/\//g, '_')
20210
+ .replace(/=+$/, '');
20211
+ }
20212
+ generateState() {
20213
+ const array = new Uint8Array(16);
20214
+ crypto.getRandomValues(array);
20215
+ return this.base64UrlEncode(array);
20216
+ }
20217
+ async redirectToAzureLogin() {
20218
+ if (!this.config) {
20219
+ throw new Error('AD Auth configuration is not available');
20220
+ }
20221
+ this.updateAuthState({ isLoading: true, error: null });
20222
+ try {
20223
+ const { codeVerifier, codeChallenge } = await this.generatePKCE();
20224
+ const state = this.config.state || this.generateState();
20225
+ sessionStorage.setItem('ad_auth_code_verifier', codeVerifier);
20226
+ sessionStorage.setItem('ad_auth_state', state);
20227
+ this.codeVerifier = codeVerifier;
20228
+ const params = new URLSearchParams({
20229
+ client_id: this.config.clientId,
20230
+ response_type: 'code',
20231
+ redirect_uri: this.config.redirectUri,
20232
+ scope: (this.config.scopes || ['openid', 'profile', 'email']).join(' '),
20233
+ response_mode: 'query',
20234
+ state: state,
20235
+ code_challenge: codeChallenge,
20236
+ code_challenge_method: 'S256'
20237
+ });
20238
+ const authUrl = `${this.config.authority}/oauth2/v2.0/authorize?${params.toString()}`;
20239
+ window.location.href = authUrl;
20240
+ }
20241
+ catch (error) {
20242
+ this.updateAuthState({ isLoading: false, error });
20243
+ throw error;
20244
+ }
20245
+ }
20246
+ getAuthorizationCode() {
20247
+ return this._authorizationCode();
20248
+ }
20249
+ clearAuthorizationCode() {
20250
+ this._authorizationCode.set(null);
20251
+ }
20252
+ isAuthorizationCodeOnlyMode() {
20253
+ return this.config?.authorizationCodeOnly === true;
20254
+ }
19970
20255
  async loadMsalModule() {
19971
20256
  if (this.msalModule) {
19972
20257
  return this.msalModule;
@@ -19998,9 +20283,13 @@ class AdAuthService {
19998
20283
  },
19999
20284
  cache: {
20000
20285
  cacheLocation: (this.config.cacheLocation || 'sessionStorage'),
20001
- storeAuthStateInCookie: false,
20286
+ storeAuthStateInCookie: this.config.interactionType === AdInteractionType.POPUP,
20002
20287
  },
20003
20288
  system: {
20289
+ allowNativeBroker: false,
20290
+ windowHashTimeout: 60000,
20291
+ iframeHashTimeout: 6000,
20292
+ loadFrameTimeout: 0,
20004
20293
  loggerOptions: {
20005
20294
  loggerCallback: this.config.enableLogging ? this.loggerCallback : undefined,
20006
20295
  logLevel: this.config.logLevel || 0,
@@ -20096,13 +20385,21 @@ class AdAuthService {
20096
20385
  this.updateAuthState({ isLoading: true, error: null });
20097
20386
  try {
20098
20387
  const loginRequest = {
20099
- scopes: this.config.scopes || ['openid', 'profile', 'email']
20388
+ scopes: this.config.scopes || ['openid', 'profile', 'email'],
20389
+ prompt: 'select_account'
20100
20390
  };
20101
20391
  const result = await this.msalInstance.loginPopup(loginRequest);
20102
20392
  this.handleAuthenticationResult(result);
20103
20393
  return this.currentUser();
20104
20394
  }
20105
20395
  catch (error) {
20396
+ if (error?.errorCode === 'hash_empty_error') {
20397
+ console.warn('MSAL: Hash vacío detectado, intentando verificar sesión existente...');
20398
+ await this.checkActiveSession();
20399
+ if (this.isAuthenticated()) {
20400
+ return this.currentUser();
20401
+ }
20402
+ }
20106
20403
  this.updateAuthState({
20107
20404
  isLoading: false,
20108
20405
  error
@@ -20131,6 +20428,10 @@ class AdAuthService {
20131
20428
  }
20132
20429
  }
20133
20430
  async login() {
20431
+ if (this.config?.authorizationCodeOnly) {
20432
+ await this.redirectToAzureLogin();
20433
+ return null;
20434
+ }
20134
20435
  const interactionType = this.config?.interactionType || AdInteractionType.POPUP;
20135
20436
  if (interactionType === AdInteractionType.REDIRECT) {
20136
20437
  await this.loginWithRedirect();
@@ -20193,7 +20494,28 @@ class AdAuthService {
20193
20494
  throw error;
20194
20495
  }
20195
20496
  }
20497
+ async logoutFromAzure() {
20498
+ if (!this.config) {
20499
+ throw new Error('AD Auth configuration is not available');
20500
+ }
20501
+ this.updateAuthState({
20502
+ isAuthenticated: false,
20503
+ user: null,
20504
+ isLoading: false,
20505
+ error: null
20506
+ });
20507
+ this._authorizationCode.set(null);
20508
+ const params = new URLSearchParams({
20509
+ post_logout_redirect_uri: this.config.postLogoutRedirectUri || this.config.redirectUri
20510
+ });
20511
+ const logoutUrl = `${this.config.authority}/oauth2/v2.0/logout?${params.toString()}`;
20512
+ window.location.href = logoutUrl;
20513
+ }
20196
20514
  async logout() {
20515
+ if (this.config?.authorizationCodeOnly) {
20516
+ await this.logoutFromAzure();
20517
+ return;
20518
+ }
20197
20519
  const interactionType = this.config?.interactionType || AdInteractionType.POPUP;
20198
20520
  if (interactionType === AdInteractionType.REDIRECT) {
20199
20521
  await this.logoutWithRedirect();
@@ -20262,11 +20584,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
20262
20584
  }], ctorParameters: () => [] });
20263
20585
 
20264
20586
  function adAuthGuard(redirectTo = '/login') {
20265
- return () => {
20587
+ return async () => {
20266
20588
  const authService = inject(AdAuthService);
20267
20589
  const router = inject(Router);
20268
20590
  if (!authService.isConfigured()) {
20269
- return false;
20591
+ return true;
20592
+ }
20593
+ try {
20594
+ await authService.isReady();
20595
+ }
20596
+ catch (error) {
20597
+ console.warn('[adAuthGuard] MSAL initialization failed, allowing access');
20598
+ return true;
20270
20599
  }
20271
20600
  if (authService.isAuthenticated()) {
20272
20601
  return true;
@@ -20275,12 +20604,18 @@ function adAuthGuard(redirectTo = '/login') {
20275
20604
  };
20276
20605
  }
20277
20606
  function adGuestGuard(redirectTo = '/') {
20278
- return () => {
20607
+ return async () => {
20279
20608
  const authService = inject(AdAuthService);
20280
20609
  const router = inject(Router);
20281
20610
  if (!authService.isConfigured()) {
20282
20611
  return true;
20283
20612
  }
20613
+ try {
20614
+ await authService.isReady();
20615
+ }
20616
+ catch (error) {
20617
+ return true;
20618
+ }
20284
20619
  if (!authService.isAuthenticated()) {
20285
20620
  return true;
20286
20621
  }
@@ -20288,11 +20623,17 @@ function adGuestGuard(redirectTo = '/') {
20288
20623
  };
20289
20624
  }
20290
20625
  function adRoleGuard(requiredRoles, redirectTo = '/unauthorized') {
20291
- return () => {
20626
+ return async () => {
20292
20627
  const authService = inject(AdAuthService);
20293
20628
  const router = inject(Router);
20294
20629
  if (!authService.isConfigured()) {
20295
- return router.createUrlTree([redirectTo]);
20630
+ return true;
20631
+ }
20632
+ try {
20633
+ await authService.isReady();
20634
+ }
20635
+ catch (error) {
20636
+ return true;
20296
20637
  }
20297
20638
  if (!authService.isAuthenticated()) {
20298
20639
  return router.createUrlTree(['/login']);
@@ -20482,6 +20823,533 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
20482
20823
  args: [{ selector: 'core-ad-login-button', standalone: true, imports: [CommonModule, GenericButtonComponent, TranslateModule], template: "<div class=\"ad-auth-container\" [ngClass]=\"config().customClass\">\n @if (!isConfigured) {\n <div class=\"ad-auth-not-configured\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n {{ \"adAuth.not Configured\" | translate }}\n </div>\n } @else if (isLoading() && config().showLoader !== false) {\n <div class=\"ad-auth-loading\">\n <span class=\"ad-auth-spinner\"></span>\n {{ \"adAuth.authenticating\" | translate }}\n </div>\n } @else if (isAuthenticated() && currentUser()) { @if (showUserInfo()) {\n <div class=\"ad-auth-user-info\">\n <div class=\"ad-auth-user-avatar\">\n {{ userInitials() }}\n </div>\n <div class=\"ad-auth-user-details\">\n <p class=\"ad-auth-user-name\">\n {{ currentUser()!.name || (\"adAuth.user\" | translate) }}\n </p>\n <p class=\"ad-auth-user-email\">{{ currentUser()!.email }}</p>\n </div>\n </div>\n }\n\n <div class=\"ad-auth-buttons\">\n <core-generic-button\n [config]=\"logoutButtonConfig()\"\n (buttonClick)=\"onLogoutClick()\"\n />\n </div>\n } @else { @if (error()) {\n <div class=\"ad-auth-error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ \"adAuth.authError\" | translate }}\n </div>\n }\n\n <div class=\"ad-auth-buttons\">\n <core-generic-button\n [config]=\"loginButtonConfig()\"\n (buttonClick)=\"onLoginClick()\"\n />\n </div>\n }\n</div>\n", styles: [":host{display:block}.ad-auth-container{display:flex;flex-direction:column;gap:.75rem}.ad-auth-user-info{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;background-color:var(--color-background-secondary, #f5f5f5);border-radius:var(--border-radius, .375rem);font-size:.875rem}.ad-auth-user-avatar{width:2.5rem;height:2.5rem;border-radius:50%;background:linear-gradient(135deg,var(--color-primary, #0078d4) 0%,var(--color-primary-dark, #106ebe) 100%);display:flex;align-items:center;justify-content:center;color:#fff;font-weight:600;font-size:1rem;flex-shrink:0}.ad-auth-user-details{flex:1;min-width:0}.ad-auth-user-name{font-weight:600;color:var(--color-text-primary, #1a1a1a);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ad-auth-user-email{color:var(--color-text-secondary, #666);margin:0;font-size:.8125rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ad-auth-loading{display:flex;align-items:center;justify-content:center;padding:1rem;color:var(--color-text-secondary, #666);font-size:.875rem}.ad-auth-spinner{display:inline-block;width:1rem;height:1rem;border:2px solid var(--color-border, #e0e0e0);border-top-color:var(--color-primary, #0078d4);border-radius:50%;animation:spin .6s linear infinite;margin-right:.5rem}@keyframes spin{to{transform:rotate(360deg)}}.ad-auth-error{padding:.75rem 1rem;background-color:var(--color-danger-light, #fee);color:var(--color-danger, #d32f2f);border-radius:var(--border-radius, .375rem);font-size:.875rem}.ad-auth-not-configured{padding:1rem;background-color:var(--color-warning-light, #fff8e1);color:var(--color-warning-dark, #f57c00);border-radius:var(--border-radius, .375rem);font-size:.875rem;text-align:center}.ad-auth-buttons{display:flex;gap:.5rem}\n"] }]
20483
20824
  }], ctorParameters: () => [] });
20484
20825
 
20826
+ class GenericCalendarComponent {
20827
+ currentDate = input(new Date());
20828
+ selectedDate = input(null);
20829
+ config = input({});
20830
+ showNavigation = input(true);
20831
+ showHeader = input(true);
20832
+ locale = input('es-ES');
20833
+ dateSelected = output();
20834
+ monthChanged = output();
20835
+ displayDate = signal(new Date());
20836
+ calendarDays = signal([]);
20837
+ monthName = computed(() => {
20838
+ const date = this.displayDate();
20839
+ const localeValue = this.config().locale || this.locale();
20840
+ return date.toLocaleDateString(localeValue, { month: 'long', timeZone: 'UTC' });
20841
+ });
20842
+ year = computed(() => this.displayDate().getUTCFullYear());
20843
+ weekDayLabels = computed(() => {
20844
+ const startOnMonday = this.config().startWeekOnMonday ?? true;
20845
+ const labels = ['L', 'M', 'M', 'J', 'V', 'S', 'D'];
20846
+ return startOnMonday ? labels : ['D', ...labels.slice(0, 6)];
20847
+ });
20848
+ constructor() {
20849
+ this.displayDate.set(this.toUTCDate(this.currentDate()));
20850
+ this.generateCalendarDays();
20851
+ effect(() => {
20852
+ const current = this.currentDate();
20853
+ this.displayDate.set(this.toUTCDate(current));
20854
+ this.generateCalendarDays();
20855
+ });
20856
+ effect(() => {
20857
+ const selected = this.selectedDate();
20858
+ const config = this.config();
20859
+ this.generateCalendarDays();
20860
+ });
20861
+ }
20862
+ toUTCDate(date) {
20863
+ return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
20864
+ }
20865
+ createUTCDate(year, month, day) {
20866
+ return new Date(Date.UTC(year, month, day));
20867
+ }
20868
+ generateCalendarDays() {
20869
+ const date = this.displayDate();
20870
+ const year = date.getUTCFullYear();
20871
+ const month = date.getUTCMonth();
20872
+ const firstDayOfMonth = this.createUTCDate(year, month, 1);
20873
+ let startDate = new Date(firstDayOfMonth);
20874
+ const startWeekOnMonday = this.config().startWeekOnMonday ?? true;
20875
+ const firstDayWeekday = startWeekOnMonday
20876
+ ? (firstDayOfMonth.getUTCDay() + 6) % 7
20877
+ : firstDayOfMonth.getUTCDay();
20878
+ startDate.setUTCDate(startDate.getUTCDate() - firstDayWeekday);
20879
+ const days = [];
20880
+ const today = this.toUTCDate(new Date());
20881
+ const holidaySets = this.getHolidaySets(this.config());
20882
+ for (let i = 0; i < 42; i++) {
20883
+ const currentDay = new Date(startDate);
20884
+ currentDay.setUTCDate(startDate.getUTCDate() + i);
20885
+ const dayType = this.getDayType(currentDay, month);
20886
+ const dayState = this.getDayState(currentDay, today);
20887
+ const isWeekend = this.isWeekend(currentDay, startWeekOnMonday);
20888
+ const disabled = this.isDayDisabled(currentDay, holidaySets);
20889
+ const holidayInfo = this.getHolidayInfo(currentDay, holidaySets);
20890
+ days.push({
20891
+ date: new Date(currentDay),
20892
+ dayNumber: currentDay.getUTCDate(),
20893
+ type: dayType,
20894
+ state: dayState,
20895
+ isToday: this.isSameDay(currentDay, today),
20896
+ isWeekend,
20897
+ disabled,
20898
+ isHoliday: holidayInfo.isHoliday,
20899
+ holidayName: holidayInfo.name
20900
+ });
20901
+ }
20902
+ this.calendarDays.set(days);
20903
+ }
20904
+ getDayType(date, currentMonth) {
20905
+ if (date.getUTCMonth() < currentMonth) {
20906
+ return DayType.PREVIOUS_MONTH;
20907
+ }
20908
+ else if (date.getUTCMonth() > currentMonth) {
20909
+ return DayType.NEXT_MONTH;
20910
+ }
20911
+ return DayType.CURRENT_MONTH;
20912
+ }
20913
+ getDayState(date, today) {
20914
+ const selectedDate = this.selectedDate();
20915
+ const config = this.config();
20916
+ if (selectedDate && this.isSameDay(date, selectedDate)) {
20917
+ return DayState.CURRENT;
20918
+ }
20919
+ if (this.isSameDay(date, today)) {
20920
+ return DayState.ACTIVE;
20921
+ }
20922
+ if (config.highlightedDates?.some((d) => this.isSameDay(date, d))) {
20923
+ return DayState.ACTIVE;
20924
+ }
20925
+ return DayState.DEFAULT;
20926
+ }
20927
+ isDayDisabled(date, holidaySets) {
20928
+ const config = this.config();
20929
+ if (!config.allowPastDates) {
20930
+ const today = this.toUTCDate(new Date());
20931
+ if (date < today)
20932
+ return true;
20933
+ }
20934
+ if (!config.allowFutureDates) {
20935
+ const today = this.toUTCDate(new Date());
20936
+ if (date > today)
20937
+ return true;
20938
+ }
20939
+ if (config.minDate) {
20940
+ const minDateUTC = this.toUTCDate(config.minDate);
20941
+ if (date < minDateUTC)
20942
+ return true;
20943
+ }
20944
+ if (config.maxDate) {
20945
+ const maxDateUTC = this.toUTCDate(config.maxDate);
20946
+ if (date > maxDateUTC)
20947
+ return true;
20948
+ }
20949
+ if (config.disabledDates?.some((d) => this.isSameDay(date, d)))
20950
+ return true;
20951
+ const formattedDate = this.formatDateUTC(date);
20952
+ if (holidaySets.exactDates.has(formattedDate)) {
20953
+ return true;
20954
+ }
20955
+ const monthDay = this.formatMonthDayUTC(date);
20956
+ if (holidaySets.recurringMonthDays.has(monthDay)) {
20957
+ return true;
20958
+ }
20959
+ return false;
20960
+ }
20961
+ isWeekend(date, startWeekOnMonday) {
20962
+ const dayOfWeek = date.getUTCDay();
20963
+ return dayOfWeek === 0 || dayOfWeek === 6;
20964
+ }
20965
+ isSameDay(date1, date2) {
20966
+ return date1.getUTCFullYear() === date2.getUTCFullYear() &&
20967
+ date1.getUTCMonth() === date2.getUTCMonth() &&
20968
+ date1.getUTCDate() === date2.getUTCDate();
20969
+ }
20970
+ getHolidaySets(config) {
20971
+ const holidays = config.holidays ?? [];
20972
+ const exactDates = new Set();
20973
+ const recurringMonthDays = new Set();
20974
+ const holidayNames = new Map();
20975
+ holidays.forEach((holiday) => {
20976
+ if (!holiday?.date) {
20977
+ return;
20978
+ }
20979
+ const holidayDate = this.parseToUTCDate(holiday.date);
20980
+ if (!holidayDate) {
20981
+ return;
20982
+ }
20983
+ const formattedDate = this.formatDateUTC(holidayDate);
20984
+ const monthDay = this.formatMonthDayUTC(holidayDate);
20985
+ const isRecurring = holiday.isRecurring || holiday.is_recurring;
20986
+ if (isRecurring) {
20987
+ recurringMonthDays.add(monthDay);
20988
+ holidayNames.set(`recurring:${monthDay}`, holiday.name || 'Día festivo');
20989
+ }
20990
+ else {
20991
+ exactDates.add(formattedDate);
20992
+ holidayNames.set(`exact:${formattedDate}`, holiday.name || 'Día festivo');
20993
+ }
20994
+ });
20995
+ return { exactDates, recurringMonthDays, holidayNames };
20996
+ }
20997
+ getHolidayInfo(date, holidaySets) {
20998
+ const formattedDate = this.formatDateUTC(date);
20999
+ const monthDay = this.formatMonthDayUTC(date);
21000
+ if (holidaySets.exactDates.has(formattedDate)) {
21001
+ return {
21002
+ isHoliday: true,
21003
+ name: holidaySets.holidayNames?.get(`exact:${formattedDate}`)
21004
+ };
21005
+ }
21006
+ if (holidaySets.recurringMonthDays.has(monthDay)) {
21007
+ return {
21008
+ isHoliday: true,
21009
+ name: holidaySets.holidayNames?.get(`recurring:${monthDay}`)
21010
+ };
21011
+ }
21012
+ return { isHoliday: false };
21013
+ }
21014
+ parseToUTCDate(value) {
21015
+ if (value instanceof Date) {
21016
+ return this.toUTCDate(value);
21017
+ }
21018
+ if (typeof value === 'string' && value.match(/^\d{4}-\d{2}-\d{2}$/)) {
21019
+ const [year, month, day] = value.split('-').map(Number);
21020
+ return this.createUTCDate(year, month - 1, day);
21021
+ }
21022
+ const parsed = new Date(value);
21023
+ return Number.isNaN(parsed.getTime()) ? null : this.toUTCDate(parsed);
21024
+ }
21025
+ formatDateUTC(date) {
21026
+ const year = date.getUTCFullYear();
21027
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
21028
+ const day = String(date.getUTCDate()).padStart(2, '0');
21029
+ return `${year}-${month}-${day}`;
21030
+ }
21031
+ formatMonthDayUTC(date) {
21032
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
21033
+ const day = String(date.getUTCDate()).padStart(2, '0');
21034
+ return `${month}-${day}`;
21035
+ }
21036
+ onDayClick(day) {
21037
+ if (day.disabled)
21038
+ return;
21039
+ if (day.type !== DayType.CURRENT_MONTH) {
21040
+ const clickedDate = day.date;
21041
+ const currentDisplayDate = this.displayDate();
21042
+ const newDate = this.createUTCDate(clickedDate.getUTCFullYear(), clickedDate.getUTCMonth(), 1);
21043
+ const isNextMonth = clickedDate > currentDisplayDate;
21044
+ this.displayDate.set(newDate);
21045
+ this.generateCalendarDays();
21046
+ const navigationEvent = {
21047
+ type: isNextMonth ? 'next' : 'previous',
21048
+ currentDate: new Date(currentDisplayDate),
21049
+ newDate: new Date(newDate)
21050
+ };
21051
+ this.monthChanged.emit(navigationEvent);
21052
+ }
21053
+ const event = {
21054
+ selectedDate: day.date,
21055
+ calendarDay: day,
21056
+ formattedDate: this.formatDateUTC(day.date)
21057
+ };
21058
+ this.dateSelected.emit(event);
21059
+ }
21060
+ onPreviousMonth() {
21061
+ const currentDate = this.displayDate();
21062
+ const newDate = this.createUTCDate(currentDate.getUTCFullYear(), currentDate.getUTCMonth() - 1, 1);
21063
+ const event = {
21064
+ type: 'previous',
21065
+ currentDate: new Date(currentDate),
21066
+ newDate: new Date(newDate)
21067
+ };
21068
+ this.displayDate.set(newDate);
21069
+ this.generateCalendarDays();
21070
+ this.monthChanged.emit(event);
21071
+ }
21072
+ onNextMonth() {
21073
+ const currentDate = this.displayDate();
21074
+ const newDate = this.createUTCDate(currentDate.getUTCFullYear(), currentDate.getUTCMonth() + 1, 1);
21075
+ const event = {
21076
+ type: 'next',
21077
+ currentDate: new Date(currentDate),
21078
+ newDate: new Date(newDate)
21079
+ };
21080
+ this.displayDate.set(newDate);
21081
+ this.generateCalendarDays();
21082
+ this.monthChanged.emit(event);
21083
+ }
21084
+ resetToCurrentMonth() {
21085
+ const today = this.toUTCDate(new Date());
21086
+ const currentMonth = this.createUTCDate(today.getUTCFullYear(), today.getUTCMonth(), 1);
21087
+ if (this.displayDate().getTime() !== currentMonth.getTime()) {
21088
+ const event = {
21089
+ type: 'reset',
21090
+ currentDate: new Date(this.displayDate()),
21091
+ newDate: new Date(currentMonth)
21092
+ };
21093
+ this.displayDate.set(currentMonth);
21094
+ this.generateCalendarDays();
21095
+ this.monthChanged.emit(event);
21096
+ }
21097
+ }
21098
+ getDayClasses(day) {
21099
+ const classes = ['c-calendar__day'];
21100
+ if (day.type !== DayType.CURRENT_MONTH) {
21101
+ classes.push('not-current');
21102
+ }
21103
+ switch (day.state) {
21104
+ case DayState.CURRENT:
21105
+ classes.push('is-current');
21106
+ break;
21107
+ case DayState.ACTIVE:
21108
+ classes.push('is-active');
21109
+ break;
21110
+ }
21111
+ if (day.disabled) {
21112
+ classes.push('is-disabled');
21113
+ }
21114
+ if (day.isWeekend) {
21115
+ classes.push('is-weekend');
21116
+ }
21117
+ if (day.isHoliday) {
21118
+ classes.push('is-holiday');
21119
+ }
21120
+ return classes.join(' ');
21121
+ }
21122
+ getDayTitle(day) {
21123
+ if (day.isHoliday && day.holidayName) {
21124
+ return `${day.holidayName} - Día festivo`;
21125
+ }
21126
+ if (day.disabled && day.isHoliday) {
21127
+ return 'Día festivo - No disponible';
21128
+ }
21129
+ if (day.disabled) {
21130
+ return 'Día no disponible';
21131
+ }
21132
+ return '';
21133
+ }
21134
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21135
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: GenericCalendarComponent, isStandalone: true, selector: "core-generic-calendar", inputs: { currentDate: { classPropertyName: "currentDate", publicName: "currentDate", isSignal: true, isRequired: false, transformFunction: null }, selectedDate: { classPropertyName: "selectedDate", publicName: "selectedDate", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, showNavigation: { classPropertyName: "showNavigation", publicName: "showNavigation", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateSelected: "dateSelected", monthChanged: "monthChanged" }, ngImport: i0, template: "<div class=\"c-bookings-calendar c-bookings-card\">\n @if (showHeader()) {\n <div class=\"c-bookings-card__top\">\n <h3 class=\"c-bookings-subtitle\">\n {{ monthName() | titlecase }} {{ year() }}\n </h3>\n @if (showNavigation()) {\n <div class=\"u-flex\">\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-left\"\n title=\"Anterior\"\n (click)=\"onPreviousMonth()\"\n ></button>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n title=\"Siguiente\"\n (click)=\"onNextMonth()\"\n ></button>\n </div>\n }\n </div>\n }\n\n <div class=\"c-calendar u-push-t\">\n @for (dayLabel of weekDayLabels(); track $index) {\n <span class=\"c-calendar__day-header\">{{ dayLabel }}</span>\n } @for (day of calendarDays(); track day.date.getTime()) {\n <button\n [class]=\"getDayClasses(day)\"\n [disabled]=\"day.disabled\"\n (click)=\"onDayClick(day)\"\n [title]=\"getDayTitle(day) || day.date.toLocaleDateString(locale())\"\n >\n {{ day.dayNumber }}\n </button>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2.TitleCasePipe, name: "titlecase" }] });
21136
+ }
21137
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericCalendarComponent, decorators: [{
21138
+ type: Component,
21139
+ args: [{ selector: 'core-generic-calendar', standalone: true, imports: [CommonModule], template: "<div class=\"c-bookings-calendar c-bookings-card\">\n @if (showHeader()) {\n <div class=\"c-bookings-card__top\">\n <h3 class=\"c-bookings-subtitle\">\n {{ monthName() | titlecase }} {{ year() }}\n </h3>\n @if (showNavigation()) {\n <div class=\"u-flex\">\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-left\"\n title=\"Anterior\"\n (click)=\"onPreviousMonth()\"\n ></button>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n title=\"Siguiente\"\n (click)=\"onNextMonth()\"\n ></button>\n </div>\n }\n </div>\n }\n\n <div class=\"c-calendar u-push-t\">\n @for (dayLabel of weekDayLabels(); track $index) {\n <span class=\"c-calendar__day-header\">{{ dayLabel }}</span>\n } @for (day of calendarDays(); track day.date.getTime()) {\n <button\n [class]=\"getDayClasses(day)\"\n [disabled]=\"day.disabled\"\n (click)=\"onDayClick(day)\"\n [title]=\"getDayTitle(day) || day.date.toLocaleDateString(locale())\"\n >\n {{ day.dayNumber }}\n </button>\n }\n </div>\n</div>\n" }]
21140
+ }], ctorParameters: () => [] });
21141
+
21142
+ const DEFAULT_SCHEDULER_CONFIG = {
21143
+ startHour: 6,
21144
+ endHour: 20,
21145
+ slotDuration: 30,
21146
+ rowHeightRem: 4,
21147
+ showCurrentTimeLine: true,
21148
+ locale: 'es-ES'
21149
+ };
21150
+
21151
+ class GenericSchedulerComponent {
21152
+ selectedDate = input(new Date());
21153
+ columns = input([]);
21154
+ events = input([]);
21155
+ config = input({});
21156
+ showTimeColumn = input(true);
21157
+ showHeader = input(true);
21158
+ timeColumnLabel = input('H');
21159
+ emptySlotLabel = input('Disponible');
21160
+ disabledSlotLabel = input('No disponible');
21161
+ todayLabel = input('Hoy');
21162
+ locale = input('es-ES');
21163
+ slotClick = output();
21164
+ eventClick = output();
21165
+ eventHover = output();
21166
+ eventLeave = output();
21167
+ todayClick = output();
21168
+ previousDay = output();
21169
+ nextDay = output();
21170
+ timeSlots = signal([]);
21171
+ currentTime = signal(new Date());
21172
+ timeUpdateInterval = null;
21173
+ mergedConfig = computed(() => ({ ...DEFAULT_SCHEDULER_CONFIG, ...this.config() }));
21174
+ isToday = computed(() => {
21175
+ const selected = this.selectedDate();
21176
+ const today = new Date();
21177
+ return selected.getUTCFullYear() === today.getUTCFullYear() &&
21178
+ selected.getUTCMonth() === today.getUTCMonth() &&
21179
+ selected.getUTCDate() === today.getUTCDate();
21180
+ });
21181
+ formattedDate = computed(() => {
21182
+ const date = this.selectedDate();
21183
+ const localeValue = this.locale();
21184
+ return date.toLocaleDateString(localeValue, {
21185
+ weekday: 'long',
21186
+ year: 'numeric',
21187
+ month: 'long',
21188
+ day: 'numeric',
21189
+ timeZone: 'UTC'
21190
+ });
21191
+ });
21192
+ currentTimePosition = computed(() => {
21193
+ if (!this.isToday() || !this.mergedConfig().showCurrentTimeLine)
21194
+ return null;
21195
+ const now = this.currentTime();
21196
+ const hours = now.getUTCHours();
21197
+ const minutes = now.getUTCMinutes();
21198
+ const cfg = this.mergedConfig();
21199
+ if (hours < cfg.startHour || hours >= cfg.endHour) {
21200
+ return null;
21201
+ }
21202
+ const minutesFromStart = (hours - cfg.startHour) * 60 + minutes;
21203
+ const slotsFromStart = minutesFromStart / cfg.slotDuration;
21204
+ const positionInRem = slotsFromStart * cfg.rowHeightRem;
21205
+ return positionInRem;
21206
+ });
21207
+ eventMap = computed(() => {
21208
+ const map = new Map();
21209
+ const evts = this.events();
21210
+ evts.forEach(event => {
21211
+ const key = event.columnId;
21212
+ if (!map.has(key)) {
21213
+ map.set(key, []);
21214
+ }
21215
+ map.get(key).push(event);
21216
+ });
21217
+ return map;
21218
+ });
21219
+ ngOnInit() {
21220
+ this.initializeTimeSlots();
21221
+ this.startTimeUpdater();
21222
+ }
21223
+ ngOnDestroy() {
21224
+ this.stopTimeUpdater();
21225
+ }
21226
+ initializeTimeSlots() {
21227
+ const cfg = this.mergedConfig();
21228
+ const slots = [];
21229
+ for (let hour = cfg.startHour; hour < cfg.endHour; hour++) {
21230
+ for (let minutes = 0; minutes < 60; minutes += cfg.slotDuration) {
21231
+ const timeString = `${hour.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
21232
+ const isHalfHour = minutes !== 0;
21233
+ slots.push({
21234
+ time: timeString,
21235
+ hour,
21236
+ minutes,
21237
+ isHalfHour,
21238
+ displayTime: !isHalfHour
21239
+ });
21240
+ }
21241
+ }
21242
+ this.timeSlots.set(slots);
21243
+ }
21244
+ startTimeUpdater() {
21245
+ this.currentTime.set(new Date());
21246
+ this.timeUpdateInterval = setInterval(() => {
21247
+ this.currentTime.set(new Date());
21248
+ }, 60000);
21249
+ }
21250
+ stopTimeUpdater() {
21251
+ if (this.timeUpdateInterval) {
21252
+ clearInterval(this.timeUpdateInterval);
21253
+ this.timeUpdateInterval = null;
21254
+ }
21255
+ }
21256
+ isSlotOccupied(columnId, slot) {
21257
+ const evts = this.eventMap().get(columnId) || [];
21258
+ return evts.some(event => this.isTimeInEvent(slot.time, event));
21259
+ }
21260
+ shouldShowEvent(columnId, slot) {
21261
+ const evts = this.eventMap().get(columnId) || [];
21262
+ return evts.some(event => event.startTime === slot.time);
21263
+ }
21264
+ getEventForSlot(columnId, slot) {
21265
+ const evts = this.eventMap().get(columnId) || [];
21266
+ return evts.find(event => event.startTime === slot.time);
21267
+ }
21268
+ getEventRowSpan(event) {
21269
+ if (event.rowSpan)
21270
+ return event.rowSpan;
21271
+ const cfg = this.mergedConfig();
21272
+ const slotsPerHour = 60 / cfg.slotDuration;
21273
+ return Math.ceil(event.duration / cfg.slotDuration) || 1;
21274
+ }
21275
+ isTimeInEvent(time, event) {
21276
+ const [slotHour, slotMin] = time.split(':').map(Number);
21277
+ const [startHour, startMin] = event.startTime.split(':').map(Number);
21278
+ const [endHour, endMin] = event.endTime.split(':').map(Number);
21279
+ const slotMinutes = slotHour * 60 + slotMin;
21280
+ const startMinutes = startHour * 60 + startMin;
21281
+ const endMinutes = endHour * 60 + endMin;
21282
+ return slotMinutes >= startMinutes && slotMinutes < endMinutes;
21283
+ }
21284
+ isSlotDisabled(columnId, slot) {
21285
+ const now = new Date();
21286
+ const selected = this.selectedDate();
21287
+ const todayUTC = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
21288
+ const selectedUTC = Date.UTC(selected.getUTCFullYear(), selected.getUTCMonth(), selected.getUTCDate());
21289
+ if (selectedUTC < todayUTC) {
21290
+ return true;
21291
+ }
21292
+ if (selectedUTC === todayUTC) {
21293
+ const [slotHour, slotMin] = slot.time.split(':').map(Number);
21294
+ const slotMinutes = slotHour * 60 + slotMin;
21295
+ const currentMinutes = now.getUTCHours() * 60 + now.getUTCMinutes();
21296
+ return slotMinutes < currentMinutes;
21297
+ }
21298
+ return false;
21299
+ }
21300
+ onSlotClick(columnId, slot) {
21301
+ if (this.isSlotOccupied(columnId, slot) || this.isSlotDisabled(columnId, slot)) {
21302
+ return;
21303
+ }
21304
+ this.slotClick.emit({
21305
+ columnId,
21306
+ slot,
21307
+ date: this.selectedDate()
21308
+ });
21309
+ }
21310
+ onEventClick(event, column) {
21311
+ this.eventClick.emit({ event, column });
21312
+ }
21313
+ onEventHover(mouseEvent, event) {
21314
+ this.eventHover.emit({
21315
+ event,
21316
+ position: { x: mouseEvent.clientX, y: mouseEvent.clientY }
21317
+ });
21318
+ }
21319
+ onEventLeave() {
21320
+ this.eventLeave.emit();
21321
+ }
21322
+ getEventClasses(event) {
21323
+ const classes = ['c-bookings-grid__booking'];
21324
+ if (event.type) {
21325
+ classes.push(`c-bookings-grid__booking--${event.type}`);
21326
+ }
21327
+ return classes.join(' ');
21328
+ }
21329
+ onTodayClick() {
21330
+ this.todayClick.emit();
21331
+ }
21332
+ onPreviousDay() {
21333
+ const current = this.selectedDate();
21334
+ const prevDay = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate() - 1));
21335
+ this.previousDay.emit(prevDay);
21336
+ }
21337
+ onNextDay() {
21338
+ const current = this.selectedDate();
21339
+ const nextDayDate = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate() + 1));
21340
+ this.nextDay.emit(nextDayDate);
21341
+ }
21342
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericSchedulerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21343
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: GenericSchedulerComponent, isStandalone: true, selector: "core-generic-scheduler", inputs: { selectedDate: { classPropertyName: "selectedDate", publicName: "selectedDate", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, showTimeColumn: { classPropertyName: "showTimeColumn", publicName: "showTimeColumn", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, timeColumnLabel: { classPropertyName: "timeColumnLabel", publicName: "timeColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, emptySlotLabel: { classPropertyName: "emptySlotLabel", publicName: "emptySlotLabel", isSignal: true, isRequired: false, transformFunction: null }, disabledSlotLabel: { classPropertyName: "disabledSlotLabel", publicName: "disabledSlotLabel", isSignal: true, isRequired: false, transformFunction: null }, todayLabel: { classPropertyName: "todayLabel", publicName: "todayLabel", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { slotClick: "slotClick", eventClick: "eventClick", eventHover: "eventHover", eventLeave: "eventLeave", todayClick: "todayClick", previousDay: "previousDay", nextDay: "nextDay" }, host: { properties: { "style.--cols": "columns().length" }, classAttribute: "c-bookings-grid c-bookings-card" }, ngImport: i0, template: "@if (showHeader()) {\n<div class=\"c-bookings-header\">\n <button class=\"c-bookings-header__today\" (click)=\"onTodayClick()\">\n {{ todayLabel() }}\n </button>\n\n <div class=\"c-bookings-header__date\">\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-left\"\n title=\"D\u00EDa anterior\"\n (click)=\"onPreviousDay()\"\n ></button>\n <span>{{ formattedDate() }}</span>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n title=\"D\u00EDa siguiente\"\n (click)=\"onNextDay()\"\n ></button>\n </div>\n</div>\n}\n\n<div\n class=\"c-bookings-grid__wrapper\"\n [style.--cols]=\"columns().length\"\n style=\"position: relative\"\n>\n @if (isToday() && currentTimePosition() !== null) {\n <div\n class=\"c-bookings-grid__current-time-line\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top\">\n <div class=\"c-bookings-grid__title\">{{ timeColumnLabel() }}</div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (slot.displayTime) {\n <span class=\"c-bookings-grid__time\">{{ slot.time }}</span>\n }\n </div>\n }\n </div>\n } @for (column of columns(); track column.id) {\n <div class=\"c-bookings-grid__col\">\n <div class=\"c-bookings-grid__top\">\n <p class=\"c-bookings-grid__title\">{{ column.name }}</p>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupied(column.id, slot)) { @if (isSlotDisabled(column.id,\n slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n >\n {{ disabledSlotLabel() }}\n </button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onSlotClick(column.id, slot)\"\n >\n {{ emptySlotLabel() }}\n </button>\n } } @if (shouldShowEvent(column.id, slot)) { @let event =\n getEventForSlot(column.id, slot); @if (event) {\n <div\n [class]=\"getEventClasses(event)\"\n [attr.data-type]=\"event.type\"\n [attr.data-status]=\"event.status\"\n [style.--rows]=\"getEventRowSpan(event)\"\n (mouseenter)=\"onEventHover($event, event)\"\n (mouseleave)=\"onEventLeave()\"\n (click)=\"onEventClick(event, column)\"\n >\n <p class=\"c-bookings-grid__title\">\n {{ event.subtitle || event.title }}\n </p>\n <p class=\"c-bookings-grid__text\">\n {{ event.startTime }} - {{ event.endTime }}\n </p>\n\n @if (event.canCancel) {\n <button\n class=\"c-bookings-grid__link c-link--underlined\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"icon-cross-thin\"></span>\n Cancelar\n </button>\n } @if ((event.canApprove || event.canReject) && event.duration >= 91) {\n <div class=\"c-bookings-grid__quick-actions\">\n @if (event.canApprove) {\n <button\n class=\"c-icon-btn--fill context:success icon-check\"\n title=\"Aprobar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n } @if (event.canReject) {\n <button\n class=\"c-icon-btn--fill context:error icon-cross\"\n title=\"Rechazar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n }\n </div>\n }\n </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;overflow:visible}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
21344
+ }
21345
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericSchedulerComponent, decorators: [{
21346
+ type: Component,
21347
+ args: [{ selector: 'core-generic-scheduler', standalone: true, imports: [CommonModule], host: {
21348
+ 'class': 'c-bookings-grid c-bookings-card',
21349
+ '[style.--cols]': 'columns().length'
21350
+ }, template: "@if (showHeader()) {\n<div class=\"c-bookings-header\">\n <button class=\"c-bookings-header__today\" (click)=\"onTodayClick()\">\n {{ todayLabel() }}\n </button>\n\n <div class=\"c-bookings-header__date\">\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-left\"\n title=\"D\u00EDa anterior\"\n (click)=\"onPreviousDay()\"\n ></button>\n <span>{{ formattedDate() }}</span>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n title=\"D\u00EDa siguiente\"\n (click)=\"onNextDay()\"\n ></button>\n </div>\n</div>\n}\n\n<div\n class=\"c-bookings-grid__wrapper\"\n [style.--cols]=\"columns().length\"\n style=\"position: relative\"\n>\n @if (isToday() && currentTimePosition() !== null) {\n <div\n class=\"c-bookings-grid__current-time-line\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top\">\n <div class=\"c-bookings-grid__title\">{{ timeColumnLabel() }}</div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (slot.displayTime) {\n <span class=\"c-bookings-grid__time\">{{ slot.time }}</span>\n }\n </div>\n }\n </div>\n } @for (column of columns(); track column.id) {\n <div class=\"c-bookings-grid__col\">\n <div class=\"c-bookings-grid__top\">\n <p class=\"c-bookings-grid__title\">{{ column.name }}</p>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupied(column.id, slot)) { @if (isSlotDisabled(column.id,\n slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n >\n {{ disabledSlotLabel() }}\n </button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onSlotClick(column.id, slot)\"\n >\n {{ emptySlotLabel() }}\n </button>\n } } @if (shouldShowEvent(column.id, slot)) { @let event =\n getEventForSlot(column.id, slot); @if (event) {\n <div\n [class]=\"getEventClasses(event)\"\n [attr.data-type]=\"event.type\"\n [attr.data-status]=\"event.status\"\n [style.--rows]=\"getEventRowSpan(event)\"\n (mouseenter)=\"onEventHover($event, event)\"\n (mouseleave)=\"onEventLeave()\"\n (click)=\"onEventClick(event, column)\"\n >\n <p class=\"c-bookings-grid__title\">\n {{ event.subtitle || event.title }}\n </p>\n <p class=\"c-bookings-grid__text\">\n {{ event.startTime }} - {{ event.endTime }}\n </p>\n\n @if (event.canCancel) {\n <button\n class=\"c-bookings-grid__link c-link--underlined\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"icon-cross-thin\"></span>\n Cancelar\n </button>\n } @if ((event.canApprove || event.canReject) && event.duration >= 91) {\n <div class=\"c-bookings-grid__quick-actions\">\n @if (event.canApprove) {\n <button\n class=\"c-icon-btn--fill context:success icon-check\"\n title=\"Aprobar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n } @if (event.canReject) {\n <button\n class=\"c-icon-btn--fill context:error icon-cross\"\n title=\"Rechazar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n }\n </div>\n }\n </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;overflow:visible}\n"] }]
21351
+ }] });
21352
+
20485
21353
  class CacheBustingInterceptor {
20486
21354
  intercept(req, next) {
20487
21355
  if (req.url.includes('/assets/i18n/') && req.url.endsWith('.json')) {
@@ -20763,5 +21631,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
20763
21631
  * Generated bundle index. Do not edit.
20764
21632
  */
20765
21633
 
20766
- export { AD_AUTH_CONFIG, AD_AUTH_INTERCEPTOR_CONFIG, ALL_COUNTRY_CODES, ActiveFiltersComponent, AdAuthService, AdInteractionType, AdLoginButtonComponent, 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_AD_AUTH_INTERCEPTOR_CONFIG, 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, MODEL_REFERENCE_SORT_KEY, 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, RedirectUrlService, 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, adAuthGuard, adAuthInterceptor, adGuestGuard, adRoleGuard, ageValidator, calculateAge, equalToValidator, generateRandomUruguayanDocument, getCountryCodeStrings, getLatestBirthDateForAge, getRandomCi, getUruguayanDocumentValidationDigit, getValidationDigit, isSameDate, isValidCountryCode, provideAdAuth, provideAdAuthInterceptor, provideAdAuthWithInterceptor, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader, random, transform, transformUruguayanDocument, uruguayanDocumentValidator, validate, validateAge, validateCi, validateUruguayanDocument, validationDigit };
21634
+ export { AD_AUTH_CONFIG, AD_AUTH_INTERCEPTOR_CONFIG, ALL_COUNTRY_CODES, ActiveFiltersComponent, AdAuthService, AdInteractionType, AdLoginButtonComponent, AgeValidationHelper, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, COMMON_COUNTRIES, CacheBustingInterceptor, CalendarEventType, CardComponent, CarouselComponent, ChatMessagePosition, ChatMessageType, CheckboxFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreManualRefreshComponent, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, CountryCode, CustomClassService, DEFAULT_AD_AUTH_INTERCEPTOR_CONFIG, DEFAULT_COUNTRIES, DEFAULT_SCHEDULER_CONFIG, DataListComponent, DataListItemComponent, DataStoreService, DateFieldComponent, DateUtility, DatetimeFieldComponent, DayState, DayType, 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, GenericCalendarComponent, GenericChatComponent, GenericChatService, GenericDocumentationComponent, GenericFixedActionsComponent, GenericGalleryComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSchedulerComponent, 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, MODEL_REFERENCE_SORT_KEY, 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, RedirectUrlService, 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, WeekDay, adAuthGuard, adAuthInterceptor, adGuestGuard, adRoleGuard, ageValidator, calculateAge, equalToValidator, generateRandomUruguayanDocument, getCountryCodeStrings, getLatestBirthDateForAge, getRandomCi, getUruguayanDocumentValidationDigit, getValidationDigit, isSameDate, isValidCountryCode, provideAdAuth, provideAdAuthInterceptor, provideAdAuthWithInterceptor, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader, random, transform, transformUruguayanDocument, uruguayanDocumentValidator, validate, validateAge, validateCi, validateUruguayanDocument, validationDigit };
20767
21635
  //# sourceMappingURL=solcre-org-core-ui.mjs.map