This commit is contained in:
Gaurav Kumar
2025-11-01 16:20:59 +05:30
parent c6022b0e22
commit 807058e40d
3 changed files with 246 additions and 61 deletions

View File

@@ -13,6 +13,19 @@
<h4>{{ charttitle }}</h4> <h4>{{ charttitle }}</h4>
</div> </div>
<!-- Filter toggle icon -->
<div class="filter-toggle-icon" *ngIf="baseFilters && baseFilters.length > 0"
(click)="toggleFilters()"
style="cursor: pointer; text-align: right; padding: 5px;">
<clr-icon shape="filter" size="24"
[style.color]="showFilters ? '#007cba' : '#666'"
title="Toggle Filters">
</clr-icon>
<span style="margin-left: 5px; font-size: 12px; color: #666;">
{{ showFilters ? 'Hide Filters' : 'Show Filters' }}
</span>
</div>
<!-- Render different chart types based on chartType input --> <!-- Render different chart types based on chartType input -->
<div class="chart-wrapper"> <div class="chart-wrapper">
<!-- Bar Chart --> <!-- Bar Chart -->
@@ -131,23 +144,23 @@
</div> </div>
</div> </div>
<!-- Base Filters --> <!-- Collapsible Base Filters -->
<div class="filters-section" *ngIf="baseFilters && baseFilters.length > 0"> <div class="filters-section" *ngIf="baseFilters && baseFilters.length > 0 && showFilters">
<h5>Filters</h5> <h5>Filters</h5>
<div class="filters-container"> <div class="filters-container">
<div class="filter-item" *ngFor="let filter of baseFilters; let i = index"> <div class="filter-item" *ngFor="let filter of baseFilters; let i = index">
<!-- Text Filter --> <!-- Text Filter -->
<div *ngIf="filter.type === 'text'" class="filter-text"> <div *ngIf="!filter.type || filter.type === 'text'" class="filter-text">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<input type="text" [(ngModel)]="filter.value" (ngModelChange)="onBaseFilterChange(filter)" <input type="text" [(ngModel)]="filter.value" (ngModelChange)="onBaseFilterChange(filter)"
class="form-control" placeholder="Enter {{ filter.field }}"> class="form-control" placeholder="Enter {{ filter.field || 'value' }}">
</div> </div>
<!-- Dropdown Filter --> <!-- Dropdown Filter -->
<div *ngIf="filter.type === 'dropdown'" class="filter-dropdown"> <div *ngIf="filter.type === 'dropdown'" class="filter-dropdown">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<select [(ngModel)]="filter.value" (ngModelChange)="onBaseFilterChange(filter)" class="form-control"> <select [(ngModel)]="filter.value" (ngModelChange)="onBaseFilterChange(filter)" class="form-control">
<option value="">Select {{ filter.field }}</option> <option value="">Select {{ filter.field || 'value' }}</option>
<option *ngFor="let option of getFilterOptions(filter)" [value]="option"> <option *ngFor="let option of getFilterOptions(filter)" [value]="option">
{{ option }} {{ option }}
</option> </option>
@@ -156,12 +169,15 @@
<!-- Multiselect Filter --> <!-- Multiselect Filter -->
<div *ngIf="filter.type === 'multiselect'" class="filter-multiselect"> <div *ngIf="filter.type === 'multiselect'" class="filter-multiselect">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="multiselect-container"> <div class="multiselect-container">
<div class="multiselect-display" (click)="toggleMultiselect(filter, 'base')"> <div class="multiselect-display" (click)="toggleMultiselect(filter, 'base')">
<span *ngIf="getSelectedOptionsCount(filter) === 0">Select {{ filter.field }}</span> <span *ngIf="!filter.value || (Array.isArray(filter.value) && filter.value.length === 0)">Select {{ filter.field || 'options' }}</span>
<span *ngIf="getSelectedOptionsCount(filter) > 0"> <span *ngIf="filter.value && !Array.isArray(filter.value)">
{{ getSelectedOptionsCount(filter) }} selected {{ filter.value }}
</span>
<span *ngIf="filter.value && Array.isArray(filter.value) && filter.value.length > 0">
{{ filter.value.length }} selected
</span> </span>
</div> </div>
<div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'base')"> <div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'base')">
@@ -178,18 +194,18 @@
<!-- Date Range Filter --> <!-- Date Range Filter -->
<div *ngIf="filter.type === 'date-range'" class="filter-date-range"> <div *ngIf="filter.type === 'date-range'" class="filter-date-range">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="date-range-inputs"> <div class="date-range-inputs">
<input type="date" [(ngModel)]="filter.value.start" (ngModelChange)="onDateRangeChange(filter, filter.value)" <input type="date" [(ngModel)]="filter.value.start" (ngModelChange)="onDateRangeInputChange(filter, 'start', $event)"
class="form-control" placeholder="Start Date"> class="form-control" placeholder="Start Date">
<input type="date" [(ngModel)]="filter.value.end" (ngModelChange)="onDateRangeChange(filter, filter.value)" <input type="date" [(ngModel)]="filter.value.end" (ngModelChange)="onDateRangeInputChange(filter, 'end', $event)"
class="form-control" placeholder="End Date"> class="form-control" placeholder="End Date">
</div> </div>
</div> </div>
<!-- Toggle Filter --> <!-- Toggle Filter -->
<div *ngIf="filter.type === 'toggle'" class="filter-toggle"> <div *ngIf="filter.type === 'toggle'" class="filter-toggle">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="toggle-switch"> <div class="toggle-switch">
<input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)" <input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)"
id="toggle-{{ filter.field }}"> id="toggle-{{ filter.field }}">
@@ -203,22 +219,22 @@
</div> </div>
<!-- Drilldown Filters --> <!-- Drilldown Filters -->
<div class="filters-section" *ngIf="drilldownFilters && drilldownFilters.length > 0 && currentDrilldownLevel > 0"> <div class="filters-section" *ngIf="drilldownFilters && drilldownFilters.length > 0 && currentDrilldownLevel > 0 && showFilters">
<h5>Drilldown Filters</h5> <h5>Drilldown Filters</h5>
<div class="filters-container"> <div class="filters-container">
<div class="filter-item" *ngFor="let filter of drilldownFilters; let i = index"> <div class="filter-item" *ngFor="let filter of drilldownFilters; let i = index">
<!-- Text Filter --> <!-- Text Filter -->
<div *ngIf="filter.type === 'text'" class="filter-text"> <div *ngIf="!filter.type || filter.type === 'text'" class="filter-text">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<input type="text" [(ngModel)]="filter.value" (ngModelChange)="onDrilldownFilterChange(filter)" <input type="text" [(ngModel)]="filter.value" (ngModelChange)="onDrilldownFilterChange(filter)"
class="form-control" placeholder="Enter {{ filter.field }}"> class="form-control" placeholder="Enter {{ filter.field || 'value' }}">
</div> </div>
<!-- Dropdown Filter --> <!-- Dropdown Filter -->
<div *ngIf="filter.type === 'dropdown'" class="filter-dropdown"> <div *ngIf="filter.type === 'dropdown'" class="filter-dropdown">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<select [(ngModel)]="filter.value" (ngModelChange)="onDrilldownFilterChange(filter)" class="form-control"> <select [(ngModel)]="filter.value" (ngModelChange)="onDrilldownFilterChange(filter)" class="form-control">
<option value="">Select {{ filter.field }}</option> <option value="">Select {{ filter.field || 'value' }}</option>
<option *ngFor="let option of getFilterOptions(filter)" [value]="option"> <option *ngFor="let option of getFilterOptions(filter)" [value]="option">
{{ option }} {{ option }}
</option> </option>
@@ -227,12 +243,15 @@
<!-- Multiselect Filter --> <!-- Multiselect Filter -->
<div *ngIf="filter.type === 'multiselect'" class="filter-multiselect"> <div *ngIf="filter.type === 'multiselect'" class="filter-multiselect">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="multiselect-container"> <div class="multiselect-container">
<div class="multiselect-display" (click)="toggleMultiselect(filter, 'drilldown')"> <div class="multiselect-display" (click)="toggleMultiselect(filter, 'drilldown')">
<span *ngIf="getSelectedOptionsCount(filter) === 0">Select {{ filter.field }}</span> <span *ngIf="!filter.value || (Array.isArray(filter.value) && filter.value.length === 0)">Select {{ filter.field || 'options' }}</span>
<span *ngIf="getSelectedOptionsCount(filter) > 0"> <span *ngIf="filter.value && !Array.isArray(filter.value)">
{{ getSelectedOptionsCount(filter) }} selected {{ filter.value }}
</span>
<span *ngIf="filter.value && Array.isArray(filter.value) && filter.value.length > 0">
{{ filter.value.length }} selected
</span> </span>
</div> </div>
<div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'drilldown')"> <div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'drilldown')">
@@ -249,18 +268,18 @@
<!-- Date Range Filter --> <!-- Date Range Filter -->
<div *ngIf="filter.type === 'date-range'" class="filter-date-range"> <div *ngIf="filter.type === 'date-range'" class="filter-date-range">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="date-range-inputs"> <div class="date-range-inputs">
<input type="date" [(ngModel)]="filter.value.start" (ngModelChange)="onDateRangeChange(filter, filter.value)" <input type="date" [(ngModel)]="filter.value.start" (ngModelChange)="onDateRangeInputChange(filter, 'start', $event)"
class="form-control" placeholder="Start Date"> class="form-control" placeholder="Start Date">
<input type="date" [(ngModel)]="filter.value.end" (ngModelChange)="onDateRangeChange(filter, filter.value)" <input type="date" [(ngModel)]="filter.value.end" (ngModelChange)="onDateRangeInputChange(filter, 'end', $event)"
class="form-control" placeholder="End Date"> class="form-control" placeholder="End Date">
</div> </div>
</div> </div>
<!-- Toggle Filter --> <!-- Toggle Filter -->
<div *ngIf="filter.type === 'toggle'" class="filter-toggle"> <div *ngIf="filter.type === 'toggle'" class="filter-toggle">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="toggle-switch"> <div class="toggle-switch">
<input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)" <input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)"
id="drilldown-toggle-{{ filter.field }}"> id="drilldown-toggle-{{ filter.field }}">
@@ -274,22 +293,22 @@
</div> </div>
<!-- Layer Filters --> <!-- Layer Filters -->
<div class="filters-section" *ngIf="hasActiveLayerFilters()"> <div class="filters-section" *ngIf="hasActiveLayerFilters() && showFilters">
<h5>Layer Filters</h5> <h5>Layer Filters</h5>
<div class="filters-container"> <div class="filters-container">
<div class="filter-item" *ngFor="let filter of getActiveLayerFilters(); let i = index"> <div class="filter-item" *ngFor="let filter of getActiveLayerFilters(); let i = index">
<!-- Text Filter --> <!-- Text Filter -->
<div *ngIf="filter.type === 'text'" class="filter-text"> <div *ngIf="!filter.type || filter.type === 'text'" class="filter-text">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<input type="text" [(ngModel)]="filter.value" (ngModelChange)="onLayerFilterChange(filter)" <input type="text" [(ngModel)]="filter.value" (ngModelChange)="onLayerFilterChange(filter)"
class="form-control" placeholder="Enter {{ filter.field }}"> class="form-control" placeholder="Enter {{ filter.field || 'value' }}">
</div> </div>
<!-- Dropdown Filter --> <!-- Dropdown Filter -->
<div *ngIf="filter.type === 'dropdown'" class="filter-dropdown"> <div *ngIf="filter.type === 'dropdown'" class="filter-dropdown">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<select [(ngModel)]="filter.value" (ngModelChange)="onLayerFilterChange(filter)" class="form-control"> <select [(ngModel)]="filter.value" (ngModelChange)="onLayerFilterChange(filter)" class="form-control">
<option value="">Select {{ filter.field }}</option> <option value="">Select {{ filter.field || 'value' }}</option>
<option *ngFor="let option of getFilterOptions(filter)" [value]="option"> <option *ngFor="let option of getFilterOptions(filter)" [value]="option">
{{ option }} {{ option }}
</option> </option>
@@ -298,12 +317,15 @@
<!-- Multiselect Filter --> <!-- Multiselect Filter -->
<div *ngIf="filter.type === 'multiselect'" class="filter-multiselect"> <div *ngIf="filter.type === 'multiselect'" class="filter-multiselect">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="multiselect-container"> <div class="multiselect-container">
<div class="multiselect-display" (click)="toggleMultiselect(filter, 'layer')"> <div class="multiselect-display" (click)="toggleMultiselect(filter, 'layer')">
<span *ngIf="getSelectedOptionsCount(filter) === 0">Select {{ filter.field }}</span> <span *ngIf="!filter.value || (Array.isArray(filter.value) && filter.value.length === 0)">Select {{ filter.field || 'options' }}</span>
<span *ngIf="getSelectedOptionsCount(filter) > 0"> <span *ngIf="filter.value && !Array.isArray(filter.value)">
{{ getSelectedOptionsCount(filter) }} selected {{ filter.value }}
</span>
<span *ngIf="filter.value && Array.isArray(filter.value) && filter.value.length > 0">
{{ filter.value.length }} selected
</span> </span>
</div> </div>
<div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'layer')"> <div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'layer')">
@@ -320,18 +342,18 @@
<!-- Date Range Filter --> <!-- Date Range Filter -->
<div *ngIf="filter.type === 'date-range'" class="filter-date-range"> <div *ngIf="filter.type === 'date-range'" class="filter-date-range">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="date-range-inputs"> <div class="date-range-inputs">
<input type="date" [(ngModel)]="filter.value.start" (ngModelChange)="onDateRangeChange(filter, filter.value)" <input type="date" [(ngModel)]="filter.value.start" (ngModelChange)="onDateRangeInputChange(filter, 'start', $event)"
class="form-control" placeholder="Start Date"> class="form-control" placeholder="Start Date">
<input type="date" [(ngModel)]="filter.value.end" (ngModelChange)="onDateRangeChange(filter, filter.value)" <input type="date" [(ngModel)]="filter.value.end" (ngModelChange)="onDateRangeInputChange(filter, 'end', $event)"
class="form-control" placeholder="End Date"> class="form-control" placeholder="End Date">
</div> </div>
</div> </div>
<!-- Toggle Filter --> <!-- Toggle Filter -->
<div *ngIf="filter.type === 'toggle'" class="filter-toggle"> <div *ngIf="filter.type === 'toggle'" class="filter-toggle">
<label>{{ filter.field }}</label> <label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
<div class="toggle-switch"> <div class="toggle-switch">
<input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)" <input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)"
id="layer-toggle-{{ filter.field }}"> id="layer-toggle-{{ filter.field }}">
@@ -345,7 +367,7 @@
</div> </div>
<!-- Clear Filters Button --> <!-- Clear Filters Button -->
<div class="clear-filters" *ngIf="hasActiveFilters()"> <div class="clear-filters" *ngIf="hasActiveFilters() && showFilters">
<button class="btn btn-sm btn-outline" (click)="clearAllFilters()"> <button class="btn btn-sm btn-outline" (click)="clearAllFilters()">
Clear All Filters Clear All Filters
</button> </button>

