chart
This commit is contained in:
@@ -13,6 +13,19 @@
|
||||
<h4>{{ charttitle }}</h4>
|
||||
</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 -->
|
||||
<div class="chart-wrapper">
|
||||
<!-- Bar Chart -->
|
||||
@@ -131,23 +144,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Base Filters -->
|
||||
<div class="filters-section" *ngIf="baseFilters && baseFilters.length > 0">
|
||||
<!-- Collapsible Base Filters -->
|
||||
<div class="filters-section" *ngIf="baseFilters && baseFilters.length > 0 && showFilters">
|
||||
<h5>Filters</h5>
|
||||
<div class="filters-container">
|
||||
<div class="filter-item" *ngFor="let filter of baseFilters; let i = index">
|
||||
<!-- Text Filter -->
|
||||
<div *ngIf="filter.type === 'text'" class="filter-text">
|
||||
<label>{{ filter.field }}</label>
|
||||
<div *ngIf="!filter.type || filter.type === 'text'" class="filter-text">
|
||||
<label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
|
||||
<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>
|
||||
|
||||
<!-- Dropdown Filter -->
|
||||
<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">
|
||||
<option value="">Select {{ filter.field }}</option>
|
||||
<option value="">Select {{ filter.field || 'value' }}</option>
|
||||
<option *ngFor="let option of getFilterOptions(filter)" [value]="option">
|
||||
{{ option }}
|
||||
</option>
|
||||
@@ -156,12 +169,15 @@
|
||||
|
||||
<!-- Multiselect Filter -->
|
||||
<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-display" (click)="toggleMultiselect(filter, 'base')">
|
||||
<span *ngIf="getSelectedOptionsCount(filter) === 0">Select {{ filter.field }}</span>
|
||||
<span *ngIf="getSelectedOptionsCount(filter) > 0">
|
||||
{{ getSelectedOptionsCount(filter) }} selected
|
||||
<span *ngIf="!filter.value || (Array.isArray(filter.value) && filter.value.length === 0)">Select {{ filter.field || 'options' }}</span>
|
||||
<span *ngIf="filter.value && !Array.isArray(filter.value)">
|
||||
{{ filter.value }}
|
||||
</span>
|
||||
<span *ngIf="filter.value && Array.isArray(filter.value) && filter.value.length > 0">
|
||||
{{ filter.value.length }} selected
|
||||
</span>
|
||||
</div>
|
||||
<div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'base')">
|
||||
@@ -178,18 +194,18 @@
|
||||
|
||||
<!-- Date Range Filter -->
|
||||
<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">
|
||||
<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">
|
||||
<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">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toggle Filter -->
|
||||
<div *ngIf="filter.type === 'toggle'" class="filter-toggle">
|
||||
<label>{{ filter.field }}</label>
|
||||
<label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
|
||||
<div class="toggle-switch">
|
||||
<input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)"
|
||||
id="toggle-{{ filter.field }}">
|
||||
@@ -203,22 +219,22 @@
|
||||
</div>
|
||||
|
||||
<!-- 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>
|
||||
<div class="filters-container">
|
||||
<div class="filter-item" *ngFor="let filter of drilldownFilters; let i = index">
|
||||
<!-- Text Filter -->
|
||||
<div *ngIf="filter.type === 'text'" class="filter-text">
|
||||
<label>{{ filter.field }}</label>
|
||||
<div *ngIf="!filter.type || filter.type === 'text'" class="filter-text">
|
||||
<label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
|
||||
<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>
|
||||
|
||||
<!-- Dropdown Filter -->
|
||||
<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">
|
||||
<option value="">Select {{ filter.field }}</option>
|
||||
<option value="">Select {{ filter.field || 'value' }}</option>
|
||||
<option *ngFor="let option of getFilterOptions(filter)" [value]="option">
|
||||
{{ option }}
|
||||
</option>
|
||||
@@ -227,12 +243,15 @@
|
||||
|
||||
<!-- Multiselect Filter -->
|
||||
<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-display" (click)="toggleMultiselect(filter, 'drilldown')">
|
||||
<span *ngIf="getSelectedOptionsCount(filter) === 0">Select {{ filter.field }}</span>
|
||||
<span *ngIf="getSelectedOptionsCount(filter) > 0">
|
||||
{{ getSelectedOptionsCount(filter) }} selected
|
||||
<span *ngIf="!filter.value || (Array.isArray(filter.value) && filter.value.length === 0)">Select {{ filter.field || 'options' }}</span>
|
||||
<span *ngIf="filter.value && !Array.isArray(filter.value)">
|
||||
{{ filter.value }}
|
||||
</span>
|
||||
<span *ngIf="filter.value && Array.isArray(filter.value) && filter.value.length > 0">
|
||||
{{ filter.value.length }} selected
|
||||
</span>
|
||||
</div>
|
||||
<div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'drilldown')">
|
||||
@@ -249,18 +268,18 @@
|
||||
|
||||
<!-- Date Range Filter -->
|
||||
<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">
|
||||
<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">
|
||||
<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">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toggle Filter -->
|
||||
<div *ngIf="filter.type === 'toggle'" class="filter-toggle">
|
||||
<label>{{ filter.field }}</label>
|
||||
<label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
|
||||
<div class="toggle-switch">
|
||||
<input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)"
|
||||
id="drilldown-toggle-{{ filter.field }}">
|
||||
@@ -274,22 +293,22 @@
|
||||
</div>
|
||||
|
||||
<!-- Layer Filters -->
|
||||
<div class="filters-section" *ngIf="hasActiveLayerFilters()">
|
||||
<div class="filters-section" *ngIf="hasActiveLayerFilters() && showFilters">
|
||||
<h5>Layer Filters</h5>
|
||||
<div class="filters-container">
|
||||
<div class="filter-item" *ngFor="let filter of getActiveLayerFilters(); let i = index">
|
||||
<!-- Text Filter -->
|
||||
<div *ngIf="filter.type === 'text'" class="filter-text">
|
||||
<label>{{ filter.field }}</label>
|
||||
<div *ngIf="!filter.type || filter.type === 'text'" class="filter-text">
|
||||
<label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
|
||||
<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>
|
||||
|
||||
<!-- Dropdown Filter -->
|
||||
<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">
|
||||
<option value="">Select {{ filter.field }}</option>
|
||||
<option value="">Select {{ filter.field || 'value' }}</option>
|
||||
<option *ngFor="let option of getFilterOptions(filter)" [value]="option">
|
||||
{{ option }}
|
||||
</option>
|
||||
@@ -298,12 +317,15 @@
|
||||
|
||||
<!-- Multiselect Filter -->
|
||||
<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-display" (click)="toggleMultiselect(filter, 'layer')">
|
||||
<span *ngIf="getSelectedOptionsCount(filter) === 0">Select {{ filter.field }}</span>
|
||||
<span *ngIf="getSelectedOptionsCount(filter) > 0">
|
||||
{{ getSelectedOptionsCount(filter) }} selected
|
||||
<span *ngIf="!filter.value || (Array.isArray(filter.value) && filter.value.length === 0)">Select {{ filter.field || 'options' }}</span>
|
||||
<span *ngIf="filter.value && !Array.isArray(filter.value)">
|
||||
{{ filter.value }}
|
||||
</span>
|
||||
<span *ngIf="filter.value && Array.isArray(filter.value) && filter.value.length > 0">
|
||||
{{ filter.value.length }} selected
|
||||
</span>
|
||||
</div>
|
||||
<div class="multiselect-dropdown" *ngIf="isMultiselectOpen(filter, 'layer')">
|
||||
@@ -320,18 +342,18 @@
|
||||
|
||||
<!-- Date Range Filter -->
|
||||
<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">
|
||||
<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">
|
||||
<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">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toggle Filter -->
|
||||
<div *ngIf="filter.type === 'toggle'" class="filter-toggle">
|
||||
<label>{{ filter.field }}</label>
|
||||
<label>{{ filter.field || 'Filter ' + (i + 1) }}</label>
|
||||
<div class="toggle-switch">
|
||||
<input type="checkbox" [(ngModel)]="filter.value" (ngModelChange)="onToggleChange(filter, $event.target.checked)"
|
||||
id="layer-toggle-{{ filter.field }}">
|
||||
@@ -345,7 +367,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 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()">
|
||||
Clear All Filters
|
||||
</button>
|
||||
|
||||
@@ -30,16 +30,15 @@
|
||||
.chart-wrapper {
|
||||
position: relative;
|
||||
height: calc(100% - 100px);
|
||||
min-height: 400px; // Increased minimum height for better visibility
|
||||
padding: 10px; // Add padding to create space around the chart
|
||||
min-height: 400px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
// Specific container for chart canvas elements
|
||||
.chart-canvas-container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 15px; // Add padding around the canvas for better spacing
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
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 {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
@@ -262,7 +288,6 @@
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
// Responsive adjustments
|
||||
@media (max-width: 768px) {
|
||||
.filters-container {
|
||||
flex-direction: column;
|
||||
|
||||
@@ -61,6 +61,9 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
currentDrilldownLevel: number = 0;
|
||||
originalChartData: any = {};
|
||||
|
||||
// Filter visibility toggle
|
||||
showFilters: boolean = false;
|
||||
|
||||
// Flag to prevent infinite loops
|
||||
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.fetchChartData();
|
||||
}
|
||||
@@ -92,6 +102,17 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
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
|
||||
if (!this.filtersInitialized && (changes.baseFilters || changes.drilldownFilters || changes.drilldownLayers)) {
|
||||
this.initializeFilterValues();
|
||||
@@ -114,6 +135,36 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
const drilldownYAxisChanged = changes.drilldownYAxis && !changes.drilldownYAxis.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
|
||||
if (!this.isFetchingData && (chartTypeChanged || xAxisChanged || yAxisChanged || tableChanged || connectionChanged || baseFiltersChanged || drilldownFiltersChanged ||
|
||||
drilldownEnabledChanged || drilldownApiUrlChanged || drilldownXAxisChanged || drilldownYAxisChanged ||
|
||||
@@ -126,7 +177,18 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
// Update legend visibility if it changed
|
||||
if (changes.chartlegend !== undefined) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
private initializeFilterValues(): void {
|
||||
console.log('Initializing filter values');
|
||||
console.log('Base filters before initialization:', this.baseFilters);
|
||||
|
||||
// Initialize base filters
|
||||
if (this.baseFilters) {
|
||||
this.baseFilters.forEach(filter => {
|
||||
if (this.baseFilters && Array.isArray(this.baseFilters)) {
|
||||
this.baseFilters.forEach((filter, index) => {
|
||||
console.log(`Processing base filter ${index}:`, filter);
|
||||
if (filter.value === undefined || filter.value === null) {
|
||||
switch (filter.type) {
|
||||
case 'multiselect':
|
||||
@@ -162,13 +241,22 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
default:
|
||||
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
|
||||
if (this.drilldownFilters) {
|
||||
this.drilldownFilters.forEach(filter => {
|
||||
if (this.drilldownFilters && Array.isArray(this.drilldownFilters)) {
|
||||
this.drilldownFilters.forEach((filter, index) => {
|
||||
console.log(`Processing drilldown filter ${index}:`, filter);
|
||||
if (filter.value === undefined || filter.value === null) {
|
||||
switch (filter.type) {
|
||||
case 'multiselect':
|
||||
@@ -183,15 +271,23 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
default:
|
||||
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
|
||||
if (this.drilldownLayers) {
|
||||
this.drilldownLayers.forEach(layer => {
|
||||
if (layer.filters) {
|
||||
layer.filters.forEach((filter: any) => {
|
||||
if (this.drilldownLayers && Array.isArray(this.drilldownLayers)) {
|
||||
this.drilldownLayers.forEach((layer, layerIndex) => {
|
||||
console.log(`Processing drilldown layer ${layerIndex}:`, layer);
|
||||
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) {
|
||||
switch (filter.type) {
|
||||
case 'multiselect':
|
||||
@@ -206,10 +302,16 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
default:
|
||||
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:', {
|
||||
@@ -221,6 +323,18 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
// Initialize chart options based on chart type
|
||||
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) {
|
||||
case 'bar':
|
||||
this.initializeBarChartOptions();
|
||||
@@ -573,6 +687,11 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.isLoading = true;
|
||||
this.noDataAvailable = false;
|
||||
|
||||
// Ensure chart options are initialized
|
||||
if (!this.chartOptions) {
|
||||
this.initializeChartOptions();
|
||||
}
|
||||
|
||||
console.log('Starting fetchChartData for chart type:', this.chartType);
|
||||
|
||||
// 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 {
|
||||
console.log('Chart hovered:', e);
|
||||
// console.log('Chart hovered:', e);
|
||||
}
|
||||
|
||||
// Method to check if chart data is valid
|
||||
@@ -1476,8 +1595,27 @@ export class UnifiedChartComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
// Handle date range changes
|
||||
onDateRangeChange(filter: any, dateRange: { start: string | null, end: string | null }): void {
|
||||
filter.value = dateRange;
|
||||
onDateRangeChange(filter: any, event: any): void {
|
||||
// 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
|
||||
this.fetchChartData();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user