This commit is contained in:
Gaurav Kumar
2025-11-04 18:37:45 +05:30
parent 0e6e4899e5
commit 1263805d61
3 changed files with 285 additions and 239 deletions

View File

@@ -89,17 +89,25 @@ export class DynamicChartLoaderService {
* Get chart type by name * Get chart type by name
* This is useful for finding a chart type by its name rather than ID * This is useful for finding a chart type by its name rather than ID
*/ */
getChartTypeByName(name: string): Observable<ChartType | null> { // getChartTypeByName(name: string): Observable<ChartType | null> {
// console.log(`Finding chart type by name: ${name}`);
// return this.apiRequest.get(`${this.chartTypesUrl}/byname?chartName=${name}`).pipe(
// map((chartTypes: ChartType[]) => {
// console.log('Available chart types:', chartTypes);
// const chartType = chartTypes.find(ct => ct.name === name);
// console.log(`Found chart type for name ${name}:`, chartType);
// return chartType || null;
// })
// );
// }
getChartTypeByName(name: string): Observable<any> {
console.log(`Finding chart type by name: ${name}`); console.log(`Finding chart type by name: ${name}`);
return this.apiRequest.get(`${this.chartTypesUrl}`).pipe( return this.apiRequest.get(`${this.chartTypesUrl}/byname?chartName=${name}`);
map((chartTypes: ChartType[]) => {
const chartType = chartTypes.find(ct => ct.name === name);
console.log(`Found chart type for name ${name}:`, chartType);
return chartType || null;
})
);
} }
/** /**
* Load all active chart types * Load all active chart types
* This is used to populate the chart selection in the dashboard editor * This is used to populate the chart selection in the dashboard editor

View File

@@ -43,7 +43,7 @@
</div> --> </div> -->
<!-- Line Chart --> <!-- Line Chart -->
<div *ngIf="chartType === 'line'" class="chart-canvas-container"> <!-- <div *ngIf="chartType === 'line'" class="chart-canvas-container">
<canvas baseChart <canvas baseChart
[datasets]="chartData" [datasets]="chartData"
[labels]="chartLabels" [labels]="chartLabels"
@@ -53,10 +53,10 @@
(chartClick)="chartClicked($event)" (chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)"> (chartHover)="chartHovered($event)">
</canvas> </canvas>
</div> </div> -->
<!-- Pie Chart --> <!-- Pie Chart -->
<div *ngIf="chartType === 'pie'" class="chart-canvas-container"> <!-- <div *ngIf="chartType === 'pie'" class="chart-canvas-container">
<canvas baseChart <canvas baseChart
[datasets]="chartData" [datasets]="chartData"
[labels]="chartLabels" [labels]="chartLabels"
@@ -66,10 +66,10 @@
(chartClick)="chartClicked($event)" (chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)"> (chartHover)="chartHovered($event)">
</canvas> </canvas>
</div> </div> -->
<!-- Doughnut Chart --> <!-- Doughnut Chart -->
<div *ngIf="chartType === 'doughnut'" class="chart-canvas-container"> <!-- <div *ngIf="chartType === 'doughnut'" class="chart-canvas-container">
<canvas baseChart <canvas baseChart
[datasets]="chartData" [datasets]="chartData"
[labels]="chartLabels" [labels]="chartLabels"
@@ -79,10 +79,10 @@
(chartClick)="chartClicked($event)" (chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)"> (chartHover)="chartHovered($event)">
</canvas> </canvas>
</div> </div> -->
<!-- Bubble Chart --> <!-- Bubble Chart -->
<div *ngIf="chartType === 'bubble'" class="chart-canvas-container"> <!-- <div *ngIf="chartType === 'bubble'" class="chart-canvas-container">
<canvas baseChart <canvas baseChart
[datasets]="bubbleChartData" [datasets]="bubbleChartData"
[options]="chartOptions" [options]="chartOptions"
@@ -91,10 +91,10 @@
(chartClick)="chartClicked($event)" (chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)"> (chartHover)="chartHovered($event)">
</canvas> </canvas>
</div> </div> -->
<!-- Radar Chart --> <!-- Radar Chart -->
<div *ngIf="chartType === 'radar'" class="chart-canvas-container"> <!-- <div *ngIf="chartType === 'radar'" class="chart-canvas-container">
<canvas baseChart <canvas baseChart
[datasets]="chartData" [datasets]="chartData"
[labels]="chartLabels" [labels]="chartLabels"
@@ -104,10 +104,10 @@
(chartClick)="chartClicked($event)" (chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)"> (chartHover)="chartHovered($event)">
</canvas> </canvas>
</div> </div> -->
<!-- Polar Area Chart --> <!-- Polar Area Chart -->
<div *ngIf="chartType === 'polar'" class="chart-canvas-container"> <!-- <div *ngIf="chartType === 'polar'" class="chart-canvas-container">
<canvas baseChart <canvas baseChart
[datasets]="chartData" [datasets]="chartData"
[labels]="chartLabels" [labels]="chartLabels"
@@ -117,10 +117,10 @@
(chartClick)="chartClicked($event)" (chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)"> (chartHover)="chartHovered($event)">
</canvas> </canvas>
</div> </div> -->
<!-- Scatter Chart --> <!-- Scatter Chart -->
<div *ngIf="chartType === 'scatter'" class="chart-canvas-container"> <!-- <div *ngIf="chartType === 'scatter'" class="chart-canvas-container">
<canvas baseChart <canvas baseChart
[datasets]="chartData" [datasets]="chartData"
[options]="chartOptions" [options]="chartOptions"
@@ -129,7 +129,7 @@
(chartClick)="chartClicked($event)" (chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)"> (chartHover)="chartHovered($event)">
</canvas> </canvas>
</div> </div> -->
<!-- Default/Unknown Chart Type --> <!-- Default/Unknown Chart Type -->
<div *ngIf="!['bar', 'line', 'pie', 'doughnut', 'bubble', 'radar', 'polar', 'scatter'].includes(chartType)" class="chart-canvas-container"> <div *ngIf="!['bar', 'line', 'pie', 'doughnut', 'bubble', 'radar', 'polar', 'scatter'].includes(chartType)" class="chart-canvas-container">

View File

@@ -81,6 +81,12 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
dynamicStyles: string = ''; dynamicStyles: string = '';
dynamicOptions: any = null; dynamicOptions: any = null;
// Add setter to log when dynamicTemplate changes
setDynamicTemplate(value: string) {
console.log('Setting dynamic template:', value);
this.dynamicTemplate = value;
}
constructor( constructor(
private dashboardService: Dashboard3Service, private dashboardService: Dashboard3Service,
private filterService: FilterService, private filterService: FilterService,
@@ -129,6 +135,11 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
console.log('UnifiedChartComponent input changes:', changes); console.log('UnifiedChartComponent input changes:', changes);
// Log chartType changes specifically
if (changes.chartType) {
console.log('Chart type changed from', changes.chartType.previousValue, 'to', changes.chartType.currentValue);
}
// Log all input values for debugging // Log all input values for debugging
console.log('Current input values:', { console.log('Current input values:', {
chartType: this.chartType, chartType: this.chartType,
@@ -199,8 +210,8 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
// Only fetch data if the actual chart configuration changed and we're not already fetching // Only fetch data if the actual chart configuration changed and we're not already fetching
if (!this.isFetchingData && (chartTypeChanged || xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged || if (!this.isFetchingData && (chartTypeChanged || xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged ||
drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged || drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged ||
drilldownLayersChanged)) { drilldownLayersChanged)) {
console.log('Chart configuration changed, fetching new data'); console.log('Chart configuration changed, fetching new data');
this.initializeChartOptions(); this.initializeChartOptions();
this.fetchChartData(); this.fetchChartData();
@@ -243,38 +254,53 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
} }
console.log(`Loading dynamic chart configuration for chart type: ${this.chartType}`); console.log(`Loading dynamic chart configuration for chart type: ${this.chartType}`);
console.log('Current dynamic template:', this.dynamicTemplate);
// Get chart type by name and load its configuration // Get chart type by name and load its configuration
console.log('Calling getChartTypeByName with:', this.chartType);
this.dynamicChartLoader.getChartTypeByName(this.chartType).subscribe({ this.dynamicChartLoader.getChartTypeByName(this.chartType).subscribe({
next: (chartType) => { next: (chartType) => {
console.log('Received chart type by name :', chartType);
if (chartType) { if (chartType) {
console.log('Found chart type:', chartType); console.log('Found chart type:', chartType);
// Load the complete configuration for this chart type // Load the complete configuration for this chart type
console.log('Loading chart configuration for chart type ID:', chartType.id);
this.dynamicChartLoader.loadChartConfiguration(chartType.id).subscribe({ this.dynamicChartLoader.loadChartConfiguration(chartType.id).subscribe({
next: (config) => { next: (config) => {
console.log('Received chart configuration:', config);
console.log('Loaded chart configuration:', config); console.log('Loaded chart configuration:', config);
// Apply the first template if available // Apply the first template if available
if (config.templates && config.templates.length > 0) { if (config.templates && config.templates.length > 0) {
const defaultTemplate = config.templates.find(t => t.isDefault) || config.templates[0]; const defaultTemplate = config.templates.find(t => t.isDefault) || config.templates[0];
if (defaultTemplate) { if (defaultTemplate) {
this.dynamicTemplate = defaultTemplate.templateHtml || ''; this.setDynamicTemplate(defaultTemplate.templateHtml || '');
this.dynamicStyles = defaultTemplate.templateCss || ''; this.dynamicStyles = defaultTemplate.templateCss || '';
// Apply styles to the component // Apply styles to the component
this.applyDynamicStyles(); this.applyDynamicStyles();
console.log('Applied dynamic template and styles'); console.log('Applied dynamic template and styles', {
template: this.dynamicTemplate,
styles: this.dynamicStyles
});
} }
} else {
console.log('No templates found for chart type:', this.chartType);
} }
// Apply dynamic options if available // Apply dynamic options if available
console.log('Checking for dynamic fields:', config.dynamicFields);
if (config.dynamicFields && config.dynamicFields.length > 0) { if (config.dynamicFields && config.dynamicFields.length > 0) {
// Find the field that contains chart options // Find the field that contains chart options
const optionsField = config.dynamicFields.find(field => const optionsField = config.dynamicFields.find(field =>
field.fieldName === 'chartOptions' || field.fieldName.toLowerCase().includes('options')); field.fieldName === 'chartOptions' || field.fieldName.toLowerCase().includes('options'));
if (!optionsField) {
console.log('No chartOptions field found in dynamic fields');
}
if (optionsField && optionsField.fieldOptions) { if (optionsField && optionsField.fieldOptions) {
try { try {
this.dynamicOptions = JSON.parse(optionsField.fieldOptions); this.dynamicOptions = JSON.parse(optionsField.fieldOptions);
@@ -286,6 +312,8 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
console.error('Error parsing dynamic chart options:', e); console.error('Error parsing dynamic chart options:', e);
} }
} }
} else {
console.log('No dynamic fields found for chart type:', this.chartType);
} }
}, },
error: (error) => { error: (error) => {
@@ -294,6 +322,16 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
}); });
} else { } else {
console.log(`Chart type ${this.chartType} not found in database`); console.log(`Chart type ${this.chartType} not found in database`);
// Log available chart types for debugging
console.log('Available chart types in database:');
this.dynamicChartLoader.loadAllChartConfigurations().subscribe({
next: (chartTypes) => {
console.log('All chart types:', chartTypes);
},
error: (error) => {
console.error('Error loading chart types:', error);
}
});
} }
}, },
error: (error) => { error: (error) => {
@@ -713,7 +751,7 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
mode: 'point', mode: 'point',
intersect: false, intersect: false,
callbacks: { callbacks: {
label: function(context: any) { label: function (context: any) {
const point: any = context.raw; const point: any = context.raw;
if (point && point.hasOwnProperty('y') && point.hasOwnProperty('r')) { if (point && point.hasOwnProperty('y') && point.hasOwnProperty('r')) {
const yValue = parseFloat(point.y); const yValue = parseFloat(point.y);
@@ -1216,8 +1254,8 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
// If we have the expected bubble data format, return it as is // If we have the expected bubble data format, return it as is
if (data && data.length > 0 && data[0].data && data[0].data.length > 0 && if (data && data.length > 0 && data[0].data && data[0].data.length > 0 &&
typeof data[0].data[0] === 'object' && data[0].data[0].hasOwnProperty('x') && typeof data[0].data[0] === 'object' && data[0].data[0].hasOwnProperty('x') &&
data[0].data[0].hasOwnProperty('y') && data[0].data[0].hasOwnProperty('r')) { data[0].data[0].hasOwnProperty('y') && data[0].data[0].hasOwnProperty('r')) {
console.log('Data is already in bubble format, returning as is'); console.log('Data is already in bubble format, returning as is');
return data; return data;
} }
@@ -1399,17 +1437,17 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
const hue2rgb = (p: number, q: number, t: number) => { const hue2rgb = (p: number, q: number, t: number) => {
if (t < 0) t += 1; if (t < 0) t += 1;
if (t > 1) t -= 1; if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t; if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1/2) return q; if (t < 1 / 2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p; return p;
}; };
const q = l < 0.5 ? l * (1 + s) : l + s - l * s; const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q; const p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3); r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h); g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3); b = hue2rgb(p, q, h - 1 / 3);
} }
return { return {
@@ -1534,9 +1572,9 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
if (layerIndex < this.drilldownLayers.length) { if (layerIndex < this.drilldownLayers.length) {
drilldownConfig = this.drilldownLayers[layerIndex]; drilldownConfig = this.drilldownLayers[layerIndex];
hasDrilldownConfig = drilldownConfig.enabled && hasDrilldownConfig = drilldownConfig.enabled &&
!!drilldownConfig.apiUrl && !!drilldownConfig.apiUrl &&
!!drilldownConfig.xAxis && !!drilldownConfig.xAxis &&
!!drilldownConfig.yAxis; !!drilldownConfig.yAxis;
} }
} }
@@ -1634,8 +1672,8 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
// Check if there are active filters // Check if there are active filters
hasActiveFilters(): boolean { hasActiveFilters(): boolean {
return (this.baseFilters && this.baseFilters.length > 0) || return (this.baseFilters && this.baseFilters.length > 0) ||
(this.drilldownFilters && this.drilldownFilters.length > 0) || (this.drilldownFilters && this.drilldownFilters.length > 0) ||
this.hasActiveLayerFilters(); this.hasActiveLayerFilters();
} }
// Check if there are active layer filters for current drilldown level // Check if there are active layer filters for current drilldown level
@@ -1643,8 +1681,8 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
if (this.currentDrilldownLevel > 1 && this.drilldownLayers && this.drilldownLayers.length > 0) { if (this.currentDrilldownLevel > 1 && this.drilldownLayers && this.drilldownLayers.length > 0) {
const layerIndex = this.currentDrilldownLevel - 2; // -2 because level 1 is base drilldown const layerIndex = this.currentDrilldownLevel - 2; // -2 because level 1 is base drilldown
return layerIndex < this.drilldownLayers.length && return layerIndex < this.drilldownLayers.length &&
this.drilldownLayers[layerIndex].filters && this.drilldownLayers[layerIndex].filters &&
this.drilldownLayers[layerIndex].filters.length > 0; this.drilldownLayers[layerIndex].filters.length > 0;
} }
return false; return false;
} }
@@ -1654,7 +1692,7 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
if (this.currentDrilldownLevel > 1 && this.drilldownLayers && this.drilldownLayers.length > 0) { if (this.currentDrilldownLevel > 1 && this.drilldownLayers && this.drilldownLayers.length > 0) {
const layerIndex = this.currentDrilldownLevel - 2; // -2 because level 1 is base drilldown const layerIndex = this.currentDrilldownLevel - 2; // -2 because level 1 is base drilldown
if (layerIndex < this.drilldownLayers.length && if (layerIndex < this.drilldownLayers.length &&
this.drilldownLayers[layerIndex].filters) { this.drilldownLayers[layerIndex].filters) {
return this.drilldownLayers[layerIndex].filters; return this.drilldownLayers[layerIndex].filters;
} }
} }