ngx-dsxlibrary 2.21.75 → 2.21.76
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.
|
@@ -52,6 +52,7 @@ import { AvatarGroupModule } from 'primeng/avatargroup';
|
|
|
52
52
|
import { BadgeModule } from 'primeng/badge';
|
|
53
53
|
import { CardModule } from 'primeng/card';
|
|
54
54
|
import { CheckboxModule } from 'primeng/checkbox';
|
|
55
|
+
import { ChipModule } from 'primeng/chip';
|
|
55
56
|
import { ContextMenuModule } from 'primeng/contextmenu';
|
|
56
57
|
import { DataViewModule } from 'primeng/dataview';
|
|
57
58
|
import { DatePickerModule, DatePicker } from 'primeng/datepicker';
|
|
@@ -1887,11 +1888,11 @@ class AppMessageHelpComponent {
|
|
|
1887
1888
|
return null;
|
|
1888
1889
|
}
|
|
1889
1890
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AppMessageHelpComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
|
|
1890
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AppMessageHelpComponent, isStandalone: true, selector: "dsx-message-help", inputs: { control: "control", currentIdControl: "currentIdControl", helperFunction: "helperFunction", dataSource: "dataSource", key: "key", umbral: "umbral", debugMode: "debugMode", idFieldName: "idFieldName", maxSugerencias: "maxSugerencias" }, ngImport: i0, template: "<div class=\"dsx-help-slot\" [class.is-visible]=\"isHelpVisible()\">\r\n @if (isHelpVisible()) {\r\n <div\r\n class=\"dsx-help-message\"\r\n [class.is-warning]=\"helperFunction === 'similarity'\"\r\n >\r\n
|
|
1891
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AppMessageHelpComponent, isStandalone: true, selector: "dsx-message-help", inputs: { control: "control", currentIdControl: "currentIdControl", helperFunction: "helperFunction", dataSource: "dataSource", key: "key", umbral: "umbral", debugMode: "debugMode", idFieldName: "idFieldName", maxSugerencias: "maxSugerencias" }, ngImport: i0, template: "<div class=\"dsx-help-slot\" [class.is-visible]=\"isHelpVisible()\">\r\n @if (isHelpVisible()) {\r\n <div\r\n class=\"dsx-help-message\"\r\n [class.is-warning]=\"helperFunction === 'similarity'\"\r\n >\r\n <span>{{ getHelpMessage() }}</span>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;width:100%}.dsx-help-slot{max-height:0;margin-top:0;overflow:hidden;opacity:0;transition:max-height .22s ease,margin-top .22s ease,opacity .18s ease}.dsx-help-slot.is-visible{max-height:4rem;margin-top:.15rem;opacity:1}.dsx-help-message{--dsx-help-color: #059669;color:var(--dsx-help-color);font-family:Roboto,Montserrat,sans-serif;font-size:clamp(.7rem,.68rem + .08vw,.75rem);font-weight:400;line-height:1.4;letter-spacing:.01em;padding:.1rem 0;border:none;background:transparent;box-shadow:none;width:100%;max-width:100%;white-space:normal;word-break:break-word;box-sizing:border-box}.dsx-help-message.is-warning{--dsx-help-color: #d97706}.dsx-help-message span{display:block;word-break:break-word;color:var(--dsx-help-color)}.dsx-help-slot.is-visible .dsx-help-message{animation:fadeInHelp .2s ease}@keyframes fadeInHelp{0%{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:translateY(0)}}@media(max-width:640px){.dsx-help-slot.is-visible{max-height:5rem}.dsx-help-message{font-size:clamp(.6rem,.55rem + .15vw,.65rem);padding:.05rem 0}}:host-context(.p-floatlabel){position:absolute;top:100%;left:0;width:100%;z-index:3;pointer-events:none}:host-context(.p-floatlabel) .dsx-help-slot{max-height:none;margin-top:.1rem;overflow:visible;opacity:0;transform:translateY(-2px);transition:opacity .16s ease,transform .18s ease}:host-context(.p-floatlabel) .dsx-help-slot.is-visible{opacity:1;transform:translateY(0)}:host-context(.p-floatlabel) .dsx-help-message{width:100%;max-width:100%;padding:.05rem 0;box-sizing:border-box}\n"] });
|
|
1891
1892
|
}
|
|
1892
1893
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AppMessageHelpComponent, decorators: [{
|
|
1893
1894
|
type: Component,
|
|
1894
|
-
args: [{ selector: 'dsx-message-help', imports: [IconDsxComponent], template: "<div class=\"dsx-help-slot\" [class.is-visible]=\"isHelpVisible()\">\r\n @if (isHelpVisible()) {\r\n <div\r\n class=\"dsx-help-message\"\r\n [class.is-warning]=\"helperFunction === 'similarity'\"\r\n >\r\n
|
|
1895
|
+
args: [{ selector: 'dsx-message-help', imports: [IconDsxComponent], template: "<div class=\"dsx-help-slot\" [class.is-visible]=\"isHelpVisible()\">\r\n @if (isHelpVisible()) {\r\n <div\r\n class=\"dsx-help-message\"\r\n [class.is-warning]=\"helperFunction === 'similarity'\"\r\n >\r\n <span>{{ getHelpMessage() }}</span>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;width:100%}.dsx-help-slot{max-height:0;margin-top:0;overflow:hidden;opacity:0;transition:max-height .22s ease,margin-top .22s ease,opacity .18s ease}.dsx-help-slot.is-visible{max-height:4rem;margin-top:.15rem;opacity:1}.dsx-help-message{--dsx-help-color: #059669;color:var(--dsx-help-color);font-family:Roboto,Montserrat,sans-serif;font-size:clamp(.7rem,.68rem + .08vw,.75rem);font-weight:400;line-height:1.4;letter-spacing:.01em;padding:.1rem 0;border:none;background:transparent;box-shadow:none;width:100%;max-width:100%;white-space:normal;word-break:break-word;box-sizing:border-box}.dsx-help-message.is-warning{--dsx-help-color: #d97706}.dsx-help-message span{display:block;word-break:break-word;color:var(--dsx-help-color)}.dsx-help-slot.is-visible .dsx-help-message{animation:fadeInHelp .2s ease}@keyframes fadeInHelp{0%{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:translateY(0)}}@media(max-width:640px){.dsx-help-slot.is-visible{max-height:5rem}.dsx-help-message{font-size:clamp(.6rem,.55rem + .15vw,.65rem);padding:.05rem 0}}:host-context(.p-floatlabel){position:absolute;top:100%;left:0;width:100%;z-index:3;pointer-events:none}:host-context(.p-floatlabel) .dsx-help-slot{max-height:none;margin-top:.1rem;overflow:visible;opacity:0;transform:translateY(-2px);transition:opacity .16s ease,transform .18s ease}:host-context(.p-floatlabel) .dsx-help-slot.is-visible{opacity:1;transform:translateY(0)}:host-context(.p-floatlabel) .dsx-help-message{width:100%;max-width:100%;padding:.05rem 0;box-sizing:border-box}\n"] }]
|
|
1895
1896
|
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { control: [{
|
|
1896
1897
|
type: Input
|
|
1897
1898
|
}], currentIdControl: [{
|
|
@@ -5077,6 +5078,435 @@ const ACTION_CONFIG = {
|
|
|
5077
5078
|
},
|
|
5078
5079
|
};
|
|
5079
5080
|
|
|
5081
|
+
// dsx-calendar-view.component.ts - VERSIÓN CON isDevMode()
|
|
5082
|
+
class DsxCalendarView {
|
|
5083
|
+
// ============================================
|
|
5084
|
+
// INPUTS
|
|
5085
|
+
// ============================================
|
|
5086
|
+
// Two-way binding
|
|
5087
|
+
startDate = model(null, ...(ngDevMode ? [{ debugName: "startDate" }] : /* istanbul ignore next */ []));
|
|
5088
|
+
endDate = model(null, ...(ngDevMode ? [{ debugName: "endDate" }] : /* istanbul ignore next */ []));
|
|
5089
|
+
excludeSundays = model(false, ...(ngDevMode ? [{ debugName: "excludeSundays" }] : /* istanbul ignore next */ []));
|
|
5090
|
+
// Configuración
|
|
5091
|
+
holidays = input([], ...(ngDevMode ? [{ debugName: "holidays" }] : /* istanbul ignore next */ []));
|
|
5092
|
+
compactMode = input(true, ...(ngDevMode ? [{ debugName: "compactMode" }] : /* istanbul ignore next */ []));
|
|
5093
|
+
showKPI = input(true, ...(ngDevMode ? [{ debugName: "showKPI" }] : /* istanbul ignore next */ []));
|
|
5094
|
+
debugMode = input(false, ...(ngDevMode ? [{ debugName: "debugMode" }] : /* istanbul ignore next */ []));
|
|
5095
|
+
isEdit = input(false, ...(ngDevMode ? [{ debugName: "isEdit" }] : /* istanbul ignore next */ []));
|
|
5096
|
+
showControls = input(true, ...(ngDevMode ? [{ debugName: "showControls" }] : /* istanbul ignore next */ []));
|
|
5097
|
+
// Output
|
|
5098
|
+
rangeChanged = output();
|
|
5099
|
+
// ============================================
|
|
5100
|
+
// STATE
|
|
5101
|
+
// ============================================
|
|
5102
|
+
startDateStr = signal('', ...(ngDevMode ? [{ debugName: "startDateStr" }] : /* istanbul ignore next */ []));
|
|
5103
|
+
endDateStr = signal('', ...(ngDevMode ? [{ debugName: "endDateStr" }] : /* istanbul ignore next */ []));
|
|
5104
|
+
// ✅ Exponer isDevMode como propiedad pública para el template si es necesario
|
|
5105
|
+
isDevMode = isDevMode();
|
|
5106
|
+
// ============================================
|
|
5107
|
+
// COMPUTED
|
|
5108
|
+
// ============================================
|
|
5109
|
+
shouldShowControls = computed(() => {
|
|
5110
|
+
return this.isEdit() || this.showControls();
|
|
5111
|
+
}, ...(ngDevMode ? [{ debugName: "shouldShowControls" }] : /* istanbul ignore next */ []));
|
|
5112
|
+
months = computed(() => {
|
|
5113
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5114
|
+
const start = this.startDateStr();
|
|
5115
|
+
const end = this.endDateStr();
|
|
5116
|
+
if (!start || !end) {
|
|
5117
|
+
this.logPerformance('months', perfStart);
|
|
5118
|
+
return [];
|
|
5119
|
+
}
|
|
5120
|
+
const zonaHoraria = 'America/Guatemala';
|
|
5121
|
+
const startDate = moment(start).tz(zonaHoraria).toDate();
|
|
5122
|
+
const endDate = moment(end).tz(zonaHoraria).toDate();
|
|
5123
|
+
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
|
|
5124
|
+
this.logDebug('Fechas inválidas:', { start, end });
|
|
5125
|
+
this.logPerformance('months', perfStart);
|
|
5126
|
+
return [];
|
|
5127
|
+
}
|
|
5128
|
+
this.logDebug('fecha inicio: ', startDate);
|
|
5129
|
+
this.logDebug('fecha final: ', endDate);
|
|
5130
|
+
const startMonth = new Date(startDate.getFullYear(), startDate.getMonth(), 1);
|
|
5131
|
+
const endMonth = new Date(endDate.getFullYear(), endDate.getMonth(), 1);
|
|
5132
|
+
const monthsToShow = [];
|
|
5133
|
+
monthsToShow.push(this.generateMonth(startMonth, startDate, endDate));
|
|
5134
|
+
if (startMonth.getTime() !== endMonth.getTime()) {
|
|
5135
|
+
monthsToShow.push(this.generateMonth(endMonth, startDate, endDate));
|
|
5136
|
+
}
|
|
5137
|
+
this.logPerformance('months', perfStart);
|
|
5138
|
+
return monthsToShow;
|
|
5139
|
+
}, ...(ngDevMode ? [{ debugName: "months" }] : /* istanbul ignore next */ []));
|
|
5140
|
+
formattedHolidays = computed(() => {
|
|
5141
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5142
|
+
const holidays = this.kpi()?.holidaysList || [];
|
|
5143
|
+
const result = holidays.map((h) => ({
|
|
5144
|
+
date: this.normalizeDateToString(h.dateHoliday),
|
|
5145
|
+
label: h.labelHoliday,
|
|
5146
|
+
}));
|
|
5147
|
+
this.logPerformance('formattedHolidays', perfStart);
|
|
5148
|
+
return result;
|
|
5149
|
+
}, ...(ngDevMode ? [{ debugName: "formattedHolidays" }] : /* istanbul ignore next */ []));
|
|
5150
|
+
// ============================================
|
|
5151
|
+
// KPI: Estadísticas del rango (CORREGIDO)
|
|
5152
|
+
// ============================================
|
|
5153
|
+
kpi = computed(() => {
|
|
5154
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5155
|
+
const start = this.startDateStr();
|
|
5156
|
+
const end = this.endDateStr();
|
|
5157
|
+
if (!start || !end) {
|
|
5158
|
+
this.logPerformance('kpi', perfStart);
|
|
5159
|
+
return null;
|
|
5160
|
+
}
|
|
5161
|
+
const startDate = new Date(start);
|
|
5162
|
+
const endDate = new Date(end);
|
|
5163
|
+
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
|
|
5164
|
+
this.logPerformance('kpi', perfStart);
|
|
5165
|
+
return null;
|
|
5166
|
+
}
|
|
5167
|
+
const holidays = this.holidays();
|
|
5168
|
+
const excludeSun = this.excludeSundays();
|
|
5169
|
+
// 1. Calcular días totales
|
|
5170
|
+
const totalDays = this.getDaysBetween(startDate, endDate);
|
|
5171
|
+
// 2. Calcular domingos en el rango
|
|
5172
|
+
let sundays = 0;
|
|
5173
|
+
const current = new Date(startDate);
|
|
5174
|
+
while (current <= endDate) {
|
|
5175
|
+
if (current.getDay() === 0) {
|
|
5176
|
+
sundays++;
|
|
5177
|
+
}
|
|
5178
|
+
current.setDate(current.getDate() + 1);
|
|
5179
|
+
}
|
|
5180
|
+
// 3. 🔥 Calcular feriados en el rango
|
|
5181
|
+
const holidaysInRange = holidays.filter((h) => {
|
|
5182
|
+
const hStr = this.normalizeDateToString(h.dateHoliday);
|
|
5183
|
+
return hStr >= start && hStr <= end;
|
|
5184
|
+
});
|
|
5185
|
+
// 4. 🔥 Días hábiles = total - domingos - feriados
|
|
5186
|
+
let businessDays = totalDays;
|
|
5187
|
+
if (excludeSun) {
|
|
5188
|
+
businessDays = totalDays - sundays;
|
|
5189
|
+
}
|
|
5190
|
+
// 🔥 CORRECCIÓN: Restar feriados independientemente de excludeSun
|
|
5191
|
+
businessDays = businessDays - holidaysInRange.length;
|
|
5192
|
+
const kpiResult = {
|
|
5193
|
+
totalDays,
|
|
5194
|
+
businessDays,
|
|
5195
|
+
holidays: holidaysInRange.length,
|
|
5196
|
+
sundays: excludeSun ? sundays : 0,
|
|
5197
|
+
holidaysList: holidaysInRange,
|
|
5198
|
+
startDate: start,
|
|
5199
|
+
endDate: end,
|
|
5200
|
+
};
|
|
5201
|
+
this.logDebug('KPI calculado:', kpiResult);
|
|
5202
|
+
this.logPerformance('kpi', perfStart);
|
|
5203
|
+
return kpiResult;
|
|
5204
|
+
}, ...(ngDevMode ? [{ debugName: "kpi" }] : /* istanbul ignore next */ []));
|
|
5205
|
+
// ============================================
|
|
5206
|
+
// EFFECTS
|
|
5207
|
+
// ============================================
|
|
5208
|
+
constructor() {
|
|
5209
|
+
effect(() => {
|
|
5210
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5211
|
+
const value = this.startDate();
|
|
5212
|
+
const formatted = this.formatInputDate(value);
|
|
5213
|
+
this.startDateStr.set(formatted);
|
|
5214
|
+
this.logDebug('startDate actualizado:', { value, formatted });
|
|
5215
|
+
this.emitRangeChange();
|
|
5216
|
+
this.logPerformance('startDate effect', perfStart);
|
|
5217
|
+
});
|
|
5218
|
+
effect(() => {
|
|
5219
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5220
|
+
const value = this.endDate();
|
|
5221
|
+
const formatted = this.formatInputDate(value);
|
|
5222
|
+
this.endDateStr.set(formatted);
|
|
5223
|
+
this.logDebug('endDate actualizado:', { value, formatted });
|
|
5224
|
+
this.emitRangeChange();
|
|
5225
|
+
this.logPerformance('endDate effect', perfStart);
|
|
5226
|
+
});
|
|
5227
|
+
effect(() => {
|
|
5228
|
+
this.logDebug('excludeSundays actualizado:', this.excludeSundays());
|
|
5229
|
+
});
|
|
5230
|
+
}
|
|
5231
|
+
// ============================================
|
|
5232
|
+
// PRIVATE METHODS
|
|
5233
|
+
// ============================================
|
|
5234
|
+
normalizeDateToString(date) {
|
|
5235
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5236
|
+
let result = '';
|
|
5237
|
+
if (!date) {
|
|
5238
|
+
this.logPerformance('normalizeDateToString', perfStart);
|
|
5239
|
+
return result;
|
|
5240
|
+
}
|
|
5241
|
+
if (date instanceof Date) {
|
|
5242
|
+
if (isNaN(date.getTime())) {
|
|
5243
|
+
this.logPerformance('normalizeDateToString', perfStart);
|
|
5244
|
+
return result;
|
|
5245
|
+
}
|
|
5246
|
+
result = this.formatDate(date);
|
|
5247
|
+
}
|
|
5248
|
+
if (typeof date === 'string') {
|
|
5249
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
5250
|
+
result = date;
|
|
5251
|
+
}
|
|
5252
|
+
else {
|
|
5253
|
+
const parsed = new Date(date);
|
|
5254
|
+
if (!isNaN(parsed.getTime())) {
|
|
5255
|
+
result = this.formatDate(parsed);
|
|
5256
|
+
}
|
|
5257
|
+
}
|
|
5258
|
+
}
|
|
5259
|
+
this.logPerformance('normalizeDateToString', perfStart);
|
|
5260
|
+
return result;
|
|
5261
|
+
}
|
|
5262
|
+
formatInputDate(value) {
|
|
5263
|
+
if (!value)
|
|
5264
|
+
return '';
|
|
5265
|
+
if (value instanceof Date) {
|
|
5266
|
+
if (isNaN(value.getTime()))
|
|
5267
|
+
return '';
|
|
5268
|
+
return this.formatDate(value);
|
|
5269
|
+
}
|
|
5270
|
+
if (typeof value === 'string') {
|
|
5271
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
5272
|
+
return value;
|
|
5273
|
+
}
|
|
5274
|
+
const date = new Date(value);
|
|
5275
|
+
if (!isNaN(date.getTime())) {
|
|
5276
|
+
return this.formatDate(date);
|
|
5277
|
+
}
|
|
5278
|
+
return '';
|
|
5279
|
+
}
|
|
5280
|
+
return '';
|
|
5281
|
+
}
|
|
5282
|
+
emitRangeChange() {
|
|
5283
|
+
const start = this.startDateStr();
|
|
5284
|
+
const end = this.endDateStr();
|
|
5285
|
+
if (start && end) {
|
|
5286
|
+
this.logDebug('Emitiendo rangeChanged:', { start, end });
|
|
5287
|
+
this.rangeChanged.emit({ start, end });
|
|
5288
|
+
}
|
|
5289
|
+
}
|
|
5290
|
+
// ============================================
|
|
5291
|
+
// PUBLIC METHODS (Template)
|
|
5292
|
+
// ============================================
|
|
5293
|
+
onStartDateChange(event) {
|
|
5294
|
+
if (!this.isEdit())
|
|
5295
|
+
return;
|
|
5296
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5297
|
+
const value = event.target.value;
|
|
5298
|
+
this.startDate.set(value);
|
|
5299
|
+
this.logDebug('onStartDateChange:', value);
|
|
5300
|
+
this.logPerformance('onStartDateChange', perfStart);
|
|
5301
|
+
}
|
|
5302
|
+
onEndDateChange(event) {
|
|
5303
|
+
if (!this.isEdit())
|
|
5304
|
+
return;
|
|
5305
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5306
|
+
const value = event.target.value;
|
|
5307
|
+
this.endDate.set(value);
|
|
5308
|
+
this.logDebug('onEndDateChange:', value);
|
|
5309
|
+
this.logPerformance('onEndDateChange', perfStart);
|
|
5310
|
+
}
|
|
5311
|
+
onToggleSundays(event) {
|
|
5312
|
+
if (!this.isEdit())
|
|
5313
|
+
return;
|
|
5314
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5315
|
+
const checked = event.target.checked;
|
|
5316
|
+
this.excludeSundays.set(checked);
|
|
5317
|
+
this.logDebug('onToggleSundays:', checked);
|
|
5318
|
+
this.logPerformance('onToggleSundays', perfStart);
|
|
5319
|
+
}
|
|
5320
|
+
// ============================================
|
|
5321
|
+
// GENERATE MONTH
|
|
5322
|
+
// ============================================
|
|
5323
|
+
generateMonth(monthDate, rangeStart, rangeEnd) {
|
|
5324
|
+
const perfStart = this.shouldLog() ? performance.now() : 0;
|
|
5325
|
+
const year = monthDate.getFullYear();
|
|
5326
|
+
const month = monthDate.getMonth();
|
|
5327
|
+
const firstDay = new Date(year, month, 1);
|
|
5328
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
5329
|
+
const startDayOfWeek = firstDay.getDay();
|
|
5330
|
+
const days = [];
|
|
5331
|
+
const holidays = this.holidays();
|
|
5332
|
+
const totalRangeDays = this.getDaysBetween(rangeStart, rangeEnd);
|
|
5333
|
+
// Días anteriores
|
|
5334
|
+
const prevMonthLastDay = new Date(year, month, 0).getDate();
|
|
5335
|
+
for (let i = startDayOfWeek - 1; i >= 0; i--) {
|
|
5336
|
+
const d = new Date(year, month, -i);
|
|
5337
|
+
days.push({
|
|
5338
|
+
date: d,
|
|
5339
|
+
day: prevMonthLastDay - i,
|
|
5340
|
+
isCurrentMonth: false,
|
|
5341
|
+
isSunday: d.getDay() === 0,
|
|
5342
|
+
isInRange: false,
|
|
5343
|
+
isStart: false,
|
|
5344
|
+
isEnd: false,
|
|
5345
|
+
isHoliday: false,
|
|
5346
|
+
disabled: false,
|
|
5347
|
+
});
|
|
5348
|
+
}
|
|
5349
|
+
// Días del mes actual
|
|
5350
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
5351
|
+
const d = new Date(year, month, i);
|
|
5352
|
+
const dateStr = this.formatDate(d);
|
|
5353
|
+
const holiday = holidays.find((h) => {
|
|
5354
|
+
const hStr = this.normalizeDateToString(h.dateHoliday);
|
|
5355
|
+
return hStr === dateStr;
|
|
5356
|
+
});
|
|
5357
|
+
const isSunday = d.getDay() === 0;
|
|
5358
|
+
const isInRange = this.isDateInRange(d, rangeStart, rangeEnd);
|
|
5359
|
+
const isStart = this.isSameDay(d, rangeStart);
|
|
5360
|
+
const isEnd = this.isSameDay(d, rangeEnd);
|
|
5361
|
+
const disabled = this.excludeSundays() && isSunday;
|
|
5362
|
+
let rangePosition = 0;
|
|
5363
|
+
if (isInRange && !disabled) {
|
|
5364
|
+
const dayDiff = this.getDaysBetween(rangeStart, d) - 1;
|
|
5365
|
+
rangePosition = totalRangeDays > 1 ? dayDiff / (totalRangeDays - 1) : 0;
|
|
5366
|
+
}
|
|
5367
|
+
days.push({
|
|
5368
|
+
date: d,
|
|
5369
|
+
day: i,
|
|
5370
|
+
isCurrentMonth: true,
|
|
5371
|
+
isSunday,
|
|
5372
|
+
isInRange,
|
|
5373
|
+
isStart,
|
|
5374
|
+
isEnd,
|
|
5375
|
+
isHoliday: !!holiday,
|
|
5376
|
+
holidayLabel: holiday?.labelHoliday,
|
|
5377
|
+
disabled,
|
|
5378
|
+
rangePosition,
|
|
5379
|
+
});
|
|
5380
|
+
}
|
|
5381
|
+
// Días siguientes
|
|
5382
|
+
const totalCells = Math.ceil((startDayOfWeek + daysInMonth) / 7) * 7;
|
|
5383
|
+
const remaining = totalCells - days.length;
|
|
5384
|
+
for (let i = 1; i <= remaining; i++) {
|
|
5385
|
+
const d = new Date(year, month + 1, i);
|
|
5386
|
+
days.push({
|
|
5387
|
+
date: d,
|
|
5388
|
+
day: i,
|
|
5389
|
+
isCurrentMonth: false,
|
|
5390
|
+
isSunday: d.getDay() === 0,
|
|
5391
|
+
isInRange: false,
|
|
5392
|
+
isStart: false,
|
|
5393
|
+
isEnd: false,
|
|
5394
|
+
isHoliday: false,
|
|
5395
|
+
disabled: false,
|
|
5396
|
+
});
|
|
5397
|
+
}
|
|
5398
|
+
// Recalcular para días del mes actual
|
|
5399
|
+
for (const day of days) {
|
|
5400
|
+
if (day.isCurrentMonth) {
|
|
5401
|
+
const d = day.date;
|
|
5402
|
+
day.isInRange = this.isDateInRange(d, rangeStart, rangeEnd);
|
|
5403
|
+
day.isStart = this.isSameDay(d, rangeStart);
|
|
5404
|
+
day.isEnd = this.isSameDay(d, rangeEnd);
|
|
5405
|
+
day.disabled = this.excludeSundays() && day.isSunday;
|
|
5406
|
+
if (day.isInRange && !day.disabled) {
|
|
5407
|
+
const dayDiff = this.getDaysBetween(rangeStart, d) - 1;
|
|
5408
|
+
day.rangePosition =
|
|
5409
|
+
totalRangeDays > 1 ? dayDiff / (totalRangeDays - 1) : 0;
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5412
|
+
}
|
|
5413
|
+
const monthNames = [
|
|
5414
|
+
'Enero',
|
|
5415
|
+
'Febrero',
|
|
5416
|
+
'Marzo',
|
|
5417
|
+
'Abril',
|
|
5418
|
+
'Mayo',
|
|
5419
|
+
'Junio',
|
|
5420
|
+
'Julio',
|
|
5421
|
+
'Agosto',
|
|
5422
|
+
'Septiembre',
|
|
5423
|
+
'Octubre',
|
|
5424
|
+
'Noviembre',
|
|
5425
|
+
'Diciembre',
|
|
5426
|
+
];
|
|
5427
|
+
this.logPerformance('generateMonth', perfStart);
|
|
5428
|
+
return {
|
|
5429
|
+
label: `${monthNames[month]} ${year}`,
|
|
5430
|
+
days,
|
|
5431
|
+
};
|
|
5432
|
+
}
|
|
5433
|
+
// ============================================
|
|
5434
|
+
// HELPERS
|
|
5435
|
+
// ============================================
|
|
5436
|
+
getDaysBetween(start, end) {
|
|
5437
|
+
const s = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
5438
|
+
const e = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
5439
|
+
const diffTime = Math.abs(e.getTime() - s.getTime());
|
|
5440
|
+
return Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1;
|
|
5441
|
+
}
|
|
5442
|
+
isDateInRange(date, start, end) {
|
|
5443
|
+
const d = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
5444
|
+
const s = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
5445
|
+
const e = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
5446
|
+
return d >= s && d <= e;
|
|
5447
|
+
}
|
|
5448
|
+
isSameDay(d1, d2) {
|
|
5449
|
+
if (!d2)
|
|
5450
|
+
return false;
|
|
5451
|
+
return (d1.getFullYear() === d2.getFullYear() &&
|
|
5452
|
+
d1.getMonth() === d2.getMonth() &&
|
|
5453
|
+
d1.getDate() === d2.getDate());
|
|
5454
|
+
}
|
|
5455
|
+
formatDate(date) {
|
|
5456
|
+
const y = date.getFullYear();
|
|
5457
|
+
const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
5458
|
+
const d = String(date.getDate()).padStart(2, '0');
|
|
5459
|
+
return `${y}-${m}-${d}`;
|
|
5460
|
+
}
|
|
5461
|
+
// ============================================
|
|
5462
|
+
// LOGGING - SIMPLE Y SEGURO
|
|
5463
|
+
// ============================================
|
|
5464
|
+
/**
|
|
5465
|
+
* Verifica si debemos mostrar logs
|
|
5466
|
+
* ✅ Usa isDevMode() de Angular - simple y confiable
|
|
5467
|
+
*/
|
|
5468
|
+
shouldLog() {
|
|
5469
|
+
return isDevMode() && this.debugMode();
|
|
5470
|
+
}
|
|
5471
|
+
/**
|
|
5472
|
+
* Log de depuración - Solo visible en desarrollo con debugMode=true
|
|
5473
|
+
* 🔥 NUNCA se ejecuta en producción
|
|
5474
|
+
*/
|
|
5475
|
+
logDebug(...args) {
|
|
5476
|
+
if (this.shouldLog()) {
|
|
5477
|
+
console.log('[DsxCalendarView]', ...args);
|
|
5478
|
+
}
|
|
5479
|
+
}
|
|
5480
|
+
/**
|
|
5481
|
+
* Log de rendimiento - Mide tiempos de ejecución
|
|
5482
|
+
* 🔥 NUNCA se ejecuta en producción
|
|
5483
|
+
*/
|
|
5484
|
+
logPerformance(method, startTime) {
|
|
5485
|
+
if (this.shouldLog() && startTime > 0) {
|
|
5486
|
+
const elapsed = (performance.now() - startTime).toFixed(2);
|
|
5487
|
+
if (Number(elapsed) > 0.1) {
|
|
5488
|
+
console.log(`[DsxCalendarView] ⚡ ${method} - ${elapsed}ms`);
|
|
5489
|
+
}
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5492
|
+
// ============================================
|
|
5493
|
+
// TEMPLATE HELPERS
|
|
5494
|
+
// ============================================
|
|
5495
|
+
chunk(arr, size) {
|
|
5496
|
+
const result = [];
|
|
5497
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
5498
|
+
result.push(arr.slice(i, i + size));
|
|
5499
|
+
}
|
|
5500
|
+
return result;
|
|
5501
|
+
}
|
|
5502
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxCalendarView, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5503
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: DsxCalendarView, isStandalone: true, selector: "dsx-calendar-view", inputs: { startDate: { classPropertyName: "startDate", publicName: "startDate", isSignal: true, isRequired: false, transformFunction: null }, endDate: { classPropertyName: "endDate", publicName: "endDate", isSignal: true, isRequired: false, transformFunction: null }, excludeSundays: { classPropertyName: "excludeSundays", publicName: "excludeSundays", isSignal: true, isRequired: false, transformFunction: null }, holidays: { classPropertyName: "holidays", publicName: "holidays", isSignal: true, isRequired: false, transformFunction: null }, compactMode: { classPropertyName: "compactMode", publicName: "compactMode", isSignal: true, isRequired: false, transformFunction: null }, showKPI: { classPropertyName: "showKPI", publicName: "showKPI", isSignal: true, isRequired: false, transformFunction: null }, debugMode: { classPropertyName: "debugMode", publicName: "debugMode", isSignal: true, isRequired: false, transformFunction: null }, isEdit: { classPropertyName: "isEdit", publicName: "isEdit", isSignal: true, isRequired: false, transformFunction: null }, showControls: { classPropertyName: "showControls", publicName: "showControls", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { startDate: "startDateChange", endDate: "endDateChange", excludeSundays: "excludeSundaysChange", rangeChanged: "rangeChanged" }, ngImport: i0, template: "<!-- dsx-calendar-view.html - ACTUALIZADO CON showControls -->\r\n\r\n<div class=\"calendar-range\" [class.compact]=\"compactMode()\">\r\n <!-- ==========================================\r\n CONTROLES - Ocultables con showControls\r\n ========================================== -->\r\n @if (shouldShowControls()) {\r\n <div class=\"controls\">\r\n <div class=\"control-group\">\r\n <label>Fecha Inicio</label>\r\n <input\r\n type=\"date\"\r\n [value]=\"startDateStr()\"\r\n (input)=\"onStartDateChange($event)\"\r\n [disabled]=\"!isEdit()\"\r\n />\r\n </div>\r\n <div class=\"control-group\">\r\n <label>Fecha Fin</label>\r\n <input\r\n type=\"date\"\r\n [value]=\"endDateStr()\"\r\n (input)=\"onEndDateChange($event)\"\r\n [disabled]=\"!isEdit()\"\r\n />\r\n </div>\r\n <div class=\"control-group checkbox\">\r\n <label>\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"excludeSundays()\"\r\n (change)=\"onToggleSundays($event)\"\r\n [disabled]=\"!isEdit()\"\r\n />\r\n Excluir Domingos\r\n </label>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- ==========================================\r\n KPIs\r\n ========================================== -->\r\n @if (showKPI() && kpi()) {\r\n <div class=\"kpi-container\">\r\n <div class=\"kpi-item\">\r\n <span class=\"kpi-label\">\r\n <i class=\"fa-regular fa-calendar-days\"></i>\r\n D\u00EDas calendario\r\n </span>\r\n <span class=\"kpi-value\">{{ kpi()?.totalDays }}</span>\r\n </div>\r\n <div class=\"kpi-item\">\r\n <span class=\"kpi-label\">\r\n <i class=\"fa-regular fa-circle-check\"></i>\r\n D\u00EDas h\u00E1biles\r\n </span>\r\n <span class=\"kpi-value\">{{ kpi()?.businessDays }}</span>\r\n </div>\r\n <div class=\"kpi-item\">\r\n <span class=\"kpi-label\">\r\n <i class=\"fa-solid fa-not-equal\"></i>\r\n Feriados\r\n </span>\r\n <span class=\"kpi-value\">{{ kpi()?.holidays }}</span>\r\n </div>\r\n @if (excludeSundays()) {\r\n <div class=\"kpi-item\">\r\n <span class=\"kpi-label\">\r\n <i class=\"fa-solid fa-calendar-day\"></i>\r\n Domingos\r\n </span>\r\n <span class=\"kpi-value\">{{ kpi()?.sundays }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- ==========================================\r\n CALENDARIO\r\n ========================================== -->\r\n <div class=\"months-grid\">\r\n @for (month of months(); track month.label) {\r\n <div class=\"month-card\">\r\n <div class=\"month-title\">{{ month.label }}</div>\r\n <table class=\"calendar-table\">\r\n <thead>\r\n <tr>\r\n @for (dia of ['Do','Lu','Ma','Mi','Ju','Vi','Sa']; track dia) {\r\n <th>{{ dia }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of chunk(month.days, 7); track $index) {\r\n <tr>\r\n @for (day of row; track day.date) {\r\n <td\r\n [class.other-month]=\"!day.isCurrentMonth\"\r\n [class.sunday]=\"day.isSunday && !day.disabled && day.isCurrentMonth\"\r\n [class.disabled-sunday]=\"day.disabled\"\r\n [class.in-range]=\"day.isInRange && day.isCurrentMonth\"\r\n [class.start-date]=\"day.isStart && day.isCurrentMonth\"\r\n [class.end-date]=\"day.isEnd && day.isCurrentMonth\"\r\n [class.holiday]=\"day.isHoliday && day.isCurrentMonth\"\r\n [class.same-day]=\"day.isStart && day.isEnd\"\r\n [style.--range-position]=\"day.rangePosition\"\r\n [title]=\"day.isHoliday ? day.holidayLabel : ''\"\r\n >\r\n <span class=\"day-number\">{{ day.day }}</span>\r\n @if (day.isHoliday && day.isCurrentMonth) {\r\n <span class=\"holiday-label\">{{ day.holidayLabel }}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ==========================================\r\n FERIADOS DETALLE\r\n ========================================== -->\r\n @if (kpi()?.holidays && formattedHolidays().length) {\r\n <div class=\"holidays-detail\">\r\n <div class=\"holidays-detail-title\">\r\n <i class=\"fa-solid fa-calendar-day\"></i>\r\n Feriados en el per\u00EDodo\r\n </div>\r\n <div class=\"holidays-detail-list\">\r\n @for (h of formattedHolidays(); track h.date) {\r\n <span class=\"holiday-detail-tag\">\r\n <i class=\"fa-regular fa-calendar\"></i>\r\n {{ h.date }} - {{ h.label }}\r\n </span>\r\n }\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".calendar-range{font-family:system-ui,-apple-system,sans-serif;max-width:100%;padding:8px}.calendar-range.compact{max-width:750px;margin:0 auto}.controls{display:flex;flex-wrap:wrap;gap:16px 24px;margin-bottom:12px;padding:10px 16px;background:#f8f9fa;border-radius:6px;border:1px solid #e9ecef;align-items:center;justify-content:center}.control-group{display:flex;align-items:center;gap:8px}.control-group label{font-size:.8rem;font-weight:600;color:#495057;white-space:nowrap}.control-group input[type=date]{padding:4px 8px;border:1px solid #ced4da;border-radius:4px;font-size:.8rem;background:#fff;min-width:130px}.control-group.checkbox{margin-left:0;padding-left:8px;border-left:1px solid #dee2e6}.control-group.checkbox label{font-weight:400;font-size:.75rem;cursor:pointer;display:flex;align-items:center;gap:4px}.kpi-container{display:flex;flex-wrap:wrap;gap:20px 32px;padding:10px 20px;margin-bottom:12px;background:linear-gradient(135deg,#f8f9fa,#e9ecef);border-radius:8px;border:1px solid #dee2e6;justify-content:center;align-items:center}.kpi-item{display:flex;align-items:center;gap:6px;font-size:.85rem}.kpi-label{color:#6c757d;font-weight:500}.kpi-value{font-weight:700;color:#212529;font-size:1.1rem;min-width:24px;text-align:center;background:#fff;padding:0 8px;border-radius:4px}.kpi-holidays{display:none}.months-grid{display:flex;gap:16px;justify-content:center;flex-wrap:wrap}.month-card{flex:1 1 auto;min-width:230px;max-width:300px;background:#fff;border:1px solid #dee2e6;border-radius:6px;padding:6px 4px 4px}.month-title{text-align:center;font-size:.85rem;font-weight:600;color:#212529;margin-bottom:4px;padding:2px 0}.calendar-table{width:100%;border-collapse:collapse;font-size:.7rem;table-layout:fixed}.calendar-table th{text-align:center;font-weight:600;color:#6c757d;padding:2px 0;font-size:.65rem}.calendar-table td{text-align:center;padding:2px 0;border-radius:3px;height:28px;vertical-align:middle;font-size:.7rem;transition:background .1s;position:relative}.other-month{color:#ced4da;background:transparent}.sunday{background:#ffe0e0}.disabled-sunday{background:#f1f3f5!important;color:#adb5bd!important;cursor:default}.in-range{background:#c4eeff}.start-date{background:#28a745!important;color:#fff!important;border-radius:3px 0 0 3px;font-weight:700}.end-date{background:#d17015!important;color:#fff!important;border-radius:0 3px 3px 0;font-weight:700}.same-day{background:#28a745!important;color:#fff!important;border-radius:3px}.day-number{display:block;font-size:.75rem;line-height:1.2}.holiday:not(.other-month){background:#e8f0fe!important;border:2px solid #1a5a8c!important;border-radius:4px!important;position:relative;z-index:1}.holiday .day-number{font-weight:700!important;color:#1a3a5c!important}.holiday-label{display:block;font-size:.45rem;line-height:1.2;color:#1a3a5c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:95%;margin:0 auto;background:#1a5a8c1a;border-radius:2px;padding:0 2px;font-weight:600}.holiday:hover .holiday-label{white-space:normal;overflow:visible;position:absolute;bottom:100%;left:50%;transform:translate(-50%);background:#1a3a5c;color:#fff;padding:4px 10px;border-radius:4px;font-size:.6rem;z-index:10;box-shadow:0 2px 8px #0003;max-width:180px;white-space:nowrap}.holidays-detail{margin-top:12px;padding:10px 16px;background:#f0f4f8;border:1px solid #1a5a8c;border-radius:8px;border-left:4px solid #1a5a8c}.holidays-detail-title{font-size:.8rem;font-weight:600;color:#1a3a5c;margin-bottom:6px;display:flex;align-items:center;gap:6px}.holidays-detail-title i{color:#1a5a8c}.holidays-detail-list{display:flex;flex-wrap:wrap;gap:6px 12px}.holiday-detail-tag{font-size:.7rem;color:#1a3a5c;background:#e8f0fe;padding:2px 12px;border-radius:12px;border:1px solid #b3cfe5;display:inline-flex;align-items:center;gap:4px;white-space:nowrap}.holiday-detail-tag i{font-size:.6rem;color:#1a5a8c}.control-group input:disabled,.control-group input[disabled]{background:#f1f3f5!important;color:#6c757d!important;cursor:not-allowed;opacity:.7}.control-group input[type=checkbox]:disabled{cursor:not-allowed;opacity:.6}.control-group.checkbox label:has(input:disabled){color:#6c757d;cursor:not-allowed}@media(max-width:600px){.month-card{min-width:180px;max-width:100%}.controls{gap:10px;padding:8px 12px;flex-direction:column;align-items:stretch}.control-group{justify-content:space-between}.control-group input[type=date]{min-width:100px;flex:1}.control-group.checkbox{border-left:none;padding-left:0;justify-content:center}.kpi-container{gap:10px 16px;padding:8px 12px;justify-content:center}.kpi-item{font-size:.75rem}.kpi-value{font-size:.9rem;min-width:20px;padding:0 4px}.holidays-detail{padding:8px 12px}.holiday-detail-tag{font-size:.6rem;padding:2px 8px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }] });
|
|
5504
|
+
}
|
|
5505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxCalendarView, decorators: [{
|
|
5506
|
+
type: Component,
|
|
5507
|
+
args: [{ selector: 'dsx-calendar-view', standalone: true, imports: [CommonModule, FormsModule], template: "<!-- dsx-calendar-view.html - ACTUALIZADO CON showControls -->\r\n\r\n<div class=\"calendar-range\" [class.compact]=\"compactMode()\">\r\n <!-- ==========================================\r\n CONTROLES - Ocultables con showControls\r\n ========================================== -->\r\n @if (shouldShowControls()) {\r\n <div class=\"controls\">\r\n <div class=\"control-group\">\r\n <label>Fecha Inicio</label>\r\n <input\r\n type=\"date\"\r\n [value]=\"startDateStr()\"\r\n (input)=\"onStartDateChange($event)\"\r\n [disabled]=\"!isEdit()\"\r\n />\r\n </div>\r\n <div class=\"control-group\">\r\n <label>Fecha Fin</label>\r\n <input\r\n type=\"date\"\r\n [value]=\"endDateStr()\"\r\n (input)=\"onEndDateChange($event)\"\r\n [disabled]=\"!isEdit()\"\r\n />\r\n </div>\r\n <div class=\"control-group checkbox\">\r\n <label>\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"excludeSundays()\"\r\n (change)=\"onToggleSundays($event)\"\r\n [disabled]=\"!isEdit()\"\r\n />\r\n Excluir Domingos\r\n </label>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- ==========================================\r\n KPIs\r\n ========================================== -->\r\n @if (showKPI() && kpi()) {\r\n <div class=\"kpi-container\">\r\n <div class=\"kpi-item\">\r\n <span class=\"kpi-label\">\r\n <i class=\"fa-regular fa-calendar-days\"></i>\r\n D\u00EDas calendario\r\n </span>\r\n <span class=\"kpi-value\">{{ kpi()?.totalDays }}</span>\r\n </div>\r\n <div class=\"kpi-item\">\r\n <span class=\"kpi-label\">\r\n <i class=\"fa-regular fa-circle-check\"></i>\r\n D\u00EDas h\u00E1biles\r\n </span>\r\n <span class=\"kpi-value\">{{ kpi()?.businessDays }}</span>\r\n </div>\r\n <div class=\"kpi-item\">\r\n <span class=\"kpi-label\">\r\n <i class=\"fa-solid fa-not-equal\"></i>\r\n Feriados\r\n </span>\r\n <span class=\"kpi-value\">{{ kpi()?.holidays }}</span>\r\n </div>\r\n @if (excludeSundays()) {\r\n <div class=\"kpi-item\">\r\n <span class=\"kpi-label\">\r\n <i class=\"fa-solid fa-calendar-day\"></i>\r\n Domingos\r\n </span>\r\n <span class=\"kpi-value\">{{ kpi()?.sundays }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- ==========================================\r\n CALENDARIO\r\n ========================================== -->\r\n <div class=\"months-grid\">\r\n @for (month of months(); track month.label) {\r\n <div class=\"month-card\">\r\n <div class=\"month-title\">{{ month.label }}</div>\r\n <table class=\"calendar-table\">\r\n <thead>\r\n <tr>\r\n @for (dia of ['Do','Lu','Ma','Mi','Ju','Vi','Sa']; track dia) {\r\n <th>{{ dia }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of chunk(month.days, 7); track $index) {\r\n <tr>\r\n @for (day of row; track day.date) {\r\n <td\r\n [class.other-month]=\"!day.isCurrentMonth\"\r\n [class.sunday]=\"day.isSunday && !day.disabled && day.isCurrentMonth\"\r\n [class.disabled-sunday]=\"day.disabled\"\r\n [class.in-range]=\"day.isInRange && day.isCurrentMonth\"\r\n [class.start-date]=\"day.isStart && day.isCurrentMonth\"\r\n [class.end-date]=\"day.isEnd && day.isCurrentMonth\"\r\n [class.holiday]=\"day.isHoliday && day.isCurrentMonth\"\r\n [class.same-day]=\"day.isStart && day.isEnd\"\r\n [style.--range-position]=\"day.rangePosition\"\r\n [title]=\"day.isHoliday ? day.holidayLabel : ''\"\r\n >\r\n <span class=\"day-number\">{{ day.day }}</span>\r\n @if (day.isHoliday && day.isCurrentMonth) {\r\n <span class=\"holiday-label\">{{ day.holidayLabel }}</span>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ==========================================\r\n FERIADOS DETALLE\r\n ========================================== -->\r\n @if (kpi()?.holidays && formattedHolidays().length) {\r\n <div class=\"holidays-detail\">\r\n <div class=\"holidays-detail-title\">\r\n <i class=\"fa-solid fa-calendar-day\"></i>\r\n Feriados en el per\u00EDodo\r\n </div>\r\n <div class=\"holidays-detail-list\">\r\n @for (h of formattedHolidays(); track h.date) {\r\n <span class=\"holiday-detail-tag\">\r\n <i class=\"fa-regular fa-calendar\"></i>\r\n {{ h.date }} - {{ h.label }}\r\n </span>\r\n }\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".calendar-range{font-family:system-ui,-apple-system,sans-serif;max-width:100%;padding:8px}.calendar-range.compact{max-width:750px;margin:0 auto}.controls{display:flex;flex-wrap:wrap;gap:16px 24px;margin-bottom:12px;padding:10px 16px;background:#f8f9fa;border-radius:6px;border:1px solid #e9ecef;align-items:center;justify-content:center}.control-group{display:flex;align-items:center;gap:8px}.control-group label{font-size:.8rem;font-weight:600;color:#495057;white-space:nowrap}.control-group input[type=date]{padding:4px 8px;border:1px solid #ced4da;border-radius:4px;font-size:.8rem;background:#fff;min-width:130px}.control-group.checkbox{margin-left:0;padding-left:8px;border-left:1px solid #dee2e6}.control-group.checkbox label{font-weight:400;font-size:.75rem;cursor:pointer;display:flex;align-items:center;gap:4px}.kpi-container{display:flex;flex-wrap:wrap;gap:20px 32px;padding:10px 20px;margin-bottom:12px;background:linear-gradient(135deg,#f8f9fa,#e9ecef);border-radius:8px;border:1px solid #dee2e6;justify-content:center;align-items:center}.kpi-item{display:flex;align-items:center;gap:6px;font-size:.85rem}.kpi-label{color:#6c757d;font-weight:500}.kpi-value{font-weight:700;color:#212529;font-size:1.1rem;min-width:24px;text-align:center;background:#fff;padding:0 8px;border-radius:4px}.kpi-holidays{display:none}.months-grid{display:flex;gap:16px;justify-content:center;flex-wrap:wrap}.month-card{flex:1 1 auto;min-width:230px;max-width:300px;background:#fff;border:1px solid #dee2e6;border-radius:6px;padding:6px 4px 4px}.month-title{text-align:center;font-size:.85rem;font-weight:600;color:#212529;margin-bottom:4px;padding:2px 0}.calendar-table{width:100%;border-collapse:collapse;font-size:.7rem;table-layout:fixed}.calendar-table th{text-align:center;font-weight:600;color:#6c757d;padding:2px 0;font-size:.65rem}.calendar-table td{text-align:center;padding:2px 0;border-radius:3px;height:28px;vertical-align:middle;font-size:.7rem;transition:background .1s;position:relative}.other-month{color:#ced4da;background:transparent}.sunday{background:#ffe0e0}.disabled-sunday{background:#f1f3f5!important;color:#adb5bd!important;cursor:default}.in-range{background:#c4eeff}.start-date{background:#28a745!important;color:#fff!important;border-radius:3px 0 0 3px;font-weight:700}.end-date{background:#d17015!important;color:#fff!important;border-radius:0 3px 3px 0;font-weight:700}.same-day{background:#28a745!important;color:#fff!important;border-radius:3px}.day-number{display:block;font-size:.75rem;line-height:1.2}.holiday:not(.other-month){background:#e8f0fe!important;border:2px solid #1a5a8c!important;border-radius:4px!important;position:relative;z-index:1}.holiday .day-number{font-weight:700!important;color:#1a3a5c!important}.holiday-label{display:block;font-size:.45rem;line-height:1.2;color:#1a3a5c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:95%;margin:0 auto;background:#1a5a8c1a;border-radius:2px;padding:0 2px;font-weight:600}.holiday:hover .holiday-label{white-space:normal;overflow:visible;position:absolute;bottom:100%;left:50%;transform:translate(-50%);background:#1a3a5c;color:#fff;padding:4px 10px;border-radius:4px;font-size:.6rem;z-index:10;box-shadow:0 2px 8px #0003;max-width:180px;white-space:nowrap}.holidays-detail{margin-top:12px;padding:10px 16px;background:#f0f4f8;border:1px solid #1a5a8c;border-radius:8px;border-left:4px solid #1a5a8c}.holidays-detail-title{font-size:.8rem;font-weight:600;color:#1a3a5c;margin-bottom:6px;display:flex;align-items:center;gap:6px}.holidays-detail-title i{color:#1a5a8c}.holidays-detail-list{display:flex;flex-wrap:wrap;gap:6px 12px}.holiday-detail-tag{font-size:.7rem;color:#1a3a5c;background:#e8f0fe;padding:2px 12px;border-radius:12px;border:1px solid #b3cfe5;display:inline-flex;align-items:center;gap:4px;white-space:nowrap}.holiday-detail-tag i{font-size:.6rem;color:#1a5a8c}.control-group input:disabled,.control-group input[disabled]{background:#f1f3f5!important;color:#6c757d!important;cursor:not-allowed;opacity:.7}.control-group input[type=checkbox]:disabled{cursor:not-allowed;opacity:.6}.control-group.checkbox label:has(input:disabled){color:#6c757d;cursor:not-allowed}@media(max-width:600px){.month-card{min-width:180px;max-width:100%}.controls{gap:10px;padding:8px 12px;flex-direction:column;align-items:stretch}.control-group{justify-content:space-between}.control-group input[type=date]{min-width:100px;flex:1}.control-group.checkbox{border-left:none;padding-left:0;justify-content:center}.kpi-container{gap:10px 16px;padding:8px 12px;justify-content:center}.kpi-item{font-size:.75rem}.kpi-value{font-size:.9rem;min-width:20px;padding:0 4px}.holidays-detail{padding:8px 12px}.holiday-detail-tag{font-size:.6rem;padding:2px 8px}}\n"] }]
|
|
5508
|
+
}], ctorParameters: () => [], propDecorators: { startDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "startDate", required: false }] }, { type: i0.Output, args: ["startDateChange"] }], endDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "endDate", required: false }] }, { type: i0.Output, args: ["endDateChange"] }], excludeSundays: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludeSundays", required: false }] }, { type: i0.Output, args: ["excludeSundaysChange"] }], holidays: [{ type: i0.Input, args: [{ isSignal: true, alias: "holidays", required: false }] }], compactMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "compactMode", required: false }] }], showKPI: [{ type: i0.Input, args: [{ isSignal: true, alias: "showKPI", required: false }] }], debugMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "debugMode", required: false }] }], isEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEdit", required: false }] }], showControls: [{ type: i0.Input, args: [{ isSignal: true, alias: "showControls", required: false }] }], rangeChanged: [{ type: i0.Output, args: ["rangeChanged"] }] } });
|
|
5509
|
+
|
|
5080
5510
|
class FileComponent {
|
|
5081
5511
|
// Inputs
|
|
5082
5512
|
existingFile = input(null, ...(ngDevMode ? [{ debugName: "existingFile" }] : /* istanbul ignore next */ []));
|
|
@@ -8551,6 +8981,7 @@ const PRIME_NG_MODULES = [
|
|
|
8551
8981
|
ButtonModule,
|
|
8552
8982
|
CardModule,
|
|
8553
8983
|
CheckboxModule,
|
|
8984
|
+
ChipModule,
|
|
8554
8985
|
ContextMenuModule,
|
|
8555
8986
|
DataViewModule,
|
|
8556
8987
|
DatePickerModule,
|
|
@@ -8610,6 +9041,7 @@ class PrimeNgModule {
|
|
|
8610
9041
|
ButtonModule,
|
|
8611
9042
|
CardModule,
|
|
8612
9043
|
CheckboxModule,
|
|
9044
|
+
ChipModule,
|
|
8613
9045
|
ContextMenuModule,
|
|
8614
9046
|
DataViewModule,
|
|
8615
9047
|
DatePickerModule,
|
|
@@ -8666,6 +9098,7 @@ class PrimeNgModule {
|
|
|
8666
9098
|
ButtonModule,
|
|
8667
9099
|
CardModule,
|
|
8668
9100
|
CheckboxModule,
|
|
9101
|
+
ChipModule,
|
|
8669
9102
|
ContextMenuModule,
|
|
8670
9103
|
DataViewModule,
|
|
8671
9104
|
DatePickerModule,
|
|
@@ -9124,7 +9557,7 @@ class DsxdateShort {
|
|
|
9124
9557
|
useExisting: forwardRef(() => DsxdateShort),
|
|
9125
9558
|
multi: true,
|
|
9126
9559
|
},
|
|
9127
|
-
], ngImport: i0, template: "<!-- dsxdate-short.html -->\r\n<p-floatLabel variant=\"on\">\r\n <p-datepicker\r\n fluid\r\n appendTo=\"body\"\r\n [formControl]=\"fechaControl\"\r\n [fluid]=\"true\"\r\n [showIcon]=\"showIcon()\"\r\n [showOnFocus]=\"showOnFocus()\"\r\n [showButtonBar]=\"showButtonBar()\"\r\n [dateFormat]=\"dateFormat()\"\r\n [placeholder]=\"placeholder()\"\r\n pInputMask=\"99/99/9999\"\r\n />\r\n <label>{{ label() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- \u2705 SIN CONDICI\u00D3N - IGUAL QUE EL ORIGINAL -->\r\n<dsx-message-error [control]=\"fechaControl\" />\r\n\r\n<!-- Debug info -->\r\n@if (debugEnabled() && isDevMode) {\r\n<div\r\n class=\"debug-info\"\r\n style=\"\r\n font-size: 12px;\r\n color: #666;\r\n margin-top: 4px;\r\n border-top: 1px dashed #ccc;\r\n padding-top: 4px;\r\n \"\r\n>\r\n <small>\r\n <strong>Debug:</strong>\r\n Value: {{ fechaControl.value | json }} | Valid: {{ fechaControl.valid }} |\r\n Invalid: {{ fechaControl.invalid }} | Errors: {{ fechaControl.errors | json\r\n }} | Dirty: {{ fechaControl.dirty }} | Touched: {{ fechaControl.touched }} |\r\n Status: {{ fechaControl.status }}\r\n </small>\r\n</div>\r\n}\r\n", styles: [""], dependencies: [{ kind: "component", type: AppMessageErrorComponent, selector: "dsx-message-error", inputs: ["control", "form", "debugMode"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "ngmodule", type: InputMaskModule }, { kind: "directive", type: i1$7.InputMaskDirective, selector: "[pInputMask]", inputs: ["pInputMaskPT", "pInputMaskUnstyled", "pInputMask", "slotChar", "autoClear", "characterPattern", "keepBuffer"], outputs: ["onComplete", "onUnmaskedChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] });
|
|
9560
|
+
], ngImport: i0, template: "<!-- dsxdate-short.html -->\r\n<p-floatLabel variant=\"on\">\r\n <p-datepicker\r\n fluid\r\n appendTo=\"body\"\r\n size=\"small\"\r\n [formControl]=\"fechaControl\"\r\n [fluid]=\"true\"\r\n [showIcon]=\"showIcon()\"\r\n [showOnFocus]=\"showOnFocus()\"\r\n [showButtonBar]=\"showButtonBar()\"\r\n [dateFormat]=\"dateFormat()\"\r\n [placeholder]=\"placeholder()\"\r\n pInputMask=\"99/99/9999\"\r\n />\r\n <label>{{ label() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- \u2705 SIN CONDICI\u00D3N - IGUAL QUE EL ORIGINAL -->\r\n<dsx-message-error [control]=\"fechaControl\" />\r\n\r\n<dsx-message-help [control]=\"fechaControl\" />\r\n\r\n<!-- Debug info -->\r\n@if (debugEnabled() && isDevMode) {\r\n<div\r\n class=\"debug-info\"\r\n style=\"\r\n font-size: 12px;\r\n color: #666;\r\n margin-top: 4px;\r\n border-top: 1px dashed #ccc;\r\n padding-top: 4px;\r\n \"\r\n>\r\n <small>\r\n <strong>Debug:</strong>\r\n Value: {{ fechaControl.value | json }} | Valid: {{ fechaControl.valid }} |\r\n Invalid: {{ fechaControl.invalid }} | Errors: {{ fechaControl.errors | json\r\n }} | Dirty: {{ fechaControl.dirty }} | Touched: {{ fechaControl.touched }} |\r\n Status: {{ fechaControl.status }}\r\n </small>\r\n</div>\r\n}\r\n", styles: [""], dependencies: [{ kind: "component", type: AppMessageErrorComponent, selector: "dsx-message-error", inputs: ["control", "form", "debugMode"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "ngmodule", type: InputMaskModule }, { kind: "directive", type: i1$7.InputMaskDirective, selector: "[pInputMask]", inputs: ["pInputMaskPT", "pInputMaskUnstyled", "pInputMask", "slotChar", "autoClear", "characterPattern", "keepBuffer"], outputs: ["onComplete", "onUnmaskedChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: AppMessageHelpComponent, selector: "dsx-message-help", inputs: ["control", "currentIdControl", "helperFunction", "dataSource", "key", "umbral", "debugMode", "idFieldName", "maxSugerencias"] }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] });
|
|
9128
9561
|
}
|
|
9129
9562
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxdateShort, decorators: [{
|
|
9130
9563
|
type: Component,
|
|
@@ -9136,13 +9569,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
9136
9569
|
InputMaskModule,
|
|
9137
9570
|
JsonPipe,
|
|
9138
9571
|
ReactiveFormsModule,
|
|
9572
|
+
AppMessageHelpComponent,
|
|
9139
9573
|
], providers: [
|
|
9140
9574
|
{
|
|
9141
9575
|
provide: NG_VALUE_ACCESSOR,
|
|
9142
9576
|
useExisting: forwardRef(() => DsxdateShort),
|
|
9143
9577
|
multi: true,
|
|
9144
9578
|
},
|
|
9145
|
-
], template: "<!-- dsxdate-short.html -->\r\n<p-floatLabel variant=\"on\">\r\n <p-datepicker\r\n fluid\r\n appendTo=\"body\"\r\n [formControl]=\"fechaControl\"\r\n [fluid]=\"true\"\r\n [showIcon]=\"showIcon()\"\r\n [showOnFocus]=\"showOnFocus()\"\r\n [showButtonBar]=\"showButtonBar()\"\r\n [dateFormat]=\"dateFormat()\"\r\n [placeholder]=\"placeholder()\"\r\n pInputMask=\"99/99/9999\"\r\n />\r\n <label>{{ label() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- \u2705 SIN CONDICI\u00D3N - IGUAL QUE EL ORIGINAL -->\r\n<dsx-message-error [control]=\"fechaControl\" />\r\n\r\n<!-- Debug info -->\r\n@if (debugEnabled() && isDevMode) {\r\n<div\r\n class=\"debug-info\"\r\n style=\"\r\n font-size: 12px;\r\n color: #666;\r\n margin-top: 4px;\r\n border-top: 1px dashed #ccc;\r\n padding-top: 4px;\r\n \"\r\n>\r\n <small>\r\n <strong>Debug:</strong>\r\n Value: {{ fechaControl.value | json }} | Valid: {{ fechaControl.valid }} |\r\n Invalid: {{ fechaControl.invalid }} | Errors: {{ fechaControl.errors | json\r\n }} | Dirty: {{ fechaControl.dirty }} | Touched: {{ fechaControl.touched }} |\r\n Status: {{ fechaControl.status }}\r\n </small>\r\n</div>\r\n}\r\n" }]
|
|
9579
|
+
], template: "<!-- dsxdate-short.html -->\r\n<p-floatLabel variant=\"on\">\r\n <p-datepicker\r\n fluid\r\n appendTo=\"body\"\r\n size=\"small\"\r\n [formControl]=\"fechaControl\"\r\n [fluid]=\"true\"\r\n [showIcon]=\"showIcon()\"\r\n [showOnFocus]=\"showOnFocus()\"\r\n [showButtonBar]=\"showButtonBar()\"\r\n [dateFormat]=\"dateFormat()\"\r\n [placeholder]=\"placeholder()\"\r\n pInputMask=\"99/99/9999\"\r\n />\r\n <label>{{ label() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- \u2705 SIN CONDICI\u00D3N - IGUAL QUE EL ORIGINAL -->\r\n<dsx-message-error [control]=\"fechaControl\" />\r\n\r\n<dsx-message-help [control]=\"fechaControl\" />\r\n\r\n<!-- Debug info -->\r\n@if (debugEnabled() && isDevMode) {\r\n<div\r\n class=\"debug-info\"\r\n style=\"\r\n font-size: 12px;\r\n color: #666;\r\n margin-top: 4px;\r\n border-top: 1px dashed #ccc;\r\n padding-top: 4px;\r\n \"\r\n>\r\n <small>\r\n <strong>Debug:</strong>\r\n Value: {{ fechaControl.value | json }} | Valid: {{ fechaControl.valid }} |\r\n Invalid: {{ fechaControl.invalid }} | Errors: {{ fechaControl.errors | json\r\n }} | Dirty: {{ fechaControl.dirty }} | Touched: {{ fechaControl.touched }} |\r\n Status: {{ fechaControl.status }}\r\n </small>\r\n</div>\r\n}\r\n" }]
|
|
9146
9580
|
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], showOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOnFocus", required: false }] }], showButtonBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtonBar", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }] } });
|
|
9147
9581
|
|
|
9148
9582
|
class DsxdateTime {
|
|
@@ -10488,7 +10922,7 @@ class DsxSelect {
|
|
|
10488
10922
|
useExisting: forwardRef(() => DsxSelect),
|
|
10489
10923
|
multi: true,
|
|
10490
10924
|
},
|
|
10491
|
-
], ngImport: i0, template: "<!-- dsx-select.html -->\r\n<p-floatLabel [variant]=\"variant()\">\r\n <p-select\r\n fluid\r\n appendTo=\"body\"\r\n [options]=\"dataList()\"\r\n [filter]=\"true\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [showClear]=\"showClear()\"\r\n [disabled]=\"disabled\"\r\n [optionLabel]=\"resolvedOptionLabel()\"\r\n [optionValue]=\"resolvedOptionValue()\"\r\n [virtualScroll]=\"virtualScroll()\"\r\n [virtualScrollItemSize]=\"virtualScrollItemSize()\"\r\n [(ngModel)]=\"value\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n (onFocus)=\"onFocus()\"\r\n (onHide)=\"onHide()\"\r\n >\r\n <!-- Item template -->\r\n <ng-template let-item #item>\r\n <div class=\"flex align-items-center gap-1\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"itemIcon()\" class=\"text-gray-500!\"></icon-dsx>\r\n } @if (showSecondaryField()) {\r\n <div class=\"flex flex-col\">\r\n <span class=\"font-semibold text-sky-800\">\r\n {{ item[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-xs text-gray-400\">\r\n {{ item[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ item[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Selected item template -->\r\n <ng-template #selectedItem let-selectedOptions>\r\n <div class=\"flex align-items-center gap-1\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"selectedIcon()\" class=\"text-green-600!\"></icon-dsx>\r\n } @if (showSecondaryField() && selectedOptions) {\r\n <div class=\"flex gap-x-2\">\r\n <span class=\"font-semibold text-sky-700\">\r\n {{ selectedOptions[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-gray-400\">\r\n {{ selectedOptions[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ selectedOptions?.[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n </p-select>\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- Mensaje de error condicional -->\r\n@if (showError() && errorControl()) {\r\n<dsx-message-error [control]=\"errorControl()\" />\r\n}\r\n", styles: ["icon-dsx{font-size:1.5em}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "component", type: IconDsxComponent, selector: "icon-dsx", inputs: ["name", "style", "debug"] }, { kind: "component", type: AppMessageErrorComponent, selector: "dsx-message-error", inputs: ["control", "form", "debugMode"] }] });
|
|
10925
|
+
], ngImport: i0, template: "<!-- dsx-select.html -->\r\n<p-floatLabel [variant]=\"variant()\">\r\n <p-select\r\n fluid\r\n appendTo=\"body\"\r\n size=\"small\"\r\n [options]=\"dataList()\"\r\n [filter]=\"true\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [showClear]=\"showClear()\"\r\n [disabled]=\"disabled\"\r\n [optionLabel]=\"resolvedOptionLabel()\"\r\n [optionValue]=\"resolvedOptionValue()\"\r\n [virtualScroll]=\"virtualScroll()\"\r\n [virtualScrollItemSize]=\"virtualScrollItemSize()\"\r\n [(ngModel)]=\"value\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n (onFocus)=\"onFocus()\"\r\n (onHide)=\"onHide()\"\r\n >\r\n <!-- Item template -->\r\n <ng-template let-item #item>\r\n <div class=\"flex align-items-center gap-1\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"itemIcon()\" class=\"text-gray-500!\"></icon-dsx>\r\n } @if (showSecondaryField()) {\r\n <div class=\"flex flex-col\">\r\n <span class=\"font-semibold text-sky-800\">\r\n {{ item[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-xs text-gray-400\">\r\n {{ item[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ item[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Selected item template -->\r\n <ng-template #selectedItem let-selectedOptions>\r\n <div class=\"flex align-items-center gap-1\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"selectedIcon()\" class=\"text-green-600!\"></icon-dsx>\r\n } @if (showSecondaryField() && selectedOptions) {\r\n <div class=\"flex gap-x-2\">\r\n <span class=\"font-semibold text-sky-700\">\r\n {{ selectedOptions[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-gray-400\">\r\n {{ selectedOptions[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ selectedOptions?.[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n </p-select>\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- Mensaje de error condicional -->\r\n@if (showError() && errorControl()) {\r\n<dsx-message-error [control]=\"errorControl()\" />\r\n}\r\n", styles: ["icon-dsx{font-size:1.5em}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "component", type: IconDsxComponent, selector: "icon-dsx", inputs: ["name", "style", "debug"] }, { kind: "component", type: AppMessageErrorComponent, selector: "dsx-message-error", inputs: ["control", "form", "debugMode"] }] });
|
|
10492
10926
|
}
|
|
10493
10927
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxSelect, decorators: [{
|
|
10494
10928
|
type: Component,
|
|
@@ -10504,7 +10938,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10504
10938
|
useExisting: forwardRef(() => DsxSelect),
|
|
10505
10939
|
multi: true,
|
|
10506
10940
|
},
|
|
10507
|
-
], template: "<!-- dsx-select.html -->\r\n<p-floatLabel [variant]=\"variant()\">\r\n <p-select\r\n fluid\r\n appendTo=\"body\"\r\n [options]=\"dataList()\"\r\n [filter]=\"true\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [showClear]=\"showClear()\"\r\n [disabled]=\"disabled\"\r\n [optionLabel]=\"resolvedOptionLabel()\"\r\n [optionValue]=\"resolvedOptionValue()\"\r\n [virtualScroll]=\"virtualScroll()\"\r\n [virtualScrollItemSize]=\"virtualScrollItemSize()\"\r\n [(ngModel)]=\"value\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n (onFocus)=\"onFocus()\"\r\n (onHide)=\"onHide()\"\r\n >\r\n <!-- Item template -->\r\n <ng-template let-item #item>\r\n <div class=\"flex align-items-center gap-1\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"itemIcon()\" class=\"text-gray-500!\"></icon-dsx>\r\n } @if (showSecondaryField()) {\r\n <div class=\"flex flex-col\">\r\n <span class=\"font-semibold text-sky-800\">\r\n {{ item[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-xs text-gray-400\">\r\n {{ item[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ item[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Selected item template -->\r\n <ng-template #selectedItem let-selectedOptions>\r\n <div class=\"flex align-items-center gap-1\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"selectedIcon()\" class=\"text-green-600!\"></icon-dsx>\r\n } @if (showSecondaryField() && selectedOptions) {\r\n <div class=\"flex gap-x-2\">\r\n <span class=\"font-semibold text-sky-700\">\r\n {{ selectedOptions[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-gray-400\">\r\n {{ selectedOptions[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ selectedOptions?.[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n </p-select>\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- Mensaje de error condicional -->\r\n@if (showError() && errorControl()) {\r\n<dsx-message-error [control]=\"errorControl()\" />\r\n}\r\n", styles: ["icon-dsx{font-size:1.5em}\n"] }]
|
|
10941
|
+
], template: "<!-- dsx-select.html -->\r\n<p-floatLabel [variant]=\"variant()\">\r\n <p-select\r\n fluid\r\n appendTo=\"body\"\r\n size=\"small\"\r\n [options]=\"dataList()\"\r\n [filter]=\"true\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [showClear]=\"showClear()\"\r\n [disabled]=\"disabled\"\r\n [optionLabel]=\"resolvedOptionLabel()\"\r\n [optionValue]=\"resolvedOptionValue()\"\r\n [virtualScroll]=\"virtualScroll()\"\r\n [virtualScrollItemSize]=\"virtualScrollItemSize()\"\r\n [(ngModel)]=\"value\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n (onFocus)=\"onFocus()\"\r\n (onHide)=\"onHide()\"\r\n >\r\n <!-- Item template -->\r\n <ng-template let-item #item>\r\n <div class=\"flex align-items-center gap-1\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"itemIcon()\" class=\"text-gray-500!\"></icon-dsx>\r\n } @if (showSecondaryField()) {\r\n <div class=\"flex flex-col\">\r\n <span class=\"font-semibold text-sky-800\">\r\n {{ item[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-xs text-gray-400\">\r\n {{ item[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ item[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Selected item template -->\r\n <ng-template #selectedItem let-selectedOptions>\r\n <div class=\"flex align-items-center gap-1\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"selectedIcon()\" class=\"text-green-600!\"></icon-dsx>\r\n } @if (showSecondaryField() && selectedOptions) {\r\n <div class=\"flex gap-x-2\">\r\n <span class=\"font-semibold text-sky-700\">\r\n {{ selectedOptions[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-gray-400\">\r\n {{ selectedOptions[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ selectedOptions?.[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n </p-select>\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- Mensaje de error condicional -->\r\n@if (showError() && errorControl()) {\r\n<dsx-message-error [control]=\"errorControl()\" />\r\n}\r\n", styles: ["icon-dsx{font-size:1.5em}\n"] }]
|
|
10508
10942
|
}], ctorParameters: () => [], propDecorators: { dataList: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataList", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], secondaryField: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryField", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], useIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "useIcon", required: false }] }], itemIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemIcon", required: false }] }], selectedIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIcon", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }], showError: [{ type: i0.Input, args: [{ isSignal: true, alias: "showError", required: false }] }], selectedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValue", required: false }] }, { type: i0.Output, args: ["selectedValueChange"] }] } });
|
|
10509
10943
|
|
|
10510
10944
|
/**
|
|
@@ -12672,9 +13106,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12672
13106
|
// form-preview.service.ts
|
|
12673
13107
|
class FormPreviewService {
|
|
12674
13108
|
environment;
|
|
13109
|
+
isDev;
|
|
12675
13110
|
constructor() {
|
|
12676
|
-
// Inyectar el token en el constructor
|
|
12677
13111
|
this.environment = inject(ENVIRONMENT);
|
|
13112
|
+
this.isDev = !this.environment.production;
|
|
12678
13113
|
}
|
|
12679
13114
|
/**
|
|
12680
13115
|
* Construye el HTML para el preview de un objeto
|
|
@@ -12685,17 +13120,30 @@ class FormPreviewService {
|
|
|
12685
13120
|
*
|
|
12686
13121
|
* @example
|
|
12687
13122
|
* ```typescript
|
|
13123
|
+
* // Ejemplo básico
|
|
12688
13124
|
* const data = {
|
|
12689
|
-
*
|
|
12690
|
-
*
|
|
12691
|
-
* email: 'juan@email.com'
|
|
12692
|
-
* },
|
|
13125
|
+
* empleadoId: 2,
|
|
13126
|
+
* fechaIngreso: '2026-04-07',
|
|
12693
13127
|
* estado: 1
|
|
12694
13128
|
* };
|
|
12695
13129
|
*
|
|
13130
|
+
* const empleados = [
|
|
13131
|
+
* { id: 1, nombreCompleto: 'Juan Pérez' },
|
|
13132
|
+
* { id: 2, nombreCompleto: 'María García' }
|
|
13133
|
+
* ];
|
|
13134
|
+
*
|
|
12696
13135
|
* const fields = [
|
|
12697
|
-
* {
|
|
12698
|
-
*
|
|
13136
|
+
* {
|
|
13137
|
+
* key: 'empleadoId',
|
|
13138
|
+
* label: 'Empleado',
|
|
13139
|
+
* referenceMap: empleados,
|
|
13140
|
+
* referenceLabel: 'nombreCompleto'
|
|
13141
|
+
* },
|
|
13142
|
+
* {
|
|
13143
|
+
* key: 'fechaIngreso',
|
|
13144
|
+
* label: 'Fecha de Ingreso',
|
|
13145
|
+
* format: 'dateLong' // "07 de abril de 2026"
|
|
13146
|
+
* },
|
|
12699
13147
|
* {
|
|
12700
13148
|
* key: 'estado',
|
|
12701
13149
|
* label: 'Estado',
|
|
@@ -12703,30 +13151,33 @@ class FormPreviewService {
|
|
|
12703
13151
|
* }
|
|
12704
13152
|
* ];
|
|
12705
13153
|
*
|
|
12706
|
-
* const html = this.formPreviewService.buildObjectSummaryHtml(
|
|
12707
|
-
*
|
|
12708
|
-
*
|
|
12709
|
-
*
|
|
12710
|
-
*
|
|
12711
|
-
*
|
|
13154
|
+
* const html = this.formPreviewService.buildObjectSummaryHtml(
|
|
13155
|
+
* data,
|
|
13156
|
+
* fields,
|
|
13157
|
+
* {
|
|
13158
|
+
* title: 'Datos del Usuario',
|
|
13159
|
+
* showEmpty: false,
|
|
13160
|
+
* compact: true,
|
|
13161
|
+
* debug: true // Solo en desarrollo
|
|
13162
|
+
* }
|
|
13163
|
+
* );
|
|
12712
13164
|
* ```
|
|
12713
13165
|
*/
|
|
12714
13166
|
buildObjectSummaryHtml(data, fields, options) {
|
|
12715
13167
|
const debug = options?.debug ?? false;
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
if (debug && isDev) {
|
|
13168
|
+
// 🔍 Debug solo en desarrollo
|
|
13169
|
+
if (debug && this.isDev) {
|
|
12719
13170
|
this.debugInputData(data, fields, options);
|
|
12720
13171
|
}
|
|
12721
|
-
//
|
|
13172
|
+
// Validaciones
|
|
12722
13173
|
if (!data) {
|
|
12723
|
-
if (debug && isDev) {
|
|
13174
|
+
if (debug && this.isDev) {
|
|
12724
13175
|
console.error('❌ FormPreview: data es null o undefined');
|
|
12725
13176
|
}
|
|
12726
13177
|
return '';
|
|
12727
13178
|
}
|
|
12728
13179
|
if (!fields || fields.length === 0) {
|
|
12729
|
-
if (debug && isDev) {
|
|
13180
|
+
if (debug && this.isDev) {
|
|
12730
13181
|
console.error('❌ FormPreview: fields está vacío');
|
|
12731
13182
|
}
|
|
12732
13183
|
return '';
|
|
@@ -12742,11 +13193,13 @@ class FormPreviewService {
|
|
|
12742
13193
|
if (field.referenceMap && value !== undefined && value !== null) {
|
|
12743
13194
|
const originalValue = value;
|
|
12744
13195
|
value = this.resolveReferenceValue(value, field);
|
|
12745
|
-
//
|
|
12746
|
-
if (debug && isDev) {
|
|
13196
|
+
// 🔍 Debug solo en desarrollo
|
|
13197
|
+
if (debug && this.isDev) {
|
|
12747
13198
|
console.log(`🔍 Resolviendo referencia para "${field.key}":`, {
|
|
12748
13199
|
original: originalValue,
|
|
12749
13200
|
resuelto: value,
|
|
13201
|
+
referenciaId: field.referenceId || field.key || 'id',
|
|
13202
|
+
referenciaLabel: field.referenceLabel || 'nombre',
|
|
12750
13203
|
tipoMapa: Array.isArray(field.referenceMap)
|
|
12751
13204
|
? 'Array'
|
|
12752
13205
|
: field.referenceMap instanceof Map
|
|
@@ -12757,9 +13210,10 @@ class FormPreviewService {
|
|
|
12757
13210
|
});
|
|
12758
13211
|
}
|
|
12759
13212
|
}
|
|
13213
|
+
// Aplicar formato
|
|
12760
13214
|
const valueText = field.format
|
|
12761
|
-
? field.format
|
|
12762
|
-
: this.
|
|
13215
|
+
? this.formatValue(value, field.format)
|
|
13216
|
+
: this.formatDefault(value);
|
|
12763
13217
|
if (value === undefined) {
|
|
12764
13218
|
propiedadesNoEncontradas.push(field.key);
|
|
12765
13219
|
}
|
|
@@ -12770,8 +13224,8 @@ class FormPreviewService {
|
|
|
12770
13224
|
value: valueText || '—',
|
|
12771
13225
|
});
|
|
12772
13226
|
}
|
|
12773
|
-
//
|
|
12774
|
-
if (debug && isDev) {
|
|
13227
|
+
// 🔍 Debug solo en desarrollo
|
|
13228
|
+
if (debug && this.isDev) {
|
|
12775
13229
|
if (propiedadesNoEncontradas.length > 0) {
|
|
12776
13230
|
console.warn('⚠️ FormPreview: Propiedades no encontradas:', propiedadesNoEncontradas);
|
|
12777
13231
|
console.warn('📋 Propiedades disponibles en data:', Object.keys(data));
|
|
@@ -12783,19 +13237,29 @@ class FormPreviewService {
|
|
|
12783
13237
|
console.log('📋 Fields:', fields);
|
|
12784
13238
|
}
|
|
12785
13239
|
else {
|
|
12786
|
-
console.log('✅ FormPreview: HTML generado correctamente', {
|
|
13240
|
+
console.log('✅ FormPreview: HTML generado correctamente', {
|
|
13241
|
+
totalCeldas: cells.length,
|
|
13242
|
+
campos: cells.map((c) => c.label),
|
|
13243
|
+
});
|
|
12787
13244
|
}
|
|
12788
13245
|
}
|
|
12789
13246
|
if (!cells.length)
|
|
12790
13247
|
return '';
|
|
12791
13248
|
return this.generateHtml(title, cells, compact);
|
|
12792
13249
|
}
|
|
13250
|
+
/**
|
|
13251
|
+
* Resuelve el valor de referencia
|
|
13252
|
+
* Soporta: arrays, maps, objetos literales y funciones
|
|
13253
|
+
*/
|
|
12793
13254
|
resolveReferenceValue(value, field) {
|
|
12794
13255
|
if (Array.isArray(value)) {
|
|
12795
13256
|
return value.map((item) => this.resolveSingleReference(item, field));
|
|
12796
13257
|
}
|
|
12797
13258
|
return this.resolveSingleReference(value, field);
|
|
12798
13259
|
}
|
|
13260
|
+
/**
|
|
13261
|
+
* Resuelve un valor individual de referencia
|
|
13262
|
+
*/
|
|
12799
13263
|
resolveSingleReference(value, field) {
|
|
12800
13264
|
if (!value)
|
|
12801
13265
|
return value;
|
|
@@ -12812,8 +13276,31 @@ class FormPreviewService {
|
|
|
12812
13276
|
referencedItem = map.get(value);
|
|
12813
13277
|
}
|
|
12814
13278
|
else if (Array.isArray(map)) {
|
|
12815
|
-
|
|
12816
|
-
|
|
13279
|
+
// Si no se especifica referenceId, usar el key del campo
|
|
13280
|
+
const idKey = field.referenceId || field.key || 'id';
|
|
13281
|
+
const labelKey = field.referenceLabel || 'nombre';
|
|
13282
|
+
const found = map.find((item) => {
|
|
13283
|
+
if (item[idKey] !== undefined) {
|
|
13284
|
+
return item[idKey] === value;
|
|
13285
|
+
}
|
|
13286
|
+
if (item.id !== undefined) {
|
|
13287
|
+
return item.id === value;
|
|
13288
|
+
}
|
|
13289
|
+
return false;
|
|
13290
|
+
});
|
|
13291
|
+
if (found) {
|
|
13292
|
+
if (found[labelKey] !== undefined && found[labelKey] !== null) {
|
|
13293
|
+
return found[labelKey];
|
|
13294
|
+
}
|
|
13295
|
+
// Fallback: buscar otras propiedades comunes
|
|
13296
|
+
for (const prop of ['label', 'nombre', 'name', 'text', 'value']) {
|
|
13297
|
+
if (found[prop] !== undefined && found[prop] !== null) {
|
|
13298
|
+
return found[prop];
|
|
13299
|
+
}
|
|
13300
|
+
}
|
|
13301
|
+
return found;
|
|
13302
|
+
}
|
|
13303
|
+
return value;
|
|
12817
13304
|
}
|
|
12818
13305
|
else if (typeof map === 'object') {
|
|
12819
13306
|
referencedItem = map[String(value)];
|
|
@@ -12825,12 +13312,23 @@ class FormPreviewService {
|
|
|
12825
13312
|
referencedItem[labelProp] !== null) {
|
|
12826
13313
|
return referencedItem[labelProp];
|
|
12827
13314
|
}
|
|
13315
|
+
for (const prop of ['label', 'nombre', 'name', 'text', 'value']) {
|
|
13316
|
+
if (referencedItem[prop] !== undefined &&
|
|
13317
|
+
referencedItem[prop] !== null) {
|
|
13318
|
+
return referencedItem[prop];
|
|
13319
|
+
}
|
|
13320
|
+
}
|
|
12828
13321
|
return referencedItem;
|
|
12829
13322
|
}
|
|
12830
13323
|
return referencedItem;
|
|
12831
13324
|
}
|
|
12832
13325
|
return value;
|
|
12833
13326
|
}
|
|
13327
|
+
/**
|
|
13328
|
+
* Obtiene un valor anidado usando notación punto
|
|
13329
|
+
* @example
|
|
13330
|
+
* getNestedValue({ user: { name: 'Juan' } }, 'user.name') // 'Juan'
|
|
13331
|
+
*/
|
|
12834
13332
|
getNestedValue(obj, path) {
|
|
12835
13333
|
if (!obj || !path)
|
|
12836
13334
|
return undefined;
|
|
@@ -12843,7 +13341,29 @@ class FormPreviewService {
|
|
|
12843
13341
|
}
|
|
12844
13342
|
return result;
|
|
12845
13343
|
}
|
|
12846
|
-
|
|
13344
|
+
/**
|
|
13345
|
+
* Formatea un valor usando el formato especificado
|
|
13346
|
+
* @param value - Valor a formatear
|
|
13347
|
+
* @param format - Formato a aplicar (string predefinido o función personalizada)
|
|
13348
|
+
* @returns String formateado
|
|
13349
|
+
*/
|
|
13350
|
+
formatValue(value, format) {
|
|
13351
|
+
if (value === null || value === undefined)
|
|
13352
|
+
return '';
|
|
13353
|
+
// Si es función personalizada, ejecutarla
|
|
13354
|
+
if (typeof format === 'function') {
|
|
13355
|
+
return format(value);
|
|
13356
|
+
}
|
|
13357
|
+
// Si es string, verificar si es un formato de fecha
|
|
13358
|
+
if (typeof format === 'string') {
|
|
13359
|
+
return this.formatDate(value, format);
|
|
13360
|
+
}
|
|
13361
|
+
return this.formatDefault(value);
|
|
13362
|
+
}
|
|
13363
|
+
/**
|
|
13364
|
+
* Formato por defecto para cualquier valor
|
|
13365
|
+
*/
|
|
13366
|
+
formatDefault(value) {
|
|
12847
13367
|
if (value === null || value === undefined)
|
|
12848
13368
|
return '';
|
|
12849
13369
|
if (value instanceof Date)
|
|
@@ -12859,6 +13379,68 @@ class FormPreviewService {
|
|
|
12859
13379
|
}
|
|
12860
13380
|
return String(value);
|
|
12861
13381
|
}
|
|
13382
|
+
/**
|
|
13383
|
+
* 🗓️ FORMATOS DE FECHA DISPONIBLES
|
|
13384
|
+
*
|
|
13385
|
+
* Para agregar un nuevo formato:
|
|
13386
|
+
* 1. Agrega el tipo en DateFormat
|
|
13387
|
+
* 2. Agrega el case en el switch del método formatDate
|
|
13388
|
+
* 3. Define las opciones de Intl.DateTimeFormatOptions
|
|
13389
|
+
*
|
|
13390
|
+
* @example
|
|
13391
|
+
* // Agregar 'dateShort' para mostrar "07-abr-2026"
|
|
13392
|
+
* // 1. type DateFormat = 'date' | 'dateLong' | 'dateTime' | 'dateShort'
|
|
13393
|
+
* // 2. case 'dateShort':
|
|
13394
|
+
* // options.day = '2-digit';
|
|
13395
|
+
* // options.month = 'short';
|
|
13396
|
+
* // options.year = 'numeric';
|
|
13397
|
+
* // break;
|
|
13398
|
+
*/
|
|
13399
|
+
formatDate(value, format) {
|
|
13400
|
+
if (!value)
|
|
13401
|
+
return '';
|
|
13402
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
13403
|
+
if (isNaN(date.getTime())) {
|
|
13404
|
+
// Si no es una fecha válida, devolver el valor original
|
|
13405
|
+
return String(value);
|
|
13406
|
+
}
|
|
13407
|
+
const options = {};
|
|
13408
|
+
switch (format) {
|
|
13409
|
+
case 'date':
|
|
13410
|
+
// "07/04/2026"
|
|
13411
|
+
options.day = '2-digit';
|
|
13412
|
+
options.month = '2-digit';
|
|
13413
|
+
options.year = 'numeric';
|
|
13414
|
+
break;
|
|
13415
|
+
case 'dateLong':
|
|
13416
|
+
// "martes 07 de abril de 2026"
|
|
13417
|
+
options.weekday = 'long';
|
|
13418
|
+
options.day = '2-digit';
|
|
13419
|
+
options.month = 'long';
|
|
13420
|
+
options.year = 'numeric';
|
|
13421
|
+
break;
|
|
13422
|
+
case 'dateTime':
|
|
13423
|
+
// "07/04/2026 14:30"
|
|
13424
|
+
options.day = '2-digit';
|
|
13425
|
+
options.month = '2-digit';
|
|
13426
|
+
options.year = 'numeric';
|
|
13427
|
+
options.hour = '2-digit';
|
|
13428
|
+
options.minute = '2-digit';
|
|
13429
|
+
break;
|
|
13430
|
+
default:
|
|
13431
|
+
return this.formatDefault(value);
|
|
13432
|
+
}
|
|
13433
|
+
try {
|
|
13434
|
+
return date.toLocaleDateString('es-ES', options);
|
|
13435
|
+
}
|
|
13436
|
+
catch (error) {
|
|
13437
|
+
// Si hay error al formatear, devolver el valor original
|
|
13438
|
+
return String(value);
|
|
13439
|
+
}
|
|
13440
|
+
}
|
|
13441
|
+
/**
|
|
13442
|
+
* Formatea un valor individual (para objetos y arrays)
|
|
13443
|
+
*/
|
|
12862
13444
|
formatSingleValue(value) {
|
|
12863
13445
|
if (!value || typeof value !== 'object')
|
|
12864
13446
|
return String(value);
|
|
@@ -12890,6 +13472,9 @@ class FormPreviewService {
|
|
|
12890
13472
|
return '[Objeto]';
|
|
12891
13473
|
}
|
|
12892
13474
|
}
|
|
13475
|
+
/**
|
|
13476
|
+
* Genera el HTML del preview
|
|
13477
|
+
*/
|
|
12893
13478
|
generateHtml(title, cells, compact) {
|
|
12894
13479
|
if (compact) {
|
|
12895
13480
|
return `
|
|
@@ -12940,15 +13525,20 @@ class FormPreviewService {
|
|
|
12940
13525
|
</div>
|
|
12941
13526
|
`;
|
|
12942
13527
|
}
|
|
13528
|
+
/**
|
|
13529
|
+
* 🔍 Debug: Muestra información detallada para depuración
|
|
13530
|
+
* ⚠️ SOLO se ejecuta en entorno de desarrollo
|
|
13531
|
+
*/
|
|
12943
13532
|
debugInputData(data, fields, options) {
|
|
12944
|
-
|
|
12945
|
-
if (!isDev)
|
|
13533
|
+
// ⚠️ Seguridad: Si es producción, NO ejecutar nada
|
|
13534
|
+
if (!this.isDev)
|
|
12946
13535
|
return;
|
|
12947
13536
|
console.group('🔍 FormPreview Debug');
|
|
12948
13537
|
console.log('📊 Data:', data);
|
|
12949
13538
|
console.log('📋 Propiedades disponibles:', data ? Object.keys(data) : 'data es null');
|
|
12950
13539
|
console.log('🎯 Fields solicitados:', fields);
|
|
12951
13540
|
console.log('⚙️ Options:', options);
|
|
13541
|
+
console.log('🌍 Entorno:', this.environment.production ? 'Producción' : 'Desarrollo');
|
|
12952
13542
|
if (data) {
|
|
12953
13543
|
for (const field of fields) {
|
|
12954
13544
|
const value = this.getNestedValue(data, field.key);
|
|
@@ -12962,11 +13552,18 @@ class FormPreviewService {
|
|
|
12962
13552
|
}
|
|
12963
13553
|
else {
|
|
12964
13554
|
console.log(`✅ Campo "${field.key}" existe:`, value);
|
|
13555
|
+
// Mostrar información del formato si existe
|
|
13556
|
+
if (field.format) {
|
|
13557
|
+
console.log(` 📝 Formato: ${typeof field.format === 'function' ? 'Función personalizada' : field.format}`);
|
|
13558
|
+
}
|
|
12965
13559
|
}
|
|
12966
13560
|
}
|
|
12967
13561
|
}
|
|
12968
13562
|
console.groupEnd();
|
|
12969
13563
|
}
|
|
13564
|
+
/**
|
|
13565
|
+
* Encuentra propiedades similares para sugerencias en debug
|
|
13566
|
+
*/
|
|
12970
13567
|
findSimilarProperties(search, properties) {
|
|
12971
13568
|
const searchLower = search.toLowerCase();
|
|
12972
13569
|
return properties
|
|
@@ -12976,6 +13573,9 @@ class FormPreviewService {
|
|
|
12976
13573
|
})
|
|
12977
13574
|
.slice(0, 3);
|
|
12978
13575
|
}
|
|
13576
|
+
/**
|
|
13577
|
+
* Escapa caracteres HTML para evitar inyección
|
|
13578
|
+
*/
|
|
12979
13579
|
escapeHtml(str) {
|
|
12980
13580
|
if (!str)
|
|
12981
13581
|
return '';
|
|
@@ -13375,6 +13975,54 @@ function hasStorage(key) {
|
|
|
13375
13975
|
}
|
|
13376
13976
|
}
|
|
13377
13977
|
|
|
13978
|
+
/**
|
|
13979
|
+
* Calcula la fecha sumando días hábiles (Lunes a Sábado, Domingos no cuentan)
|
|
13980
|
+
* Los feriados en el rango no consumen días
|
|
13981
|
+
*
|
|
13982
|
+
* @param fechaInicio - Fecha desde donde empezar
|
|
13983
|
+
* @param cantidadDias - Días hábiles a sumar
|
|
13984
|
+
* @param feriados - Lista de feriados (opcional)
|
|
13985
|
+
* @returns Fecha calculada o null si fechaInicio es null
|
|
13986
|
+
*
|
|
13987
|
+
* @example
|
|
13988
|
+
* // Sin feriados
|
|
13989
|
+
* calcularFechaFin(new Date('2026-07-07'), 15) // 2026-07-25
|
|
13990
|
+
*
|
|
13991
|
+
* @example
|
|
13992
|
+
* // Con feriados
|
|
13993
|
+
* calcularFechaFin(
|
|
13994
|
+
* new Date('2026-07-07'),
|
|
13995
|
+
* 15,
|
|
13996
|
+
* [{ date: '2026-07-14' }, { date: '2026-07-21' }]
|
|
13997
|
+
* ) // 2026-07-27
|
|
13998
|
+
*/
|
|
13999
|
+
function dsxCalcularRangoFecha(fechaInicio, cantidadDias, feriados) {
|
|
14000
|
+
// Validación básica
|
|
14001
|
+
if (!fechaInicio)
|
|
14002
|
+
return null;
|
|
14003
|
+
if (cantidadDias === 0)
|
|
14004
|
+
return new Date(fechaInicio);
|
|
14005
|
+
// Crear Set de feriados con moment para comparación directa
|
|
14006
|
+
const feriadosSet = new Set(feriados?.map((f) => moment(f.dateHoliday).format('YYYY-MM-DD')));
|
|
14007
|
+
// Usar moment para la fecha
|
|
14008
|
+
const fecha = moment(fechaInicio).startOf('day');
|
|
14009
|
+
let dias = cantidadDias;
|
|
14010
|
+
while (dias > 0) {
|
|
14011
|
+
fecha.add(1, 'day');
|
|
14012
|
+
const diaSemana = fecha.day(); // 0=domingo
|
|
14013
|
+
const fechaStr = fecha.format('YYYY-MM-DD');
|
|
14014
|
+
// Días que NO consumen días (se saltan):
|
|
14015
|
+
// 1. Domingos
|
|
14016
|
+
// 2. Feriados
|
|
14017
|
+
if (diaSemana === 0 || feriadosSet.has(fechaStr)) {
|
|
14018
|
+
continue;
|
|
14019
|
+
}
|
|
14020
|
+
// Sábado = medio día, resto = día completo
|
|
14021
|
+
dias -= diaSemana === 6 ? 0.5 : 1;
|
|
14022
|
+
}
|
|
14023
|
+
return fecha.toDate();
|
|
14024
|
+
}
|
|
14025
|
+
|
|
13378
14026
|
function chainControlGroups(form, groups) {
|
|
13379
14027
|
groups.forEach((group) => {
|
|
13380
14028
|
chainControls(form, group);
|
|
@@ -14008,5 +14656,5 @@ function sorensenDiceValidator(dataSource, key, umbral = 0.7) {
|
|
|
14008
14656
|
* Generated bundle index. Do not edit.
|
|
14009
14657
|
*/
|
|
14010
14658
|
|
|
14011
|
-
export { ACTION_TYPES, AlertaService, AppMessageErrorComponent, AppMessageHelpComponent, ArrowNavigationDirective, AuthorizeService, AutoScrollHeightDirective, BaseCRUDService, CACHE_KEYS, CacheService, CssV2Component, DSX_PALETTE, DateIndicator, DocxPreviewComponent, DsxAddToolsModule, DsxAutocomplete, DsxButtonComponent, DsxEnableDisable, DsxInputCurrency, DsxMessagesService, DsxSelect, DsxStatusToggle, DsxdateShort, DsxdateTime, DteService, ENVIRONMENT, EndpointService, ErrorHandlerService, FileComponent, FormPreviewService, GTQFormatter, HeaderDsx, HelpersService, HttpHelpersService, INITIAL_PARAMETERS, IcoLabel, IconDsxComponent, JoinByPipe, JsonHighlightPipe, JsonValuesDebujComponent, JsonViewerComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, LogoDsxComponent, MasterDetailChangeService, NavbarDsxComponent, NetworkStatusComponent, OnlyRangoPatternDirective, ParameterValuesService, PdfPreviewComponent, PrimeNgModule, QrGenerator, ResultFileService, SWEET_ALERT_THEMES, ScreenInspector, SecurityService, SelectAllOnFocusDirective, SpinnerLoadingService, SweetAlert2DialogService, TablePreviewService, TemplateHighlight, TokenPurposeLogin, TruncatePipe, UtilityAddService, asyncExistsValidator, atLeastOneFieldRequiredValidator, chainControlGroups, createCurrencyFormatter, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, dateRangeValidatorFromTo, developmentEnvironment, getActionMessageConfig, getStorage, getZeroBasedRolIndex, guardTokenPurposeGuard, hasStorage, httpAuthorizeInterceptor, minimumAgeValidator, nitValidator, productionEnvironment, provideEnvironment, removeStorage, setStorage, setStorageObject, sorensenDiceValidator, templateStructureValidator, templateVariablesValidator, validateEnvironmentConfig };
|
|
14659
|
+
export { ACTION_TYPES, AlertaService, AppMessageErrorComponent, AppMessageHelpComponent, ArrowNavigationDirective, AuthorizeService, AutoScrollHeightDirective, BaseCRUDService, CACHE_KEYS, CacheService, CssV2Component, DSX_PALETTE, DateIndicator, DocxPreviewComponent, DsxAddToolsModule, DsxAutocomplete, DsxButtonComponent, DsxCalendarView, DsxEnableDisable, DsxInputCurrency, DsxMessagesService, DsxSelect, DsxStatusToggle, DsxdateShort, DsxdateTime, DteService, ENVIRONMENT, EndpointService, ErrorHandlerService, FileComponent, FormPreviewService, GTQFormatter, HeaderDsx, HelpersService, HttpHelpersService, INITIAL_PARAMETERS, IcoLabel, IconDsxComponent, JoinByPipe, JsonHighlightPipe, JsonValuesDebujComponent, JsonViewerComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, LogoDsxComponent, MasterDetailChangeService, NavbarDsxComponent, NetworkStatusComponent, OnlyRangoPatternDirective, ParameterValuesService, PdfPreviewComponent, PrimeNgModule, QrGenerator, ResultFileService, SWEET_ALERT_THEMES, ScreenInspector, SecurityService, SelectAllOnFocusDirective, SpinnerLoadingService, SweetAlert2DialogService, TablePreviewService, TemplateHighlight, TokenPurposeLogin, TruncatePipe, UtilityAddService, asyncExistsValidator, atLeastOneFieldRequiredValidator, chainControlGroups, createCurrencyFormatter, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, dateRangeValidatorFromTo, developmentEnvironment, dsxCalcularRangoFecha, getActionMessageConfig, getStorage, getZeroBasedRolIndex, guardTokenPurposeGuard, hasStorage, httpAuthorizeInterceptor, minimumAgeValidator, nitValidator, productionEnvironment, provideEnvironment, removeStorage, setStorage, setStorageObject, sorensenDiceValidator, templateStructureValidator, templateVariablesValidator, validateEnvironmentConfig };
|
|
14012
14660
|
//# sourceMappingURL=ngx-dsxlibrary.mjs.map
|