View File

@@ -30,16 +30,15 @@
.chart-wrapper { .chart-wrapper {
position: relative; position: relative;
height: calc(100% - 100px); height: calc(100% - 100px);
min-height: 400px; // Increased minimum height for better visibility min-height: 400px;
padding: 10px; // Add padding to create space around the chart padding: 10px;
} }
// Specific container for chart canvas elements
.chart-canvas-container { .chart-canvas-container {
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; width: 100%;
padding: 15px; // Add padding around the canvas for better spacing padding: 15px;
box-sizing: border-box; box-sizing: border-box;
canvas { canvas {
@@ -49,6 +48,33 @@
} }
} }
.filter-toggle-icon {
display: flex;
align-items: center;
justify-content: flex-end;
padding: 5px;
cursor: pointer;
clr-icon {
transition: color 0.3s ease;
&:hover {
color: #007cba !important;
}
}
span {
margin-left: 5px;
font-size: 12px;
color: #666;
transition: color 0.3s ease;
}
&:hover span {
color: #007cba;
}
}
.filters-section { .filters-section {
margin-top: 20px; margin-top: 20px;
padding: 15px; padding: 15px;
@@ -262,7 +288,6 @@
100% { transform: rotate(360deg); } 100% { transform: rotate(360deg); }
} }
// Responsive adjustments
@media (max-width: 768px) { @media (max-width: 768px) {
.filters-container { .filters-container {
flex-direction: column; flex-direction: column;

View File

@@ -61,6 +61,9 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
currentDrilldownLevel: number = 0; currentDrilldownLevel: number = 0;
originalChartData: any = {}; originalChartData: any = {};
// Filter visibility toggle
showFilters: boolean = false;
// Flag to prevent infinite loops // Flag to prevent infinite loops
private isFetchingData: boolean = false; private isFetchingData: boolean = false;
@@ -85,6 +88,13 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
}) })
); );
// Initialize filter values if they haven't been initialized yet
if (!this.filtersInitialized) {
this.initializeFilterValues();
this.filtersInitialized = true;
}
// Initialize chart options with default structure
this.initializeChartOptions(); this.initializeChartOptions();
this.fetchChartData(); this.fetchChartData();
} }
@@ -92,6 +102,17 @@ 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 all input values for debugging
console.log('Current input values:', {
chartType: this.chartType,
xAxis: this.xAxis,
yAxis: this.yAxis,
table: this.table,
baseFilters: this.baseFilters,
drilldownFilters: this.drilldownFilters,
drilldownLayers: this.drilldownLayers
});
// Initialize filter values if they haven't been initialized yet // Initialize filter values if they haven't been initialized yet
if (!this.filtersInitialized && (changes.baseFilters || changes.drilldownFilters || changes.drilldownLayers)) { if (!this.filtersInitialized && (changes.baseFilters || changes.drilldownFilters || changes.drilldownLayers)) {
this.initializeFilterValues(); this.initializeFilterValues();
@@ -114,6 +135,36 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
const drilldownYAxisChanged = changes.drilldownYAxis && !changes.drilldownYAxis.firstChange; const drilldownYAxisChanged = changes.drilldownYAxis && !changes.drilldownYAxis.firstChange;
const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange; const drilldownLayersChanged = changes.drilldownLayers && !changes.drilldownLayers.firstChange;
// Log base filters changes for debugging
if (baseFiltersChanged) {
console.log('Base filters changed:', changes.baseFilters);
console.log('Current base filters:', this.baseFilters);
// Log detailed information about each filter
if (this.baseFilters && Array.isArray(this.baseFilters)) {
this.baseFilters.forEach((filter, index) => {
console.log(`Base filter ${index} details:`, {
field: filter.field,
value: filter.value,
type: filter.type,
options: filter.options
});
});
}
}
// Also log when baseFilters is not changed but we still have filters
if (!baseFiltersChanged && this.baseFilters && this.baseFilters.length > 0) {
console.log('Base filters present but not changed, logging current state:');
this.baseFilters.forEach((filter, index) => {
console.log(`Base filter ${index} details:`, {
field: filter.field,
value: filter.value,
type: filter.type,
options: filter.options
});
});
}
// 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 ||
@@ -126,7 +177,18 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
// Update legend visibility if it changed // Update legend visibility if it changed
if (changes.chartlegend !== undefined) { if (changes.chartlegend !== undefined) {
this.chartLegend = changes.chartlegend.currentValue; this.chartLegend = changes.chartlegend.currentValue;
this.chartOptions.plugins.legend.display = this.chartLegend; // Ensure chartOptions and required structures exist before accessing legend
if (!this.chartOptions) {
this.chartOptions = {};
}
if (!this.chartOptions.plugins) {
this.chartOptions.plugins = {};
}
if (!this.chartOptions.plugins.legend) {
this.chartOptions.plugins.legend = { display: this.chartLegend };
} else {
this.chartOptions.plugins.legend.display = this.chartLegend;
}
console.log('Chart legend changed to:', this.chartLegend); console.log('Chart legend changed to:', this.chartLegend);
} }
} }
@@ -141,13 +203,30 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
} }
} }
// Check if filters are available
hasFilters(): boolean {
const hasBaseFilters = this.baseFilters && this.baseFilters.length > 0;
console.log('Checking for filters - baseFilters:', this.baseFilters, 'hasBaseFilters:', hasBaseFilters);
return hasBaseFilters;
}
// Toggle filter visibility
toggleFilters(): void {
console.log('Toggling filters. Current state:', this.showFilters);
console.log('Base filters available:', this.hasFilters());
this.showFilters = !this.showFilters;
console.log('New state:', this.showFilters);
}
// Initialize filter values with proper default values based on type // Initialize filter values with proper default values based on type
private initializeFilterValues(): void { private initializeFilterValues(): void {
console.log('Initializing filter values'); console.log('Initializing filter values');
console.log('Base filters before initialization:', this.baseFilters);
// Initialize base filters // Initialize base filters
if (this.baseFilters) { if (this.baseFilters && Array.isArray(this.baseFilters)) {
this.baseFilters.forEach(filter => { this.baseFilters.forEach((filter, index) => {
console.log(`Processing base filter ${index}:`, filter);
if (filter.value === undefined || filter.value === null) { if (filter.value === undefined || filter.value === null) {
switch (filter.type) { switch (filter.type) {
case 'multiselect': case 'multiselect':
@@ -162,13 +241,22 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
default: default:
filter.value = ''; filter.value = '';
} }
console.log(`Initialized base filter ${index} value to:`, filter.value);
} else {
console.log(`Base filter ${index} already has value:`, filter.value);
} }
}); });
} else {
// Initialize as empty array if not provided
this.baseFilters = [];
} }
console.log('Base filters after initialization:', this.baseFilters);
// Initialize drilldown filters // Initialize drilldown filters
if (this.drilldownFilters) { if (this.drilldownFilters && Array.isArray(this.drilldownFilters)) {
this.drilldownFilters.forEach(filter => { this.drilldownFilters.forEach((filter, index) => {
console.log(`Processing drilldown filter ${index}:`, filter);
if (filter.value === undefined || filter.value === null) { if (filter.value === undefined || filter.value === null) {
switch (filter.type) { switch (filter.type) {
case 'multiselect': case 'multiselect':
@@ -183,15 +271,23 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
default: default:
filter.value = ''; filter.value = '';
} }
console.log(`Initialized drilldown filter ${index} value to:`, filter.value);
} else {
console.log(`Drilldown filter ${index} already has value:`, filter.value);
} }
}); });
} else {
// Initialize as empty array if not provided
this.drilldownFilters = [];
} }
// Initialize layer filters // Initialize layer filters
if (this.drilldownLayers) { if (this.drilldownLayers && Array.isArray(this.drilldownLayers)) {
this.drilldownLayers.forEach(layer => { this.drilldownLayers.forEach((layer, layerIndex) => {
if (layer.filters) { console.log(`Processing drilldown layer ${layerIndex}:`, layer);
layer.filters.forEach((filter: any) => { if (layer.filters && Array.isArray(layer.filters)) {
layer.filters.forEach((filter, filterIndex) => {
console.log(`Processing layer ${layerIndex} filter ${filterIndex}:`, filter);
if (filter.value === undefined || filter.value === null) { if (filter.value === undefined || filter.value === null) {
switch (filter.type) { switch (filter.type) {
case 'multiselect': case 'multiselect':
@@ -206,10 +302,16 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
default: default:
filter.value = ''; filter.value = '';
} }
console.log(`Initialized layer ${layerIndex} filter ${filterIndex} value to:`, filter.value);
} else {
console.log(`Layer ${layerIndex} filter ${filterIndex} already has value:`, filter.value);
} }
}); });
} }
}); });
} else {
// Initialize as empty array if not provided
this.drilldownLayers = [];
} }
console.log('Filter values initialized:', { console.log('Filter values initialized:', {
@@ -221,6 +323,18 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
// Initialize chart options based on chart type // Initialize chart options based on chart type
private initializeChartOptions(): void { private initializeChartOptions(): void {
// Initialize with default structure to ensure plugins.legend exists
this.chartOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
position: 'top'
}
}
};
switch (this.chartType) { switch (this.chartType) {
case 'bar': case 'bar':
this.initializeBarChartOptions(); this.initializeBarChartOptions();
@@ -573,6 +687,11 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
this.isLoading = true; this.isLoading = true;
this.noDataAvailable = false; this.noDataAvailable = false;
// Ensure chart options are initialized
if (!this.chartOptions) {
this.initializeChartOptions();
}
console.log('Starting fetchChartData for chart type:', this.chartType); console.log('Starting fetchChartData for chart type:', this.chartType);
// If we're in drilldown mode, fetch the appropriate drilldown data // If we're in drilldown mode, fetch the appropriate drilldown data
@@ -1320,7 +1439,7 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
} }
public chartHovered(e: any): void { public chartHovered(e: any): void {
console.log('Chart hovered:', e); // console.log('Chart hovered:', e);
} }
// Method to check if chart data is valid // Method to check if chart data is valid
@@ -1476,8 +1595,27 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
} }
// Handle date range changes // Handle date range changes
onDateRangeChange(filter: any, dateRange: { start: string | null, end: string | null }): void { onDateRangeChange(filter: any, event: any): void {
filter.value = dateRange; // For date range filters, we need to handle the change differently
// since we're binding to individual start/end properties
if (!filter.value) {
filter.value = { start: null, end: null };
}
// Refresh data when filter changes
this.fetchChartData();
}
// Handle date range input changes for start/end dates
onDateRangeInputChange(filter: any, dateType: string, event: any): void {
// Initialize filter.value if it doesn't exist
if (!filter.value) {
filter.value = { start: null, end: null };
}
// Update the specific date type (start or end)
filter.value[dateType] = event.target.value;
// Refresh data when filter changes // Refresh data when filter changes
this.fetchChartData(); this.fetchChartData();
} }