unified
This commit is contained in:
@@ -1,11 +1,4 @@
|
||||
<div class="chart-container" *ngIf="!noDataAvailable && !isLoading">
|
||||
<!-- Dynamic template container -->
|
||||
<div class="dynamic-template-container" *ngIf="dynamicTemplate" [innerHTML]="dynamicTemplate"></div>
|
||||
<!-- Debug: Show when dynamic template is loaded -->
|
||||
<div *ngIf="dynamicTemplate" style="color: red; font-weight: bold; margin: 10px;">
|
||||
DEBUG: Dynamic template loaded - check browser DevTools Elements tab to see if canvas is in DOM
|
||||
</div>
|
||||
|
||||
<!-- Back button for drilldown navigation -->
|
||||
<div class="drilldown-back" *ngIf="currentDrilldownLevel > 0">
|
||||
<button class="btn btn-sm btn-secondary" (click)="navigateBack()">
|
||||
@@ -33,110 +26,21 @@
|
||||
|
||||
<!-- Render different chart types based on chartType input -->
|
||||
<div class="chart-wrapper">
|
||||
<!-- Bar Chart -->
|
||||
<!-- <div *ngIf="chartType === 'bar'" class="chart-canvas-container">
|
||||
<!-- Dynamic Chart Container - uses extracted dynamic options and styles but static template -->
|
||||
<div *ngIf="dynamicTemplate || chartType" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData"
|
||||
[labels]="chartLabels"
|
||||
[options]="chartOptions"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="'bar'"
|
||||
[chartType]="chartType || 'bar'"
|
||||
(chartClick)="chartClicked($event)"
|
||||
(chartHover)="chartHovered($event)">
|
||||
</canvas>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- Line Chart -->
|
||||
<!-- <div *ngIf="chartType === 'line'" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData"
|
||||
[labels]="chartLabels"
|
||||
[options]="chartOptions"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="'line'"
|
||||
(chartClick)="chartClicked($event)"
|
||||
(chartHover)="chartHovered($event)">
|
||||
</canvas>
|
||||
</div> -->
|
||||
|
||||
<!-- Pie Chart -->
|
||||
<!-- <div *ngIf="chartType === 'pie'" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData"
|
||||
[labels]="chartLabels"
|
||||
[options]="chartOptions"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="'pie'"
|
||||
(chartClick)="chartClicked($event)"
|
||||
(chartHover)="chartHovered($event)">
|
||||
</canvas>
|
||||
</div> -->
|
||||
|
||||
<!-- Doughnut Chart -->
|
||||
<!-- <div *ngIf="chartType === 'doughnut'" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData"
|
||||
[labels]="chartLabels"
|
||||
[options]="chartOptions"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="'doughnut'"
|
||||
(chartClick)="chartClicked($event)"
|
||||
(chartHover)="chartHovered($event)">
|
||||
</canvas>
|
||||
</div> -->
|
||||
|
||||
<!-- Bubble Chart -->
|
||||
<!-- <div *ngIf="chartType === 'bubble'" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="bubbleChartData"
|
||||
[options]="chartOptions"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="'bubble'"
|
||||
(chartClick)="chartClicked($event)"
|
||||
(chartHover)="chartHovered($event)">
|
||||
</canvas>
|
||||
</div> -->
|
||||
|
||||
<!-- Radar Chart -->
|
||||
<!-- <div *ngIf="chartType === 'radar'" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData"
|
||||
[labels]="chartLabels"
|
||||
[options]="chartOptions"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="'radar'"
|
||||
(chartClick)="chartClicked($event)"
|
||||
(chartHover)="chartHovered($event)">
|
||||
</canvas>
|
||||
</div> -->
|
||||
|
||||
<!-- Polar Area Chart -->
|
||||
<!-- <div *ngIf="chartType === 'polar'" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData"
|
||||
[labels]="chartLabels"
|
||||
[options]="chartOptions"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="'polarArea'"
|
||||
(chartClick)="chartClicked($event)"
|
||||
(chartHover)="chartHovered($event)">
|
||||
</canvas>
|
||||
</div> -->
|
||||
|
||||
<!-- Scatter Chart -->
|
||||
<!-- <div *ngIf="chartType === 'scatter'" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData"
|
||||
[options]="chartOptions"
|
||||
[legend]="chartLegend"
|
||||
[chartType]="'scatter'"
|
||||
(chartClick)="chartClicked($event)"
|
||||
(chartHover)="chartHovered($event)">
|
||||
</canvas>
|
||||
</div> -->
|
||||
|
||||
<!-- Default/Unknown Chart Type -->
|
||||
<div *ngIf="!dynamicTemplate && !['bar', 'line', 'pie', 'doughnut', 'bubble', 'radar', 'polar', 'scatter'].includes(chartType)" class="chart-canvas-container">
|
||||
<!-- Fallback for when no chart type is specified -->
|
||||
<div *ngIf="!dynamicTemplate && !chartType" class="chart-canvas-container">
|
||||
<canvas baseChart
|
||||
[datasets]="chartData"
|
||||
[labels]="chartLabels"
|
||||
|
||||
@@ -80,14 +80,43 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
dynamicTemplate: string = '';
|
||||
dynamicStyles: string = '';
|
||||
dynamicOptions: any = null;
|
||||
|
||||
// Properties to hold extracted values from dynamic template
|
||||
extractedChartType: string = '';
|
||||
extractedDatasetsBinding: string = '';
|
||||
extractedLabelsBinding: string = '';
|
||||
extractedOptionsBinding: string = '';
|
||||
extractedLegendBinding: string = '';
|
||||
extractedChartClickBinding: string = '';
|
||||
extractedChartHoverBinding: string = '';
|
||||
|
||||
// Add setter to log when dynamicTemplate changes
|
||||
setDynamicTemplate(value: string) {
|
||||
console.log('Setting dynamic template:', value);
|
||||
this.dynamicTemplate = value;
|
||||
|
||||
// Extract values from the dynamic template
|
||||
this.extractTemplateValues(value);
|
||||
|
||||
// Apply dynamic options if they were extracted
|
||||
if (this.dynamicOptions) {
|
||||
this.mergeDynamicOptions();
|
||||
}
|
||||
|
||||
// Apply dynamic styles if they were extracted
|
||||
if (this.dynamicStyles) {
|
||||
this.applyDynamicStyles();
|
||||
}
|
||||
|
||||
// Trigger change detection to ensure the template is rendered
|
||||
setTimeout(() => {
|
||||
console.log('Dynamic template updated in DOM');
|
||||
// Check if the dynamic template container exists
|
||||
const dynamicContainer = this.el.nativeElement.querySelector('.dynamic-template-container');
|
||||
console.log('Dynamic template container:', dynamicContainer);
|
||||
if (dynamicContainer) {
|
||||
console.log('Dynamic container innerHTML:', dynamicContainer.innerHTML);
|
||||
}
|
||||
// Check if the canvas element exists in the DOM
|
||||
const canvasElements = this.el.nativeElement.querySelectorAll('canvas');
|
||||
console.log('Canvas elements found in DOM:', canvasElements.length);
|
||||
@@ -96,10 +125,96 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
// Check if it has the baseChart directive processed
|
||||
const firstCanvas = canvasElements[0];
|
||||
console.log('Canvas has baseChart directive processed:', firstCanvas.classList.contains('chartjs-render-monitor'));
|
||||
} else {
|
||||
console.log('No canvas elements found - checking if template was inserted but not processed');
|
||||
// Check if there's HTML content in the dynamic container
|
||||
if (dynamicContainer) {
|
||||
const htmlContent = dynamicContainer.innerHTML;
|
||||
console.log('HTML content in dynamic container:', htmlContent);
|
||||
if (htmlContent && htmlContent.includes('canvas')) {
|
||||
console.log('Canvas tag found in HTML but not processed by Angular');
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Extract values from dynamic template HTML
|
||||
private extractTemplateValues(template: string): void {
|
||||
console.log('Extracting values from template:', template);
|
||||
|
||||
// Reset extracted values
|
||||
this.extractedChartType = this.chartType || '';
|
||||
this.extractedDatasetsBinding = 'chartData';
|
||||
this.extractedLabelsBinding = 'chartLabels';
|
||||
this.extractedOptionsBinding = 'chartOptions';
|
||||
this.extractedLegendBinding = 'chartLegend';
|
||||
this.extractedChartClickBinding = 'chartClicked($event)';
|
||||
this.extractedChartHoverBinding = 'chartHovered($event)';
|
||||
|
||||
if (!template) {
|
||||
console.log('No template to extract values from');
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the template to extract bindings
|
||||
// Look for [chartType] binding
|
||||
const chartTypeMatch = template.match(/\[chartType\]="([^"]+)"/);
|
||||
if (chartTypeMatch && chartTypeMatch[1]) {
|
||||
this.extractedChartType = chartTypeMatch[1];
|
||||
console.log('Extracted chartType binding:', this.extractedChartType);
|
||||
}
|
||||
|
||||
// Look for [datasets] binding
|
||||
const datasetsMatch = template.match(/\[datasets\]="([^"]+)"/);
|
||||
if (datasetsMatch && datasetsMatch[1]) {
|
||||
this.extractedDatasetsBinding = datasetsMatch[1];
|
||||
console.log('Extracted datasets binding:', this.extractedDatasetsBinding);
|
||||
}
|
||||
|
||||
// Look for [labels] binding
|
||||
const labelsMatch = template.match(/\[labels\]="([^"]+)"/);
|
||||
if (labelsMatch && labelsMatch[1]) {
|
||||
this.extractedLabelsBinding = labelsMatch[1];
|
||||
console.log('Extracted labels binding:', this.extractedLabelsBinding);
|
||||
}
|
||||
|
||||
// Look for [options] binding
|
||||
const optionsMatch = template.match(/\[options\]="([^"]+)"/);
|
||||
if (optionsMatch && optionsMatch[1]) {
|
||||
this.extractedOptionsBinding = optionsMatch[1];
|
||||
console.log('Extracted options binding:', this.extractedOptionsBinding);
|
||||
}
|
||||
|
||||
// Look for [legend] binding
|
||||
const legendMatch = template.match(/\[legend\]="([^"]+)"/);
|
||||
if (legendMatch && legendMatch[1]) {
|
||||
this.extractedLegendBinding = legendMatch[1];
|
||||
console.log('Extracted legend binding:', this.extractedLegendBinding);
|
||||
}
|
||||
|
||||
// Look for (chartClick) binding
|
||||
const chartClickMatch = template.match(/\(chartClick\)="([^"]+)"/);
|
||||
if (chartClickMatch && chartClickMatch[1]) {
|
||||
this.extractedChartClickBinding = chartClickMatch[1];
|
||||
console.log('Extracted chartClick binding:', this.extractedChartClickBinding);
|
||||
}
|
||||
|
||||
// Look for (chartHover) binding
|
||||
const chartHoverMatch = template.match(/\(chartHover\)="([^"]+)"/);
|
||||
if (chartHoverMatch && chartHoverMatch[1]) {
|
||||
this.extractedChartHoverBinding = chartHoverMatch[1];
|
||||
console.log('Extracted chartHover binding:', this.extractedChartHoverBinding);
|
||||
}
|
||||
|
||||
// Extract CSS styles if present in the template
|
||||
const styleMatch = template.match(/<style[^>]*>([\s\S]*?)<\/style>/i);
|
||||
if (styleMatch && styleMatch[1]) {
|
||||
this.dynamicStyles = styleMatch[1];
|
||||
console.log('Extracted CSS styles:', this.dynamicStyles);
|
||||
}
|
||||
}
|
||||
|
||||
constructor(
|
||||
private dashboardService: Dashboard3Service,
|
||||
private filterService: FilterService,
|
||||
@@ -284,11 +399,13 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
console.log('Received chart configuration:', config);
|
||||
console.log('Loaded chart configuration:', config);
|
||||
|
||||
// Apply the first template if available
|
||||
// Apply the first template if available (for CSS styles)
|
||||
if (config.templates && config.templates.length > 0) {
|
||||
const defaultTemplate = config.templates.find(t => t.isDefault) || config.templates[0];
|
||||
if (defaultTemplate) {
|
||||
this.setDynamicTemplate(defaultTemplate.templateHtml || '');
|
||||
const templateHtml = defaultTemplate.templateHtml || '';
|
||||
console.log('Template HTML to be set:', templateHtml);
|
||||
this.setDynamicTemplate(templateHtml);
|
||||
this.dynamicStyles = defaultTemplate.templateCss || '';
|
||||
|
||||
// Apply styles to the component
|
||||
@@ -356,8 +473,15 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
// 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 };
|
||||
console.log('Merging dynamic options with existing chart options:', {
|
||||
existing: this.chartOptions,
|
||||
dynamic: this.dynamicOptions
|
||||
});
|
||||
|
||||
// Deep merge dynamic options with existing chart options
|
||||
this.chartOptions = this.deepMerge(this.chartOptions, this.dynamicOptions);
|
||||
|
||||
console.log('Merged chart options:', this.chartOptions);
|
||||
|
||||
// If we have a chart instance, update it
|
||||
if (this.chart) {
|
||||
@@ -366,6 +490,25 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method for deep merging objects
|
||||
private deepMerge(target: any, source: any): any {
|
||||
const result = { ...target };
|
||||
|
||||
for (const key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
|
||||
// Recursively merge objects
|
||||
result[key] = this.deepMerge(result[key] || {}, source[key]);
|
||||
} else {
|
||||
// Override with source value
|
||||
result[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Apply dynamic styles to the component
|
||||
private applyDynamicStyles(): void {
|
||||
@@ -381,6 +524,7 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.renderer.setAttribute(styleElement, 'class', 'dynamic-chart-styles');
|
||||
this.renderer.setProperty(styleElement, 'textContent', this.dynamicStyles);
|
||||
this.renderer.appendChild(this.el.nativeElement, styleElement);
|
||||
console.log('Applied dynamic styles to component');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user