This commit is contained in:
Gaurav Kumar
2025-11-04 17:41:18 +05:30
parent 29e50253af
commit 0e6e4899e5
3 changed files with 216 additions and 46 deletions

View File

@@ -60,6 +60,7 @@ export class EditnewdashComponent implements OnInit {
// Add availableKeys property for compact filter
availableKeys: string[] = [];
// Initialize with default widgets and update dynamically
WidgetsMock: WidgetModel[] = [
{
name: 'Common Filter',
@@ -77,26 +78,26 @@ export class EditnewdashComponent implements OnInit {
name: 'Line Chart',
identifier: 'line_chart'
},
{
name: 'Bar Chart',
identifier: 'bar_chart'
},
{
name: 'Pie Chart',
identifier: 'pie_chart'
},
{
name: 'Polar Area Chart',
identifier: 'polar_area_chart'
},
{
name: 'Bubble Chart',
identifier: 'bubble_chart'
},
{
name: 'Scatter Chart',
identifier: 'scatter_chart'
},
// {
// name: 'Bar Chart',
// identifier: 'bar_chart'
// },
// {
// name: 'Pie Chart',
// identifier: 'pie_chart'
// },
// {
// name: 'Polar Area Chart',
// identifier: 'polar_area_chart'
// },
// {
// name: 'Bubble Chart',
// identifier: 'bubble_chart'
// },
// {
// name: 'Scatter Chart',
// identifier: 'scatter_chart'
// },
{
name: 'Dynamic Chart',
identifier: 'dynamic_chart'
@@ -208,6 +209,9 @@ export class EditnewdashComponent implements OnInit {
// Add drilldown column data property
drilldownColumnData = []; // Add drilldown column data property
// Add chart types property for dynamic chart selection
chartTypes: any[] = [];
constructor(private route: ActivatedRoute,
private router: Router,
private dashboardService: Dashboard3Service,
@@ -302,6 +306,9 @@ export class EditnewdashComponent implements OnInit {
apiUrl: ['']
});
// Load chart types for dynamic chart selection
this.loadChartTypesForSelection();
// Load sureconnect data first, then load dashboard data
this.loadSureconnectData();
@@ -309,6 +316,37 @@ export class EditnewdashComponent implements OnInit {
this.loadCommonFilterData();
}
// Add method to load all chart types for dynamic selection
loadChartTypesForSelection() {
console.log('Loading chart types for selection');
this.dynamicChartLoader.loadActiveChartTypes().subscribe({
next: (chartTypes) => {
console.log('Loaded chart types for selection:', chartTypes);
this.chartTypes = chartTypes;
// Convert each chart type to a WidgetModel
const newWidgets = chartTypes.map(ct => ({
name: ct.displayName || ct.name,
// identifier: ct.name.toLowerCase().replace(/\s+/g, '_')
identifier: `${ct.name.toLowerCase().replace(/\s+/g, '_')}_chart`
}));
// Filter out duplicates by identifier
const existingIds = new Set(this.WidgetsMock.map(w => w.identifier));
const uniqueNewWidgets = newWidgets.filter(w => !existingIds.has(w.identifier));
// Append unique new widgets to WidgetsMock
this.WidgetsMock = [...this.WidgetsMock, ...uniqueNewWidgets];
console.log('Updated WidgetsMock:', this.WidgetsMock);
},
error: (error) => {
console.error('Error loading chart types for selection:', error);
}
});
}
// Add method to load sureconnect data
loadSureconnectData() {
this.sureconnectService.getAll().subscribe((data: any[]) => {
@@ -2151,20 +2189,7 @@ export class EditnewdashComponent implements OnInit {
});
}
// Add method to load all chart types for dynamic selection
loadChartTypesForSelection() {
console.log('Loading chart types for selection');
this.dynamicChartLoader.loadActiveChartTypes().subscribe({
next: (chartTypes) => {
console.log('Loaded chart types for selection:', chartTypes);
// Here you would update the UI to show available chart types
// For example, populate a dropdown or list
},
error: (error) => {
console.error('Error loading chart types for selection:', error);
}
});
}
// Add method to create a dynamic chart with configuration from database
createDynamicChart(chartTypeName: string, maxChartId: number) {
@@ -2212,24 +2237,24 @@ export class EditnewdashComponent implements OnInit {
error: (error) => {
console.error(`Error loading configuration for ${chartTypeName}:`, error);
// Fallback to default configuration
this.createDefaultChart(chartTypeName, maxChartId);
// this.createDefaultChart(chartTypeName, maxChartId);
}
});
} else {
console.warn(`Chart type ${chartTypeName} not found, using default configuration`);
this.createDefaultChart(chartTypeName, maxChartId);
// this.createDefaultChart(chartTypeName, maxChartId);
}
},
error: (error) => {
console.error(`Error finding chart type ${chartTypeName}:`, error);
console.error('Error loading configuration for chart type:', error);
// Fallback to default configuration
this.createDefaultChart(chartTypeName, maxChartId);
// this.createDefaultChart(chartType.name, chartType.displayName || chartType.name);
}
});
}
// Fallback method to create default chart configuration
createDefaultChart(chartTypeName: string, maxChartId: number) {
createDefaultChart(chartTypeName: string, chartDisplayName: string) {
console.log(`Creating default chart for ${chartTypeName}`);
// Map chart type names to chart types
@@ -2247,6 +2272,18 @@ export class EditnewdashComponent implements OnInit {
// Get the chart type from the name
const chartType = chartTypeMap[chartTypeName.toLowerCase()] || 'bar';
// Safely calculate maxChartId, handling cases where chartid might be NaN or missing
let maxChartId = 0;
if (this.dashboardArray && this.dashboardArray.length > 0) {
const validChartIds = this.dashboardArray
.map(item => item.chartid)
.filter(chartid => typeof chartid === 'number' && !isNaN(chartid));
if (validChartIds.length > 0) {
maxChartId = Math.max(...validChartIds);
}
}
const chartItem = {
cols: 5,
rows: 6,
@@ -2254,7 +2291,7 @@ export class EditnewdashComponent implements OnInit {
y: 0,
chartid: maxChartId + 1,
component: UnifiedChartComponent,
name: this.getChartDisplayName(chartTypeName),
name: chartDisplayName,
chartType: chartType,
xAxis: '',
yAxis: '',
@@ -2263,7 +2300,15 @@ export class EditnewdashComponent implements OnInit {
};
this.dashboardArray.push(chartItem);
console.log(`Created default chart:`, chartItem);
console.log('Created default chart:', chartItem);
// Update the dashboard collection
this.dashboardCollection.dashboard = this.dashboardArray.slice();
// Force gridster to refresh
if (this.options && this.options.api) {
this.options.api.optionsChanged();
}
}
// Helper method to get display name for chart type

View File

@@ -1,4 +1,7 @@
<div class="chart-container" *ngIf="!noDataAvailable && !isLoading">
<!-- Dynamic template container -->
<div class="dynamic-template-container" *ngIf="dynamicTemplate" [innerHTML]="dynamicTemplate"></div>
<!-- Back button for drilldown navigation -->
<div class="drilldown-back" *ngIf="currentDrilldownLevel > 0">
<button class="btn btn-sm btn-secondary" (click)="navigateBack()">
@@ -27,7 +30,7 @@
<!-- Render different chart types based on chartType input -->
<div class="chart-wrapper">
<!-- Bar Chart -->
<div *ngIf="chartType === 'bar'" class="chart-canvas-container">
<!-- <div *ngIf="chartType === 'bar'" class="chart-canvas-container">
<canvas baseChart
[datasets]="chartData"
[labels]="chartLabels"
@@ -37,7 +40,7 @@
(chartClick)="chartClicked($event)"
(chartHover)="chartHovered($event)">
</canvas>
</div>
</div> -->
<!-- Line Chart -->
<div *ngIf="chartType === 'line'" class="chart-canvas-container">

View File

@@ -1,9 +1,10 @@
import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChanges, ViewChild } from '@angular/core';
import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChanges, ViewChild, ElementRef, Renderer2 } from '@angular/core';
import { Dashboard3Service } from '../../../../../../services/builder/dashboard3.service';
import { FilterService } from '../../common-filter/filter.service';
import { Subscription } from 'rxjs';
import { BaseChartDirective } from 'ng2-charts';
import { ChartConfiguration, ChartDataset } from 'chart.js';
import { DynamicChartLoaderService } from '../../chart-config/dynamic-chart-loader.service';
@Component({
selector: 'app-unified-chart',
@@ -75,9 +76,17 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
private documentClickHandler: ((event: MouseEvent) => void) | null = null;
private filtersInitialized: boolean = false;
// Dynamic template properties
dynamicTemplate: string = '';
dynamicStyles: string = '';
dynamicOptions: any = null;
constructor(
private dashboardService: Dashboard3Service,
private filterService: FilterService
private filterService: FilterService,
private dynamicChartLoader: DynamicChartLoaderService,
private renderer: Renderer2,
private el: ElementRef
) { }
ngOnInit(): void {
@@ -110,6 +119,10 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
// Initialize chart options with default structure
this.initializeChartOptions();
// Load dynamic template and options for this chart type
this.loadDynamicChartConfig();
this.fetchChartData();
}
@@ -179,6 +192,11 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
});
}
// Load dynamic template and options if chart type changed
if (chartTypeChanged) {
this.loadDynamicChartConfig();
}
// 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 ||
drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged ||
@@ -217,6 +235,104 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
}
}
// Load dynamic chart configuration (template, styles, and options) for the current chart type
private loadDynamicChartConfig(): void {
if (!this.chartType) {
console.log('No chart type specified, skipping dynamic chart config loading');
return;
}
console.log(`Loading dynamic chart configuration for chart type: ${this.chartType}`);
// Get chart type by name and load its configuration
this.dynamicChartLoader.getChartTypeByName(this.chartType).subscribe({
next: (chartType) => {
if (chartType) {
console.log('Found chart type:', chartType);
// Load the complete configuration for this chart type
this.dynamicChartLoader.loadChartConfiguration(chartType.id).subscribe({
next: (config) => {
console.log('Loaded chart configuration:', config);
// Apply the first template if available
if (config.templates && config.templates.length > 0) {
const defaultTemplate = config.templates.find(t => t.isDefault) || config.templates[0];
if (defaultTemplate) {
this.dynamicTemplate = defaultTemplate.templateHtml || '';
this.dynamicStyles = defaultTemplate.templateCss || '';
// Apply styles to the component
this.applyDynamicStyles();
console.log('Applied dynamic template and styles');
}
}
// Apply dynamic options if available
if (config.dynamicFields && config.dynamicFields.length > 0) {
// Find the field that contains chart options
const optionsField = config.dynamicFields.find(field =>
field.fieldName === 'chartOptions' || field.fieldName.toLowerCase().includes('options'));
if (optionsField && optionsField.fieldOptions) {
try {
this.dynamicOptions = JSON.parse(optionsField.fieldOptions);
console.log('Applied dynamic chart options:', this.dynamicOptions);
// Merge dynamic options with current chart options
this.mergeDynamicOptions();
} catch (e) {
console.error('Error parsing dynamic chart options:', e);
}
}
}
},
error: (error) => {
console.error('Error loading chart configuration:', error);
}
});
} else {
console.log(`Chart type ${this.chartType} not found in database`);
}
},
error: (error) => {
console.error('Error loading chart type:', error);
}
});
}
// Merge dynamic options with current chart options
private mergeDynamicOptions(): void {
if (this.dynamicOptions) {
// Merge dynamic options with existing chart options
this.chartOptions = { ...this.chartOptions, ...this.dynamicOptions };
// If we have a chart instance, update it
if (this.chart) {
this.chart.options = this.chartOptions;
this.chart.render();
}
}
}
// Apply dynamic styles to the component
private applyDynamicStyles(): void {
// Remove any previously applied dynamic styles
const existingStyles = this.el.nativeElement.querySelectorAll('.dynamic-chart-styles');
existingStyles.forEach((style: HTMLElement) => {
style.remove();
});
// Apply new styles if available
if (this.dynamicStyles) {
const styleElement = this.renderer.createElement('style');
this.renderer.setAttribute(styleElement, 'class', 'dynamic-chart-styles');
this.renderer.setProperty(styleElement, 'textContent', this.dynamicStyles);
this.renderer.appendChild(this.el.nativeElement, styleElement);
}
}
// Check if filters are available
hasFilters(): boolean {
const hasBaseFilters = this.baseFilters && this.baseFilters.length > 0;
@@ -349,6 +465,12 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
}
};
// If we have dynamic options, use them instead of the default ones
if (this.dynamicOptions) {
this.mergeDynamicOptions();
return;
}
switch (this.chartType) {
case 'bar':
this.initializeBarChartOptions();