@solcre-org/core-ui 2.16.4 → 2.17.1
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.
|
@@ -578,6 +578,95 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
|
|
|
578
578
|
args: [{ selector: 'core-checkbox-field', standalone: true, imports: [CommonModule, FormsModule, ReactiveFormsModule, TranslateModule, FieldErrorsComponent], hostDirectives: [CoreHostDirective], template: "<!-- Clase para layout inline cuando hay m\u00FAltiples opciones -->\n<div class=\"c-entry-toggle-holder\" [class.hasSeparatedOptions]=\"hasSeparatedOptions()\" [class.multiple-inline]=\"hasMultipleOptions()\">\n\n <span class=\"c-entry-text\"\n *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredIndicator()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n \n @if (hasMultipleOptions()) {\n @for (option of options(); track option.value) {\n\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"cannotDeselect(option)\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (!allowMultiple() && isRequired()) {\n <!-- Cuando allowMultiple: false y required: true, usar radio buttons para todas las opciones -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else if (cannotDeselect(option)) {\n <!-- Usar radio cuando no se puede deseleccionar (modo m\u00FAltiple con una sola opci\u00F3n) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"allowMultiple() ? field().key.toString() + '[]' : field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n\n <span class=\"c-entry-toggle__text\">\n {{ option.label | translate }}\n @if(option.externalLink) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"option.externalLink\" target=\"_blank\"></a>\n }\n </span>\n @if(option.detail) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ option.detail }}</span>\n }\n </label>\n\n }\n } @else {\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"isRequired() && !!formControl().value\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (isRequired() && !!formControl().value) {\n <!-- Usar radio cuando es requerido y tiene valor (cannot-deselect) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"!!formControl().value\"\n (change)=\"onRadioChange($event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [formControl]=\"formControl()\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n <span class=\"c-entry-toggle__text\">\n {{ field().label | translate }}\n @if (hasRequiredIndicator()) {\n <span class=\"c-required\">*</span>\n }\n @if(externalLink()) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"externalLink()\" target=\"_blank\"></a>\n }\n </span>\n @if(detail()) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ detail() }}</span>\n }\n </label>\n }\n\n <core-field-errors [errors]=\"errors()\" />\n</div> \n ", styles: [".cannot-deselect{pointer-events:none;cursor:not-allowed}.c-entry-text+.c-entry-toggle-holder.hasSeparatedOptions{margin-top:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions .c-entry-text{grid-column:span 2;margin-top:1em}\n"] }]
|
|
579
579
|
}], ctorParameters: () => [] });
|
|
580
580
|
|
|
581
|
+
const DEFAULT_COLORS = [
|
|
582
|
+
'#4285f4', '#ea4335', '#34a853', '#fbbc04',
|
|
583
|
+
'#9c27b0', '#00bcd4', '#ff5722', '#795548',
|
|
584
|
+
'#607d8b', '#e91e63', '#3f51b5', '#009688',
|
|
585
|
+
'#ff9800', '#673ab7', '#2196f3', '#4caf50'
|
|
586
|
+
];
|
|
587
|
+
class ColorPickerFieldComponent extends BaseFieldComponent {
|
|
588
|
+
isPickerOpen = signal(false);
|
|
589
|
+
presetColors = signal(DEFAULT_COLORS);
|
|
590
|
+
constructor() {
|
|
591
|
+
super();
|
|
592
|
+
effect(() => {
|
|
593
|
+
const shouldDisable = this.mode() === ModalMode.VIEW || this.evaluateReadonly();
|
|
594
|
+
const control = this.formControl();
|
|
595
|
+
if (shouldDisable && control.enabled) {
|
|
596
|
+
control.disable();
|
|
597
|
+
}
|
|
598
|
+
else if (!shouldDisable && control.disabled) {
|
|
599
|
+
control.enable();
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
effect(() => {
|
|
603
|
+
const fieldConfig = this.field();
|
|
604
|
+
if (fieldConfig.presetColors && Array.isArray(fieldConfig.presetColors)) {
|
|
605
|
+
this.presetColors.set(fieldConfig.presetColors);
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
isDisabled() {
|
|
610
|
+
return this.mode() === ModalMode.VIEW || this.evaluateReadonly();
|
|
611
|
+
}
|
|
612
|
+
togglePicker() {
|
|
613
|
+
if (!this.isDisabled()) {
|
|
614
|
+
this.isPickerOpen.update(open => !open);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
closePicker() {
|
|
618
|
+
this.isPickerOpen.set(false);
|
|
619
|
+
}
|
|
620
|
+
selectColor(color) {
|
|
621
|
+
if (!this.isDisabled()) {
|
|
622
|
+
this.formControl().setValue(color);
|
|
623
|
+
this.valueChange.emit(color);
|
|
624
|
+
this.closePicker();
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
onColorInputChange(event) {
|
|
628
|
+
const input = event.target;
|
|
629
|
+
const color = input.value;
|
|
630
|
+
this.formControl().setValue(color);
|
|
631
|
+
this.valueChange.emit(color);
|
|
632
|
+
}
|
|
633
|
+
onTextInputChange(event) {
|
|
634
|
+
const input = event.target;
|
|
635
|
+
let color = input.value;
|
|
636
|
+
if (color && !color.startsWith('#')) {
|
|
637
|
+
color = '#' + color;
|
|
638
|
+
}
|
|
639
|
+
if (this.isValidHexColor(color)) {
|
|
640
|
+
this.formControl().setValue(color);
|
|
641
|
+
this.valueChange.emit(color);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
isValidHexColor(color) {
|
|
645
|
+
return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
|
|
646
|
+
}
|
|
647
|
+
getCurrentColor() {
|
|
648
|
+
const value = this.formControl().value;
|
|
649
|
+
return value && this.isValidHexColor(value) ? value : '#4783E1';
|
|
650
|
+
}
|
|
651
|
+
onBlurInput(event) {
|
|
652
|
+
setTimeout(() => {
|
|
653
|
+
if (!this.isPickerOpen()) {
|
|
654
|
+
this.onBlur(event);
|
|
655
|
+
}
|
|
656
|
+
}, 200);
|
|
657
|
+
}
|
|
658
|
+
handleEnterKey(event) {
|
|
659
|
+
const keyboardEvent = event;
|
|
660
|
+
this.onEnterInput(keyboardEvent);
|
|
661
|
+
}
|
|
662
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ColorPickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
663
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: ColorPickerFieldComponent, isStandalone: true, selector: "core-color-picker-field", usesInheritance: true, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<label class=\"c-entry-item\" [class.c-entry-item--inline]=\"field().inline\">\n <span class=\"c-entry-text\" *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n\n <div class=\"c-entry-input c-entry-input--color\"\n [class.is-readonly]=\"isReadonly()\"\n [class.is-disabled]=\"isDisabled()\">\n <div class=\"c-color-picker\">\n <div class=\"c-color-picker__preview-wrapper\">\n <div \n class=\"c-color-picker__preview\"\n [style.background-color]=\"getCurrentColor()\"\n (click)=\"togglePicker()\"\n [class.c-color-picker__preview--disabled]=\"isDisabled()\">\n </div>\n \n <input\n type=\"text\"\n class=\"c-color-picker__text-input\"\n [id]=\"field().key\"\n [formControl]=\"formControl()\"\n [placeholder]=\"(field().placeholder ?? '#4783E1') | translate\"\n [class.c-color-picker__text-input--disabled]=\"isDisabled()\"\n [class.c-color-picker__text-input--error]=\"hasError()\"\n (input)=\"onTextInputChange($event)\"\n (blur)=\"onBlurInput($event)\"\n (keydown.enter)=\"handleEnterKey($event)\"\n maxlength=\"7\"\n />\n \n <input\n type=\"color\"\n class=\"c-color-picker__native-input\"\n [value]=\"getCurrentColor()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onColorInputChange($event)\"\n />\n </div>\n\n @if (isPickerOpen()) {\n <div class=\"c-color-picker__dropdown\">\n <div class=\"c-color-picker__preset-colors\">\n @for (color of presetColors(); track color) {\n <button\n type=\"button\"\n class=\"c-color-picker__preset-color\"\n [style.background-color]=\"color\"\n [class.c-color-picker__preset-color--selected]=\"getCurrentColor() === color\"\n (click)=\"selectColor(color)\"\n [title]=\"color\">\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <core-field-errors [errors]=\"errors()\"></core-field-errors>\n</label>\n", styles: [".c-color-picker{position:relative;width:100%}.c-color-picker__preview-wrapper{display:flex;align-items:center;gap:8px}.c-color-picker__preview{width:36px;height:36px;border-radius:6px;border:2px solid var(--color-border, #e0e0e0);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease;flex-shrink:0}.c-color-picker__preview:hover:not(.c-color-picker__preview--disabled){border-color:var(--color-primary, #4783E1);box-shadow:0 0 0 2px #4783e133}.c-color-picker__preview--disabled{cursor:not-allowed;opacity:.6}.c-color-picker__text-input{flex:1;height:36px;padding:0 12px;font-size:14px;font-family:monospace;text-transform:uppercase;border:1px solid var(--color-border, #e0e0e0);border-radius:6px;background-color:var(--color-background, #fff);transition:border-color .2s ease,box-shadow .2s ease}.c-color-picker__text-input:focus{outline:none;border-color:var(--color-primary, #4783E1);box-shadow:0 0 0 2px #4783e133}.c-color-picker__text-input--disabled{background-color:var(--color-disabled-bg, #f5f5f5);cursor:not-allowed;opacity:.6}.c-color-picker__text-input--error{border-color:var(--color-danger, #dc3545)}.c-color-picker__text-input--error:focus{box-shadow:0 0 0 2px #dc354533}.c-color-picker__native-input{width:36px;height:36px;padding:0;border:none;border-radius:6px;cursor:pointer;flex-shrink:0}.c-color-picker__native-input::-webkit-color-swatch-wrapper{padding:0}.c-color-picker__native-input::-webkit-color-swatch{border:2px solid var(--color-border, #e0e0e0);border-radius:6px}.c-color-picker__native-input:disabled{cursor:not-allowed;opacity:.6}.c-color-picker__dropdown{position:absolute;top:calc(100% + 8px);left:0;z-index:1000;background-color:var(--color-background, #fff);border:1px solid var(--color-border, #e0e0e0);border-radius:8px;box-shadow:0 4px 12px #00000026;padding:12px;min-width:200px}.c-color-picker__preset-colors{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.c-color-picker__preset-color{width:32px;height:32px;border:2px solid transparent;border-radius:6px;cursor:pointer;padding:0;transition:transform .15s ease,border-color .15s ease}.c-color-picker__preset-color:hover{transform:scale(1.1)}.c-color-picker__preset-color--selected{border-color:var(--color-text, #333);box-shadow:0 0 0 2px var(--color-background, #fff),0 0 0 4px var(--color-primary, #4783E1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FieldErrorsComponent, selector: "core-field-errors", inputs: ["errors"] }] });
|
|
664
|
+
}
|
|
665
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ColorPickerFieldComponent, decorators: [{
|
|
666
|
+
type: Component,
|
|
667
|
+
args: [{ selector: 'core-color-picker-field', standalone: true, imports: [CommonModule, FormsModule, TranslateModule, ReactiveFormsModule, FieldErrorsComponent], hostDirectives: [CoreHostDirective], template: "<label class=\"c-entry-item\" [class.c-entry-item--inline]=\"field().inline\">\n <span class=\"c-entry-text\" *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n\n <div class=\"c-entry-input c-entry-input--color\"\n [class.is-readonly]=\"isReadonly()\"\n [class.is-disabled]=\"isDisabled()\">\n <div class=\"c-color-picker\">\n <div class=\"c-color-picker__preview-wrapper\">\n <div \n class=\"c-color-picker__preview\"\n [style.background-color]=\"getCurrentColor()\"\n (click)=\"togglePicker()\"\n [class.c-color-picker__preview--disabled]=\"isDisabled()\">\n </div>\n \n <input\n type=\"text\"\n class=\"c-color-picker__text-input\"\n [id]=\"field().key\"\n [formControl]=\"formControl()\"\n [placeholder]=\"(field().placeholder ?? '#4783E1') | translate\"\n [class.c-color-picker__text-input--disabled]=\"isDisabled()\"\n [class.c-color-picker__text-input--error]=\"hasError()\"\n (input)=\"onTextInputChange($event)\"\n (blur)=\"onBlurInput($event)\"\n (keydown.enter)=\"handleEnterKey($event)\"\n maxlength=\"7\"\n />\n \n <input\n type=\"color\"\n class=\"c-color-picker__native-input\"\n [value]=\"getCurrentColor()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onColorInputChange($event)\"\n />\n </div>\n\n @if (isPickerOpen()) {\n <div class=\"c-color-picker__dropdown\">\n <div class=\"c-color-picker__preset-colors\">\n @for (color of presetColors(); track color) {\n <button\n type=\"button\"\n class=\"c-color-picker__preset-color\"\n [style.background-color]=\"color\"\n [class.c-color-picker__preset-color--selected]=\"getCurrentColor() === color\"\n (click)=\"selectColor(color)\"\n [title]=\"color\">\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <core-field-errors [errors]=\"errors()\"></core-field-errors>\n</label>\n", styles: [".c-color-picker{position:relative;width:100%}.c-color-picker__preview-wrapper{display:flex;align-items:center;gap:8px}.c-color-picker__preview{width:36px;height:36px;border-radius:6px;border:2px solid var(--color-border, #e0e0e0);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease;flex-shrink:0}.c-color-picker__preview:hover:not(.c-color-picker__preview--disabled){border-color:var(--color-primary, #4783E1);box-shadow:0 0 0 2px #4783e133}.c-color-picker__preview--disabled{cursor:not-allowed;opacity:.6}.c-color-picker__text-input{flex:1;height:36px;padding:0 12px;font-size:14px;font-family:monospace;text-transform:uppercase;border:1px solid var(--color-border, #e0e0e0);border-radius:6px;background-color:var(--color-background, #fff);transition:border-color .2s ease,box-shadow .2s ease}.c-color-picker__text-input:focus{outline:none;border-color:var(--color-primary, #4783E1);box-shadow:0 0 0 2px #4783e133}.c-color-picker__text-input--disabled{background-color:var(--color-disabled-bg, #f5f5f5);cursor:not-allowed;opacity:.6}.c-color-picker__text-input--error{border-color:var(--color-danger, #dc3545)}.c-color-picker__text-input--error:focus{box-shadow:0 0 0 2px #dc354533}.c-color-picker__native-input{width:36px;height:36px;padding:0;border:none;border-radius:6px;cursor:pointer;flex-shrink:0}.c-color-picker__native-input::-webkit-color-swatch-wrapper{padding:0}.c-color-picker__native-input::-webkit-color-swatch{border:2px solid var(--color-border, #e0e0e0);border-radius:6px}.c-color-picker__native-input:disabled{cursor:not-allowed;opacity:.6}.c-color-picker__dropdown{position:absolute;top:calc(100% + 8px);left:0;z-index:1000;background-color:var(--color-background, #fff);border:1px solid var(--color-border, #e0e0e0);border-radius:8px;box-shadow:0 4px 12px #00000026;padding:12px;min-width:200px}.c-color-picker__preset-colors{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.c-color-picker__preset-color{width:32px;height:32px;border:2px solid transparent;border-radius:6px;cursor:pointer;padding:0;transition:transform .15s ease,border-color .15s ease}.c-color-picker__preset-color:hover{transform:scale(1.1)}.c-color-picker__preset-color--selected{border-color:var(--color-text, #333);box-shadow:0 0 0 2px var(--color-background, #fff),0 0 0 4px var(--color-primary, #4783E1)}\n"] }]
|
|
668
|
+
}], ctorParameters: () => [] });
|
|
669
|
+
|
|
581
670
|
class DateFieldComponent extends BaseFieldComponent {
|
|
582
671
|
elementRef;
|
|
583
672
|
isPickerOpen = false;
|
|
@@ -766,8 +855,8 @@ class DatetimeFieldComponent {
|
|
|
766
855
|
ModalMode = ModalMode;
|
|
767
856
|
TimeInterval = TimeInterval;
|
|
768
857
|
selectedDate = signal(null);
|
|
769
|
-
selectedHour = signal(
|
|
770
|
-
selectedMinute = signal(
|
|
858
|
+
selectedHour = signal(null);
|
|
859
|
+
selectedMinute = signal(null);
|
|
771
860
|
hasHourValue = signal(false);
|
|
772
861
|
hasMinuteValue = signal(false);
|
|
773
862
|
hours = Array.from({ length: 24 }, (_, i) => i);
|
|
@@ -922,24 +1011,33 @@ class DatetimeFieldComponent {
|
|
|
922
1011
|
this.selectedMinute.set(roundedMinute);
|
|
923
1012
|
}
|
|
924
1013
|
else {
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
this.
|
|
928
|
-
this.selectedHour.set(0);
|
|
929
|
-
this.selectedMinute.set(0);
|
|
1014
|
+
this.selectedDate.set(null);
|
|
1015
|
+
this.selectedHour.set(null);
|
|
1016
|
+
this.selectedMinute.set(null);
|
|
930
1017
|
}
|
|
931
1018
|
}
|
|
932
1019
|
onDateChange(event) {
|
|
933
1020
|
const input = event.target;
|
|
934
1021
|
const newDate = input.value ? new Date(input.value + 'T00:00:00') : null;
|
|
935
1022
|
if (newDate && !isNaN(newDate.getTime())) {
|
|
936
|
-
|
|
937
|
-
|
|
1023
|
+
// If hour/minute not set, default to 0
|
|
1024
|
+
const currentHour = this.selectedHour() ?? 0;
|
|
1025
|
+
const currentMinute = this.selectedMinute() ?? 0;
|
|
1026
|
+
this.selectedHour.set(currentHour);
|
|
1027
|
+
this.selectedMinute.set(currentMinute);
|
|
1028
|
+
newDate.setHours(currentHour);
|
|
1029
|
+
newDate.setMinutes(currentMinute);
|
|
938
1030
|
newDate.setSeconds(0);
|
|
939
1031
|
newDate.setMilliseconds(0);
|
|
940
1032
|
this.selectedDate.set(newDate);
|
|
941
1033
|
this.emitValue();
|
|
942
1034
|
}
|
|
1035
|
+
else {
|
|
1036
|
+
//If date is cleared, clear everything? Or just date?
|
|
1037
|
+
//Usually if date input is cleared, value is null.
|
|
1038
|
+
this.selectedDate.set(null);
|
|
1039
|
+
this.emitValue();
|
|
1040
|
+
}
|
|
943
1041
|
}
|
|
944
1042
|
onHourChange(value) {
|
|
945
1043
|
this.selectedHour.set(value);
|
|
@@ -951,13 +1049,15 @@ class DatetimeFieldComponent {
|
|
|
951
1049
|
}
|
|
952
1050
|
emitValue() {
|
|
953
1051
|
const date = this.selectedDate();
|
|
1052
|
+
// If no date selected, value is null regardless of time
|
|
954
1053
|
if (!date || isNaN(date.getTime())) {
|
|
955
1054
|
this.valueChange.emit(null);
|
|
956
1055
|
return;
|
|
957
1056
|
}
|
|
958
1057
|
const newDate = new Date(date.getTime());
|
|
959
|
-
|
|
960
|
-
newDate.
|
|
1058
|
+
// Use 0 if time not selected yet but date is present
|
|
1059
|
+
newDate.setHours(this.selectedHour() ?? 0);
|
|
1060
|
+
newDate.setMinutes(this.selectedMinute() ?? 0);
|
|
961
1061
|
newDate.setSeconds(0);
|
|
962
1062
|
newDate.setMilliseconds(0);
|
|
963
1063
|
this.valueChange.emit(newDate);
|
|
@@ -2398,6 +2498,7 @@ var FieldType;
|
|
|
2398
2498
|
FieldType["FILE"] = "file";
|
|
2399
2499
|
FieldType["PHONE"] = "phone";
|
|
2400
2500
|
FieldType["DOCUMENT"] = "document";
|
|
2501
|
+
FieldType["COLOR"] = "color";
|
|
2401
2502
|
})(FieldType || (FieldType = {}));
|
|
2402
2503
|
var NumberFieldType;
|
|
2403
2504
|
(function (NumberFieldType) {
|
|
@@ -4958,6 +5059,7 @@ class DynamicFieldDirective {
|
|
|
4958
5059
|
document: DocumentFieldComponent,
|
|
4959
5060
|
file: FileFieldComponent,
|
|
4960
5061
|
phone: PhoneFieldComponent,
|
|
5062
|
+
color: ColorPickerFieldComponent,
|
|
4961
5063
|
};
|
|
4962
5064
|
ngOnChanges(changes) {
|
|
4963
5065
|
if (changes['field']?.firstChange || this.shouldReloadComponent(changes)) {
|
|
@@ -16545,12 +16647,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
|
|
|
16545
16647
|
// Este archivo es generado automáticamente por scripts/update-version.js
|
|
16546
16648
|
// No edites manualmente este archivo
|
|
16547
16649
|
const VERSION = {
|
|
16548
|
-
full: '2.
|
|
16650
|
+
full: '2.17.1',
|
|
16549
16651
|
major: 2,
|
|
16550
|
-
minor:
|
|
16551
|
-
patch:
|
|
16552
|
-
timestamp: '2025-12-
|
|
16553
|
-
buildDate: '
|
|
16652
|
+
minor: 17,
|
|
16653
|
+
patch: 1,
|
|
16654
|
+
timestamp: '2025-12-16T13:58:16.774Z',
|
|
16655
|
+
buildDate: '16/12/2025'
|
|
16554
16656
|
};
|
|
16555
16657
|
|
|
16556
16658
|
class MainNavComponent {
|
|
@@ -21145,7 +21247,8 @@ const DEFAULT_SCHEDULER_CONFIG = {
|
|
|
21145
21247
|
slotDuration: 30,
|
|
21146
21248
|
rowHeightRem: 4,
|
|
21147
21249
|
showCurrentTimeLine: true,
|
|
21148
|
-
locale: 'es-ES'
|
|
21250
|
+
locale: 'es-ES',
|
|
21251
|
+
viewMode: 'day'
|
|
21149
21252
|
};
|
|
21150
21253
|
|
|
21151
21254
|
class GenericSchedulerComponent {
|
|
@@ -21160,6 +21263,10 @@ class GenericSchedulerComponent {
|
|
|
21160
21263
|
disabledSlotLabel = input('No disponible');
|
|
21161
21264
|
todayLabel = input('Hoy');
|
|
21162
21265
|
locale = input('es-ES');
|
|
21266
|
+
weekLabel = input('Semana');
|
|
21267
|
+
dayLabel = input('Día');
|
|
21268
|
+
monthLabel = input('Mes');
|
|
21269
|
+
disabledDates = input([]);
|
|
21163
21270
|
slotClick = output();
|
|
21164
21271
|
eventClick = output();
|
|
21165
21272
|
eventHover = output();
|
|
@@ -21167,10 +21274,70 @@ class GenericSchedulerComponent {
|
|
|
21167
21274
|
todayClick = output();
|
|
21168
21275
|
previousDay = output();
|
|
21169
21276
|
nextDay = output();
|
|
21277
|
+
previousWeek = output();
|
|
21278
|
+
nextWeek = output();
|
|
21279
|
+
previousMonth = output();
|
|
21280
|
+
nextMonth = output();
|
|
21281
|
+
viewModeChange = output();
|
|
21170
21282
|
timeSlots = signal([]);
|
|
21171
21283
|
currentTime = signal(new Date());
|
|
21284
|
+
expandedDay = signal(null);
|
|
21172
21285
|
timeUpdateInterval = null;
|
|
21173
21286
|
mergedConfig = computed(() => ({ ...DEFAULT_SCHEDULER_CONFIG, ...this.config() }));
|
|
21287
|
+
viewMode = computed(() => this.mergedConfig().viewMode || 'day');
|
|
21288
|
+
weekDays = computed(() => {
|
|
21289
|
+
if (this.viewMode() !== 'week')
|
|
21290
|
+
return [];
|
|
21291
|
+
const selected = this.selectedDate();
|
|
21292
|
+
const localeValue = this.locale();
|
|
21293
|
+
const today = new Date();
|
|
21294
|
+
const dayOfWeek = selected.getUTCDay();
|
|
21295
|
+
const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
|
|
21296
|
+
const monday = new Date(Date.UTC(selected.getUTCFullYear(), selected.getUTCMonth(), selected.getUTCDate() + mondayOffset));
|
|
21297
|
+
const days = [];
|
|
21298
|
+
for (let i = 0; i < 7; i++) {
|
|
21299
|
+
const date = new Date(Date.UTC(monday.getUTCFullYear(), monday.getUTCMonth(), monday.getUTCDate() + i));
|
|
21300
|
+
const isToday = date.getUTCFullYear() === today.getUTCFullYear() &&
|
|
21301
|
+
date.getUTCMonth() === today.getUTCMonth() &&
|
|
21302
|
+
date.getUTCDate() === today.getUTCDate();
|
|
21303
|
+
days.push({
|
|
21304
|
+
date,
|
|
21305
|
+
dayNumber: date.getUTCDate(),
|
|
21306
|
+
dayName: date.toLocaleDateString(localeValue, { weekday: 'short', timeZone: 'UTC' }),
|
|
21307
|
+
isToday,
|
|
21308
|
+
isWeekend: i >= 5
|
|
21309
|
+
});
|
|
21310
|
+
}
|
|
21311
|
+
return days;
|
|
21312
|
+
});
|
|
21313
|
+
monthDays = computed(() => {
|
|
21314
|
+
if (this.viewMode() !== 'month')
|
|
21315
|
+
return [];
|
|
21316
|
+
const selected = this.selectedDate();
|
|
21317
|
+
const localeValue = this.locale();
|
|
21318
|
+
const today = new Date();
|
|
21319
|
+
const year = selected.getUTCFullYear();
|
|
21320
|
+
const month = selected.getUTCMonth();
|
|
21321
|
+
const firstDayOfMonth = new Date(Date.UTC(year, month, 1));
|
|
21322
|
+
const dayOfWeek = firstDayOfMonth.getUTCDay();
|
|
21323
|
+
const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
|
|
21324
|
+
const startDate = new Date(Date.UTC(year, month, 1 + mondayOffset));
|
|
21325
|
+
const days = [];
|
|
21326
|
+
for (let i = 0; i < 42; i++) {
|
|
21327
|
+
const date = new Date(Date.UTC(startDate.getUTCFullYear(), startDate.getUTCMonth(), startDate.getUTCDate() + i));
|
|
21328
|
+
const isToday = date.getUTCFullYear() === today.getUTCFullYear() &&
|
|
21329
|
+
date.getUTCMonth() === today.getUTCMonth() &&
|
|
21330
|
+
date.getUTCDate() === today.getUTCDate();
|
|
21331
|
+
days.push({
|
|
21332
|
+
date,
|
|
21333
|
+
dayNumber: date.getUTCDate(),
|
|
21334
|
+
dayName: date.toLocaleDateString(localeValue, { weekday: 'short', timeZone: 'UTC' }),
|
|
21335
|
+
isToday,
|
|
21336
|
+
isWeekend: [0, 6].includes(date.getUTCDay())
|
|
21337
|
+
});
|
|
21338
|
+
}
|
|
21339
|
+
return days;
|
|
21340
|
+
});
|
|
21174
21341
|
isToday = computed(() => {
|
|
21175
21342
|
const selected = this.selectedDate();
|
|
21176
21343
|
const today = new Date();
|
|
@@ -21181,6 +21348,32 @@ class GenericSchedulerComponent {
|
|
|
21181
21348
|
formattedDate = computed(() => {
|
|
21182
21349
|
const date = this.selectedDate();
|
|
21183
21350
|
const localeValue = this.locale();
|
|
21351
|
+
if (this.viewMode() === 'week') {
|
|
21352
|
+
const days = this.weekDays();
|
|
21353
|
+
if (days.length > 0) {
|
|
21354
|
+
const firstDay = days[0].date;
|
|
21355
|
+
const lastDay = days[6].date;
|
|
21356
|
+
const firstFormatted = firstDay.toLocaleDateString(localeValue, {
|
|
21357
|
+
day: 'numeric',
|
|
21358
|
+
month: 'short',
|
|
21359
|
+
timeZone: 'UTC'
|
|
21360
|
+
});
|
|
21361
|
+
const lastFormatted = lastDay.toLocaleDateString(localeValue, {
|
|
21362
|
+
day: 'numeric',
|
|
21363
|
+
month: 'short',
|
|
21364
|
+
year: 'numeric',
|
|
21365
|
+
timeZone: 'UTC'
|
|
21366
|
+
});
|
|
21367
|
+
return `${firstFormatted} - ${lastFormatted}`;
|
|
21368
|
+
}
|
|
21369
|
+
}
|
|
21370
|
+
if (this.viewMode() === 'month') {
|
|
21371
|
+
return date.toLocaleDateString(localeValue, {
|
|
21372
|
+
month: 'long',
|
|
21373
|
+
year: 'numeric',
|
|
21374
|
+
timeZone: 'UTC'
|
|
21375
|
+
});
|
|
21376
|
+
}
|
|
21184
21377
|
return date.toLocaleDateString(localeValue, {
|
|
21185
21378
|
weekday: 'long',
|
|
21186
21379
|
year: 'numeric',
|
|
@@ -21190,8 +21383,17 @@ class GenericSchedulerComponent {
|
|
|
21190
21383
|
});
|
|
21191
21384
|
});
|
|
21192
21385
|
currentTimePosition = computed(() => {
|
|
21193
|
-
if (!this.
|
|
21386
|
+
if (!this.mergedConfig().showCurrentTimeLine)
|
|
21194
21387
|
return null;
|
|
21388
|
+
if (this.viewMode() === 'week') {
|
|
21389
|
+
const days = this.weekDays();
|
|
21390
|
+
const todayIndex = days.findIndex(d => d.isToday);
|
|
21391
|
+
if (todayIndex === -1)
|
|
21392
|
+
return null;
|
|
21393
|
+
}
|
|
21394
|
+
else if (!this.isToday()) {
|
|
21395
|
+
return null;
|
|
21396
|
+
}
|
|
21195
21397
|
const now = this.currentTime();
|
|
21196
21398
|
const hours = now.getUTCHours();
|
|
21197
21399
|
const minutes = now.getUTCMinutes();
|
|
@@ -21204,6 +21406,12 @@ class GenericSchedulerComponent {
|
|
|
21204
21406
|
const positionInRem = slotsFromStart * cfg.rowHeightRem;
|
|
21205
21407
|
return positionInRem;
|
|
21206
21408
|
});
|
|
21409
|
+
currentTimeDayIndex = computed(() => {
|
|
21410
|
+
if (this.viewMode() !== 'week')
|
|
21411
|
+
return -1;
|
|
21412
|
+
const days = this.weekDays();
|
|
21413
|
+
return days.findIndex(d => d.isToday);
|
|
21414
|
+
});
|
|
21207
21415
|
eventMap = computed(() => {
|
|
21208
21416
|
const map = new Map();
|
|
21209
21417
|
const evts = this.events();
|
|
@@ -21284,6 +21492,10 @@ class GenericSchedulerComponent {
|
|
|
21284
21492
|
isSlotDisabled(columnId, slot) {
|
|
21285
21493
|
const now = new Date();
|
|
21286
21494
|
const selected = this.selectedDate();
|
|
21495
|
+
const dateStr = selected.toISOString().split('T')[0];
|
|
21496
|
+
if (this.disabledDates().includes(dateStr)) {
|
|
21497
|
+
return true;
|
|
21498
|
+
}
|
|
21287
21499
|
const todayUTC = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
|
|
21288
21500
|
const selectedUTC = Date.UTC(selected.getUTCFullYear(), selected.getUTCMonth(), selected.getUTCDate());
|
|
21289
21501
|
if (selectedUTC < todayUTC) {
|
|
@@ -21339,15 +21551,170 @@ class GenericSchedulerComponent {
|
|
|
21339
21551
|
const nextDayDate = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate() + 1));
|
|
21340
21552
|
this.nextDay.emit(nextDayDate);
|
|
21341
21553
|
}
|
|
21554
|
+
onPreviousWeek() {
|
|
21555
|
+
const current = this.selectedDate();
|
|
21556
|
+
const prevWeek = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate() - 7));
|
|
21557
|
+
this.previousWeek.emit(prevWeek);
|
|
21558
|
+
}
|
|
21559
|
+
onNextWeek() {
|
|
21560
|
+
const current = this.selectedDate();
|
|
21561
|
+
const nextWeekDate = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate() + 7));
|
|
21562
|
+
this.nextWeek.emit(nextWeekDate);
|
|
21563
|
+
}
|
|
21564
|
+
onPreviousMonth() {
|
|
21565
|
+
const current = this.selectedDate();
|
|
21566
|
+
const prevMonth = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth() - 1, 1));
|
|
21567
|
+
this.previousMonth.emit(prevMonth);
|
|
21568
|
+
}
|
|
21569
|
+
onNextMonth() {
|
|
21570
|
+
const current = this.selectedDate();
|
|
21571
|
+
const nextMonth = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth() + 1, 1));
|
|
21572
|
+
this.nextMonth.emit(nextMonth);
|
|
21573
|
+
}
|
|
21574
|
+
onPrevious() {
|
|
21575
|
+
if (this.viewMode() === 'week') {
|
|
21576
|
+
this.onPreviousWeek();
|
|
21577
|
+
}
|
|
21578
|
+
else if (this.viewMode() === 'month') {
|
|
21579
|
+
this.onPreviousMonth();
|
|
21580
|
+
}
|
|
21581
|
+
else {
|
|
21582
|
+
this.onPreviousDay();
|
|
21583
|
+
}
|
|
21584
|
+
}
|
|
21585
|
+
onNext() {
|
|
21586
|
+
if (this.viewMode() === 'week') {
|
|
21587
|
+
this.onNextWeek();
|
|
21588
|
+
}
|
|
21589
|
+
else if (this.viewMode() === 'month') {
|
|
21590
|
+
this.onNextMonth();
|
|
21591
|
+
}
|
|
21592
|
+
else {
|
|
21593
|
+
this.onNextDay();
|
|
21594
|
+
}
|
|
21595
|
+
}
|
|
21596
|
+
toggleViewMode() {
|
|
21597
|
+
const newMode = this.viewMode() === 'day' ? 'week' : 'day';
|
|
21598
|
+
this.viewModeChange.emit(newMode);
|
|
21599
|
+
}
|
|
21600
|
+
setViewMode(mode) {
|
|
21601
|
+
this.viewModeChange.emit(mode);
|
|
21602
|
+
}
|
|
21603
|
+
getEventsForDay(dayDate) {
|
|
21604
|
+
const evts = this.events();
|
|
21605
|
+
return evts.filter(event => {
|
|
21606
|
+
if (!event.date)
|
|
21607
|
+
return false;
|
|
21608
|
+
const eventDate = new Date(event.date);
|
|
21609
|
+
return eventDate.getUTCFullYear() === dayDate.getUTCFullYear() &&
|
|
21610
|
+
eventDate.getUTCMonth() === dayDate.getUTCMonth() &&
|
|
21611
|
+
eventDate.getUTCDate() === dayDate.getUTCDate();
|
|
21612
|
+
});
|
|
21613
|
+
}
|
|
21614
|
+
isSlotOccupiedForDay(dayDate, slot) {
|
|
21615
|
+
const evts = this.getEventsForDay(dayDate);
|
|
21616
|
+
return evts.some(event => this.isTimeInEvent(slot.time, event));
|
|
21617
|
+
}
|
|
21618
|
+
shouldShowEventForDay(dayDate, slot) {
|
|
21619
|
+
const evts = this.getEventsForDay(dayDate);
|
|
21620
|
+
return evts.some(event => event.startTime === slot.time);
|
|
21621
|
+
}
|
|
21622
|
+
getEventForDaySlot(dayDate, slot) {
|
|
21623
|
+
const evts = this.getEventsForDay(dayDate);
|
|
21624
|
+
return evts.find(event => event.startTime === slot.time);
|
|
21625
|
+
}
|
|
21626
|
+
isDayDisabled(dayDate) {
|
|
21627
|
+
const dateStr = dayDate.toISOString().split('T')[0];
|
|
21628
|
+
return this.disabledDates().includes(dateStr);
|
|
21629
|
+
}
|
|
21630
|
+
isSlotDisabledForDay(dayDate, slot) {
|
|
21631
|
+
if (this.isDayDisabled(dayDate)) {
|
|
21632
|
+
return true;
|
|
21633
|
+
}
|
|
21634
|
+
const now = new Date();
|
|
21635
|
+
const todayUTC = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
|
|
21636
|
+
const dayUTC = Date.UTC(dayDate.getUTCFullYear(), dayDate.getUTCMonth(), dayDate.getUTCDate());
|
|
21637
|
+
if (dayUTC < todayUTC) {
|
|
21638
|
+
return true;
|
|
21639
|
+
}
|
|
21640
|
+
if (dayUTC === todayUTC) {
|
|
21641
|
+
const [slotHour, slotMin] = slot.time.split(':').map(Number);
|
|
21642
|
+
const slotMinutes = slotHour * 60 + slotMin;
|
|
21643
|
+
const currentMinutes = now.getUTCHours() * 60 + now.getUTCMinutes();
|
|
21644
|
+
return slotMinutes < currentMinutes;
|
|
21645
|
+
}
|
|
21646
|
+
return false;
|
|
21647
|
+
}
|
|
21648
|
+
onWeekSlotClick(dayDate, slot) {
|
|
21649
|
+
if (this.isSlotOccupiedForDay(dayDate, slot) || this.isSlotDisabledForDay(dayDate, slot)) {
|
|
21650
|
+
return;
|
|
21651
|
+
}
|
|
21652
|
+
this.slotClick.emit({
|
|
21653
|
+
columnId: dayDate.toISOString(),
|
|
21654
|
+
slot,
|
|
21655
|
+
date: dayDate
|
|
21656
|
+
});
|
|
21657
|
+
}
|
|
21658
|
+
onWeekEventClick(event, dayDate) {
|
|
21659
|
+
const pseudoColumn = {
|
|
21660
|
+
id: dayDate.toISOString(),
|
|
21661
|
+
name: dayDate.toLocaleDateString(this.locale(), { weekday: 'long', timeZone: 'UTC' })
|
|
21662
|
+
};
|
|
21663
|
+
this.eventClick.emit({ event, column: pseudoColumn });
|
|
21664
|
+
}
|
|
21665
|
+
onMonthDayClick(dayDate) {
|
|
21666
|
+
const dummySlot = {
|
|
21667
|
+
time: '00:00',
|
|
21668
|
+
hour: 0,
|
|
21669
|
+
minutes: 0,
|
|
21670
|
+
isHalfHour: false,
|
|
21671
|
+
displayTime: false
|
|
21672
|
+
};
|
|
21673
|
+
this.slotClick.emit({
|
|
21674
|
+
columnId: dayDate.toISOString(),
|
|
21675
|
+
slot: dummySlot,
|
|
21676
|
+
date: dayDate
|
|
21677
|
+
});
|
|
21678
|
+
}
|
|
21679
|
+
onMonthEventClick(event, dayDate) {
|
|
21680
|
+
const pseudoColumn = {
|
|
21681
|
+
id: dayDate.toISOString(),
|
|
21682
|
+
name: dayDate.toLocaleDateString(this.locale(), { weekday: 'long', timeZone: 'UTC' })
|
|
21683
|
+
};
|
|
21684
|
+
this.eventClick.emit({ event, column: pseudoColumn });
|
|
21685
|
+
}
|
|
21686
|
+
openDayPopover(dayDate, event) {
|
|
21687
|
+
event.stopPropagation();
|
|
21688
|
+
this.expandedDay.set(dayDate);
|
|
21689
|
+
}
|
|
21690
|
+
closeDayPopover() {
|
|
21691
|
+
this.expandedDay.set(null);
|
|
21692
|
+
}
|
|
21693
|
+
getExpandedDayEvents() {
|
|
21694
|
+
const day = this.expandedDay();
|
|
21695
|
+
if (!day)
|
|
21696
|
+
return [];
|
|
21697
|
+
return this.getEventsForDay(day);
|
|
21698
|
+
}
|
|
21699
|
+
getExpandedDayLabel() {
|
|
21700
|
+
const day = this.expandedDay();
|
|
21701
|
+
if (!day)
|
|
21702
|
+
return '';
|
|
21703
|
+
const localeValue = this.locale();
|
|
21704
|
+
const weekday = day.toLocaleDateString(localeValue, { weekday: 'short', timeZone: 'UTC' }).toUpperCase();
|
|
21705
|
+
const dayNum = day.getUTCDate();
|
|
21706
|
+
return `${weekday}\n${dayNum}`;
|
|
21707
|
+
}
|
|
21342
21708
|
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 }] });
|
|
21709
|
+
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 }, weekLabel: { classPropertyName: "weekLabel", publicName: "weekLabel", isSignal: true, isRequired: false, transformFunction: null }, dayLabel: { classPropertyName: "dayLabel", publicName: "dayLabel", isSignal: true, isRequired: false, transformFunction: null }, monthLabel: { classPropertyName: "monthLabel", publicName: "monthLabel", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { slotClick: "slotClick", eventClick: "eventClick", eventHover: "eventHover", eventLeave: "eventLeave", todayClick: "todayClick", previousDay: "previousDay", nextDay: "nextDay", previousWeek: "previousWeek", nextWeek: "nextWeek", previousMonth: "previousMonth", nextMonth: "nextMonth", viewModeChange: "viewModeChange" }, host: { properties: { "class.c-bookings-grid--weekly": "viewMode() === \"week\"", "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]=\"viewMode() === 'week' ? 'Semana anterior' : 'D\u00EDa anterior'\"\n (click)=\"onPrevious()\"\n ></button>\n <span>{{ formattedDate() }}</span>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n [title]=\"viewMode() === 'week' ? 'Semana siguiente' : 'D\u00EDa siguiente'\"\n (click)=\"onNext()\"\n ></button>\n </div>\n\n <div class=\"c-bookings-header__view-toggle\">\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'day'\"\n (click)=\"setViewMode('day')\"\n >\n {{ dayLabel() }}\n </button>\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'week'\"\n (click)=\"setViewMode('week')\"\n >\n {{ weekLabel() }}\n </button>\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'month'\"\n (click)=\"setViewMode('month')\"\n >\n {{ monthLabel() }}\n </button>\n </div>\n</div>\n} @if (viewMode() === 'day') {\n<!-- DAILY VIEW -->\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} @else if (viewMode() === 'week') {\n<!-- WEEKLY VIEW -->\n<div\n class=\"c-bookings-grid__wrapper c-bookings-grid__wrapper--weekly\"\n [style.--cols]=\"7\"\n style=\"position: relative\"\n>\n @if (currentTimePosition() !== null && currentTimeDayIndex() >= 0) {\n <div\n class=\"c-bookings-grid__current-time-line c-bookings-grid__current-time-line--weekly\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n [style.--day-index]=\"currentTimeDayIndex()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top c-bookings-grid__top--weekly\">\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 (day of weekDays(); track day.date.getTime()) {\n <div\n class=\"c-bookings-grid__col\"\n [class.c-bookings-grid__col--weekend]=\"day.isWeekend\"\n >\n <div class=\"c-bookings-grid__top c-bookings-grid__top--weekly\">\n <div class=\"c-bookings-grid__day-header\" [class.is-today]=\"day.isToday\">\n <span class=\"c-bookings-grid__day-name\">{{ day.dayName }}</span>\n <span\n class=\"c-bookings-grid__day-number\"\n [class.is-today]=\"day.isToday\"\n >{{ day.dayNumber }}</span\n >\n </div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupiedForDay(day.date, slot)) { @if\n (isSlotDisabledForDay(day.date, slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n ></button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onWeekSlotClick(day.date, slot)\"\n ></button>\n } } @if (shouldShowEventForDay(day.date, slot)) { @let event =\n getEventForDaySlot(day.date, 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)=\"onWeekEventClick(event, day.date)\"\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 </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n} @else if (viewMode() === 'month') {\n<!-- MONTHLY VIEW -->\n<div class=\"c-bookings-grid__wrapper c-bookings-grid__wrapper--monthly\">\n <!-- Header Row -->\n <div class=\"c-bookings-grid__header-row\">\n @for (day of monthDays().slice(0, 7); track day.dayName) {\n <div class=\"c-bookings-grid__header-cell\">\n {{ day.dayName }}\n </div>\n }\n </div>\n\n <!-- Days Grid -->\n <div class=\"c-bookings-grid__month-grid\">\n @for (day of monthDays(); track day.date.getTime()) {\n <div\n class=\"c-bookings-grid__month-cell\"\n [class.is-today]=\"day.isToday\"\n [class.is-weekend]=\"day.isWeekend\"\n [class.is-other-month]=\"\n day.date.getUTCMonth() !== selectedDate().getUTCMonth()\n \"\n [class.is-disabled]=\"isDayDisabled(day.date)\"\n (click)=\"!isDayDisabled(day.date) && onMonthDayClick(day.date)\"\n >\n <div class=\"c-bookings-grid__month-day-number\">\n {{ day.dayNumber }}\n </div>\n\n <div class=\"c-bookings-grid__month-events\">\n @let dayEvents = getEventsForDay(day.date); @for (event of\n dayEvents.slice(0, 3); track event.id) {\n <div\n class=\"c-bookings-grid__month-event\"\n [attr.data-type]=\"event.type\"\n [style.background-color]=\"event.metadata?.['color']\"\n [style.border-left]=\"event.metadata?.['color'] ? '3px solid ' + event.metadata?.['color'] : ''\"\n (click)=\"$event.stopPropagation(); onMonthEventClick(event, day.date)\"\n >\n <span class=\"c-bookings-grid__month-event-title\">{{\n event.title\n }}</span>\n </div>\n } @if (dayEvents.length > 3) {\n <div\n class=\"c-bookings-grid__more-events\"\n (click)=\"openDayPopover(day.date, $event)\"\n >\n {{ dayEvents.length - 3 }} m\u00E1s\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n @if (expandedDay()) {\n <div class=\"c-bookings-grid__popover-overlay\" (click)=\"closeDayPopover()\">\n <div class=\"c-bookings-grid__popover\" (click)=\"$event.stopPropagation()\">\n <div class=\"c-bookings-grid__popover-header\">\n <div class=\"c-bookings-grid__popover-date\">\n <span class=\"c-bookings-grid__popover-weekday\">{{\n expandedDay() | date : \"EEE\" : \"UTC\" : locale() | uppercase\n }}</span>\n <span class=\"c-bookings-grid__popover-daynum\">{{\n expandedDay() | date : \"d\" : \"UTC\"\n }}</span>\n </div>\n <button\n class=\"c-bookings-grid__popover-close\"\n (click)=\"closeDayPopover()\"\n >\n <span class=\"icon-cross\"></span>\n </button>\n </div>\n <div class=\"c-bookings-grid__popover-content\">\n @for (event of getExpandedDayEvents(); track event.id) {\n <div\n class=\"c-bookings-grid__month-event c-bookings-grid__month-event--popover\"\n [attr.data-type]=\"event.type\"\n [style.background-color]=\"event.metadata?.['color']\"\n [style.border-left]=\"event.metadata?.['color'] ? '3px solid ' + event.metadata?.['color'] : ''\"\n (click)=\"onMonthEventClick(event, expandedDay()!)\"\n >\n <span class=\"c-bookings-grid__month-event-title\">{{\n event.title\n }}</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n</div>\n}\n", styles: [":host{display:block;width:100%;overflow:visible}.c-bookings-grid__month-cell.is-disabled{background-color:#f3f4f6;cursor:not-allowed;opacity:.7}.c-bookings-grid__month-cell.is-disabled:hover{background-color:#f3f4f6}.c-bookings-grid__month-cell.is-disabled .c-bookings-grid__month-day-number{color:#9ca3af}.c-bookings-grid__slot--disabled{background-color:#f3f4f6;cursor:not-allowed}.c-bookings-grid__slot--disabled:hover{background-color:#f3f4f6}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i2.DatePipe, name: "date" }] });
|
|
21344
21710
|
}
|
|
21345
21711
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericSchedulerComponent, decorators: [{
|
|
21346
21712
|
type: Component,
|
|
21347
21713
|
args: [{ selector: 'core-generic-scheduler', standalone: true, imports: [CommonModule], host: {
|
|
21348
21714
|
'class': 'c-bookings-grid c-bookings-card',
|
|
21715
|
+
'[class.c-bookings-grid--weekly]': 'viewMode() === "week"',
|
|
21349
21716
|
'[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"] }]
|
|
21717
|
+
}, 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]=\"viewMode() === 'week' ? 'Semana anterior' : 'D\u00EDa anterior'\"\n (click)=\"onPrevious()\"\n ></button>\n <span>{{ formattedDate() }}</span>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n [title]=\"viewMode() === 'week' ? 'Semana siguiente' : 'D\u00EDa siguiente'\"\n (click)=\"onNext()\"\n ></button>\n </div>\n\n <div class=\"c-bookings-header__view-toggle\">\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'day'\"\n (click)=\"setViewMode('day')\"\n >\n {{ dayLabel() }}\n </button>\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'week'\"\n (click)=\"setViewMode('week')\"\n >\n {{ weekLabel() }}\n </button>\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'month'\"\n (click)=\"setViewMode('month')\"\n >\n {{ monthLabel() }}\n </button>\n </div>\n</div>\n} @if (viewMode() === 'day') {\n<!-- DAILY VIEW -->\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} @else if (viewMode() === 'week') {\n<!-- WEEKLY VIEW -->\n<div\n class=\"c-bookings-grid__wrapper c-bookings-grid__wrapper--weekly\"\n [style.--cols]=\"7\"\n style=\"position: relative\"\n>\n @if (currentTimePosition() !== null && currentTimeDayIndex() >= 0) {\n <div\n class=\"c-bookings-grid__current-time-line c-bookings-grid__current-time-line--weekly\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n [style.--day-index]=\"currentTimeDayIndex()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top c-bookings-grid__top--weekly\">\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 (day of weekDays(); track day.date.getTime()) {\n <div\n class=\"c-bookings-grid__col\"\n [class.c-bookings-grid__col--weekend]=\"day.isWeekend\"\n >\n <div class=\"c-bookings-grid__top c-bookings-grid__top--weekly\">\n <div class=\"c-bookings-grid__day-header\" [class.is-today]=\"day.isToday\">\n <span class=\"c-bookings-grid__day-name\">{{ day.dayName }}</span>\n <span\n class=\"c-bookings-grid__day-number\"\n [class.is-today]=\"day.isToday\"\n >{{ day.dayNumber }}</span\n >\n </div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupiedForDay(day.date, slot)) { @if\n (isSlotDisabledForDay(day.date, slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n ></button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onWeekSlotClick(day.date, slot)\"\n ></button>\n } } @if (shouldShowEventForDay(day.date, slot)) { @let event =\n getEventForDaySlot(day.date, 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)=\"onWeekEventClick(event, day.date)\"\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 </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n} @else if (viewMode() === 'month') {\n<!-- MONTHLY VIEW -->\n<div class=\"c-bookings-grid__wrapper c-bookings-grid__wrapper--monthly\">\n <!-- Header Row -->\n <div class=\"c-bookings-grid__header-row\">\n @for (day of monthDays().slice(0, 7); track day.dayName) {\n <div class=\"c-bookings-grid__header-cell\">\n {{ day.dayName }}\n </div>\n }\n </div>\n\n <!-- Days Grid -->\n <div class=\"c-bookings-grid__month-grid\">\n @for (day of monthDays(); track day.date.getTime()) {\n <div\n class=\"c-bookings-grid__month-cell\"\n [class.is-today]=\"day.isToday\"\n [class.is-weekend]=\"day.isWeekend\"\n [class.is-other-month]=\"\n day.date.getUTCMonth() !== selectedDate().getUTCMonth()\n \"\n [class.is-disabled]=\"isDayDisabled(day.date)\"\n (click)=\"!isDayDisabled(day.date) && onMonthDayClick(day.date)\"\n >\n <div class=\"c-bookings-grid__month-day-number\">\n {{ day.dayNumber }}\n </div>\n\n <div class=\"c-bookings-grid__month-events\">\n @let dayEvents = getEventsForDay(day.date); @for (event of\n dayEvents.slice(0, 3); track event.id) {\n <div\n class=\"c-bookings-grid__month-event\"\n [attr.data-type]=\"event.type\"\n [style.background-color]=\"event.metadata?.['color']\"\n [style.border-left]=\"event.metadata?.['color'] ? '3px solid ' + event.metadata?.['color'] : ''\"\n (click)=\"$event.stopPropagation(); onMonthEventClick(event, day.date)\"\n >\n <span class=\"c-bookings-grid__month-event-title\">{{\n event.title\n }}</span>\n </div>\n } @if (dayEvents.length > 3) {\n <div\n class=\"c-bookings-grid__more-events\"\n (click)=\"openDayPopover(day.date, $event)\"\n >\n {{ dayEvents.length - 3 }} m\u00E1s\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n @if (expandedDay()) {\n <div class=\"c-bookings-grid__popover-overlay\" (click)=\"closeDayPopover()\">\n <div class=\"c-bookings-grid__popover\" (click)=\"$event.stopPropagation()\">\n <div class=\"c-bookings-grid__popover-header\">\n <div class=\"c-bookings-grid__popover-date\">\n <span class=\"c-bookings-grid__popover-weekday\">{{\n expandedDay() | date : \"EEE\" : \"UTC\" : locale() | uppercase\n }}</span>\n <span class=\"c-bookings-grid__popover-daynum\">{{\n expandedDay() | date : \"d\" : \"UTC\"\n }}</span>\n </div>\n <button\n class=\"c-bookings-grid__popover-close\"\n (click)=\"closeDayPopover()\"\n >\n <span class=\"icon-cross\"></span>\n </button>\n </div>\n <div class=\"c-bookings-grid__popover-content\">\n @for (event of getExpandedDayEvents(); track event.id) {\n <div\n class=\"c-bookings-grid__month-event c-bookings-grid__month-event--popover\"\n [attr.data-type]=\"event.type\"\n [style.background-color]=\"event.metadata?.['color']\"\n [style.border-left]=\"event.metadata?.['color'] ? '3px solid ' + event.metadata?.['color'] : ''\"\n (click)=\"onMonthEventClick(event, expandedDay()!)\"\n >\n <span class=\"c-bookings-grid__month-event-title\">{{\n event.title\n }}</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n</div>\n}\n", styles: [":host{display:block;width:100%;overflow:visible}.c-bookings-grid__month-cell.is-disabled{background-color:#f3f4f6;cursor:not-allowed;opacity:.7}.c-bookings-grid__month-cell.is-disabled:hover{background-color:#f3f4f6}.c-bookings-grid__month-cell.is-disabled .c-bookings-grid__month-day-number{color:#9ca3af}.c-bookings-grid__slot--disabled{background-color:#f3f4f6;cursor:not-allowed}.c-bookings-grid__slot--disabled:hover{background-color:#f3f4f6}\n"] }]
|
|
21351
21718
|
}] });
|
|
21352
21719
|
|
|
21353
21720
|
class CacheBustingInterceptor {
|
|
@@ -21631,5 +21998,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
|
|
|
21631
21998
|
* Generated bundle index. Do not edit.
|
|
21632
21999
|
*/
|
|
21633
22000
|
|
|
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 };
|
|
22001
|
+
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, ColorPickerFieldComponent, 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 };
|
|
21635
22002
|
//# sourceMappingURL=solcre-org-core-ui.mjs.map
|