bubble
This commit is contained in:
parent
9b775a8c63
commit
ad57f11f8a
@ -279,19 +279,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- No data message -->
|
<!-- Chart container -->
|
||||||
<div *ngIf="noDataAvailable" style="text-align: center; padding: 20px; color: #666; font-style: italic;">
|
<div style="position: relative; height: calc(100% - 50px); width: 100%;">
|
||||||
No data available
|
<!-- Loading indicator -->
|
||||||
</div>
|
<div *ngIf="!dataLoaded" style="text-align: center; padding: 20px; color: #666; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; width: 100%;">
|
||||||
|
Loading data...
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Chart display -->
|
<!-- No data message -->
|
||||||
<div *ngIf="!noDataAvailable" style="position: relative; height: calc(100% - 50px);">
|
<div *ngIf="dataLoaded && (noDataAvailable || !isChartDataValid())" style="text-align: center; padding: 20px; color: #666; font-style: italic; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; width: 100%;">
|
||||||
|
No data available
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Chart display - Always render the canvas but conditionally show/hide with CSS -->
|
||||||
<canvas baseChart
|
<canvas baseChart
|
||||||
[datasets]="bubbleChartData"
|
[datasets]="bubbleChartData"
|
||||||
[type]="bubbleChartType"
|
[type]="bubbleChartType"
|
||||||
[options]="bubbleChartOptions"
|
[options]="bubbleChartOptions"
|
||||||
(chartHover)="chartHovered($event)"
|
(chartHover)="chartHovered($event)"
|
||||||
(chartClick)="chartClicked($event)">
|
(chartClick)="chartClicked($event)"
|
||||||
|
[style.visibility]="dataLoaded && !noDataAvailable && isChartDataValid() ? 'visible' : 'hidden'"
|
||||||
|
[style.position]="'absolute'"
|
||||||
|
[style.top]="'0'"
|
||||||
|
[style.left]="'0'"
|
||||||
|
[style.height]="'100%'"
|
||||||
|
[style.width]="'100%'">
|
||||||
</canvas>
|
</canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -37,55 +37,43 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
@Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
|
@Input() drilldownLayers: any[] = []; // Array of drilldown layer configurations
|
||||||
|
|
||||||
public bubbleChartOptions: ChartConfiguration['options'] = {
|
public bubbleChartOptions: ChartConfiguration['options'] = {
|
||||||
// scales: {
|
responsive: true,
|
||||||
// x: {
|
maintainAspectRatio: false,
|
||||||
// min: 0,
|
scales: {
|
||||||
// max: 30,
|
x: {
|
||||||
// ticks: {}
|
beginAtZero: true,
|
||||||
// },
|
title: {
|
||||||
// y: {
|
display: true,
|
||||||
// min: 0,
|
text: 'X Axis'
|
||||||
// max: 30,
|
}
|
||||||
// ticks: {}
|
},
|
||||||
// },
|
y: {
|
||||||
// plugins: {
|
beginAtZero: true,
|
||||||
// title: {
|
title: {
|
||||||
// display: true,
|
display: true,
|
||||||
// text: 'Bubble Chart'
|
text: 'Y Axis'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
position: 'top',
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
enabled: true,
|
||||||
|
mode: 'point',
|
||||||
|
intersect: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
duration: 800,
|
||||||
|
easing: 'easeInOutQuart'
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public bubbleChartType: string = 'bubble';
|
public bubbleChartType: string = 'bubble';
|
||||||
public bubbleChartData: ChartDataset[] = [
|
public bubbleChartData: ChartDataset[] = [];
|
||||||
{
|
|
||||||
data: [
|
|
||||||
{ x: 10, y: 10, r: 10 },
|
|
||||||
{ x: 15, y: 5, r: 15 },
|
|
||||||
{ x: 26, y: 12, r: 23 },
|
|
||||||
{ x: 7, y: 8, r: 8 },
|
|
||||||
],
|
|
||||||
label: 'Investment Equities',
|
|
||||||
backgroundColor: 'rgba(255, 0, 0, 0.6)', // Red
|
|
||||||
borderColor: 'blue',
|
|
||||||
hoverBackgroundColor: 'purple',
|
|
||||||
hoverBorderColor: 'red',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data: [
|
|
||||||
{ x: 5, y: 15, r: 12 },
|
|
||||||
{ x: 20, y: 7, r: 8 },
|
|
||||||
{ x: 12, y: 18, r: 15 },
|
|
||||||
{ x: 8, y: 6, r: 10 },
|
|
||||||
],
|
|
||||||
label: 'Investment Bonds',
|
|
||||||
backgroundColor: 'rgba(0, 255, 0, 0.6)', // Green
|
|
||||||
borderColor: 'green',
|
|
||||||
hoverBackgroundColor: 'yellow',
|
|
||||||
hoverBorderColor: 'blue',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// Multi-layer drilldown state tracking
|
// Multi-layer drilldown state tracking
|
||||||
drilldownStack: any[] = []; // Stack to track drilldown navigation history
|
drilldownStack: any[] = []; // Stack to track drilldown navigation history
|
||||||
@ -94,6 +82,7 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
// No data state
|
// No data state
|
||||||
noDataAvailable: boolean = false;
|
noDataAvailable: boolean = false;
|
||||||
|
dataLoaded: boolean = false; // Track if data has been loaded
|
||||||
|
|
||||||
// Flag to prevent infinite loops
|
// Flag to prevent infinite loops
|
||||||
private isFetchingData: boolean = false;
|
private isFetchingData: boolean = false;
|
||||||
@ -471,39 +460,126 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
// Bubble charts expect data in the format: {x: number, y: number, r: number}
|
// Bubble charts expect data in the format: {x: number, y: number, r: number}
|
||||||
console.log('Transforming data to bubble format:', { labels, data });
|
console.log('Transforming data to bubble format:', { labels, data });
|
||||||
|
|
||||||
|
// Handle null/undefined data
|
||||||
|
if (!labels || !data) {
|
||||||
|
console.log('Labels or data is null/undefined, returning empty dataset');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
// 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');
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, create a default bubble dataset
|
// Transform the data properly for bubble chart
|
||||||
const bubbleDatasets: ChartDataset[] = [
|
// Assuming labels are x-values and data[0].data are y-values
|
||||||
{
|
if (labels && data && data.length > 0 && data[0].data) {
|
||||||
data: [
|
console.log('Transforming regular data to bubble format');
|
||||||
{ x: 10, y: 10, r: 10 },
|
const yValues = data[0].data;
|
||||||
{ x: 15, y: 5, r: 15 },
|
const label = data[0].label || 'Dataset 1';
|
||||||
{ x: 26, y: 12, r: 23 },
|
|
||||||
{ x: 7, y: 8, r: 8 },
|
|
||||||
],
|
|
||||||
label: 'Dataset 1',
|
|
||||||
backgroundColor: 'rgba(255, 0, 0, 0.6)',
|
|
||||||
borderColor: 'blue',
|
|
||||||
hoverBackgroundColor: 'purple',
|
|
||||||
hoverBorderColor: 'red',
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
return bubbleDatasets;
|
// Handle case where yValues might not be an array
|
||||||
|
if (!Array.isArray(yValues)) {
|
||||||
|
console.log('yValues is not an array, returning empty dataset');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('yValues type:', typeof yValues);
|
||||||
|
console.log('yValues length:', yValues.length);
|
||||||
|
console.log('First few yValues:', yValues.slice(0, 5));
|
||||||
|
|
||||||
|
// Create bubble points from labels (x) and data (y)
|
||||||
|
const bubblePoints = [];
|
||||||
|
const minLength = Math.min(labels.length, yValues.length);
|
||||||
|
|
||||||
|
console.log('Processing data points:', { labels, yValues, minLength });
|
||||||
|
|
||||||
|
for (let i = 0; i < minLength; i++) {
|
||||||
|
// Log each point for debugging
|
||||||
|
console.log(`Processing point ${i}: label=${labels[i]}, yValue=${yValues[i]}, type=${typeof yValues[i]}`);
|
||||||
|
|
||||||
|
// Convert y to number if it's a string
|
||||||
|
let y;
|
||||||
|
if (typeof yValues[i] === 'string') {
|
||||||
|
y = parseFloat(yValues[i]);
|
||||||
|
console.log(`Converted string yValue to number: ${yValues[i]} -> ${y}`);
|
||||||
|
} else {
|
||||||
|
y = yValues[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle NaN values
|
||||||
|
if (isNaN(y)) {
|
||||||
|
console.log(`Skipping point ${i} due to NaN y value: ${yValues[i]}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate radius based on the y-value
|
||||||
|
const r = Math.max(5, Math.min(30, Math.abs(y) / 10));
|
||||||
|
|
||||||
|
// For x-value, we'll use the index position since labels are strings
|
||||||
|
const x = i;
|
||||||
|
|
||||||
|
// Add the point
|
||||||
|
const point = {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
r
|
||||||
|
};
|
||||||
|
console.log(`Adding point ${i}:`, point);
|
||||||
|
bubblePoints.push(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Generated bubble points:', bubblePoints);
|
||||||
|
console.log('Generated bubble points count:', bubblePoints.length);
|
||||||
|
|
||||||
|
// If we have no valid points, return empty array
|
||||||
|
if (bubblePoints.length === 0) {
|
||||||
|
console.log('No valid bubble points generated, returning empty dataset');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a single dataset with all bubble points
|
||||||
|
const bubbleDatasets: ChartDataset[] = [
|
||||||
|
{
|
||||||
|
data: bubblePoints,
|
||||||
|
label: label,
|
||||||
|
backgroundColor: 'rgba(255, 99, 132, 0.6)',
|
||||||
|
borderColor: 'rgba(255, 99, 132, 1)',
|
||||||
|
hoverBackgroundColor: 'rgba(255, 99, 132, 0.8)',
|
||||||
|
hoverBorderColor: 'rgba(255, 99, 132, 1)',
|
||||||
|
borderWidth: 1,
|
||||||
|
pointHoverRadius: 10,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log('Transformed bubble data:', bubbleDatasets);
|
||||||
|
return bubbleDatasets;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Could not transform data, returning empty dataset');
|
||||||
|
// Return empty dataset instead of default data
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchChartData(): void {
|
fetchChartData(): void {
|
||||||
// Set flag to prevent recursive calls
|
// Set flag to prevent recursive calls
|
||||||
this.isFetchingData = true;
|
this.isFetchingData = true;
|
||||||
|
this.dataLoaded = false; // Mark data as not loaded yet
|
||||||
|
this.noDataAvailable = false; // Reset no data flag
|
||||||
|
|
||||||
|
console.log('Starting fetchChartData, current state:', {
|
||||||
|
table: this.table,
|
||||||
|
xAxis: this.xAxis,
|
||||||
|
yAxis: this.yAxis,
|
||||||
|
connection: this.connection
|
||||||
|
});
|
||||||
|
|
||||||
// If we're in drilldown mode, fetch the appropriate drilldown data
|
// If we're in drilldown mode, fetch the appropriate drilldown data
|
||||||
if (this.currentDrilldownLevel > 0 && this.drilldownStack.length > 0) {
|
if (this.currentDrilldownLevel > 0 && this.drilldownStack.length > 0) {
|
||||||
|
console.log('Fetching drilldown data');
|
||||||
this.fetchDrilldownData();
|
this.fetchDrilldownData();
|
||||||
// Reset flag after fetching
|
// Reset flag after fetching
|
||||||
this.isFetchingData = false;
|
this.isFetchingData = false;
|
||||||
@ -583,32 +659,82 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
this.dashboardService.getChartData(this.table, 'bubble', this.xAxis, yAxisString, this.connection, '', '', filterParams).subscribe(
|
this.dashboardService.getChartData(this.table, 'bubble', this.xAxis, yAxisString, this.connection, '', '', filterParams).subscribe(
|
||||||
(data: any) => {
|
(data: any) => {
|
||||||
console.log('Received bubble chart data:', data);
|
console.log('Received bubble chart data:', data);
|
||||||
if (data === null) {
|
|
||||||
console.warn('Bubble chart API returned null data. Check if the API endpoint is working correctly.');
|
|
||||||
this.noDataAvailable = true;
|
|
||||||
this.bubbleChartData = [];
|
|
||||||
// Reset flag after fetching
|
|
||||||
this.isFetchingData = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the actual data structure returned by the API
|
// Reset chart data to empty first
|
||||||
if (data && data.chartLabels && data.chartData) {
|
this.bubbleChartData = [];
|
||||||
|
|
||||||
|
if (data === null || data === undefined) {
|
||||||
|
console.warn('Bubble chart API returned null/undefined data. Check if the API endpoint is working correctly.');
|
||||||
|
this.noDataAvailable = true;
|
||||||
|
} else if (data && data.chartLabels && data.chartData) {
|
||||||
// For bubble charts, we need to transform the data into bubble format
|
// For bubble charts, we need to transform the data into bubble format
|
||||||
// Bubble charts expect data in the format: {x: number, y: number, r: number}
|
// Bubble charts expect data in the format: {x: number, y: number, r: number}
|
||||||
this.noDataAvailable = data.chartLabels.length === 0;
|
console.log('Processing chartLabels and chartData format');
|
||||||
this.bubbleChartData = this.transformToBubbleData(data.chartLabels, data.chartData);
|
const transformedData = this.transformToBubbleData(data.chartLabels, data.chartData);
|
||||||
console.log('Updated bubble chart with data:', this.bubbleChartData);
|
console.log('Transformed data:', transformedData);
|
||||||
|
|
||||||
|
// Check if we have valid data
|
||||||
|
let hasValidData = false;
|
||||||
|
if (transformedData && transformedData.length > 0) {
|
||||||
|
for (const dataset of transformedData) {
|
||||||
|
if (dataset.data && dataset.data.length > 0) {
|
||||||
|
hasValidData = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasValidData) {
|
||||||
|
// Create a new array reference to trigger change detection
|
||||||
|
this.bubbleChartData = [...transformedData];
|
||||||
|
this.noDataAvailable = false;
|
||||||
|
console.log('Updated bubble chart with data:', this.bubbleChartData);
|
||||||
|
} else {
|
||||||
|
console.log('No valid data after transformation');
|
||||||
|
this.noDataAvailable = true;
|
||||||
|
}
|
||||||
} else if (data && data.labels && data.datasets) {
|
} else if (data && data.labels && data.datasets) {
|
||||||
// Handle the original expected format as fallback
|
// Handle the original expected format as fallback
|
||||||
this.noDataAvailable = data.labels.length === 0;
|
console.log('Processing labels and datasets format');
|
||||||
this.bubbleChartData = data.datasets;
|
// Check if we have valid data
|
||||||
console.log('Updated bubble chart with legacy data format:', this.bubbleChartData);
|
let hasValidData = false;
|
||||||
|
if (data.datasets && data.datasets.length > 0) {
|
||||||
|
for (const dataset of data.datasets) {
|
||||||
|
if (dataset.data && dataset.data.length > 0) {
|
||||||
|
hasValidData = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasValidData) {
|
||||||
|
// Create a new array reference to trigger change detection
|
||||||
|
this.bubbleChartData = [...data.datasets];
|
||||||
|
this.noDataAvailable = false;
|
||||||
|
console.log('Updated bubble chart with legacy data format:', this.bubbleChartData);
|
||||||
|
} else {
|
||||||
|
console.log('No valid data in legacy format');
|
||||||
|
this.noDataAvailable = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn('Bubble chart received data does not have expected structure', data);
|
console.warn('Bubble chart received data does not have expected structure', data);
|
||||||
this.noDataAvailable = true;
|
this.noDataAvailable = true;
|
||||||
this.bubbleChartData = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.dataLoaded = true; // Mark data as loaded
|
||||||
|
|
||||||
|
console.log('Final state after data fetch:', {
|
||||||
|
noDataAvailable: this.noDataAvailable,
|
||||||
|
dataLoaded: this.dataLoaded,
|
||||||
|
bubbleChartDataLength: this.bubbleChartData.length,
|
||||||
|
isChartDataValid: this.isChartDataValid()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trigger change detection with a small delay to ensure proper rendering
|
||||||
|
setTimeout(() => {
|
||||||
|
this.forceChartUpdate();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
// Reset flag after fetching
|
// Reset flag after fetching
|
||||||
this.isFetchingData = false;
|
this.isFetchingData = false;
|
||||||
},
|
},
|
||||||
@ -616,15 +742,24 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
console.error('Error fetching bubble chart data:', error);
|
console.error('Error fetching bubble chart data:', error);
|
||||||
this.noDataAvailable = true;
|
this.noDataAvailable = true;
|
||||||
this.bubbleChartData = [];
|
this.bubbleChartData = [];
|
||||||
|
this.dataLoaded = true;
|
||||||
|
// Trigger change detection
|
||||||
|
setTimeout(() => {
|
||||||
|
this.forceChartUpdate();
|
||||||
|
}, 100);
|
||||||
// Reset flag after fetching
|
// Reset flag after fetching
|
||||||
this.isFetchingData = false;
|
this.isFetchingData = false;
|
||||||
// Keep default data in case of error
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log('Missing required data for bubble chart:', { table: this.table, xAxis: this.xAxis, yAxis: this.yAxis, connection: this.connection });
|
console.log('Missing required data for bubble chart:', { table: this.table, xAxis: this.xAxis, yAxis: this.yAxis, connection: this.connection });
|
||||||
this.noDataAvailable = true;
|
this.noDataAvailable = true;
|
||||||
this.bubbleChartData = [];
|
this.bubbleChartData = [];
|
||||||
|
this.dataLoaded = true;
|
||||||
|
// Trigger change detection
|
||||||
|
setTimeout(() => {
|
||||||
|
this.forceChartUpdate();
|
||||||
|
}, 100);
|
||||||
// Reset flag after fetching
|
// Reset flag after fetching
|
||||||
this.isFetchingData = false;
|
this.isFetchingData = false;
|
||||||
}
|
}
|
||||||
@ -654,6 +789,10 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
console.warn('Invalid drilldown layer index:', layerIndex);
|
console.warn('Invalid drilldown layer index:', layerIndex);
|
||||||
this.noDataAvailable = true;
|
this.noDataAvailable = true;
|
||||||
this.bubbleChartData = [];
|
this.bubbleChartData = [];
|
||||||
|
this.dataLoaded = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.forceChartUpdate();
|
||||||
|
}, 100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -665,6 +804,10 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
console.warn('Missing drilldown configuration for level:', this.currentDrilldownLevel);
|
console.warn('Missing drilldown configuration for level:', this.currentDrilldownLevel);
|
||||||
this.noDataAvailable = true;
|
this.noDataAvailable = true;
|
||||||
this.bubbleChartData = [];
|
this.bubbleChartData = [];
|
||||||
|
this.dataLoaded = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.forceChartUpdate();
|
||||||
|
}, 100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,35 +901,84 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
this.dashboardService.getChartData(actualApiUrl, 'bubble', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
this.dashboardService.getChartData(actualApiUrl, 'bubble', drilldownConfig.xAxis, drilldownConfig.yAxis, this.connection, parameterField, parameterValue, filterParams).subscribe(
|
||||||
(data: any) => {
|
(data: any) => {
|
||||||
console.log('Received drilldown data:', data);
|
console.log('Received drilldown data:', data);
|
||||||
if (data === null) {
|
|
||||||
console.warn('Drilldown API returned null data. Check if the API endpoint is working correctly.');
|
|
||||||
this.noDataAvailable = true;
|
|
||||||
this.bubbleChartData = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the actual data structure returned by the API
|
// Reset chart data to empty first
|
||||||
if (data && data.chartLabels && data.chartData) {
|
this.bubbleChartData = [];
|
||||||
|
|
||||||
|
if (data === null || data === undefined) {
|
||||||
|
console.warn('Drilldown API returned null/undefined data. Check if the API endpoint is working correctly.');
|
||||||
|
this.noDataAvailable = true;
|
||||||
|
} else if (data && data.chartLabels && data.chartData) {
|
||||||
// For bubble charts, we need to transform the data into bubble format
|
// For bubble charts, we need to transform the data into bubble format
|
||||||
this.noDataAvailable = data.chartLabels.length === 0;
|
const transformedData = this.transformToBubbleData(data.chartLabels, data.chartData);
|
||||||
this.bubbleChartData = this.transformToBubbleData(data.chartLabels, data.chartData);
|
|
||||||
console.log('Updated bubble chart with drilldown data:', this.bubbleChartData);
|
// Check if we have valid data
|
||||||
|
let hasValidData = false;
|
||||||
|
if (transformedData && transformedData.length > 0) {
|
||||||
|
for (const dataset of transformedData) {
|
||||||
|
if (dataset.data && dataset.data.length > 0) {
|
||||||
|
hasValidData = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasValidData) {
|
||||||
|
this.bubbleChartData = transformedData;
|
||||||
|
this.noDataAvailable = false;
|
||||||
|
console.log('Updated bubble chart with drilldown data:', this.bubbleChartData);
|
||||||
|
} else {
|
||||||
|
console.log('No valid data after transformation in drilldown');
|
||||||
|
this.noDataAvailable = true;
|
||||||
|
}
|
||||||
} else if (data && data.labels && data.datasets) {
|
} else if (data && data.labels && data.datasets) {
|
||||||
// Handle the original expected format as fallback
|
// Handle the original expected format as fallback
|
||||||
this.noDataAvailable = data.labels.length === 0;
|
// Check if we have valid data
|
||||||
this.bubbleChartData = data.datasets;
|
let hasValidData = false;
|
||||||
console.log('Updated bubble chart with drilldown legacy data format:', this.bubbleChartData);
|
if (data.datasets && data.datasets.length > 0) {
|
||||||
|
for (const dataset of data.datasets) {
|
||||||
|
if (dataset.data && dataset.data.length > 0) {
|
||||||
|
hasValidData = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasValidData) {
|
||||||
|
this.bubbleChartData = data.datasets;
|
||||||
|
this.noDataAvailable = false;
|
||||||
|
console.log('Updated bubble chart with drilldown legacy data format:', this.bubbleChartData);
|
||||||
|
} else {
|
||||||
|
console.log('No valid data in legacy format in drilldown');
|
||||||
|
this.noDataAvailable = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn('Drilldown received data does not have expected structure', data);
|
console.warn('Drilldown received data does not have expected structure', data);
|
||||||
this.noDataAvailable = true;
|
this.noDataAvailable = true;
|
||||||
this.bubbleChartData = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.dataLoaded = true; // Mark data as loaded
|
||||||
|
|
||||||
|
console.log('Final state after drilldown data fetch:', {
|
||||||
|
noDataAvailable: this.noDataAvailable,
|
||||||
|
dataLoaded: this.dataLoaded,
|
||||||
|
bubbleChartDataLength: this.bubbleChartData.length,
|
||||||
|
isChartDataValid: this.isChartDataValid()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trigger change detection
|
||||||
|
setTimeout(() => {
|
||||||
|
this.forceChartUpdate();
|
||||||
|
}, 100);
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
console.error('Error fetching drilldown data:', error);
|
console.error('Error fetching drilldown data:', error);
|
||||||
this.noDataAvailable = true;
|
this.noDataAvailable = true;
|
||||||
this.bubbleChartData = [];
|
this.bubbleChartData = [];
|
||||||
// Keep current data in case of error
|
this.dataLoaded = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.forceChartUpdate();
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -933,4 +1125,52 @@ export class BubbleChartComponent implements OnInit, OnChanges {
|
|||||||
public chartHovered(e: any): void {
|
public chartHovered(e: any): void {
|
||||||
console.log('Bubble chart hovered:', e);
|
console.log('Bubble chart hovered:', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method to check if chart data is valid
|
||||||
|
public isChartDataValid(): boolean {
|
||||||
|
console.log('Checking if chart data is valid:', this.bubbleChartData);
|
||||||
|
if (!this.bubbleChartData || this.bubbleChartData.length === 0) {
|
||||||
|
console.log('Chart data is null or empty');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if any dataset has data
|
||||||
|
for (const dataset of this.bubbleChartData) {
|
||||||
|
console.log('Checking dataset:', dataset);
|
||||||
|
if (dataset.data && dataset.data.length > 0) {
|
||||||
|
console.log('Dataset has data, length:', dataset.data.length);
|
||||||
|
// For bubble charts, check if data points have x, y, r properties
|
||||||
|
for (const point of dataset.data) {
|
||||||
|
console.log('Checking point:', point);
|
||||||
|
if (typeof point === 'object' && point.hasOwnProperty('x') && point.hasOwnProperty('y') && point.hasOwnProperty('r')) {
|
||||||
|
// Valid bubble point
|
||||||
|
console.log('Found valid bubble point');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('No valid chart data found');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to force chart update
|
||||||
|
private forceChartUpdate(): void {
|
||||||
|
console.log('Forcing chart update');
|
||||||
|
console.log('Current bubbleChartData:', this.bubbleChartData);
|
||||||
|
console.log('Current bubbleChartData length:', this.bubbleChartData ? this.bubbleChartData.length : 0);
|
||||||
|
if (this.bubbleChartData && this.bubbleChartData.length > 0) {
|
||||||
|
console.log('First dataset data length:', this.bubbleChartData[0].data ? this.bubbleChartData[0].data.length : 0);
|
||||||
|
}
|
||||||
|
// Create a new reference to trigger change detection
|
||||||
|
if (this.bubbleChartData) {
|
||||||
|
this.bubbleChartData = [...this.bubbleChartData];
|
||||||
|
}
|
||||||
|
// Also update noDataAvailable to trigger UI changes
|
||||||
|
this.noDataAvailable = this.noDataAvailable;
|
||||||
|
console.log('Chart update forced, noDataAvailable:', this.noDataAvailable);
|
||||||
|
console.log('Chart update forced, bubbleChartData length:', this.bubbleChartData ? this.bubbleChartData.length : 0);
|
||||||
|
console.log('Chart update forced, isChartDataValid:', this.isChartDataValid());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user