yw-charts-library 0.0.3 → 0.0.4
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.
- package/fesm2022/yw-charts-library.mjs +1706 -1656
- package/fesm2022/yw-charts-library.mjs.map +1 -1
- package/index.d.ts +3 -1
- package/package.json +1 -1
|
@@ -94,7 +94,8 @@ const YwDashboardWidgetTypes = [
|
|
|
94
94
|
{ code: "chart-bar", description: "Chart Bar" },
|
|
95
95
|
{ code: "chart-line", description: "Chart Bar" },
|
|
96
96
|
{ code: "chart-doughnut", description: "Chart Doughnut" },
|
|
97
|
-
{ code: "chart-gauge", description: "Chart Gauge" }
|
|
97
|
+
{ code: "chart-gauge", description: "Chart Gauge" },
|
|
98
|
+
{ code: "chart-bubble", description: "Chart Bubble" }
|
|
98
99
|
];
|
|
99
100
|
|
|
100
101
|
const YwDashboardWidgetFilterTypes = [
|
|
@@ -250,14 +251,14 @@ const resolveJoinedTableData = (allTablesData, configJoins) => {
|
|
|
250
251
|
return out;
|
|
251
252
|
};
|
|
252
253
|
let currentRows = baseData.map((r) => prefixRow(r, baseTable));
|
|
253
|
-
|
|
254
|
+
for (const rel of relations) {
|
|
254
255
|
const { leftTable, leftId, rightTable, rightId } = rel;
|
|
255
256
|
if (!allTablesData[rightTable]) {
|
|
256
257
|
throw new Error(`La tabla destino "${rightTable}" especificada en el join no existe en los datos.`);
|
|
257
258
|
}
|
|
258
259
|
const targetData = allTablesData[rightTable] || [];
|
|
259
260
|
if (targetData.length === 0) {
|
|
260
|
-
|
|
261
|
+
return [];
|
|
261
262
|
}
|
|
262
263
|
if (targetData[0][rightId] === undefined) {
|
|
263
264
|
throw new Error(`La columna "${rightId}" no existe en la tabla destino "${rightTable}".`);
|
|
@@ -270,18 +271,10 @@ const resolveJoinedTableData = (allTablesData, configJoins) => {
|
|
|
270
271
|
}
|
|
271
272
|
});
|
|
272
273
|
let matchCount = 0;
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
// if (foreignKeyVal === undefined) {
|
|
276
|
-
// const foundKey = Object.keys(row).find(
|
|
277
|
-
// (k) => k === leftId || k.endsWith(`.${leftId}`),
|
|
278
|
-
// );
|
|
279
|
-
// if (foundKey) foreignKeyVal = row[foundKey];
|
|
280
|
-
// }
|
|
281
|
-
// REVSISAR COMO ESTA FUNCIONADO EL PARCHE
|
|
274
|
+
const nextRows = [];
|
|
275
|
+
currentRows.forEach((row) => {
|
|
282
276
|
let foreignKeyVal = row[`${leftTable}.${leftId}`];
|
|
283
277
|
if (foreignKeyVal === undefined) {
|
|
284
|
-
// Si no está, aplicas tu respaldo anterior
|
|
285
278
|
const foundKey = Object.keys(row).find((k) => k === leftId || k.endsWith(`.${leftId}`));
|
|
286
279
|
if (foundKey)
|
|
287
280
|
foreignKeyVal = row[foundKey];
|
|
@@ -289,14 +282,14 @@ const resolveJoinedTableData = (allTablesData, configJoins) => {
|
|
|
289
282
|
if (foreignKeyVal !== undefined && targetMap.has(String(foreignKeyVal))) {
|
|
290
283
|
matchCount++;
|
|
291
284
|
const matchedRow = targetMap.get(String(foreignKeyVal));
|
|
292
|
-
|
|
285
|
+
nextRows.push({ ...row, ...matchedRow });
|
|
293
286
|
}
|
|
294
|
-
return row;
|
|
295
287
|
});
|
|
288
|
+
currentRows = nextRows;
|
|
296
289
|
if (matchCount === 0) {
|
|
297
|
-
|
|
290
|
+
return [];
|
|
298
291
|
}
|
|
299
|
-
}
|
|
292
|
+
}
|
|
300
293
|
return currentRows;
|
|
301
294
|
};
|
|
302
295
|
// ACCESO A PROPIEDADES ANIDADAS (SOPORTA NOTACIÓN DE PUNTOS Y TOLERANCIA DE PREFIJOS)
|
|
@@ -1716,13 +1709,17 @@ const parseDataPie = parseSyncFusionData$2;
|
|
|
1716
1709
|
const detectCategoryKey = (row) => {
|
|
1717
1710
|
if (!row)
|
|
1718
1711
|
return undefined;
|
|
1712
|
+
const isDateKey = (k) => {
|
|
1713
|
+
const lk = k.toLowerCase();
|
|
1714
|
+
return lk.includes('fecha') || lk.includes('date') || lk.includes('time') || lk.includes('timestamp');
|
|
1715
|
+
};
|
|
1719
1716
|
const candidates = ['x', 'name', 'label', 'category', 'categoria', 'sucursal', 'producto', 'key', 'title'];
|
|
1720
1717
|
for (const c of candidates) {
|
|
1721
|
-
if (row[c] !== undefined && row[c] !== null && typeof row[c] === 'string')
|
|
1718
|
+
if (row[c] !== undefined && row[c] !== null && typeof row[c] === 'string' && !isDateKey(c))
|
|
1722
1719
|
return c;
|
|
1723
1720
|
}
|
|
1724
1721
|
for (const k of Object.keys(row)) {
|
|
1725
|
-
if (typeof row[k] === 'string')
|
|
1722
|
+
if (typeof row[k] === 'string' && !isDateKey(k))
|
|
1726
1723
|
return k;
|
|
1727
1724
|
}
|
|
1728
1725
|
return undefined;
|
|
@@ -1821,7 +1818,7 @@ const parseForSyncfusion$1 = (rawData, config) => {
|
|
|
1821
1818
|
if (!row)
|
|
1822
1819
|
return;
|
|
1823
1820
|
let xVal = effectiveXKey ? getNestedValue(row, effectiveXKey) : undefined;
|
|
1824
|
-
if (xVal === undefined) {
|
|
1821
|
+
if (xVal === undefined && !xKey) {
|
|
1825
1822
|
const autoX = detectCategoryKey(row);
|
|
1826
1823
|
if (autoX)
|
|
1827
1824
|
xVal = row[autoX];
|
|
@@ -1974,10 +1971,23 @@ class PieChartSyncfusionComponent {
|
|
|
1974
1971
|
this.chartTitle = '';
|
|
1975
1972
|
this._lastWidth = 0;
|
|
1976
1973
|
this._lastHeight = 0;
|
|
1974
|
+
this._dataSnapshot = '';
|
|
1977
1975
|
}
|
|
1978
1976
|
ngOnInit() {
|
|
1979
1977
|
this.updateParsedData();
|
|
1980
1978
|
}
|
|
1979
|
+
ngDoCheck() {
|
|
1980
|
+
try {
|
|
1981
|
+
const snap = JSON.stringify(this.chartData);
|
|
1982
|
+
if (snap !== this._dataSnapshot) {
|
|
1983
|
+
this._dataSnapshot = snap;
|
|
1984
|
+
this.updateParsedData();
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
catch {
|
|
1988
|
+
// Ignorar si hay referencias circulares en los datos
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1981
1991
|
ngAfterViewInit() {
|
|
1982
1992
|
if (typeof ResizeObserver === 'undefined')
|
|
1983
1993
|
return;
|
|
@@ -2050,6 +2060,12 @@ class PieChartSyncfusionComponent {
|
|
|
2050
2060
|
this.centerLabelSettings = undefined;
|
|
2051
2061
|
this.chartTitle = this.config?.title || '';
|
|
2052
2062
|
}
|
|
2063
|
+
this.cdr.markForCheck();
|
|
2064
|
+
if (this.chartInstance) {
|
|
2065
|
+
setTimeout(() => {
|
|
2066
|
+
this.chartInstance?.refresh();
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2053
2069
|
}
|
|
2054
2070
|
onChartLoaded(args) {
|
|
2055
2071
|
if (this.centerLabel?.show && args?.accumulation?.element?.id) {
|
|
@@ -2532,8 +2548,12 @@ class GaugeChartSyncfusionComponent {
|
|
|
2532
2548
|
/** HTML con estilos inline para la annotation central del gauge */
|
|
2533
2549
|
get annotationHtml() {
|
|
2534
2550
|
const text = this.animatedLabelText || (this.gaugePoint?.text ?? '');
|
|
2551
|
+
return this.buildAnnotationHtml(text);
|
|
2552
|
+
}
|
|
2553
|
+
buildAnnotationHtml(text) {
|
|
2535
2554
|
const size = this.currentLabelSize || this.visualConfig?.labelSize || '24px';
|
|
2536
|
-
const
|
|
2555
|
+
const isBold = this.visualConfig?.labelBold || this.visualConfig?.labelWeight === 'bold' || this.visualConfig?.labelWeight === '700';
|
|
2556
|
+
const weight = isBold ? 'bold' : (this.visualConfig?.labelWeight || 'normal');
|
|
2537
2557
|
const color = this.visualConfig?.labelColor || '#1F2937';
|
|
2538
2558
|
return `<div style="font-size:${size};font-weight:${weight};color:${color};text-align:center;font-family:inherit;line-height:1.1;white-space:nowrap;">${text}</div>`;
|
|
2539
2559
|
}
|
|
@@ -2663,6 +2683,12 @@ class GaugeChartSyncfusionComponent {
|
|
|
2663
2683
|
else {
|
|
2664
2684
|
this.currentLabelSize = `${parsedSize}px`;
|
|
2665
2685
|
}
|
|
2686
|
+
if (this.gaugeInstance && this.visualConfig?.showLabel && !this._isAnimating) {
|
|
2687
|
+
try {
|
|
2688
|
+
this.gaugeInstance.setAnnotationValue(0, 0, this.annotationHtml);
|
|
2689
|
+
}
|
|
2690
|
+
catch { }
|
|
2691
|
+
}
|
|
2666
2692
|
this.cdr.markForCheck();
|
|
2667
2693
|
return;
|
|
2668
2694
|
}
|
|
@@ -2670,6 +2696,12 @@ class GaugeChartSyncfusionComponent {
|
|
|
2670
2696
|
// Proporción estándar ideal (~7.5% del ancho del contenedor, acotado entre 13px y 26px)
|
|
2671
2697
|
const base = Math.max(13, Math.min(26, Math.round(width * 0.075)));
|
|
2672
2698
|
this.currentLabelSize = `${base}px`;
|
|
2699
|
+
if (this.gaugeInstance && this.visualConfig?.showLabel && !this._isAnimating) {
|
|
2700
|
+
try {
|
|
2701
|
+
this.gaugeInstance.setAnnotationValue(0, 0, this.annotationHtml);
|
|
2702
|
+
}
|
|
2703
|
+
catch { }
|
|
2704
|
+
}
|
|
2673
2705
|
this.cdr.markForCheck();
|
|
2674
2706
|
}
|
|
2675
2707
|
/**
|
|
@@ -2759,7 +2791,7 @@ class GaugeChartSyncfusionComponent {
|
|
|
2759
2791
|
this.animatedLabelText = labelText;
|
|
2760
2792
|
if (this.gaugeInstance) {
|
|
2761
2793
|
try {
|
|
2762
|
-
this.gaugeInstance.setAnnotationValue(0, 0, labelText);
|
|
2794
|
+
this.gaugeInstance.setAnnotationValue(0, 0, this.buildAnnotationHtml(labelText));
|
|
2763
2795
|
}
|
|
2764
2796
|
catch {
|
|
2765
2797
|
// Ignorar si la anotación aún no se ha montado
|
|
@@ -2776,7 +2808,7 @@ class GaugeChartSyncfusionComponent {
|
|
|
2776
2808
|
this.animatedLabelText = finalLabel;
|
|
2777
2809
|
if (this.gaugeInstance) {
|
|
2778
2810
|
try {
|
|
2779
|
-
this.gaugeInstance.setAnnotationValue(0, 0, finalLabel);
|
|
2811
|
+
this.gaugeInstance.setAnnotationValue(0, 0, this.buildAnnotationHtml(finalLabel));
|
|
2780
2812
|
}
|
|
2781
2813
|
catch { }
|
|
2782
2814
|
}
|
|
@@ -2885,1822 +2917,1840 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
|
|
|
2885
2917
|
args: ['config']
|
|
2886
2918
|
}] } });
|
|
2887
2919
|
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
this.componentWidgetId = '';
|
|
2892
|
-
this.typeComponent = '';
|
|
2893
|
-
this.varShowConfigButtons = false;
|
|
2894
|
-
this.styleWidget = input(DEFAULT_WIDGET_STYLE, ...(ngDevMode ? [{ debugName: "styleWidget" }] : []));
|
|
2895
|
-
// Signal calculada que combina los valores recibidos con los valores por defecto
|
|
2896
|
-
this.instanceStyleWidget = computed(() => ({
|
|
2897
|
-
widgetBackgroundColor: this.styleWidget()?.widgetBackgroundColor ?? DEFAULT_WIDGET_STYLE.widgetBackgroundColor,
|
|
2898
|
-
widgetBorderColor: this.styleWidget()?.widgetBorderColor ?? DEFAULT_WIDGET_STYLE.widgetBorderColor
|
|
2899
|
-
}), ...(ngDevMode ? [{ debugName: "instanceStyleWidget" }] : []));
|
|
2900
|
-
this.configWidget = {
|
|
2901
|
-
widgetId: '',
|
|
2902
|
-
title: '',
|
|
2903
|
-
typeComponent: '',
|
|
2904
|
-
showConfigButtons: false,
|
|
2905
|
-
widgetStyle: DEFAULT_WIDGET_STYLE,
|
|
2906
|
-
layoutConfig: { id: '', w: 0, h: 0, content: undefined },
|
|
2907
|
-
controlConfig: {},
|
|
2908
|
-
controlTables: []
|
|
2909
|
-
};
|
|
2910
|
-
this.controlConfig = {};
|
|
2911
|
-
this.controlData = {};
|
|
2912
|
-
this.isLocked = model(false, ...(ngDevMode ? [{ debugName: "isLocked" }] : []));
|
|
2913
|
-
this.isMaximized = signal(false, ...(ngDevMode ? [{ debugName: "isMaximized" }] : []));
|
|
2914
|
-
this.eventDeleteRequest = output();
|
|
2915
|
-
this.eventLockToggleRequest = output();
|
|
2916
|
-
this.eventMaximizeToggleRequest = output();
|
|
2917
|
-
this.eventShowConfigFormRequest = output();
|
|
2920
|
+
const parseSyncFusionData = (allTablesData, configData_) => {
|
|
2921
|
+
if (!allTablesData || !configData_) {
|
|
2922
|
+
return { series: [], labelData: {} };
|
|
2918
2923
|
}
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
controlData: this.controlData
|
|
2925
|
-
};
|
|
2926
|
-
console.log('DATOS INICIALES INIT:');
|
|
2927
|
-
console.log(this.dataWidget);
|
|
2924
|
+
console.log("bubble data:--", allTablesData, configData_);
|
|
2925
|
+
// SI LO MANDAN COMO UN ARREGLO PLANO, LO ENVOLVEMOS AUTOMÁTICAMENTE
|
|
2926
|
+
if (Array.isArray(allTablesData)) {
|
|
2927
|
+
const defaultTableName = configData_?.configData?.table || 'default';
|
|
2928
|
+
allTablesData = { [defaultTableName]: allTablesData };
|
|
2928
2929
|
}
|
|
2929
|
-
|
|
2930
|
-
|
|
2930
|
+
const { ruleColorPoint, configData, xLabelText, yLabelText, title, chartoColoredLine, opacity, emptyPointSettings } = configData_;
|
|
2931
|
+
console.log("configData_:.::", configData_);
|
|
2932
|
+
const cfg = configData || {};
|
|
2933
|
+
const { xAxis, yAxis, joins, configJoins, table, serie, tooltip, legends } = cfg;
|
|
2934
|
+
let series = [];
|
|
2935
|
+
// Función auxiliar robusta para obtener propiedades (soporta notación con puntos de los joins)
|
|
2936
|
+
// const getNestedValue = (obj: any, path: string) => {
|
|
2937
|
+
// if (!obj || !path) return undefined;
|
|
2938
|
+
// if (obj[path] !== undefined) return obj[path];
|
|
2939
|
+
// return path.split('.').reduce((acc, part) => (acc && acc[part] !== undefined ? acc[part] : undefined), obj);
|
|
2940
|
+
// };
|
|
2941
|
+
const sortByXAxis = (data) => {
|
|
2942
|
+
if (!xAxis)
|
|
2943
|
+
return data;
|
|
2944
|
+
return [...data].sort((a, b) => {
|
|
2945
|
+
const aValue = getNestedValue(a, xAxis);
|
|
2946
|
+
const bValue = getNestedValue(b, xAxis);
|
|
2947
|
+
if (aValue == null)
|
|
2948
|
+
return 1;
|
|
2949
|
+
if (bValue == null)
|
|
2950
|
+
return -1;
|
|
2951
|
+
return String(aValue).localeCompare(String(bValue), undefined, { numeric: true, sensitivity: 'base' });
|
|
2952
|
+
});
|
|
2953
|
+
};
|
|
2954
|
+
if (joins === true) {
|
|
2955
|
+
if (!configJoins) {
|
|
2956
|
+
series = [];
|
|
2957
|
+
}
|
|
2958
|
+
else {
|
|
2959
|
+
const unifiedTable = resolveJoinedTableData(allTablesData, configJoins);
|
|
2960
|
+
console.log('unifiedTable bubble', unifiedTable);
|
|
2961
|
+
if (unifiedTable && unifiedTable.length > 0) {
|
|
2962
|
+
// const validRawData = unifiedTable.filter(
|
|
2963
|
+
// (item: any) =>
|
|
2964
|
+
// item &&
|
|
2965
|
+
// xAxis &&
|
|
2966
|
+
// getNestedValue(item, xAxis) !== undefined &&
|
|
2967
|
+
// getNestedValue(item, xAxis) !== null,
|
|
2968
|
+
// );
|
|
2969
|
+
const validRawData = unifiedTable.filter((item) => item &&
|
|
2970
|
+
xAxis &&
|
|
2971
|
+
getNestedValue(item, xAxis) !== undefined &&
|
|
2972
|
+
getNestedValue(item, xAxis) !== null);
|
|
2973
|
+
const orderedRawData = sortByXAxis(validRawData);
|
|
2974
|
+
if (orderedRawData.length > 0) {
|
|
2975
|
+
if (serie) {
|
|
2976
|
+
// 2. Agrupamos los datos por el valor de la serie (ej. sucursal o vendedor)
|
|
2977
|
+
const groupedBySerie = orderedRawData.reduce((acc, item) => {
|
|
2978
|
+
const serieVal = getNestedValue(item, serie);
|
|
2979
|
+
const serieKey = serieVal !== undefined && serieVal !== null
|
|
2980
|
+
? String(serieVal)
|
|
2981
|
+
: 'Desconocido';
|
|
2982
|
+
if (!acc[serieKey]) {
|
|
2983
|
+
acc[serieKey] = [];
|
|
2984
|
+
}
|
|
2985
|
+
acc[serieKey].push(item);
|
|
2986
|
+
return acc;
|
|
2987
|
+
}, {});
|
|
2988
|
+
series = Object.entries(groupedBySerie).map(([serieName, groupItems]) => {
|
|
2989
|
+
const orderedGroupItems = [...groupItems].sort((a, b) => {
|
|
2990
|
+
const aValue = getNestedValue(a, xAxis);
|
|
2991
|
+
const bValue = getNestedValue(b, xAxis);
|
|
2992
|
+
return String(aValue).localeCompare(String(bValue), undefined, {
|
|
2993
|
+
numeric: true,
|
|
2994
|
+
sensitivity: 'base'
|
|
2995
|
+
});
|
|
2996
|
+
});
|
|
2997
|
+
console.log("SERIES NAME:", orderedGroupItems);
|
|
2998
|
+
const dataSource = orderedGroupItems.map((item) => {
|
|
2999
|
+
const rawVal = getNestedValue(item, yAxis);
|
|
3000
|
+
const valorFinal = rawVal !== undefined
|
|
3001
|
+
? typeof rawVal === 'number'
|
|
3002
|
+
? rawVal
|
|
3003
|
+
: Number(rawVal) || 0
|
|
3004
|
+
: 0;
|
|
3005
|
+
const sizeFinal = Math.abs(valorFinal) !== 0 ? Math.abs(valorFinal) * 0.05 : 0;
|
|
3006
|
+
return {
|
|
3007
|
+
x: String(getNestedValue(item, xAxis)),
|
|
3008
|
+
y: valorFinal,
|
|
3009
|
+
size: sizeFinal,
|
|
3010
|
+
name: String(getNestedValue(item, xAxis)),
|
|
3011
|
+
// ...(chartoColoredLine
|
|
3012
|
+
// ? { color: getRandomProfessionalHex() }
|
|
3013
|
+
// : {})
|
|
3014
|
+
};
|
|
3015
|
+
});
|
|
3016
|
+
return {
|
|
3017
|
+
name: serieName === 'default' ? 'Serie 1' : serieName,
|
|
3018
|
+
dataSource: aggregateByX(dataSource),
|
|
3019
|
+
opacity: opacity,
|
|
3020
|
+
emptyPointSettings: emptyPointSettings,
|
|
3021
|
+
// dashArray: dashArray !== undefined ? dashArray : undefined,
|
|
3022
|
+
// width: width !== undefined ? width : undefined,
|
|
3023
|
+
// widthLine: widthLine !== undefined ? widthLine : undefined,
|
|
3024
|
+
};
|
|
3025
|
+
});
|
|
3026
|
+
}
|
|
3027
|
+
else {
|
|
3028
|
+
const dataSource = orderedRawData.map((item) => {
|
|
3029
|
+
let valorFinal = 0;
|
|
3030
|
+
let sizeFinal = 0;
|
|
3031
|
+
// const shouldColorLine = chartoColoredLine;
|
|
3032
|
+
const rawVal = getNestedValue(item, yAxis);
|
|
3033
|
+
// const rawSize = getNestedValue(item, size); // <--- Extraer el valor real
|
|
3034
|
+
if (rawVal !== undefined) {
|
|
3035
|
+
valorFinal = typeof rawVal === 'number' ? rawVal : Number(rawVal) || 0;
|
|
3036
|
+
}
|
|
3037
|
+
// if (rawSize !== undefined) {
|
|
3038
|
+
sizeFinal = Math.abs(valorFinal) !== 0 ? Math.abs(valorFinal) * 0.05 : 0;
|
|
3039
|
+
// }
|
|
3040
|
+
return {
|
|
3041
|
+
x: String(getNestedValue(item, xAxis)),
|
|
3042
|
+
y: valorFinal,
|
|
3043
|
+
size: sizeFinal, // <--- Valor numérico extraído
|
|
3044
|
+
name: String(getNestedValue(item, xAxis)),
|
|
3045
|
+
// ...(shouldColorLine ? { color: getRandomProfessionalHex() } : {})
|
|
3046
|
+
};
|
|
3047
|
+
});
|
|
3048
|
+
series = [
|
|
3049
|
+
{
|
|
3050
|
+
name: xAxis.split(".")[0] && xAxis !== 'default' ? xAxis.split(".")[0] : 'Serie Join',
|
|
3051
|
+
dataSource: aggregateByX(dataSource),
|
|
3052
|
+
opacity: opacity,
|
|
3053
|
+
emptyPointSettings: emptyPointSettings,
|
|
3054
|
+
// dashArray: dashArray !== undefined ? dashArray : undefined,
|
|
3055
|
+
// width: width !== undefined ? width : undefined,
|
|
3056
|
+
// widthLine: widthLine !== undefined ? widthLine : undefined,
|
|
3057
|
+
}
|
|
3058
|
+
];
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
2931
3063
|
}
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
;
|
|
3064
|
+
else {
|
|
3065
|
+
let normalizedTables = [];
|
|
3066
|
+
if (Array.isArray(table)) {
|
|
3067
|
+
normalizedTables = table.filter((t) => typeof t === 'string' && t.trim() !== '');
|
|
2937
3068
|
}
|
|
2938
|
-
if (
|
|
2939
|
-
|
|
3069
|
+
else if (typeof table === 'string' && table.trim() !== '') {
|
|
3070
|
+
normalizedTables = [table];
|
|
2940
3071
|
}
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
this.dataWidget = { idComponent: this.componentWidgetId,
|
|
2944
|
-
controlConfig: this.controlConfig,
|
|
2945
|
-
controlData: this.controlData
|
|
2946
|
-
};
|
|
3072
|
+
else {
|
|
3073
|
+
normalizedTables = Object.keys(allTablesData);
|
|
2947
3074
|
}
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwDashboardWidgetComponent, isStandalone: true, selector: "yw-dashboard-widget", inputs: { styleWidget: { classPropertyName: "styleWidget", publicName: "styleWidget", isSignal: true, isRequired: false, transformFunction: null }, configWidget: { classPropertyName: "configWidget", publicName: "configWidget", isSignal: false, isRequired: false, transformFunction: null }, controlConfig: { classPropertyName: "controlConfig", publicName: "controlConfig", isSignal: false, isRequired: false, transformFunction: null }, controlData: { classPropertyName: "controlData", publicName: "controlData", isSignal: false, isRequired: false, transformFunction: null }, isLocked: { classPropertyName: "isLocked", publicName: "isLocked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isLocked: "isLockedChange", eventDeleteRequest: "eventDeleteRequest", eventLockToggleRequest: "eventLockToggleRequest", eventMaximizeToggleRequest: "eventMaximizeToggleRequest", eventShowConfigFormRequest: "eventShowConfigFormRequest" }, host: { properties: { "style.--widget-bg": "instanceStyleWidget().widgetBackgroundColor", "style.--widget-border-color": "instanceStyleWidget().widgetBorderColor" } }, usesOnChanges: true, ngImport: i0, template: "\r\n<!-- <div class=\"widget-action-bar\"> \r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-action\" (click)=\"onLockClick()\">{{ isLocked() ? '\uD83D\uDD12' : '\uD83D\uDD13' }}</button>\r\n <button class=\"btn-action\" (click)=\"onMaximizeClick()\">{{ isMaximized() ? '\uD83D\uDDD7' : '\uD83D\uDDD6' }}</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\">\uD83D\uDDD1\uFE0F</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\">\u2699\uFE0F</button>\r\n</div> -->\r\n\r\n<div class=\"widget-action-bar\">\r\n <!-- Bot\u00F3n Bloquear / Desbloquear -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-action\" (click)=\"onLockClick()\" [title]=\"isLocked() ? 'Desbloquear' : 'Bloquear'\">\r\n <svg *ngIf=\"isLocked(); else unlockedIcon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path></svg>\r\n <ng-template #unlockedIcon>\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect><path d=\"M7 11V7a5 5 0 0 1 9.9-1\"></path></svg>\r\n </ng-template>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Maximizar / Restaurar -->\r\n <button class=\"btn-action\" (click)=\"onMaximizeClick()\" [title]=\"isMaximized() ? 'Restaurar' : 'Maximizar'\">\r\n <svg *ngIf=\"isMaximized(); else maxIcon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3\"></path></svg>\r\n <ng-template #maxIcon>\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7\"></path></svg>\r\n </ng-template>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Eliminar -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\" title=\"Eliminar\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"></polyline><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"></path></svg>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Configuraci\u00F3n -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\" title=\"Configurar\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"></circle><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z\"></path></svg>\r\n </button>\r\n</div>\r\n\r\n<div class=\"widget-content-wrapper\">\r\n @if ( typeComponent == 'dummy' ) {\r\n <ng-container *ngTemplateOutlet=\"testdummy; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'empty-visual' ) {\r\n <ng-container *ngTemplateOutlet=\"emptyvisual; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-bar' ) {\r\n <ng-container *ngTemplateOutlet=\"chartbar; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-line' ) {\r\n <ng-container *ngTemplateOutlet=\"chartline; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-doughnut' ) {\r\n <ng-container *ngTemplateOutlet=\"chartdoughnut; context: { control: dataWidget }\"></ng-container>\r\n } \r\n @if ( typeComponent == 'chart-gauge' ) {\r\n <ng-container *ngTemplateOutlet=\"chartgauge; context: { control: dataWidget }\"></ng-container>\r\n } \r\n \r\n \r\n</div>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- DUMMY TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #testdummy let-control = \"control\">\r\n <lib-test-chart [idComponent]=\"control.idComponent\" > \r\n </lib-test-chart>\r\n</ng-template>\r\n<!--------------------------------------------------------------->\r\n<!---------------------- EMPTY VISUAL TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #emptyvisual let-control = \"control\">\r\n <yw-empty-visual [idComponent]=\"control.idComponent\"\r\n [config]=\"control.controlConfig\" \r\n > \r\n </yw-empty-visual>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- BAR CHART TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartbar let-control = \"control\">\r\n <yw-bar-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-bar-chart>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE CHART TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartline let-control = \"control\">\r\n <yw-line-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-line-chart>\r\n</ng-template>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE DOUGHNUT TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartdoughnut let-control = \"control\">\r\n <yw-pie-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-pie-chart>\r\n</ng-template>\r\n\r\n \r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE GAUGE TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartgauge let-control = \"control\">\r\n <yw-gauge-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-gauge-chart>\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";:host{display:block;flex-direction:column;width:100%;overflow:hidden;box-sizing:border-box;background-color:var(--widget-bg, #ffffff);border:1px solid var(--widget-border-color, #007bff)}:host *,:host *:before,:host *:after{box-sizing:border-box}.widget-action-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%}.widget-content-wrapper{width:100%;flex-grow:1;height:0;display:flex;flex-direction:column}.widget-action-bar button,.widget-action-bar .btn-action,.widget-action-bar .btn-delete,.widget-action-bar .btn-config{background:transparent;border:1px solid #d9d9d9;border-radius:4px;cursor:pointer;width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;color:#595959;padding:0;transition:all .2s ease}.widget-action-bar button svg,.widget-action-bar .btn-action svg,.widget-action-bar .btn-delete svg,.widget-action-bar .btn-config svg{width:14px;height:14px}.widget-action-bar button:hover,.widget-action-bar .btn-action:hover,.widget-action-bar .btn-delete:hover,.widget-action-bar .btn-config:hover{background-color:#f5f5f5;color:#262626;border-color:#bfbfbf}.widget-action-bar button:active,.widget-action-bar .btn-action:active,.widget-action-bar .btn-delete:active,.widget-action-bar .btn-config:active{background-color:#e6e6e6}.widget-action-bar .btn-delete:hover{background-color:#fff1f0;color:#ff4d4f;border-color:#ffa39e}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TestChartComponent, selector: "lib-test-chart", inputs: ["idComponent"] }, { kind: "component", type: YwEmptyVisualComponent, selector: "yw-empty-visual", inputs: ["idComponent", "config"] }, { kind: "component", type: LineChartComponent, selector: "yw-line-chart", inputs: ["chartData", "config", "idComponent"] }, { kind: "component", type: BarChartComponent, selector: "yw-bar-chart", inputs: ["chartData", "config", "idComponent"] }, { kind: "component", type: PieChartComponent, selector: "yw-pie-chart", inputs: ["idComponent", "chartData", "config"] }, { kind: "component", type: GaugeChartComponent, selector: "yw-gauge-chart", inputs: ["idComponent", "chartData", "config"] }] }); }
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3075
|
+
series = normalizedTables
|
|
3076
|
+
.map((tableName) => {
|
|
3077
|
+
const rawData = (allTablesData && allTablesData[tableName]) ? allTablesData[tableName] : [];
|
|
3078
|
+
if (!rawData || rawData.length === 0)
|
|
3079
|
+
return null;
|
|
3080
|
+
const orderedRawData = rawData.filter((item) => item && xAxis && getNestedValue(item, xAxis) !== undefined && getNestedValue(item, xAxis) !== null);
|
|
3081
|
+
if (orderedRawData.length === 0)
|
|
3082
|
+
return null;
|
|
3083
|
+
const dataSource = orderedRawData.map((item) => {
|
|
3084
|
+
let valorFinal = 0;
|
|
3085
|
+
let sizeFinal = 0;
|
|
3086
|
+
const shouldColorLine = chartoColoredLine;
|
|
3087
|
+
const rawVal = getNestedValue(item, yAxis);
|
|
3088
|
+
// const rawSize = getNestedValue(item, size);
|
|
3089
|
+
if (rawVal !== undefined) {
|
|
3090
|
+
valorFinal = typeof rawVal === "number" ? rawVal : Number(rawVal) || 0;
|
|
3091
|
+
}
|
|
3092
|
+
// if (rawSize !== undefined) {
|
|
3093
|
+
sizeFinal = Math.abs(valorFinal) !== 0 ? Math.abs(valorFinal) * 0.05 : 0;
|
|
3094
|
+
// }
|
|
3095
|
+
return {
|
|
3096
|
+
x: String(getNestedValue(item, xAxis)),
|
|
3097
|
+
y: valorFinal,
|
|
3098
|
+
size: sizeFinal, // <--- Valor numérico extraído
|
|
3099
|
+
name: String(getNestedValue(item, xAxis))
|
|
3100
|
+
// ...(shouldColorLine ? { color: getRandomProfessionalHex() } : {})
|
|
3101
|
+
};
|
|
3102
|
+
});
|
|
3103
|
+
return {
|
|
3104
|
+
name: tableName === 'default' ? xAxis : tableName,
|
|
3105
|
+
dataSource: aggregateByX(dataSource),
|
|
3106
|
+
opacity: opacity,
|
|
3107
|
+
emptyPointSettings: emptyPointSettings,
|
|
3108
|
+
// dashArray: dashArray !== undefined ? dashArray : undefined,
|
|
3109
|
+
// width: width !== undefined ? width : undefined,
|
|
3110
|
+
// widthLine: widthLine !== undefined ? widthLine : undefined,
|
|
3111
|
+
};
|
|
3112
|
+
})
|
|
3113
|
+
.filter((item) => item !== null);
|
|
3114
|
+
}
|
|
3115
|
+
const labelData = {
|
|
3116
|
+
title: title || "",
|
|
3117
|
+
titleStyle: {
|
|
3118
|
+
size: '16px',
|
|
3119
|
+
fontWeight: '600',
|
|
3120
|
+
color: '#2b2b2b',
|
|
3121
|
+
fontFamily: 'Inherit',
|
|
3122
|
+
textAlignment: 'Center'
|
|
3123
|
+
},
|
|
3124
|
+
axisX: {
|
|
3125
|
+
valueType: 'Category',
|
|
3126
|
+
// title: typeof xLabelText === 'string' ? xLabelText : 'Categoría',
|
|
3127
|
+
// labelIntersectAction: 'Rotate90',
|
|
3128
|
+
// labelIntersectAction: 'Rotate45',
|
|
3129
|
+
majorGridLines: { width: 0 },
|
|
3130
|
+
majorTickLines: { width: 0 },
|
|
3131
|
+
lineStyle: { width: 0 },
|
|
3132
|
+
labelStyle: { color: '#64748B', size: '12px', fontFamily: 'Inherit' }
|
|
3133
|
+
},
|
|
3134
|
+
axisY: {
|
|
3135
|
+
title: typeof yLabelText === 'string' ? yLabelText : 'Valor',
|
|
3136
|
+
minimum: 0,
|
|
3137
|
+
edgeLabelPlacement: 'Shift',
|
|
3138
|
+
lineStyle: { width: 0 },
|
|
3139
|
+
majorTickLines: { width: 0 },
|
|
3140
|
+
minorTickLines: { width: 0 },
|
|
3141
|
+
majorGridLines: { width: 0.5, color: '#E2E8F0', dashArray: '4,4' },
|
|
3142
|
+
labelStyle: { color: '#94A3B8', size: '12px', fontFamily: 'Inherit' },
|
|
3143
|
+
titleStyle: { size: '12px', color: '#64748B', fontFamily: 'Inherit' }
|
|
3144
|
+
},
|
|
3145
|
+
marker: {
|
|
3146
|
+
visible: true,
|
|
3147
|
+
width: 8,
|
|
3148
|
+
height: 8,
|
|
3149
|
+
dataLabel: {
|
|
3150
|
+
visible: true,
|
|
3151
|
+
position: 'Top', // Centra el texto exactamente en el medio de la burbuja
|
|
3152
|
+
name: 'text', // Asegúrate de que apunte al campo de tu data que trae el nombre (ej: 'text' o 'name')
|
|
3153
|
+
font: {
|
|
3154
|
+
fontWeight: '600',
|
|
3155
|
+
color: '#334155', // Color del texto (oscuro para que contraste con el fondo claro) o '#FFFFFF' si prefieres blanco
|
|
3156
|
+
size: '12px',
|
|
3157
|
+
fontFamily: 'Inherit'
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
},
|
|
3161
|
+
palettes: ['#6366F1', '#22D3EE', '#F59E0B', '#10B981', '#F43F5E'],
|
|
3162
|
+
border: { width: 0 },
|
|
3163
|
+
chartArea: { border: { width: 0 }, margin: { bottom: 12 } },
|
|
3164
|
+
tooltip: {
|
|
3165
|
+
...(tooltip?.enable !== undefined ? { enable: tooltip.enable } : {}),
|
|
3166
|
+
...(tooltip?.format ? { format: tooltip.format } : {}),
|
|
3167
|
+
...(tooltip?.header ? { header: tooltip.header } : {}),
|
|
3168
|
+
...(tooltip?.shared !== undefined ? { shared: tooltip.shared } : {}),
|
|
3169
|
+
enableHighlight: true,
|
|
3170
|
+
},
|
|
3171
|
+
legendSettings: {
|
|
3172
|
+
visible: legends?.visible !== undefined ? legends.visible : undefined,
|
|
3173
|
+
position: legends?.position !== undefined ? legends.position : undefined
|
|
3174
|
+
},
|
|
3175
|
+
ruleColorPoint: ruleColorPoint !== undefined ? ruleColorPoint : undefined
|
|
3176
|
+
};
|
|
3177
|
+
return {
|
|
3178
|
+
series,
|
|
3179
|
+
labelData
|
|
3180
|
+
};
|
|
3181
|
+
};
|
|
2991
3182
|
|
|
2992
|
-
class
|
|
2993
|
-
constructor() {
|
|
2994
|
-
|
|
3183
|
+
class BubbleChartSyncfusionComponent {
|
|
3184
|
+
constructor(elRef, cdr) {
|
|
3185
|
+
this.elRef = elRef;
|
|
3186
|
+
this.cdr = cdr;
|
|
2995
3187
|
this.idComponent = '';
|
|
2996
|
-
this.
|
|
2997
|
-
this.
|
|
2998
|
-
this.
|
|
2999
|
-
this.max = input(...(ngDevMode ? [undefined, { debugName: "max" }] : []));
|
|
3000
|
-
this.step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : []));
|
|
3001
|
-
this.minCurrent = input(...(ngDevMode ? [undefined, { debugName: "minCurrent" }] : []));
|
|
3002
|
-
this.maxCurrent = input(...(ngDevMode ? [undefined, { debugName: "maxCurrent" }] : []));
|
|
3003
|
-
this.minNumber = 0;
|
|
3004
|
-
this.maxNumber = 1000;
|
|
3005
|
-
this.minDate = '2020-01-01';
|
|
3006
|
-
this.maxDate = '2022-12-31';
|
|
3007
|
-
// Evento de salida
|
|
3008
|
-
this.rangeChange = output();
|
|
3009
|
-
// Signals para las fechas seleccionadas
|
|
3010
|
-
this.startDate = signal('2020-01-01', ...(ngDevMode ? [{ debugName: "startDate" }] : []));
|
|
3011
|
-
this.endDate = signal('2022-09-22', ...(ngDevMode ? [{ debugName: "endDate" }] : []));
|
|
3012
|
-
// Signals para los numeros seleccionadas
|
|
3013
|
-
this.startVal = signal(0, ...(ngDevMode ? [{ debugName: "startVal" }] : []));
|
|
3014
|
-
this.endVal = signal(1000, ...(ngDevMode ? [{ debugName: "endVal" }] : []));
|
|
3015
|
-
this.minTimestamp = computed(() => new Date(this.minDate).getTime(), ...(ngDevMode ? [{ debugName: "minTimestamp" }] : []));
|
|
3016
|
-
this.maxTimestamp = computed(() => new Date(this.maxDate).getTime(), ...(ngDevMode ? [{ debugName: "maxTimestamp" }] : []));
|
|
3017
|
-
this.startTimestamp = computed(() => new Date(this.startDate()).getTime(), ...(ngDevMode ? [{ debugName: "startTimestamp" }] : []));
|
|
3018
|
-
this.endTimestamp = computed(() => new Date(this.endDate()).getTime(), ...(ngDevMode ? [{ debugName: "endTimestamp" }] : []));
|
|
3019
|
-
// Inicializar valores al arrancar
|
|
3020
|
-
effect(() => {
|
|
3021
|
-
if (this.dataType == 'date') {
|
|
3022
|
-
this.startDate.set(this.minCurrent() || this.minDate);
|
|
3023
|
-
this.endDate.set(this.maxCurrent() || this.maxDate);
|
|
3024
|
-
}
|
|
3025
|
-
if (this.dataType == 'number') {
|
|
3026
|
-
this.startVal.set(this.minCurrent() || this.minNumber);
|
|
3027
|
-
this.endVal.set(this.maxCurrent() || this.maxNumber);
|
|
3028
|
-
}
|
|
3029
|
-
}, { allowSignalWrites: true });
|
|
3030
|
-
// Notificar al padre cada vez que cambien los valores
|
|
3031
|
-
effect(() => {
|
|
3032
|
-
if (this.dataType == 'date') {
|
|
3033
|
-
this.rangeChange.emit({
|
|
3034
|
-
startDate: this.startDate(),
|
|
3035
|
-
endDate: this.endDate()
|
|
3036
|
-
});
|
|
3037
|
-
}
|
|
3038
|
-
if (this.dataType == 'number') {
|
|
3039
|
-
this.rangeChange.emit({
|
|
3040
|
-
minValue: this.startVal(),
|
|
3041
|
-
maxValue: this.endVal()
|
|
3042
|
-
});
|
|
3043
|
-
}
|
|
3044
|
-
});
|
|
3188
|
+
this.dataChartParse = [];
|
|
3189
|
+
this.currentLabelSize = '';
|
|
3190
|
+
this.currentWidgetWidth = 0; // Valor inicial por defecto
|
|
3045
3191
|
}
|
|
3046
3192
|
ngOnInit() {
|
|
3047
|
-
|
|
3048
|
-
this.minDate = this.min();
|
|
3049
|
-
this.maxDate = this.max();
|
|
3050
|
-
this.minTimestamp = computed(() => new Date(this.minDate).getTime(), ...(ngDevMode ? [{ debugName: "minTimestamp" }] : []));
|
|
3051
|
-
this.maxTimestamp = computed(() => new Date(this.maxDate).getTime(), ...(ngDevMode ? [{ debugName: "maxTimestamp" }] : []));
|
|
3052
|
-
this.startTimestamp = computed(() => new Date(this.startDate()).getTime(), ...(ngDevMode ? [{ debugName: "startTimestamp" }] : []));
|
|
3053
|
-
this.endTimestamp = computed(() => new Date(this.endDate()).getTime(), ...(ngDevMode ? [{ debugName: "endTimestamp" }] : []));
|
|
3054
|
-
}
|
|
3055
|
-
if (this.dataType == 'number') {
|
|
3056
|
-
this.minNumber = this.min();
|
|
3057
|
-
this.maxNumber = this.max();
|
|
3058
|
-
}
|
|
3059
|
-
}
|
|
3060
|
-
// Handlers para la entrada manual de fechas
|
|
3061
|
-
onStartDateInput(value) {
|
|
3062
|
-
if (value && value <= this.endDate()) {
|
|
3063
|
-
this.startDate.set(value);
|
|
3064
|
-
}
|
|
3193
|
+
this.updateParsedData();
|
|
3065
3194
|
}
|
|
3066
|
-
|
|
3067
|
-
if (
|
|
3068
|
-
this.
|
|
3195
|
+
ngOnChanges(changes) {
|
|
3196
|
+
if (changes['chartData'] || changes['config']) {
|
|
3197
|
+
this.updateParsedData();
|
|
3069
3198
|
}
|
|
3070
3199
|
}
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
const value = Number(event.target.value);
|
|
3074
|
-
if (!isNaN(value) && value <= this.endVal() && value >= this.min()) {
|
|
3075
|
-
this.startVal.set(value);
|
|
3076
|
-
}
|
|
3200
|
+
ngAfterViewInit() {
|
|
3201
|
+
this._startResizeObserver();
|
|
3077
3202
|
}
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
if (!isNaN(value) && value >= this.startVal() && value <= this.max()) {
|
|
3081
|
-
this.endVal.set(value);
|
|
3082
|
-
}
|
|
3203
|
+
ngOnDestroy() {
|
|
3204
|
+
this._resizeObserver?.disconnect();
|
|
3083
3205
|
}
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
if (
|
|
3090
|
-
this.
|
|
3206
|
+
updateParsedData() {
|
|
3207
|
+
if (this.chartData && this.config) {
|
|
3208
|
+
const rawParsed = parseSyncFusionData(this.chartData, this.config);
|
|
3209
|
+
this.dataChartParse = rawParsed.series;
|
|
3210
|
+
this.labelData = rawParsed.labelData;
|
|
3211
|
+
if (this.dataLabel && this.labelData) {
|
|
3212
|
+
this.labelData.dataLabel = this.dataLabel;
|
|
3091
3213
|
}
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3214
|
+
this.cdr.markForCheck();
|
|
3215
|
+
if (this.chartInstance) {
|
|
3216
|
+
setTimeout(() => {
|
|
3217
|
+
this.chartInstance?.refresh();
|
|
3218
|
+
});
|
|
3097
3219
|
}
|
|
3098
3220
|
}
|
|
3099
3221
|
}
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
if (val > this.startVal()) {
|
|
3111
|
-
this.endVal.set(val);
|
|
3222
|
+
pointRender(args) {
|
|
3223
|
+
const yValue = Number(args.point.y);
|
|
3224
|
+
// =====================================================
|
|
3225
|
+
// EMPTY POINT / VALOR 0
|
|
3226
|
+
// Tiene prioridad sobre ruleColorPoint
|
|
3227
|
+
// =====================================================
|
|
3228
|
+
if (yValue === 0) {
|
|
3229
|
+
const emptyPoint = this.config.emptyPointSettings;
|
|
3230
|
+
if (emptyPoint && emptyPoint !== '') {
|
|
3231
|
+
args.fill = emptyPoint;
|
|
3112
3232
|
}
|
|
3233
|
+
return;
|
|
3113
3234
|
}
|
|
3235
|
+
// =====================================================
|
|
3236
|
+
// RULE COLOR POINT
|
|
3237
|
+
// =====================================================
|
|
3238
|
+
const configPoint = this.config.ruleColorPoint || null;
|
|
3239
|
+
if (!configPoint) {
|
|
3240
|
+
return;
|
|
3241
|
+
}
|
|
3242
|
+
let passesRule = false;
|
|
3243
|
+
switch (configPoint.rule) {
|
|
3244
|
+
case 'threshold':
|
|
3245
|
+
passesRule =
|
|
3246
|
+
yValue >= (configPoint.thresholdValue || 0);
|
|
3247
|
+
break;
|
|
3248
|
+
case 'pair':
|
|
3249
|
+
passesRule = yValue % 2 === 0;
|
|
3250
|
+
break;
|
|
3251
|
+
case 'range':
|
|
3252
|
+
const min = configPoint.minRange || 0;
|
|
3253
|
+
const max = configPoint.maxRange || 100;
|
|
3254
|
+
passesRule =
|
|
3255
|
+
yValue >= min &&
|
|
3256
|
+
yValue <= max;
|
|
3257
|
+
break;
|
|
3258
|
+
default:
|
|
3259
|
+
passesRule = true;
|
|
3260
|
+
}
|
|
3261
|
+
args.fill = passesRule
|
|
3262
|
+
? (configPoint.trueColor || '#10B981')
|
|
3263
|
+
: (configPoint.falseColor || '#EF4444');
|
|
3114
3264
|
}
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
// Configuración de entradas
|
|
3132
|
-
this.idComponent = '';
|
|
3133
|
-
this.label = input('Tipo de producto', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3134
|
-
this.options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
3135
|
-
this.allowMultiple = input(true, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : [])); // Permite cambiar a selección única si es necesario
|
|
3136
|
-
// Evento de salida con la lista de IDs seleccionados
|
|
3137
|
-
this.selectionChange = output();
|
|
3138
|
-
// Signal con los IDs seleccionados
|
|
3139
|
-
this.selectedIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedIds" }] : []));
|
|
3140
|
-
// Current IDs seleccionados
|
|
3141
|
-
this.currentIds = input([], ...(ngDevMode ? [{ debugName: "currentIds" }] : []));
|
|
3142
|
-
// Emitir el listado en Array cada vez que la Signal de selección cambie
|
|
3143
|
-
effect(() => {
|
|
3144
|
-
this.selectionChange.emit(Array.from(this.selectedIds()));
|
|
3145
|
-
});
|
|
3146
|
-
}
|
|
3147
|
-
ngOnInit() {
|
|
3148
|
-
if (this.currentIds() && this.currentIds().length > 0) {
|
|
3149
|
-
this.selectedIds().clear();
|
|
3150
|
-
this.currentIds().forEach((itemId) => {
|
|
3151
|
-
this.selectedIds().add(itemId);
|
|
3265
|
+
_startResizeObserver() {
|
|
3266
|
+
if (typeof ResizeObserver === 'undefined')
|
|
3267
|
+
return;
|
|
3268
|
+
const hostEl = this.elRef.nativeElement;
|
|
3269
|
+
this._resizeObserver = new ResizeObserver((entries) => {
|
|
3270
|
+
window.requestAnimationFrame(() => {
|
|
3271
|
+
for (const entry of entries) {
|
|
3272
|
+
this.currentWidgetWidth = entry.contentRect.width;
|
|
3273
|
+
if (this.currentWidgetWidth > 0) {
|
|
3274
|
+
this._updateAdaptiveLabelSize(this.currentWidgetWidth);
|
|
3275
|
+
if (this.chartInstance) {
|
|
3276
|
+
// SI ACTIVAMSO EL REFRESH DA UN REBOTE AL REDIMENCIONAR
|
|
3277
|
+
this.chartInstance.refresh();
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3152
3281
|
});
|
|
3282
|
+
});
|
|
3283
|
+
this._resizeObserver.observe(hostEl);
|
|
3284
|
+
}
|
|
3285
|
+
_updateAdaptiveLabelSize(width) {
|
|
3286
|
+
if (this.config?.labelSize) {
|
|
3287
|
+
const parsedSize = typeof this.config.labelSize === 'number'
|
|
3288
|
+
? this.config.labelSize
|
|
3289
|
+
: parseFloat(this.config.labelSize);
|
|
3290
|
+
if (!isNaN(parsedSize)) {
|
|
3291
|
+
if (width < 260) {
|
|
3292
|
+
const scale = Math.max(0.65, width / 260);
|
|
3293
|
+
this.currentLabelSize = `${Math.round(parsedSize * scale)}px`;
|
|
3294
|
+
}
|
|
3295
|
+
else {
|
|
3296
|
+
this.currentLabelSize = `${parsedSize}px`;
|
|
3297
|
+
}
|
|
3298
|
+
this.cdr.markForCheck();
|
|
3299
|
+
return;
|
|
3300
|
+
}
|
|
3153
3301
|
}
|
|
3302
|
+
// Proporción estándar ideal (~7.5% del ancho del contenedor, acotado entre 13px y 26px)
|
|
3303
|
+
const base = Math.max(13, Math.min(26, Math.round(width * 0.075)));
|
|
3304
|
+
this.currentLabelSize = `${base}px`;
|
|
3305
|
+
this.cdr.markForCheck();
|
|
3154
3306
|
}
|
|
3155
|
-
|
|
3156
|
-
this.
|
|
3157
|
-
this.selectionChange.emit([]);
|
|
3307
|
+
refresh() {
|
|
3308
|
+
this.updateParsedData();
|
|
3158
3309
|
}
|
|
3159
|
-
//
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3310
|
+
// pointRender(args: any) {
|
|
3311
|
+
// if (args.point?.y === 0) {
|
|
3312
|
+
// args.fill = this.emptyPointSettings.fill;
|
|
3313
|
+
// args.border = {
|
|
3314
|
+
// width: this.emptyPointSettings.border?.width ?? 0,
|
|
3315
|
+
// color: this.emptyPointSettings.border?.color ?? ''
|
|
3316
|
+
// };
|
|
3317
|
+
// }
|
|
3318
|
+
// }
|
|
3319
|
+
axisLabelRender(args) {
|
|
3320
|
+
const umbralWidget = 700;
|
|
3321
|
+
if (this.currentWidgetWidth > umbralWidget) {
|
|
3322
|
+
return;
|
|
3323
|
+
}
|
|
3324
|
+
// Si la tarjeta es estrecha, aplicamos el recorte de etiquetas
|
|
3325
|
+
if (args.text && typeof args.text === 'string') {
|
|
3326
|
+
const palabras = args.text.split(' ');
|
|
3327
|
+
if (palabras.length > 1) {
|
|
3328
|
+
const primeraPalabra = palabras[0];
|
|
3329
|
+
const inicialSegunda = palabras[1].charAt(0).toUpperCase();
|
|
3330
|
+
args.text = `${primeraPalabra} ${inicialSegunda}.`;
|
|
3165
3331
|
}
|
|
3166
3332
|
else {
|
|
3167
|
-
|
|
3333
|
+
if (args.text.length > 10) {
|
|
3334
|
+
args.text = args.text.substring(0, 9) + '.';
|
|
3335
|
+
}
|
|
3168
3336
|
}
|
|
3169
3337
|
}
|
|
3170
|
-
else {
|
|
3171
|
-
// Si es selección única
|
|
3172
|
-
current.clear();
|
|
3173
|
-
current.add(id);
|
|
3174
|
-
}
|
|
3175
|
-
this.selectedIds.set(current);
|
|
3176
|
-
}
|
|
3177
|
-
isSelected(id) {
|
|
3178
|
-
return this.selectedIds().has(id);
|
|
3179
3338
|
}
|
|
3180
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
3181
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type:
|
|
3339
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: BubbleChartSyncfusionComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3340
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: BubbleChartSyncfusionComponent, isStandalone: true, selector: "yw-bubble-chart-syncfusion", inputs: { chartData: "chartData", config: "config", idComponent: "idComponent" }, providers: [BubbleSeriesService, CategoryService, CategoryService,
|
|
3341
|
+
TooltipService,
|
|
3342
|
+
LegendService,
|
|
3343
|
+
DateTimeService, DataLabelService], viewQueries: [{ propertyName: "chartInstance", first: true, predicate: ["chart"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"control-section\">\r\n <ejs-chart \r\n #chart \r\n [primaryXAxis]=\"labelData.axisX\" \r\n [primaryYAxis]=\"labelData.axisY\" \r\n [title]=\"labelData.title\" \r\n [palettes]=\"labelData.palettes\"\r\n [chartArea]=\"labelData.chartArea\"\r\n [titleStyle]=\"labelData.titleStyle\"\r\n\r\n (pointRender)=\"pointRender($event)\" \r\n height=\"100%\"\r\n width=\"100%\"\r\n [legendSettings]=\"labelData.legendSettings\"\r\n (axisLabelRender)=\"axisLabelRender($event)\"\r\n\r\n [tooltip]=\"labelData.tooltip\">\r\n <e-series-collection>\r\n @for(series of dataChartParse; track $index){\r\n <e-series \r\n [opacity]=\"series.opacity\"\r\n [dataSource]='series.dataSource' \r\n type='Bubble' \r\n xName='x' \r\n yName='y' \r\n size='size'\r\n [name]='series.name' \r\n\r\n [marker]=\"labelData.marker\"\r\n \r\n >\r\n <!-- [dataLabel]='series.dataLabel' -->\r\n </e-series>\r\n\r\n }\r\n </e-series-collection>\r\n</ejs-chart>\r\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;width:100%;height:100%;min-height:260px;box-sizing:border-box;overflow:hidden}.control-section{display:flex;flex-direction:column;width:100%;height:100%;min-height:260px;box-sizing:border-box;overflow:hidden;background:#fff;border-radius:8px}:host ::ng-deep ejs-circulargauge{display:block;width:100%!important;height:100%!important;flex-grow:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ChartModule }, { kind: "component", type: i1.ChartComponent, selector: "ejs-chart", inputs: ["accessibility", "allowExport", "allowMultiSelection", "annotations", "axes", "background", "backgroundImage", "border", "chartArea", "columns", "crosshair", "currencyCode", "dataSource", "description", "enableAnimation", "enableAutoIntervalOnBothAxis", "enableCanvas", "enableExport", "enableHtmlSanitizer", "enablePersistence", "enableRtl", "enableSideBySidePlacement", "focusBorderColor", "focusBorderMargin", "focusBorderWidth", "height", "highlightColor", "highlightMode", "highlightPattern", "indicators", "isMultiSelect", "isTransposed", "legendSettings", "locale", "margin", "palettes", "primaryXAxis", "primaryYAxis", "rangeColorSettings", "rows", "selectedDataIndexes", "selectionMode", "selectionPattern", "series", "subTitle", "subTitleStyle", "tabIndex", "theme", "title", "titleStyle", "tooltip", "useGroupingSeparator", "width", "zoomSettings"], outputs: ["afterExport", "animationComplete", "annotationRender", "axisLabelClick", "axisLabelRender", "axisMultiLabelRender", "axisRangeCalculated", "beforeExport", "beforePrint", "beforeResize", "chartDoubleClick", "chartMouseClick", "chartMouseDown", "chartMouseLeave", "chartMouseMove", "chartMouseUp", "drag", "dragComplete", "dragEnd", "dragStart", "legendClick", "legendRender", "load", "loaded", "multiLevelLabelClick", "onZooming", "pointClick", "pointDoubleClick", "pointMove", "pointRender", "resized", "scrollChanged", "scrollEnd", "scrollStart", "selectionComplete", "seriesRender", "sharedTooltipRender", "textRender", "tooltipRender", "zoomComplete", "dataSourceChange"] }, { kind: "directive", type: i1.SeriesDirective, selector: "e-series-collection>e-series", inputs: ["accessibility", "animation", "bearFillColor", "binInterval", "border", "boxPlotMode", "bullFillColor", "cardinalSplineTension", "close", "colorName", "columnFacet", "columnSpacing", "columnWidth", "columnWidthInPixel", "connector", "cornerRadius", "dashArray", "dataSource", "dragSettings", "drawType", "emptyPointSettings", "enableComplexProperty", "enableSolidCandles", "enableTooltip", "errorBar", "fill", "groupName", "high", "intermediateSumIndexes", "isClosed", "legendImageUrl", "legendShape", "low", "marker", "maxRadius", "minRadius", "name", "negativeFillColor", "noRisers", "nonHighlightStyle", "opacity", "open", "paretoOptions", "pointColorMapping", "query", "segmentAxis", "segments", "selectionStyle", "showMean", "showNormalDistribution", "size", "splineType", "stackingGroup", "step", "sumIndexes", "summaryFillColor", "tooltipFormat", "tooltipMappingName", "trendlines", "type", "unSelectedStyle", "visible", "volume", "width", "xAxisName", "xName", "yAxisName", "yName", "zOrder"] }, { kind: "directive", type: i1.SeriesCollectionDirective, selector: "ej-chart>e-series-collection" }] }); }
|
|
3182
3344
|
}
|
|
3183
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
3345
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: BubbleChartSyncfusionComponent, decorators: [{
|
|
3184
3346
|
type: Component,
|
|
3185
|
-
args: [{ selector: 'yw-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3347
|
+
args: [{ selector: 'yw-bubble-chart-syncfusion', standalone: true, imports: [CommonModule, ChartModule], providers: [BubbleSeriesService, CategoryService, CategoryService,
|
|
3348
|
+
TooltipService,
|
|
3349
|
+
LegendService,
|
|
3350
|
+
DateTimeService, DataLabelService], template: "<div class=\"control-section\">\r\n <ejs-chart \r\n #chart \r\n [primaryXAxis]=\"labelData.axisX\" \r\n [primaryYAxis]=\"labelData.axisY\" \r\n [title]=\"labelData.title\" \r\n [palettes]=\"labelData.palettes\"\r\n [chartArea]=\"labelData.chartArea\"\r\n [titleStyle]=\"labelData.titleStyle\"\r\n\r\n (pointRender)=\"pointRender($event)\" \r\n height=\"100%\"\r\n width=\"100%\"\r\n [legendSettings]=\"labelData.legendSettings\"\r\n (axisLabelRender)=\"axisLabelRender($event)\"\r\n\r\n [tooltip]=\"labelData.tooltip\">\r\n <e-series-collection>\r\n @for(series of dataChartParse; track $index){\r\n <e-series \r\n [opacity]=\"series.opacity\"\r\n [dataSource]='series.dataSource' \r\n type='Bubble' \r\n xName='x' \r\n yName='y' \r\n size='size'\r\n [name]='series.name' \r\n\r\n [marker]=\"labelData.marker\"\r\n \r\n >\r\n <!-- [dataLabel]='series.dataLabel' -->\r\n </e-series>\r\n\r\n }\r\n </e-series-collection>\r\n</ejs-chart>\r\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;width:100%;height:100%;min-height:260px;box-sizing:border-box;overflow:hidden}.control-section{display:flex;flex-direction:column;width:100%;height:100%;min-height:260px;box-sizing:border-box;overflow:hidden;background:#fff;border-radius:8px}:host ::ng-deep ejs-circulargauge{display:block;width:100%!important;height:100%!important;flex-grow:1}\n"] }]
|
|
3351
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { chartInstance: [{
|
|
3352
|
+
type: ViewChild,
|
|
3353
|
+
args: ['chart']
|
|
3354
|
+
}], chartData: [{
|
|
3355
|
+
type: Input,
|
|
3356
|
+
args: ['chartData']
|
|
3357
|
+
}], config: [{
|
|
3358
|
+
type: Input,
|
|
3359
|
+
args: ['config']
|
|
3360
|
+
}], idComponent: [{
|
|
3361
|
+
type: Input,
|
|
3362
|
+
args: ['idComponent']
|
|
3363
|
+
}] } });
|
|
3191
3364
|
|
|
3192
|
-
|
|
3365
|
+
// import { LineChartSyncfusionComponent } from '../../../../../adapters/charts/line-chart/syncfusion/visual/yw-line-chart-syncfusion.component';
|
|
3366
|
+
// import { YwLineMappingConfig } from '../../../../../models/config/chart/yw-line-chart-config.interface';
|
|
3367
|
+
class BubbleChartComponent {
|
|
3193
3368
|
constructor() {
|
|
3194
|
-
// Entradas generales
|
|
3195
3369
|
this.idComponent = '';
|
|
3196
|
-
this.label = input('Filtro Jerárquico', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3197
|
-
this.clearTitleLabel = input('Limpiar Seleccion', ...(ngDevMode ? [{ debugName: "clearTitleLabel" }] : []));
|
|
3198
|
-
// Opción 1: Entregar datos en árbol de texto directo
|
|
3199
|
-
this.rawData = input([], ...(ngDevMode ? [{ debugName: "rawData" }] : []));
|
|
3200
|
-
// Opción 2: Generar desde fechas
|
|
3201
|
-
this.dataType = input('date', ...(ngDevMode ? [{ debugName: "dataType" }] : []));
|
|
3202
|
-
this.minDate = input('', ...(ngDevMode ? [{ debugName: "minDate" }] : [])); // Formato 'YYYY-MM-DD'
|
|
3203
|
-
this.maxDate = input('', ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
|
|
3204
|
-
this.dateHierarchyType = input('YEAR_TRIMESTER_MONTH', ...(ngDevMode ? [{ debugName: "dateHierarchyType" }] : []));
|
|
3205
|
-
this.monthNames = input(['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], ...(ngDevMode ? [{ debugName: "monthNames" }] : []));
|
|
3206
|
-
// Evento de salida con el ID/Nodo seleccionado
|
|
3207
|
-
this.selectionChange = output();
|
|
3208
|
-
this.filterValueChange = output(); // Output 2 (Rangos o Hojas)
|
|
3209
|
-
// ID del elemento seleccionado (Selección Simple)
|
|
3210
|
-
this.selectedId = signal(null, ...(ngDevMode ? [{ debugName: "selectedId" }] : []));
|
|
3211
|
-
this.currentSelectedId = input(null, ...(ngDevMode ? [{ debugName: "currentSelectedId" }] : []));
|
|
3212
|
-
// Arbol de nodos computado
|
|
3213
|
-
this.treeNodes = computed(() => {
|
|
3214
|
-
if (this.dataType() == 'date' && this.minDate() && this.maxDate()) {
|
|
3215
|
-
return this.generateDateHierarchy(this.minDate(), this.maxDate(), this.dateHierarchyType());
|
|
3216
|
-
}
|
|
3217
|
-
return this.rawData();
|
|
3218
|
-
}, ...(ngDevMode ? [{ debugName: "treeNodes" }] : []));
|
|
3219
|
-
effect(() => {
|
|
3220
|
-
const currentId = this.selectedId();
|
|
3221
|
-
if (!currentId) {
|
|
3222
|
-
this.selectionChange.emit(null);
|
|
3223
|
-
this.filterValueChange.emit(null);
|
|
3224
|
-
return;
|
|
3225
|
-
}
|
|
3226
|
-
const node = this.findNodeById(this.treeNodes(), currentId);
|
|
3227
|
-
this.selectionChange.emit(node);
|
|
3228
|
-
if (node) {
|
|
3229
|
-
// Emitir el segundo Output según el modo
|
|
3230
|
-
const calculatedValue = this.processFilterOutput(node);
|
|
3231
|
-
this.filterValueChange.emit(calculatedValue);
|
|
3232
|
-
}
|
|
3233
|
-
});
|
|
3234
3370
|
}
|
|
3235
3371
|
ngOnInit() {
|
|
3236
|
-
|
|
3237
|
-
this.selectedId.set(this.currentSelectedId());
|
|
3238
|
-
}
|
|
3239
|
-
}
|
|
3240
|
-
// Métodos de Selección y Expansión
|
|
3241
|
-
toggleExpand(node, event) {
|
|
3242
|
-
event.stopPropagation();
|
|
3243
|
-
node.expanded = !node.expanded;
|
|
3244
|
-
}
|
|
3245
|
-
selectNode(node, event) {
|
|
3246
|
-
event.stopPropagation();
|
|
3247
|
-
this.selectedId.set(this.selectedId() === node.id ? null : node.id);
|
|
3372
|
+
console.log("EL ID DEL COMPONENTE:", this.idComponent);
|
|
3248
3373
|
}
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3374
|
+
ngOnChanges(changes) {
|
|
3375
|
+
if (changes['chartData']) {
|
|
3376
|
+
console.log('change chartDataBubble:', changes['chartData'].currentValue);
|
|
3377
|
+
}
|
|
3378
|
+
if (changes['config']) {
|
|
3379
|
+
console.log('change configBubble:', changes['config'].currentValue);
|
|
3380
|
+
}
|
|
3252
3381
|
}
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
// 1. Obtener todas las hojas (nodos del nivel más bajo) pertenecientes al bloque seleccionado
|
|
3256
|
-
const leaves = this.getLeafNodes(selectedNode);
|
|
3257
|
-
if (this.dataType() == 'date') {
|
|
3258
|
-
// Extraer todas las fechas de las hojas del bloque
|
|
3259
|
-
const dates = leaves
|
|
3260
|
-
.map(leaf => leaf.value)
|
|
3261
|
-
.filter(d => d instanceof Date)
|
|
3262
|
-
.sort((a, b) => a.getTime() - b.getTime());
|
|
3263
|
-
if (dates.length > 0) {
|
|
3264
|
-
const minD = dates[0];
|
|
3265
|
-
// Para la fecha máxima, tomamos el último día del mes correspondiente
|
|
3266
|
-
const maxD = new Date(dates[dates.length - 1].getFullYear(), dates[dates.length - 1].getMonth() + 1, 0);
|
|
3267
|
-
return {
|
|
3268
|
-
type: 'DATE_RANGE',
|
|
3269
|
-
dateRange: {
|
|
3270
|
-
minDate: minD.toISOString().split('T')[0],
|
|
3271
|
-
maxDate: maxD.toISOString().split('T')[0]
|
|
3272
|
-
},
|
|
3273
|
-
currentNodeId: selectedNode.id
|
|
3274
|
-
};
|
|
3275
|
-
}
|
|
3276
|
-
}
|
|
3277
|
-
// Modo Texto: Entregar arreglo con las hojas
|
|
3278
|
-
return {
|
|
3279
|
-
type: 'TEXT_LEAVES',
|
|
3280
|
-
leafNodes: leaves,
|
|
3281
|
-
leafIds: leaves.map(l => l.id),
|
|
3282
|
-
currentNodeId: selectedNode.id
|
|
3283
|
-
};
|
|
3284
|
-
}
|
|
3285
|
-
// Recorrido recursivo para obtener solo los nodos terminales (sin hijos)
|
|
3286
|
-
getLeafNodes(node) {
|
|
3287
|
-
if (!node.children || node.children.length === 0) {
|
|
3288
|
-
return [node];
|
|
3289
|
-
}
|
|
3290
|
-
let leaves = [];
|
|
3291
|
-
for (const child of node.children) {
|
|
3292
|
-
leaves = leaves.concat(this.getLeafNodes(child));
|
|
3293
|
-
}
|
|
3294
|
-
return leaves;
|
|
3295
|
-
}
|
|
3296
|
-
findNodeById(nodes, id) {
|
|
3297
|
-
for (const node of nodes) {
|
|
3298
|
-
if (node.id === id)
|
|
3299
|
-
return node;
|
|
3300
|
-
if (node.children) {
|
|
3301
|
-
const found = this.findNodeById(node.children, id);
|
|
3302
|
-
if (found)
|
|
3303
|
-
return found;
|
|
3304
|
-
}
|
|
3305
|
-
}
|
|
3306
|
-
return null;
|
|
3307
|
-
}
|
|
3308
|
-
// Generador de Jerarquía por Fechas
|
|
3309
|
-
generateDateHierarchy(startStr, endStr, type) {
|
|
3310
|
-
const start = new Date(startStr);
|
|
3311
|
-
const end = new Date(endStr);
|
|
3312
|
-
const tree = [];
|
|
3313
|
-
const monthNames = this.monthNames();
|
|
3314
|
-
if (type === 'YEAR_TRIMESTER_MONTH') {
|
|
3315
|
-
let current = new Date(start);
|
|
3316
|
-
while (current <= end) {
|
|
3317
|
-
const year = current.getFullYear();
|
|
3318
|
-
let yearNode = tree.find(n => n.id === `Y_${year}`);
|
|
3319
|
-
if (!yearNode) {
|
|
3320
|
-
yearNode = { id: `Y_${year}`, label: `${year}`, children: [], expanded: false };
|
|
3321
|
-
tree.push(yearNode);
|
|
3322
|
-
}
|
|
3323
|
-
const month = current.getMonth();
|
|
3324
|
-
const qtrNum = Math.floor(month / 3) + 1;
|
|
3325
|
-
let qtrNode = yearNode.children.find(n => n.id === `Q_${year}_${qtrNum}`);
|
|
3326
|
-
if (!qtrNode) {
|
|
3327
|
-
qtrNode = { id: `Q_${year}_${qtrNum}`, label: `Qtr ${qtrNum}`, children: [], expanded: false };
|
|
3328
|
-
yearNode.children.push(qtrNode);
|
|
3329
|
-
}
|
|
3330
|
-
const monthId = `M_${year}_${month + 1}`;
|
|
3331
|
-
if (!qtrNode.children.some(n => n.id === monthId)) {
|
|
3332
|
-
qtrNode.children.push({
|
|
3333
|
-
id: monthId,
|
|
3334
|
-
label: monthNames[month],
|
|
3335
|
-
value: new Date(year, month, 1) // Fecha inicial del mes
|
|
3336
|
-
});
|
|
3337
|
-
}
|
|
3338
|
-
current.setMonth(current.getMonth() + 1);
|
|
3339
|
-
}
|
|
3340
|
-
}
|
|
3341
|
-
if (type === 'YEAR_SEMESTER_MONTH') {
|
|
3342
|
-
let current = new Date(start);
|
|
3343
|
-
while (current <= end) {
|
|
3344
|
-
const year = current.getFullYear();
|
|
3345
|
-
let yearNode = tree.find(n => n.id === `Y_${year}`);
|
|
3346
|
-
if (!yearNode) {
|
|
3347
|
-
yearNode = { id: `Y_${year}`, label: `${year}`, children: [], expanded: false };
|
|
3348
|
-
tree.push(yearNode);
|
|
3349
|
-
}
|
|
3350
|
-
const month = current.getMonth();
|
|
3351
|
-
const qtrNum = Math.floor(month / 6) + 1;
|
|
3352
|
-
let qtrNode = yearNode.children.find(n => n.id === `S_${year}_${qtrNum}`);
|
|
3353
|
-
if (!qtrNode) {
|
|
3354
|
-
qtrNode = { id: `S_${year}_${qtrNum}`, label: `S ${qtrNum}`, children: [], expanded: false };
|
|
3355
|
-
yearNode.children.push(qtrNode);
|
|
3356
|
-
}
|
|
3357
|
-
const monthId = `M_${year}_${month + 1}`;
|
|
3358
|
-
if (!qtrNode.children.some(n => n.id === monthId)) {
|
|
3359
|
-
qtrNode.children.push({
|
|
3360
|
-
id: monthId,
|
|
3361
|
-
label: monthNames[month],
|
|
3362
|
-
value: new Date(year, month, 1) // Fecha inicial del mes
|
|
3363
|
-
});
|
|
3364
|
-
}
|
|
3365
|
-
current.setMonth(current.getMonth() + 1);
|
|
3366
|
-
}
|
|
3367
|
-
}
|
|
3368
|
-
return tree;
|
|
3369
|
-
}
|
|
3370
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwListSlicerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3371
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwListSlicerComponent, isStandalone: true, selector: "yw-list-slicer", inputs: { idComponent: { classPropertyName: "idComponent", publicName: "idComponent", isSignal: false, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, clearTitleLabel: { classPropertyName: "clearTitleLabel", publicName: "clearTitleLabel", isSignal: true, isRequired: false, transformFunction: null }, rawData: { classPropertyName: "rawData", publicName: "rawData", isSignal: true, isRequired: false, transformFunction: null }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, dateHierarchyType: { classPropertyName: "dateHierarchyType", publicName: "dateHierarchyType", isSignal: true, isRequired: false, transformFunction: null }, monthNames: { classPropertyName: "monthNames", publicName: "monthNames", isSignal: true, isRequired: false, transformFunction: null }, currentSelectedId: { classPropertyName: "currentSelectedId", publicName: "currentSelectedId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", filterValueChange: "filterValueChange" }, host: { properties: { "attr.id": "idComponent" } }, ngImport: i0, template: "<div class=\"filter-container\">\r\n <!-- Cabecera con t\u00EDtulo y acciones de filtro -->\r\n <div class=\"filter-header\">\r\n <span class=\"filter-label\">{{ label() }}</span>\r\n <div class=\"header-actions\">\r\n <!--<button class=\"icon-btn\" title=\"Filtro\">\uD83D\uDD3B</button>-->\r\n <button class=\"icon-btn\" (click)=\"clearSelection()\" title=\"{{clearTitleLabel}}\">\uD83E\uDDF9</button>\r\n <!--<button class=\"icon-btn\" title=\"M\u00E1s opciones\">\u22EE</button>-->\r\n </div>\r\n </div>\r\n\r\n <!-- Vista en \u00C1rbol con scroll interno -->\r\n <div class=\"tree-scroll-container\">\r\n <ng-container *ngTemplateOutlet=\"nodeListTemplate; context: { $implicit: treeNodes(), level: 0 }\"></ng-container>\r\n </div>\r\n</div>\r\n\r\n<!-- Plantilla Recursiva para renderizar niveles del \u00C1rbol -->\r\n<ng-template #nodeListTemplate let-nodes let-level=\"level\">\r\n <div class=\"tree-level\">\r\n @for (node of nodes; track node.id) {\r\n <div class=\"tree-node-wrapper\">\r\n <!-- Fila de opci\u00F3n -->\r\n <div \r\n class=\"tree-node-row\" \r\n [class.selected]=\"selectedId() === node.id\"\r\n [style.padding-left.px]=\"level * 18 + 6\"\r\n (click)=\"selectNode(node, $event)\">\r\n \r\n <!-- Flecha expandir/colapsar (si tiene hijos) -->\r\n @if (node.children && node.children.length > 0) {\r\n <span class=\"chevron-icon\" (click)=\"toggleExpand(node, $event)\">\r\n {{ node.expanded ? '\uD83D\uDF83' : '\uD83D\uDF82' }}\r\n </span>\r\n } @else {\r\n <span class=\"chevron-spacer\"></span>\r\n }\r\n\r\n <!-- Radio Button (Selecci\u00F3n simple) -->\r\n <div class=\"radio-circle\" [class.checked]=\"selectedId() === node.id\">\r\n <div class=\"radio-inner\"></div>\r\n </div>\r\n\r\n <!-- Etiqueta del Nodo -->\r\n <span class=\"node-label\">{{ node.label }}</span>\r\n </div>\r\n\r\n <!-- Renderizado de hijos si est\u00E1 expandido -->\r\n @if (node.children && node.children.length > 0 && node.expanded) {\r\n <ng-container *ngTemplateOutlet=\"nodeListTemplate; context: { $implicit: node.children, level: level + 1 }\"></ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{display:block;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;width:100%;max-width:320px;background:#fff}.filter-container{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:4px;background-color:#fff}.filter-header{display:flex;align-items:center;justify-content:space-between;padding:6px 10px;border-bottom:1px solid #f0f0f0}.filter-label{font-size:13px;font-weight:600;color:#252423}.header-actions{display:flex;gap:4px}.icon-btn{background:none;border:none;cursor:pointer;font-size:12px;color:#605e5c;padding:2px 4px;border-radius:2px}.icon-btn:hover{background-color:#f3f2f1}.tree-scroll-container{max-height:220px;overflow-y:auto;padding:4px 0}.tree-level{display:flex;flex-direction:column}.tree-node-row{display:flex;align-items:center;height:28px;cursor:pointer;-webkit-user-select:none;user-select:none;gap:6px;transition:background-color .1s ease}.tree-node-row:hover{background-color:#f3f2f1}.tree-node-row.selected{background-color:#e1dfdd}.chevron-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:10px;color:#323130}.chevron-spacer{width:16px}.radio-circle{width:14px;height:14px;border-radius:50%;border:1.5px solid #605e5c;display:flex;align-items:center;justify-content:center;box-sizing:border-box;background-color:#fff}.radio-circle.checked{border-color:#0078d4}.radio-circle.checked .radio-inner{width:6px;height:6px;border-radius:50%;background-color:#0078d4}.node-label{font-size:13px;color:#323130;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tree-scroll-container::-webkit-scrollbar{width:6px}.tree-scroll-container::-webkit-scrollbar-track{background:#f1f1f1}.tree-scroll-container::-webkit-scrollbar-thumb{background:#8a8886;border-radius:3px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
|
|
3382
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: BubbleChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3383
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: BubbleChartComponent, isStandalone: true, selector: "yw-bubble-chart", inputs: { chartData: "chartData", config: "config", idComponent: "idComponent" }, usesOnChanges: true, ngImport: i0, template: "@if(config.provider==='syncfusion'){\r\n <div style=\"position: relative; width: 100%; height: 100%;\">\r\n <yw-bubble-chart-syncfusion \r\n [idComponent]=\"idComponent\"\r\n [chartData]=\"chartData\" \r\n [config]=\"config\" style=\"display: block; width: 100%; height: 100%;\">\r\n </yw-bubble-chart-syncfusion>\r\n</div>\r\n}", styles: [":host{display:block;width:100%;height:100%;min-height:260px;min-width:0;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BubbleChartSyncfusionComponent, selector: "yw-bubble-chart-syncfusion", inputs: ["chartData", "config", "idComponent"] }] }); }
|
|
3372
3384
|
}
|
|
3373
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
3385
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: BubbleChartComponent, decorators: [{
|
|
3374
3386
|
type: Component,
|
|
3375
|
-
args: [{ selector: 'yw-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3387
|
+
args: [{ selector: 'yw-bubble-chart', standalone: true, imports: [CommonModule, BubbleChartSyncfusionComponent], template: "@if(config.provider==='syncfusion'){\r\n <div style=\"position: relative; width: 100%; height: 100%;\">\r\n <yw-bubble-chart-syncfusion \r\n [idComponent]=\"idComponent\"\r\n [chartData]=\"chartData\" \r\n [config]=\"config\" style=\"display: block; width: 100%; height: 100%;\">\r\n </yw-bubble-chart-syncfusion>\r\n</div>\r\n}", styles: [":host{display:block;width:100%;height:100%;min-height:260px;min-width:0;overflow:hidden}\n"] }]
|
|
3388
|
+
}], propDecorators: { chartData: [{
|
|
3389
|
+
type: Input,
|
|
3390
|
+
args: ['chartData']
|
|
3391
|
+
}], config: [{
|
|
3392
|
+
type: Input,
|
|
3393
|
+
args: ['config']
|
|
3394
|
+
}], idComponent: [{
|
|
3395
|
+
type: Input,
|
|
3396
|
+
args: ['idComponent']
|
|
3397
|
+
}] } });
|
|
3381
3398
|
|
|
3382
|
-
|
|
3399
|
+
/*BEGIN - COMPONENTES VALIDOS PARA WIDGET*/
|
|
3400
|
+
class YwDashboardWidgetComponent {
|
|
3383
3401
|
constructor() {
|
|
3384
3402
|
this.componentWidgetId = '';
|
|
3385
3403
|
this.typeComponent = '';
|
|
3386
3404
|
this.varShowConfigButtons = false;
|
|
3405
|
+
this.styleWidget = input(DEFAULT_WIDGET_STYLE, ...(ngDevMode ? [{ debugName: "styleWidget" }] : []));
|
|
3406
|
+
// Signal calculada que combina los valores recibidos con los valores por defecto
|
|
3407
|
+
this.instanceStyleWidget = computed(() => ({
|
|
3408
|
+
widgetBackgroundColor: this.styleWidget()?.widgetBackgroundColor ?? DEFAULT_WIDGET_STYLE.widgetBackgroundColor,
|
|
3409
|
+
widgetBorderColor: this.styleWidget()?.widgetBorderColor ?? DEFAULT_WIDGET_STYLE.widgetBorderColor
|
|
3410
|
+
}), ...(ngDevMode ? [{ debugName: "instanceStyleWidget" }] : []));
|
|
3387
3411
|
this.configWidget = {
|
|
3388
3412
|
widgetId: '',
|
|
3389
|
-
|
|
3413
|
+
title: '',
|
|
3390
3414
|
typeComponent: '',
|
|
3391
|
-
|
|
3415
|
+
showConfigButtons: false,
|
|
3416
|
+
widgetStyle: DEFAULT_WIDGET_STYLE,
|
|
3417
|
+
layoutConfig: { id: '', w: 0, h: 0, content: undefined },
|
|
3418
|
+
controlConfig: {},
|
|
3419
|
+
controlTables: []
|
|
3392
3420
|
};
|
|
3393
|
-
this.controlConfig =
|
|
3394
|
-
this.controlData =
|
|
3421
|
+
this.controlConfig = {};
|
|
3422
|
+
this.controlData = {};
|
|
3423
|
+
this.isLocked = model(false, ...(ngDevMode ? [{ debugName: "isLocked" }] : []));
|
|
3424
|
+
this.isMaximized = signal(false, ...(ngDevMode ? [{ debugName: "isMaximized" }] : []));
|
|
3395
3425
|
this.eventDeleteRequest = output();
|
|
3426
|
+
this.eventLockToggleRequest = output();
|
|
3427
|
+
this.eventMaximizeToggleRequest = output();
|
|
3396
3428
|
this.eventShowConfigFormRequest = output();
|
|
3397
|
-
this.selectionChange = output();
|
|
3398
|
-
effect(() => {
|
|
3399
|
-
const value_controlConfig = this.fnFormatConfigData();
|
|
3400
|
-
this.dataWidget = { idComponent: this.componentWidgetId,
|
|
3401
|
-
configWidget: this.configWidget,
|
|
3402
|
-
controlConfig: value_controlConfig
|
|
3403
|
-
};
|
|
3404
|
-
});
|
|
3405
3429
|
}
|
|
3406
3430
|
ngOnInit() {
|
|
3407
|
-
this.componentWidgetId = this.configWidget.widgetId;
|
|
3431
|
+
this.componentWidgetId = 'cmpnt-' + this.configWidget.widgetId;
|
|
3408
3432
|
this.typeComponent = this.configWidget.typeComponent;
|
|
3409
|
-
const value_controlConfig = this.fnFormatConfigData();
|
|
3410
3433
|
this.dataWidget = { idComponent: this.componentWidgetId,
|
|
3411
|
-
|
|
3412
|
-
|
|
3434
|
+
controlConfig: this.controlConfig,
|
|
3435
|
+
controlData: this.controlData
|
|
3413
3436
|
};
|
|
3437
|
+
// console.log('DATOS INICIALES INIT:');
|
|
3438
|
+
// console.log(this.dataWidget);
|
|
3414
3439
|
}
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
const currentData = this.controlConfig();
|
|
3424
|
-
if (dataType == 'date') {
|
|
3425
|
-
const fieldName = this.controlConfig().filterField;
|
|
3426
|
-
const fechas = this.controlData.map((d) => new Date(d[fieldName]).getTime());
|
|
3427
|
-
const val_min = new Date(Math.min(...fechas)).toISOString().split("T")[0];
|
|
3428
|
-
const val_max = new Date(Math.max(...fechas)).toISOString().split("T")[0];
|
|
3429
|
-
responsedata = { dataType: dataType, min: val_min, max: val_max, minCurrent: currentData?.minCurrent, maxCurrent: currentData?.maxCurrent };
|
|
3430
|
-
}
|
|
3431
|
-
if (dataType == 'number') {
|
|
3432
|
-
const fieldName = this.controlConfig().filterField;
|
|
3433
|
-
const valStep = this.controlConfig().step;
|
|
3434
|
-
const DataNumbers = this.controlData.map((d) => d[fieldName]);
|
|
3435
|
-
const val_min = Math.min(...DataNumbers);
|
|
3436
|
-
const val_max = Math.max(...DataNumbers);
|
|
3437
|
-
responsedata = { dataType: dataType, min: val_min, max: val_max, step: valStep, minCurrent: currentData?.minCurrent, maxCurrent: currentData?.maxCurrent };
|
|
3438
|
-
}
|
|
3440
|
+
ngAfterViewInit() {
|
|
3441
|
+
this.varShowConfigButtons = this.configWidget.showConfigButtons || false;
|
|
3442
|
+
}
|
|
3443
|
+
ngOnChanges(changes) {
|
|
3444
|
+
if (changes['configWidget']) {
|
|
3445
|
+
//console.log('Nuevo valor configWidget:', this.configWidget);
|
|
3446
|
+
this.varShowConfigButtons = this.configWidget.showConfigButtons || false;
|
|
3447
|
+
;
|
|
3439
3448
|
}
|
|
3440
|
-
if (
|
|
3441
|
-
|
|
3442
|
-
const fieldNameId = this.controlConfig().filterFieldId;
|
|
3443
|
-
const val_allowMultiple = this.controlConfig().allowMultiple;
|
|
3444
|
-
const currentData = this.controlConfig();
|
|
3445
|
-
let listoptions = this.controlData.map((item) => { return { 'id': item[fieldNameId], 'label': item[fieldName] }; });
|
|
3446
|
-
const listoptionsunicos = [...new Map(listoptions.map(d => [d.id, d])).values()];
|
|
3447
|
-
responsedata = { options: listoptionsunicos, allowMultiple: val_allowMultiple, currentIds: currentData?.currentIds };
|
|
3449
|
+
if (changes['controlConfig']) {
|
|
3450
|
+
// console.log('Nuevo valor controlConfig:', this.controlConfig);
|
|
3448
3451
|
}
|
|
3449
|
-
if (
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
const fechas = this.controlData.map((d) => new Date(d[fieldName]).getTime());
|
|
3456
|
-
const val_min = new Date(Math.min(...fechas)).toISOString().split("T")[0];
|
|
3457
|
-
const val_max = new Date(Math.max(...fechas)).toISOString().split("T")[0];
|
|
3458
|
-
responsedata = { dataType: dataType, minDate: val_min, maxDate: val_max, dateHierarchyType: val_dateHierarchyType, currentSelectedId: currentData.currentSelectedId };
|
|
3459
|
-
}
|
|
3460
|
-
if (dataType == 'text') {
|
|
3461
|
-
const fieldName1 = this.controlConfig().filterField;
|
|
3462
|
-
const fieldName2 = this.controlConfig().filterFieldN2;
|
|
3463
|
-
const fieldName3 = this.controlConfig().filterFieldN3;
|
|
3464
|
-
let foundN2 = false;
|
|
3465
|
-
let foundN3 = false;
|
|
3466
|
-
let lsizeN2 = 0;
|
|
3467
|
-
let lsizeN3 = 0;
|
|
3468
|
-
let nodebase = { id: '', label: '' };
|
|
3469
|
-
let nodeN2 = { id: '', label: '' };
|
|
3470
|
-
let nodeN3 = { id: '', label: '' };
|
|
3471
|
-
let listNivel1 = [];
|
|
3472
|
-
let listNivel2 = [];
|
|
3473
|
-
let listNivel3 = [];
|
|
3474
|
-
this.controlData.forEach((item) => {
|
|
3475
|
-
nodebase = { id: item[fieldName1], label: item[fieldName1] };
|
|
3476
|
-
//NIVEL 2
|
|
3477
|
-
if (fieldName2) {
|
|
3478
|
-
foundN2 = false;
|
|
3479
|
-
lsizeN2 = Object.keys(listNivel2).length;
|
|
3480
|
-
for (let i = 0; i < lsizeN2; i++) {
|
|
3481
|
-
const itemN2 = listNivel2[i];
|
|
3482
|
-
if (itemN2.id == item[fieldName2]) {
|
|
3483
|
-
itemN2.children.push(nodebase);
|
|
3484
|
-
nodeN2 = itemN2;
|
|
3485
|
-
foundN2 = true;
|
|
3486
|
-
break;
|
|
3487
|
-
}
|
|
3488
|
-
}
|
|
3489
|
-
;
|
|
3490
|
-
if (foundN2 == false) {
|
|
3491
|
-
nodeN2 = { id: item[fieldName2], label: item[fieldName2], expanded: true, children: [nodebase] };
|
|
3492
|
-
if (fieldName3) {
|
|
3493
|
-
nodeN2.parentId = item[fieldName3];
|
|
3494
|
-
}
|
|
3495
|
-
listNivel2.push(nodeN2);
|
|
3496
|
-
}
|
|
3497
|
-
}
|
|
3498
|
-
else {
|
|
3499
|
-
listNivel1.push(nodebase);
|
|
3500
|
-
}
|
|
3501
|
-
});
|
|
3502
|
-
//NIVEL 1 - Basico no hay Jerarquia
|
|
3503
|
-
responsedata = { dataType: dataType, rawData: listNivel1, currentSelectedId: currentData.currentSelectedId };
|
|
3504
|
-
//NIVEL 2 - Jerarquia de 2 niveles
|
|
3505
|
-
if (fieldName2) {
|
|
3506
|
-
responsedata = { dataType: dataType, rawData: listNivel2, currentSelectedId: currentData.currentSelectedId };
|
|
3507
|
-
}
|
|
3508
|
-
//NIVEL 3 - Jerarquia de 3 niveles
|
|
3509
|
-
if (fieldName3) {
|
|
3510
|
-
listNivel2.forEach((item) => {
|
|
3511
|
-
nodebase = item;
|
|
3512
|
-
foundN3 = false;
|
|
3513
|
-
lsizeN3 = Object.keys(listNivel3).length;
|
|
3514
|
-
for (let i = 0; i < lsizeN3; i++) {
|
|
3515
|
-
const itemN3 = listNivel3[i];
|
|
3516
|
-
if (itemN3.id == item.parentId) {
|
|
3517
|
-
itemN3.children.push(nodebase);
|
|
3518
|
-
foundN3 = true;
|
|
3519
|
-
break;
|
|
3520
|
-
}
|
|
3521
|
-
}
|
|
3522
|
-
;
|
|
3523
|
-
if (foundN3 == false) {
|
|
3524
|
-
nodeN3 = { id: item[fieldName3], label: item[fieldName3], expanded: true, children: [nodebase] };
|
|
3525
|
-
listNivel3.push(nodeN3);
|
|
3526
|
-
}
|
|
3527
|
-
});
|
|
3528
|
-
responsedata = { dataType: dataType, rawData: listNivel3, currentSelectedId: currentData.currentSelectedId };
|
|
3529
|
-
}
|
|
3530
|
-
}
|
|
3452
|
+
if (changes['controlData']) {
|
|
3453
|
+
//console.log('Nuevo valor controlData:', this.controlData);
|
|
3454
|
+
this.dataWidget = { idComponent: this.componentWidgetId,
|
|
3455
|
+
controlConfig: this.controlConfig,
|
|
3456
|
+
controlData: this.controlData
|
|
3457
|
+
};
|
|
3531
3458
|
}
|
|
3532
|
-
return responsedata;
|
|
3533
|
-
}
|
|
3534
|
-
//Filtro Slicer
|
|
3535
|
-
onFilterSlicerChange(range) {
|
|
3536
|
-
console.log('Filtro actualizado:', range);
|
|
3537
|
-
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: range });
|
|
3538
|
-
}
|
|
3539
|
-
//Filtro Button
|
|
3540
|
-
onFilterButtonChange(selectedIds) {
|
|
3541
|
-
console.log('Tipos seleccionados:', selectedIds);
|
|
3542
|
-
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: selectedIds });
|
|
3543
3459
|
}
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
//this.selectionChange.emit({widgetId:this.componentWidgetId,eventResponse:selectedData});
|
|
3460
|
+
/* BEGIN - BARRA DE EVENTOS DEL WIDGET */
|
|
3461
|
+
//Eliminacion de Widget - Conectado al Dashboard
|
|
3462
|
+
onDeleteClick() {
|
|
3463
|
+
this.eventDeleteRequest.emit(this.configWidget.widgetId);
|
|
3549
3464
|
}
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
}
|
|
3556
|
-
if (data.type === 'DATE_RANGE') {
|
|
3557
|
-
//console.log('Rango a filtrar en SQL/Dashboard:', data.dateRange?.minDate, 'hasta', data.dateRange?.maxDate);
|
|
3558
|
-
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: { minDate: data.dateRange?.minDate, maxDate: data.dateRange?.maxDate, currentNodeId: data.currentNodeId } });
|
|
3559
|
-
}
|
|
3560
|
-
else if (data.type === 'TEXT_LEAVES') {
|
|
3561
|
-
//console.log('Lista de elementos terminales seleccionados:', data.leafIds);
|
|
3562
|
-
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: { ids: data.leafIds, currentNodeId: data.currentNodeId } });
|
|
3563
|
-
}
|
|
3465
|
+
onLockClick() {
|
|
3466
|
+
// Invertimos el estado local y notificamos al padre
|
|
3467
|
+
const nextState = !this.isLocked();
|
|
3468
|
+
this.isLocked.set(nextState);
|
|
3469
|
+
this.eventLockToggleRequest.emit({ widgetId: this.configWidget.widgetId, shouldLock: nextState });
|
|
3564
3470
|
}
|
|
3565
|
-
|
|
3471
|
+
onMaximizeClick() {
|
|
3472
|
+
const nextState = !this.isMaximized();
|
|
3473
|
+
this.isMaximized.set(nextState);
|
|
3474
|
+
this.eventMaximizeToggleRequest.emit({ widgetId: this.configWidget.widgetId, shouldMaximize: nextState });
|
|
3566
3475
|
}
|
|
3567
3476
|
onShowFormConfigClick() {
|
|
3477
|
+
this.eventShowConfigFormRequest.emit(this.configWidget.widgetId);
|
|
3568
3478
|
}
|
|
3569
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
3570
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwDashboardFilterWidgetComponent, isStandalone: true, selector: "yw-dashboard-filter-widget", inputs: { configWidget: { classPropertyName: "configWidget", publicName: "configWidget", isSignal: false, isRequired: false, transformFunction: null }, controlConfig: { classPropertyName: "controlConfig", publicName: "controlConfig", isSignal: true, isRequired: false, transformFunction: null }, controlData: { classPropertyName: "controlData", publicName: "controlData", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { eventDeleteRequest: "eventDeleteRequest", eventShowConfigFormRequest: "eventShowConfigFormRequest", selectionChange: "selectionChange" }, ngImport: i0, template: "\r\n<div class=\"widget-filter-action-bar\"> \r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\">\uD83D\uDDD1\uFE0F</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\">\u2699\uFE0F</button>\r\n</div>\r\n<div class=\"widget-filter-content-wrapper\">\r\n @if ( typeComponent == 'empty-visual' ) { \r\n <ng-container *ngTemplateOutlet=\"emptyvisual; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-slicer' ) { \r\n <ng-container *ngTemplateOutlet=\"filterslicer; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-button' ) { \r\n <ng-container *ngTemplateOutlet=\"filterbutton; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-list' ) { \r\n <ng-container *ngTemplateOutlet=\"filterlist; context: { control: dataWidget }\"></ng-container>\r\n } \r\n \r\n</div>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- EMPTY VISUAL TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #emptyvisual let-control = \"control\">\r\n <yw-empty-visual [idComponent]=\"control.idComponent\"\r\n [config]=\"control.controlConfig\" \r\n > \r\n </yw-empty-visual>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER SLICER TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterslicer let-control = \"control\"> \r\n @if (control.controlConfig.dataType === 'date') { \r\n <yw-base-slicer [idComponent]=\"control.idComponent\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [label]=\"control.configWidget.label\"\r\n [min]=\"control.controlConfig.min\"\r\n [max]=\"control.controlConfig.max\" \r\n [minCurrent]=\"control.controlConfig.minCurrent\"\r\n [maxCurrent]=\"control.controlConfig.maxCurrent\" \r\n (rangeChange)=\"onFilterSlicerChange($event)\"\r\n >\r\n </yw-base-slicer>\r\n }\r\n @if (control.controlConfig.dataType === 'number') { \r\n <yw-base-slicer [idComponent]=\"control.idComponent\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [label]=\"control.configWidget.label\"\r\n [min]=\"control.controlConfig.min\"\r\n [max]=\"control.controlConfig.max\"\r\n [minCurrent]=\"control.controlConfig.minCurrent\"\r\n [maxCurrent]=\"control.controlConfig.maxCurrent\"\r\n [step]=\"control.controlConfig.step\"\r\n (rangeChange)=\"onFilterSlicerChange($event)\"\r\n >\r\n </yw-base-slicer>\r\n }\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER BUTTON TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterbutton let-control = \"control\"> \r\n <yw-button-slicer [idComponent]=\"control.idComponent\" \r\n [label]=\"control.configWidget.label\"\r\n [options]=\"control.controlConfig.options\"\r\n [allowMultiple]=\"control.controlConfig.allowMultiple\"\r\n [currentIds]=\"control.controlConfig.currentIds\"\r\n (selectionChange)=\"onFilterButtonChange($event)\" \r\n >\r\n </yw-button-slicer>\r\n</ng-template>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER LIST TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterlist let-control = \"control\"> \r\n \r\n @if (control.controlConfig.dataType === 'date') { \r\n <yw-list-slicer [idComponent]=\"control.idComponent\" \r\n [label]=\"control.configWidget.label\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [minDate]=\"control.controlConfig.minDate\"\r\n [maxDate]=\"control.controlConfig.maxDate\"\r\n [dateHierarchyType]=\"control.controlConfig.dateHierarchyType\"\r\n [currentSelectedId]=\"control.controlConfig.currentSelectedId\"\r\n (selectionChange)=\"onFilterListChange($event)\"\r\n (filterValueChange)=\"onFilterListCalculated($event)\" \r\n >\r\n </yw-list-slicer>\r\n }\r\n\r\n\r\n @if (control.controlConfig.dataType === 'text') { \r\n <yw-list-slicer [idComponent]=\"control.idComponent\"\r\n [label]=\"control.configWidget.label\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [rawData]=\"control.controlConfig.rawData\"\r\n [currentSelectedId]=\"control.controlConfig.currentSelectedId\"\r\n (selectionChange)=\"onFilterListChange($event)\"\r\n (filterValueChange)=\"onFilterListCalculated($event)\" \r\n >\r\n </yw-list-slicer>\r\n }\r\n\r\n\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;width:100%;box-sizing:border-box;background-color:var(--widget-bg, #ffffff);border:1px solid var(--widget-border-color, #040404);border-radius:var(--widget-border-radius, 8px);padding:var(--widget-padding, 10px)}:host *,:host *:before,:host *:after{box-sizing:border-box}.widget-filter-action-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%}.widget-filter-content-wrapper{width:100%;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: YwEmptyVisualComponent, selector: "yw-empty-visual", inputs: ["idComponent", "config"] }, { kind: "component", type: YwBaseSlicerComponent, selector: "yw-base-slicer", inputs: ["idComponent", "dataType", "label", "min", "max", "step", "minCurrent", "maxCurrent"], outputs: ["rangeChange"] }, { kind: "component", type: YwButtonSlicerComponent, selector: "yw-button-slicer", inputs: ["idComponent", "label", "options", "allowMultiple", "currentIds"], outputs: ["selectionChange"] }, { kind: "component", type: YwListSlicerComponent, selector: "yw-list-slicer", inputs: ["idComponent", "label", "clearTitleLabel", "rawData", "dataType", "minDate", "maxDate", "dateHierarchyType", "monthNames", "currentSelectedId"], outputs: ["selectionChange", "filterValueChange"] }] }); }
|
|
3479
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwDashboardWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3480
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwDashboardWidgetComponent, isStandalone: true, selector: "yw-dashboard-widget", inputs: { styleWidget: { classPropertyName: "styleWidget", publicName: "styleWidget", isSignal: true, isRequired: false, transformFunction: null }, configWidget: { classPropertyName: "configWidget", publicName: "configWidget", isSignal: false, isRequired: false, transformFunction: null }, controlConfig: { classPropertyName: "controlConfig", publicName: "controlConfig", isSignal: false, isRequired: false, transformFunction: null }, controlData: { classPropertyName: "controlData", publicName: "controlData", isSignal: false, isRequired: false, transformFunction: null }, isLocked: { classPropertyName: "isLocked", publicName: "isLocked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isLocked: "isLockedChange", eventDeleteRequest: "eventDeleteRequest", eventLockToggleRequest: "eventLockToggleRequest", eventMaximizeToggleRequest: "eventMaximizeToggleRequest", eventShowConfigFormRequest: "eventShowConfigFormRequest" }, host: { properties: { "style.--widget-bg": "instanceStyleWidget().widgetBackgroundColor", "style.--widget-border-color": "instanceStyleWidget().widgetBorderColor" } }, usesOnChanges: true, ngImport: i0, template: "\r\n<!-- <div class=\"widget-action-bar\"> \r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-action\" (click)=\"onLockClick()\">{{ isLocked() ? '\uD83D\uDD12' : '\uD83D\uDD13' }}</button>\r\n <button class=\"btn-action\" (click)=\"onMaximizeClick()\">{{ isMaximized() ? '\uD83D\uDDD7' : '\uD83D\uDDD6' }}</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\">\uD83D\uDDD1\uFE0F</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\">\u2699\uFE0F</button>\r\n</div> -->\r\n\r\n<div class=\"widget-action-bar\">\r\n <!-- Bot\u00F3n Bloquear / Desbloquear -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-action\" (click)=\"onLockClick()\" [title]=\"isLocked() ? 'Desbloquear' : 'Bloquear'\">\r\n <svg *ngIf=\"isLocked(); else unlockedIcon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path></svg>\r\n <ng-template #unlockedIcon>\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect><path d=\"M7 11V7a5 5 0 0 1 9.9-1\"></path></svg>\r\n </ng-template>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Maximizar / Restaurar -->\r\n <button class=\"btn-action\" (click)=\"onMaximizeClick()\" [title]=\"isMaximized() ? 'Restaurar' : 'Maximizar'\">\r\n <svg *ngIf=\"isMaximized(); else maxIcon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3\"></path></svg>\r\n <ng-template #maxIcon>\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7\"></path></svg>\r\n </ng-template>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Eliminar -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\" title=\"Eliminar\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"></polyline><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"></path></svg>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Configuraci\u00F3n -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\" title=\"Configurar\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"></circle><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z\"></path></svg>\r\n </button>\r\n</div>\r\n\r\n<div class=\"widget-content-wrapper\">\r\n @if ( typeComponent == 'dummy' ) {\r\n <ng-container *ngTemplateOutlet=\"testdummy; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'empty-visual' ) {\r\n <ng-container *ngTemplateOutlet=\"emptyvisual; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-bar' ) {\r\n <ng-container *ngTemplateOutlet=\"chartbar; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-line' ) {\r\n <ng-container *ngTemplateOutlet=\"chartline; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-doughnut' ) {\r\n <ng-container *ngTemplateOutlet=\"chartdoughnut; context: { control: dataWidget }\"></ng-container>\r\n } \r\n @if ( typeComponent == 'chart-gauge' ) {\r\n <ng-container *ngTemplateOutlet=\"chartgauge; context: { control: dataWidget }\"></ng-container>\r\n } \r\n @if ( typeComponent == 'chart-bubble' ) {\r\n <ng-container *ngTemplateOutlet=\"chartbubble; context: { control: dataWidget }\"></ng-container>\r\n } \r\n \r\n \r\n</div>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- DUMMY TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #testdummy let-control = \"control\">\r\n <lib-test-chart [idComponent]=\"control.idComponent\" > \r\n </lib-test-chart>\r\n</ng-template>\r\n<!--------------------------------------------------------------->\r\n<!---------------------- EMPTY VISUAL TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #emptyvisual let-control = \"control\">\r\n <yw-empty-visual [idComponent]=\"control.idComponent\"\r\n [config]=\"control.controlConfig\" \r\n > \r\n </yw-empty-visual>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- BAR CHART TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartbar let-control = \"control\">\r\n <yw-bar-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-bar-chart>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE CHART TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartline let-control = \"control\">\r\n <yw-line-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-line-chart>\r\n</ng-template>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE DOUGHNUT TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartdoughnut let-control = \"control\">\r\n <yw-pie-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-pie-chart>\r\n</ng-template>\r\n\r\n \r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE GAUGE TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartgauge let-control = \"control\">\r\n <yw-gauge-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-gauge-chart>\r\n</ng-template>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- BUBBLE TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartbubble let-control=\"control\">\r\n \r\n <yw-bubble-chart \r\n [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\">\r\n </yw-bubble-chart>\r\n</ng-template> ", styles: ["@charset \"UTF-8\";:host{display:block;flex-direction:column;width:100%;overflow:hidden;box-sizing:border-box;background-color:var(--widget-bg, #ffffff);border:1px solid var(--widget-border-color, #007bff)}:host *,:host *:before,:host *:after{box-sizing:border-box}.widget-action-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%}.widget-content-wrapper{width:100%;flex-grow:1;height:0;display:flex;flex-direction:column}.widget-action-bar button,.widget-action-bar .btn-action,.widget-action-bar .btn-delete,.widget-action-bar .btn-config{background:transparent;border:1px solid #d9d9d9;border-radius:4px;cursor:pointer;width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;color:#595959;padding:0;transition:all .2s ease}.widget-action-bar button svg,.widget-action-bar .btn-action svg,.widget-action-bar .btn-delete svg,.widget-action-bar .btn-config svg{width:14px;height:14px}.widget-action-bar button:hover,.widget-action-bar .btn-action:hover,.widget-action-bar .btn-delete:hover,.widget-action-bar .btn-config:hover{background-color:#f5f5f5;color:#262626;border-color:#bfbfbf}.widget-action-bar button:active,.widget-action-bar .btn-action:active,.widget-action-bar .btn-delete:active,.widget-action-bar .btn-config:active{background-color:#e6e6e6}.widget-action-bar .btn-delete:hover{background-color:#fff1f0;color:#ff4d4f;border-color:#ffa39e}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TestChartComponent, selector: "lib-test-chart", inputs: ["idComponent"] }, { kind: "component", type: YwEmptyVisualComponent, selector: "yw-empty-visual", inputs: ["idComponent", "config"] }, { kind: "component", type: LineChartComponent, selector: "yw-line-chart", inputs: ["chartData", "config", "idComponent"] }, { kind: "component", type: BarChartComponent, selector: "yw-bar-chart", inputs: ["chartData", "config", "idComponent"] }, { kind: "component", type: PieChartComponent, selector: "yw-pie-chart", inputs: ["idComponent", "chartData", "config"] }, { kind: "component", type: GaugeChartComponent, selector: "yw-gauge-chart", inputs: ["idComponent", "chartData", "config"] }, { kind: "component", type: BubbleChartComponent, selector: "yw-bubble-chart", inputs: ["chartData", "config", "idComponent"] }] }); }
|
|
3571
3481
|
}
|
|
3572
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
3482
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwDashboardWidgetComponent, decorators: [{
|
|
3573
3483
|
type: Component,
|
|
3574
|
-
args: [{ selector: 'yw-dashboard-
|
|
3484
|
+
args: [{ selector: 'yw-dashboard-widget', standalone: true, imports: [CommonModule,
|
|
3485
|
+
TestChartComponent,
|
|
3575
3486
|
YwEmptyVisualComponent,
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3487
|
+
LineChartComponent,
|
|
3488
|
+
BarChartComponent,
|
|
3489
|
+
PieChartComponent,
|
|
3490
|
+
GaugeChartComponent, BubbleChartComponent], host: {
|
|
3491
|
+
'[style.--widget-bg]': 'instanceStyleWidget().widgetBackgroundColor',
|
|
3492
|
+
'[style.--widget-border-color]': 'instanceStyleWidget().widgetBorderColor'
|
|
3493
|
+
}, template: "\r\n<!-- <div class=\"widget-action-bar\"> \r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-action\" (click)=\"onLockClick()\">{{ isLocked() ? '\uD83D\uDD12' : '\uD83D\uDD13' }}</button>\r\n <button class=\"btn-action\" (click)=\"onMaximizeClick()\">{{ isMaximized() ? '\uD83D\uDDD7' : '\uD83D\uDDD6' }}</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\">\uD83D\uDDD1\uFE0F</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\">\u2699\uFE0F</button>\r\n</div> -->\r\n\r\n<div class=\"widget-action-bar\">\r\n <!-- Bot\u00F3n Bloquear / Desbloquear -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-action\" (click)=\"onLockClick()\" [title]=\"isLocked() ? 'Desbloquear' : 'Bloquear'\">\r\n <svg *ngIf=\"isLocked(); else unlockedIcon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path></svg>\r\n <ng-template #unlockedIcon>\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect><path d=\"M7 11V7a5 5 0 0 1 9.9-1\"></path></svg>\r\n </ng-template>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Maximizar / Restaurar -->\r\n <button class=\"btn-action\" (click)=\"onMaximizeClick()\" [title]=\"isMaximized() ? 'Restaurar' : 'Maximizar'\">\r\n <svg *ngIf=\"isMaximized(); else maxIcon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3\"></path></svg>\r\n <ng-template #maxIcon>\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7\"></path></svg>\r\n </ng-template>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Eliminar -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\" title=\"Eliminar\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"></polyline><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"></path></svg>\r\n </button>\r\n\r\n <!-- Bot\u00F3n Configuraci\u00F3n -->\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\" title=\"Configurar\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"></circle><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z\"></path></svg>\r\n </button>\r\n</div>\r\n\r\n<div class=\"widget-content-wrapper\">\r\n @if ( typeComponent == 'dummy' ) {\r\n <ng-container *ngTemplateOutlet=\"testdummy; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'empty-visual' ) {\r\n <ng-container *ngTemplateOutlet=\"emptyvisual; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-bar' ) {\r\n <ng-container *ngTemplateOutlet=\"chartbar; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-line' ) {\r\n <ng-container *ngTemplateOutlet=\"chartline; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'chart-doughnut' ) {\r\n <ng-container *ngTemplateOutlet=\"chartdoughnut; context: { control: dataWidget }\"></ng-container>\r\n } \r\n @if ( typeComponent == 'chart-gauge' ) {\r\n <ng-container *ngTemplateOutlet=\"chartgauge; context: { control: dataWidget }\"></ng-container>\r\n } \r\n @if ( typeComponent == 'chart-bubble' ) {\r\n <ng-container *ngTemplateOutlet=\"chartbubble; context: { control: dataWidget }\"></ng-container>\r\n } \r\n \r\n \r\n</div>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- DUMMY TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #testdummy let-control = \"control\">\r\n <lib-test-chart [idComponent]=\"control.idComponent\" > \r\n </lib-test-chart>\r\n</ng-template>\r\n<!--------------------------------------------------------------->\r\n<!---------------------- EMPTY VISUAL TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #emptyvisual let-control = \"control\">\r\n <yw-empty-visual [idComponent]=\"control.idComponent\"\r\n [config]=\"control.controlConfig\" \r\n > \r\n </yw-empty-visual>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- BAR CHART TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartbar let-control = \"control\">\r\n <yw-bar-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-bar-chart>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE CHART TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartline let-control = \"control\">\r\n <yw-line-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-line-chart>\r\n</ng-template>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE DOUGHNUT TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartdoughnut let-control = \"control\">\r\n <yw-pie-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-pie-chart>\r\n</ng-template>\r\n\r\n \r\n<!--------------------------------------------------------------->\r\n<!---------------------- LINE GAUGE TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartgauge let-control = \"control\">\r\n <yw-gauge-chart [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\" \r\n >\r\n </yw-gauge-chart>\r\n</ng-template>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- BUBBLE TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #chartbubble let-control=\"control\">\r\n \r\n <yw-bubble-chart \r\n [idComponent]=\"control.idComponent\"\r\n [chartData]=\"control.controlData\"\r\n [config]=\"control.controlConfig\">\r\n </yw-bubble-chart>\r\n</ng-template> ", styles: ["@charset \"UTF-8\";:host{display:block;flex-direction:column;width:100%;overflow:hidden;box-sizing:border-box;background-color:var(--widget-bg, #ffffff);border:1px solid var(--widget-border-color, #007bff)}:host *,:host *:before,:host *:after{box-sizing:border-box}.widget-action-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%}.widget-content-wrapper{width:100%;flex-grow:1;height:0;display:flex;flex-direction:column}.widget-action-bar button,.widget-action-bar .btn-action,.widget-action-bar .btn-delete,.widget-action-bar .btn-config{background:transparent;border:1px solid #d9d9d9;border-radius:4px;cursor:pointer;width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;color:#595959;padding:0;transition:all .2s ease}.widget-action-bar button svg,.widget-action-bar .btn-action svg,.widget-action-bar .btn-delete svg,.widget-action-bar .btn-config svg{width:14px;height:14px}.widget-action-bar button:hover,.widget-action-bar .btn-action:hover,.widget-action-bar .btn-delete:hover,.widget-action-bar .btn-config:hover{background-color:#f5f5f5;color:#262626;border-color:#bfbfbf}.widget-action-bar button:active,.widget-action-bar .btn-action:active,.widget-action-bar .btn-delete:active,.widget-action-bar .btn-config:active{background-color:#e6e6e6}.widget-action-bar .btn-delete:hover{background-color:#fff1f0;color:#ff4d4f;border-color:#ffa39e}\n"] }]
|
|
3494
|
+
}], ctorParameters: () => [], propDecorators: { styleWidget: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleWidget", required: false }] }], configWidget: [{
|
|
3581
3495
|
type: Input
|
|
3582
|
-
}], controlConfig: [{
|
|
3496
|
+
}], controlConfig: [{
|
|
3583
3497
|
type: Input
|
|
3584
|
-
}],
|
|
3498
|
+
}], controlData: [{
|
|
3499
|
+
type: Input
|
|
3500
|
+
}], isLocked: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLocked", required: false }] }, { type: i0.Output, args: ["isLockedChange"] }], eventDeleteRequest: [{ type: i0.Output, args: ["eventDeleteRequest"] }], eventLockToggleRequest: [{ type: i0.Output, args: ["eventLockToggleRequest"] }], eventMaximizeToggleRequest: [{ type: i0.Output, args: ["eventMaximizeToggleRequest"] }], eventShowConfigFormRequest: [{ type: i0.Output, args: ["eventShowConfigFormRequest"] }] } });
|
|
3585
3501
|
|
|
3586
|
-
class
|
|
3502
|
+
class YwBaseSlicerComponent {
|
|
3587
3503
|
constructor() {
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
};
|
|
3593
|
-
this.
|
|
3594
|
-
this.
|
|
3595
|
-
this.
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
this.
|
|
3599
|
-
this.
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
});
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
if (prmTableName.localeCompare(curTableRef.tableName) == 0) {
|
|
3619
|
-
dataresponse = curTableRef.tableData;
|
|
3504
|
+
// Inputs de configuración del rango de fechas
|
|
3505
|
+
this.idComponent = '';
|
|
3506
|
+
this.dataType = 'date';
|
|
3507
|
+
this.label = input('Fecha', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3508
|
+
this.min = input(...(ngDevMode ? [undefined, { debugName: "min" }] : []));
|
|
3509
|
+
this.max = input(...(ngDevMode ? [undefined, { debugName: "max" }] : []));
|
|
3510
|
+
this.step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : []));
|
|
3511
|
+
this.minCurrent = input(...(ngDevMode ? [undefined, { debugName: "minCurrent" }] : []));
|
|
3512
|
+
this.maxCurrent = input(...(ngDevMode ? [undefined, { debugName: "maxCurrent" }] : []));
|
|
3513
|
+
this.minNumber = 0;
|
|
3514
|
+
this.maxNumber = 1000;
|
|
3515
|
+
this.minDate = '2020-01-01';
|
|
3516
|
+
this.maxDate = '2022-12-31';
|
|
3517
|
+
// Evento de salida
|
|
3518
|
+
this.rangeChange = output();
|
|
3519
|
+
// Signals para las fechas seleccionadas
|
|
3520
|
+
this.startDate = signal('2020-01-01', ...(ngDevMode ? [{ debugName: "startDate" }] : []));
|
|
3521
|
+
this.endDate = signal('2022-09-22', ...(ngDevMode ? [{ debugName: "endDate" }] : []));
|
|
3522
|
+
// Signals para los numeros seleccionadas
|
|
3523
|
+
this.startVal = signal(0, ...(ngDevMode ? [{ debugName: "startVal" }] : []));
|
|
3524
|
+
this.endVal = signal(1000, ...(ngDevMode ? [{ debugName: "endVal" }] : []));
|
|
3525
|
+
this.minTimestamp = computed(() => new Date(this.minDate).getTime(), ...(ngDevMode ? [{ debugName: "minTimestamp" }] : []));
|
|
3526
|
+
this.maxTimestamp = computed(() => new Date(this.maxDate).getTime(), ...(ngDevMode ? [{ debugName: "maxTimestamp" }] : []));
|
|
3527
|
+
this.startTimestamp = computed(() => new Date(this.startDate()).getTime(), ...(ngDevMode ? [{ debugName: "startTimestamp" }] : []));
|
|
3528
|
+
this.endTimestamp = computed(() => new Date(this.endDate()).getTime(), ...(ngDevMode ? [{ debugName: "endTimestamp" }] : []));
|
|
3529
|
+
// Inicializar valores al arrancar
|
|
3530
|
+
effect(() => {
|
|
3531
|
+
if (this.dataType == 'date') {
|
|
3532
|
+
this.startDate.set(this.minCurrent() || this.minDate);
|
|
3533
|
+
this.endDate.set(this.maxCurrent() || this.maxDate);
|
|
3620
3534
|
}
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
onFilterChange(eventData) {
|
|
3625
|
-
this.filterSelectionChange.emit({ widgetId: eventData.widgetId, eventResponse: eventData.eventResponse });
|
|
3626
|
-
}
|
|
3627
|
-
fnSetControlFilterCurrentValues(prmControlConfig) {
|
|
3628
|
-
if (prmControlConfig.typeComponent == 'filter-slicer') {
|
|
3629
|
-
let curConfigComponent = prmControlConfig.configComponent;
|
|
3630
|
-
if (prmControlConfig.configComponent.dataType == 'date') {
|
|
3631
|
-
curConfigComponent.minCurrent = prmControlConfig.controlFilterData['startDate'];
|
|
3632
|
-
curConfigComponent.maxCurrent = prmControlConfig.controlFilterData['endDate'];
|
|
3535
|
+
if (this.dataType == 'number') {
|
|
3536
|
+
this.startVal.set(this.minCurrent() || this.minNumber);
|
|
3537
|
+
this.endVal.set(this.maxCurrent() || this.maxNumber);
|
|
3633
3538
|
}
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3539
|
+
}, { allowSignalWrites: true });
|
|
3540
|
+
// Notificar al padre cada vez que cambien los valores
|
|
3541
|
+
effect(() => {
|
|
3542
|
+
if (this.dataType == 'date') {
|
|
3543
|
+
this.rangeChange.emit({
|
|
3544
|
+
startDate: this.startDate(),
|
|
3545
|
+
endDate: this.endDate()
|
|
3546
|
+
});
|
|
3637
3547
|
}
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
return curConfigComponent;
|
|
3644
|
-
}
|
|
3645
|
-
if (prmControlConfig.typeComponent == 'filter-list') {
|
|
3646
|
-
let curConfigComponent = prmControlConfig.configComponent;
|
|
3647
|
-
curConfigComponent.currentSelectedId = prmControlConfig.controlFilterData['currentNodeId'];
|
|
3648
|
-
return curConfigComponent;
|
|
3649
|
-
}
|
|
3650
|
-
}
|
|
3651
|
-
handleClearFilter() {
|
|
3652
|
-
this.controlListConfig = [];
|
|
3653
|
-
this.dashboardFilterConfig.controlListConfig.forEach((item) => {
|
|
3654
|
-
const tableName = item.controlTable;
|
|
3655
|
-
const prmcontrolData = this.fn_getDataForWidgetFilterComponent(tableName, this.dashboardData);
|
|
3656
|
-
const prmconfigWidget = { ...item };
|
|
3657
|
-
if (item.controlFilterData) {
|
|
3658
|
-
item.configComponent = this.fnSetControlFilterClearValues(prmconfigWidget);
|
|
3548
|
+
if (this.dataType == 'number') {
|
|
3549
|
+
this.rangeChange.emit({
|
|
3550
|
+
minValue: this.startVal(),
|
|
3551
|
+
maxValue: this.endVal()
|
|
3552
|
+
});
|
|
3659
3553
|
}
|
|
3660
|
-
const configControl = { configWidget: prmconfigWidget,
|
|
3661
|
-
controlData: prmcontrolData,
|
|
3662
|
-
controlConfig: item.configComponent
|
|
3663
|
-
};
|
|
3664
|
-
this.controlListConfig.push(configControl);
|
|
3665
3554
|
});
|
|
3666
3555
|
}
|
|
3667
|
-
|
|
3668
|
-
if (
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
let curConfigComponent = prmControlConfig.configComponent;
|
|
3676
|
-
curConfigComponent.currentIds = [];
|
|
3677
|
-
return curConfigComponent;
|
|
3556
|
+
ngOnInit() {
|
|
3557
|
+
if (this.dataType == 'date') {
|
|
3558
|
+
this.minDate = this.min();
|
|
3559
|
+
this.maxDate = this.max();
|
|
3560
|
+
this.minTimestamp = computed(() => new Date(this.minDate).getTime(), ...(ngDevMode ? [{ debugName: "minTimestamp" }] : []));
|
|
3561
|
+
this.maxTimestamp = computed(() => new Date(this.maxDate).getTime(), ...(ngDevMode ? [{ debugName: "maxTimestamp" }] : []));
|
|
3562
|
+
this.startTimestamp = computed(() => new Date(this.startDate()).getTime(), ...(ngDevMode ? [{ debugName: "startTimestamp" }] : []));
|
|
3563
|
+
this.endTimestamp = computed(() => new Date(this.endDate()).getTime(), ...(ngDevMode ? [{ debugName: "endTimestamp" }] : []));
|
|
3678
3564
|
}
|
|
3679
|
-
if (
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
return curConfigComponent;
|
|
3565
|
+
if (this.dataType == 'number') {
|
|
3566
|
+
this.minNumber = this.min();
|
|
3567
|
+
this.maxNumber = this.max();
|
|
3683
3568
|
}
|
|
3684
3569
|
}
|
|
3685
|
-
|
|
3686
|
-
|
|
3570
|
+
// Handlers para la entrada manual de fechas
|
|
3571
|
+
onStartDateInput(value) {
|
|
3572
|
+
if (value && value <= this.endDate()) {
|
|
3573
|
+
this.startDate.set(value);
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
onEndDateInput(value) {
|
|
3577
|
+
if (value && value >= this.startDate()) {
|
|
3578
|
+
this.endDate.set(value);
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
// Métodos para cambiar desde el Input Numérico
|
|
3582
|
+
onStartInput(event) {
|
|
3583
|
+
const value = Number(event.target.value);
|
|
3584
|
+
if (!isNaN(value) && value <= this.endVal() && value >= this.min()) {
|
|
3585
|
+
this.startVal.set(value);
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
onEndInput(event) {
|
|
3589
|
+
const value = Number(event.target.value);
|
|
3590
|
+
if (!isNaN(value) && value >= this.startVal() && value <= this.max()) {
|
|
3591
|
+
this.endVal.set(value);
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
// Handlers para el movimiento del slider
|
|
3595
|
+
onStartSliderChange(event) {
|
|
3596
|
+
if (this.dataType == 'date') {
|
|
3597
|
+
const val = Number(event.target.value);
|
|
3598
|
+
const dateStr = new Date(val).toISOString().split('T')[0];
|
|
3599
|
+
if (val < this.endTimestamp()) {
|
|
3600
|
+
this.startDate.set(dateStr);
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3603
|
+
if (this.dataType == 'number') {
|
|
3604
|
+
const val = Number(event.target.value);
|
|
3605
|
+
if (val < this.endVal()) {
|
|
3606
|
+
this.startVal.set(val);
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
onEndSliderChange(event) {
|
|
3611
|
+
if (this.dataType == 'date') {
|
|
3612
|
+
const val = Number(event.target.value);
|
|
3613
|
+
const dateStr = new Date(val).toISOString().split('T')[0];
|
|
3614
|
+
if (val > this.startTimestamp()) {
|
|
3615
|
+
this.endDate.set(dateStr);
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
if (this.dataType == 'number') {
|
|
3619
|
+
const val = Number(event.target.value);
|
|
3620
|
+
if (val > this.startVal()) {
|
|
3621
|
+
this.endVal.set(val);
|
|
3622
|
+
}
|
|
3623
|
+
}
|
|
3624
|
+
}
|
|
3625
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwBaseSlicerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3626
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwBaseSlicerComponent, isStandalone: true, selector: "yw-base-slicer", inputs: { idComponent: { classPropertyName: "idComponent", publicName: "idComponent", isSignal: false, isRequired: false, transformFunction: null }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: false, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, minCurrent: { classPropertyName: "minCurrent", publicName: "minCurrent", isSignal: true, isRequired: false, transformFunction: null }, maxCurrent: { classPropertyName: "maxCurrent", publicName: "maxCurrent", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rangeChange: "rangeChange" }, host: { properties: { "attr.id": "idComponent" } }, ngImport: i0, template: "<div class=\"filter-container\">\r\n <label class=\"filter-label\">{{ label() }}</label>\r\n\r\n <!-- Inputs de fecha superiores -->\r\n <div class=\"date-inputs-row\">\r\n <div class=\"input-wrapper\">\r\n @if (dataType === 'date') { \r\n <input \r\n type=\"date\" \r\n [value]=\"startDate()\"\r\n [min]=\"minDate\"\r\n [max]=\"endDate()\"\r\n (change)=\"onStartDateInput($any($event.target).value)\" \r\n />\r\n }\r\n @if (dataType === 'number') { \r\n <input \r\n type=\"number\" \r\n [value]=\"startVal()\"\r\n [min]=\"minNumber\"\r\n [max]=\"endVal()\"\r\n [step]=\"step()\"\r\n (input)=\"onStartInput($event)\" \r\n />\r\n } \r\n </div>\r\n\r\n <div class=\"input-wrapper\">\r\n @if (dataType === 'date') { \r\n <input \r\n type=\"date\" \r\n [value]=\"endDate()\"\r\n [min]=\"startDate()\"\r\n [max]=\"maxDate\"\r\n (change)=\"onEndDateInput($any($event.target).value)\" \r\n />\r\n }\r\n @if (dataType === 'number') { \r\n <input \r\n type=\"number\" \r\n [value]=\"endVal()\"\r\n [min]=\"startVal()\"\r\n [max]=\"maxNumber\"\r\n [step]=\"step()\"\r\n (input)=\"onEndInput($event)\" \r\n />\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Dual Slider personalizado -->\r\n <div class=\"slider-container\">\r\n <div class=\"slider-track\"></div>\r\n @if (dataType === 'date') { \r\n <!-- Slider Inicio -->\r\n <input \r\n type=\"range\" \r\n [min]=\"minTimestamp()\" \r\n [max]=\"maxTimestamp()\" \r\n [value]=\"startTimestamp()\"\r\n (input)=\"onStartSliderChange($event)\"\r\n class=\"thumb thumb-left\"\r\n />\r\n\r\n <!-- Slider Fin -->\r\n <input \r\n type=\"range\" \r\n [min]=\"minTimestamp()\" \r\n [max]=\"maxTimestamp()\" \r\n [value]=\"endTimestamp()\"\r\n (input)=\"onEndSliderChange($event)\"\r\n class=\"thumb thumb-right\"\r\n />\r\n }\r\n\r\n @if (dataType === 'number') { \r\n\r\n <input \r\n type=\"range\" \r\n [min]=\"minNumber\" \r\n [max]=\"maxNumber\" \r\n [step]=\"step()\"\r\n [value]=\"startVal()\"\r\n (input)=\"onStartSliderChange($event)\"\r\n class=\"thumb thumb-left\"\r\n />\r\n\r\n <!-- Slider M\u00E1ximo -->\r\n <input \r\n type=\"range\" \r\n [min]=\"minNumber\" \r\n [max]=\"maxNumber\" \r\n [step]=\"step()\"\r\n [value]=\"endVal()\"\r\n (input)=\"onEndSliderChange($event)\"\r\n class=\"thumb thumb-right\"\r\n />\r\n\r\n }\r\n\r\n </div>\r\n</div>", styles: ["@charset \"UTF-8\";:host{display:block;font-family:Arial,Helvetica,sans-serif;width:100%;max-width:360px}.filter-container{display:flex;flex-direction:column;gap:8px}.filter-label{font-size:13px;font-weight:600;color:#333}.date-inputs-row,.number-inputs-row{display:flex;gap:8px}.input-wrapper input[type=date]{border:1px solid #e2e8f0;border-radius:2px;padding:4px 8px;font-size:13px;color:#333;outline:none;background-color:#fff;box-shadow:0 1px 2px #0000000d}.input-wrapper input[type=date]:focus{border-color:#a0aec0}.input-wrapper input[type=number]{border:1px solid #e2e8f0;border-radius:2px;padding:4px 8px;font-size:13px;color:#333;width:90px;outline:none;background-color:#fff;box-shadow:0 1px 2px #0000000d}.input-wrapper input[type=number]:focus{border-color:#a0aec0}.slider-container{position:relative;width:100%;height:30px;display:flex;align-items:center;margin-top:4px}.slider-track{position:absolute;width:100%;height:2px;background-color:#666;border-radius:1px;z-index:1}.thumb{position:absolute;width:100%;appearance:none;-webkit-appearance:none;background:none;pointer-events:none;outline:none;margin:0;z-index:2}.thumb-right{z-index:3}.thumb::-webkit-slider-thumb{appearance:none;-webkit-appearance:none;pointer-events:auto;width:22px;height:22px;border-radius:50%;background:#fff;border:3px solid #666666;cursor:pointer;box-sizing:border-box;transition:transform .1s ease}.thumb::-webkit-slider-thumb:hover{transform:scale(1.1);border-color:#333}.thumb::-moz-range-thumb{pointer-events:auto;width:22px;height:22px;border-radius:50%;background:#fff;border:3px solid #666666;cursor:pointer;box-sizing:border-box}\n"] }); }
|
|
3687
3627
|
}
|
|
3688
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
3628
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwBaseSlicerComponent, decorators: [{
|
|
3689
3629
|
type: Component,
|
|
3690
|
-
args: [{ selector: 'yw-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
], template: "\r\n <div class=\"dashboard-filter-content-bar\">\r\n @if ( dashboardFilterConfig.showConfigButtons ) { \r\n <button nz-button nzType=\"primary\" >\r\n <span nz-icon nz-type=\"plus\"></span> A\u00F1adir widget\r\n </button>\r\n }\r\n <button nz-button \r\n nzType=\"default\" \r\n nzShape=\"circle\" \r\n (click)=\"handleClearFilter()\" \r\n class=\"btn-clean\" \r\n > \r\n <!-- Icono de Borrador (Eraser) activo / relleno --> \r\n <svg \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M16.24 3.56a2.12 2.12 0 0 1 3 0l1.2 1.2a2.12 2.12 0 0 1 0 3l-8.5 8.5H6.5a1.5 1.5 0 0 1-1.5-1.5v-5.44l11.24-11.24zM19 19H5a1 1 0 0 1 0-2h14a1 1 0 0 1 0 2z\"/>\r\n </svg>\r\n \r\n </button>\r\n </div>\r\n\r\n <div class=\"dashboard-filter-content-wrapper\">\r\n @for ( colFilter of controlListConfig; track colFilter) { \r\n <div class=\"dashboard-filter-content-wrapper-item\">\r\n \r\n <yw-dashboard-filter-widget \r\n [configWidget]=\"colFilter.configWidget\"\r\n [controlConfig]=\"colFilter.controlConfig\"\r\n [controlData]=\"colFilter.controlData\"\r\n (selectionChange)=\"onFilterChange($event)\"\r\n > \r\n </yw-dashboard-filter-widget>\r\n\r\n </div>\r\n }\r\n </div>", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden;box-sizing:border-box}.dashboard-filter-content-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%;box-sizing:border-box}.dashboard-filter-content-wrapper{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;width:100%;display:flex;flex-direction:column;box-sizing:border-box}.dashboard-filter-content-wrapper-item{padding-bottom:5px}.btn-clean{display:inline-flex;align-items:center;justify-content:center;padding:0;width:32px;height:32px;border-radius:50%;transition:all .3s ease}.btn-clean.active{color:#fff;background-color:#1890ff;border-color:#1890ff}.btn-clean.active:hover{background-color:#40a9ff;border-color:#40a9ff}\n"] }]
|
|
3695
|
-
}], ctorParameters: () => [], propDecorators: { dashboardFilterConfig: [{
|
|
3630
|
+
args: [{ selector: 'yw-base-slicer', imports: [], host: {
|
|
3631
|
+
'[attr.id]': 'idComponent' // Vincula el atributo id al valor de la propiedad
|
|
3632
|
+
}, template: "<div class=\"filter-container\">\r\n <label class=\"filter-label\">{{ label() }}</label>\r\n\r\n <!-- Inputs de fecha superiores -->\r\n <div class=\"date-inputs-row\">\r\n <div class=\"input-wrapper\">\r\n @if (dataType === 'date') { \r\n <input \r\n type=\"date\" \r\n [value]=\"startDate()\"\r\n [min]=\"minDate\"\r\n [max]=\"endDate()\"\r\n (change)=\"onStartDateInput($any($event.target).value)\" \r\n />\r\n }\r\n @if (dataType === 'number') { \r\n <input \r\n type=\"number\" \r\n [value]=\"startVal()\"\r\n [min]=\"minNumber\"\r\n [max]=\"endVal()\"\r\n [step]=\"step()\"\r\n (input)=\"onStartInput($event)\" \r\n />\r\n } \r\n </div>\r\n\r\n <div class=\"input-wrapper\">\r\n @if (dataType === 'date') { \r\n <input \r\n type=\"date\" \r\n [value]=\"endDate()\"\r\n [min]=\"startDate()\"\r\n [max]=\"maxDate\"\r\n (change)=\"onEndDateInput($any($event.target).value)\" \r\n />\r\n }\r\n @if (dataType === 'number') { \r\n <input \r\n type=\"number\" \r\n [value]=\"endVal()\"\r\n [min]=\"startVal()\"\r\n [max]=\"maxNumber\"\r\n [step]=\"step()\"\r\n (input)=\"onEndInput($event)\" \r\n />\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Dual Slider personalizado -->\r\n <div class=\"slider-container\">\r\n <div class=\"slider-track\"></div>\r\n @if (dataType === 'date') { \r\n <!-- Slider Inicio -->\r\n <input \r\n type=\"range\" \r\n [min]=\"minTimestamp()\" \r\n [max]=\"maxTimestamp()\" \r\n [value]=\"startTimestamp()\"\r\n (input)=\"onStartSliderChange($event)\"\r\n class=\"thumb thumb-left\"\r\n />\r\n\r\n <!-- Slider Fin -->\r\n <input \r\n type=\"range\" \r\n [min]=\"minTimestamp()\" \r\n [max]=\"maxTimestamp()\" \r\n [value]=\"endTimestamp()\"\r\n (input)=\"onEndSliderChange($event)\"\r\n class=\"thumb thumb-right\"\r\n />\r\n }\r\n\r\n @if (dataType === 'number') { \r\n\r\n <input \r\n type=\"range\" \r\n [min]=\"minNumber\" \r\n [max]=\"maxNumber\" \r\n [step]=\"step()\"\r\n [value]=\"startVal()\"\r\n (input)=\"onStartSliderChange($event)\"\r\n class=\"thumb thumb-left\"\r\n />\r\n\r\n <!-- Slider M\u00E1ximo -->\r\n <input \r\n type=\"range\" \r\n [min]=\"minNumber\" \r\n [max]=\"maxNumber\" \r\n [step]=\"step()\"\r\n [value]=\"endVal()\"\r\n (input)=\"onEndSliderChange($event)\"\r\n class=\"thumb thumb-right\"\r\n />\r\n\r\n }\r\n\r\n </div>\r\n</div>", styles: ["@charset \"UTF-8\";:host{display:block;font-family:Arial,Helvetica,sans-serif;width:100%;max-width:360px}.filter-container{display:flex;flex-direction:column;gap:8px}.filter-label{font-size:13px;font-weight:600;color:#333}.date-inputs-row,.number-inputs-row{display:flex;gap:8px}.input-wrapper input[type=date]{border:1px solid #e2e8f0;border-radius:2px;padding:4px 8px;font-size:13px;color:#333;outline:none;background-color:#fff;box-shadow:0 1px 2px #0000000d}.input-wrapper input[type=date]:focus{border-color:#a0aec0}.input-wrapper input[type=number]{border:1px solid #e2e8f0;border-radius:2px;padding:4px 8px;font-size:13px;color:#333;width:90px;outline:none;background-color:#fff;box-shadow:0 1px 2px #0000000d}.input-wrapper input[type=number]:focus{border-color:#a0aec0}.slider-container{position:relative;width:100%;height:30px;display:flex;align-items:center;margin-top:4px}.slider-track{position:absolute;width:100%;height:2px;background-color:#666;border-radius:1px;z-index:1}.thumb{position:absolute;width:100%;appearance:none;-webkit-appearance:none;background:none;pointer-events:none;outline:none;margin:0;z-index:2}.thumb-right{z-index:3}.thumb::-webkit-slider-thumb{appearance:none;-webkit-appearance:none;pointer-events:auto;width:22px;height:22px;border-radius:50%;background:#fff;border:3px solid #666666;cursor:pointer;box-sizing:border-box;transition:transform .1s ease}.thumb::-webkit-slider-thumb:hover{transform:scale(1.1);border-color:#333}.thumb::-moz-range-thumb{pointer-events:auto;width:22px;height:22px;border-radius:50%;background:#fff;border:3px solid #666666;cursor:pointer;box-sizing:border-box}\n"] }]
|
|
3633
|
+
}], ctorParameters: () => [], propDecorators: { idComponent: [{
|
|
3696
3634
|
type: Input
|
|
3697
|
-
}],
|
|
3635
|
+
}], dataType: [{
|
|
3698
3636
|
type: Input
|
|
3699
|
-
}],
|
|
3637
|
+
}], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], minCurrent: [{ type: i0.Input, args: [{ isSignal: true, alias: "minCurrent", required: false }] }], maxCurrent: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxCurrent", required: false }] }], rangeChange: [{ type: i0.Output, args: ["rangeChange"] }] } });
|
|
3700
3638
|
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3639
|
+
class YwButtonSlicerComponent {
|
|
3640
|
+
constructor() {
|
|
3641
|
+
// Configuración de entradas
|
|
3642
|
+
this.idComponent = '';
|
|
3643
|
+
this.label = input('Tipo de producto', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3644
|
+
this.options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
3645
|
+
this.allowMultiple = input(true, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : [])); // Permite cambiar a selección única si es necesario
|
|
3646
|
+
// Evento de salida con la lista de IDs seleccionados
|
|
3647
|
+
this.selectionChange = output();
|
|
3648
|
+
// Signal con los IDs seleccionados
|
|
3649
|
+
this.selectedIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedIds" }] : []));
|
|
3650
|
+
// Current IDs seleccionados
|
|
3651
|
+
this.currentIds = input([], ...(ngDevMode ? [{ debugName: "currentIds" }] : []));
|
|
3652
|
+
// Emitir el listado en Array cada vez que la Signal de selección cambie
|
|
3707
3653
|
effect(() => {
|
|
3708
|
-
|
|
3709
|
-
console.log('El estado de bloqueo cambió a:', isLocked);
|
|
3710
|
-
this.fn_lockPositionWidgets(isLocked);
|
|
3654
|
+
this.selectionChange.emit(Array.from(this.selectedIds()));
|
|
3711
3655
|
});
|
|
3712
|
-
*/
|
|
3713
|
-
this.environmentInjector = environmentInjector;
|
|
3714
|
-
this.appRef = appRef;
|
|
3715
|
-
this.widgetsActivos = new Map();
|
|
3716
|
-
this.showControls = input(false, ...(ngDevMode ? [{ debugName: "showControls" }] : []));
|
|
3717
|
-
this.showFilter = input(false, ...(ngDevMode ? [{ debugName: "showFilter" }] : []));
|
|
3718
|
-
this.allIsLocked = signal(false, ...(ngDevMode ? [{ debugName: "allIsLocked" }] : []));
|
|
3719
|
-
this.drawerfiltervisible = false;
|
|
3720
|
-
this.drawerconfigvisible = false;
|
|
3721
|
-
this.drawerCurrentWidgetObject = {};
|
|
3722
|
-
this.isLocked = false;
|
|
3723
|
-
this.countWidget = 1;
|
|
3724
|
-
this.layoutConfig = {
|
|
3725
|
-
margin: 10,
|
|
3726
|
-
cellHeight: 100,
|
|
3727
|
-
columns: 24
|
|
3728
|
-
};
|
|
3729
|
-
/* ejemplo de Items
|
|
3730
|
-
items: [
|
|
3731
|
-
{ id: 'div-1', x: 0, y: 0, w: 14, h: 2, content: 'DIV 1' , contentData : {}},
|
|
3732
|
-
{ id: 'div-2', x: 5, y: 2, w: 19, h: 1, content: 'DIV 2' , contentData : {}},
|
|
3733
|
-
{ id: 'div-3', x: 0, y: 3, w: 22, h: 1, content: 'DIV 3', contentData : {} }
|
|
3734
|
-
]
|
|
3735
|
-
*/
|
|
3736
|
-
this.dashboardStyle = {
|
|
3737
|
-
canvasBackgroundColor: "#f5f5f5",
|
|
3738
|
-
widgetBackgroundColor: "#ffffff",
|
|
3739
|
-
widgetBorderColor: "#007bff"
|
|
3740
|
-
};
|
|
3741
|
-
this.dashboardConfig = {
|
|
3742
|
-
showConfigButtons: false,
|
|
3743
|
-
lockPositionWidgets: false,
|
|
3744
|
-
layoutConfig: {
|
|
3745
|
-
margin: 0,
|
|
3746
|
-
cellHeight: 0,
|
|
3747
|
-
columns: 0
|
|
3748
|
-
},
|
|
3749
|
-
controlListConfig: []
|
|
3750
|
-
};
|
|
3751
|
-
this.dashboardData = [];
|
|
3752
|
-
this.dashboardItems = [];
|
|
3753
|
-
/* REF FILTROS */
|
|
3754
|
-
this.dashboardFilterConfig = {
|
|
3755
|
-
showConfigButtons: false,
|
|
3756
|
-
lockPositionWidgets: false,
|
|
3757
|
-
controlListConfig: []
|
|
3758
|
-
};
|
|
3759
3656
|
}
|
|
3760
3657
|
ngOnInit() {
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
}
|
|
3767
|
-
if (changes['dashboardData']) {
|
|
3768
|
-
console.log('Nuevo valor dashboardData:', this.dashboardData);
|
|
3769
|
-
//this.initCanvasGrid();
|
|
3658
|
+
if (this.currentIds() && this.currentIds().length > 0) {
|
|
3659
|
+
this.selectedIds().clear();
|
|
3660
|
+
this.currentIds().forEach((itemId) => {
|
|
3661
|
+
this.selectedIds().add(itemId);
|
|
3662
|
+
});
|
|
3770
3663
|
}
|
|
3771
3664
|
}
|
|
3772
|
-
|
|
3773
|
-
this.
|
|
3774
|
-
|
|
3775
|
-
initCanvasGrid() {
|
|
3776
|
-
this.layoutConfig = this.dashboardConfig.layoutConfig;
|
|
3777
|
-
// Opciones para restringir colisiones y comportamiento
|
|
3778
|
-
let options = {
|
|
3779
|
-
column: this.layoutConfig.columns,
|
|
3780
|
-
cellHeight: this.layoutConfig.cellHeight,
|
|
3781
|
-
margin: this.layoutConfig.margin,
|
|
3782
|
-
float: true, // Evita que los divs floten automáticamente hacia arriba
|
|
3783
|
-
//noOverlap: true, // CLAVE: Bloquea el movimiento si colisiona con otro DIV
|
|
3784
|
-
resizable: { handles: 'e, se, s, sw, w, nw, n, ne', autoHide: true } // Permite redimensionar desde todos los bordes
|
|
3785
|
-
};
|
|
3786
|
-
if (this.layoutConfig.columnOpts) {
|
|
3787
|
-
options = {
|
|
3788
|
-
column: this.layoutConfig.columns,
|
|
3789
|
-
cellHeight: this.layoutConfig.cellHeight,
|
|
3790
|
-
margin: this.layoutConfig.margin,
|
|
3791
|
-
columnOpts: {
|
|
3792
|
-
breakpointForWindow: this.layoutConfig.columnOpts.breakpointForWindow, // Mide el ancho de la ventana gráfica
|
|
3793
|
-
breakpoints: this.layoutConfig.columnOpts.breakpoints,
|
|
3794
|
-
layout: this.layoutConfig.columnOpts.layout || 'list', // Mantiene el orden de los widgets secuencialmente al colapsar
|
|
3795
|
-
},
|
|
3796
|
-
float: true, // Evita que los divs floten automáticamente hacia arriba
|
|
3797
|
-
//noOverlap: true, // CLAVE: Bloquea el movimiento si colisiona con otro DIV
|
|
3798
|
-
resizable: { handles: 'e, se, s, sw, w, nw, n, ne', autoHide: true } // Permite redimensionar desde todos los bordes
|
|
3799
|
-
};
|
|
3800
|
-
}
|
|
3801
|
-
/*EXAMPLE OF "columnOpts"
|
|
3802
|
-
columnOpts: {
|
|
3803
|
-
breakpointForWindow: true,
|
|
3804
|
-
breakpoints: [
|
|
3805
|
-
{ w: 768, c: 1 },
|
|
3806
|
-
{ w: 992, c: 6 },
|
|
3807
|
-
{ w: 1200, c: this.layoutConfig.columns } // 👈 Usa tu variable para consistencia en Desktop
|
|
3808
|
-
],
|
|
3809
|
-
layout: 'list'
|
|
3810
|
-
}
|
|
3811
|
-
*/
|
|
3812
|
-
// Inicializar el canvas
|
|
3813
|
-
this.grid = GridStack.init(options, this.gridContainer.nativeElement);
|
|
3814
|
-
// Cargar los elementos iniciales desde el JSON
|
|
3815
|
-
//this.loadLayoutFromJSON(this.dashboardItems);
|
|
3816
|
-
this.loadLayoutFromJSON(this.dashboardConfig, this.dashboardStyle);
|
|
3817
|
-
//Evaluar Bloqueo de Widgets en Inicializacion
|
|
3818
|
-
if (this.dashboardConfig.lockPositionWidgets) {
|
|
3819
|
-
this.fn_lockPositionWidgets(this.dashboardConfig.lockPositionWidgets);
|
|
3820
|
-
}
|
|
3821
|
-
// Listener para detectar cambios y actualizar el JSON
|
|
3822
|
-
this.grid.on('change', (event, items) => {
|
|
3823
|
-
this.saveLayoutToJSON();
|
|
3824
|
-
});
|
|
3825
|
-
//Listener para detectar cuando cambia las dimenciones de un widget
|
|
3826
|
-
this.grid.on('resizestop', (event, el) => {
|
|
3827
|
-
// Disparamos el evento nativo del navegador de forma controlada
|
|
3828
|
-
window.dispatchEvent(new Event('resize'));
|
|
3829
|
-
});
|
|
3665
|
+
clearSelection() {
|
|
3666
|
+
this.selectedIds().clear();
|
|
3667
|
+
this.selectionChange.emit([]);
|
|
3830
3668
|
}
|
|
3831
|
-
//
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
}
|
|
3842
|
-
});
|
|
3843
|
-
});
|
|
3669
|
+
// Toggle para seleccionar / deseleccionar
|
|
3670
|
+
toggleSelection(id) {
|
|
3671
|
+
const current = new Set(this.selectedIds());
|
|
3672
|
+
if (this.allowMultiple()) {
|
|
3673
|
+
if (current.has(id)) {
|
|
3674
|
+
current.delete(id);
|
|
3675
|
+
}
|
|
3676
|
+
else {
|
|
3677
|
+
current.add(id);
|
|
3678
|
+
}
|
|
3844
3679
|
}
|
|
3845
3680
|
else {
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3681
|
+
// Si es selección única
|
|
3682
|
+
current.clear();
|
|
3683
|
+
current.add(id);
|
|
3849
3684
|
}
|
|
3850
|
-
|
|
3851
|
-
return object_base_response;
|
|
3685
|
+
this.selectedIds.set(current);
|
|
3852
3686
|
}
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3687
|
+
isSelected(id) {
|
|
3688
|
+
return this.selectedIds().has(id);
|
|
3689
|
+
}
|
|
3690
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwButtonSlicerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3691
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwButtonSlicerComponent, isStandalone: true, selector: "yw-button-slicer", inputs: { idComponent: { classPropertyName: "idComponent", publicName: "idComponent", isSignal: false, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, allowMultiple: { classPropertyName: "allowMultiple", publicName: "allowMultiple", isSignal: true, isRequired: false, transformFunction: null }, currentIds: { classPropertyName: "currentIds", publicName: "currentIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { properties: { "attr.id": "idComponent" } }, ngImport: i0, template: "<div class=\"filter-container\">\r\n \r\n <div class=\"filter-header\">\r\n <span class=\"filter-label\">{{ label() }}</span>\r\n <div class=\"header-actions\"> \r\n <button class=\"icon-btn\" (click)=\"clearSelection()\" >\uD83E\uDDF9</button> \r\n </div>\r\n </div>\r\n\r\n\r\n <!-- Contenedor con barra de desplazamiento interna -->\r\n <div class=\"grid-scroll-container\">\r\n <div class=\"buttons-grid\">\r\n @for (item of options(); track item.id) {\r\n <button \r\n type=\"button\" \r\n class=\"option-btn\" \r\n [class.selected]=\"isSelected(item.id)\"\r\n (click)=\"toggleSelection(item.id)\"\r\n [title]=\"item.label\">\r\n <span class=\"btn-text\">{{ item.label }}</span>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n</div>", styles: ["@charset \"UTF-8\";:host{display:block;font-family:Arial,Helvetica,sans-serif;width:100%;max-width:320px}.filter-container{display:flex;flex-direction:column;gap:8px}.filter-header{display:flex;align-items:center;justify-content:space-between;padding:6px 10px;border-bottom:1px solid #f0f0f0}.filter-label{font-size:13px;font-weight:600;color:#333}.header-actions{display:flex;gap:4px}.grid-scroll-container{max-height:145px;overflow-y:auto;padding-right:4px}.buttons-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.option-btn{display:flex;align-items:center;justify-content:center;height:38px;padding:4px 6px;background-color:#fff;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;transition:all .15s ease-in-out;outline:none;box-sizing:border-box}.option-btn:hover{border-color:#9ca3af;background-color:#f9fafb}.btn-text{font-size:12px;color:#374151;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%;text-align:center}.option-btn.selected{border-color:#2563eb;background-color:#eff6ff;box-shadow:0 0 0 1px #2563eb}.option-btn.selected .btn-text{color:#1d4ed8;font-weight:600}.grid-scroll-container::-webkit-scrollbar{width:6px}.grid-scroll-container::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}.grid-scroll-container::-webkit-scrollbar-thumb{background:#71717a;border-radius:4px}.grid-scroll-container::-webkit-scrollbar-thumb:hover{background:#52525b}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
|
|
3692
|
+
}
|
|
3693
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwButtonSlicerComponent, decorators: [{
|
|
3694
|
+
type: Component,
|
|
3695
|
+
args: [{ selector: 'yw-button-slicer', standalone: true, imports: [CommonModule], host: {
|
|
3696
|
+
'[attr.id]': 'idComponent' // Vincula el atributo id al valor de la propiedad
|
|
3697
|
+
}, template: "<div class=\"filter-container\">\r\n \r\n <div class=\"filter-header\">\r\n <span class=\"filter-label\">{{ label() }}</span>\r\n <div class=\"header-actions\"> \r\n <button class=\"icon-btn\" (click)=\"clearSelection()\" >\uD83E\uDDF9</button> \r\n </div>\r\n </div>\r\n\r\n\r\n <!-- Contenedor con barra de desplazamiento interna -->\r\n <div class=\"grid-scroll-container\">\r\n <div class=\"buttons-grid\">\r\n @for (item of options(); track item.id) {\r\n <button \r\n type=\"button\" \r\n class=\"option-btn\" \r\n [class.selected]=\"isSelected(item.id)\"\r\n (click)=\"toggleSelection(item.id)\"\r\n [title]=\"item.label\">\r\n <span class=\"btn-text\">{{ item.label }}</span>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n</div>", styles: ["@charset \"UTF-8\";:host{display:block;font-family:Arial,Helvetica,sans-serif;width:100%;max-width:320px}.filter-container{display:flex;flex-direction:column;gap:8px}.filter-header{display:flex;align-items:center;justify-content:space-between;padding:6px 10px;border-bottom:1px solid #f0f0f0}.filter-label{font-size:13px;font-weight:600;color:#333}.header-actions{display:flex;gap:4px}.grid-scroll-container{max-height:145px;overflow-y:auto;padding-right:4px}.buttons-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.option-btn{display:flex;align-items:center;justify-content:center;height:38px;padding:4px 6px;background-color:#fff;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;transition:all .15s ease-in-out;outline:none;box-sizing:border-box}.option-btn:hover{border-color:#9ca3af;background-color:#f9fafb}.btn-text{font-size:12px;color:#374151;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%;text-align:center}.option-btn.selected{border-color:#2563eb;background-color:#eff6ff;box-shadow:0 0 0 1px #2563eb}.option-btn.selected .btn-text{color:#1d4ed8;font-weight:600}.grid-scroll-container::-webkit-scrollbar{width:6px}.grid-scroll-container::-webkit-scrollbar-track{background:#f1f1f1;border-radius:4px}.grid-scroll-container::-webkit-scrollbar-thumb{background:#71717a;border-radius:4px}.grid-scroll-container::-webkit-scrollbar-thumb:hover{background:#52525b}\n"] }]
|
|
3698
|
+
}], ctorParameters: () => [], propDecorators: { idComponent: [{
|
|
3699
|
+
type: Input
|
|
3700
|
+
}], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], allowMultiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowMultiple", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], currentIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentIds", required: false }] }] } });
|
|
3701
|
+
|
|
3702
|
+
class YwListSlicerComponent {
|
|
3703
|
+
constructor() {
|
|
3704
|
+
// Entradas generales
|
|
3705
|
+
this.idComponent = '';
|
|
3706
|
+
this.label = input('Filtro Jerárquico', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3707
|
+
this.clearTitleLabel = input('Limpiar Seleccion', ...(ngDevMode ? [{ debugName: "clearTitleLabel" }] : []));
|
|
3708
|
+
// Opción 1: Entregar datos en árbol de texto directo
|
|
3709
|
+
this.rawData = input([], ...(ngDevMode ? [{ debugName: "rawData" }] : []));
|
|
3710
|
+
// Opción 2: Generar desde fechas
|
|
3711
|
+
this.dataType = input('date', ...(ngDevMode ? [{ debugName: "dataType" }] : []));
|
|
3712
|
+
this.minDate = input('', ...(ngDevMode ? [{ debugName: "minDate" }] : [])); // Formato 'YYYY-MM-DD'
|
|
3713
|
+
this.maxDate = input('', ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
|
|
3714
|
+
this.dateHierarchyType = input('YEAR_TRIMESTER_MONTH', ...(ngDevMode ? [{ debugName: "dateHierarchyType" }] : []));
|
|
3715
|
+
this.monthNames = input(['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], ...(ngDevMode ? [{ debugName: "monthNames" }] : []));
|
|
3716
|
+
// Evento de salida con el ID/Nodo seleccionado
|
|
3717
|
+
this.selectionChange = output();
|
|
3718
|
+
this.filterValueChange = output(); // Output 2 (Rangos o Hojas)
|
|
3719
|
+
// ID del elemento seleccionado (Selección Simple)
|
|
3720
|
+
this.selectedId = signal(null, ...(ngDevMode ? [{ debugName: "selectedId" }] : []));
|
|
3721
|
+
this.currentSelectedId = input(null, ...(ngDevMode ? [{ debugName: "currentSelectedId" }] : []));
|
|
3722
|
+
// Arbol de nodos computado
|
|
3723
|
+
this.treeNodes = computed(() => {
|
|
3724
|
+
if (this.dataType() == 'date' && this.minDate() && this.maxDate()) {
|
|
3725
|
+
return this.generateDateHierarchy(this.minDate(), this.maxDate(), this.dateHierarchyType());
|
|
3726
|
+
}
|
|
3727
|
+
return this.rawData();
|
|
3728
|
+
}, ...(ngDevMode ? [{ debugName: "treeNodes" }] : []));
|
|
3729
|
+
effect(() => {
|
|
3730
|
+
const currentId = this.selectedId();
|
|
3731
|
+
if (!currentId) {
|
|
3732
|
+
this.selectionChange.emit(null);
|
|
3733
|
+
this.filterValueChange.emit(null);
|
|
3734
|
+
return;
|
|
3735
|
+
}
|
|
3736
|
+
const node = this.findNodeById(this.treeNodes(), currentId);
|
|
3737
|
+
this.selectionChange.emit(node);
|
|
3738
|
+
if (node) {
|
|
3739
|
+
// Emitir el segundo Output según el modo
|
|
3740
|
+
const calculatedValue = this.processFilterOutput(node);
|
|
3741
|
+
this.filterValueChange.emit(calculatedValue);
|
|
3742
|
+
}
|
|
3743
|
+
});
|
|
3744
|
+
}
|
|
3745
|
+
ngOnInit() {
|
|
3746
|
+
if (this.currentSelectedId()) {
|
|
3747
|
+
this.selectedId.set(this.currentSelectedId());
|
|
3865
3748
|
}
|
|
3866
|
-
|
|
3867
|
-
|
|
3749
|
+
}
|
|
3750
|
+
// Métodos de Selección y Expansión
|
|
3751
|
+
toggleExpand(node, event) {
|
|
3752
|
+
event.stopPropagation();
|
|
3753
|
+
node.expanded = !node.expanded;
|
|
3754
|
+
}
|
|
3755
|
+
selectNode(node, event) {
|
|
3756
|
+
event.stopPropagation();
|
|
3757
|
+
this.selectedId.set(this.selectedId() === node.id ? null : node.id);
|
|
3758
|
+
}
|
|
3759
|
+
clearSelection() {
|
|
3760
|
+
this.selectedId.set(null);
|
|
3761
|
+
this.filterValueChange.emit(null);
|
|
3762
|
+
}
|
|
3763
|
+
// --- LÓGICA DE PROCESAMIENTO DE LAS HOJAS / RANGOS ---
|
|
3764
|
+
processFilterOutput(selectedNode) {
|
|
3765
|
+
// 1. Obtener todas las hojas (nodos del nivel más bajo) pertenecientes al bloque seleccionado
|
|
3766
|
+
const leaves = this.getLeafNodes(selectedNode);
|
|
3767
|
+
if (this.dataType() == 'date') {
|
|
3768
|
+
// Extraer todas las fechas de las hojas del bloque
|
|
3769
|
+
const dates = leaves
|
|
3770
|
+
.map(leaf => leaf.value)
|
|
3771
|
+
.filter(d => d instanceof Date)
|
|
3772
|
+
.sort((a, b) => a.getTime() - b.getTime());
|
|
3773
|
+
if (dates.length > 0) {
|
|
3774
|
+
const minD = dates[0];
|
|
3775
|
+
// Para la fecha máxima, tomamos el último día del mes correspondiente
|
|
3776
|
+
const maxD = new Date(dates[dates.length - 1].getFullYear(), dates[dates.length - 1].getMonth() + 1, 0);
|
|
3777
|
+
return {
|
|
3778
|
+
type: 'DATE_RANGE',
|
|
3779
|
+
dateRange: {
|
|
3780
|
+
minDate: minD.toISOString().split('T')[0],
|
|
3781
|
+
maxDate: maxD.toISOString().split('T')[0]
|
|
3782
|
+
},
|
|
3783
|
+
currentNodeId: selectedNode.id
|
|
3784
|
+
};
|
|
3785
|
+
}
|
|
3868
3786
|
}
|
|
3869
|
-
|
|
3787
|
+
// Modo Texto: Entregar arreglo con las hojas
|
|
3788
|
+
return {
|
|
3789
|
+
type: 'TEXT_LEAVES',
|
|
3790
|
+
leafNodes: leaves,
|
|
3791
|
+
leafIds: leaves.map(l => l.id),
|
|
3792
|
+
currentNodeId: selectedNode.id
|
|
3793
|
+
};
|
|
3870
3794
|
}
|
|
3871
|
-
//
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
const
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3795
|
+
// Recorrido recursivo para obtener solo los nodos terminales (sin hijos)
|
|
3796
|
+
getLeafNodes(node) {
|
|
3797
|
+
if (!node.children || node.children.length === 0) {
|
|
3798
|
+
return [node];
|
|
3799
|
+
}
|
|
3800
|
+
let leaves = [];
|
|
3801
|
+
for (const child of node.children) {
|
|
3802
|
+
leaves = leaves.concat(this.getLeafNodes(child));
|
|
3803
|
+
}
|
|
3804
|
+
return leaves;
|
|
3805
|
+
}
|
|
3806
|
+
findNodeById(nodes, id) {
|
|
3807
|
+
for (const node of nodes) {
|
|
3808
|
+
if (node.id === id)
|
|
3809
|
+
return node;
|
|
3810
|
+
if (node.children) {
|
|
3811
|
+
const found = this.findNodeById(node.children, id);
|
|
3812
|
+
if (found)
|
|
3813
|
+
return found;
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
return null;
|
|
3817
|
+
}
|
|
3818
|
+
// Generador de Jerarquía por Fechas
|
|
3819
|
+
generateDateHierarchy(startStr, endStr, type) {
|
|
3820
|
+
const start = new Date(startStr);
|
|
3821
|
+
const end = new Date(endStr);
|
|
3822
|
+
const tree = [];
|
|
3823
|
+
const monthNames = this.monthNames();
|
|
3824
|
+
if (type === 'YEAR_TRIMESTER_MONTH') {
|
|
3825
|
+
let current = new Date(start);
|
|
3826
|
+
while (current <= end) {
|
|
3827
|
+
const year = current.getFullYear();
|
|
3828
|
+
let yearNode = tree.find(n => n.id === `Y_${year}`);
|
|
3829
|
+
if (!yearNode) {
|
|
3830
|
+
yearNode = { id: `Y_${year}`, label: `${year}`, children: [], expanded: false };
|
|
3831
|
+
tree.push(yearNode);
|
|
3887
3832
|
}
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3833
|
+
const month = current.getMonth();
|
|
3834
|
+
const qtrNum = Math.floor(month / 3) + 1;
|
|
3835
|
+
let qtrNode = yearNode.children.find(n => n.id === `Q_${year}_${qtrNum}`);
|
|
3836
|
+
if (!qtrNode) {
|
|
3837
|
+
qtrNode = { id: `Q_${year}_${qtrNum}`, label: `Qtr ${qtrNum}`, children: [], expanded: false };
|
|
3838
|
+
yearNode.children.push(qtrNode);
|
|
3893
3839
|
}
|
|
3894
|
-
|
|
3895
|
-
|
|
3840
|
+
const monthId = `M_${year}_${month + 1}`;
|
|
3841
|
+
if (!qtrNode.children.some(n => n.id === monthId)) {
|
|
3842
|
+
qtrNode.children.push({
|
|
3843
|
+
id: monthId,
|
|
3844
|
+
label: monthNames[month],
|
|
3845
|
+
value: new Date(year, month, 1) // Fecha inicial del mes
|
|
3846
|
+
});
|
|
3847
|
+
}
|
|
3848
|
+
current.setMonth(current.getMonth() + 1);
|
|
3849
|
+
}
|
|
3896
3850
|
}
|
|
3851
|
+
if (type === 'YEAR_SEMESTER_MONTH') {
|
|
3852
|
+
let current = new Date(start);
|
|
3853
|
+
while (current <= end) {
|
|
3854
|
+
const year = current.getFullYear();
|
|
3855
|
+
let yearNode = tree.find(n => n.id === `Y_${year}`);
|
|
3856
|
+
if (!yearNode) {
|
|
3857
|
+
yearNode = { id: `Y_${year}`, label: `${year}`, children: [], expanded: false };
|
|
3858
|
+
tree.push(yearNode);
|
|
3859
|
+
}
|
|
3860
|
+
const month = current.getMonth();
|
|
3861
|
+
const qtrNum = Math.floor(month / 6) + 1;
|
|
3862
|
+
let qtrNode = yearNode.children.find(n => n.id === `S_${year}_${qtrNum}`);
|
|
3863
|
+
if (!qtrNode) {
|
|
3864
|
+
qtrNode = { id: `S_${year}_${qtrNum}`, label: `S ${qtrNum}`, children: [], expanded: false };
|
|
3865
|
+
yearNode.children.push(qtrNode);
|
|
3866
|
+
}
|
|
3867
|
+
const monthId = `M_${year}_${month + 1}`;
|
|
3868
|
+
if (!qtrNode.children.some(n => n.id === monthId)) {
|
|
3869
|
+
qtrNode.children.push({
|
|
3870
|
+
id: monthId,
|
|
3871
|
+
label: monthNames[month],
|
|
3872
|
+
value: new Date(year, month, 1) // Fecha inicial del mes
|
|
3873
|
+
});
|
|
3874
|
+
}
|
|
3875
|
+
current.setMonth(current.getMonth() + 1);
|
|
3876
|
+
}
|
|
3877
|
+
}
|
|
3878
|
+
return tree;
|
|
3897
3879
|
}
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
this.
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
};
|
|
3921
|
-
//Datos de Widget y sus Contenidos
|
|
3922
|
-
const widgetConfig = {
|
|
3923
|
-
widgetId: newWidgetId,
|
|
3924
|
-
title: '',
|
|
3925
|
-
typeComponent: 'empty-visual',
|
|
3926
|
-
showConfigButtons: true,
|
|
3927
|
-
widgetStyle: DEFAULT_WIDGET_STYLE,
|
|
3928
|
-
layoutConfig: {
|
|
3929
|
-
id: '',
|
|
3930
|
-
w: 0,
|
|
3931
|
-
h: 0,
|
|
3932
|
-
content: undefined
|
|
3933
|
-
},
|
|
3934
|
-
controlConfig: {},
|
|
3935
|
-
controlTables: []
|
|
3880
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwListSlicerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3881
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwListSlicerComponent, isStandalone: true, selector: "yw-list-slicer", inputs: { idComponent: { classPropertyName: "idComponent", publicName: "idComponent", isSignal: false, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, clearTitleLabel: { classPropertyName: "clearTitleLabel", publicName: "clearTitleLabel", isSignal: true, isRequired: false, transformFunction: null }, rawData: { classPropertyName: "rawData", publicName: "rawData", isSignal: true, isRequired: false, transformFunction: null }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, dateHierarchyType: { classPropertyName: "dateHierarchyType", publicName: "dateHierarchyType", isSignal: true, isRequired: false, transformFunction: null }, monthNames: { classPropertyName: "monthNames", publicName: "monthNames", isSignal: true, isRequired: false, transformFunction: null }, currentSelectedId: { classPropertyName: "currentSelectedId", publicName: "currentSelectedId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", filterValueChange: "filterValueChange" }, host: { properties: { "attr.id": "idComponent" } }, ngImport: i0, template: "<div class=\"filter-container\">\r\n <!-- Cabecera con t\u00EDtulo y acciones de filtro -->\r\n <div class=\"filter-header\">\r\n <span class=\"filter-label\">{{ label() }}</span>\r\n <div class=\"header-actions\">\r\n <!--<button class=\"icon-btn\" title=\"Filtro\">\uD83D\uDD3B</button>-->\r\n <button class=\"icon-btn\" (click)=\"clearSelection()\" title=\"{{clearTitleLabel}}\">\uD83E\uDDF9</button>\r\n <!--<button class=\"icon-btn\" title=\"M\u00E1s opciones\">\u22EE</button>-->\r\n </div>\r\n </div>\r\n\r\n <!-- Vista en \u00C1rbol con scroll interno -->\r\n <div class=\"tree-scroll-container\">\r\n <ng-container *ngTemplateOutlet=\"nodeListTemplate; context: { $implicit: treeNodes(), level: 0 }\"></ng-container>\r\n </div>\r\n</div>\r\n\r\n<!-- Plantilla Recursiva para renderizar niveles del \u00C1rbol -->\r\n<ng-template #nodeListTemplate let-nodes let-level=\"level\">\r\n <div class=\"tree-level\">\r\n @for (node of nodes; track node.id) {\r\n <div class=\"tree-node-wrapper\">\r\n <!-- Fila de opci\u00F3n -->\r\n <div \r\n class=\"tree-node-row\" \r\n [class.selected]=\"selectedId() === node.id\"\r\n [style.padding-left.px]=\"level * 18 + 6\"\r\n (click)=\"selectNode(node, $event)\">\r\n \r\n <!-- Flecha expandir/colapsar (si tiene hijos) -->\r\n @if (node.children && node.children.length > 0) {\r\n <span class=\"chevron-icon\" (click)=\"toggleExpand(node, $event)\">\r\n {{ node.expanded ? '\uD83D\uDF83' : '\uD83D\uDF82' }}\r\n </span>\r\n } @else {\r\n <span class=\"chevron-spacer\"></span>\r\n }\r\n\r\n <!-- Radio Button (Selecci\u00F3n simple) -->\r\n <div class=\"radio-circle\" [class.checked]=\"selectedId() === node.id\">\r\n <div class=\"radio-inner\"></div>\r\n </div>\r\n\r\n <!-- Etiqueta del Nodo -->\r\n <span class=\"node-label\">{{ node.label }}</span>\r\n </div>\r\n\r\n <!-- Renderizado de hijos si est\u00E1 expandido -->\r\n @if (node.children && node.children.length > 0 && node.expanded) {\r\n <ng-container *ngTemplateOutlet=\"nodeListTemplate; context: { $implicit: node.children, level: level + 1 }\"></ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{display:block;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;width:100%;max-width:320px;background:#fff}.filter-container{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:4px;background-color:#fff}.filter-header{display:flex;align-items:center;justify-content:space-between;padding:6px 10px;border-bottom:1px solid #f0f0f0}.filter-label{font-size:13px;font-weight:600;color:#252423}.header-actions{display:flex;gap:4px}.icon-btn{background:none;border:none;cursor:pointer;font-size:12px;color:#605e5c;padding:2px 4px;border-radius:2px}.icon-btn:hover{background-color:#f3f2f1}.tree-scroll-container{max-height:220px;overflow-y:auto;padding:4px 0}.tree-level{display:flex;flex-direction:column}.tree-node-row{display:flex;align-items:center;height:28px;cursor:pointer;-webkit-user-select:none;user-select:none;gap:6px;transition:background-color .1s ease}.tree-node-row:hover{background-color:#f3f2f1}.tree-node-row.selected{background-color:#e1dfdd}.chevron-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:10px;color:#323130}.chevron-spacer{width:16px}.radio-circle{width:14px;height:14px;border-radius:50%;border:1.5px solid #605e5c;display:flex;align-items:center;justify-content:center;box-sizing:border-box;background-color:#fff}.radio-circle.checked{border-color:#0078d4}.radio-circle.checked .radio-inner{width:6px;height:6px;border-radius:50%;background-color:#0078d4}.node-label{font-size:13px;color:#323130;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tree-scroll-container::-webkit-scrollbar{width:6px}.tree-scroll-container::-webkit-scrollbar-track{background:#f1f1f1}.tree-scroll-container::-webkit-scrollbar-thumb{background:#8a8886;border-radius:3px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
|
|
3882
|
+
}
|
|
3883
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwListSlicerComponent, decorators: [{
|
|
3884
|
+
type: Component,
|
|
3885
|
+
args: [{ selector: 'yw-list-slicer', standalone: true, imports: [CommonModule], host: {
|
|
3886
|
+
'[attr.id]': 'idComponent' // Vincula el atributo id al valor de la propiedad
|
|
3887
|
+
}, template: "<div class=\"filter-container\">\r\n <!-- Cabecera con t\u00EDtulo y acciones de filtro -->\r\n <div class=\"filter-header\">\r\n <span class=\"filter-label\">{{ label() }}</span>\r\n <div class=\"header-actions\">\r\n <!--<button class=\"icon-btn\" title=\"Filtro\">\uD83D\uDD3B</button>-->\r\n <button class=\"icon-btn\" (click)=\"clearSelection()\" title=\"{{clearTitleLabel}}\">\uD83E\uDDF9</button>\r\n <!--<button class=\"icon-btn\" title=\"M\u00E1s opciones\">\u22EE</button>-->\r\n </div>\r\n </div>\r\n\r\n <!-- Vista en \u00C1rbol con scroll interno -->\r\n <div class=\"tree-scroll-container\">\r\n <ng-container *ngTemplateOutlet=\"nodeListTemplate; context: { $implicit: treeNodes(), level: 0 }\"></ng-container>\r\n </div>\r\n</div>\r\n\r\n<!-- Plantilla Recursiva para renderizar niveles del \u00C1rbol -->\r\n<ng-template #nodeListTemplate let-nodes let-level=\"level\">\r\n <div class=\"tree-level\">\r\n @for (node of nodes; track node.id) {\r\n <div class=\"tree-node-wrapper\">\r\n <!-- Fila de opci\u00F3n -->\r\n <div \r\n class=\"tree-node-row\" \r\n [class.selected]=\"selectedId() === node.id\"\r\n [style.padding-left.px]=\"level * 18 + 6\"\r\n (click)=\"selectNode(node, $event)\">\r\n \r\n <!-- Flecha expandir/colapsar (si tiene hijos) -->\r\n @if (node.children && node.children.length > 0) {\r\n <span class=\"chevron-icon\" (click)=\"toggleExpand(node, $event)\">\r\n {{ node.expanded ? '\uD83D\uDF83' : '\uD83D\uDF82' }}\r\n </span>\r\n } @else {\r\n <span class=\"chevron-spacer\"></span>\r\n }\r\n\r\n <!-- Radio Button (Selecci\u00F3n simple) -->\r\n <div class=\"radio-circle\" [class.checked]=\"selectedId() === node.id\">\r\n <div class=\"radio-inner\"></div>\r\n </div>\r\n\r\n <!-- Etiqueta del Nodo -->\r\n <span class=\"node-label\">{{ node.label }}</span>\r\n </div>\r\n\r\n <!-- Renderizado de hijos si est\u00E1 expandido -->\r\n @if (node.children && node.children.length > 0 && node.expanded) {\r\n <ng-container *ngTemplateOutlet=\"nodeListTemplate; context: { $implicit: node.children, level: level + 1 }\"></ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{display:block;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;width:100%;max-width:320px;background:#fff}.filter-container{display:flex;flex-direction:column;border:1px solid #e0e0e0;border-radius:4px;background-color:#fff}.filter-header{display:flex;align-items:center;justify-content:space-between;padding:6px 10px;border-bottom:1px solid #f0f0f0}.filter-label{font-size:13px;font-weight:600;color:#252423}.header-actions{display:flex;gap:4px}.icon-btn{background:none;border:none;cursor:pointer;font-size:12px;color:#605e5c;padding:2px 4px;border-radius:2px}.icon-btn:hover{background-color:#f3f2f1}.tree-scroll-container{max-height:220px;overflow-y:auto;padding:4px 0}.tree-level{display:flex;flex-direction:column}.tree-node-row{display:flex;align-items:center;height:28px;cursor:pointer;-webkit-user-select:none;user-select:none;gap:6px;transition:background-color .1s ease}.tree-node-row:hover{background-color:#f3f2f1}.tree-node-row.selected{background-color:#e1dfdd}.chevron-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:10px;color:#323130}.chevron-spacer{width:16px}.radio-circle{width:14px;height:14px;border-radius:50%;border:1.5px solid #605e5c;display:flex;align-items:center;justify-content:center;box-sizing:border-box;background-color:#fff}.radio-circle.checked{border-color:#0078d4}.radio-circle.checked .radio-inner{width:6px;height:6px;border-radius:50%;background-color:#0078d4}.node-label{font-size:13px;color:#323130;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tree-scroll-container::-webkit-scrollbar{width:6px}.tree-scroll-container::-webkit-scrollbar-track{background:#f1f1f1}.tree-scroll-container::-webkit-scrollbar-thumb{background:#8a8886;border-radius:3px}\n"] }]
|
|
3888
|
+
}], ctorParameters: () => [], propDecorators: { idComponent: [{
|
|
3889
|
+
type: Input
|
|
3890
|
+
}], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], clearTitleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearTitleLabel", required: false }] }], rawData: [{ type: i0.Input, args: [{ isSignal: true, alias: "rawData", required: false }] }], dataType: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataType", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], dateHierarchyType: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateHierarchyType", required: false }] }], monthNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthNames", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], filterValueChange: [{ type: i0.Output, args: ["filterValueChange"] }], currentSelectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentSelectedId", required: false }] }] } });
|
|
3891
|
+
|
|
3892
|
+
class YwDashboardFilterWidgetComponent {
|
|
3893
|
+
constructor() {
|
|
3894
|
+
this.componentWidgetId = '';
|
|
3895
|
+
this.typeComponent = '';
|
|
3896
|
+
this.varShowConfigButtons = false;
|
|
3897
|
+
this.configWidget = {
|
|
3898
|
+
widgetId: '',
|
|
3899
|
+
label: '',
|
|
3900
|
+
typeComponent: '',
|
|
3901
|
+
controlTable: '',
|
|
3936
3902
|
};
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
this.
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3903
|
+
this.controlConfig = input(...(ngDevMode ? [undefined, { debugName: "controlConfig" }] : []));
|
|
3904
|
+
this.controlData = [];
|
|
3905
|
+
this.eventDeleteRequest = output();
|
|
3906
|
+
this.eventShowConfigFormRequest = output();
|
|
3907
|
+
this.selectionChange = output();
|
|
3908
|
+
effect(() => {
|
|
3909
|
+
const value_controlConfig = this.fnFormatConfigData();
|
|
3910
|
+
this.dataWidget = { idComponent: this.componentWidgetId,
|
|
3911
|
+
configWidget: this.configWidget,
|
|
3912
|
+
controlConfig: value_controlConfig
|
|
3913
|
+
};
|
|
3914
|
+
});
|
|
3946
3915
|
}
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
this.
|
|
3950
|
-
const
|
|
3951
|
-
this.
|
|
3952
|
-
|
|
3953
|
-
|
|
3916
|
+
ngOnInit() {
|
|
3917
|
+
this.componentWidgetId = this.configWidget.widgetId;
|
|
3918
|
+
this.typeComponent = this.configWidget.typeComponent;
|
|
3919
|
+
const value_controlConfig = this.fnFormatConfigData();
|
|
3920
|
+
this.dataWidget = { idComponent: this.componentWidgetId,
|
|
3921
|
+
configWidget: this.configWidget,
|
|
3922
|
+
controlConfig: value_controlConfig
|
|
3923
|
+
};
|
|
3954
3924
|
}
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3925
|
+
/*
|
|
3926
|
+
Los Datos a este componente llegan a un nivel basico, sin embargo es necesario configurar la informacion, para que se adapte a los componentes.
|
|
3927
|
+
*/
|
|
3928
|
+
fnFormatConfigData() {
|
|
3929
|
+
let responsedata = {};
|
|
3930
|
+
const typeComponent = this.configWidget.typeComponent;
|
|
3931
|
+
if (typeComponent == 'filter-slicer') {
|
|
3932
|
+
const dataType = this.controlConfig().dataType;
|
|
3933
|
+
const currentData = this.controlConfig();
|
|
3934
|
+
if (dataType == 'date') {
|
|
3935
|
+
const fieldName = this.controlConfig().filterField;
|
|
3936
|
+
const fechas = this.controlData.map((d) => new Date(d[fieldName]).getTime());
|
|
3937
|
+
const val_min = new Date(Math.min(...fechas)).toISOString().split("T")[0];
|
|
3938
|
+
const val_max = new Date(Math.max(...fechas)).toISOString().split("T")[0];
|
|
3939
|
+
responsedata = { dataType: dataType, min: val_min, max: val_max, minCurrent: currentData?.minCurrent, maxCurrent: currentData?.maxCurrent };
|
|
3940
|
+
}
|
|
3941
|
+
if (dataType == 'number') {
|
|
3942
|
+
const fieldName = this.controlConfig().filterField;
|
|
3943
|
+
const valStep = this.controlConfig().step;
|
|
3944
|
+
const DataNumbers = this.controlData.map((d) => d[fieldName]);
|
|
3945
|
+
const val_min = Math.min(...DataNumbers);
|
|
3946
|
+
const val_max = Math.max(...DataNumbers);
|
|
3947
|
+
responsedata = { dataType: dataType, min: val_min, max: val_max, step: valStep, minCurrent: currentData?.minCurrent, maxCurrent: currentData?.maxCurrent };
|
|
3948
|
+
}
|
|
3949
|
+
}
|
|
3950
|
+
if (typeComponent == 'filter-button') {
|
|
3951
|
+
const fieldName = this.controlConfig().filterField;
|
|
3952
|
+
const fieldNameId = this.controlConfig().filterFieldId;
|
|
3953
|
+
const val_allowMultiple = this.controlConfig().allowMultiple;
|
|
3954
|
+
const currentData = this.controlConfig();
|
|
3955
|
+
let listoptions = this.controlData.map((item) => { return { 'id': item[fieldNameId], 'label': item[fieldName] }; });
|
|
3956
|
+
const listoptionsunicos = [...new Map(listoptions.map(d => [d.id, d])).values()];
|
|
3957
|
+
responsedata = { options: listoptionsunicos, allowMultiple: val_allowMultiple, currentIds: currentData?.currentIds };
|
|
3958
|
+
}
|
|
3959
|
+
if (typeComponent == 'filter-list') {
|
|
3960
|
+
const dataType = this.controlConfig().dataType;
|
|
3961
|
+
const currentData = this.controlConfig();
|
|
3962
|
+
if (dataType == 'date') {
|
|
3963
|
+
const fieldName = this.controlConfig().filterField;
|
|
3964
|
+
const val_dateHierarchyType = this.controlConfig().dateHierarchyType;
|
|
3965
|
+
const fechas = this.controlData.map((d) => new Date(d[fieldName]).getTime());
|
|
3966
|
+
const val_min = new Date(Math.min(...fechas)).toISOString().split("T")[0];
|
|
3967
|
+
const val_max = new Date(Math.max(...fechas)).toISOString().split("T")[0];
|
|
3968
|
+
responsedata = { dataType: dataType, minDate: val_min, maxDate: val_max, dateHierarchyType: val_dateHierarchyType, currentSelectedId: currentData.currentSelectedId };
|
|
3969
|
+
}
|
|
3970
|
+
if (dataType == 'text') {
|
|
3971
|
+
const fieldName1 = this.controlConfig().filterField;
|
|
3972
|
+
const fieldName2 = this.controlConfig().filterFieldN2;
|
|
3973
|
+
const fieldName3 = this.controlConfig().filterFieldN3;
|
|
3974
|
+
let foundN2 = false;
|
|
3975
|
+
let foundN3 = false;
|
|
3976
|
+
let lsizeN2 = 0;
|
|
3977
|
+
let lsizeN3 = 0;
|
|
3978
|
+
let nodebase = { id: '', label: '' };
|
|
3979
|
+
let nodeN2 = { id: '', label: '' };
|
|
3980
|
+
let nodeN3 = { id: '', label: '' };
|
|
3981
|
+
let listNivel1 = [];
|
|
3982
|
+
let listNivel2 = [];
|
|
3983
|
+
let listNivel3 = [];
|
|
3984
|
+
this.controlData.forEach((item) => {
|
|
3985
|
+
nodebase = { id: item[fieldName1], label: item[fieldName1] };
|
|
3986
|
+
//NIVEL 2
|
|
3987
|
+
if (fieldName2) {
|
|
3988
|
+
foundN2 = false;
|
|
3989
|
+
lsizeN2 = Object.keys(listNivel2).length;
|
|
3990
|
+
for (let i = 0; i < lsizeN2; i++) {
|
|
3991
|
+
const itemN2 = listNivel2[i];
|
|
3992
|
+
if (itemN2.id == item[fieldName2]) {
|
|
3993
|
+
itemN2.children.push(nodebase);
|
|
3994
|
+
nodeN2 = itemN2;
|
|
3995
|
+
foundN2 = true;
|
|
3996
|
+
break;
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3999
|
+
;
|
|
4000
|
+
if (foundN2 == false) {
|
|
4001
|
+
nodeN2 = { id: item[fieldName2], label: item[fieldName2], expanded: true, children: [nodebase] };
|
|
4002
|
+
if (fieldName3) {
|
|
4003
|
+
nodeN2.parentId = item[fieldName3];
|
|
4004
|
+
}
|
|
4005
|
+
listNivel2.push(nodeN2);
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
else {
|
|
4009
|
+
listNivel1.push(nodebase);
|
|
4010
|
+
}
|
|
4011
|
+
});
|
|
4012
|
+
//NIVEL 1 - Basico no hay Jerarquia
|
|
4013
|
+
responsedata = { dataType: dataType, rawData: listNivel1, currentSelectedId: currentData.currentSelectedId };
|
|
4014
|
+
//NIVEL 2 - Jerarquia de 2 niveles
|
|
4015
|
+
if (fieldName2) {
|
|
4016
|
+
responsedata = { dataType: dataType, rawData: listNivel2, currentSelectedId: currentData.currentSelectedId };
|
|
4017
|
+
}
|
|
4018
|
+
//NIVEL 3 - Jerarquia de 3 niveles
|
|
4019
|
+
if (fieldName3) {
|
|
4020
|
+
listNivel2.forEach((item) => {
|
|
4021
|
+
nodebase = item;
|
|
4022
|
+
foundN3 = false;
|
|
4023
|
+
lsizeN3 = Object.keys(listNivel3).length;
|
|
4024
|
+
for (let i = 0; i < lsizeN3; i++) {
|
|
4025
|
+
const itemN3 = listNivel3[i];
|
|
4026
|
+
if (itemN3.id == item.parentId) {
|
|
4027
|
+
itemN3.children.push(nodebase);
|
|
4028
|
+
foundN3 = true;
|
|
4029
|
+
break;
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
;
|
|
4033
|
+
if (foundN3 == false) {
|
|
4034
|
+
nodeN3 = { id: item[fieldName3], label: item[fieldName3], expanded: true, children: [nodebase] };
|
|
4035
|
+
listNivel3.push(nodeN3);
|
|
4036
|
+
}
|
|
4037
|
+
});
|
|
4038
|
+
responsedata = { dataType: dataType, rawData: listNivel3, currentSelectedId: currentData.currentSelectedId };
|
|
4039
|
+
}
|
|
4040
|
+
}
|
|
4041
|
+
}
|
|
4042
|
+
return responsedata;
|
|
3965
4043
|
}
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
newControlConfig['provider'] = 'syncfusion';
|
|
3971
|
-
this.eventUpdateWidgetControlConfig(idWidget, newControlConfig);
|
|
4044
|
+
//Filtro Slicer
|
|
4045
|
+
onFilterSlicerChange(range) {
|
|
4046
|
+
console.log('Filtro actualizado:', range);
|
|
4047
|
+
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: range });
|
|
3972
4048
|
}
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
newControlData = [
|
|
3978
|
-
{ month: 'Ene', sales: 35, expenses: 28 },
|
|
3979
|
-
{ month: 'Feb', sales: 28, expenses: 22 },
|
|
3980
|
-
{ month: 'Mar', sales: 34, expenses: 25 },
|
|
3981
|
-
{ month: 'Abr', sales: 32, expenses: 27 },
|
|
3982
|
-
{ month: 'May', sales: 40, expenses: 30 },
|
|
3983
|
-
{ month: 'Jun', sales: 32, expenses: 26 },
|
|
3984
|
-
{ month: 'Jul', sales: 45, expenses: 32 },
|
|
3985
|
-
{ month: 'Ago', sales: 38, expenses: 29 },
|
|
3986
|
-
{ month: 'Sep', sales: 42, expenses: 31 },
|
|
3987
|
-
{ month: 'Oct', sales: 48, expenses: 35 },
|
|
3988
|
-
{ month: 'Nov', sales: 52, expenses: 38 },
|
|
3989
|
-
{ month: 'Dic', sales: 58, expenses: 42 },
|
|
3990
|
-
];
|
|
3991
|
-
this.eventUpdateWidgetControlData(idWidget, newControlData);
|
|
4049
|
+
//Filtro Button
|
|
4050
|
+
onFilterButtonChange(selectedIds) {
|
|
4051
|
+
console.log('Tipos seleccionados:', selectedIds);
|
|
4052
|
+
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: selectedIds });
|
|
3992
4053
|
}
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
//
|
|
3997
|
-
|
|
3998
|
-
// 2. Obtener el contenedor interno generado por Gridstack
|
|
3999
|
-
const contentElement = el.querySelector('.grid-stack-item-content');
|
|
4000
|
-
if (contentElement) {
|
|
4001
|
-
// 3. Crear dinámicamente la instancia del componente Angular
|
|
4002
|
-
const componentRef = createComponent(YwDashboardWidgetComponent, {
|
|
4003
|
-
environmentInjector: this.environmentInjector, // Requerido para resolver dependencias
|
|
4004
|
-
hostElement: contentElement // Renderiza directamente aquí dentro
|
|
4005
|
-
});
|
|
4006
|
-
// 4. Pasar las propiedades/Inputs al componente creado
|
|
4007
|
-
//Evaluar Estilos
|
|
4008
|
-
componentRef.setInput('styleWidget', widgetConfig.widgetStyle);
|
|
4009
|
-
//componentRef.instance.configWidget = widgetConfig;
|
|
4010
|
-
componentRef.setInput('configWidget', widgetConfig);
|
|
4011
|
-
componentRef.setInput('controlConfig', controlConfig);
|
|
4012
|
-
componentRef.setInput('controlData', controlData);
|
|
4013
|
-
/* BEGIN - Eventos que provienen desde widget */
|
|
4014
|
-
componentRef.instance.eventDeleteRequest.subscribe((idWidget) => {
|
|
4015
|
-
// Ejecutamos la función de borrado que ya programamos en el paso anterior
|
|
4016
|
-
this.eventRemoveWidgetById(idWidget);
|
|
4017
|
-
});
|
|
4018
|
-
componentRef.instance.eventLockToggleRequest.subscribe((event) => {
|
|
4019
|
-
this.eventToggleLockWidget(event.widgetId, event.shouldLock);
|
|
4020
|
-
});
|
|
4021
|
-
componentRef.instance.eventMaximizeToggleRequest.subscribe((event) => {
|
|
4022
|
-
this.eventToggleMaximizeWidget(event.widgetId, event.shouldMaximize);
|
|
4023
|
-
});
|
|
4024
|
-
//Mostrar
|
|
4025
|
-
componentRef.instance.eventShowConfigFormRequest.subscribe((idWidget) => {
|
|
4026
|
-
this.eventShowFormConfigWidget(idWidget);
|
|
4027
|
-
});
|
|
4028
|
-
/* END - Eventos que provienen desde widget */
|
|
4029
|
-
// 5. Mover los nodos del DOM generados por Angular dentro del DIV del Widget
|
|
4030
|
-
this.appRef.attachView(componentRef.hostView);
|
|
4031
|
-
// Guardar la referencia de Componentes para hacer operaciones con estas.
|
|
4032
|
-
this.widgetsActivos.set(item.id, componentRef);
|
|
4033
|
-
//El componente interno no aparece bien dimensionado, con esto disparamos el evento para que se ajuste a las dimenciones correctas
|
|
4034
|
-
setTimeout(() => {
|
|
4035
|
-
window.dispatchEvent(new Event('resize'));
|
|
4036
|
-
}, 50);
|
|
4037
|
-
}
|
|
4054
|
+
//Filtro Lista - 1
|
|
4055
|
+
onFilterListChange(selectedData) {
|
|
4056
|
+
console.log('Tipos seleccionados:', selectedData);
|
|
4057
|
+
// Filtrar la información del dashboard
|
|
4058
|
+
//this.selectionChange.emit({widgetId:this.componentWidgetId,eventResponse:selectedData});
|
|
4038
4059
|
}
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
if (!componentRef) {
|
|
4044
|
-
console.warn(`No se encontró un widget activo con el ID: ${idWidget}`);
|
|
4060
|
+
//Filtro Lista - 2
|
|
4061
|
+
onFilterListCalculated(data) {
|
|
4062
|
+
if (!data) {
|
|
4063
|
+
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: null });
|
|
4045
4064
|
return;
|
|
4046
4065
|
}
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
eventUpdateWidgetControlData(idWidget, newControlData) {
|
|
4055
|
-
//Obtener la referencia del componente almacenada en el Map
|
|
4056
|
-
const componentRef = this.widgetsActivos.get(idWidget);
|
|
4057
|
-
if (!componentRef) {
|
|
4058
|
-
console.warn(`No se encontró un widget activo con el ID: ${idWidget}`);
|
|
4059
|
-
return;
|
|
4066
|
+
if (data.type === 'DATE_RANGE') {
|
|
4067
|
+
//console.log('Rango a filtrar en SQL/Dashboard:', data.dateRange?.minDate, 'hasta', data.dateRange?.maxDate);
|
|
4068
|
+
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: { minDate: data.dateRange?.minDate, maxDate: data.dateRange?.maxDate, currentNodeId: data.currentNodeId } });
|
|
4069
|
+
}
|
|
4070
|
+
else if (data.type === 'TEXT_LEAVES') {
|
|
4071
|
+
//console.log('Lista de elementos terminales seleccionados:', data.leafIds);
|
|
4072
|
+
this.selectionChange.emit({ widgetId: this.componentWidgetId, eventResponse: { ids: data.leafIds, currentNodeId: data.currentNodeId } });
|
|
4060
4073
|
}
|
|
4061
|
-
//Actualizar el Input usando la API oficial setInput
|
|
4062
|
-
componentRef.setInput('controlData', newControlData);
|
|
4063
|
-
// NOTA: setInput dispara automáticamente la detección de cambios (ChangeDetectionStrategy.OnPush).
|
|
4064
|
-
// Si deseas asegurarte manualmente, puedes forzar un render:
|
|
4065
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
4066
|
-
}
|
|
4067
|
-
/****************************************************** */
|
|
4068
|
-
/* BEGIN - DRAWER */
|
|
4069
|
-
handleShowFormFilterDrawer() {
|
|
4070
|
-
this.drawerfiltervisible = true;
|
|
4071
4074
|
}
|
|
4072
|
-
|
|
4073
|
-
this.drawerfiltervisible = false;
|
|
4075
|
+
onDeleteClick() {
|
|
4074
4076
|
}
|
|
4075
|
-
|
|
4076
|
-
this.drawerconfigvisible = false;
|
|
4077
|
+
onShowFormConfigClick() {
|
|
4077
4078
|
}
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4079
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwDashboardFilterWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4080
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwDashboardFilterWidgetComponent, isStandalone: true, selector: "yw-dashboard-filter-widget", inputs: { configWidget: { classPropertyName: "configWidget", publicName: "configWidget", isSignal: false, isRequired: false, transformFunction: null }, controlConfig: { classPropertyName: "controlConfig", publicName: "controlConfig", isSignal: true, isRequired: false, transformFunction: null }, controlData: { classPropertyName: "controlData", publicName: "controlData", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { eventDeleteRequest: "eventDeleteRequest", eventShowConfigFormRequest: "eventShowConfigFormRequest", selectionChange: "selectionChange" }, ngImport: i0, template: "\r\n<div class=\"widget-filter-action-bar\"> \r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\">\uD83D\uDDD1\uFE0F</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\">\u2699\uFE0F</button>\r\n</div>\r\n<div class=\"widget-filter-content-wrapper\">\r\n @if ( typeComponent == 'empty-visual' ) { \r\n <ng-container *ngTemplateOutlet=\"emptyvisual; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-slicer' ) { \r\n <ng-container *ngTemplateOutlet=\"filterslicer; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-button' ) { \r\n <ng-container *ngTemplateOutlet=\"filterbutton; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-list' ) { \r\n <ng-container *ngTemplateOutlet=\"filterlist; context: { control: dataWidget }\"></ng-container>\r\n } \r\n \r\n</div>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- EMPTY VISUAL TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #emptyvisual let-control = \"control\">\r\n <yw-empty-visual [idComponent]=\"control.idComponent\"\r\n [config]=\"control.controlConfig\" \r\n > \r\n </yw-empty-visual>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER SLICER TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterslicer let-control = \"control\"> \r\n @if (control.controlConfig.dataType === 'date') { \r\n <yw-base-slicer [idComponent]=\"control.idComponent\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [label]=\"control.configWidget.label\"\r\n [min]=\"control.controlConfig.min\"\r\n [max]=\"control.controlConfig.max\" \r\n [minCurrent]=\"control.controlConfig.minCurrent\"\r\n [maxCurrent]=\"control.controlConfig.maxCurrent\" \r\n (rangeChange)=\"onFilterSlicerChange($event)\"\r\n >\r\n </yw-base-slicer>\r\n }\r\n @if (control.controlConfig.dataType === 'number') { \r\n <yw-base-slicer [idComponent]=\"control.idComponent\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [label]=\"control.configWidget.label\"\r\n [min]=\"control.controlConfig.min\"\r\n [max]=\"control.controlConfig.max\"\r\n [minCurrent]=\"control.controlConfig.minCurrent\"\r\n [maxCurrent]=\"control.controlConfig.maxCurrent\"\r\n [step]=\"control.controlConfig.step\"\r\n (rangeChange)=\"onFilterSlicerChange($event)\"\r\n >\r\n </yw-base-slicer>\r\n }\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER BUTTON TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterbutton let-control = \"control\"> \r\n <yw-button-slicer [idComponent]=\"control.idComponent\" \r\n [label]=\"control.configWidget.label\"\r\n [options]=\"control.controlConfig.options\"\r\n [allowMultiple]=\"control.controlConfig.allowMultiple\"\r\n [currentIds]=\"control.controlConfig.currentIds\"\r\n (selectionChange)=\"onFilterButtonChange($event)\" \r\n >\r\n </yw-button-slicer>\r\n</ng-template>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER LIST TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterlist let-control = \"control\"> \r\n \r\n @if (control.controlConfig.dataType === 'date') { \r\n <yw-list-slicer [idComponent]=\"control.idComponent\" \r\n [label]=\"control.configWidget.label\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [minDate]=\"control.controlConfig.minDate\"\r\n [maxDate]=\"control.controlConfig.maxDate\"\r\n [dateHierarchyType]=\"control.controlConfig.dateHierarchyType\"\r\n [currentSelectedId]=\"control.controlConfig.currentSelectedId\"\r\n (selectionChange)=\"onFilterListChange($event)\"\r\n (filterValueChange)=\"onFilterListCalculated($event)\" \r\n >\r\n </yw-list-slicer>\r\n }\r\n\r\n\r\n @if (control.controlConfig.dataType === 'text') { \r\n <yw-list-slicer [idComponent]=\"control.idComponent\"\r\n [label]=\"control.configWidget.label\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [rawData]=\"control.controlConfig.rawData\"\r\n [currentSelectedId]=\"control.controlConfig.currentSelectedId\"\r\n (selectionChange)=\"onFilterListChange($event)\"\r\n (filterValueChange)=\"onFilterListCalculated($event)\" \r\n >\r\n </yw-list-slicer>\r\n }\r\n\r\n\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;width:100%;box-sizing:border-box;background-color:var(--widget-bg, #ffffff);border:1px solid var(--widget-border-color, #040404);border-radius:var(--widget-border-radius, 8px);padding:var(--widget-padding, 10px)}:host *,:host *:before,:host *:after{box-sizing:border-box}.widget-filter-action-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%}.widget-filter-content-wrapper{width:100%;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: YwEmptyVisualComponent, selector: "yw-empty-visual", inputs: ["idComponent", "config"] }, { kind: "component", type: YwBaseSlicerComponent, selector: "yw-base-slicer", inputs: ["idComponent", "dataType", "label", "min", "max", "step", "minCurrent", "maxCurrent"], outputs: ["rangeChange"] }, { kind: "component", type: YwButtonSlicerComponent, selector: "yw-button-slicer", inputs: ["idComponent", "label", "options", "allowMultiple", "currentIds"], outputs: ["selectionChange"] }, { kind: "component", type: YwListSlicerComponent, selector: "yw-list-slicer", inputs: ["idComponent", "label", "clearTitleLabel", "rawData", "dataType", "minDate", "maxDate", "dateHierarchyType", "monthNames", "currentSelectedId"], outputs: ["selectionChange", "filterValueChange"] }] }); }
|
|
4081
|
+
}
|
|
4082
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwDashboardFilterWidgetComponent, decorators: [{
|
|
4083
|
+
type: Component,
|
|
4084
|
+
args: [{ selector: 'yw-dashboard-filter-widget', standalone: true, imports: [CommonModule,
|
|
4085
|
+
YwEmptyVisualComponent,
|
|
4086
|
+
YwBaseSlicerComponent,
|
|
4087
|
+
YwButtonSlicerComponent,
|
|
4088
|
+
YwListSlicerComponent,
|
|
4089
|
+
], template: "\r\n<div class=\"widget-filter-action-bar\"> \r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-delete\" (click)=\"onDeleteClick()\">\uD83D\uDDD1\uFE0F</button>\r\n <button [hidden]=\"!varShowConfigButtons\" class=\"btn-config\" (click)=\"onShowFormConfigClick()\">\u2699\uFE0F</button>\r\n</div>\r\n<div class=\"widget-filter-content-wrapper\">\r\n @if ( typeComponent == 'empty-visual' ) { \r\n <ng-container *ngTemplateOutlet=\"emptyvisual; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-slicer' ) { \r\n <ng-container *ngTemplateOutlet=\"filterslicer; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-button' ) { \r\n <ng-container *ngTemplateOutlet=\"filterbutton; context: { control: dataWidget }\"></ng-container>\r\n }\r\n @if ( typeComponent == 'filter-list' ) { \r\n <ng-container *ngTemplateOutlet=\"filterlist; context: { control: dataWidget }\"></ng-container>\r\n } \r\n \r\n</div>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- EMPTY VISUAL TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #emptyvisual let-control = \"control\">\r\n <yw-empty-visual [idComponent]=\"control.idComponent\"\r\n [config]=\"control.controlConfig\" \r\n > \r\n </yw-empty-visual>\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER SLICER TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterslicer let-control = \"control\"> \r\n @if (control.controlConfig.dataType === 'date') { \r\n <yw-base-slicer [idComponent]=\"control.idComponent\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [label]=\"control.configWidget.label\"\r\n [min]=\"control.controlConfig.min\"\r\n [max]=\"control.controlConfig.max\" \r\n [minCurrent]=\"control.controlConfig.minCurrent\"\r\n [maxCurrent]=\"control.controlConfig.maxCurrent\" \r\n (rangeChange)=\"onFilterSlicerChange($event)\"\r\n >\r\n </yw-base-slicer>\r\n }\r\n @if (control.controlConfig.dataType === 'number') { \r\n <yw-base-slicer [idComponent]=\"control.idComponent\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [label]=\"control.configWidget.label\"\r\n [min]=\"control.controlConfig.min\"\r\n [max]=\"control.controlConfig.max\"\r\n [minCurrent]=\"control.controlConfig.minCurrent\"\r\n [maxCurrent]=\"control.controlConfig.maxCurrent\"\r\n [step]=\"control.controlConfig.step\"\r\n (rangeChange)=\"onFilterSlicerChange($event)\"\r\n >\r\n </yw-base-slicer>\r\n }\r\n</ng-template>\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER BUTTON TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterbutton let-control = \"control\"> \r\n <yw-button-slicer [idComponent]=\"control.idComponent\" \r\n [label]=\"control.configWidget.label\"\r\n [options]=\"control.controlConfig.options\"\r\n [allowMultiple]=\"control.controlConfig.allowMultiple\"\r\n [currentIds]=\"control.controlConfig.currentIds\"\r\n (selectionChange)=\"onFilterButtonChange($event)\" \r\n >\r\n </yw-button-slicer>\r\n</ng-template>\r\n\r\n\r\n<!--------------------------------------------------------------->\r\n<!---------------------- FILTER LIST TEMPLATE ---------------------->\r\n<!--------------------------------------------------------------->\r\n<ng-template #filterlist let-control = \"control\"> \r\n \r\n @if (control.controlConfig.dataType === 'date') { \r\n <yw-list-slicer [idComponent]=\"control.idComponent\" \r\n [label]=\"control.configWidget.label\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [minDate]=\"control.controlConfig.minDate\"\r\n [maxDate]=\"control.controlConfig.maxDate\"\r\n [dateHierarchyType]=\"control.controlConfig.dateHierarchyType\"\r\n [currentSelectedId]=\"control.controlConfig.currentSelectedId\"\r\n (selectionChange)=\"onFilterListChange($event)\"\r\n (filterValueChange)=\"onFilterListCalculated($event)\" \r\n >\r\n </yw-list-slicer>\r\n }\r\n\r\n\r\n @if (control.controlConfig.dataType === 'text') { \r\n <yw-list-slicer [idComponent]=\"control.idComponent\"\r\n [label]=\"control.configWidget.label\"\r\n [dataType]=\"control.controlConfig.dataType\"\r\n [rawData]=\"control.controlConfig.rawData\"\r\n [currentSelectedId]=\"control.controlConfig.currentSelectedId\"\r\n (selectionChange)=\"onFilterListChange($event)\"\r\n (filterValueChange)=\"onFilterListCalculated($event)\" \r\n >\r\n </yw-list-slicer>\r\n }\r\n\r\n\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;width:100%;box-sizing:border-box;background-color:var(--widget-bg, #ffffff);border:1px solid var(--widget-border-color, #040404);border-radius:var(--widget-border-radius, 8px);padding:var(--widget-padding, 10px)}:host *,:host *:before,:host *:after{box-sizing:border-box}.widget-filter-action-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%}.widget-filter-content-wrapper{width:100%;display:flex;flex-direction:column}\n"] }]
|
|
4090
|
+
}], ctorParameters: () => [], propDecorators: { configWidget: [{
|
|
4091
|
+
type: Input
|
|
4092
|
+
}], controlConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlConfig", required: false }] }], controlData: [{
|
|
4093
|
+
type: Input
|
|
4094
|
+
}], eventDeleteRequest: [{ type: i0.Output, args: ["eventDeleteRequest"] }], eventShowConfigFormRequest: [{ type: i0.Output, args: ["eventShowConfigFormRequest"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
|
|
4095
|
+
|
|
4096
|
+
class YwDashboardFilterComponent {
|
|
4097
|
+
constructor() {
|
|
4098
|
+
this.dashboardFilterConfig = {
|
|
4099
|
+
showConfigButtons: false,
|
|
4100
|
+
lockPositionWidgets: false,
|
|
4101
|
+
controlListConfig: []
|
|
4102
|
+
};
|
|
4103
|
+
this.dashboardData = [];
|
|
4104
|
+
this.filterSelectionChange = output();
|
|
4105
|
+
this.controlListConfig = [];
|
|
4088
4106
|
}
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
const
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
this.
|
|
4107
|
+
ngOnInit() {
|
|
4108
|
+
this.controlListConfig = [];
|
|
4109
|
+
this.dashboardFilterConfig.controlListConfig.forEach((item) => {
|
|
4110
|
+
const tableName = item.controlTable;
|
|
4111
|
+
const prmcontrolData = this.fn_getDataForWidgetFilterComponent(tableName, this.dashboardData);
|
|
4112
|
+
const prmconfigWidget = { ...item };
|
|
4113
|
+
if (item.controlFilterData) {
|
|
4114
|
+
item.configComponent = this.fnSetControlFilterCurrentValues(prmconfigWidget);
|
|
4097
4115
|
}
|
|
4098
|
-
|
|
4116
|
+
const configControl = { configWidget: prmconfigWidget,
|
|
4117
|
+
controlData: prmcontrolData,
|
|
4118
|
+
controlConfig: item.configComponent
|
|
4119
|
+
};
|
|
4120
|
+
this.controlListConfig.push(configControl);
|
|
4121
|
+
});
|
|
4099
4122
|
}
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
const minDate = item.controlFilterData['startDate'];
|
|
4108
|
-
const maxDate = item.controlFilterData['endDate'];
|
|
4109
|
-
if (minDate && maxDate) {
|
|
4110
|
-
const filterData = tableSelected.tableData.filter((y) => (minDate <= y[fieldName] && y[fieldName] <= maxDate));
|
|
4111
|
-
tableSelected.tableData = filterData;
|
|
4112
|
-
}
|
|
4113
|
-
}
|
|
4114
|
-
if (item.configComponent.dataType == 'number') {
|
|
4115
|
-
const minNum = Number(item.controlFilterData['minValue']);
|
|
4116
|
-
const maxNum = Number(item.controlFilterData['maxValue']);
|
|
4117
|
-
if (minNum && maxNum) {
|
|
4118
|
-
const filterData = tableSelected.tableData.filter((y) => (minNum <= y[fieldName] && y[fieldName] <= maxNum));
|
|
4119
|
-
tableSelected.tableData = filterData;
|
|
4120
|
-
}
|
|
4121
|
-
}
|
|
4122
|
-
}
|
|
4123
|
-
if (item.typeComponent == 'filter-button' && tableSelected && item.controlFilterData) {
|
|
4124
|
-
const fieldName = item.configComponent.filterField;
|
|
4125
|
-
const listValues = item.controlFilterData || [];
|
|
4126
|
-
if (listValues && listValues.length > 0) {
|
|
4127
|
-
const filterData = tableSelected.tableData.filter((y) => (listValues.includes(y[fieldName])));
|
|
4128
|
-
tableSelected.tableData = filterData;
|
|
4129
|
-
}
|
|
4130
|
-
}
|
|
4131
|
-
if (item.typeComponent == 'filter-list' && tableSelected && item.controlFilterData) {
|
|
4132
|
-
const fieldName = item.configComponent.filterField;
|
|
4133
|
-
if (item.configComponent.dataType == 'text') {
|
|
4134
|
-
const listValues = item.controlFilterData['ids'] || [];
|
|
4135
|
-
if (listValues && listValues.length > 0) {
|
|
4136
|
-
const listValues1D = listValues;
|
|
4137
|
-
const filterData = tableSelected.tableData.filter((y) => (listValues1D.includes(y[fieldName])));
|
|
4138
|
-
tableSelected.tableData = filterData;
|
|
4139
|
-
}
|
|
4140
|
-
}
|
|
4141
|
-
if (item.configComponent.dataType == 'date') {
|
|
4142
|
-
const minDate = item.controlFilterData['minDate'];
|
|
4143
|
-
const maxDate = item.controlFilterData['maxDate'];
|
|
4144
|
-
if (minDate && maxDate) {
|
|
4145
|
-
const filterData = tableSelected.tableData.filter((y) => (minDate <= y[fieldName] && y[fieldName] <= maxDate));
|
|
4146
|
-
tableSelected.tableData = filterData;
|
|
4147
|
-
}
|
|
4148
|
-
}
|
|
4123
|
+
//Filtrar Datos por Componente del Widget
|
|
4124
|
+
fn_getDataForWidgetFilterComponent(prmTableName, prmdashboardData) {
|
|
4125
|
+
let dataresponse = [];
|
|
4126
|
+
const ldsize = prmdashboardData.length;
|
|
4127
|
+
prmdashboardData.forEach((curTableRef) => {
|
|
4128
|
+
if (prmTableName.localeCompare(curTableRef.tableName) == 0) {
|
|
4129
|
+
dataresponse = curTableRef.tableData;
|
|
4149
4130
|
}
|
|
4150
4131
|
});
|
|
4151
|
-
|
|
4152
|
-
this.dashboardConfig.controlListConfig.forEach((item) => {
|
|
4153
|
-
const controlData = this.fn_getDataForWidgetComponent(item.controlTables, copyDashboardData);
|
|
4154
|
-
this.eventUpdateWidgetControlData(item.widgetId, controlData);
|
|
4155
|
-
});
|
|
4132
|
+
return dataresponse;
|
|
4156
4133
|
}
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4134
|
+
onFilterChange(eventData) {
|
|
4135
|
+
this.filterSelectionChange.emit({ widgetId: eventData.widgetId, eventResponse: eventData.eventResponse });
|
|
4136
|
+
}
|
|
4137
|
+
fnSetControlFilterCurrentValues(prmControlConfig) {
|
|
4138
|
+
if (prmControlConfig.typeComponent == 'filter-slicer') {
|
|
4139
|
+
let curConfigComponent = prmControlConfig.configComponent;
|
|
4140
|
+
if (prmControlConfig.configComponent.dataType == 'date') {
|
|
4141
|
+
curConfigComponent.minCurrent = prmControlConfig.controlFilterData['startDate'];
|
|
4142
|
+
curConfigComponent.maxCurrent = prmControlConfig.controlFilterData['endDate'];
|
|
4143
|
+
}
|
|
4144
|
+
if (prmControlConfig.configComponent.dataType == 'number') {
|
|
4145
|
+
curConfigComponent.minCurrent = prmControlConfig.controlFilterData['minValue'];
|
|
4146
|
+
curConfigComponent.maxCurrent = prmControlConfig.controlFilterData['maxValue'];
|
|
4147
|
+
}
|
|
4148
|
+
return curConfigComponent;
|
|
4166
4149
|
}
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
this.appRef.detachView(componentRef.hostView);
|
|
4172
|
-
// Destruye el componente y libera la memoria RAM
|
|
4173
|
-
componentRef.destroy();
|
|
4174
|
-
// Eliminamos el registro de nuestro Mapa
|
|
4175
|
-
this.widgetsActivos.delete(widgetId);
|
|
4150
|
+
if (prmControlConfig.typeComponent == 'filter-button') {
|
|
4151
|
+
let curConfigComponent = prmControlConfig.configComponent;
|
|
4152
|
+
curConfigComponent.currentIds = prmControlConfig.controlFilterData || [];
|
|
4153
|
+
return curConfigComponent;
|
|
4176
4154
|
}
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
if (elementoHtml) {
|
|
4182
|
-
// La API de Gridstack nos permite congelar un nodo específico pasándole true/false
|
|
4183
|
-
this.grid.movable(elementoHtml, !shouldLock);
|
|
4184
|
-
this.grid.resizable(elementoHtml, !shouldLock);
|
|
4185
|
-
//console.log(`Widget ${widgetId} cambiado a estado bloqueado: ${shouldLock}`);
|
|
4155
|
+
if (prmControlConfig.typeComponent == 'filter-list') {
|
|
4156
|
+
let curConfigComponent = prmControlConfig.configComponent;
|
|
4157
|
+
curConfigComponent.currentSelectedId = prmControlConfig.controlFilterData['currentNodeId'];
|
|
4158
|
+
return curConfigComponent;
|
|
4186
4159
|
}
|
|
4187
4160
|
}
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
this.
|
|
4196
|
-
this.grid.resizable(elementoHtml, false);
|
|
4197
|
-
}
|
|
4198
|
-
else {
|
|
4199
|
-
elementoHtml.classList.remove('widget-maximized');
|
|
4200
|
-
// Restauramos los permisos normales leyendo si el componente de Angular estaba bloqueado previamente
|
|
4201
|
-
const componentRef = this.widgetsActivos.get(widgetId);
|
|
4202
|
-
const isCurrentlyLocked = componentRef?.instance.isLocked() || false;
|
|
4203
|
-
this.grid.movable(elementoHtml, !isCurrentlyLocked);
|
|
4204
|
-
this.grid.resizable(elementoHtml, !isCurrentlyLocked);
|
|
4161
|
+
handleClearFilter() {
|
|
4162
|
+
this.controlListConfig = [];
|
|
4163
|
+
this.dashboardFilterConfig.controlListConfig.forEach((item) => {
|
|
4164
|
+
const tableName = item.controlTable;
|
|
4165
|
+
const prmcontrolData = this.fn_getDataForWidgetFilterComponent(tableName, this.dashboardData);
|
|
4166
|
+
const prmconfigWidget = { ...item };
|
|
4167
|
+
if (item.controlFilterData) {
|
|
4168
|
+
item.configComponent = this.fnSetControlFilterClearValues(prmconfigWidget);
|
|
4205
4169
|
}
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
}
|
|
4210
|
-
|
|
4170
|
+
const configControl = { configWidget: prmconfigWidget,
|
|
4171
|
+
controlData: prmcontrolData,
|
|
4172
|
+
controlConfig: item.configComponent
|
|
4173
|
+
};
|
|
4174
|
+
this.controlListConfig.push(configControl);
|
|
4175
|
+
});
|
|
4211
4176
|
}
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4177
|
+
fnSetControlFilterClearValues(prmControlConfig) {
|
|
4178
|
+
if (prmControlConfig.typeComponent == 'filter-slicer') {
|
|
4179
|
+
let curConfigComponent = prmControlConfig.configComponent;
|
|
4180
|
+
curConfigComponent.minCurrent = null;
|
|
4181
|
+
curConfigComponent.maxCurrent = null;
|
|
4182
|
+
return curConfigComponent;
|
|
4183
|
+
}
|
|
4184
|
+
if (prmControlConfig.typeComponent == 'filter-button') {
|
|
4185
|
+
let curConfigComponent = prmControlConfig.configComponent;
|
|
4186
|
+
curConfigComponent.currentIds = [];
|
|
4187
|
+
return curConfigComponent;
|
|
4188
|
+
}
|
|
4189
|
+
if (prmControlConfig.typeComponent == 'filter-list') {
|
|
4190
|
+
let curConfigComponent = prmControlConfig.configComponent;
|
|
4191
|
+
curConfigComponent.currentSelectedId = null;
|
|
4192
|
+
return curConfigComponent;
|
|
4193
|
+
}
|
|
4215
4194
|
}
|
|
4216
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
4217
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwDashboardComponent, isStandalone: true, selector: "yw-dashboard", inputs: { showControls: { classPropertyName: "showControls", publicName: "showControls", isSignal: true, isRequired: false, transformFunction: null }, showFilter: { classPropertyName: "showFilter", publicName: "showFilter", isSignal: true, isRequired: false, transformFunction: null }, dashboardStyle: { classPropertyName: "dashboardStyle", publicName: "dashboardStyle", isSignal: false, isRequired: false, transformFunction: null }, dashboardConfig: { classPropertyName: "dashboardConfig", publicName: "dashboardConfig", isSignal: false, isRequired: false, transformFunction: null }, dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: false, isRequired: false, transformFunction: null }, dashboardFilterConfig: { classPropertyName: "dashboardFilterConfig", publicName: "dashboardFilterConfig", isSignal: false, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "gridContainer", first: true, predicate: ["gridContainer"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<!-- <div class=\"controls\" [hidden]=\"!showControls()\">\r\n <button (click)=\"saveLayoutToJSON()\">Guardar JSON en Consola</button>\r\n <button (click)=\"fn_btn_addWidget()\">add widget</button>\r\n <button (click)=\"fn_btn_lockPositionWidgets()\">Lock widgets</button>\r\n <button (click)=\"handleShowFormFilterDrawer()\" class=\"btn-filtro\">\r\n <svg *ngIf=\"drawerfiltervisible; else filtroInactivo\" \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"20\" height=\"20\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"/>\r\n </svg>\r\n <ng-template #filtroInactivo>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"20\" height=\"20\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"none\" \r\n stroke=\"currentColor\" \r\n stroke-width=\"2\">\r\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>\r\n </svg>\r\n </ng-template>\r\n </button>\r\n</div> -->\r\n\r\n<div class=\"controls-container\" >\r\n @if ( showControls() ) { \r\n <!-- Botones principales con nz-button y tipos de Ant Design -->\r\n <button nz-button nzType=\"default\" (click)=\"saveLayoutToJSON()\" >\r\n <span nz-icon nz-type=\"code\"></span> Guardar JSON\r\n </button>\r\n\r\n <button nz-button nzType=\"primary\" (click)=\"fn_btn_addWidget()\" >\r\n <span nz-icon nz-type=\"plus\"></span> A\u00F1adir widget\r\n </button>\r\n\r\n <button nz-button [nzType]=\"isLocked ? 'primary' : 'default'\" nzDanger (click)=\"fn_btn_lockPositionWidgets()\" >\r\n <span nz-icon [nzType]=\"isLocked ? 'lock' : 'unlock'\"></span> \r\n {{ isLocked ? 'Bloqueado' : 'Bloquear' }}\r\n </button>\r\n }\r\n @if ( showFilter() ) { \r\n <!-- Bot\u00F3n de filtro con estilo ic\u00F3nico -->\r\n <button nz-button nzType=\"default\" nzShape=\"circle\" (click)=\"handleShowFormFilterDrawer()\" class=\"btn-filtro\" [class.active]=\"drawerfiltervisible\" >\r\n <svg *ngIf=\"drawerfiltervisible; else filtroInactivo\" \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"/>\r\n </svg>\r\n <ng-template #filtroInactivo>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"none\" \r\n stroke=\"currentColor\" \r\n stroke-width=\"2\">\r\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>\r\n </svg>\r\n </ng-template>\r\n </button>\r\n }\r\n</div>\r\n<div #gridContainer class=\"grid-stack canvas-container\"\r\n [style.--canvas-bg]=\"dashboardStyle.canvasBackgroundColor\"\r\n></div>\r\n\r\n\r\n\r\n\r\n<!-- DRAWER - FILTER -->\r\n\r\n<nz-drawer\r\n[nzVisible]=\"drawerfiltervisible\"\r\n[nzMaskClosable]=\"false\"\r\nnzPlacement=\"right\"\r\n[nzWidth]=\"fnGetDrawerWidth(50)\"\r\n(nzOnClose)=\"handleCloseFormFilterDrawer()\"\r\n>\r\n<ng-container *nzDrawerContent>\r\n <div class=\"widget-details-info\">\r\n <h6 nz-typography>Filtros</h6>\r\n <yw-dashboard-filter\r\n [dashboardFilterConfig]=\"dashboardFilterConfig\"\r\n [dashboardData]=\"dashboardData\"\r\n (filterSelectionChange)=\"onFilterSelectionChange($event)\"\r\n >\r\n </yw-dashboard-filter>\r\n </div>\r\n\r\n <!--\r\n <nz-tabset nzCentered>\r\n <nz-tab nzTitle=\"Secion de Filtros\">\r\n <div class=\"controls\">\r\n aqui botones de control:\r\n\r\n </div>\r\n <div>\r\n \r\n\r\n </div>\r\n\r\n </nz-tab>\r\n \r\n </nz-tabset>\r\n-->\r\n</ng-container>\r\n</nz-drawer>\r\n\r\n\r\n\r\n<!-- DRAWER - CONFIGURACION -->\r\n<nz-drawer\r\n[nzVisible]=\"drawerconfigvisible\"\r\n[nzMaskClosable]=\"false\"\r\nnzPlacement=\"right\"\r\n[nzWidth]=\"fnGetDrawerWidth(50)\"\r\n(nzOnClose)=\"handleCloseFormDrawer()\"\r\n>\r\n<ng-container *nzDrawerContent>\r\n <div class=\"widget-details-info\">\r\n <h6 nz-typography>{{ drawerCurrentWidgetObject.widgetId }}</h6>\r\n </div>\r\n <nz-tabset nzCentered>\r\n <nz-tab nzTitle=\"{{ drawerCurrentWidgetObject.widgetId }}\">\r\n <div class=\"controls\">\r\n <button (click)=\"fn_btn_updateWidgetControlConfig(drawerCurrentWidgetObject.widgetId)\">Actualiza Configuracion</button>\r\n <button (click)=\"fn_btn_updateWidgetControlData(drawerCurrentWidgetObject.widgetId)\">Actualiza Data</button> \r\n </div>\r\n <div>\r\n bla bla bla\r\n </div>\r\n\r\n </nz-tab>\r\n \r\n </nz-tabset>\r\n</ng-container>\r\n</nz-drawer>", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.canvas-container{background-color:var(--canvas-bg, #f5f5f5);min-height:500px;padding:10px}::vdeep .card-inner{background:#fff;border:1px solid #ccc;height:100%;display:flex;align-items:center;justify-content:center}:host ::ng-deep .grid-stack-item-content{border-radius:6px;box-shadow:0 2px 5px #0000001a;display:flex;align-items:center;justify-content:center;font-weight:700;overflow:hidden}::ng-deep .grid-stack-item.widget-maximized{position:fixed!important;top:0!important;left:0!important;width:100vw!important;height:100vh!important;z-index:9999!important;transform:none!important;margin:0!important;padding:5px}::ng-deep .grid-stack-item.widget-maximized .grid-stack-item-content{position:absolute!important;inset:0!important;width:100%!important;height:100%!important;margin:0!important;padding:0!important;border:none!important;border-radius:0!important;box-shadow:none!important;background-color:#fff!important;overflow:hidden}::ng-deep .grid-stack>.grid-stack-item>.ui-resizable-handle{opacity:0!important;background-image:none!important}.widget-details-info{padding-top:30px;text-align:center}.widget-details-info h6{font-family:manrope,sans-serif;font-size:20px;font-weight:700;line-height:26px;color:#2d3144}.widget-details-info p{font-family:manrope,sans-serif;font-size:14px;font-weight:400;line-height:21px;color:#4b5064}.controls-container{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:12px 16px;background:#fff;border-bottom:1px solid #f0f0f0;box-shadow:0 2px 8px #0000000a;border-radius:6px;margin-bottom:16px;width:100%;box-sizing:border-box}.controls-container button{white-space:nowrap}.controls-container .btn-filtro{display:inline-flex;align-items:center;justify-content:center;padding:0;width:32px;height:32px;border-radius:50%;transition:all .3s ease}.controls-container .btn-filtro.active{color:#fff;background-color:#1890ff;border-color:#1890ff}.controls-container .btn-filtro.active:hover{background-color:#40a9ff;border-color:#40a9ff}@media(max-width:576px){.controls-container{gap:8px;padding:8px 10px}.controls-container button[nz-button]{font-size:13px;padding:0 10px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: NzDrawerModule }, { kind: "component", type: i2.NzDrawerComponent, selector: "nz-drawer", inputs: ["nzContent", "nzCloseIcon", "nzClosable", "nzMaskClosable", "nzMask", "nzCloseOnNavigation", "nzNoAnimation", "nzKeyboard", "nzTitle", "nzExtra", "nzFooter", "nzPlacement", "nzSize", "nzMaskStyle", "nzBodyStyle", "nzWrapClassName", "nzWidth", "nzHeight", "nzZIndex", "nzOffsetX", "nzOffsetY", "nzVisible"], outputs: ["nzOnViewInit", "nzOnClose", "nzVisibleChange"], exportAs: ["nzDrawer"] }, { kind: "directive", type: i2.NzDrawerContentDirective, selector: "[nzDrawerContent]", exportAs: ["nzDrawerContent"] }, { kind: "ngmodule", type: NzTabsModule }, { kind: "component", type: i3.NzTabsComponent, selector: "nz-tabs,nz-tabset", inputs: ["nzSelectedIndex", "nzTabPosition", "nzTabBarExtraContent", "nzCanDeactivate", "nzAddIcon", "nzTabBarStyle", "nzType", "nzSize", "nzAnimated", "nzTabBarGutter", "nzHideAdd", "nzCentered", "nzHideAll", "nzLinkRouter", "nzLinkExact", "nzDestroyInactiveTabPane"], outputs: ["nzSelectChange", "nzSelectedIndexChange", "nzTabListScroll", "nzClose", "nzAdd"], exportAs: ["nzTabs"] }, { kind: "component", type: i3.NzTabComponent, selector: "nz-tab", inputs: ["nzTitle", "nzClosable", "nzCloseIcon", "nzDisabled", "nzForceRender"], outputs: ["nzSelect", "nzDeselect", "nzClick", "nzContextmenu"], exportAs: ["nzTab"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i1$3.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i5.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i6.ɵNzTransitionPatchDirective, selector: "[nz-button], [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "directive", type: i7.NzWaveDirective, selector: "[nz-wave],button[nz-button]:not([nzType=\"link\"]):not([nzType=\"text\"])", inputs: ["nzWaveExtraNode"], exportAs: ["nzWave"] }, { kind: "component", type: YwDashboardFilterComponent, selector: "yw-dashboard-filter", inputs: ["dashboardFilterConfig", "dashboardData"], outputs: ["filterSelectionChange"] }] }); }
|
|
4195
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwDashboardFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4196
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwDashboardFilterComponent, isStandalone: true, selector: "yw-dashboard-filter", inputs: { dashboardFilterConfig: "dashboardFilterConfig", dashboardData: "dashboardData" }, outputs: { filterSelectionChange: "filterSelectionChange" }, ngImport: i0, template: "\r\n <div class=\"dashboard-filter-content-bar\">\r\n @if ( dashboardFilterConfig.showConfigButtons ) { \r\n <button nz-button nzType=\"primary\" >\r\n <span nz-icon nz-type=\"plus\"></span> A\u00F1adir widget\r\n </button>\r\n }\r\n <button nz-button \r\n nzType=\"default\" \r\n nzShape=\"circle\" \r\n (click)=\"handleClearFilter()\" \r\n class=\"btn-clean\" \r\n > \r\n <!-- Icono de Borrador (Eraser) activo / relleno --> \r\n <svg \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M16.24 3.56a2.12 2.12 0 0 1 3 0l1.2 1.2a2.12 2.12 0 0 1 0 3l-8.5 8.5H6.5a1.5 1.5 0 0 1-1.5-1.5v-5.44l11.24-11.24zM19 19H5a1 1 0 0 1 0-2h14a1 1 0 0 1 0 2z\"/>\r\n </svg>\r\n \r\n </button>\r\n </div>\r\n\r\n <div class=\"dashboard-filter-content-wrapper\">\r\n @for ( colFilter of controlListConfig; track colFilter) { \r\n <div class=\"dashboard-filter-content-wrapper-item\">\r\n \r\n <yw-dashboard-filter-widget \r\n [configWidget]=\"colFilter.configWidget\"\r\n [controlConfig]=\"colFilter.controlConfig\"\r\n [controlData]=\"colFilter.controlData\"\r\n (selectionChange)=\"onFilterChange($event)\"\r\n > \r\n </yw-dashboard-filter-widget>\r\n\r\n </div>\r\n }\r\n </div>", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden;box-sizing:border-box}.dashboard-filter-content-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%;box-sizing:border-box}.dashboard-filter-content-wrapper{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;width:100%;display:flex;flex-direction:column;box-sizing:border-box}.dashboard-filter-content-wrapper-item{padding-bottom:5px}.btn-clean{display:inline-flex;align-items:center;justify-content:center;padding:0;width:32px;height:32px;border-radius:50%;transition:all .3s ease}.btn-clean.active{color:#fff;background-color:#1890ff;border-color:#1890ff}.btn-clean.active:hover{background-color:#40a9ff;border-color:#40a9ff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: YwDashboardFilterWidgetComponent, selector: "yw-dashboard-filter-widget", inputs: ["configWidget", "controlConfig", "controlData"], outputs: ["eventDeleteRequest", "eventShowConfigFormRequest", "selectionChange"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i1$3.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i5.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i6.ɵNzTransitionPatchDirective, selector: "[nz-button], [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "directive", type: i7.NzWaveDirective, selector: "[nz-wave],button[nz-button]:not([nzType=\"link\"]):not([nzType=\"text\"])", inputs: ["nzWaveExtraNode"], exportAs: ["nzWave"] }] }); }
|
|
4218
4197
|
}
|
|
4219
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
4198
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwDashboardFilterComponent, decorators: [{
|
|
4220
4199
|
type: Component,
|
|
4221
|
-
args: [{ selector: 'yw-dashboard', standalone: true, imports: [CommonModule,
|
|
4222
|
-
|
|
4223
|
-
NzDrawerModule,
|
|
4224
|
-
NzTabsModule,
|
|
4225
|
-
YwBaseSlicerComponent,
|
|
4200
|
+
args: [{ selector: 'yw-dashboard-filter', standalone: true, imports: [CommonModule,
|
|
4201
|
+
YwDashboardFilterWidgetComponent,
|
|
4226
4202
|
NzIconModule,
|
|
4227
4203
|
NzButtonModule,
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
YwDashboardFilterComponent
|
|
4231
|
-
], template: "<!-- <div class=\"controls\" [hidden]=\"!showControls()\">\r\n <button (click)=\"saveLayoutToJSON()\">Guardar JSON en Consola</button>\r\n <button (click)=\"fn_btn_addWidget()\">add widget</button>\r\n <button (click)=\"fn_btn_lockPositionWidgets()\">Lock widgets</button>\r\n <button (click)=\"handleShowFormFilterDrawer()\" class=\"btn-filtro\">\r\n <svg *ngIf=\"drawerfiltervisible; else filtroInactivo\" \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"20\" height=\"20\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"/>\r\n </svg>\r\n <ng-template #filtroInactivo>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"20\" height=\"20\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"none\" \r\n stroke=\"currentColor\" \r\n stroke-width=\"2\">\r\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>\r\n </svg>\r\n </ng-template>\r\n </button>\r\n</div> -->\r\n\r\n<div class=\"controls-container\" >\r\n @if ( showControls() ) { \r\n <!-- Botones principales con nz-button y tipos de Ant Design -->\r\n <button nz-button nzType=\"default\" (click)=\"saveLayoutToJSON()\" >\r\n <span nz-icon nz-type=\"code\"></span> Guardar JSON\r\n </button>\r\n\r\n <button nz-button nzType=\"primary\" (click)=\"fn_btn_addWidget()\" >\r\n <span nz-icon nz-type=\"plus\"></span> A\u00F1adir widget\r\n </button>\r\n\r\n <button nz-button [nzType]=\"isLocked ? 'primary' : 'default'\" nzDanger (click)=\"fn_btn_lockPositionWidgets()\" >\r\n <span nz-icon [nzType]=\"isLocked ? 'lock' : 'unlock'\"></span> \r\n {{ isLocked ? 'Bloqueado' : 'Bloquear' }}\r\n </button>\r\n }\r\n @if ( showFilter() ) { \r\n <!-- Bot\u00F3n de filtro con estilo ic\u00F3nico -->\r\n <button nz-button nzType=\"default\" nzShape=\"circle\" (click)=\"handleShowFormFilterDrawer()\" class=\"btn-filtro\" [class.active]=\"drawerfiltervisible\" >\r\n <svg *ngIf=\"drawerfiltervisible; else filtroInactivo\" \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"/>\r\n </svg>\r\n <ng-template #filtroInactivo>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"none\" \r\n stroke=\"currentColor\" \r\n stroke-width=\"2\">\r\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>\r\n </svg>\r\n </ng-template>\r\n </button>\r\n }\r\n</div>\r\n<div #gridContainer class=\"grid-stack canvas-container\"\r\n [style.--canvas-bg]=\"dashboardStyle.canvasBackgroundColor\"\r\n></div>\r\n\r\n\r\n\r\n\r\n<!-- DRAWER - FILTER -->\r\n\r\n<nz-drawer\r\n[nzVisible]=\"drawerfiltervisible\"\r\n[nzMaskClosable]=\"false\"\r\nnzPlacement=\"right\"\r\n[nzWidth]=\"fnGetDrawerWidth(50)\"\r\n(nzOnClose)=\"handleCloseFormFilterDrawer()\"\r\n>\r\n<ng-container *nzDrawerContent>\r\n <div class=\"widget-details-info\">\r\n <h6 nz-typography>Filtros</h6>\r\n <yw-dashboard-filter\r\n [dashboardFilterConfig]=\"dashboardFilterConfig\"\r\n [dashboardData]=\"dashboardData\"\r\n (filterSelectionChange)=\"onFilterSelectionChange($event)\"\r\n >\r\n </yw-dashboard-filter>\r\n </div>\r\n\r\n <!--\r\n <nz-tabset nzCentered>\r\n <nz-tab nzTitle=\"Secion de Filtros\">\r\n <div class=\"controls\">\r\n aqui botones de control:\r\n\r\n </div>\r\n <div>\r\n \r\n\r\n </div>\r\n\r\n </nz-tab>\r\n \r\n </nz-tabset>\r\n-->\r\n</ng-container>\r\n</nz-drawer>\r\n\r\n\r\n\r\n<!-- DRAWER - CONFIGURACION -->\r\n<nz-drawer\r\n[nzVisible]=\"drawerconfigvisible\"\r\n[nzMaskClosable]=\"false\"\r\nnzPlacement=\"right\"\r\n[nzWidth]=\"fnGetDrawerWidth(50)\"\r\n(nzOnClose)=\"handleCloseFormDrawer()\"\r\n>\r\n<ng-container *nzDrawerContent>\r\n <div class=\"widget-details-info\">\r\n <h6 nz-typography>{{ drawerCurrentWidgetObject.widgetId }}</h6>\r\n </div>\r\n <nz-tabset nzCentered>\r\n <nz-tab nzTitle=\"{{ drawerCurrentWidgetObject.widgetId }}\">\r\n <div class=\"controls\">\r\n <button (click)=\"fn_btn_updateWidgetControlConfig(drawerCurrentWidgetObject.widgetId)\">Actualiza Configuracion</button>\r\n <button (click)=\"fn_btn_updateWidgetControlData(drawerCurrentWidgetObject.widgetId)\">Actualiza Data</button> \r\n </div>\r\n <div>\r\n bla bla bla\r\n </div>\r\n\r\n </nz-tab>\r\n \r\n </nz-tabset>\r\n</ng-container>\r\n</nz-drawer>", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.canvas-container{background-color:var(--canvas-bg, #f5f5f5);min-height:500px;padding:10px}::vdeep .card-inner{background:#fff;border:1px solid #ccc;height:100%;display:flex;align-items:center;justify-content:center}:host ::ng-deep .grid-stack-item-content{border-radius:6px;box-shadow:0 2px 5px #0000001a;display:flex;align-items:center;justify-content:center;font-weight:700;overflow:hidden}::ng-deep .grid-stack-item.widget-maximized{position:fixed!important;top:0!important;left:0!important;width:100vw!important;height:100vh!important;z-index:9999!important;transform:none!important;margin:0!important;padding:5px}::ng-deep .grid-stack-item.widget-maximized .grid-stack-item-content{position:absolute!important;inset:0!important;width:100%!important;height:100%!important;margin:0!important;padding:0!important;border:none!important;border-radius:0!important;box-shadow:none!important;background-color:#fff!important;overflow:hidden}::ng-deep .grid-stack>.grid-stack-item>.ui-resizable-handle{opacity:0!important;background-image:none!important}.widget-details-info{padding-top:30px;text-align:center}.widget-details-info h6{font-family:manrope,sans-serif;font-size:20px;font-weight:700;line-height:26px;color:#2d3144}.widget-details-info p{font-family:manrope,sans-serif;font-size:14px;font-weight:400;line-height:21px;color:#4b5064}.controls-container{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:12px 16px;background:#fff;border-bottom:1px solid #f0f0f0;box-shadow:0 2px 8px #0000000a;border-radius:6px;margin-bottom:16px;width:100%;box-sizing:border-box}.controls-container button{white-space:nowrap}.controls-container .btn-filtro{display:inline-flex;align-items:center;justify-content:center;padding:0;width:32px;height:32px;border-radius:50%;transition:all .3s ease}.controls-container .btn-filtro.active{color:#fff;background-color:#1890ff;border-color:#1890ff}.controls-container .btn-filtro.active:hover{background-color:#40a9ff;border-color:#40a9ff}@media(max-width:576px){.controls-container{gap:8px;padding:8px 10px}.controls-container button[nz-button]{font-size:13px;padding:0 10px}}\n"] }]
|
|
4232
|
-
}], ctorParameters: () => [{ type: i0.EnvironmentInjector }, { type: i0.ApplicationRef }], propDecorators: { gridContainer: [{
|
|
4233
|
-
type: ViewChild,
|
|
4234
|
-
args: ['gridContainer', { static: true }]
|
|
4235
|
-
}], showControls: [{ type: i0.Input, args: [{ isSignal: true, alias: "showControls", required: false }] }], showFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFilter", required: false }] }], dashboardStyle: [{
|
|
4236
|
-
type: Input
|
|
4237
|
-
}], dashboardConfig: [{
|
|
4204
|
+
], template: "\r\n <div class=\"dashboard-filter-content-bar\">\r\n @if ( dashboardFilterConfig.showConfigButtons ) { \r\n <button nz-button nzType=\"primary\" >\r\n <span nz-icon nz-type=\"plus\"></span> A\u00F1adir widget\r\n </button>\r\n }\r\n <button nz-button \r\n nzType=\"default\" \r\n nzShape=\"circle\" \r\n (click)=\"handleClearFilter()\" \r\n class=\"btn-clean\" \r\n > \r\n <!-- Icono de Borrador (Eraser) activo / relleno --> \r\n <svg \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M16.24 3.56a2.12 2.12 0 0 1 3 0l1.2 1.2a2.12 2.12 0 0 1 0 3l-8.5 8.5H6.5a1.5 1.5 0 0 1-1.5-1.5v-5.44l11.24-11.24zM19 19H5a1 1 0 0 1 0-2h14a1 1 0 0 1 0 2z\"/>\r\n </svg>\r\n \r\n </button>\r\n </div>\r\n\r\n <div class=\"dashboard-filter-content-wrapper\">\r\n @for ( colFilter of controlListConfig; track colFilter) { \r\n <div class=\"dashboard-filter-content-wrapper-item\">\r\n \r\n <yw-dashboard-filter-widget \r\n [configWidget]=\"colFilter.configWidget\"\r\n [controlConfig]=\"colFilter.controlConfig\"\r\n [controlData]=\"colFilter.controlData\"\r\n (selectionChange)=\"onFilterChange($event)\"\r\n > \r\n </yw-dashboard-filter-widget>\r\n\r\n </div>\r\n }\r\n </div>", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden;box-sizing:border-box}.dashboard-filter-content-bar{display:flex;justify-content:flex-end;gap:4px;padding:5px 10px;flex-shrink:0;width:100%;box-sizing:border-box}.dashboard-filter-content-wrapper{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;width:100%;display:flex;flex-direction:column;box-sizing:border-box}.dashboard-filter-content-wrapper-item{padding-bottom:5px}.btn-clean{display:inline-flex;align-items:center;justify-content:center;padding:0;width:32px;height:32px;border-radius:50%;transition:all .3s ease}.btn-clean.active{color:#fff;background-color:#1890ff;border-color:#1890ff}.btn-clean.active:hover{background-color:#40a9ff;border-color:#40a9ff}\n"] }]
|
|
4205
|
+
}], ctorParameters: () => [], propDecorators: { dashboardFilterConfig: [{
|
|
4238
4206
|
type: Input
|
|
4239
4207
|
}], dashboardData: [{
|
|
4240
4208
|
type: Input
|
|
4241
|
-
}],
|
|
4242
|
-
type: Input
|
|
4243
|
-
}] } });
|
|
4209
|
+
}], filterSelectionChange: [{ type: i0.Output, args: ["filterSelectionChange"] }] } });
|
|
4244
4210
|
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4211
|
+
/* END - FILTROS */
|
|
4212
|
+
class YwDashboardComponent {
|
|
4213
|
+
/* */
|
|
4214
|
+
constructor(environmentInjector, appRef) {
|
|
4215
|
+
//Configurar Bloqueo de Widgets
|
|
4216
|
+
/*
|
|
4217
|
+
effect(() => {
|
|
4218
|
+
const isLocked = this.allIsLocked();
|
|
4219
|
+
console.log('El estado de bloqueo cambió a:', isLocked);
|
|
4220
|
+
this.fn_lockPositionWidgets(isLocked);
|
|
4221
|
+
});
|
|
4222
|
+
*/
|
|
4223
|
+
this.environmentInjector = environmentInjector;
|
|
4224
|
+
this.appRef = appRef;
|
|
4225
|
+
this.widgetsActivos = new Map();
|
|
4226
|
+
this.showControls = input(false, ...(ngDevMode ? [{ debugName: "showControls" }] : []));
|
|
4227
|
+
this.showFilter = input(false, ...(ngDevMode ? [{ debugName: "showFilter" }] : []));
|
|
4228
|
+
this.allIsLocked = signal(false, ...(ngDevMode ? [{ debugName: "allIsLocked" }] : []));
|
|
4229
|
+
this.drawerfiltervisible = false;
|
|
4230
|
+
this.drawerconfigvisible = false;
|
|
4231
|
+
this.drawerCurrentWidgetObject = {};
|
|
4232
|
+
this.isLocked = false;
|
|
4233
|
+
this.countWidget = 1;
|
|
4234
|
+
this.layoutConfig = {
|
|
4235
|
+
margin: 10,
|
|
4236
|
+
cellHeight: 100,
|
|
4237
|
+
columns: 24
|
|
4238
|
+
};
|
|
4239
|
+
/* ejemplo de Items
|
|
4240
|
+
items: [
|
|
4241
|
+
{ id: 'div-1', x: 0, y: 0, w: 14, h: 2, content: 'DIV 1' , contentData : {}},
|
|
4242
|
+
{ id: 'div-2', x: 5, y: 2, w: 19, h: 1, content: 'DIV 2' , contentData : {}},
|
|
4243
|
+
{ id: 'div-3', x: 0, y: 3, w: 22, h: 1, content: 'DIV 3', contentData : {} }
|
|
4244
|
+
]
|
|
4245
|
+
*/
|
|
4246
|
+
this.dashboardStyle = {
|
|
4247
|
+
canvasBackgroundColor: "#f5f5f5",
|
|
4248
|
+
widgetBackgroundColor: "#ffffff",
|
|
4249
|
+
widgetBorderColor: "#007bff"
|
|
4250
|
+
};
|
|
4251
|
+
this.dashboardConfig = {
|
|
4252
|
+
showConfigButtons: false,
|
|
4253
|
+
lockPositionWidgets: false,
|
|
4254
|
+
layoutConfig: {
|
|
4255
|
+
margin: 0,
|
|
4256
|
+
cellHeight: 0,
|
|
4257
|
+
columns: 0
|
|
4258
|
+
},
|
|
4259
|
+
controlListConfig: []
|
|
4260
|
+
};
|
|
4261
|
+
this.dashboardData = [];
|
|
4262
|
+
this.dashboardItems = [];
|
|
4263
|
+
/* REF FILTROS */
|
|
4264
|
+
this.dashboardFilterConfig = {
|
|
4265
|
+
showConfigButtons: false,
|
|
4266
|
+
lockPositionWidgets: false,
|
|
4267
|
+
controlListConfig: []
|
|
4268
|
+
};
|
|
4248
4269
|
}
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
if (Array.isArray(allTablesData)) {
|
|
4252
|
-
const defaultTableName = configData_?.configData?.table || 'default';
|
|
4253
|
-
allTablesData = { [defaultTableName]: allTablesData };
|
|
4270
|
+
ngOnInit() {
|
|
4271
|
+
// console.log("DATA QUE LLEGA AL DASHBOARD:",this.dashboardConfig)
|
|
4254
4272
|
}
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4273
|
+
ngOnChanges(changes) {
|
|
4274
|
+
if (changes['dashboardConfig']) {
|
|
4275
|
+
console.log('Nuevo valor dashboardConfig:', this.dashboardConfig);
|
|
4276
|
+
//this.initCanvasGrid();
|
|
4277
|
+
}
|
|
4278
|
+
if (changes['dashboardData']) {
|
|
4279
|
+
console.log('Nuevo valor dashboardData:', this.dashboardData);
|
|
4280
|
+
//this.initCanvasGrid();
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
ngAfterViewInit() {
|
|
4284
|
+
this.initCanvasGrid();
|
|
4285
|
+
}
|
|
4286
|
+
initCanvasGrid() {
|
|
4287
|
+
this.layoutConfig = this.dashboardConfig.layoutConfig;
|
|
4288
|
+
// Opciones para restringir colisiones y comportamiento
|
|
4289
|
+
let options = {
|
|
4290
|
+
column: this.layoutConfig.columns,
|
|
4291
|
+
cellHeight: this.layoutConfig.cellHeight,
|
|
4292
|
+
margin: this.layoutConfig.margin,
|
|
4293
|
+
float: true, // Evita que los divs floten automáticamente hacia arriba
|
|
4294
|
+
//noOverlap: true, // CLAVE: Bloquea el movimiento si colisiona con otro DIV
|
|
4295
|
+
resizable: { handles: 'e, se, s, sw, w, nw, n, ne', autoHide: true } // Permite redimensionar desde todos los bordes
|
|
4296
|
+
};
|
|
4297
|
+
if (this.layoutConfig.columnOpts) {
|
|
4298
|
+
options = {
|
|
4299
|
+
column: this.layoutConfig.columns,
|
|
4300
|
+
cellHeight: this.layoutConfig.cellHeight,
|
|
4301
|
+
margin: this.layoutConfig.margin,
|
|
4302
|
+
columnOpts: {
|
|
4303
|
+
breakpointForWindow: this.layoutConfig.columnOpts.breakpointForWindow, // Mide el ancho de la ventana gráfica
|
|
4304
|
+
breakpoints: this.layoutConfig.columnOpts.breakpoints,
|
|
4305
|
+
layout: this.layoutConfig.columnOpts.layout || 'list', // Mantiene el orden de los widgets secuencialmente al colapsar
|
|
4306
|
+
},
|
|
4307
|
+
float: true, // Evita que los divs floten automáticamente hacia arriba
|
|
4308
|
+
//noOverlap: true, // CLAVE: Bloquea el movimiento si colisiona con otro DIV
|
|
4309
|
+
resizable: { handles: 'e, se, s, sw, w, nw, n, ne', autoHide: true } // Permite redimensionar desde todos los bordes
|
|
4310
|
+
};
|
|
4282
4311
|
}
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
// getNestedValue(item, xAxis) !== null,
|
|
4293
|
-
// );
|
|
4294
|
-
const validRawData = unifiedTable.filter((item) => item &&
|
|
4295
|
-
xAxis &&
|
|
4296
|
-
getNestedValue(item, xAxis) !== undefined &&
|
|
4297
|
-
getNestedValue(item, xAxis) !== null);
|
|
4298
|
-
const orderedRawData = sortByXAxis(validRawData);
|
|
4299
|
-
if (orderedRawData.length > 0) {
|
|
4300
|
-
if (serie) {
|
|
4301
|
-
// 2. Agrupamos los datos por el valor de la serie (ej. sucursal o vendedor)
|
|
4302
|
-
const groupedBySerie = orderedRawData.reduce((acc, item) => {
|
|
4303
|
-
const serieVal = getNestedValue(item, serie);
|
|
4304
|
-
const serieKey = serieVal !== undefined && serieVal !== null
|
|
4305
|
-
? String(serieVal)
|
|
4306
|
-
: 'Desconocido';
|
|
4307
|
-
if (!acc[serieKey]) {
|
|
4308
|
-
acc[serieKey] = [];
|
|
4309
|
-
}
|
|
4310
|
-
acc[serieKey].push(item);
|
|
4311
|
-
return acc;
|
|
4312
|
-
}, {});
|
|
4313
|
-
series = Object.entries(groupedBySerie).map(([serieName, groupItems]) => {
|
|
4314
|
-
const orderedGroupItems = [...groupItems].sort((a, b) => {
|
|
4315
|
-
const aValue = getNestedValue(a, xAxis);
|
|
4316
|
-
const bValue = getNestedValue(b, xAxis);
|
|
4317
|
-
return String(aValue).localeCompare(String(bValue), undefined, {
|
|
4318
|
-
numeric: true,
|
|
4319
|
-
sensitivity: 'base'
|
|
4320
|
-
});
|
|
4321
|
-
});
|
|
4322
|
-
console.log("SERIES NAME:", orderedGroupItems);
|
|
4323
|
-
const dataSource = orderedGroupItems.map((item) => {
|
|
4324
|
-
const rawVal = getNestedValue(item, yAxis);
|
|
4325
|
-
const valorFinal = rawVal !== undefined
|
|
4326
|
-
? typeof rawVal === 'number'
|
|
4327
|
-
? rawVal
|
|
4328
|
-
: Number(rawVal) || 0
|
|
4329
|
-
: 0;
|
|
4330
|
-
const sizeFinal = Math.abs(valorFinal) !== 0 ? Math.abs(valorFinal) * 0.05 : 0;
|
|
4331
|
-
return {
|
|
4332
|
-
x: String(getNestedValue(item, xAxis)),
|
|
4333
|
-
y: valorFinal,
|
|
4334
|
-
size: sizeFinal,
|
|
4335
|
-
name: String(getNestedValue(item, xAxis)),
|
|
4336
|
-
// ...(chartoColoredLine
|
|
4337
|
-
// ? { color: getRandomProfessionalHex() }
|
|
4338
|
-
// : {})
|
|
4339
|
-
};
|
|
4340
|
-
});
|
|
4341
|
-
return {
|
|
4342
|
-
name: serieName === 'default' ? 'Serie 1' : serieName,
|
|
4343
|
-
dataSource,
|
|
4344
|
-
opacity: opacity,
|
|
4345
|
-
emptyPointSettings: emptyPointSettings
|
|
4346
|
-
// dashArray: dashArray !== undefined ? dashArray : undefined,
|
|
4347
|
-
// width: width !== undefined ? width : undefined,
|
|
4348
|
-
// widthLine: widthLine !== undefined ? widthLine : undefined,
|
|
4349
|
-
};
|
|
4350
|
-
});
|
|
4351
|
-
}
|
|
4352
|
-
else {
|
|
4353
|
-
const dataSource = orderedRawData.map((item) => {
|
|
4354
|
-
let valorFinal = 0;
|
|
4355
|
-
let sizeFinal = 0;
|
|
4356
|
-
// const shouldColorLine = chartoColoredLine;
|
|
4357
|
-
const rawVal = getNestedValue(item, yAxis);
|
|
4358
|
-
// const rawSize = getNestedValue(item, size); // <--- Extraer el valor real
|
|
4359
|
-
if (rawVal !== undefined) {
|
|
4360
|
-
valorFinal = typeof rawVal === 'number' ? rawVal : Number(rawVal) || 0;
|
|
4361
|
-
}
|
|
4362
|
-
// if (rawSize !== undefined) {
|
|
4363
|
-
sizeFinal = Math.abs(valorFinal) !== 0 ? Math.abs(valorFinal) * 0.05 : 0;
|
|
4364
|
-
// }
|
|
4365
|
-
return {
|
|
4366
|
-
x: String(getNestedValue(item, xAxis)),
|
|
4367
|
-
y: valorFinal,
|
|
4368
|
-
size: sizeFinal, // <--- Valor numérico extraído
|
|
4369
|
-
name: String(getNestedValue(item, xAxis)),
|
|
4370
|
-
// ...(shouldColorLine ? { color: getRandomProfessionalHex() } : {})
|
|
4371
|
-
};
|
|
4372
|
-
});
|
|
4373
|
-
series = [
|
|
4374
|
-
{
|
|
4375
|
-
name: xAxis.split(".")[0] && xAxis !== 'default' ? xAxis.split(".")[0] : 'Serie Join',
|
|
4376
|
-
dataSource: dataSource,
|
|
4377
|
-
opacity: opacity,
|
|
4378
|
-
emptyPointSettings: emptyPointSettings
|
|
4379
|
-
// dashArray: dashArray !== undefined ? dashArray : undefined,
|
|
4380
|
-
// width: width !== undefined ? width : undefined,
|
|
4381
|
-
// widthLine: widthLine !== undefined ? widthLine : undefined,
|
|
4382
|
-
}
|
|
4383
|
-
];
|
|
4312
|
+
/*EXAMPLE OF "columnOpts"
|
|
4313
|
+
columnOpts: {
|
|
4314
|
+
breakpointForWindow: true,
|
|
4315
|
+
breakpoints: [
|
|
4316
|
+
{ w: 768, c: 1 },
|
|
4317
|
+
{ w: 992, c: 6 },
|
|
4318
|
+
{ w: 1200, c: this.layoutConfig.columns } // 👈 Usa tu variable para consistencia en Desktop
|
|
4319
|
+
],
|
|
4320
|
+
layout: 'list'
|
|
4384
4321
|
}
|
|
4385
|
-
|
|
4386
|
-
|
|
4322
|
+
*/
|
|
4323
|
+
// Inicializar el canvas
|
|
4324
|
+
this.grid = GridStack.init(options, this.gridContainer.nativeElement);
|
|
4325
|
+
// Cargar los elementos iniciales desde el JSON
|
|
4326
|
+
//this.loadLayoutFromJSON(this.dashboardItems);
|
|
4327
|
+
this.loadLayoutFromJSON(this.dashboardConfig, this.dashboardStyle);
|
|
4328
|
+
//Evaluar Bloqueo de Widgets en Inicializacion
|
|
4329
|
+
if (this.dashboardConfig.lockPositionWidgets) {
|
|
4330
|
+
this.fn_lockPositionWidgets(this.dashboardConfig.lockPositionWidgets);
|
|
4387
4331
|
}
|
|
4332
|
+
// Listener para detectar cambios y actualizar el JSON
|
|
4333
|
+
this.grid.on('change', (event, items) => {
|
|
4334
|
+
this.saveLayoutToJSON();
|
|
4335
|
+
});
|
|
4336
|
+
//Listener para detectar cuando cambia las dimenciones de un widget
|
|
4337
|
+
this.grid.on('resizestop', (event, el) => {
|
|
4338
|
+
// Disparamos el evento nativo del navegador de forma controlada
|
|
4339
|
+
window.dispatchEvent(new Event('resize'));
|
|
4340
|
+
});
|
|
4388
4341
|
}
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4342
|
+
//Filtrar Datos por Componente del Widget
|
|
4343
|
+
fn_getDataForWidgetComponent(listTables, prmDashboardData) {
|
|
4344
|
+
let dataresponse = new Map();
|
|
4345
|
+
const ldsize = prmDashboardData.length;
|
|
4346
|
+
const ltsize = listTables.length;
|
|
4347
|
+
if (ltsize > 0) {
|
|
4348
|
+
listTables.forEach((curTableName) => {
|
|
4349
|
+
prmDashboardData.forEach((curTableRef) => {
|
|
4350
|
+
if (curTableName.localeCompare(curTableRef.tableName) == 0) {
|
|
4351
|
+
dataresponse.set(curTableRef.tableName, curTableRef.tableData);
|
|
4352
|
+
}
|
|
4353
|
+
});
|
|
4354
|
+
});
|
|
4393
4355
|
}
|
|
4394
|
-
else
|
|
4395
|
-
|
|
4356
|
+
else {
|
|
4357
|
+
prmDashboardData.forEach((curTableRef) => {
|
|
4358
|
+
dataresponse.set(curTableRef.tableName, curTableRef.tableData);
|
|
4359
|
+
});
|
|
4360
|
+
}
|
|
4361
|
+
const object_base_response = Object.fromEntries(dataresponse);
|
|
4362
|
+
return object_base_response;
|
|
4363
|
+
}
|
|
4364
|
+
fn_getDataForWidgetComponent_back(listTables) {
|
|
4365
|
+
let dataresponse = [];
|
|
4366
|
+
const ldsize = this.dashboardData.length;
|
|
4367
|
+
const ltsize = listTables.length;
|
|
4368
|
+
if (ltsize > 0) {
|
|
4369
|
+
listTables.forEach((curTableName) => {
|
|
4370
|
+
this.dashboardData.forEach((curTableData) => {
|
|
4371
|
+
if (curTableName.localeCompare(curTableData.tableName) == 0) {
|
|
4372
|
+
dataresponse.push(curTableData);
|
|
4373
|
+
}
|
|
4374
|
+
});
|
|
4375
|
+
});
|
|
4396
4376
|
}
|
|
4397
4377
|
else {
|
|
4398
|
-
|
|
4378
|
+
return this.dashboardData;
|
|
4399
4379
|
}
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
const
|
|
4413
|
-
//
|
|
4414
|
-
|
|
4415
|
-
|
|
4380
|
+
return dataresponse;
|
|
4381
|
+
}
|
|
4382
|
+
// Carga elementos desde la configuración JSON
|
|
4383
|
+
//public loadLayoutFromJSON(dashboardItems: YwWidgetLayoutInterface[], ): void {
|
|
4384
|
+
loadLayoutFromJSON(prmDashboardConfig, prmDashboardStyle) {
|
|
4385
|
+
this.grid.removeAll();
|
|
4386
|
+
const widgets = [];
|
|
4387
|
+
this.grid.load(widgets);
|
|
4388
|
+
const lsize = prmDashboardConfig.controlListConfig.length;
|
|
4389
|
+
if (lsize > 0) {
|
|
4390
|
+
prmDashboardConfig.controlListConfig.forEach((widgetConfig) => {
|
|
4391
|
+
//Agregar uno por uno, para poder cargar los parametros internos de los componentes.
|
|
4392
|
+
const controlData = this.fn_getDataForWidgetComponent(widgetConfig.controlTables, this.dashboardData);
|
|
4393
|
+
//Sobre Escribir el ID Correcto en Layaout
|
|
4394
|
+
widgetConfig.layoutConfig.id = widgetConfig.widgetId;
|
|
4395
|
+
//Evaluar Mostrar Eventos
|
|
4396
|
+
if (widgetConfig.showConfigButtons == null || widgetConfig.showConfigButtons == undefined) {
|
|
4397
|
+
widgetConfig.showConfigButtons = prmDashboardConfig.showConfigButtons;
|
|
4416
4398
|
}
|
|
4417
|
-
//
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
name: String(getNestedValue(item, xAxis))
|
|
4425
|
-
// ...(shouldColorLine ? { color: getRandomProfessionalHex() } : {})
|
|
4426
|
-
};
|
|
4399
|
+
//Evalua Asignacion de Estilos
|
|
4400
|
+
if (widgetConfig.widgetStyle == null || widgetConfig.widgetStyle == undefined) {
|
|
4401
|
+
widgetConfig['widgetStyle'] = {};
|
|
4402
|
+
widgetConfig['widgetStyle']['widgetBackgroundColor'] = prmDashboardStyle.widgetBackgroundColor;
|
|
4403
|
+
widgetConfig['widgetStyle']['widgetBorderColor'] = prmDashboardStyle.widgetBorderColor;
|
|
4404
|
+
}
|
|
4405
|
+
this.eventAddWidget(widgetConfig, widgetConfig.controlConfig, controlData, widgetConfig.layoutConfig);
|
|
4427
4406
|
});
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
.
|
|
4407
|
+
}
|
|
4408
|
+
}
|
|
4409
|
+
// Guarda los elementos desde la configuración JSON
|
|
4410
|
+
saveLayoutToJSON() {
|
|
4411
|
+
const currentWidgets = this.grid.save(false);
|
|
4412
|
+
this.dashboardItems = currentWidgets.map(w => ({
|
|
4413
|
+
id: w.id,
|
|
4414
|
+
x: w.x || 0,
|
|
4415
|
+
y: w.y || 0,
|
|
4416
|
+
w: w.w || 1,
|
|
4417
|
+
h: w.h || 1,
|
|
4418
|
+
content: w.content,
|
|
4419
|
+
contentData: {}
|
|
4420
|
+
}));
|
|
4421
|
+
console.log('JSON Guardado:', JSON.stringify(this.dashboardItems));
|
|
4422
|
+
return this.dashboardItems;
|
|
4439
4423
|
}
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
}
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
};
|
|
4468
|
-
};
|
|
4469
|
-
|
|
4470
|
-
class BubbleChartSyncfusionComponent {
|
|
4471
|
-
constructor(elRef, cdr) {
|
|
4472
|
-
this.elRef = elRef;
|
|
4473
|
-
this.cdr = cdr;
|
|
4474
|
-
this.idComponent = '';
|
|
4475
|
-
this.dataChartParse = [];
|
|
4476
|
-
this.currentLabelSize = '';
|
|
4477
|
-
this.currentWidgetWidth = 0; // Valor inicial por defecto
|
|
4424
|
+
/*BUTTON ADD WIDGET*/
|
|
4425
|
+
fn_btn_addWidget() {
|
|
4426
|
+
this.countWidget++;
|
|
4427
|
+
const newWidgetId = 'widget-' + this.countWidget;
|
|
4428
|
+
let newItem = {
|
|
4429
|
+
id: newWidgetId, autoPosition: true, w: 6, h: 3,
|
|
4430
|
+
content: ''
|
|
4431
|
+
};
|
|
4432
|
+
//Datos de Widget y sus Contenidos
|
|
4433
|
+
const widgetConfig = {
|
|
4434
|
+
widgetId: newWidgetId,
|
|
4435
|
+
title: '',
|
|
4436
|
+
typeComponent: 'empty-visual',
|
|
4437
|
+
showConfigButtons: true,
|
|
4438
|
+
widgetStyle: DEFAULT_WIDGET_STYLE,
|
|
4439
|
+
layoutConfig: {
|
|
4440
|
+
id: '',
|
|
4441
|
+
w: 0,
|
|
4442
|
+
h: 0,
|
|
4443
|
+
content: undefined
|
|
4444
|
+
},
|
|
4445
|
+
controlConfig: {},
|
|
4446
|
+
controlTables: []
|
|
4447
|
+
};
|
|
4448
|
+
const controlConfig = {};
|
|
4449
|
+
const controlData = {};
|
|
4450
|
+
this.eventAddWidget(widgetConfig, controlConfig, controlData, newItem);
|
|
4478
4451
|
}
|
|
4479
|
-
|
|
4480
|
-
|
|
4452
|
+
/*BUTTON DELETE WIDGET*/
|
|
4453
|
+
fn_btn_deleteWidget() {
|
|
4454
|
+
const newWidgetId = 'widget-' + this.countWidget;
|
|
4455
|
+
this.eventRemoveWidgetById(newWidgetId);
|
|
4456
|
+
this.countWidget--;
|
|
4481
4457
|
}
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4458
|
+
/*BUTTON BLOCK WIDGETS*/
|
|
4459
|
+
fn_btn_lockPositionWidgets() {
|
|
4460
|
+
this.isLocked = !this.isLocked;
|
|
4461
|
+
const shouldLock = !this.allIsLocked();
|
|
4462
|
+
this.allIsLocked.set(shouldLock);
|
|
4463
|
+
this.fn_lockPositionWidgets(shouldLock);
|
|
4464
|
+
console.log(`All widgets have been visually and functionally locked: ${shouldLock}`);
|
|
4486
4465
|
}
|
|
4487
|
-
|
|
4488
|
-
|
|
4466
|
+
fn_lockPositionWidgets(prmAllIsLocked) {
|
|
4467
|
+
const shouldLock = prmAllIsLocked;
|
|
4468
|
+
// 1. Perform the functional Gridstack task on the core grid layout
|
|
4469
|
+
this.grid.movable('.grid-stack-item', !shouldLock);
|
|
4470
|
+
this.grid.resizable('.grid-stack-item', !shouldLock);
|
|
4471
|
+
// 2. Broadcast the state change down to every active dynamic child component
|
|
4472
|
+
this.widgetsActivos.forEach((componentRef) => {
|
|
4473
|
+
componentRef.setInput('isLocked', shouldLock);
|
|
4474
|
+
});
|
|
4475
|
+
console.log(`All widgets have been visually and functionally locked - por TS Config: ${shouldLock}`);
|
|
4489
4476
|
}
|
|
4490
|
-
|
|
4491
|
-
|
|
4477
|
+
/*BUTTON UPDATE WIDGET - CONTROL CONFIG */
|
|
4478
|
+
fn_btn_updateWidgetControlConfig(idWidget) {
|
|
4479
|
+
let newControlConfig = {};
|
|
4480
|
+
/*MODIFICAR METODO PARA CARGAR INFO DEL FORMULARIO*/
|
|
4481
|
+
newControlConfig['provider'] = 'syncfusion';
|
|
4482
|
+
this.eventUpdateWidgetControlConfig(idWidget, newControlConfig);
|
|
4492
4483
|
}
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
}
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
}
|
|
4484
|
+
/*BUTTON UPDATE WIDGET - CONTROL CONFIG */
|
|
4485
|
+
fn_btn_updateWidgetControlData(idWidget) {
|
|
4486
|
+
let newControlData = [];
|
|
4487
|
+
/*MODIFICAR METODO PARA CARGAR INFO DEL FORMULARIO*/
|
|
4488
|
+
newControlData = [
|
|
4489
|
+
{ month: 'Ene', sales: 35, expenses: 28 },
|
|
4490
|
+
{ month: 'Feb', sales: 28, expenses: 22 },
|
|
4491
|
+
{ month: 'Mar', sales: 34, expenses: 25 },
|
|
4492
|
+
{ month: 'Abr', sales: 32, expenses: 27 },
|
|
4493
|
+
{ month: 'May', sales: 40, expenses: 30 },
|
|
4494
|
+
{ month: 'Jun', sales: 32, expenses: 26 },
|
|
4495
|
+
{ month: 'Jul', sales: 45, expenses: 32 },
|
|
4496
|
+
{ month: 'Ago', sales: 38, expenses: 29 },
|
|
4497
|
+
{ month: 'Sep', sales: 42, expenses: 31 },
|
|
4498
|
+
{ month: 'Oct', sales: 48, expenses: 35 },
|
|
4499
|
+
{ month: 'Nov', sales: 52, expenses: 38 },
|
|
4500
|
+
{ month: 'Dic', sales: 58, expenses: 42 },
|
|
4501
|
+
];
|
|
4502
|
+
this.eventUpdateWidgetControlData(idWidget, newControlData);
|
|
4503
|
+
}
|
|
4504
|
+
/****************************************************** */
|
|
4505
|
+
/*AGREGAR WIDGET*/
|
|
4506
|
+
eventAddWidget(widgetConfig, controlConfig, controlData, item) {
|
|
4507
|
+
// 1. Agregar el contenedor del widget a Gridstack
|
|
4508
|
+
const el = this.grid.addWidget(item);
|
|
4509
|
+
// 2. Obtener el contenedor interno generado por Gridstack
|
|
4510
|
+
const contentElement = el.querySelector('.grid-stack-item-content');
|
|
4511
|
+
if (contentElement) {
|
|
4512
|
+
// 3. Crear dinámicamente la instancia del componente Angular
|
|
4513
|
+
const componentRef = createComponent(YwDashboardWidgetComponent, {
|
|
4514
|
+
environmentInjector: this.environmentInjector, // Requerido para resolver dependencias
|
|
4515
|
+
hostElement: contentElement // Renderiza directamente aquí dentro
|
|
4516
|
+
});
|
|
4517
|
+
// 4. Pasar las propiedades/Inputs al componente creado
|
|
4518
|
+
//Evaluar Estilos
|
|
4519
|
+
componentRef.setInput('styleWidget', widgetConfig.widgetStyle);
|
|
4520
|
+
//componentRef.instance.configWidget = widgetConfig;
|
|
4521
|
+
componentRef.setInput('configWidget', widgetConfig);
|
|
4522
|
+
componentRef.setInput('controlConfig', controlConfig);
|
|
4523
|
+
componentRef.setInput('controlData', controlData);
|
|
4524
|
+
/* BEGIN - Eventos que provienen desde widget */
|
|
4525
|
+
componentRef.instance.eventDeleteRequest.subscribe((idWidget) => {
|
|
4526
|
+
// Ejecutamos la función de borrado que ya programamos en el paso anterior
|
|
4527
|
+
this.eventRemoveWidgetById(idWidget);
|
|
4528
|
+
});
|
|
4529
|
+
componentRef.instance.eventLockToggleRequest.subscribe((event) => {
|
|
4530
|
+
this.eventToggleLockWidget(event.widgetId, event.shouldLock);
|
|
4531
|
+
});
|
|
4532
|
+
componentRef.instance.eventMaximizeToggleRequest.subscribe((event) => {
|
|
4533
|
+
this.eventToggleMaximizeWidget(event.widgetId, event.shouldMaximize);
|
|
4534
|
+
});
|
|
4535
|
+
//Mostrar
|
|
4536
|
+
componentRef.instance.eventShowConfigFormRequest.subscribe((idWidget) => {
|
|
4537
|
+
this.eventShowFormConfigWidget(idWidget);
|
|
4538
|
+
});
|
|
4539
|
+
/* END - Eventos que provienen desde widget */
|
|
4540
|
+
// 5. Mover los nodos del DOM generados por Angular dentro del DIV del Widget
|
|
4541
|
+
this.appRef.attachView(componentRef.hostView);
|
|
4542
|
+
// Guardar la referencia de Componentes para hacer operaciones con estas.
|
|
4543
|
+
this.widgetsActivos.set(item.id, componentRef);
|
|
4544
|
+
//El componente interno no aparece bien dimensionado, con esto disparamos el evento para que se ajuste a las dimenciones correctas
|
|
4545
|
+
setTimeout(() => {
|
|
4546
|
+
window.dispatchEvent(new Event('resize'));
|
|
4547
|
+
}, 50);
|
|
4508
4548
|
}
|
|
4509
4549
|
}
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
// case 'threshold':
|
|
4517
|
-
// passesRule = yValue >= (configPoint.thresholdValue || 0);
|
|
4518
|
-
// break;
|
|
4519
|
-
// case 'pair':
|
|
4520
|
-
// passesRule = yValue % 2 === 0;
|
|
4521
|
-
// break;
|
|
4522
|
-
// case 'range':
|
|
4523
|
-
// const min = configPoint.minRange || 0;
|
|
4524
|
-
// const max = configPoint.maxRange || 100;
|
|
4525
|
-
// passesRule = yValue >= min && yValue <= max;
|
|
4526
|
-
// break;
|
|
4527
|
-
// default:
|
|
4528
|
-
// passesRule = true;
|
|
4529
|
-
// }
|
|
4530
|
-
// args.fill = passesRule ? (configPoint.trueColor || '#10B981') : (configPoint.falseColor || '#EF4444');
|
|
4531
|
-
// }
|
|
4532
|
-
pointRender(args) {
|
|
4533
|
-
const yValue = Number(args.point.y);
|
|
4534
|
-
// =====================================================
|
|
4535
|
-
// EMPTY POINT / VALOR 0
|
|
4536
|
-
// Tiene prioridad sobre ruleColorPoint
|
|
4537
|
-
// =====================================================
|
|
4538
|
-
if (yValue === 0) {
|
|
4539
|
-
const emptyPoint = this.config.emptyPointSettings;
|
|
4540
|
-
if (emptyPoint && emptyPoint !== '') {
|
|
4541
|
-
args.fill = emptyPoint;
|
|
4542
|
-
}
|
|
4550
|
+
/*UPDATE CONTROLCONFIG WIDGET*/
|
|
4551
|
+
eventUpdateWidgetControlConfig(idWidget, newControlConfig) {
|
|
4552
|
+
//Obtener la referencia del componente almacenada en el Map
|
|
4553
|
+
const componentRef = this.widgetsActivos.get(idWidget);
|
|
4554
|
+
if (!componentRef) {
|
|
4555
|
+
console.warn(`No se encontró un widget activo con el ID: ${idWidget}`);
|
|
4543
4556
|
return;
|
|
4544
4557
|
}
|
|
4545
|
-
//
|
|
4546
|
-
|
|
4547
|
-
//
|
|
4548
|
-
|
|
4549
|
-
|
|
4558
|
+
//Actualizar el Input usando la API oficial setInput
|
|
4559
|
+
componentRef.setInput('controlConfig', newControlConfig);
|
|
4560
|
+
// NOTA: setInput dispara automáticamente la detección de cambios (ChangeDetectionStrategy.OnPush).
|
|
4561
|
+
// Si deseas asegurarte manualmente, puedes forzar un render:
|
|
4562
|
+
// componentRef.changeDetectorRef.detectChanges();
|
|
4563
|
+
}
|
|
4564
|
+
/*UPDATE CONTROL DATA WIDGET*/
|
|
4565
|
+
eventUpdateWidgetControlData(idWidget, newControlData) {
|
|
4566
|
+
//Obtener la referencia del componente almacenada en el Map
|
|
4567
|
+
const componentRef = this.widgetsActivos.get(idWidget);
|
|
4568
|
+
if (!componentRef) {
|
|
4569
|
+
console.warn(`No se encontró un widget activo con el ID: ${idWidget}`);
|
|
4550
4570
|
return;
|
|
4551
4571
|
}
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4572
|
+
//Actualizar el Input usando la API oficial setInput
|
|
4573
|
+
componentRef.setInput('controlData', newControlData);
|
|
4574
|
+
// NOTA: setInput dispara automáticamente la detección de cambios (ChangeDetectionStrategy.OnPush).
|
|
4575
|
+
// Si deseas asegurarte manualmente, puedes forzar un render:
|
|
4576
|
+
componentRef.changeDetectorRef.detectChanges();
|
|
4577
|
+
}
|
|
4578
|
+
/****************************************************** */
|
|
4579
|
+
/* BEGIN - DRAWER */
|
|
4580
|
+
handleShowFormFilterDrawer() {
|
|
4581
|
+
this.drawerfiltervisible = true;
|
|
4582
|
+
}
|
|
4583
|
+
handleCloseFormFilterDrawer() {
|
|
4584
|
+
this.drawerfiltervisible = false;
|
|
4585
|
+
}
|
|
4586
|
+
handleCloseFormDrawer() {
|
|
4587
|
+
this.drawerconfigvisible = false;
|
|
4588
|
+
}
|
|
4589
|
+
fnGetDrawerWidth(prm_percent) {
|
|
4590
|
+
const curWidth = window.innerWidth;
|
|
4591
|
+
let newWidth = curWidth;
|
|
4592
|
+
if (prm_percent) {
|
|
4593
|
+
newWidth = Math.floor(curWidth * prm_percent / 100);
|
|
4570
4594
|
}
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4595
|
+
if (newWidth < 400) {
|
|
4596
|
+
newWidth = curWidth;
|
|
4597
|
+
}
|
|
4598
|
+
return newWidth;
|
|
4574
4599
|
}
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4600
|
+
onFilterSelectionChange(eventData) {
|
|
4601
|
+
const lsize = this.widgetsActivos.size;
|
|
4602
|
+
//Validar que ya se crearon y renderizaron los componentes graficos.
|
|
4603
|
+
if (lsize > 0) {
|
|
4604
|
+
const currentFilterController = this.dashboardFilterConfig.controlListConfig.find((x) => x.widgetId == eventData['widgetId']);
|
|
4605
|
+
if (currentFilterController) {
|
|
4606
|
+
currentFilterController.controlFilterData = eventData['eventResponse'];
|
|
4607
|
+
this.fnUpdateDataControllerBasedOnFilter(this.dashboardFilterConfig.controlListConfig);
|
|
4608
|
+
}
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
fnUpdateDataControllerBasedOnFilter(filterControlListConfig) {
|
|
4612
|
+
let copyDashboardData = structuredClone(this.dashboardData);
|
|
4613
|
+
filterControlListConfig.forEach((item) => {
|
|
4614
|
+
let tableSelected = copyDashboardData.find((x) => x.tableName == item.controlTable);
|
|
4615
|
+
if (item.typeComponent == 'filter-slicer' && tableSelected && item.controlFilterData) {
|
|
4616
|
+
const fieldName = item.configComponent.filterField;
|
|
4617
|
+
if (item.configComponent.dataType == 'date') {
|
|
4618
|
+
const minDate = item.controlFilterData['startDate'];
|
|
4619
|
+
const maxDate = item.controlFilterData['endDate'];
|
|
4620
|
+
if (minDate && maxDate) {
|
|
4621
|
+
const filterData = tableSelected.tableData.filter((y) => (minDate <= y[fieldName] && y[fieldName] <= maxDate));
|
|
4622
|
+
tableSelected.tableData = filterData;
|
|
4589
4623
|
}
|
|
4590
4624
|
}
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
? this.config.labelSize
|
|
4599
|
-
: parseFloat(this.config.labelSize);
|
|
4600
|
-
if (!isNaN(parsedSize)) {
|
|
4601
|
-
if (width < 260) {
|
|
4602
|
-
const scale = Math.max(0.65, width / 260);
|
|
4603
|
-
this.currentLabelSize = `${Math.round(parsedSize * scale)}px`;
|
|
4625
|
+
if (item.configComponent.dataType == 'number') {
|
|
4626
|
+
const minNum = Number(item.controlFilterData['minValue']);
|
|
4627
|
+
const maxNum = Number(item.controlFilterData['maxValue']);
|
|
4628
|
+
if (minNum && maxNum) {
|
|
4629
|
+
const filterData = tableSelected.tableData.filter((y) => (minNum <= y[fieldName] && y[fieldName] <= maxNum));
|
|
4630
|
+
tableSelected.tableData = filterData;
|
|
4631
|
+
}
|
|
4604
4632
|
}
|
|
4605
|
-
|
|
4606
|
-
|
|
4633
|
+
}
|
|
4634
|
+
if (item.typeComponent == 'filter-button' && tableSelected && item.controlFilterData) {
|
|
4635
|
+
const fieldName = item.configComponent.filterField;
|
|
4636
|
+
const listValues = item.controlFilterData || [];
|
|
4637
|
+
if (listValues && listValues.length > 0) {
|
|
4638
|
+
const filterData = tableSelected.tableData.filter((y) => (listValues.includes(y[fieldName])));
|
|
4639
|
+
tableSelected.tableData = filterData;
|
|
4607
4640
|
}
|
|
4608
|
-
this.cdr.markForCheck();
|
|
4609
|
-
return;
|
|
4610
4641
|
}
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4642
|
+
if (item.typeComponent == 'filter-list' && tableSelected && item.controlFilterData) {
|
|
4643
|
+
const fieldName = item.configComponent.filterField;
|
|
4644
|
+
if (item.configComponent.dataType == 'text') {
|
|
4645
|
+
const listValues = item.controlFilterData['ids'] || [];
|
|
4646
|
+
if (listValues && listValues.length > 0) {
|
|
4647
|
+
const listValues1D = listValues;
|
|
4648
|
+
const filterData = tableSelected.tableData.filter((y) => (listValues1D.includes(y[fieldName])));
|
|
4649
|
+
tableSelected.tableData = filterData;
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4652
|
+
if (item.configComponent.dataType == 'date') {
|
|
4653
|
+
const minDate = item.controlFilterData['minDate'];
|
|
4654
|
+
const maxDate = item.controlFilterData['maxDate'];
|
|
4655
|
+
if (minDate && maxDate) {
|
|
4656
|
+
const filterData = tableSelected.tableData.filter((y) => (minDate <= y[fieldName] && y[fieldName] <= maxDate));
|
|
4657
|
+
tableSelected.tableData = filterData;
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4660
|
+
}
|
|
4661
|
+
});
|
|
4662
|
+
//Actualizacion de Data Componentes Graficos
|
|
4663
|
+
this.dashboardConfig.controlListConfig.forEach((item) => {
|
|
4664
|
+
const controlData = this.fn_getDataForWidgetComponent(item.controlTables, copyDashboardData);
|
|
4665
|
+
this.eventUpdateWidgetControlData(item.widgetId, controlData);
|
|
4666
|
+
});
|
|
4616
4667
|
}
|
|
4617
|
-
|
|
4618
|
-
|
|
4668
|
+
/* END - DRAWER */
|
|
4669
|
+
/* BEGIN - Eventos que provienen desde widget */
|
|
4670
|
+
eventRemoveWidgetById(widgetId) {
|
|
4671
|
+
// 1. Buscar el elemento HTML físico dentro de Gridstack usando su atributo interno [gs-id]
|
|
4672
|
+
const elementoHtml = this.gridContainer.nativeElement.querySelector(`[gs-id="${widgetId}"]`);
|
|
4673
|
+
if (elementoHtml) {
|
|
4674
|
+
// 2. Remover el elemento de Gridstack (esto limpia el HTML y reordena el tablero si float es false)
|
|
4675
|
+
// El parámetro false indica que remueva el nodo del DOM pero no dispare eventos internos destructivos pesados
|
|
4676
|
+
this.grid.removeWidget(elementoHtml, false);
|
|
4677
|
+
}
|
|
4678
|
+
// 3. Buscar y destruir la instancia de Angular en memoria RAM
|
|
4679
|
+
const componentRef = this.widgetsActivos.get(widgetId);
|
|
4680
|
+
if (componentRef) {
|
|
4681
|
+
// Desengancha la vista del ciclo de renderizado global de Angular
|
|
4682
|
+
this.appRef.detachView(componentRef.hostView);
|
|
4683
|
+
// Destruye el componente y libera la memoria RAM
|
|
4684
|
+
componentRef.destroy();
|
|
4685
|
+
// Eliminamos el registro de nuestro Mapa
|
|
4686
|
+
this.widgetsActivos.delete(widgetId);
|
|
4687
|
+
}
|
|
4688
|
+
//console.log(`Widget ${widgetId} eliminado con éxito de Gridstack y Angular.`);
|
|
4619
4689
|
}
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
// }
|
|
4628
|
-
// }
|
|
4629
|
-
axisLabelRender(args) {
|
|
4630
|
-
const umbralWidget = 700;
|
|
4631
|
-
if (this.currentWidgetWidth > umbralWidget) {
|
|
4632
|
-
return;
|
|
4690
|
+
eventToggleLockWidget(widgetId, shouldLock) {
|
|
4691
|
+
const elementoHtml = this.gridContainer.nativeElement.querySelector(`[gs-id="${widgetId}"]`);
|
|
4692
|
+
if (elementoHtml) {
|
|
4693
|
+
// La API de Gridstack nos permite congelar un nodo específico pasándole true/false
|
|
4694
|
+
this.grid.movable(elementoHtml, !shouldLock);
|
|
4695
|
+
this.grid.resizable(elementoHtml, !shouldLock);
|
|
4696
|
+
//console.log(`Widget ${widgetId} cambiado a estado bloqueado: ${shouldLock}`);
|
|
4633
4697
|
}
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4698
|
+
}
|
|
4699
|
+
eventToggleMaximizeWidget(widgetId, shouldMaximize) {
|
|
4700
|
+
const elementoHtml = this.gridContainer.nativeElement.querySelector(`[gs-id="${widgetId}"]`);
|
|
4701
|
+
if (elementoHtml) {
|
|
4702
|
+
if (shouldMaximize) {
|
|
4703
|
+
// Aplicamos estilos CSS nativos para forzar al contenedor a flotar sobre todo el dashboard
|
|
4704
|
+
elementoHtml.classList.add('widget-maximized');
|
|
4705
|
+
// Deshabilitamos temporalmente que Gridstack intente moverlo mientras está maximizado
|
|
4706
|
+
this.grid.movable(elementoHtml, false);
|
|
4707
|
+
this.grid.resizable(elementoHtml, false);
|
|
4641
4708
|
}
|
|
4642
4709
|
else {
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4710
|
+
elementoHtml.classList.remove('widget-maximized');
|
|
4711
|
+
// Restauramos los permisos normales leyendo si el componente de Angular estaba bloqueado previamente
|
|
4712
|
+
const componentRef = this.widgetsActivos.get(widgetId);
|
|
4713
|
+
const isCurrentlyLocked = componentRef?.instance.isLocked() || false;
|
|
4714
|
+
this.grid.movable(elementoHtml, !isCurrentlyLocked);
|
|
4715
|
+
this.grid.resizable(elementoHtml, !isCurrentlyLocked);
|
|
4646
4716
|
}
|
|
4717
|
+
// Forzamos un evento resize simulado para que los gráficos de Syncfusion recalculen su nuevo tamaño gigante/pequeño
|
|
4718
|
+
setTimeout(() => {
|
|
4719
|
+
window.dispatchEvent(new Event('resize'));
|
|
4720
|
+
}, 50);
|
|
4647
4721
|
}
|
|
4648
4722
|
}
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
LegendService,
|
|
4653
|
-
DateTimeService], viewQueries: [{ propertyName: "chartInstance", first: true, predicate: ["chart"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"control-section\">\r\n\r\n <ejs-chart \r\n #chart \r\n [primaryXAxis]=\"labelData.axisX\" \r\n [primaryYAxis]=\"labelData.axisY\" \r\n [title]=\"labelData.title\" \r\n (pointRender)=\"pointRender($event)\" \r\n height=\"100%\"\r\n width=\"100%\"\r\n [legendSettings]=\"labelData.legendSettings\"\r\n (axisLabelRender)=\"axisLabelRender($event)\"\r\n\r\n [tooltip]=\"labelData.tooltip\">\r\n <e-series-collection>\r\n @for(series of dataChartParse; track $index){\r\n <e-series \r\n [opacity]=\"series.opacity\"\r\n [dataSource]='series.dataSource' \r\n type='Bubble' \r\n xName='x' \r\n yName='y' \r\n size='size' \r\n [name]='series.name'>\r\n </e-series>\r\n\r\n }\r\n </e-series-collection>\r\n</ejs-chart>\r\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;width:100%;height:100%;min-height:260px;box-sizing:border-box;overflow:hidden}.control-section{display:flex;flex-direction:column;width:100%;height:100%;min-height:260px;box-sizing:border-box;overflow:hidden;background:#fff;border-radius:8px}:host ::ng-deep ejs-circulargauge{display:block;width:100%!important;height:100%!important;flex-grow:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ChartModule }, { kind: "component", type: i1.ChartComponent, selector: "ejs-chart", inputs: ["accessibility", "allowExport", "allowMultiSelection", "annotations", "axes", "background", "backgroundImage", "border", "chartArea", "columns", "crosshair", "currencyCode", "dataSource", "description", "enableAnimation", "enableAutoIntervalOnBothAxis", "enableCanvas", "enableExport", "enableHtmlSanitizer", "enablePersistence", "enableRtl", "enableSideBySidePlacement", "focusBorderColor", "focusBorderMargin", "focusBorderWidth", "height", "highlightColor", "highlightMode", "highlightPattern", "indicators", "isMultiSelect", "isTransposed", "legendSettings", "locale", "margin", "palettes", "primaryXAxis", "primaryYAxis", "rangeColorSettings", "rows", "selectedDataIndexes", "selectionMode", "selectionPattern", "series", "subTitle", "subTitleStyle", "tabIndex", "theme", "title", "titleStyle", "tooltip", "useGroupingSeparator", "width", "zoomSettings"], outputs: ["afterExport", "animationComplete", "annotationRender", "axisLabelClick", "axisLabelRender", "axisMultiLabelRender", "axisRangeCalculated", "beforeExport", "beforePrint", "beforeResize", "chartDoubleClick", "chartMouseClick", "chartMouseDown", "chartMouseLeave", "chartMouseMove", "chartMouseUp", "drag", "dragComplete", "dragEnd", "dragStart", "legendClick", "legendRender", "load", "loaded", "multiLevelLabelClick", "onZooming", "pointClick", "pointDoubleClick", "pointMove", "pointRender", "resized", "scrollChanged", "scrollEnd", "scrollStart", "selectionComplete", "seriesRender", "sharedTooltipRender", "textRender", "tooltipRender", "zoomComplete", "dataSourceChange"] }, { kind: "directive", type: i1.SeriesDirective, selector: "e-series-collection>e-series", inputs: ["accessibility", "animation", "bearFillColor", "binInterval", "border", "boxPlotMode", "bullFillColor", "cardinalSplineTension", "close", "colorName", "columnFacet", "columnSpacing", "columnWidth", "columnWidthInPixel", "connector", "cornerRadius", "dashArray", "dataSource", "dragSettings", "drawType", "emptyPointSettings", "enableComplexProperty", "enableSolidCandles", "enableTooltip", "errorBar", "fill", "groupName", "high", "intermediateSumIndexes", "isClosed", "legendImageUrl", "legendShape", "low", "marker", "maxRadius", "minRadius", "name", "negativeFillColor", "noRisers", "nonHighlightStyle", "opacity", "open", "paretoOptions", "pointColorMapping", "query", "segmentAxis", "segments", "selectionStyle", "showMean", "showNormalDistribution", "size", "splineType", "stackingGroup", "step", "sumIndexes", "summaryFillColor", "tooltipFormat", "tooltipMappingName", "trendlines", "type", "unSelectedStyle", "visible", "volume", "width", "xAxisName", "xName", "yAxisName", "yName", "zOrder"] }, { kind: "directive", type: i1.SeriesCollectionDirective, selector: "ej-chart>e-series-collection" }] }); }
|
|
4654
|
-
}
|
|
4655
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: BubbleChartSyncfusionComponent, decorators: [{
|
|
4656
|
-
type: Component,
|
|
4657
|
-
args: [{ selector: 'yw-bubble-chart-syncfusion', standalone: true, imports: [CommonModule, ChartModule], providers: [BubbleSeriesService, CategoryService, CategoryService,
|
|
4658
|
-
TooltipService,
|
|
4659
|
-
LegendService,
|
|
4660
|
-
DateTimeService], template: "<div class=\"control-section\">\r\n\r\n <ejs-chart \r\n #chart \r\n [primaryXAxis]=\"labelData.axisX\" \r\n [primaryYAxis]=\"labelData.axisY\" \r\n [title]=\"labelData.title\" \r\n (pointRender)=\"pointRender($event)\" \r\n height=\"100%\"\r\n width=\"100%\"\r\n [legendSettings]=\"labelData.legendSettings\"\r\n (axisLabelRender)=\"axisLabelRender($event)\"\r\n\r\n [tooltip]=\"labelData.tooltip\">\r\n <e-series-collection>\r\n @for(series of dataChartParse; track $index){\r\n <e-series \r\n [opacity]=\"series.opacity\"\r\n [dataSource]='series.dataSource' \r\n type='Bubble' \r\n xName='x' \r\n yName='y' \r\n size='size' \r\n [name]='series.name'>\r\n </e-series>\r\n\r\n }\r\n </e-series-collection>\r\n</ejs-chart>\r\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;width:100%;height:100%;min-height:260px;box-sizing:border-box;overflow:hidden}.control-section{display:flex;flex-direction:column;width:100%;height:100%;min-height:260px;box-sizing:border-box;overflow:hidden;background:#fff;border-radius:8px}:host ::ng-deep ejs-circulargauge{display:block;width:100%!important;height:100%!important;flex-grow:1}\n"] }]
|
|
4661
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { chartInstance: [{
|
|
4662
|
-
type: ViewChild,
|
|
4663
|
-
args: ['chart']
|
|
4664
|
-
}], chartData: [{
|
|
4665
|
-
type: Input,
|
|
4666
|
-
args: ['chartData']
|
|
4667
|
-
}], config: [{
|
|
4668
|
-
type: Input,
|
|
4669
|
-
args: ['config']
|
|
4670
|
-
}], idComponent: [{
|
|
4671
|
-
type: Input,
|
|
4672
|
-
args: ['idComponent']
|
|
4673
|
-
}] } });
|
|
4674
|
-
|
|
4675
|
-
// import { LineChartSyncfusionComponent } from '../../../../../adapters/charts/line-chart/syncfusion/visual/yw-line-chart-syncfusion.component';
|
|
4676
|
-
// import { YwLineMappingConfig } from '../../../../../models/config/chart/yw-line-chart-config.interface';
|
|
4677
|
-
class BubbleChartComponent {
|
|
4678
|
-
constructor() {
|
|
4679
|
-
this.idComponent = '';
|
|
4680
|
-
}
|
|
4681
|
-
ngOnChanges(changes) {
|
|
4682
|
-
if (changes['chartData']) {
|
|
4683
|
-
console.log('change chartData:', changes['chartData'].currentValue);
|
|
4684
|
-
}
|
|
4685
|
-
if (changes['config']) {
|
|
4686
|
-
console.log('change config:', changes['config'].currentValue);
|
|
4687
|
-
}
|
|
4723
|
+
eventShowFormConfigWidget(widgetId) {
|
|
4724
|
+
this.drawerCurrentWidgetObject['widgetId'] = widgetId;
|
|
4725
|
+
this.drawerconfigvisible = true;
|
|
4688
4726
|
}
|
|
4689
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
4690
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: BubbleChartComponent, isStandalone: true, selector: "yw-bubble-chart", inputs: { chartData: "chartData", config: "config", idComponent: "idComponent" }, usesOnChanges: true, ngImport: i0, template: "llegamos\r\n@if(config.provider==='syncfusion'){\r\n <div style=\"position: relative; width: 100%; height: 100%;\">\r\n <yw-bubble-chart-syncfusion \r\n [idComponent]=\"idComponent\"\r\n [chartData]=\"chartData\" \r\n [config]=\"config\" style=\"display: block; width: 100%; height: 100%;\">\r\n </yw-bubble-chart-syncfusion>\r\n</div>\r\n}", styles: [":host{display:block;width:100%;height:100%;min-height:260px;min-width:0;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BubbleChartSyncfusionComponent, selector: "yw-bubble-chart-syncfusion", inputs: ["chartData", "config", "idComponent"] }] }); }
|
|
4727
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwDashboardComponent, deps: [{ token: i0.EnvironmentInjector }, { token: i0.ApplicationRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4728
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: YwDashboardComponent, isStandalone: true, selector: "yw-dashboard", inputs: { showControls: { classPropertyName: "showControls", publicName: "showControls", isSignal: true, isRequired: false, transformFunction: null }, showFilter: { classPropertyName: "showFilter", publicName: "showFilter", isSignal: true, isRequired: false, transformFunction: null }, dashboardStyle: { classPropertyName: "dashboardStyle", publicName: "dashboardStyle", isSignal: false, isRequired: false, transformFunction: null }, dashboardConfig: { classPropertyName: "dashboardConfig", publicName: "dashboardConfig", isSignal: false, isRequired: false, transformFunction: null }, dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: false, isRequired: false, transformFunction: null }, dashboardFilterConfig: { classPropertyName: "dashboardFilterConfig", publicName: "dashboardFilterConfig", isSignal: false, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "gridContainer", first: true, predicate: ["gridContainer"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<!-- <div class=\"controls\" [hidden]=\"!showControls()\">\r\n <button (click)=\"saveLayoutToJSON()\">Guardar JSON en Consola</button>\r\n <button (click)=\"fn_btn_addWidget()\">add widget</button>\r\n <button (click)=\"fn_btn_lockPositionWidgets()\">Lock widgets</button>\r\n <button (click)=\"handleShowFormFilterDrawer()\" class=\"btn-filtro\">\r\n <svg *ngIf=\"drawerfiltervisible; else filtroInactivo\" \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"20\" height=\"20\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"/>\r\n </svg>\r\n <ng-template #filtroInactivo>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"20\" height=\"20\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"none\" \r\n stroke=\"currentColor\" \r\n stroke-width=\"2\">\r\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>\r\n </svg>\r\n </ng-template>\r\n </button>\r\n</div> -->\r\n\r\n<div class=\"controls-container\" >\r\n @if ( showControls() ) { \r\n <!-- Botones principales con nz-button y tipos de Ant Design -->\r\n <button nz-button nzType=\"default\" (click)=\"saveLayoutToJSON()\" >\r\n <span nz-icon nz-type=\"code\"></span> Guardar JSON\r\n </button>\r\n\r\n <button nz-button nzType=\"primary\" (click)=\"fn_btn_addWidget()\" >\r\n <span nz-icon nz-type=\"plus\"></span> A\u00F1adir widget\r\n </button>\r\n\r\n <button nz-button [nzType]=\"isLocked ? 'primary' : 'default'\" nzDanger (click)=\"fn_btn_lockPositionWidgets()\" >\r\n <span nz-icon [nzType]=\"isLocked ? 'lock' : 'unlock'\"></span> \r\n {{ isLocked ? 'Bloqueado' : 'Bloquear' }}\r\n </button>\r\n }\r\n @if ( showFilter() ) { \r\n <!-- Bot\u00F3n de filtro con estilo ic\u00F3nico -->\r\n <button nz-button nzType=\"default\" nzShape=\"circle\" (click)=\"handleShowFormFilterDrawer()\" class=\"btn-filtro\" [class.active]=\"drawerfiltervisible\" >\r\n <svg *ngIf=\"drawerfiltervisible; else filtroInactivo\" \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"/>\r\n </svg>\r\n <ng-template #filtroInactivo>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"none\" \r\n stroke=\"currentColor\" \r\n stroke-width=\"2\">\r\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>\r\n </svg>\r\n </ng-template>\r\n </button>\r\n }\r\n</div>\r\n<div #gridContainer class=\"grid-stack canvas-container\"\r\n [style.--canvas-bg]=\"dashboardStyle.canvasBackgroundColor\"\r\n></div>\r\n\r\n\r\n\r\n\r\n<!-- DRAWER - FILTER -->\r\n\r\n<nz-drawer\r\n[nzVisible]=\"drawerfiltervisible\"\r\n[nzMaskClosable]=\"false\"\r\nnzPlacement=\"right\"\r\n[nzWidth]=\"fnGetDrawerWidth(50)\"\r\n(nzOnClose)=\"handleCloseFormFilterDrawer()\"\r\n>\r\n<ng-container *nzDrawerContent>\r\n <div class=\"widget-details-info\">\r\n <h6 nz-typography>Filtros</h6>\r\n <yw-dashboard-filter\r\n [dashboardFilterConfig]=\"dashboardFilterConfig\"\r\n [dashboardData]=\"dashboardData\"\r\n (filterSelectionChange)=\"onFilterSelectionChange($event)\"\r\n >\r\n </yw-dashboard-filter>\r\n </div>\r\n\r\n <!--\r\n <nz-tabset nzCentered>\r\n <nz-tab nzTitle=\"Secion de Filtros\">\r\n <div class=\"controls\">\r\n aqui botones de control:\r\n\r\n </div>\r\n <div>\r\n \r\n\r\n </div>\r\n\r\n </nz-tab>\r\n \r\n </nz-tabset>\r\n-->\r\n</ng-container>\r\n</nz-drawer>\r\n\r\n\r\n\r\n<!-- DRAWER - CONFIGURACION -->\r\n<nz-drawer\r\n[nzVisible]=\"drawerconfigvisible\"\r\n[nzMaskClosable]=\"false\"\r\nnzPlacement=\"right\"\r\n[nzWidth]=\"fnGetDrawerWidth(50)\"\r\n(nzOnClose)=\"handleCloseFormDrawer()\"\r\n>\r\n<ng-container *nzDrawerContent>\r\n <div class=\"widget-details-info\">\r\n <h6 nz-typography>{{ drawerCurrentWidgetObject.widgetId }}</h6>\r\n </div>\r\n <nz-tabset nzCentered>\r\n <nz-tab nzTitle=\"{{ drawerCurrentWidgetObject.widgetId }}\">\r\n <div class=\"controls\">\r\n <button (click)=\"fn_btn_updateWidgetControlConfig(drawerCurrentWidgetObject.widgetId)\">Actualiza Configuracion</button>\r\n <button (click)=\"fn_btn_updateWidgetControlData(drawerCurrentWidgetObject.widgetId)\">Actualiza Data</button> \r\n </div>\r\n <div>\r\n bla bla bla\r\n </div>\r\n\r\n </nz-tab>\r\n \r\n </nz-tabset>\r\n</ng-container>\r\n</nz-drawer>", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.canvas-container{background-color:var(--canvas-bg, #f5f5f5);min-height:500px;padding:10px}::vdeep .card-inner{background:#fff;border:1px solid #ccc;height:100%;display:flex;align-items:center;justify-content:center}:host ::ng-deep .grid-stack-item-content{border-radius:6px;box-shadow:0 2px 5px #0000001a;display:flex;align-items:center;justify-content:center;font-weight:700;overflow:hidden}::ng-deep .grid-stack-item.widget-maximized{position:fixed!important;top:0!important;left:0!important;width:100vw!important;height:100vh!important;z-index:9999!important;transform:none!important;margin:0!important;padding:5px}::ng-deep .grid-stack-item.widget-maximized .grid-stack-item-content{position:absolute!important;inset:0!important;width:100%!important;height:100%!important;margin:0!important;padding:0!important;border:none!important;border-radius:0!important;box-shadow:none!important;background-color:#fff!important;overflow:hidden}::ng-deep .grid-stack>.grid-stack-item>.ui-resizable-handle{opacity:0!important;background-image:none!important}.widget-details-info{padding-top:30px;text-align:center}.widget-details-info h6{font-family:manrope,sans-serif;font-size:20px;font-weight:700;line-height:26px;color:#2d3144}.widget-details-info p{font-family:manrope,sans-serif;font-size:14px;font-weight:400;line-height:21px;color:#4b5064}.controls-container{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:12px 16px;background:#fff;border-bottom:1px solid #f0f0f0;box-shadow:0 2px 8px #0000000a;border-radius:6px;margin-bottom:16px;width:100%;box-sizing:border-box;position:sticky;top:0}.controls-container button{white-space:nowrap}.controls-container .btn-filtro{display:inline-flex;align-items:center;justify-content:center;padding:0;width:32px;height:32px;border-radius:50%;transition:all .3s ease}.controls-container .btn-filtro.active{color:#fff;background-color:#1890ff;border-color:#1890ff}.controls-container .btn-filtro.active:hover{background-color:#40a9ff;border-color:#40a9ff}@media(max-width:576px){.controls-container{gap:8px;padding:8px 10px}.controls-container button[nz-button]{font-size:13px;padding:0 10px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: NzDrawerModule }, { kind: "component", type: i2.NzDrawerComponent, selector: "nz-drawer", inputs: ["nzContent", "nzCloseIcon", "nzClosable", "nzMaskClosable", "nzMask", "nzCloseOnNavigation", "nzNoAnimation", "nzKeyboard", "nzTitle", "nzExtra", "nzFooter", "nzPlacement", "nzSize", "nzMaskStyle", "nzBodyStyle", "nzWrapClassName", "nzWidth", "nzHeight", "nzZIndex", "nzOffsetX", "nzOffsetY", "nzVisible"], outputs: ["nzOnViewInit", "nzOnClose", "nzVisibleChange"], exportAs: ["nzDrawer"] }, { kind: "directive", type: i2.NzDrawerContentDirective, selector: "[nzDrawerContent]", exportAs: ["nzDrawerContent"] }, { kind: "ngmodule", type: NzTabsModule }, { kind: "component", type: i3.NzTabsComponent, selector: "nz-tabs,nz-tabset", inputs: ["nzSelectedIndex", "nzTabPosition", "nzTabBarExtraContent", "nzCanDeactivate", "nzAddIcon", "nzTabBarStyle", "nzType", "nzSize", "nzAnimated", "nzTabBarGutter", "nzHideAdd", "nzCentered", "nzHideAll", "nzLinkRouter", "nzLinkExact", "nzDestroyInactiveTabPane"], outputs: ["nzSelectChange", "nzSelectedIndexChange", "nzTabListScroll", "nzClose", "nzAdd"], exportAs: ["nzTabs"] }, { kind: "component", type: i3.NzTabComponent, selector: "nz-tab", inputs: ["nzTitle", "nzClosable", "nzCloseIcon", "nzDisabled", "nzForceRender"], outputs: ["nzSelect", "nzDeselect", "nzClick", "nzContextmenu"], exportAs: ["nzTab"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i1$3.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i5.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i6.ɵNzTransitionPatchDirective, selector: "[nz-button], [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "directive", type: i7.NzWaveDirective, selector: "[nz-wave],button[nz-button]:not([nzType=\"link\"]):not([nzType=\"text\"])", inputs: ["nzWaveExtraNode"], exportAs: ["nzWave"] }, { kind: "component", type: YwDashboardFilterComponent, selector: "yw-dashboard-filter", inputs: ["dashboardFilterConfig", "dashboardData"], outputs: ["filterSelectionChange"] }] }); }
|
|
4691
4729
|
}
|
|
4692
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type:
|
|
4730
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: YwDashboardComponent, decorators: [{
|
|
4693
4731
|
type: Component,
|
|
4694
|
-
args: [{ selector: 'yw-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4732
|
+
args: [{ selector: 'yw-dashboard', standalone: true, imports: [CommonModule,
|
|
4733
|
+
YwDashboardWidgetComponent,
|
|
4734
|
+
NzDrawerModule,
|
|
4735
|
+
NzTabsModule,
|
|
4736
|
+
YwBaseSlicerComponent,
|
|
4737
|
+
NzIconModule,
|
|
4738
|
+
NzButtonModule,
|
|
4739
|
+
YwButtonSlicerComponent,
|
|
4740
|
+
YwListSlicerComponent,
|
|
4741
|
+
YwDashboardFilterComponent
|
|
4742
|
+
], template: "<!-- <div class=\"controls\" [hidden]=\"!showControls()\">\r\n <button (click)=\"saveLayoutToJSON()\">Guardar JSON en Consola</button>\r\n <button (click)=\"fn_btn_addWidget()\">add widget</button>\r\n <button (click)=\"fn_btn_lockPositionWidgets()\">Lock widgets</button>\r\n <button (click)=\"handleShowFormFilterDrawer()\" class=\"btn-filtro\">\r\n <svg *ngIf=\"drawerfiltervisible; else filtroInactivo\" \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"20\" height=\"20\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"/>\r\n </svg>\r\n <ng-template #filtroInactivo>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"20\" height=\"20\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"none\" \r\n stroke=\"currentColor\" \r\n stroke-width=\"2\">\r\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>\r\n </svg>\r\n </ng-template>\r\n </button>\r\n</div> -->\r\n\r\n<div class=\"controls-container\" >\r\n @if ( showControls() ) { \r\n <!-- Botones principales con nz-button y tipos de Ant Design -->\r\n <button nz-button nzType=\"default\" (click)=\"saveLayoutToJSON()\" >\r\n <span nz-icon nz-type=\"code\"></span> Guardar JSON\r\n </button>\r\n\r\n <button nz-button nzType=\"primary\" (click)=\"fn_btn_addWidget()\" >\r\n <span nz-icon nz-type=\"plus\"></span> A\u00F1adir widget\r\n </button>\r\n\r\n <button nz-button [nzType]=\"isLocked ? 'primary' : 'default'\" nzDanger (click)=\"fn_btn_lockPositionWidgets()\" >\r\n <span nz-icon [nzType]=\"isLocked ? 'lock' : 'unlock'\"></span> \r\n {{ isLocked ? 'Bloqueado' : 'Bloquear' }}\r\n </button>\r\n }\r\n @if ( showFilter() ) { \r\n <!-- Bot\u00F3n de filtro con estilo ic\u00F3nico -->\r\n <button nz-button nzType=\"default\" nzShape=\"circle\" (click)=\"handleShowFormFilterDrawer()\" class=\"btn-filtro\" [class.active]=\"drawerfiltervisible\" >\r\n <svg *ngIf=\"drawerfiltervisible; else filtroInactivo\" \r\n xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"currentColor\">\r\n <path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"/>\r\n </svg>\r\n <ng-template #filtroInactivo>\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" \r\n width=\"16\" height=\"16\" \r\n viewBox=\"0 0 24 24\" \r\n fill=\"none\" \r\n stroke=\"currentColor\" \r\n stroke-width=\"2\">\r\n <polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\"/>\r\n </svg>\r\n </ng-template>\r\n </button>\r\n }\r\n</div>\r\n<div #gridContainer class=\"grid-stack canvas-container\"\r\n [style.--canvas-bg]=\"dashboardStyle.canvasBackgroundColor\"\r\n></div>\r\n\r\n\r\n\r\n\r\n<!-- DRAWER - FILTER -->\r\n\r\n<nz-drawer\r\n[nzVisible]=\"drawerfiltervisible\"\r\n[nzMaskClosable]=\"false\"\r\nnzPlacement=\"right\"\r\n[nzWidth]=\"fnGetDrawerWidth(50)\"\r\n(nzOnClose)=\"handleCloseFormFilterDrawer()\"\r\n>\r\n<ng-container *nzDrawerContent>\r\n <div class=\"widget-details-info\">\r\n <h6 nz-typography>Filtros</h6>\r\n <yw-dashboard-filter\r\n [dashboardFilterConfig]=\"dashboardFilterConfig\"\r\n [dashboardData]=\"dashboardData\"\r\n (filterSelectionChange)=\"onFilterSelectionChange($event)\"\r\n >\r\n </yw-dashboard-filter>\r\n </div>\r\n\r\n <!--\r\n <nz-tabset nzCentered>\r\n <nz-tab nzTitle=\"Secion de Filtros\">\r\n <div class=\"controls\">\r\n aqui botones de control:\r\n\r\n </div>\r\n <div>\r\n \r\n\r\n </div>\r\n\r\n </nz-tab>\r\n \r\n </nz-tabset>\r\n-->\r\n</ng-container>\r\n</nz-drawer>\r\n\r\n\r\n\r\n<!-- DRAWER - CONFIGURACION -->\r\n<nz-drawer\r\n[nzVisible]=\"drawerconfigvisible\"\r\n[nzMaskClosable]=\"false\"\r\nnzPlacement=\"right\"\r\n[nzWidth]=\"fnGetDrawerWidth(50)\"\r\n(nzOnClose)=\"handleCloseFormDrawer()\"\r\n>\r\n<ng-container *nzDrawerContent>\r\n <div class=\"widget-details-info\">\r\n <h6 nz-typography>{{ drawerCurrentWidgetObject.widgetId }}</h6>\r\n </div>\r\n <nz-tabset nzCentered>\r\n <nz-tab nzTitle=\"{{ drawerCurrentWidgetObject.widgetId }}\">\r\n <div class=\"controls\">\r\n <button (click)=\"fn_btn_updateWidgetControlConfig(drawerCurrentWidgetObject.widgetId)\">Actualiza Configuracion</button>\r\n <button (click)=\"fn_btn_updateWidgetControlData(drawerCurrentWidgetObject.widgetId)\">Actualiza Data</button> \r\n </div>\r\n <div>\r\n bla bla bla\r\n </div>\r\n\r\n </nz-tab>\r\n \r\n </nz-tabset>\r\n</ng-container>\r\n</nz-drawer>", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.canvas-container{background-color:var(--canvas-bg, #f5f5f5);min-height:500px;padding:10px}::vdeep .card-inner{background:#fff;border:1px solid #ccc;height:100%;display:flex;align-items:center;justify-content:center}:host ::ng-deep .grid-stack-item-content{border-radius:6px;box-shadow:0 2px 5px #0000001a;display:flex;align-items:center;justify-content:center;font-weight:700;overflow:hidden}::ng-deep .grid-stack-item.widget-maximized{position:fixed!important;top:0!important;left:0!important;width:100vw!important;height:100vh!important;z-index:9999!important;transform:none!important;margin:0!important;padding:5px}::ng-deep .grid-stack-item.widget-maximized .grid-stack-item-content{position:absolute!important;inset:0!important;width:100%!important;height:100%!important;margin:0!important;padding:0!important;border:none!important;border-radius:0!important;box-shadow:none!important;background-color:#fff!important;overflow:hidden}::ng-deep .grid-stack>.grid-stack-item>.ui-resizable-handle{opacity:0!important;background-image:none!important}.widget-details-info{padding-top:30px;text-align:center}.widget-details-info h6{font-family:manrope,sans-serif;font-size:20px;font-weight:700;line-height:26px;color:#2d3144}.widget-details-info p{font-family:manrope,sans-serif;font-size:14px;font-weight:400;line-height:21px;color:#4b5064}.controls-container{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:12px 16px;background:#fff;border-bottom:1px solid #f0f0f0;box-shadow:0 2px 8px #0000000a;border-radius:6px;margin-bottom:16px;width:100%;box-sizing:border-box;position:sticky;top:0}.controls-container button{white-space:nowrap}.controls-container .btn-filtro{display:inline-flex;align-items:center;justify-content:center;padding:0;width:32px;height:32px;border-radius:50%;transition:all .3s ease}.controls-container .btn-filtro.active{color:#fff;background-color:#1890ff;border-color:#1890ff}.controls-container .btn-filtro.active:hover{background-color:#40a9ff;border-color:#40a9ff}@media(max-width:576px){.controls-container{gap:8px;padding:8px 10px}.controls-container button[nz-button]{font-size:13px;padding:0 10px}}\n"] }]
|
|
4743
|
+
}], ctorParameters: () => [{ type: i0.EnvironmentInjector }, { type: i0.ApplicationRef }], propDecorators: { gridContainer: [{
|
|
4744
|
+
type: ViewChild,
|
|
4745
|
+
args: ['gridContainer', { static: true }]
|
|
4746
|
+
}], showControls: [{ type: i0.Input, args: [{ isSignal: true, alias: "showControls", required: false }] }], showFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFilter", required: false }] }], dashboardStyle: [{
|
|
4747
|
+
type: Input
|
|
4748
|
+
}], dashboardConfig: [{
|
|
4749
|
+
type: Input
|
|
4750
|
+
}], dashboardData: [{
|
|
4751
|
+
type: Input
|
|
4752
|
+
}], dashboardFilterConfig: [{
|
|
4753
|
+
type: Input
|
|
4704
4754
|
}] } });
|
|
4705
4755
|
|
|
4706
4756
|
// Configuraciones especificas de pie chart -> acumulation chart en syncfusion
|